diff --git a/src/dialogs/ImageOverlay.cpp b/src/dialogs/ImageOverlay.cpp
deleted file mode 100644
index d9f0a993..00000000
--- a/src/dialogs/ImageOverlay.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-// SPDX-FileCopyrightText: 2022 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include <QApplication>
-#include <QGuiApplication>
-#include <QPainter>
-#include <QScreen>
-
-#include "dialogs/ImageOverlay.h"
-
-#include "Utils.h"
-
-using namespace dialogs;
-
-ImageOverlay::ImageOverlay(const QPixmap &image, QWidget *parent)
- : QWidget{parent}
- , originalImage_{image}
-{
- setMouseTracking(true);
- setParent(nullptr);
-
- setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
- setWindowRole(QStringLiteral("imageoverlay"));
-
- setAttribute(Qt::WA_NoSystemBackground, true);
- setAttribute(Qt::WA_TranslucentBackground, true);
- setAttribute(Qt::WA_DeleteOnClose, true);
- setWindowState(Qt::WindowFullScreen);
- close_shortcut_ = new QShortcut(QKeySequence(Qt::Key_Escape), this);
-
- connect(close_shortcut_, &QShortcut::activated, this, &ImageOverlay::closing);
- connect(this, &ImageOverlay::closing, this, &ImageOverlay::close);
-
- raise();
-}
-
-void
-ImageOverlay::paintEvent(QPaintEvent *event)
-{
- Q_UNUSED(event);
-
- QPainter painter(this);
- painter.setRenderHint(QPainter::Antialiasing);
-
- // Full screen overlay.
- painter.fillRect(QRect(0, 0, width(), height()), QColor(55, 55, 55, 170));
-
- // Left and Right margins
- int outer_margin = width() * 0.12;
- int buttonSize = 36;
- int margin = outer_margin * 0.1;
-
- int max_width = width() - 2 * outer_margin;
- int max_height = height();
-
- image_ = utils::scaleDown(max_width, max_height, originalImage_);
-
- 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(width() - margin - buttonSize, margin, buttonSize, buttonSize);
- save_button_ = QRect(width() - (2 * margin) - (2 * 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));
-
- // Draw download button
- center = save_button_.center();
- painter.drawLine(center - QPointF(0, 15), center + QPointF(0, 15));
- painter.drawLine(center - QPointF(15, 0), center + QPointF(0, 15));
- painter.drawLine(center + QPointF(0, 15), center + QPointF(15, 0));
-}
-
-void
-ImageOverlay::mousePressEvent(QMouseEvent *event)
-{
- if (event->button() != Qt::LeftButton)
- return;
-
- if (close_button_.contains(event->pos()))
- emit closing();
- else if (save_button_.contains(event->pos()))
- emit saving();
- else if (!content_.contains(event->pos()))
- emit closing();
-}
diff --git a/src/dialogs/ImageOverlay.h b/src/dialogs/ImageOverlay.h
deleted file mode 100644
index 9ce2fb09..00000000
--- a/src/dialogs/ImageOverlay.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
-// SPDX-FileCopyrightText: 2021 Nheko Contributors
-// SPDX-FileCopyrightText: 2022 Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <QDialog>
-#include <QMouseEvent>
-#include <QPixmap>
-#include <QShortcut>
-
-namespace dialogs {
-
-class ImageOverlay : public QWidget
-{
- Q_OBJECT
-public:
- ImageOverlay(const QPixmap &image, QWidget *parent = nullptr);
-
-protected:
- void mousePressEvent(QMouseEvent *event) override;
- void paintEvent(QPaintEvent *event) override;
-
-signals:
- void closing();
- void saving();
-
-private:
- QPixmap originalImage_;
- QPixmap image_;
-
- QRect content_;
- QRect close_button_;
- QRect save_button_;
- QShortcut *close_shortcut_;
-};
-} // dialogs
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 6195c24a..7234caa9 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -6,10 +6,12 @@
#include "TimelineViewManager.h"
#include <QDropEvent>
+#include <QFileDialog>
#include <QMetaType>
#include <QPalette>
#include <QQmlContext>
#include <QQmlEngine>
+#include <QStandardPaths>
#include <QString>
#include "BlurhashProvider.h"
@@ -32,7 +34,6 @@
#include "SingleImagePackModel.h"
#include "UserSettingsPage.h"
#include "UsersModel.h"
-#include "dialogs/ImageOverlay.h"
#include "emoji/EmojiModel.h"
#include "emoji/Provider.h"
#include "encryption/DeviceVerificationFlow.h"
@@ -331,11 +332,6 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
isInitialSync_ = true;
emit initialSyncChanged(true);
});
-
- connect(this,
- &TimelineViewManager::openImageOverlayInternalCb,
- this,
- &TimelineViewManager::openImageOverlayInternal);
}
void
@@ -416,23 +412,13 @@ TimelineViewManager::escapeEmoji(QString str) const
}
void
-TimelineViewManager::openImageOverlay(QString mxcUrl, QString eventId)
+TimelineViewManager::openImageOverlay(TimelineModel *room, QString mxcUrl, QString eventId)
{
if (mxcUrl.isEmpty()) {
return;
}
- MxcImageProvider::download(mxcUrl.remove(QStringLiteral("mxc://")),
- QSize(),
- [this, eventId](QString, QSize, QImage img, QString) {
- if (img.isNull()) {
- nhlog::ui()->error(
- "Error when retrieving image for overlay.");
- return;
- }
-
- emit openImageOverlayInternalCb(eventId, std::move(img));
- });
+ emit showImageOverlay(room, eventId, mxcUrl);
}
void
@@ -443,25 +429,46 @@ TimelineViewManager::openImagePackSettings(QString roomid)
}
void
-TimelineViewManager::openImageOverlayInternal(QString eventId, QImage img)
+TimelineViewManager::saveMedia(QString mxcUrl)
{
- auto pixmap = QPixmap::fromImage(img);
+ const QString downloadsFolder =
+ QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+ const QString openLocation = downloadsFolder + "/" + mxcUrl.splitRef(u'/').constLast();
- auto imgDialog = new dialogs::ImageOverlay(pixmap);
- imgDialog->showFullScreen();
+ const QString filename = QFileDialog::getSaveFileName(getWidget(), {}, openLocation);
- auto room = rooms_->currentRoom();
- connect(imgDialog, &dialogs::ImageOverlay::saving, room, [eventId, imgDialog, room]() {
- // hide the overlay while presenting the save dialog for better
- // cross platform support.
- imgDialog->hide();
+ if (filename.isEmpty())
+ return;
- if (!room->saveMedia(eventId)) {
- imgDialog->show();
- } else {
- imgDialog->close();
- }
- });
+ const auto url = mxcUrl.toStdString();
+
+ http::client()->download(url,
+ [filename, url](const std::string &data,
+ const std::string &,
+ const std::string &,
+ mtx::http::RequestErr err) {
+ if (err) {
+ nhlog::net()->warn("failed to retrieve image {}: {} {}",
+ url,
+ err->matrix_error.error,
+ static_cast<int>(err->status_code));
+ return;
+ }
+
+ try {
+ QFile file(filename);
+
+ if (!file.open(QIODevice::WriteOnly))
+ return;
+
+ file.write(QByteArray(data.data(), (int)data.size()));
+ file.close();
+
+ return;
+ } catch (const std::exception &e) {
+ nhlog::ui()->warn("Error while saving file to: {}", e.what());
+ }
+ });
}
void
diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index 47a72412..455702f4 100644
--- a/src/timeline/TimelineViewManager.h
+++ b/src/timeline/TimelineViewManager.h
@@ -60,8 +60,9 @@ public:
Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
bool isWindowFocused() const { return isWindowFocused_; }
- Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId);
+ Q_INVOKABLE void openImageOverlay(TimelineModel *room, QString mxcUrl, QString eventId);
Q_INVOKABLE void openImagePackSettings(QString roomid);
+ Q_INVOKABLE void saveMedia(QString mxcUrl);
Q_INVOKABLE QColor userColor(QString id, QColor background);
Q_INVOKABLE QString escapeEmoji(QString str) const;
Q_INVOKABLE QString htmlEscape(QString str) const { return str.toHtmlEscaped(); }
@@ -85,13 +86,13 @@ signals:
void narrowViewChanged();
void focusChanged();
void focusInput();
- void openImageOverlayInternalCb(QString eventId, QImage img);
void openRoomMembersDialog(MemberList *members, TimelineModel *room);
void openRoomSettingsDialog(RoomSettings *settings);
void openInviteUsersDialog(InviteesModel *invitees);
void openProfile(UserProfile *profile);
void showImagePackSettings(TimelineModel *room, ImagePackListModel *packlist);
void openLeaveRoomDialog(QString roomid);
+ void showImageOverlay(TimelineModel *room, QString eventId, QString url);
public slots:
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
@@ -120,9 +121,6 @@ public slots:
RoomlistModel *rooms() { return rooms_; }
-private slots:
- void openImageOverlayInternal(QString eventId, QImage img);
-
private:
#ifdef USE_QUICK_VIEW
QQuickView *view;
diff --git a/src/ui/MxcAnimatedImage.cpp b/src/ui/MxcAnimatedImage.cpp
index 36e028e3..83787fff 100644
--- a/src/ui/MxcAnimatedImage.cpp
+++ b/src/ui/MxcAnimatedImage.cpp
@@ -20,10 +20,12 @@
void
MxcAnimatedImage::startDownload()
{
+ nhlog::ui()->debug("START DOWNLOAD!!!");
if (!room_)
return;
if (eventId_.isEmpty())
return;
+ nhlog::ui()->debug("START DOWNLOAD2!!!");
auto event = room_->eventById(eventId_);
if (!event) {
@@ -92,7 +94,9 @@ MxcAnimatedImage::startDownload()
"Playing movie with size: {}, {}", buffer.bytesAvailable(), buffer.isOpen());
movie.setFormat(mimeType);
movie.setDevice(&buffer);
- movie.setScaledSize(this->size().toSize());
+
+ if (height() != 0 && width() != 0)
+ movie.setScaledSize(this->size().toSize());
if (buffer.bytesAvailable() <
4LL * 1024 * 1024 * 1024) // cache images smaller than 4MB in RAM
movie.setCacheMode(QMovie::CacheAll);
@@ -145,6 +149,17 @@ MxcAnimatedImage::startDownload()
});
}
+void
+MxcAnimatedImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
+
+ if (newGeometry.size() != oldGeometry.size()) {
+ if (height() != 0 && width() != 0)
+ movie.setScaledSize(newGeometry.size().toSize());
+ }
+}
+
QSGNode *
MxcAnimatedImage::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
@@ -171,8 +186,8 @@ MxcAnimatedImage::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeD
return nullptr;
}
- n->setRect(QRect(0, 0, width(), height()));
- n->setFiltering(QSGTexture::Nearest);
+ n->setRect(0, 0, width(), height());
+ n->setFiltering(QSGTexture::Linear);
n->setMipmapFiltering(QSGTexture::None);
return n;
diff --git a/src/ui/MxcAnimatedImage.h b/src/ui/MxcAnimatedImage.h
index 1afe6a19..8891e57e 100644
--- a/src/ui/MxcAnimatedImage.h
+++ b/src/ui/MxcAnimatedImage.h
@@ -60,6 +60,7 @@ public:
}
}
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
QSGNode *updatePaintNode(QSGNode *oldNode,
QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;
|