File indexing completed on 2024-04-28 17:06:21

0001 /*
0002     SPDX-FileCopyrightText: 2002 Shie Erlich <erlich@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2002 Rafi Yanai <yanai@users.sourceforge.net>
0004     SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "krpreviewpopup.h"
0010 
0011 #include <algorithm>
0012 
0013 // QtGui
0014 #include <QPainter>
0015 #include <QPixmap>
0016 // QtWidgets
0017 #include <QApplication>
0018 #include <QProxyStyle>
0019 #include <QStyleOptionMenuItem>
0020 
0021 #include <KI18n/KLocalizedString>
0022 #include <KIO/PreviewJob>
0023 
0024 #include "../KViewer/krviewer.h"
0025 
0026 class KrPreviewPopup::ProxyStyle : public QProxyStyle
0027 {
0028 public:
0029     ProxyStyle()
0030         : QProxyStyle(QApplication::style())
0031     {
0032     }
0033 
0034     QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget = nullptr) const override
0035     {
0036         if (type == QStyle::CT_MenuItem) {
0037             const auto *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option);
0038 
0039             QFontMetrics fontMetrics(menuItem->font);
0040             QSize iconSize = menuItem->icon.actualSize(QSize(MAX_SIZE, MAX_SIZE));
0041             QSize textSize = QSize(fontMetrics.boundingRect(menuItem->text).width(), fontMetrics.height());
0042 
0043             return QSize(std::max(iconSize.width(), textSize.width()) + MARGIN * 2, iconSize.height() + textSize.height() + MARGIN * 2);
0044         } else
0045             return QProxyStyle::sizeFromContents(type, option, contentsSize, widget);
0046     }
0047 
0048     void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override
0049     {
0050         if (element == QStyle::CE_MenuItem) {
0051             painter->save();
0052 
0053             const auto *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option);
0054 
0055             bool active = menuItem->state & State_Selected;
0056 
0057             QRect rect = menuItem->rect;
0058 
0059             if (active)
0060                 painter->fillRect(rect, menuItem->palette.brush(QPalette::Highlight));
0061 
0062             rect.adjust(MARGIN, MARGIN, -MARGIN, -MARGIN);
0063 
0064             int textHeight = QFontMetrics(menuItem->font).height();
0065 
0066             QRect previewRect = rect;
0067             previewRect.setHeight(rect.height() - textHeight);
0068             QPixmap pixmap = menuItem->icon.pixmap(menuItem->icon.actualSize(QSize(MAX_SIZE, MAX_SIZE)));
0069             QProxyStyle::drawItemPixmap(painter, previewRect, Qt::AlignCenter, pixmap);
0070 
0071             QRect textRect = rect;
0072             textRect.setTop(previewRect.bottom() + 1);
0073             painter->setPen(active ? menuItem->palette.highlightedText().color() : menuItem->palette.buttonText().color());
0074             int textFlags = Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine | Qt::AlignCenter;
0075             painter->drawText(textRect, textFlags, menuItem->text);
0076 
0077             painter->restore();
0078         } else
0079             QProxyStyle::drawControl(element, option, painter, widget);
0080     }
0081 };
0082 
0083 KrPreviewPopup::KrPreviewPopup()
0084     : jobStarted(false)
0085 {
0086     prevNotAvailAction = addAction(i18n("Preview not available"));
0087 
0088     setStyle(new ProxyStyle());
0089 
0090     connect(this, &KrPreviewPopup::triggered, this, &KrPreviewPopup::view);
0091 }
0092 
0093 void KrPreviewPopup::showEvent(QShowEvent *event)
0094 {
0095     QMenu::showEvent(event);
0096 
0097     if (!jobStarted) {
0098         QStringList allPlugins = KIO::PreviewJob::availablePlugins();
0099         KIO::PreviewJob *pjob = new KIO::PreviewJob(files, QSize(MAX_SIZE, MAX_SIZE), &allPlugins);
0100         pjob->setOverlayIconSize(0);
0101         pjob->setOverlayIconAlpha(1);
0102         pjob->setScaleType(KIO::PreviewJob::ScaledAndCached);
0103         connect(pjob, &KIO::PreviewJob::gotPreview, this, &KrPreviewPopup::addPreview);
0104         jobStarted = true;
0105     }
0106 }
0107 
0108 void KrPreviewPopup::setUrls(const QList<QUrl> &urls)
0109 {
0110     foreach (const QUrl &url, urls) {
0111         files.push_back(KFileItem(url));
0112     }
0113 }
0114 
0115 void KrPreviewPopup::addPreview(const KFileItem &file, const QPixmap &preview)
0116 {
0117     if (prevNotAvailAction) {
0118         removeAction(prevNotAvailAction);
0119         delete prevNotAvailAction;
0120         prevNotAvailAction = nullptr;
0121     }
0122 
0123     QAction *act = addAction(file.text());
0124     act->setIcon(QIcon(preview));
0125     act->setData(QVariant::fromValue(file.url()));
0126 }
0127 
0128 void KrPreviewPopup::view(QAction *clicked)
0129 {
0130     if (clicked && clicked->data().canConvert<QUrl>())
0131         KrViewer::view(clicked->data().value<QUrl>());
0132 }