Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
plugindialog.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4
7#include "iconloader_p.h"
8
9#include <QtDesigner/abstractformeditor.h>
10#include <QtDesigner/abstractintegration.h>
11#include <QtDesigner/abstractwidgetdatabase.h>
12
13#include <QtUiPlugin/customwidget.h>
14
15#include <QtWidgets/qaction.h>
16#include <QtWidgets/qstyle.h>
17#include <QtWidgets/qheaderview.h>
18#include <QtWidgets/qmenu.h>
19#include <QtWidgets/qpushbutton.h>
20
21#if QT_CONFIG(clipboard)
22# include <QtGui/QClipboard>
23#endif
24
25#include <QtCore/qdir.h>
26#include <QtCore/qfileinfo.h>
27#include <QtCore/qpluginloader.h>
28
30
31using namespace Qt::StringLiterals;
32
33enum { ErrorItemRole = Qt::UserRole + 1 };
34
35namespace qdesigner_internal {
36
37PluginDialog::PluginDialog(QDesignerFormEditorInterface *core, QWidget *parent)
38 : QDialog(parent
39#ifdef Q_OS_MACOS
40 , Qt::Tool
41#endif
42 ), m_core(core)
43{
44 ui.setupUi(this);
45
46 ui.message->hide();
47
48 const QStringList headerLabels(tr("Components"));
49
50 ui.treeWidget->setAlternatingRowColors(false);
51 ui.treeWidget->setSelectionMode(QAbstractItemView::NoSelection);
52 ui.treeWidget->setHeaderLabels(headerLabels);
53 ui.treeWidget->header()->hide();
54 ui.treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
55 connect(ui.treeWidget, &QWidget::customContextMenuRequested,
56 this, &PluginDialog::treeWidgetContextMenu);
57
58 interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon),
59 QIcon::Normal, QIcon::On);
60 interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon),
61 QIcon::Normal, QIcon::Off);
62 featureIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon));
63
64 setWindowTitle(tr("Plugin Information"));
65 populateTreeWidget();
66
67 QPushButton *updateButton = new QPushButton(tr("Refresh"));
68 const QString tooltip = tr("Scan for newly installed custom widget plugins.");
69 updateButton->setToolTip(tooltip);
70 updateButton->setWhatsThis(tooltip);
71 connect(updateButton, &QAbstractButton::clicked, this, &PluginDialog::updateCustomWidgetPlugins);
72 ui.buttonBox->addButton(updateButton, QDialogButtonBox::ActionRole);
73
74}
75
76void PluginDialog::populateTreeWidget()
77{
78 ui.treeWidget->clear();
79 QDesignerPluginManager *pluginManager = m_core->pluginManager();
80 const QStringList fileNames = pluginManager->registeredPlugins();
81
82 if (!fileNames.isEmpty()) {
83 QTreeWidgetItem *topLevelItem = setTopLevelItem(tr("Loaded Plugins"));
84 QFont boldFont = topLevelItem->font(0);
85
86 for (const QString &fileName : fileNames) {
87 QPluginLoader loader(fileName);
88 const QFileInfo fileInfo(fileName);
89
90 QTreeWidgetItem *pluginItem = setPluginItem(topLevelItem, fileInfo, boldFont);
91
92 if (QObject *plugin = loader.instance()) {
93 if (const QDesignerCustomWidgetCollectionInterface *c = qobject_cast<QDesignerCustomWidgetCollectionInterface*>(plugin)) {
94 const auto &collCustomWidgets = c->customWidgets();
95 for (const QDesignerCustomWidgetInterface *p : collCustomWidgets)
96 setItem(pluginItem, p->name(), p->toolTip(), p->whatsThis(), p->icon());
97 } else {
98 if (const QDesignerCustomWidgetInterface *p = qobject_cast<QDesignerCustomWidgetInterface*>(plugin))
99 setItem(pluginItem, p->name(), p->toolTip(), p->whatsThis(), p->icon());
100 }
101 }
102 }
103 }
104
105 const QStringList notLoadedPlugins = pluginManager->failedPlugins();
106 if (!notLoadedPlugins.isEmpty()) {
107 QTreeWidgetItem *topLevelItem = setTopLevelItem(tr("Failed Plugins"));
108 const QFont boldFont = topLevelItem->font(0);
109 for (const QString &plugin : notLoadedPlugins) {
110 const QString failureReason = pluginManager->failureReason(plugin);
111 const QString htmlFailureReason = "<html><head/><body><p>"_L1
112 + failureReason.toHtmlEscaped()
113 + "</p></body></html>"_L1;
114 QTreeWidgetItem *pluginItem = setPluginItem(topLevelItem, QFileInfo(plugin), boldFont);
115 auto errorItem = setItem(pluginItem, failureReason,
116 htmlFailureReason, QString(), QIcon());
117 errorItem->setData(0, ErrorItemRole, QVariant(true));
118 }
119 }
120
121 if (ui.treeWidget->topLevelItemCount() == 0) {
122 ui.label->setText(tr("Qt Widgets Designer couldn't find any plugins"));
123 ui.treeWidget->hide();
124 } else {
125 ui.label->setText(tr("Qt Widgets Designer found the following plugins"));
126 }
127}
128
129QTreeWidgetItem* PluginDialog::setTopLevelItem(const QString &itemName)
130{
131 QTreeWidgetItem *topLevelItem = new QTreeWidgetItem(ui.treeWidget);
132 topLevelItem->setText(0, itemName);
133 topLevelItem->setExpanded(true);
134 topLevelItem->setIcon(0, style()->standardPixmap(QStyle::SP_DirOpenIcon));
135
136 QFont boldFont = topLevelItem->font(0);
137 boldFont.setBold(true);
138 topLevelItem->setFont(0, boldFont);
139
140 return topLevelItem;
141}
142
143QTreeWidgetItem* PluginDialog::setPluginItem(QTreeWidgetItem *topLevelItem,
144 const QFileInfo &file, const QFont &font)
145{
146 QTreeWidgetItem *pluginItem = new QTreeWidgetItem(topLevelItem);
147 QString toolTip = QDir::toNativeSeparators(file.absoluteFilePath());
148 if (file.exists())
149 toolTip += u'\n' + file.lastModified().toString();
150 pluginItem->setFont(0, font);
151 pluginItem->setText(0, file.fileName());
152 pluginItem->setToolTip(0, toolTip);
153 pluginItem->setExpanded(true);
154 pluginItem->setIcon(0, style()->standardPixmap(QStyle::SP_DirOpenIcon));
155
156 return pluginItem;
157}
158
159QTreeWidgetItem *PluginDialog::setItem(QTreeWidgetItem *pluginItem, const QString &name,
160 const QString &toolTip, const QString &whatsThis,
161 const QIcon &icon)
162{
163 QTreeWidgetItem *item = new QTreeWidgetItem(pluginItem);
164 item->setText(0, name);
165 item->setToolTip(0, toolTip);
166 item->setWhatsThis(0, whatsThis);
167 item->setIcon(0, icon.isNull() ? qtLogoIcon() : icon);
168 return item;
169}
170
171void PluginDialog::updateCustomWidgetPlugins()
172{
173 const int before = m_core->widgetDataBase()->count();
174 m_core->integration()->updateCustomWidgetPlugins();
175 const int after = m_core->widgetDataBase()->count();
176 if (after > before) {
177 ui.message->setText(tr("New custom widget plugins have been found."));
178 ui.message->show();
179 } else {
180 ui.message->setText(QString());
181 }
182 populateTreeWidget();
183}
184
185void PluginDialog::treeWidgetContextMenu(const QPoint &pos)
186{
187#if QT_CONFIG(clipboard)
188 const QTreeWidgetItem *item = ui.treeWidget->itemAt(pos);
189 if (item == nullptr || !item->data(0, ErrorItemRole).toBool())
190 return;
191 QMenu menu;
192 //: Copy error text
193 auto copyAction = menu.addAction(tr("Copy"));
194 auto chosenAction = menu.exec(ui.treeWidget->mapToGlobal(pos));
195 if (chosenAction == nullptr)
196 return;
197 if (chosenAction == copyAction)
198 QGuiApplication::clipboard()->setText(item->text(0));
199#else
200 Q_UNUSED(pos);
201#endif
202}
203
204} // namespace qdesigner_internal
205
206QT_END_NAMESPACE
207
208#include "moc_plugindialog_p.cpp"
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.
@ ErrorItemRole