6#include <iconloader_p.h>
7#include <iconselector_p.h>
8#include <qdesigner_utils_p.h>
10#include <QtDesigner/abstractformeditor.h>
12#include <QtWidgets/qapplication.h>
13#include <QtWidgets/qlabel.h>
14#include <QtWidgets/qtoolbutton.h>
15#include <QtWidgets/qboxlayout.h>
16#include <QtWidgets/qlineedit.h>
17#include <QtWidgets/qdialogbuttonbox.h>
18#include <QtWidgets/qpushbutton.h>
19#include <QtWidgets/qfiledialog.h>
20#include <QtWidgets/qmenu.h>
22#include <QtGui/qaction.h>
23#if QT_CONFIG(clipboard)
24#include <QtGui/qclipboard.h>
26#include <QtGui/qevent.h>
30using namespace Qt::StringLiterals;
39 QVBoxLayout *layout =
new QVBoxLayout(topLevel);
40 QLabel *label =
new QLabel(labelText, topLevel);
41 QDialogButtonBox *buttons =
new QDialogButtonBox(topLevel);
42 buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
43 QObject::connect(buttons, &QDialogButtonBox::accepted, topLevel, &QDialog::accept);
44 QObject::connect(buttons, &QDialogButtonBox::rejected, topLevel, &QDialog::reject);
46 layout->addWidget(label);
47 layout->addWidget(themeEditor);
48 layout->addWidget(buttons);
54 setWindowTitle(tr(
"Set Icon From XDG Theme"));
55 m_editor =
new IconThemeEditor(
this);
56 createIconThemeDialog(
this, tr(
"Select icon name from XDG theme:"), m_editor);
59std::optional<QString>
IconThemeDialog::getTheme(QWidget *parent,
const QString &theme)
62 dlg.m_editor->setTheme(theme);
63 if (dlg.exec() == QDialog::Accepted)
64 return dlg.m_editor->theme();
71 setWindowTitle(tr(
"Set Icon From Theme"));
72 m_editor =
new IconThemeEnumEditor(
this);
73 createIconThemeDialog(
this, tr(
"Select icon name from theme:"), m_editor);
79 dlg.m_editor->setThemeEnum(theme);
80 if (dlg.exec() == QDialog::Accepted)
81 return dlg.m_editor->themeEnum();
85PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
87 m_iconThemeModeEnabled(
false),
89 m_pixmapLabel(
new QLabel(
this)),
90 m_pathLabel(
new QLabel(
this)),
91 m_button(
new QToolButton(
this)),
92 m_resourceAction(
new QAction(tr(
"Choose Resource..."),
this)),
93 m_fileAction(
new QAction(tr(
"Choose File..."),
this)),
94 m_themeEnumAction(
new QAction(tr(
"Set Icon From Theme..."),
this)),
95 m_themeAction(
new QAction(tr(
"Set Icon From XDG Theme..."),
this)),
96 m_copyAction(
new QAction(createIconSet(QIcon::ThemeIcon::EditCopy,
"editcopy.png"_L1),
97 tr(
"Copy Path"),
this)),
98 m_pasteAction(
new QAction(createIconSet(QIcon::ThemeIcon::EditPaste,
"editpaste.png"_L1),
99 tr(
"Paste Path"),
this)),
100 m_layout(
new QHBoxLayout(
this)),
101 m_pixmapCache(
nullptr)
103 m_layout->addWidget(m_pixmapLabel);
104 m_layout->addWidget(m_pathLabel);
105 m_button->setText(tr(
"..."));
106 m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
107 m_button->setFixedWidth(30);
108 m_button->setPopupMode(QToolButton::MenuButtonPopup);
109 m_layout->addWidget(m_button);
110 m_layout->setContentsMargins(QMargins());
111 m_layout->setSpacing(0);
112 m_pixmapLabel->setFixedWidth(ICON_SIZE.width());
113 m_pixmapLabel->setAlignment(Qt::AlignCenter);
114 m_pathLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
115 m_themeAction->setVisible(
false);
116 m_themeEnumAction->setVisible(
false);
118 QMenu *menu =
new QMenu(
this);
119 menu->addAction(m_resourceAction);
120 menu->addAction(m_fileAction);
121 menu->addAction(m_themeEnumAction);
122 menu->addAction(m_themeAction);
124 m_button->setMenu(menu);
125 m_button->setText(tr(
"..."));
127 connect(m_button, &QAbstractButton::clicked,
this, &PixmapEditor::defaultActionActivated);
128 connect(m_resourceAction, &QAction::triggered,
this, &
PixmapEditor::resourceActionActivated);
129 connect(m_fileAction, &QAction::triggered,
this, &
PixmapEditor::fileActionActivated);
130 connect(m_themeEnumAction, &QAction::triggered,
this, &
PixmapEditor::themeEnumActionActivated);
131 connect(m_themeAction, &QAction::triggered,
this, &
PixmapEditor::themeActionActivated);
132#if QT_CONFIG(clipboard)
133 connect(m_copyAction, &QAction::triggered,
this, &PixmapEditor::copyActionActivated);
134 connect(m_pasteAction, &QAction::triggered,
this, &PixmapEditor::pasteActionActivated);
136 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored));
137 setFocusProxy(m_button);
139#if QT_CONFIG(clipboard)
140 connect(QApplication::clipboard(), &QClipboard::dataChanged,
141 this, &PixmapEditor::clipboardDataChanged);
142 clipboardDataChanged();
148 m_pixmapCache = cache;
153 if (m_iconThemeModeEnabled == enabled)
155 m_iconThemeModeEnabled = enabled;
156 m_themeAction->setVisible(enabled);
157 m_themeEnumAction->setVisible(enabled);
162 m_layout->setSpacing(spacing);
179 return tr(
"[Theme] %1").arg(t);
184 return tr(
"[Theme] %1 (missing)").arg(t);
195 m_pathLabel->setText(displayText(m_themeEnum, m_theme, m_path));
198 case State::MissingXdgTheme:
199 case State::MissingThemeEnum:
200 m_pixmapLabel->setPixmap(m_defaultPixmap);
201 m_copyAction->setEnabled(
false);
203 case State::ThemeEnum:
204 m_pixmapLabel->setPixmap(QIcon::fromTheme(
static_cast<QIcon::ThemeIcon>(m_themeEnum)).pixmap(ICON_SIZE));
205 m_copyAction->setEnabled(
true);
207 case State::XdgTheme:
208 m_pixmapLabel->setPixmap(QIcon::fromTheme(m_theme).pixmap(ICON_SIZE));
209 m_copyAction->setEnabled(
true);
212 case State::PathFallback:
214 auto pixmap = m_pixmapCache->pixmap(PropertySheetPixmapValue(m_path));
215 m_pixmapLabel->setPixmap(QIcon(pixmap).pixmap(ICON_SIZE));
217 m_copyAction->setEnabled(
true);
224 m_defaultPixmap = icon.pixmap(ICON_SIZE);
225 if (state() == State::Empty)
226 m_pixmapLabel->setPixmap(m_defaultPixmap);
231 setDefaultPixmapIcon(QIcon(pixmap));
237 menu.addAction(m_copyAction);
238 menu.addAction(m_pasteAction);
239 menu.exec(event->globalPos());
245 if (m_iconThemeModeEnabled) {
246 themeEnumActionActivated();
250 const PropertySheetPixmapValue::PixmapSource ps = m_path.isEmpty()
251 ? PropertySheetPixmapValue::ResourcePixmap
252 : PropertySheetPixmapValue::getPixmapSource(m_core, m_path);
254 case PropertySheetPixmapValue::LanguageResourcePixmap:
255 case PropertySheetPixmapValue::ResourcePixmap:
256 resourceActionActivated();
258 case PropertySheetPixmapValue::FilePixmap:
259 fileActionActivated();
266 const QString oldPath = m_path;
267 const QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(),
269 if (!newPath.isEmpty() && newPath != oldPath) {
273 emit pathChanged(newPath);
279 const QString newPath = IconSelector::choosePixmapFile(m_path, m_core->dialogGui(),
this);
280 if (!newPath.isEmpty() && newPath != m_path) {
284 emit pathChanged(newPath);
290 const auto newThemeO = IconThemeEnumDialog::getTheme(
this, {});
291 if (newThemeO.has_value()) {
292 const int newTheme = newThemeO.value();
293 if (newTheme != m_themeEnum) {
297 emit themeEnumChanged(newTheme);
304 const auto newThemeO = IconThemeDialog::getTheme(
this, m_theme);
305 if (newThemeO.has_value()) {
306 const QString newTheme = newThemeO.value();
307 if (newTheme != m_theme) {
311 emit themeChanged(newTheme);
319 if (themeEnum != -1) {
320 if (QIcon::hasThemeIcon(
static_cast<QIcon::ThemeIcon>(themeEnum)))
321 return State::ThemeEnum;
322 return path.isEmpty() ? State::MissingThemeEnum : State::PathFallback;
324 if (!xdgTheme.isEmpty()) {
325 if (QIcon::hasThemeIcon(xdgTheme))
326 return State::XdgTheme;
327 return path.isEmpty() ? State::MissingXdgTheme : State::PathFallback;
329 return path.isEmpty() ? State::Empty : State::Path;
334 return stateFromData(m_themeEnum, m_theme, m_path);
337QString
PixmapEditor::displayText(
int themeEnum,
const QString &xdgTheme,
const QString &path)
339 switch (stateFromData(themeEnum, xdgTheme, path)) {
340 case State::ThemeEnum:
341 return msgThemeIcon(IconThemeEnumEditor::iconName(themeEnum));
342 case State::MissingThemeEnum:
343 return msgMissingThemeIcon(IconThemeEnumEditor::iconName(themeEnum));
344 case State::XdgTheme:
345 return msgThemeIcon(xdgTheme);
346 case State::MissingXdgTheme:
347 return msgMissingThemeIcon(xdgTheme);
349 return QFileInfo(path).fileName();
350 case State::PathFallback:
351 return tr(
"%1 (fallback)").arg(QFileInfo(path).fileName());
360 const auto &paths = icon.paths();
361 const auto &it = paths.constFind({QIcon::Normal, QIcon::Off});
362 const QString path = it != paths.constEnd() ? it.value().path() : QString{};
363 return displayText(icon.themeEnum(), icon.theme(), path);
366#if QT_CONFIG(clipboard)
void setTheme(const QString &theme)
void setDefaultPixmap(const QPixmap &pixmap)
void setSpacing(int spacing)
void setPixmapCache(DesignerPixmapCache *cache)
void setDefaultPixmapIcon(const QIcon &icon)
void setIconThemeModeEnabled(bool enabled)
void contextMenuEvent(QContextMenuEvent *event) override
This event handler, for event event, can be reimplemented in a subclass to receive widget context men...
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.
static void createIconThemeDialog(QDialog *topLevel, const QString &labelText, QWidget *themeEditor)
static constexpr QSize ICON_SIZE