diff options
author | Konstantinos Sideris <sideris.konstantin@gmail.com> | 2017-11-30 13:53:28 +0200 |
---|---|---|
committer | Konstantinos Sideris <sideris.konstantin@gmail.com> | 2017-11-30 13:53:28 +0200 |
commit | 32c83405771b2f7a751783529d17e1b84dad4224 (patch) | |
tree | 70b51c8f019bfcaae99207fba8d0214e4b69e94d /src/timeline/widgets | |
parent | Use templates for the TimelineItem generation (diff) | |
download | nheko-32c83405771b2f7a751783529d17e1b84dad4224.tar.xz |
Create directories for related files
Diffstat (limited to 'src/timeline/widgets')
-rw-r--r-- | src/timeline/widgets/FileItem.cc | 208 | ||||
-rw-r--r-- | src/timeline/widgets/ImageItem.cc | 223 |
2 files changed, 431 insertions, 0 deletions
diff --git a/src/timeline/widgets/FileItem.cc b/src/timeline/widgets/FileItem.cc new file mode 100644 index 00000000..8d0100c7 --- /dev/null +++ b/src/timeline/widgets/FileItem.cc @@ -0,0 +1,208 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <QBrush> +#include <QDebug> +#include <QDesktopServices> +#include <QFile> +#include <QFileDialog> +#include <QFileInfo> +#include <QPainter> +#include <QPixmap> + +#include "timeline/widgets/FileItem.h" + +namespace events = matrix::events; +namespace msgs = matrix::events::messages; + +void +FileItem::init() +{ + setMouseTracking(true); + setCursor(Qt::PointingHandCursor); + setAttribute(Qt::WA_Hover, true); + + icon_.addFile(":/icons/icons/ui/arrow-pointing-down.png"); + + QList<QString> url_parts = url_.toString().split("mxc://"); + if (url_parts.size() != 2) { + qDebug() << "Invalid format for image" << url_.toString(); + return; + } + + QString media_params = url_parts[1]; + url_ = QString("%1/_matrix/media/r0/download/%2") + .arg(client_.data()->getHomeServer().toString(), media_params); + + connect(client_.data(), &MatrixClient::fileDownloaded, this, &FileItem::fileDownloaded); +} + +FileItem::FileItem(QSharedPointer<MatrixClient> client, + const events::MessageEvent<msgs::File> &event, + QWidget *parent) + : QWidget(parent) + , url_{event.msgContent().url()} + , text_{event.content().body()} + , event_{event} + , client_{client} +{ + readableFileSize_ = calculateFileSize(event.msgContent().info().size); + + init(); +} + +FileItem::FileItem(QSharedPointer<MatrixClient> client, + const QString &url, + const QString &filename, + QWidget *parent) + : QWidget(parent) + , url_{url} + , text_{QFileInfo(filename).fileName()} + , client_{client} +{ + readableFileSize_ = calculateFileSize(QFileInfo(filename).size()); + + init(); +} + +QString +FileItem::calculateFileSize(int nbytes) const +{ + if (nbytes < 1024) + return QString("%1 B").arg(nbytes); + + if (nbytes < 1024 * 1024) + return QString("%1 KB").arg(nbytes / 1024); + + return QString("%1 MB").arg(nbytes / 1024 / 1024); +} + +void +FileItem::openUrl() +{ + if (url_.toString().isEmpty()) + return; + + if (!QDesktopServices::openUrl(url_)) + qWarning() << "Could not open url" << url_.toString(); +} + +QSize +FileItem::sizeHint() const +{ + return QSize(MaxWidth, Height); +} + +void +FileItem::mousePressEvent(QMouseEvent *event) +{ + if (event->button() != Qt::LeftButton) + return; + + auto point = event->pos(); + + // Click on the download icon. + if (QRect(HorizontalPadding, VerticalPadding / 2, IconDiameter, IconDiameter) + .contains(point)) { + filenameToSave_ = QFileDialog::getSaveFileName(this, tr("Save File"), text_); + + if (filenameToSave_.isEmpty()) + return; + + client_->downloadFile(event_.eventId(), url_); + } else { + openUrl(); + } +} + +void +FileItem::fileDownloaded(const QString &event_id, const QByteArray &data) +{ + if (event_id != event_.eventId()) + return; + + try { + QFile file(filenameToSave_); + + if (!file.open(QIODevice::WriteOnly)) + return; + + file.write(data); + file.close(); + } catch (const std::exception &ex) { + qDebug() << "Error while saving file to:" << ex.what(); + } +} + +void +FileItem::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + QFont font("Open Sans"); + font.setPixelSize(12); + font.setWeight(80); + + QFontMetrics fm(font); + + int computedWidth = std::min( + fm.width(text_) + 2 * IconRadius + VerticalPadding * 2 + TextPadding, (double)MaxWidth); + + QPainterPath path; + path.addRoundedRect(QRectF(0, 0, computedWidth, Height), 10, 10); + + painter.setPen(Qt::NoPen); + painter.fillPath(path, backgroundColor_); + painter.drawPath(path); + + QPainterPath circle; + circle.addEllipse(QPoint(IconXCenter, IconYCenter), IconRadius, IconRadius); + + painter.setPen(Qt::NoPen); + painter.fillPath(circle, iconColor_); + painter.drawPath(circle); + + icon_.paint(&painter, + QRect(IconXCenter - DownloadIconRadius / 2, + IconYCenter - DownloadIconRadius / 2, + DownloadIconRadius, + DownloadIconRadius), + Qt::AlignCenter, + QIcon::Normal); + + const int textStartX = HorizontalPadding + 2 * IconRadius + TextPadding; + const int textStartY = VerticalPadding + fm.ascent() / 2; + + // Draw the filename. + QString elidedText = + fm.elidedText(text_, + Qt::ElideRight, + computedWidth - HorizontalPadding * 2 - TextPadding - 2 * IconRadius); + + painter.setFont(font); + painter.setPen(QPen(textColor_)); + painter.drawText(QPoint(textStartX, textStartY), elidedText); + + // Draw the filesize. + font.setWeight(50); + painter.setFont(font); + painter.setPen(QPen(textColor_)); + painter.drawText(QPoint(textStartX, textStartY + 1.5 * fm.ascent()), readableFileSize_); +} diff --git a/src/timeline/widgets/ImageItem.cc b/src/timeline/widgets/ImageItem.cc new file mode 100644 index 00000000..106fc79b --- /dev/null +++ b/src/timeline/widgets/ImageItem.cc @@ -0,0 +1,223 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <QBrush> +#include <QDebug> +#include <QDesktopServices> +#include <QFileInfo> +#include <QPainter> +#include <QPixmap> + +#include "dialogs/ImageOverlayDialog.h" +#include "timeline/widgets/ImageItem.h" + +namespace events = matrix::events; +namespace msgs = matrix::events::messages; + +ImageItem::ImageItem(QSharedPointer<MatrixClient> client, + const events::MessageEvent<msgs::Image> &event, + QWidget *parent) + : QWidget(parent) + , event_{event} + , client_{client} +{ + setMouseTracking(true); + setCursor(Qt::PointingHandCursor); + setAttribute(Qt::WA_Hover, true); + + url_ = event.msgContent().url(); + text_ = event.content().body(); + + QList<QString> url_parts = url_.toString().split("mxc://"); + + if (url_parts.size() != 2) { + qDebug() << "Invalid format for image" << url_.toString(); + return; + } + + QString media_params = url_parts[1]; + url_ = QString("%1/_matrix/media/r0/download/%2") + .arg(client_.data()->getHomeServer().toString(), media_params); + + client_.data()->downloadImage(event.eventId(), url_); + + connect(client_.data(), + SIGNAL(imageDownloaded(const QString &, const QPixmap &)), + this, + SLOT(imageDownloaded(const QString &, const QPixmap &))); +} + +ImageItem::ImageItem(QSharedPointer<MatrixClient> client, + const QString &url, + const QString &filename, + QWidget *parent) + : QWidget(parent) + , url_{url} + , text_{QFileInfo(filename).fileName()} + , client_{client} +{ + setMouseTracking(true); + setCursor(Qt::PointingHandCursor); + setAttribute(Qt::WA_Hover, true); + + QList<QString> url_parts = url_.toString().split("mxc://"); + + if (url_parts.size() != 2) { + qDebug() << "Invalid format for image" << url_.toString(); + return; + } + + QString media_params = url_parts[1]; + url_ = QString("%1/_matrix/media/r0/download/%2") + .arg(client_.data()->getHomeServer().toString(), media_params); + + setImage(QPixmap(filename)); +} + +void +ImageItem::imageDownloaded(const QString &event_id, const QPixmap &img) +{ + if (event_id != event_.eventId()) + return; + + setImage(img); +} + +void +ImageItem::openUrl() +{ + if (url_.toString().isEmpty()) + return; + + if (!QDesktopServices::openUrl(url_)) + qWarning() << "Could not open url" << url_.toString(); +} + +void +ImageItem::scaleImage() +{ + if (image_.isNull()) + return; + + auto width_ratio = (double)max_width_ / (double)image_.width(); + auto height_ratio = (double)max_height_ / (double)image_.height(); + + auto min_aspect_ratio = std::min(width_ratio, height_ratio); + + if (min_aspect_ratio > 1) { + width_ = image_.width(); + height_ = image_.height(); + } else { + width_ = image_.width() * min_aspect_ratio; + height_ = image_.height() * min_aspect_ratio; + } + + setFixedSize(width_, height_); + scaled_image_ = + image_.scaled(width_, height_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); +} + +QSize +ImageItem::sizeHint() const +{ + if (image_.isNull()) + return QSize(max_width_, bottom_height_); + + return QSize(width_, height_); +} + +void +ImageItem::setImage(const QPixmap &image) +{ + image_ = image; + scaleImage(); + update(); +} + +void +ImageItem::mousePressEvent(QMouseEvent *event) +{ + if (event->button() != Qt::LeftButton) + return; + + if (image_.isNull()) { + openUrl(); + return; + } + + auto point = event->pos(); + + // Click on the text box. + if (QRect(0, height_ - bottom_height_, width_, bottom_height_).contains(point)) { + openUrl(); + } else { + auto image_dialog = new ImageOverlayDialog(image_, this); + image_dialog->show(); + } +} + +void +ImageItem::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + scaleImage(); +} + +void +ImageItem::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + QFont font("Open Sans"); + font.setPixelSize(12); + + QFontMetrics metrics(font); + int fontHeight = metrics.height(); + + if (image_.isNull()) { + int height = fontHeight + 10; + + QString elidedText = metrics.elidedText(text_, Qt::ElideRight, max_width_ - 10); + + setFixedSize(metrics.width(elidedText), fontHeight + 10); + + painter.setFont(font); + painter.setPen(QPen(QColor(66, 133, 244))); + painter.drawText(QPoint(0, height / 2 + 2), elidedText); + + return; + } + + painter.fillRect(QRect(0, 0, width_, height_), scaled_image_); + + if (underMouse()) { + // Bottom text section + painter.fillRect(QRect(0, height_ - bottom_height_, width_, bottom_height_), + QBrush(QColor(33, 33, 33, 128))); + + QString elidedText = metrics.elidedText(text_, Qt::ElideRight, width_ - 10); + + font.setWeight(80); + painter.setFont(font); + painter.setPen(QPen(QColor("white"))); + painter.drawText(QPoint(5, height_ - fontHeight / 2), elidedText); + } +} |