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 }