File: krpreviewpopup.cpp

package info (click to toggle)
krusader 2%3A2.9.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 25,448 kB
  • sloc: cpp: 56,112; ansic: 1,187; xml: 811; sh: 23; makefile: 3
file content (130 lines) | stat: -rw-r--r-- 4,319 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
    SPDX-FileCopyrightText: 2002 Shie Erlich <erlich@users.sourceforge.net>
    SPDX-FileCopyrightText: 2002 Rafi Yanai <yanai@users.sourceforge.net>
    SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>

    SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "krpreviewpopup.h"

#include <algorithm>

// QtGui
#include <QPainter>
#include <QPixmap>
// QtWidgets
#include <QApplication>
#include <QProxyStyle>
#include <QStyleOptionMenuItem>

#include <KIO/PreviewJob>
#include <KLocalizedString>

#include "../KViewer/krviewer.h"

class KrPreviewPopup::ProxyStyle : public QProxyStyle
{
public:
    ProxyStyle()
        : QProxyStyle(QApplication::style())
    {
    }

    QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget = nullptr) const override
    {
        if (type == QStyle::CT_MenuItem) {
            const auto *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option);

            QFontMetrics fontMetrics(menuItem->font);
            QSize iconSize = menuItem->icon.actualSize(QSize(MAX_SIZE, MAX_SIZE));
            QSize textSize = QSize(fontMetrics.boundingRect(menuItem->text).width(), fontMetrics.height());

            return QSize(std::max(iconSize.width(), textSize.width()) + MARGIN * 2, iconSize.height() + textSize.height() + MARGIN * 2);
        } else
            return QProxyStyle::sizeFromContents(type, option, contentsSize, widget);
    }

    void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override
    {
        if (element == QStyle::CE_MenuItem) {
            painter->save();

            const auto *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option);

            bool active = menuItem->state & State_Selected;

            QRect rect = menuItem->rect;

            if (active)
                painter->fillRect(rect, menuItem->palette.brush(QPalette::Highlight));

            rect.adjust(MARGIN, MARGIN, -MARGIN, -MARGIN);

            int textHeight = QFontMetrics(menuItem->font).height();

            QRect previewRect = rect;
            previewRect.setHeight(rect.height() - textHeight);
            QPixmap pixmap = menuItem->icon.pixmap(menuItem->icon.actualSize(QSize(MAX_SIZE, MAX_SIZE)));
            QProxyStyle::drawItemPixmap(painter, previewRect, Qt::AlignCenter, pixmap);

            QRect textRect = rect;
            textRect.setTop(previewRect.bottom() + 1);
            painter->setPen(active ? menuItem->palette.highlightedText().color() : menuItem->palette.buttonText().color());
            int textFlags = Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine | Qt::AlignCenter;
            painter->drawText(textRect, textFlags, menuItem->text);

            painter->restore();
        } else
            QProxyStyle::drawControl(element, option, painter, widget);
    }
};

KrPreviewPopup::KrPreviewPopup()
    : jobStarted(false)
{
    prevNotAvailAction = addAction(i18n("Preview not available"));

    setStyle(new ProxyStyle());

    connect(this, &KrPreviewPopup::triggered, this, &KrPreviewPopup::view);
}

void KrPreviewPopup::showEvent(QShowEvent *event)
{
    QMenu::showEvent(event);

    if (!jobStarted) {
        QStringList allPlugins = KIO::PreviewJob::availablePlugins();
        KIO::PreviewJob *pjob = new KIO::PreviewJob(files, QSize(MAX_SIZE, MAX_SIZE), &allPlugins);
        pjob->setScaleType(KIO::PreviewJob::ScaledAndCached);
        connect(pjob, &KIO::PreviewJob::gotPreview, this, &KrPreviewPopup::addPreview);
        jobStarted = true;
    }
}

void KrPreviewPopup::setUrls(const QList<QUrl> &urls)
{
    for (const QUrl &url : urls) {
        files.push_back(KFileItem(url));
    }
}

void KrPreviewPopup::addPreview(const KFileItem &file, const QPixmap &preview)
{
    if (prevNotAvailAction) {
        removeAction(prevNotAvailAction);
        delete prevNotAvailAction;
        prevNotAvailAction = nullptr;
    }

    QAction *act = addAction(file.text());
    act->setIcon(QIcon(preview));
    act->setData(QVariant::fromValue(file.url()));
}

void KrPreviewPopup::view(QAction *clicked)
{
    if (clicked && clicked->data().canConvert<QUrl>())
        KrViewer::view(clicked->data().value<QUrl>());
}