FreeCAD

Форк
0
/
FileCardDelegate.cpp 
234 строки · 10.4 Кб
1
// SPDX-License-Identifier: LGPL-2.1-or-later
2
/****************************************************************************
3
 *                                                                          *
4
 *   Copyright (c) 2024 The FreeCAD Project Association AISBL               *
5
 *                                                                          *
6
 *   This file is part of FreeCAD.                                          *
7
 *                                                                          *
8
 *   FreeCAD is free software: you can redistribute it and/or modify it     *
9
 *   under the terms of the GNU Lesser General Public License as            *
10
 *   published by the Free Software Foundation, either version 2.1 of the   *
11
 *   License, or (at your option) any later version.                        *
12
 *                                                                          *
13
 *   FreeCAD is distributed in the hope that it will be useful, but         *
14
 *   WITHOUT ANY WARRANTY; without even the implied warranty of             *
15
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU       *
16
 *   Lesser General Public License for more details.                        *
17
 *                                                                          *
18
 *   You should have received a copy of the GNU Lesser General Public       *
19
 *   License along with FreeCAD. If not, see                                *
20
 *   <https://www.gnu.org/licenses/>.                                       *
21
 *                                                                          *
22
 ***************************************************************************/
23

24
#include "PreCompiled.h"
25

26
#ifndef _PreComp_
27
#include <QFile>
28
#include <QFileIconProvider>
29
#include <QImageReader>
30
#include <QPainter>
31
#include <QStyleOptionViewItem>
32
#include <QLabel>
33
#include <QModelIndex>
34
#include <QVBoxLayout>
35
#include <QApplication>
36
#endif
37

38
#include "FileCardDelegate.h"
39
#include "../App/DisplayedFilesModel.h"
40
#include "App/Application.h"
41
#include <App/Color.h>
42
#include <gsl/pointers>
43

44
using namespace Start;
45

46
FileCardDelegate::FileCardDelegate(QObject* parent)
47
    : QAbstractItemDelegate(parent)
48
{
49
    _parameterGroup = App::GetApplication().GetParameterGroupByPath(
50
        "User parameter:BaseApp/Preferences/Mod/Start");
51
    _widget = std::make_unique<QWidget>();
52
    _widget->setObjectName(QLatin1String("thumbnailWidget"));
53
    auto layout = gsl::owner<QVBoxLayout*>(new QVBoxLayout());
54
    layout->setSpacing(0);
55
    _widget->setLayout(layout);
56
}
57

58
QColor FileCardDelegate::getBorderColor() const
59
{
60
    QColor color(98, 160, 234);  // NOLINT
61
    uint32_t packed = App::Color::asPackedRGB<QColor>(color);
62
    packed = _parameterGroup->GetUnsigned("FileThumbnailBorderColor", packed);
63
    color = App::Color::fromPackedRGB<QColor>(packed);
64
    return color;
65
}
66

67
QColor FileCardDelegate::getBackgroundColor() const
68
{
69
    QColor color(221, 221, 221);  // NOLINT
70
    uint32_t packed = App::Color::asPackedRGB<QColor>(color);
71
    packed = _parameterGroup->GetUnsigned("FileThumbnailBackgroundColor", packed);
72
    color = App::Color::fromPackedRGB<QColor>(packed);
73
    return color;
74
}
75

76
QColor FileCardDelegate::getSelectionColor() const
77
{
78
    QColor color(38, 162, 105);  // NOLINT
79
    uint32_t packed = App::Color::asPackedRGB<QColor>(color);
80
    packed = _parameterGroup->GetUnsigned("FileThumbnailSelectionColor", packed);
81
    color = App::Color::fromPackedRGB<QColor>(packed);
82
    return color;
83
}
84

85
void FileCardDelegate::paint(QPainter* painter,
86
                             const QStyleOptionViewItem& option,
87
                             const QModelIndex& index) const
88
{
89
    auto thumbnailSize =
90
        static_cast<int>(_parameterGroup->GetInt("FileThumbnailIconsSize", 128));  // NOLINT
91
    auto cardWidth = thumbnailSize;
92
    auto baseName = index.data(static_cast<int>(DisplayedFilesModelRoles::baseName)).toString();
93
    auto size = index.data(static_cast<int>(DisplayedFilesModelRoles::size)).toString();
94
    auto image = index.data(static_cast<int>(DisplayedFilesModelRoles::image)).toByteArray();
95
    auto path = index.data(static_cast<int>(DisplayedFilesModelRoles::path)).toString();
96
    painter->save();
97
    auto thumbnail = std::make_unique<QLabel>();
98
    auto pixmap = std::make_unique<QPixmap>();
99
    auto layout = qobject_cast<QVBoxLayout*>(_widget->layout());
100
    if (!image.isEmpty()) {
101
        pixmap->loadFromData(image);
102
        if (!pixmap->isNull()) {
103
            auto scaled = pixmap->scaled(QSize(thumbnailSize, thumbnailSize),
104
                                         Qt::AspectRatioMode::KeepAspectRatio,
105
                                         Qt::TransformationMode::SmoothTransformation);
106
            thumbnail->setPixmap(scaled);
107
        }
108
    }
109
    else {
110
        thumbnail->setPixmap(generateThumbnail(path));
111
    }
112
    thumbnail->setFixedSize(thumbnailSize, thumbnailSize);
113
    thumbnail->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed);
114

115
    _widget->setProperty("state", QStringLiteral(""));
