KTextWidgets

kfinddialog.cpp
1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2001 S.R. Haque <srhaque@iee.org>.
4 SPDX-FileCopyrightText: 2002 David Faure <david@mandrakesoft.com>
5
6 SPDX-License-Identifier: LGPL-2.0-only
7*/
8
9#include "kfinddialog.h"
10#include "kfinddialog_p.h"
11
12#include "kfind.h"
13
14#include <QCheckBox>
15#include <QDialogButtonBox>
16#include <QGridLayout>
17#include <QGroupBox>
18#include <QLabel>
19#include <QLineEdit>
20#include <QMenu>
21#include <QPushButton>
22#include <QRegularExpression>
23
24#include <KGuiItem>
25#include <KHistoryComboBox>
26#include <KLazyLocalizedString>
27#include <KLocalizedString>
28#include <KMessageBox>
29
30#include <assert.h>
31
32KFindDialog::KFindDialog(QWidget *parent, long options, const QStringList &findStrings, bool hasSelection, bool replaceDialog)
33 : KFindDialog(*new KFindDialogPrivate(this), parent, options, findStrings, hasSelection, replaceDialog)
34{
35 setWindowTitle(i18n("Find Text"));
36}
37
38KFindDialog::KFindDialog(KFindDialogPrivate &dd, QWidget *parent, long options, const QStringList &findStrings, bool hasSelection, bool replaceDialog)
39 : QDialog(parent)
40 , d_ptr(&dd)
41{
43
44 d->init(replaceDialog, findStrings, hasSelection);
46}
47
49
51{
52 Q_D(const KFindDialog);
53
54 if (!d->findExtension) {
55 d->findExtension = new QWidget(d->findGrp);
56 d->findLayout->addWidget(d->findExtension, 3, 0, 1, 2);
57 }
58
59 return d->findExtension;
60}
61
63{
64 Q_D(const KFindDialog);
65
66 return d->find->historyItems();
67}
68
69void KFindDialogPrivate::init(bool forReplace, const QStringList &_findStrings, bool hasSelection)
70{
71 Q_Q(KFindDialog);
72
73 // Create common parts of dialog.
74 QVBoxLayout *topLayout = new QVBoxLayout(q);
75
76 findGrp = new QGroupBox(i18nc("@title:group", "Find"), q);
77 findLayout = new QGridLayout(findGrp);
78
79 QLabel *findLabel = new QLabel(i18n("&Text to find:"), findGrp);
80 find = new KHistoryComboBox(findGrp);
81 find->setMaxCount(10);
82 find->setDuplicatesEnabled(false);
83 regExp = new QCheckBox(i18n("Regular e&xpression"), findGrp);
84 regExpItem = new QPushButton(i18n("&Edit..."), findGrp);
85 regExpItem->setEnabled(false);
86
87 findLayout->addWidget(findLabel, 0, 0);
88 findLayout->addWidget(find, 1, 0, 1, 2);
89 findLayout->addWidget(regExp, 2, 0);
90 findLayout->addWidget(regExpItem, 2, 1);
91 topLayout->addWidget(findGrp);
92
93 replaceGrp = new QGroupBox(i18n("Replace With"), q);
94 replaceLayout = new QGridLayout(replaceGrp);
95
96 QLabel *replaceLabel = new QLabel(i18n("Replace&ment text:"), replaceGrp);
97 replace = new KHistoryComboBox(replaceGrp);
98 replace->setMaxCount(10);
99 replace->setDuplicatesEnabled(false);
100 backRef = new QCheckBox(i18n("Use p&laceholders"), replaceGrp);
101 backRefItem = new QPushButton(i18n("Insert Place&holder"), replaceGrp);
102 backRefItem->setEnabled(false);
103
104 replaceLayout->addWidget(replaceLabel, 0, 0);
105 replaceLayout->addWidget(replace, 1, 0, 1, 2);
106 replaceLayout->addWidget(backRef, 2, 0);
107 replaceLayout->addWidget(backRefItem, 2, 1);
108 topLayout->addWidget(replaceGrp);
109
110 QGroupBox *optionGrp = new QGroupBox(i18n("Options"), q);
111 QGridLayout *optionsLayout = new QGridLayout(optionGrp);
112
113 caseSensitive = new QCheckBox(i18n("C&ase sensitive"), optionGrp);
114 wholeWordsOnly = new QCheckBox(i18n("&Whole words only"), optionGrp);
115 fromCursor = new QCheckBox(i18n("From c&ursor"), optionGrp);
116 findBackwards = new QCheckBox(i18n("Find &backwards"), optionGrp);
117 selectedText = new QCheckBox(i18n("&Selected text"), optionGrp);
118 q->setHasSelection(hasSelection);
119 // If we have a selection, we make 'find in selection' default
120 // and if we don't, then the option has to be unchecked, obviously.
121 selectedText->setChecked(hasSelection);
122 slotSelectedTextToggled(hasSelection);
123
124 promptOnReplace = new QCheckBox(i18n("&Prompt on replace"), optionGrp);
125 promptOnReplace->setChecked(true);
126
127 optionsLayout->addWidget(caseSensitive, 0, 0);
128 optionsLayout->addWidget(wholeWordsOnly, 1, 0);
129 optionsLayout->addWidget(fromCursor, 2, 0);
130 optionsLayout->addWidget(findBackwards, 0, 1);
131 optionsLayout->addWidget(selectedText, 1, 1);
132 optionsLayout->addWidget(promptOnReplace, 2, 1);
133 topLayout->addWidget(optionGrp);
134
135 buttonBox = new QDialogButtonBox(q);
136 buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Close);
137 q->connect(buttonBox, &QDialogButtonBox::accepted, q, [this]() {
138 slotOk();
139 });
140 q->connect(buttonBox, &QDialogButtonBox::rejected, q, [this]() {
141 slotReject();
142 });
143 topLayout->addWidget(buttonBox);
144
145 // We delay creation of these until needed.
146 patterns = nullptr;
147 placeholders = nullptr;
148
149 // signals and slots connections
150 q->connect(selectedText, &QCheckBox::toggled, q, [this](bool checked) {
151 slotSelectedTextToggled(checked);
152 });
153 q->connect(regExp, &QCheckBox::toggled, regExpItem, &QWidget::setEnabled);
154 q->connect(backRef, &QCheckBox::toggled, backRefItem, &QWidget::setEnabled);
155 q->connect(regExpItem, &QPushButton::clicked, q, [this]() {
156 showPatterns();
157 });
158 q->connect(backRefItem, &QPushButton::clicked, q, [this]() {
159 showPlaceholders();
160 });
161
162 q->connect(find, &KHistoryComboBox::editTextChanged, q, [this](const QString &text) {
163 textSearchChanged(text);
164 });
165
166 q->connect(regExp, &QCheckBox::toggled, q, &KFindDialog::optionsChanged);
167 q->connect(backRef, &QCheckBox::toggled, q, &KFindDialog::optionsChanged);
168 q->connect(caseSensitive, &QCheckBox::toggled, q, &KFindDialog::optionsChanged);
169 q->connect(wholeWordsOnly, &QCheckBox::toggled, q, &KFindDialog::optionsChanged);
170 q->connect(fromCursor, &QCheckBox::toggled, q, &KFindDialog::optionsChanged);
171 q->connect(findBackwards, &QCheckBox::toggled, q, &KFindDialog::optionsChanged);
172 q->connect(selectedText, &QCheckBox::toggled, q, &KFindDialog::optionsChanged);
173 q->connect(promptOnReplace, &QCheckBox::toggled, q, &KFindDialog::optionsChanged);
174
175 // tab order
176 q->setTabOrder(find, regExp);
177 q->setTabOrder(regExp, regExpItem);
178 q->setTabOrder(regExpItem, replace); // findExtension widgets are inserted in showEvent()
179 q->setTabOrder(replace, backRef);
180 q->setTabOrder(backRef, backRefItem);
181 q->setTabOrder(backRefItem, caseSensitive);
182 q->setTabOrder(caseSensitive, wholeWordsOnly);
183 q->setTabOrder(wholeWordsOnly, fromCursor);
184 q->setTabOrder(fromCursor, findBackwards);
185 q->setTabOrder(findBackwards, selectedText);
186 q->setTabOrder(selectedText, promptOnReplace);
187
188 // buddies
189 findLabel->setBuddy(find);
190 replaceLabel->setBuddy(replace);
191
192 if (!forReplace) {
193 promptOnReplace->hide();
194 replaceGrp->hide();
195 }
196
197 findStrings = _findStrings;
198 find->setFocus();
199 QPushButton *buttonOk = buttonBox->button(QDialogButtonBox::Ok);
200 buttonOk->setEnabled(!q->pattern().isEmpty());
201
202 if (forReplace) {
203 KGuiItem::assign(buttonOk,
204 KGuiItem(i18n("&Replace"),
205 QString(),
206 i18n("Start replace"),
207 i18n("<qt>If you press the <b>Replace</b> button, the text you entered "
208 "above is searched for within the document and any occurrence is "
209 "replaced with the replacement text.</qt>")));
210 } else {
211 KGuiItem::assign(buttonOk,
212 KGuiItem(i18n("&Find"),
213 QStringLiteral("edit-find"),
214 i18n("Start searching"),
215 i18n("<qt>If you press the <b>Find</b> button, the text you entered "
216 "above is searched for within the document.</qt>")));
217 }
218
219 // QWhatsthis texts
220 find->setWhatsThis(i18n("Enter a pattern to search for, or select a previous pattern from the list."));
221 regExp->setWhatsThis(i18n("If enabled, search for a regular expression."));
222 regExpItem->setWhatsThis(i18n("Click here to edit your regular expression using a graphical editor."));
223 replace->setWhatsThis(i18n("Enter a replacement string, or select a previous one from the list."));
224 backRef->setWhatsThis(
225 i18n("<qt>If enabled, any occurrence of <code><b>\\N</b></code>, where "
226 "<code><b>N</b></code> is an integer number, will be replaced with "
227 "the corresponding capture (\"parenthesized substring\") from the "
228 "pattern.<p>To include (a literal <code><b>\\N</b></code> in your "
229 "replacement, put an extra backslash in front of it, like "
230 "<code><b>\\\\N</b></code>.</p></qt>"));
231 backRefItem->setWhatsThis(i18n("Click for a menu of available captures."));
232 wholeWordsOnly->setWhatsThis(i18n("Require word boundaries in both ends of a match to succeed."));
233 fromCursor->setWhatsThis(i18n("Start searching at the current cursor location rather than at the top."));
234 selectedText->setWhatsThis(i18n("Only search within the current selection."));
235 caseSensitive->setWhatsThis(i18n("Perform a case sensitive search: entering the pattern 'Joe' will not match 'joe' or 'JOE', only 'Joe'."));
236 findBackwards->setWhatsThis(i18n("Search backwards."));
237 promptOnReplace->setWhatsThis(i18n("Ask before replacing each match found."));
238
239 textSearchChanged(find->lineEdit()->text());
240}
241
242void KFindDialogPrivate::textSearchChanged(const QString &text)
243{
244 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty());
245}
246
247void KFindDialog::showEvent(QShowEvent *e)
248{
250
251 if (!d->initialShowDone) {
252 d->initialShowDone = true; // only once
253 // qDebug() << "showEvent\n";
254 if (!d->findStrings.isEmpty()) {
255 setFindHistory(d->findStrings);
256 }
257 d->findStrings = QStringList();
258 if (!d->pattern.isEmpty()) {
259 d->find->lineEdit()->setText(d->pattern);
260 d->find->lineEdit()->selectAll();
261 d->pattern.clear();
262 }
263 // maintain a user-friendly tab order
264 if (d->findExtension) {
265 QWidget *prev = d->regExpItem;
266 const auto children = d->findExtension->findChildren<QWidget *>();
267 for (QWidget *child : children) {
268 setTabOrder(prev, child);
269 prev = child;
270 }
271 setTabOrder(prev, d->replace);
272 }
273 }
274 d->find->setFocus();
276}
277
279{
280 Q_D(const KFindDialog);
281
282 long options = 0;
283
284 if (d->caseSensitive->isChecked()) {
286 }
287 if (d->wholeWordsOnly->isChecked()) {
289 }
290 if (d->fromCursor->isChecked()) {
292 }
293 if (d->findBackwards->isChecked()) {
295 }
296 if (d->selectedText->isChecked()) {
298 }
299 if (d->regExp->isChecked()) {
301 }
302 return options;
303}
304
306{
307 Q_D(const KFindDialog);
308
309 return d->find->currentText();
310}
311
313{
315
316 d->find->lineEdit()->setText(pattern);
317 d->find->lineEdit()->selectAll();
318 d->pattern = pattern;
319 // qDebug() << "setPattern " << pattern;
320}
321
323{
325
326 if (!strings.isEmpty()) {
327 d->find->setHistoryItems(strings, true);
328 d->find->lineEdit()->setText(strings.first());
329 d->find->lineEdit()->selectAll();
330 } else {
331 d->find->clearHistory();
332 }
333}
334
335void KFindDialog::setHasSelection(bool hasSelection)
336{
338
339 if (hasSelection) {
340 d->enabled |= KFind::SelectedText;
341 } else {
342 d->enabled &= ~KFind::SelectedText;
343 }
344 d->selectedText->setEnabled(hasSelection);
345 if (!hasSelection) {
346 d->selectedText->setChecked(false);
347 d->slotSelectedTextToggled(hasSelection);
348 }
349}
350
351void KFindDialogPrivate::slotSelectedTextToggled(bool selec)
352{
353 // From cursor doesn't make sense if we have a selection
354 fromCursor->setEnabled(!selec && (enabled & KFind::FromCursor));
355 if (selec) { // uncheck if disabled
356 fromCursor->setChecked(false);
357 }
358}
359
360void KFindDialog::setHasCursor(bool hasCursor)
361{
363
364 if (hasCursor) {
365 d->enabled |= KFind::FromCursor;
366 } else {
367 d->enabled &= ~KFind::FromCursor;
368 }
369 d->fromCursor->setEnabled(hasCursor);
370 d->fromCursor->setChecked(hasCursor && (options() & KFind::FromCursor));
371}
372
374{
376
377 // ########## Shouldn't this hide the checkbox instead?
378 if (supports) {
379 d->enabled |= KFind::FindBackwards;
380 } else {
381 d->enabled &= ~KFind::FindBackwards;
382 }
383 d->findBackwards->setEnabled(supports);
384 d->findBackwards->setChecked(supports && (options() & KFind::FindBackwards));
385}
386
388{
390
391 // ########## This should hide the checkbox instead
392 if (supports) {
393 d->enabled |= KFind::CaseSensitive;
394 } else {
395 d->enabled &= ~KFind::CaseSensitive;
396 }
397 d->caseSensitive->setEnabled(supports);
398 d->caseSensitive->setChecked(supports && (options() & KFind::CaseSensitive));
399}
400
402{
404
405 // ########## This should hide the checkbox instead
406 if (supports) {
407 d->enabled |= KFind::WholeWordsOnly;
408 } else {
409 d->enabled &= ~KFind::WholeWordsOnly;
410 }
411 d->wholeWordsOnly->setEnabled(supports);
412 d->wholeWordsOnly->setChecked(supports && (options() & KFind::WholeWordsOnly));
413}
414
416{
418
419 if (supports) {
420 d->enabled |= KFind::RegularExpression;
421 } else {
422 d->enabled &= ~KFind::RegularExpression;
423 }
424 d->regExp->setEnabled(supports);
425 d->regExp->setChecked(supports && (options() & KFind::RegularExpression));
426 if (!supports) {
427 d->regExpItem->hide();
428 d->regExp->hide();
429 } else {
430 d->regExpItem->show();
431 d->regExp->show();
432 }
433}
434
435void KFindDialog::setOptions(long options)
436{
438
439 d->caseSensitive->setChecked((d->enabled & KFind::CaseSensitive) && (options & KFind::CaseSensitive));
440 d->wholeWordsOnly->setChecked((d->enabled & KFind::WholeWordsOnly) && (options & KFind::WholeWordsOnly));
441 d->fromCursor->setChecked((d->enabled & KFind::FromCursor) && (options & KFind::FromCursor));
442 d->findBackwards->setChecked((d->enabled & KFind::FindBackwards) && (options & KFind::FindBackwards));
443 d->selectedText->setChecked((d->enabled & KFind::SelectedText) && (options & KFind::SelectedText));
444 d->regExp->setChecked((d->enabled & KFind::RegularExpression) && (options & KFind::RegularExpression));
445}
446
447// Create a popup menu with a list of regular expression terms, to help the user
448// compose a regular expression search pattern.
449void KFindDialogPrivate::showPatterns()
450{
451 Q_Q(KFindDialog);
452
453 typedef struct {
454 const KLazyLocalizedString description;
455 const char *regExp;
456 int cursorAdjustment;
457 } Term;
458 static const Term items[] = {
459 {kli18n("Any Character"), ".", 0},
460 {kli18n("Start of Line"), "^", 0},
461 {kli18n("End of Line"), "$", 0},
462 {kli18n("Set of Characters"), "[]", -1},
463 {kli18n("Repeats, Zero or More Times"), "*", 0},
464 {kli18n("Repeats, One or More Times"), "+", 0},
465 {kli18n("Optional"), "?", 0},
466 {kli18n("Escape"), "\\", 0},
467 {kli18n("TAB"), "\\t", 0},
468 {kli18n("Newline"), "\\n", 0},
469 {kli18n("Carriage Return"), "\\r", 0},
470 {kli18n("White Space"), "\\s", 0},
471 {kli18n("Digit"), "\\d", 0},
472 };
473
474 class RegExpAction : public QAction
475 {
476 public:
477 RegExpAction(QObject *parent, const QString &text, const QString &regExp, int cursor)
478 : QAction(text, parent)
479 , mText(text)
480 , mRegExp(regExp)
481 , mCursor(cursor)
482 {
483 }
484
485 QString text() const
486 {
487 return mText;
488 }
489 QString regExp() const
490 {
491 return mRegExp;
492 }
493 int cursor() const
494 {
495 return mCursor;
496 }
497
498 private:
499 QString mText;
500 QString mRegExp;
501 int mCursor;
502 };
503
504 // Populate the popup menu.
505 if (!patterns) {
506 patterns = new QMenu(q);
507 for (const Term &item : items) {
508 patterns->addAction(new RegExpAction(patterns, item.description.toString(), QLatin1String(item.regExp), item.cursorAdjustment));
509 }
510 }
511
512 // Insert the selection into the edit control.
513 QAction *action = patterns->exec(regExpItem->mapToGlobal(regExpItem->rect().bottomLeft()));
514 if (action) {
515 RegExpAction *regExpAction = static_cast<RegExpAction *>(action);
516 if (regExpAction) {
517 QLineEdit *editor = find->lineEdit();
518
519 editor->insert(regExpAction->regExp());
520 editor->setCursorPosition(editor->cursorPosition() + regExpAction->cursor());
521 }
522 }
523}
524
525class PlaceHolderAction : public QAction
526{
527public:
528 PlaceHolderAction(QObject *parent, const QString &text, int id)
529 : QAction(text, parent)
530 , mText(text)
531 , mId(id)
532 {
533 }
534
535 QString text() const
536 {
537 return mText;
538 }
539 int id() const
540 {
541 return mId;
542 }
543
544private:
545 QString mText;
546 int mId;
547};
548
549// Create a popup menu with a list of backreference terms, to help the user
550// compose a regular expression replacement pattern.
551void KFindDialogPrivate::showPlaceholders()
552{
553 Q_Q(KFindDialog);
554
555 // Populate the popup menu.
556 if (!placeholders) {
557 placeholders = new QMenu(q);
558 q->connect(placeholders, &QMenu::aboutToShow, q, [this]() {
559 slotPlaceholdersAboutToShow();
560 });
561 }
562
563 // Insert the selection into the edit control.
564 QAction *action = placeholders->exec(backRefItem->mapToGlobal(backRefItem->rect().bottomLeft()));
565 if (action) {
566 PlaceHolderAction *placeHolderAction = static_cast<PlaceHolderAction *>(action);
567 if (placeHolderAction) {
568 QLineEdit *editor = replace->lineEdit();
569 editor->insert(QStringLiteral("\\%1").arg(placeHolderAction->id()));
570 }
571 }
572}
573
574void KFindDialogPrivate::slotPlaceholdersAboutToShow()
575{
576 Q_Q(KFindDialog);
577
578 placeholders->clear();
579 placeholders->addAction(new PlaceHolderAction(placeholders, i18n("Complete Match"), 0));
580
582 for (int i = 1; i <= n; ++i) {
583 placeholders->addAction(new PlaceHolderAction(placeholders, i18n("Captured Text (%1)", i), i));
584 }
585}
586
587void KFindDialogPrivate::slotOk()
588{
589 Q_Q(KFindDialog);
590
591 // Nothing to find?
592 if (q->pattern().isEmpty()) {
593 KMessageBox::error(q, i18n("You must enter some text to search for."));
594 return;
595 }
596
597 if (regExp->isChecked()) {
598 // Check for a valid regular expression.
600 KMessageBox::error(q, i18n("Invalid PCRE pattern syntax."));
601 return;
602 }
603 }
604
605 find->addToHistory(q->pattern());
606
607 if (q->windowModality() != Qt::NonModal) {
608 q->accept();
609 }
610 Q_EMIT q->okClicked();
611}
612
613void KFindDialogPrivate::slotReject()
614{
615 Q_Q(KFindDialog);
616
617 Q_EMIT q->cancelClicked();
618 q->reject();
619}
620
621#include "moc_kfinddialog.cpp"
A generic "find" dialog.
Definition kfinddialog.h:66
void optionsChanged()
This signal is sent whenever one of the option checkboxes is toggled.
void setSupportsBackwardsFind(bool supports)
Enable/disable the 'Find backwards' option, depending on whether the application supports it.
KFindDialog(QWidget *parent=nullptr, long options=0, const QStringList &findStrings=QStringList(), bool hasSelection=false, bool replaceDialog=false)
Construct a modal find dialog.
void setHasCursor(bool hasCursor)
Hide/show the 'from cursor' option, depending on whether the application implements a cursor.
void setSupportsWholeWordsFind(bool supports)
Enable/disable the 'Whole words only' option, depending on whether the application supports it.
void setSupportsCaseSensitiveFind(bool supports)
Enable/disable the 'Case sensitive' option, depending on whether the application supports it.
void setFindHistory(const QStringList &history)
Provide the list of strings to be displayed as the history of find strings.
QStringList findHistory() const
Returns the list of history items.
QString pattern() const
Returns the pattern to find.
void setSupportsRegularExpressionFind(bool supports)
Enable/disable the 'Regular expression' option, depending on whether the application supports it.
long options() const
Returns the state of the options.
void setHasSelection(bool hasSelection)
Enable/disable the 'search in selection' option, depending on whether there actually is a selection.
~KFindDialog() override
Destructor.
void setOptions(long options)
Set the options which are checked.
void setPattern(const QString &pattern)
Sets the pattern to find.
QWidget * findExtension() const
Returns an empty widget which the user may fill with additional UI elements as required.
A generic implementation of the "find" function.
Definition kfind.h:94
@ CaseSensitive
Consider case when matching.
Definition kfind.h:105
@ SelectedText
Only search selected area.
Definition kfind.h:104
@ RegularExpression
Interpret the pattern as a regular expression.
Definition kfind.h:107
@ FromCursor
Start from current cursor position.
Definition kfind.h:103
@ FindBackwards
Go backwards.
Definition kfind.h:106
@ WholeWordsOnly
Match whole words only.
Definition kfind.h:102
static void assign(QPushButton *button, const KGuiItem &item)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
const QList< QKeySequence > & find()
const QList< QKeySequence > & replace()
void clicked(bool checked)
void toggled(bool checked)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void editTextChanged(const QString &text)
virtual void showEvent(QShowEvent *event) override
void addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment)
void setBuddy(QWidget *buddy)
void setCursorPosition(int)
void insert(const QString &newText)
T & first()
bool isEmpty() const const
void aboutToShow()
const QObjectList & children() const const
QList< T > findChildren(Qt::FindChildOptions options) const const
QObject * parent() const const
int captureCount() const const
bool isValid() const const
bool isEmpty() const const
NonModal
QWidget(QWidget *parent, Qt::WindowFlags f)
void setEnabled(bool)
void setTabOrder(QWidget *first, QWidget *second)
void setWindowTitle(const QString &)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:07 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.