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