KCMUtils

dialog.cpp
1 /*
2  This file is part of the KDE project
3  SPDX-FileCopyrightText: 2003 Matthias Kretz <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-only
6 */
7 
8 #include "dialog.h"
9 #if KCMUTILS_BUILD_DEPRECATED_SINCE(5, 85)
10 #include "dialog_p.h"
11 
12 #include <kcmutils_debug.h>
13 
14 #include <KConfig>
15 #include <KLocalizedString>
16 #include <KPluginMetaData>
17 #include <KServiceGroup>
18 #include <KServiceTypeTrader>
19 #include <KSharedConfig>
20 
21 #include <QCheckBox>
22 #include <QCoreApplication>
23 #include <QDialogButtonBox>
24 #include <QDir>
25 #include <QLabel>
26 #include <QPushButton>
27 #include <QStack>
28 #include <QVBoxLayout>
29 
30 uint qHash(const KCModuleInfo &info)
31 {
32  return qHash(info.fileName());
33 }
34 
35 namespace KSettings
36 {
38  : Dialog(QStringList{}, parent)
39 {
40 }
41 
42 Dialog::Dialog(const QStringList &components, QWidget *parent)
43  : KCMultiDialog(*new DialogPrivate(this), new KPageWidget, parent)
44 {
45  Q_D(Dialog);
46  d->components = components;
47 }
48 
49 Dialog::~Dialog()
50 {
51 }
52 
54 {
55  d_func()->staticlistview = !selection;
56 }
57 
58 bool Dialog::allowComponentSelection() const
59 {
60  return !d_func()->staticlistview;
61 }
62 
63 void Dialog::setKCMArguments(const QStringList &arguments)
64 {
65  Q_D(Dialog);
66  d->arguments = arguments;
67 }
68 
70 {
71  Q_D(Dialog);
72  d->componentBlacklist = blacklist;
73 }
74 
75 void Dialog::addPluginInfos(const KPluginInfo::List &plugininfos)
76 {
77  Q_D(Dialog);
78  for (KPluginInfo::List::ConstIterator it = plugininfos.begin(); it != plugininfos.end(); ++it) {
79  d->registeredComponents.append(it->pluginName());
80  const auto lst = it->kcmServices();
81  if (lst.isEmpty()) {
82  // this plugin has no kcm services, still we want to show the disable/enable stuff
83  // so add a dummy kcm
84  d->kcmInfos << KCModuleInfo(*it);
85  continue;
86  }
87  for (const KService::Ptr &service : lst) {
88  d->kcmInfos << KCModuleInfo(service);
89  }
90  }
91 
92  // The plugin, when disabled, disables all the KCMs described by kcmServices().
93  // - Normally they are grouped using a .setdlg file so that the group parent can get a
94  // checkbox to enable/disable the plugin.
95  // - If the plugin does not belong to a group and has only one KCM the checkbox can be
96  // used with this KCM.
97  // - If the plugin belongs to a group but there are other modules in the group that do not
98  // belong to this plugin we give a kError and show no checkbox
99  // - If the plugin belongs to multiple groups we give a kError and show no checkbox
100  d->plugininfos = plugininfos;
101 }
102 
104 {
105  return d_func()->plugininfos;
106 }
107 
109 {
110  Q_D(Dialog);
111  if (d->firstshow) {
112  setUpdatesEnabled(false);
113  d->kcmInfos += d->instanceServices();
114  if (!d->components.isEmpty()) {
115  d->kcmInfos += d->parentComponentsServices(d->components);
116  }
117  d->createDialogFromServices();
118  d->firstshow = false;
119  setUpdatesEnabled(true);
120  }
121 
122  for (const QString &compName : std::as_const(d->components)) {
123  KSharedConfig::Ptr config = KSharedConfig::openConfig(compName + QLatin1String("rc"));
124  config->sync();
125  }
126 }
127 
128 DialogPrivate::DialogPrivate(Dialog *parent)
129  : KCMultiDialogPrivate(parent)
130  , staticlistview(true)
131  , firstshow(true)
132  , pluginStateDirty(0)
133 {
134 }
135 
136 QSet<KCModuleInfo> DialogPrivate::instanceServices()
137 {
138  // qDebug() ;
140  registeredComponents.append(componentName);
141  // qDebug() << "calling KServiceGroup::childGroup( " << componentName << " )";
142  KServiceGroup::Ptr service = KServiceGroup::childGroup(componentName);
143 
144  QSet<KCModuleInfo> ret;
145 
146  if (service && service->isValid()) {
147  // qDebug() << "call was successful";
148  const KServiceGroup::List list = service->entries();
149  for (KServiceGroup::List::ConstIterator it = list.begin(); it != list.end(); ++it) {
150  KSycocaEntry::Ptr p = (*it);
151  if (p->isType(KST_KService)) {
152  // qDebug() << "found service";
153  const KService::Ptr service(static_cast<KService *>(p.data()));
154  ret << KCModuleInfo(service);
155  } else {
156  qCWarning(KCMUTILS_LOG) << "KServiceGroup::childGroup returned"
157  " something else than a KService";
158  }
159  }
160  }
161 
162  return ret;
163 }
164 
165 QSet<KCModuleInfo> DialogPrivate::parentComponentsServices(const QStringList &kcdparents)
166 {
167  registeredComponents += kcdparents;
168  QString constraint = kcdparents.join(QLatin1String("' in [X-KDE-ParentComponents]) or ('"));
169  constraint = QStringLiteral("('") + constraint + QStringLiteral("' in [X-KDE-ParentComponents])");
170 
171  // qDebug() << "constraint = " << constraint;
172  const QList<KService::Ptr> services = KServiceTypeTrader::self()->query(QStringLiteral("KCModule"), constraint);
173  QSet<KCModuleInfo> ret;
174  ret.reserve(services.count());
175  for (const KService::Ptr &service : services) {
176  ret << KCModuleInfo(service);
177  }
178  return ret;
179 }
180 
181 bool DialogPrivate::isPluginForKCMEnabled(const KCModuleInfo *moduleinfo, KPluginInfo &pinfo) const
182 {
183  // if the user of this class requested to hide disabled modules
184  // we check whether it should be enabled or not
185  bool enabled = true;
186  // qDebug() << "check whether the '" << moduleinfo->moduleName() << "' KCM should be shown";
187  // for all parent components
188  const QStringList parentComponents = moduleinfo->property(QStringLiteral("X-KDE-ParentComponents")).toStringList();
189  for (QStringList::ConstIterator pcit = parentComponents.begin(); pcit != parentComponents.end(); ++pcit) {
190  // if the parentComponent is not registered ignore it
191  if (!registeredComponents.contains(*pcit)) {
192  continue;
193  }
194 
195  // we check if the parent component is a plugin
196  // if not the KCModule must be enabled
197  enabled = true;
198  if (pinfo.pluginName() == *pcit) {
199  // it is a plugin: we check whether the plugin is enabled
200  pinfo.load();
201  enabled = pinfo.isPluginEnabled();
202  // qDebug() << "parent " << *pcit << " is " << (enabled ? "enabled" : "disabled");
203  }
204  // if it is enabled we're done for this KCModuleInfo
205  if (enabled) {
206  return true;
207  }
208  }
209  return enabled;
210 }
211 
212 bool DialogPrivate::isPluginImmutable(const KPluginInfo &pinfo) const
213 {
214  return pinfo.property(QStringLiteral("X-KDE-PluginInfo-Immutable")).toBool();
215 }
216 
217 KPageWidgetItem *DialogPrivate::createPageItem(KPageWidgetItem *parentItem, const QString &name, const QString &comment, const QString &iconName, int weight)
218 {
219  Q_Q(Dialog);
220  QWidget *page = new QWidget(q);
221 
222  QCheckBox *checkBox = new QCheckBox(i18n("Enable component"), page);
223  QLabel *iconLabel = new QLabel(page);
224  QLabel *commentLabel = new QLabel(comment, page);
225  commentLabel->setTextFormat(Qt::RichText);
226  QVBoxLayout *layout = new QVBoxLayout(page);
227  layout->addWidget(checkBox);
228  layout->addWidget(iconLabel);
229  layout->addWidget(commentLabel);
230  layout->addStretch();
231 
232  KPageWidgetItem *item = new KPageWidgetItem(page, name);
233  item->setIcon(QIcon::fromTheme(iconName));
234  iconLabel->setPixmap(item->icon().pixmap(128, 128));
235  item->setProperty("_k_weight", weight);
236  checkBoxForItem.insert(item, checkBox);
237 
238  const KPageWidgetModel *model = qobject_cast<const KPageWidgetModel *>(q->pageWidget()->model());
239  Q_ASSERT(model);
240 
241  if (parentItem) {
242  const QModelIndex parentIndex = model->index(parentItem);
243  const int siblingCount = model->rowCount(parentIndex);
244  int row = 0;
245  for (; row < siblingCount; ++row) {
246  KPageWidgetItem *siblingItem = model->item(model->index(row, 0, parentIndex));
247  if (siblingItem->property("_k_weight").toInt() > weight) {
248  // the item we found is heavier than the new module
249  q->insertPage(siblingItem, item);
250  break;
251  }
252  }
253  if (row == siblingCount) {
254  // the new module is either the first or the heaviest item
255  q->addSubPage(parentItem, item);
256  }
257  } else {
258  const int siblingCount = model->rowCount();
259  int row = 0;
260  for (; row < siblingCount; ++row) {
261  KPageWidgetItem *siblingItem = model->item(model->index(row, 0));
262  if (siblingItem->property("_k_weight").toInt() > weight) {
263  // the item we found is heavier than the new module
264  q->insertPage(siblingItem, item);
265  break;
266  }
267  }
268  if (row == siblingCount) {
269  // the new module is either the first or the heaviest item
270  q->addPage(item);
271  }
272  }
273 
274  return (item);
275 }
276 
277 void DialogPrivate::parseGroupFile(const QString &filename)
278 {
279  KConfig file(filename, KConfig::SimpleConfig);
280  const QStringList groups = file.groupList();
281  for (const QString &group : groups) {
282  if (group.isEmpty()) {
283  continue;
284  }
285  KConfigGroup conf(&file, group);
286 
287  const QString parentId = conf.readEntry("Parent");
288  KPageWidgetItem *parentItem = pageItemForGroupId.value(parentId);
289  KPageWidgetItem *item =
290  createPageItem(parentItem, conf.readEntry("Name"), conf.readEntry("Comment"), conf.readEntry("Icon"), conf.readEntry("Weight", 100));
291  pageItemForGroupId.insert(group, item);
292  }
293 }
294 
295 void DialogPrivate::createDialogFromServices()
296 {
297  Q_Q(Dialog);
298  // read .setdlg files (eg: share/kapp/kapp.setdlg)
299  const QString setdlgpath = QStandardPaths::locate(QStandardPaths::AppDataLocation /*includes appname, too*/,
300  QCoreApplication::instance()->applicationName() + QStringLiteral(".setdlg"));
301  if (!setdlgpath.isEmpty()) {
302  parseGroupFile(setdlgpath);
303  }
304 
306  QMap<QString /*fileName*/, QString /*fullPath*/> fileMap;
307  for (const QString &dir : dirs) {
308  const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.setdlg"));
309  for (const QString &file : fileNames) {
310  if (!fileMap.contains(file)) {
311  fileMap.insert(file, dir + QLatin1Char('/') + file);
312  }
313  }
314  }
315  for (auto it = fileMap.constBegin(); it != fileMap.constEnd(); ++it) {
316  parseGroupFile(it.value());
317  }
318 
319  // qDebug() << kcmInfos.count();
320  for (const KCModuleInfo &info : std::as_const(kcmInfos)) {
321  const QStringList parentComponents = info.property(QStringLiteral("X-KDE-ParentComponents")).toStringList();
322  bool blacklisted = false;
323  for (const QString &parentComponent : parentComponents) {
324  if (componentBlacklist.contains(parentComponent)) {
325  blacklisted = true;
326  break;
327  }
328  }
329  if (blacklisted) {
330  continue;
331  }
332  const QString parentId = info.property(QStringLiteral("X-KDE-CfgDlgHierarchy")).toString();
333  KPageWidgetItem *parent = pageItemForGroupId.value(parentId);
334  if (!parent) {
335  // dummy kcm
336  bool foundPlugin = false;
337  for (const KPluginInfo &pinfo : std::as_const(plugininfos)) {
338  if (pinfo.libraryPath() == info.library()) {
339  if (pinfo.kcmServices().isEmpty()) {
340  // FIXME get weight from service or plugin info
341  const int weight = 1000;
342  KPageWidgetItem *item = createPageItem(nullptr, pinfo.name(), pinfo.comment(), pinfo.icon(), weight);
343  connectItemCheckBox(item, pinfo, pinfo.isPluginEnabled());
344  foundPlugin = true;
345  break;
346  }
347  }
348  }
349  if (foundPlugin) {
350  continue;
351  }
352  }
353  KPageWidgetItem *item = q->addModule(info, parent, arguments);
354  // qDebug() << "added KCM '" << info.moduleName() << "'";
355  for (KPluginInfo pinfo : std::as_const(plugininfos)) {
356  // qDebug() << pinfo.pluginName();
357  if (pinfo.kcmServices().contains(info.service())) {
358  const bool isEnabled = isPluginForKCMEnabled(&info, pinfo);
359  // qDebug() << "correct KPluginInfo for this KCM";
360  // this KCM belongs to a plugin
361  if (parent && pinfo.kcmServices().count() >= 1) {
362  item->setEnabled(isEnabled);
363  const KPluginInfo &plugin = pluginForItem.value(parent);
364  if (plugin.isValid()) {
365  if (plugin != pinfo) {
366  qCCritical(KCMUTILS_LOG) << "A group contains more than one plugin: '" << plugin.pluginName() << "' and '" << pinfo.pluginName()
367  << "'. Now it won't be possible to enable/disable the plugin.";
368  parent->setCheckable(false);
369  q->disconnect(parent, SIGNAL(toggled(bool)), q, SLOT(_k_updateEnabledState(bool)));
370  }
371  // else everything is fine
372  } else {
373  connectItemCheckBox(parent, pinfo, isEnabled);
374  }
375  } else {
376  pluginForItem.insert(item, pinfo);
377  item->setCheckable(!isPluginImmutable(pinfo));
378  item->setChecked(isEnabled);
379  q->connect(item, SIGNAL(toggled(bool)), q, SLOT(_k_updateEnabledState(bool)));
380  }
381  break;
382  }
383  }
384  }
385  // now that the KCMs are in, check for empty groups and remove them again
386  {
387  const KPageWidgetModel *model = qobject_cast<const KPageWidgetModel *>(q->pageWidget()->model());
388  const QHash<QString, KPageWidgetItem *>::ConstIterator end = pageItemForGroupId.constEnd();
390  for (; it != end; ++it) {
391  const QModelIndex index = model->index(it.value());
392  KPluginInfo pinfo;
393  for (const KPluginInfo &p : std::as_const(plugininfos)) {
394  if (p.name() == it.key()) {
395  pinfo = p;
396  break;
397  }
398  }
399  bool allowEmpty = false;
400  if (pinfo.isValid()) {
401  allowEmpty = pinfo.property(QStringLiteral("X-KDE-PluginInfo-AllowEmptySettings")).toBool();
402  }
403 
404  if (model->rowCount(index) == 0) {
405  // no children, and it's not allowed => remove this item
406  if (!allowEmpty) {
407  q->removePage(it.value());
408  } else {
409  connectItemCheckBox(it.value(), pinfo, pinfo.isPluginEnabled());
410  }
411  }
412  }
413  }
414 
415  // TODO: Don't show the reset button until the issue with the
416  // KPluginSelector::load() method is solved.
417  // Problem:
418  // KCMultiDialog::show() call KCModule::load() to reset all KCMs
419  // (KPluginSelector::load() resets all plugin selections and all plugin
420  // KCMs).
421  // The reset button calls KCModule::load(), too but in this case we want the
422  // KPluginSelector to only reset the current visible plugin KCM and not
423  // touch the plugin selections.
424  // I have no idea how to check that in KPluginSelector::load()...
425  // q->showButton(KDialog::User1, true);
426 
427  QObject::connect(q, qOverload<>(&KCMultiDialog::configCommitted), q, [this]() {
428  updateConfiguration();
429  });
430 
431  QObject::connect(q, qOverload<const QByteArray &>(&KCMultiDialog::configCommitted), q, [](const QByteArray &componentName) {
432  KSharedConfig::Ptr config = KSharedConfig::openConfig(QString::fromLatin1(componentName) + QLatin1String("rc"));
433  config->reparseConfiguration();
434  });
435 }
436 
437 void DialogPrivate::connectItemCheckBox(KPageWidgetItem *item, const KPluginInfo &pinfo, bool isEnabled)
438 {
439  Q_Q(Dialog);
440  QCheckBox *checkBox = checkBoxForItem.value(item);
441  Q_ASSERT(checkBox);
442  pluginForItem.insert(item, pinfo);
443  item->setCheckable(!isPluginImmutable(pinfo));
444  item->setChecked(isEnabled);
445  checkBox->setVisible(!isPluginImmutable(pinfo));
446  checkBox->setChecked(isEnabled);
447  q->connect(item, SIGNAL(toggled(bool)), q, SLOT(_k_updateEnabledState(bool)));
448  q->connect(item, &KPageWidgetItem::toggled, checkBox, &QAbstractButton::setChecked);
449  q->connect(checkBox, &QAbstractButton::clicked, item, &KPageWidgetItem::setChecked);
450 }
451 
452 void DialogPrivate::updateConfiguration()
453 {
454  Q_Q(Dialog);
455  const QHash<KPageWidgetItem *, KPluginInfo>::Iterator endIt = pluginForItem.end();
457  for (; it != endIt; ++it) {
458  KPageWidgetItem *item = it.key();
459  KPluginInfo pinfo = it.value();
460  pinfo.setPluginEnabled(item->isChecked());
461  pinfo.save();
462  }
463 
464  if (pluginStateDirty > 0) {
465  Q_EMIT q->pluginSelectionChanged();
466  pluginStateDirty = 0;
467  }
468 }
469 
470 void DialogPrivate::_k_clientChanged()
471 {
472  if (pluginStateDirty > 0) {
473  Q_Q(Dialog);
474  q->buttonBox()->button(QDialogButtonBox::Apply)->setEnabled(true);
475  } else {
476  KCMultiDialogPrivate::_k_clientChanged();
477  }
478 }
479 
480 void DialogPrivate::_k_updateEnabledState(bool enabled)
481 {
482  Q_Q(Dialog);
483  KPageWidgetItem *item = qobject_cast<KPageWidgetItem *>(q->sender());
484  if (!item) {
485  qCWarning(KCMUTILS_LOG) << "invalid sender";
486  return;
487  }
488 
489  // iterate over all child KPageWidgetItem objects and check whether they need to be enabled/disabled
490  const KPageWidgetModel *model = qobject_cast<const KPageWidgetModel *>(q->pageWidget()->model());
491  Q_ASSERT(model);
492  QModelIndex index = model->index(item);
493  if (!index.isValid()) {
494  qCWarning(KCMUTILS_LOG) << "could not find item in model";
495  return;
496  }
497 
498  const KPluginInfo &pinfo = pluginForItem.value(item);
499  if (!pinfo.isValid()) {
500  qCWarning(KCMUTILS_LOG) << "could not find KPluginInfo in item";
501  return;
502  }
503  if (pinfo.isPluginEnabled() != enabled) {
504  ++pluginStateDirty;
505  } else {
506  --pluginStateDirty;
507  }
508  if (pluginStateDirty < 2) {
509  _k_clientChanged();
510  }
511 
512  // qDebug() ;
513 
514  QModelIndex firstborn = model->index(0, 0, index);
515  if (firstborn.isValid()) {
516  // qDebug() << "iterating over children";
517  // change all children
518  index = firstborn;
519  QStack<QModelIndex> stack;
520  while (index.isValid()) {
521  // qDebug() << index;
522  KPageWidgetItem *item = model->item(index);
523  // qDebug() << "item->setEnabled(" << enabled << ')';
524  item->setEnabled(enabled);
525  firstborn = model->index(0, 0, index);
526  if (firstborn.isValid()) {
527  stack.push(index);
528  index = firstborn;
529  } else {
530  index = index.sibling(index.row() + 1, 0);
531  while (!index.isValid() && !stack.isEmpty()) {
532  index = stack.pop();
533  index = index.sibling(index.row() + 1, 0);
534  }
535  }
536  }
537  }
538 }
539 
540 } // namespace
541 
542 #include "moc_dialog.cpp"
543 #endif
RichText
void setComponentBlacklist(const QStringList &blacklist)
Set the blacklisted component list.
Definition: dialog.cpp:69
QList< KPluginInfo > pluginInfos() const
Returns a list of all KPluginInfo objects the dialog uses.
Definition: dialog.cpp:103
const T value(const Key &key) const const
bool isEmpty() const const
void setChecked(bool checked)
QIcon icon() const
void addPluginInfos(const QList< KPluginInfo > &plugininfos)
If you use a Configurable dialog you need to pass KPluginInfo objects that the dialog should configur...
Definition: dialog.cpp:75
virtual int rowCount(const QModelIndex &parent) const const=0
QModelIndex sibling(int row, int column) const const
QString libraryPath() const
int count(const T &value) const const
void setTextFormat(Qt::TextFormat)
QString icon() const
QHash::iterator begin()
void clicked(bool checked)
void reserve(int size)
QIcon fromTheme(const QString &name)
void configCommitted()
Emitted after all KCModules have been told to save their configuration.
void load(const KConfigGroup &config=KConfigGroup())
QList< KService::Ptr > kcmServices() const
void toggled(bool checked)
void setChecked(bool)
void setUpdatesEnabled(bool enable)
void setCheckable(bool checkable)
QString locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
Definition: dialog.h:19
void addStretch(int stretch)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
Dialog(QWidget *parent=nullptr)
Construct a new Preferences Dialog for the application.
Definition: dialog.cpp:37
void setIcon(const QIcon &icon)
virtual void setVisible(bool visible)
QString pluginName() const
QString i18n(const char *text, const TYPE &arg...)
QHash::const_iterator constBegin() const const
KPageWidgetItem * item(const QModelIndex &index) const
bool isEmpty() const const
const Key key(const T &value) const const
QCoreApplication * instance()
int toInt(bool *ok) const const
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
static KServiceTypeTrader * self()
QVariant property(const QString &key) const
QString join(const QString &separator) const const
KSharedConfigPtr config()
void setKCMArguments(const QStringList &arguments)
Sets the argument list that is given to all the KControlModule's when they are created.
Definition: dialog.cpp:63
void setPluginEnabled(bool enabled)
QVariant property(const QString &key) const
bool isValid() const const
static Ptr childGroup(const QString &parent)
bool isValid() const
void setEnabled(bool)
void insert(int i, const T &value)
bool toBool() const const
void setAllowComponentSelection(bool allowSelection)
Tells the dialog whether the entries in the listview are all static or whether it should add checkbox...
Definition: dialog.cpp:53
int row() const const
typedef ConstIterator
bool setProperty(const char *name, const QVariant &value)
void save(KConfigGroup config=KConfigGroup())
QString name() const
void push(const T &t)
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) const const
QString fromLatin1(const char *str, int size)
QModelIndex index(const KPageWidgetItem *item) const
KStandardDirs * dirs()
QStringList locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
QString fileName() const
QList::iterator begin()
QString comment() const
QStringList toStringList() const const
KService::List query(const QString &servicetype, const QString &constraint=QString()) const
A collection of classes to create configuration dialogs that work over component boundaries.
Definition: dialog.cpp:35
QStringList entryList(QDir::Filters filters, QDir::SortFlags sort) const const
A class that provides information about a KCModule.
Definition: kcmoduleinfo.h:36
QList::iterator end()
Generic configuration dialog that works over component boundaries.
Definition: dialog.h:71
void setPixmap(const QPixmap &)
A class that offers a KPageDialog containing arbitrary KControl Modules.
Definition: kcmultidialog.h:28
void showEvent(QShowEvent *) override
Reimplemented to lazy create the dialog on first show.
Definition: dialog.cpp:108
const QList< QKeySequence > & end()
Q_D(Todo)
QHash::iterator end()
QVariant property(const char *name) const const
bool isPluginEnabled() const
bool isChecked() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sun Jun 26 2022 03:51:23 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.