116
    if (option.state & QStyle::State_Selected) {
117
        _widget->setProperty("state", QStringLiteral("pressed"));
118
        if (qApp->styleSheet().isEmpty()) {
119
            QColor color = getSelectionColor();
120
            _widget->setStyleSheet(QString::fromLatin1("QWidget#thumbnailWidget {"
121
                                                       " border: 2px solid rgb(%1, %2, %3);"
122
                                                       " border-radius: 4px;"
123
                                                       " padding: 2px;"
124
                                                       "}")
125
                                       .arg(color.red())
126
                                       .arg(color.green())
127
                                       .arg(color.blue()));
128
        }
129
    }
130
    else if (option.state & QStyle::State_MouseOver) {
131
        _widget->setProperty("state", QStringLiteral("hovered"));
132
        if (qApp->styleSheet().isEmpty()) {
133
            QColor color = getBorderColor();
134
            _widget->setStyleSheet(QString::fromLatin1("QWidget#thumbnailWidget {"
135
                                                       " border: 2px solid rgb(%1, %2, %3);"
136
                                                       " border-radius: 4px;"
137
                                                       " padding: 2px;"
138
                                                       "}")
139
                                       .arg(color.red())
140
                                       .arg(color.green())
141
                                       .arg(color.blue()));
142
        }
143
    }
144
    else if (qApp->styleSheet().isEmpty()) {
145
        QColor color = getBackgroundColor();
146
        _widget->setStyleSheet(QString::fromLatin1("QWidget#thumbnailWidget {"
147
                                                   " background-color: rgb(%1, %2, %3);"
148
                                                   " border-radius: 8px;"
149
                                                   "}")
150
                                   .arg(color.red())
151
                                   .arg(color.green())
152
                                   .arg(color.blue()));
153
    }
154

155
    auto elided =
156
        painter->fontMetrics().elidedText(baseName, Qt::TextElideMode::ElideRight, cardWidth);
157
    auto name = std::make_unique<QLabel>(elided);
158
    layout->addWidget(thumbnail.get());  // Temp. ownership transfer
159
    layout->addWidget(name.get());       // Temp. ownership transfer
160
    auto sizeLabel = std::make_unique<QLabel>(size);
161
    layout->addWidget(sizeLabel.get());  // Temp. ownership transfer
162
    layout->addStretch();
163
    _widget->resize(option.rect.size());
164
    painter->translate(option.rect.topLeft());
165
    _widget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren);
166
    painter->restore();
167
    layout->removeWidget(sizeLabel.get());
168
    layout->removeWidget(thumbnail.get());
169
    layout->removeWidget(name.get());
170
}
171

172

173
QSize FileCardDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
174
{
175
    Q_UNUSED(option)
176
    Q_UNUSED(index)
177
    auto thumbnailSize = _parameterGroup->GetInt("FileThumbnailIconsSize", 128);  // NOLINT
178
    auto cardMargin = _widget->layout()->contentsMargins();
179
    auto cardWidth = thumbnailSize + cardMargin.left() + cardMargin.right();
180
    auto spacing = _widget->layout()->spacing();
181

182
    auto font = QGuiApplication::font();
183
    auto qfm = QFontMetrics(font);
184
    auto textHeight = 2 * qfm.lineSpacing();
185
    auto cardHeight =
186
        thumbnailSize + textHeight + 2 * spacing + cardMargin.top() + cardMargin.bottom();
187

188
    return {static_cast<int>(cardWidth), static_cast<int>(cardHeight)};
189
}
190

191
namespace
192
{
193
QPixmap pixmapToSizedQImage(const QImage& pixmap, int size)
194
{
195
    return QPixmap::fromImage(pixmap).scaled(size,
196
                                             size,
197
                                             Qt::AspectRatioMode::KeepAspectRatio,
198
                                             Qt::TransformationMode::SmoothTransformation);
199
}
200
}  // namespace
201

202
QPixmap FileCardDelegate::generateThumbnail(const QString& path) const
203
{
204
    auto thumbnailSize =
205
        static_cast<int>(_parameterGroup->GetInt("FileThumbnailIconsSize", 128));  // NOLINT
206
    if (path.endsWith(QLatin1String(".fcstd"), Qt::CaseSensitivity::CaseInsensitive)) {
207
        QImageReader reader(QLatin1String(":/icons/freecad-doc.svg"));
208
        reader.setScaledSize({thumbnailSize, thumbnailSize});
209
        return QPixmap::fromImage(reader.read());
210
    }
211
    if (path.endsWith(QLatin1String(".fcmacro"), Qt::CaseSensitivity::CaseInsensitive)) {
212
        QImageReader reader(QLatin1String(":/icons/MacroEditor.svg"));
213
        reader.setScaledSize({thumbnailSize, thumbnailSize});
214
        return QPixmap::fromImage(reader.read());
215
    }
216
    if (!QImageReader::imageFormat(path).isEmpty()) {
217
        // It is an image: it can be its own thumbnail
218
        QImageReader reader(path);
219
        auto image = reader.read();
220
        if (!image.isNull()) {
221
            return pixmapToSizedQImage(image, thumbnailSize);
222
        }
223
    }
224
    QIcon icon = QFileIconProvider().icon(QFileInfo(path));
225
    if (!icon.isNull()) {
226
        QPixmap pixmap = icon.pixmap(thumbnailSize);
227
        if (!pixmap.isNull()) {
228
            return pixmap;
229
        }
230
    }
231
    QPixmap pixmap = QPixmap(thumbnailSize, thumbnailSize);
232
    pixmap.fill();
233
    return pixmap;
234
}
235

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.