1 // SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
2 // SPDX-FileCopyrightText: 2021 Nheko Contributors
3 //
4 // SPDX-License-Identifier: GPL-3.0-or-later
5
6 #include <QBuffer>
7 #include <QFile>
8 #include <QFileInfo>
9 #include <QHBoxLayout>
10 #include <QMimeDatabase>
11 #include <QVBoxLayout>
12
13 #include "dialogs/PreviewUploadOverlay.h"
14
15 #include "Config.h"
16 #include "Logging.h"
17 #include "MainWindow.h"
18 #include "Utils.h"
19
20 using namespace dialogs;
21
22 constexpr const char *DEFAULT = "Upload %1?";
23 constexpr const char *ERR_MSG = "Failed to load image type '%1'. Continue upload?";
24
PreviewUploadOverlay(QWidget * parent)25 PreviewUploadOverlay::PreviewUploadOverlay(QWidget *parent)
26 : QWidget{parent}
27 , titleLabel_{this}
28 , fileName_{this}
29 , upload_{tr("Upload"), this}
30 , cancel_{tr("Cancel"), this}
31 {
32 auto hlayout = new QHBoxLayout;
33 hlayout->addStretch(1);
34 hlayout->addWidget(&cancel_);
35 hlayout->addWidget(&upload_);
36 hlayout->setMargin(0);
37
38 auto vlayout = new QVBoxLayout{this};
39 vlayout->addWidget(&titleLabel_);
40 vlayout->addWidget(&infoLabel_);
41 vlayout->addWidget(&fileName_);
42 vlayout->addLayout(hlayout);
43 vlayout->setSpacing(conf::modals::WIDGET_SPACING);
44 vlayout->setMargin(conf::modals::WIDGET_MARGIN);
45
46 upload_.setDefault(true);
__anon9b508dd00102() 47 connect(&upload_, &QPushButton::clicked, [this]() {
48 emit confirmUpload(data_, mediaType_, fileName_.text());
49 close();
50 });
51
__anon9b508dd00202() 52 connect(&fileName_, &QLineEdit::returnPressed, this, [this]() {
53 emit confirmUpload(data_, mediaType_, fileName_.text());
54 close();
55 });
56
__anon9b508dd00302() 57 connect(&cancel_, &QPushButton::clicked, this, [this]() {
58 emit aborted();
59 close();
60 });
61 }
62
63 void
init()64 PreviewUploadOverlay::init()
65 {
66 QSize winsize;
67 QPoint center;
68
69 auto window = MainWindow::instance();
70 if (window) {
71 winsize = window->frameGeometry().size();
72 center = window->frameGeometry().center();
73 } else {
74 nhlog::ui()->warn("unable to retrieve MainWindow's size");
75 }
76
77 fileName_.setText(QFileInfo{filePath_}.fileName());
78
79 setAutoFillBackground(true);
80 setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
81 setWindowModality(Qt::WindowModal);
82
83 QFont font;
84 font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
85
86 titleLabel_.setFont(font);
87 titleLabel_.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
88 titleLabel_.setAlignment(Qt::AlignCenter);
89 infoLabel_.setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
90 fileName_.setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
91 fileName_.setAlignment(Qt::AlignCenter);
92 upload_.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
93 cancel_.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
94
95 if (isImage_) {
96 infoLabel_.setAlignment(Qt::AlignCenter);
97
98 const auto maxWidth = winsize.width() * 0.8;
99 const auto maxHeight = winsize.height() * 0.8;
100
101 // Scale image preview to fit into the application window.
102 infoLabel_.setPixmap(utils::scaleDown(maxWidth, maxHeight, image_));
103 move(center.x() - (width() * 0.5), center.y() - (height() * 0.5));
104 } else {
105 infoLabel_.setAlignment(Qt::AlignLeft);
106 }
107 infoLabel_.setScaledContents(false);
108
109 show();
110 }
111
112 void
setLabels(const QString & type,const QString & mime,uint64_t upload_size)113 PreviewUploadOverlay::setLabels(const QString &type, const QString &mime, uint64_t upload_size)
114 {
115 if (mediaType_.split('/')[0] == "image") {
116 if (!image_.loadFromData(data_)) {
117 titleLabel_.setText(QString{tr(ERR_MSG)}.arg(type));
118 } else {
119 titleLabel_.setText(QString{tr(DEFAULT)}.arg(mediaType_));
120 }
121 isImage_ = true;
122 } else {
123 auto const info = QString{tr("Media type: %1\n"
124 "Media size: %2\n")}
125 .arg(mime)
126 .arg(utils::humanReadableFileSize(upload_size));
127
128 titleLabel_.setText(QString{tr(DEFAULT)}.arg("file"));
129 infoLabel_.setText(info);
130 }
131 }
132
133 void
setPreview(const QImage & src,const QString & mime)134 PreviewUploadOverlay::setPreview(const QImage &src, const QString &mime)
135 {
136 nhlog::ui()->info(
137 "Pasting image with size: {}x{}, format: {}", src.height(), src.width(), mime.toStdString());
138
139 auto const &split = mime.split('/');
140 auto const &type = split[1];
141
142 QBuffer buffer(&data_);
143 buffer.open(QIODevice::WriteOnly);
144 if (src.save(&buffer, type.toStdString().c_str()))
145 titleLabel_.setText(QString{tr(DEFAULT)}.arg("image"));
146 else
147 titleLabel_.setText(QString{tr(ERR_MSG)}.arg(type));
148
149 mediaType_ = mime;
150 filePath_ = "clipboard." + type;
151 image_.convertFromImage(src);
152 isImage_ = true;
153
154 titleLabel_.setText(QString{tr(DEFAULT)}.arg("image"));
155 init();
156 }
157
158 void
setPreview(const QByteArray data,const QString & mime)159 PreviewUploadOverlay::setPreview(const QByteArray data, const QString &mime)
160 {
161 nhlog::ui()->info("Pasting {} bytes of data, mimetype {}", data.size(), mime.toStdString());
162
163 auto const &split = mime.split('/');
164 auto const &type = split[1];
165
166 data_ = data;
167 mediaType_ = mime;
168 filePath_ = "clipboard." + type;
169 isImage_ = false;
170
171 if (mime == "image/svg+xml") {
172 isImage_ = true;
173 image_.loadFromData(data_, mediaType_.toStdString().c_str());
174 }
175
176 setLabels(type, mime, data_.size());
177 init();
178 }
179
180 void
setPreview(const QString & path)181 PreviewUploadOverlay::setPreview(const QString &path)
182 {
183 QFile file{path};
184
185 if (!file.open(QIODevice::ReadOnly)) {
186 nhlog::ui()->warn(
187 "Failed to open file ({}): {}", path.toStdString(), file.errorString().toStdString());
188 close();
189 return;
190 }
191
192 QMimeDatabase db;
193 auto mime = db.mimeTypeForFileNameAndData(path, &file);
194
195 if ((data_ = file.readAll()).isEmpty()) {
196 nhlog::ui()->warn("Failed to read media: {}", file.errorString().toStdString());
197 close();
198 return;
199 }
200
201 auto const &split = mime.name().split('/');
202
203 mediaType_ = mime.name();
204 filePath_ = file.fileName();
205 isImage_ = false;
206
207 setLabels(split[1], mime.name(), data_.size());
208 init();
209 }
210
211 void
keyPressEvent(QKeyEvent * event)212 PreviewUploadOverlay::keyPressEvent(QKeyEvent *event)
213 {
214 if (event->matches(QKeySequence::Cancel)) {
215 emit aborted();
216 close();
217 } else {
218 QWidget::keyPressEvent(event);
219 }
220 }