From 57332553c4ec7aed517e8e1b1958f302eaf8c4bd Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Sun, 30 Apr 2017 01:55:10 +0300 Subject: [PATCH] Add full screen overlay for image display --- CMakeLists.txt | 2 + include/ImageOverlayDialog.h | 44 +++++++++++++ src/ImageItem.cc | 9 ++- src/ImageOverlayDialog.cc | 116 +++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 include/ImageOverlayDialog.h create mode 100644 src/ImageOverlayDialog.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 01de678a..390ef837 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ set(SRC_FILES src/EmojiPickButton.cc src/EmojiProvider.cc src/ImageItem.cc + src/ImageOverlayDialog.cc src/TimelineItem.cc src/TimelineView.cc src/TimelineViewManager.cc @@ -129,6 +130,7 @@ qt5_wrap_cpp(MOC_HEADERS include/EmojiPanel.h include/EmojiPickButton.h include/ImageItem.h + include/ImageOverlayDialog.h include/TimelineItem.h include/TimelineView.h include/TimelineViewManager.h diff --git a/include/ImageOverlayDialog.h b/include/ImageOverlayDialog.h new file mode 100644 index 00000000..21f59d12 --- /dev/null +++ b/include/ImageOverlayDialog.h @@ -0,0 +1,44 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris + * + * 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 . + */ + +#ifndef IMAGE_OVERLAY_DIALOG_H +#define IMAGE_OVERLAY_DIALOG_H + +#include +#include +#include + +class ImageOverlayDialog : public QDialog +{ + Q_OBJECT +public: + ImageOverlayDialog(QPixmap image, QWidget *parent = nullptr); + +protected: + void mousePressEvent(QMouseEvent *event) override; + void paintEvent(QPaintEvent *event) override; + +private: + void scaleImage(int width, int height); + + QPixmap image_; + + QRect content_; + QRect close_button_; +}; + +#endif // IMAGE_OVERLAY_DIALOG_H diff --git a/src/ImageItem.cc b/src/ImageItem.cc index 0a2b62f2..d03e41b5 100644 --- a/src/ImageItem.cc +++ b/src/ImageItem.cc @@ -23,6 +23,7 @@ #include #include "ImageItem.h" +#include "ImageOverlayDialog.h" ImageItem::ImageItem(QSharedPointer client, const Event &event, const QString &body, const QUrl &url, QWidget *parent) : QWidget(parent) @@ -121,10 +122,12 @@ void ImageItem::mousePressEvent(QMouseEvent *event) auto point = event->pos(); // Click on the text box. - if (QRect(0, height_ - bottom_height_, width_, bottom_height_).contains(point)) + if (QRect(0, height_ - bottom_height_, width_, bottom_height_).contains(point)) { openUrl(); - else - qDebug() << "Opening image overlay. Not implemented yet."; + } else { + auto image_dialog = new ImageOverlayDialog(image_, this); + image_dialog->show(); + } } void ImageItem::resizeEvent(QResizeEvent *event) diff --git a/src/ImageOverlayDialog.cc b/src/ImageOverlayDialog.cc new file mode 100644 index 00000000..0fe1c0e4 --- /dev/null +++ b/src/ImageOverlayDialog.cc @@ -0,0 +1,116 @@ +/* + * nheko Copyright (C) 2017 Konstantinos Sideris + * + * 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 . + */ + +#include +#include + +#include "ImageOverlayDialog.h" + +ImageOverlayDialog::ImageOverlayDialog(QPixmap image, QWidget *parent) + : QDialog{parent} + , image_{image} +{ + setMouseTracking(true); + setModal(false); + + setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + + setAttribute(Qt::WA_NoSystemBackground, true); + setAttribute(Qt::WA_TranslucentBackground, true); + setAttribute(Qt::WA_DeleteOnClose, true); + + setWindowState(Qt::WindowFullScreen); + + raise(); +} + +// TODO: Move this into Utils +void ImageOverlayDialog::scaleImage(int max_width, int max_height) +{ + 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); + + int final_width = 0; + int final_height = 0; + + if (min_aspect_ratio > 1) { + final_width = image_.width(); + final_height = image_.height(); + } else { + final_width = image_.width() * min_aspect_ratio; + final_height = image_.height() * min_aspect_ratio; + } + + image_ = image_.scaled(final_width, final_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); +} + +void ImageOverlayDialog::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + // Full screen overlay. + painter.fillRect(rect(), QColor(55, 55, 55, 170)); + + // Left and Right margins + int outer_margin = rect().width() * 0.12; + int buttonSize = 36; + int margin = outer_margin * 0.1; + + int max_width = rect().width() - 2 * outer_margin; + int max_height = rect().height(); + + scaleImage(max_width, max_height); + + int diff_x = max_width - image_.width(); + int diff_y = max_height - image_.height(); + + content_ = QRect(outer_margin + diff_x / 2, diff_y / 2, image_.width(), image_.height()); + close_button_ = QRect(rect().width() - margin - buttonSize, margin, buttonSize, buttonSize); + + // Draw main content_. + painter.drawPixmap(content_, image_); + + // Draw top right corner X. + QPen pen; + pen.setCapStyle(Qt::RoundCap); + pen.setWidthF(5); + pen.setColor("gray"); + + auto center = close_button_.center(); + + painter.setPen(pen); + painter.drawLine(center - QPointF(15, 15), center + QPointF(15, 15)); + painter.drawLine(center + QPointF(15, -15), center - QPointF(15, -15)); +} + +void ImageOverlayDialog::mousePressEvent(QMouseEvent *event) +{ + if (event->button() != Qt::LeftButton) + return; + + // FIXME: The main window needs double click to regain focus. + if (close_button_.contains(event->pos())) + close(); +}