109void QxPluginManagerDialogPrivate::init()
113 q->setWindowTitle(QxPluginManagerDialog::tr(
"Plugins"));
116 QVBoxLayout *outer =
new QVBoxLayout(q);
118 QHBoxLayout *body =
new QHBoxLayout();
119 outer->addLayout(body, 1);
121 m_tree =
new QTreeWidget(q);
122 m_tree->setRootIsDecorated(
false);
123 m_tree->setUniformRowHeights(
true);
124 m_tree->setAllColumnsShowFocus(
true);
125 m_tree->setSelectionMode(QAbstractItemView::SingleSelection);
126 m_tree->setColumnCount(4);
127 m_tree->setHeaderLabels(QStringList{QxPluginManagerDialog::tr(
"Order"), QxPluginManagerDialog::tr(
"Plugin"),
128 QxPluginManagerDialog::tr(
"Version"), QxPluginManagerDialog::tr(
"Status")});
129 m_tree->header()->setSectionResizeMode(kPluginColumn, QHeaderView::Stretch);
130 m_tree->setColumnWidth(kOrderColumn, 64);
131 m_tree->setColumnWidth(kVersionColumn, 90);
132 m_tree->setColumnWidth(kStatusColumn, 130);
133 body->addWidget(m_tree, 3);
135 QVBoxLayout *side =
new QVBoxLayout();
136 body->addLayout(side, 2);
138 QGroupBox *details =
new QGroupBox(QxPluginManagerDialog::tr(
"Details"), q);
139 QFormLayout *form =
new QFormLayout(details);
140 m_id = addValueRow(form, QxPluginManagerDialog::tr(
"Plugin"));
141 m_description = addValueRow(form, QxPluginManagerDialog::tr(
"Description"));
142 m_version = addValueRow(form, QxPluginManagerDialog::tr(
"Version"));
143 m_vendor = addValueRow(form, QxPluginManagerDialog::tr(
"Vendor"));
144 m_file = addValueRow(form, QxPluginManagerDialog::tr(
"File"));
145 m_order = addValueRow(form, QxPluginManagerDialog::tr(
"Load order"));
146 m_state = addValueRow(form, QxPluginManagerDialog::tr(
"State"));
147 m_dependencies = addValueRow(form, QxPluginManagerDialog::tr(
"Depends on"));
148 m_optional = addValueRow(form, QxPluginManagerDialog::tr(
"Optional"));
149 m_dependents = addValueRow(form, QxPluginManagerDialog::tr(
"Required by"));
150 m_error = addValueRow(form, QxPluginManagerDialog::tr(
"Error"));
151 side->addWidget(details);
153 QGroupBox *diagnosticsBox =
new QGroupBox(QxPluginManagerDialog::tr(
"Diagnostics"), q);
154 QVBoxLayout *diagnosticsLayout =
new QVBoxLayout(diagnosticsBox);
155 m_diagnostics =
new QLabel(diagnosticsBox);
156 m_diagnostics->setWordWrap(
true);
157 m_diagnostics->setTextInteractionFlags(Qt::TextSelectableByMouse);
158 m_diagnostics->setAlignment(Qt::AlignLeft | Qt::AlignTop);
159 diagnosticsLayout->addWidget(m_diagnostics);
160 side->addWidget(diagnosticsBox, 1);
162 QLabel *hint =
new QLabel(
163 QxPluginManagerDialog::tr(
"Switching a plugin on or off takes effect the next time the application starts."),
165 hint->setWordWrap(
true);
166 outer->addWidget(hint);
168 m_buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply, q);
169 outer->addWidget(m_buttons);
171 QObject::connect(m_buttons, &QDialogButtonBox::accepted, q, [q]() {
174 QObject::connect(m_buttons, &QDialogButtonBox::rejected, q, [q]() {
179 QObject::connect(m_buttons->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, q, [q]() {
183 QObject::connect(m_tree, &QTreeWidget::currentItemChanged, q, [
this](QTreeWidgetItem *current, QTreeWidgetItem *) {
184 const int row = current ? m_tree->indexOfTopLevelItem(current) : -1;
187 QObject::connect(m_tree, &QTreeWidget::itemChanged, q, [
this](QTreeWidgetItem *item) {
242void QxPluginManagerDialogPrivate::rebuild()
254 QList<QxPluginSpec *> specs;
255 QHash<QxPluginSpec *, int> orderOf;
256 if (!m_manager.isNull()) {
257 specs = m_manager->allSpecs();
258 const QList<QxPluginSpec *> ordered = m_manager->specs();
259 for (
int i = 0; i < ordered.count(); ++i)
260 orderOf.insert(ordered.at(i), i);
266 return orderOf.value(spec, -1);
269 const int leftRank = rank(left);
270 const int rightRank = rank(right);
271 if (leftRank >= 0 && rightRank < 0)
273 if (leftRank < 0 && rightRank >= 0)
275 if (leftRank >= 0 && rightRank >= 0 && leftRank != rightRank)
276 return leftRank < rightRank;
277 return QString::compare(left->id(), right->id(), Qt::CaseInsensitive) < 0;
281 const int order = orderOf.value(spec, -1);
282 QTreeWidgetItem *item =
new QTreeWidgetItem(m_tree);
283 item->setText(kOrderColumn, order < 0 ? emptyMark() : QString::number(order + 1));
284 item->setText(kPluginColumn, spec->id());
285 item->setText(kVersionColumn, spec->version().toString());
286 item->setText(kStatusColumn, stateTextOf(spec));
287 item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
288 const bool on = savedState(spec);
289 item->setCheckState(kPluginColumn, on ? Qt::Checked : Qt::Unchecked);
290 if (!spec->error().isEmpty())
291 item->setToolTip(kPluginColumn, spec->error());
293 m_specs.append(spec);
294 m_switch.insert(spec->id(), on);
298 if (!m_specs.isEmpty())
299 m_tree->setCurrentItem(m_tree->topLevelItem(0));
303 m_diagnostics->setText(!m_manager.isNull() && m_manager->hasError() ? m_manager->errorString()
304 : QxPluginManagerDialog::tr(
"No errors."));
310 const QList<QLabel *> labels{m_id, m_description, m_version, m_vendor, m_file, m_order,
311 m_state, m_dependencies, m_optional, m_dependents, m_error};
314 for (QLabel *label : labels)
320 if (!m_manager.isNull())
321 order = m_manager->specs().indexOf(spec);
325 QStringList dependents;
329 if (other->dependencies().contains(spec->
id()))
330 dependents.append(other->id());
331 else if (other->optionalDependencies().contains(spec->
id()))
332 dependents.append(QxPluginManagerDialog::tr(
"%1 (optional)").arg(other->id()));
335 m_id->setText(spec->
id());
338 m_version->setText(spec->
version().toString());
340 m_version->setText(QxPluginManagerDialog::tr(
"%1 (host compatible from %2)")
342 m_vendor->setText(spec->
vendor().isEmpty() ? emptyMark() : spec->
vendor());
343 m_file->setText(spec->
filePath().isEmpty() ? emptyMark() : spec->
filePath());
344 m_order->setText(order < 0 ? emptyMark() : QString::number(order + 1));
345 m_state->setText(stateTextOf(spec));
348 m_dependents->setText(joined(dependents));
349 m_error->setText(spec->
error().isEmpty() ? emptyMark() : spec->
error());