diff options
Diffstat (limited to 'qarma/image-preview.patch')
| -rw-r--r-- | qarma/image-preview.patch | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/qarma/image-preview.patch b/qarma/image-preview.patch new file mode 100644 index 0000000..01799bb --- /dev/null +++ b/qarma/image-preview.patch @@ -0,0 +1,158 @@ +From 425ae90cae55f9136e0620c3165baf839e54bc0a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thomas=20L=C3=BCbking?= <thomas.luebking@gmail.com> +Date: Fri, 26 Dec 2025 18:54:33 +0100 +Subject: [PATCH] add option or preview images in file dialogs + +closes #57 +--- + Qarma.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 95 insertions(+), 1 deletion(-) + +diff --git a/Qarma.cpp b/Qarma.cpp +index 3708360..c0f1f77 100644 +--- a/Qarma.cpp ++++ b/Qarma.cpp +@@ -24,6 +24,7 @@ + #include <QCheckBox> + #include <QColorDialog> + #include <QComboBox> ++#include <QCryptographicHash> + #include <QDate> + #include <QDBusConnection> + #include <QDBusConnectionInterface> +@@ -34,6 +35,7 @@ + #include <QFontDialog> + #include <QFormLayout> + #include <QIcon> ++#include <QImageReader> + #include <QInputDialog> + #include <QLabel> + #include <QLocale> +@@ -42,12 +44,15 @@ + #include <QProcess> + #include <QProgressDialog> + #include <QPropertyAnimation> ++#include <QProxyStyle> + #include <QPushButton> + #include <QScreen> + #include <QScrollBar> + #include <QSettings> + #include <QSlider> + #include <QSocketNotifier> ++#include <QSplitter> ++#include <QStandardPaths> + #include <QStringBuilder> + #include <QStringList> + #include <QTextBrowser> +@@ -785,6 +790,83 @@ char Qarma::showMessage(const QStringList &args, char type) + return 0; + } + ++QPixmap thumbnail(const QString &path, uint size) ++{ ++ size = qMin(size, 1024u); ++ QImage thumb; ++ QImageReader thumbReader; ++ thumbReader.setFileName(path); ++ if (!thumbReader.canRead()) ++ return QPixmap(); ++ ++ thumbReader.setQuality(50); ++ QSize sz = thumbReader.size(); ++ QSize origSz = sz; ++ bool skipThumbnail = sz.width()*sz.height() < 1920*1200+1; ++ ++ if (skipThumbnail) { ++ sz.scale(QSize(size,size), Qt::KeepAspectRatio); ++ thumbReader.setScaledSize(sz); ++ } else { ++ QFileInfo info(path); ++ QString canonicalPath = info.canonicalFilePath(); ++ if (canonicalPath.isEmpty()) ++ canonicalPath = info.absoluteFilePath(); ++ QUrl url = QUrl::fromLocalFile(canonicalPath); ++ QCryptographicHash md5(QCryptographicHash::Md5); ++ md5.addData(QFile::encodeName(url.adjusted(QUrl::RemovePassword).url())); ++ ++ QString folder; ++ uint tSize; ++ if (size <= 128) { ++ tSize = 128; folder = "normal/"; ++ } else if (size <= 256) { ++ tSize = 256; folder = "large/"; ++ } else if (size <= 512) { ++ tSize = 512; folder = "x-large/"; ++ } else { ++ tSize = 1024; folder = "xx-large/"; ++ } ++ Q_UNUSED(tSize); ++ ++ const QString thumbPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + ++ QLatin1String("/thumbnails/") + folder + ++ QString::fromLatin1(md5.result().toHex()) + QStringLiteral(".png"); ++ QFileInfo tInfo(thumbPath); ++ if (tInfo.exists() && info.metadataChangeTime() <= tInfo.lastModified() && info.lastModified() <= tInfo.lastModified()) { ++ thumbReader.setFileName(thumbPath); ++ sz.scale(QSize(size,size), Qt::KeepAspectRatio); ++ thumbReader.setScaledSize(sz); ++ if (thumbReader.read(&thumb)) { ++ int w = thumb.text("Thumb::Image::Width").toInt(); ++ int h = thumb.text("Thumb::Image::Height").toInt(); ++ if (origSz == QSize(w, h)) ++ return QPixmap::fromImage(thumb); ++ } ++ } ++ thumbReader.setFileName(path); ++// sz.scale(QSize(tSize,tSize), Qt::KeepAspectRatio); // in case we'll ever store the thumbnail ++ sz.scale(QSize(size,size), Qt::KeepAspectRatio); ++ thumbReader.setScaledSize(sz); ++ } ++ if (!thumbReader.read(&thumb)) ++ return QPixmap(); ++// if (skipThumbnail) ++ return QPixmap::fromImage(thumb); ++} ++ ++class DblClckStyle : public QProxyStyle ++{ ++ public: ++ int styleHint(StyleHint hint, const QStyleOption *option = nullptr, ++ const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override ++ { ++ if (hint == QStyle::SH_ItemView_ActivateItemOnSingleClick) ++ return false; ++ return QProxyStyle::styleHint(hint, option, widget, returnData); ++ } ++}; ++ + char Qarma::showFileSelection(const QStringList &args) + { + QFileDialog *dlg = new QFileDialog; +@@ -827,6 +909,17 @@ char Qarma::showFileSelection(const QStringList &args) + if (idx > -1) + mimeFilter = mimeFilter.left(idx).trimmed() + " (" + mimeFilter.mid(idx+1).trimmed() + ")"; + mimeFilters << mimeFilter; ++ } else if (args.at(i) == "--preview-images") { ++ READ_INT(size, UInt, "--preview-images must be followed by a positive number for the thumbnail size"); ++ dlg->setOption(QFileDialog::DontUseNativeDialog); ++ if (QSplitter *splitter = dlg->findChild<QSplitter*>()) { ++ qApp->setStyle(new DblClckStyle); ++ QLabel *preview = new QLabel(splitter); ++ splitter->addWidget(preview); ++ connect(dlg, &QFileDialog::currentChanged, [=](const QString &path) { ++ preview->setPixmap(thumbnail(path, size)); ++ }); ++ } + } + else { WARN_UNKNOWN_ARG("--file-selection") } + } +@@ -1815,7 +1908,8 @@ void Qarma::printHelp(const QString &category) + Help("--save", tr("Activate save mode")) << + Help("--separator=SEPARATOR", tr("Set output separator character")) << + Help("--confirm-overwrite", tr("Confirm file selection if filename already exists")) << +- Help("--file-filter=NAME | PATTERN1 PATTERN2 ...", tr("Sets a filename filter"))); ++ Help("--file-filter=NAME | PATTERN1 PATTERN2 ...", tr("Sets a filename filter")) << ++ Help("--preview-images=SIZE", "QARMA ONLY! " + tr("Show image thumbnails of SIZE"))); + helpDict["list"] = CategoryHelp(tr("List Command\n %1 --list [Options] [Item1 ...]\nList Options").arg(applicationName()), HelpList() << + Help("--text=TEXT", tr("Set the dialog text")) << + Help("--column=COLUMN", tr("Set the column header")) << |
