1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qinputdialog.h"
5
6#include "qapplication.h"
7#include "qcombobox.h"
8#include "qdialogbuttonbox.h"
9#include "qlabel.h"
10#include "qlayout.h"
11#include "qlineedit.h"
12#include "qplaintextedit.h"
13#include "qlistview.h"
14#include "qpushbutton.h"
15#include "qspinbox.h"
16#include "qstackedlayout.h"
17#include "qvalidator.h"
18#include "qevent.h"
19#include "qdialog_p.h"
20
21#include <QtCore/qpointer.h>
22
23QT_USE_NAMESPACE
24
25enum CandidateSignal {
26 TextValueSelectedSignal,
27 IntValueSelectedSignal,
28 DoubleValueSelectedSignal,
29
30 NumCandidateSignals
31};
32
33static const char *candidateSignal(int which)
34{
35 switch (CandidateSignal(which)) {
36 case TextValueSelectedSignal: return SIGNAL(textValueSelected(QString));
37 case IntValueSelectedSignal: return SIGNAL(intValueSelected(int));
38 case DoubleValueSelectedSignal: return SIGNAL(doubleValueSelected(double));
39
40 case NumCandidateSignals:
41 break;
42 };
43 Q_UNREACHABLE_RETURN(nullptr);
44}
45
46static const char *signalForMember(const char *member)
47{
48 QByteArray normalizedMember(QMetaObject::normalizedSignature(method: member));
49
50 for (int i = 0; i < NumCandidateSignals; ++i)
51 if (QMetaObject::checkConnectArgs(signal: candidateSignal(which: i), method: normalizedMember))
52 return candidateSignal(which: i);
53
54 // otherwise, use fit-all accepted signal:
55 return SIGNAL(accepted());
56}
57
58QT_BEGIN_NAMESPACE
59
60/*
61 These internal classes add extra validation to QSpinBox and QDoubleSpinBox by emitting
62 textChanged(bool) after events that may potentially change the visible text. Return or
63 Enter key presses are not propagated if the visible text is invalid. Instead, the visible
64 text is modified to the last valid value.
65*/
66class QInputDialogSpinBox : public QSpinBox
67{
68 Q_OBJECT
69
70public:
71 QInputDialogSpinBox(QWidget *parent)
72 : QSpinBox(parent) {
73 connect(sender: lineEdit(), signal: &QLineEdit::textChanged,
74 context: this, slot: &QInputDialogSpinBox::notifyTextChanged);
75 connect(sender: this, signal: &QInputDialogSpinBox::editingFinished,
76 context: this, slot: &QInputDialogSpinBox::notifyTextChanged);
77 }
78
79signals:
80 void textChanged(bool);
81
82private slots:
83 void notifyTextChanged() { emit textChanged(hasAcceptableInput()); }
84
85private:
86 void keyPressEvent(QKeyEvent *event) override {
87 if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && !hasAcceptableInput()) {
88 setProperty(name: "value", value: property(name: "value"));
89 } else {
90 QSpinBox::keyPressEvent(event);
91 }
92 notifyTextChanged();
93 }
94
95 void mousePressEvent(QMouseEvent *event) override {
96 QSpinBox::mousePressEvent(event);
97 notifyTextChanged();
98 }
99};
100
101class QInputDialogDoubleSpinBox : public QDoubleSpinBox
102{
103 Q_OBJECT
104
105public:
106 QInputDialogDoubleSpinBox(QWidget *parent = nullptr)
107 : QDoubleSpinBox(parent) {
108 connect(sender: lineEdit(), signal: &QLineEdit::textChanged,
109 context: this, slot: &QInputDialogDoubleSpinBox::notifyTextChanged);
110 connect(sender: this, signal: &QInputDialogDoubleSpinBox::editingFinished,
111 context: this, slot: &QInputDialogDoubleSpinBox::notifyTextChanged);
112 }
113
114signals:
115 void textChanged(bool);
116
117private slots:
118 void notifyTextChanged() { emit textChanged(hasAcceptableInput()); }
119
120private:
121 void keyPressEvent(QKeyEvent *event) override {
122 if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && !hasAcceptableInput()) {
123 setProperty(name: "value", value: property(name: "value"));
124 } else {
125 QDoubleSpinBox::keyPressEvent(event);
126 }
127 notifyTextChanged();
128 }
129
130 void mousePressEvent(QMouseEvent *event) override {
131 QDoubleSpinBox::mousePressEvent(event);
132 notifyTextChanged();
133 }
134};
135
136class QInputDialogListView : public QListView
137{
138public:
139 QInputDialogListView(QWidget *parent = nullptr) : QListView(parent) {}
140 QVariant inputMethodQuery(Qt::InputMethodQuery query) const override
141 {
142 if (query == Qt::ImEnabled)
143 return false;
144 return QListView::inputMethodQuery(query);
145 }
146};
147
148class QInputDialogPrivate : public QDialogPrivate
149{
150 Q_DECLARE_PUBLIC(QInputDialog)
151
152public:
153 QInputDialogPrivate();
154
155 void ensureLayout();
156 void ensureLineEdit();
157 void ensurePlainTextEdit();
158 void ensureComboBox();
159 void ensureListView();
160 void ensureIntSpinBox();
161 void ensureDoubleSpinBox();
162 void ensureEnabledConnection(QAbstractSpinBox *spinBox);
163 void setInputWidget(QWidget *widget);
164 void chooseRightTextInputWidget();
165 void setComboBoxText(const QString &text);
166 void setListViewText(const QString &text);
167 QString listViewText() const;
168 void ensureLayout() const { const_cast<QInputDialogPrivate *>(this)->ensureLayout(); }
169 bool useComboBoxOrListView() const { return comboBox && comboBox->count() > 0; }
170 void textChanged(const QString &text);
171 void plainTextEditTextChanged();
172 void currentRowChanged(const QModelIndex &newIndex, const QModelIndex &oldIndex);
173
174 mutable QLabel *label;
175 mutable QDialogButtonBox *buttonBox;
176 mutable QLineEdit *lineEdit;
177 mutable QPlainTextEdit *plainTextEdit;
178 mutable QSpinBox *intSpinBox;
179 mutable QDoubleSpinBox *doubleSpinBox;
180 mutable QComboBox *comboBox;
181 mutable QInputDialogListView *listView;
182 mutable QWidget *inputWidget;
183 mutable QVBoxLayout *mainLayout;
184 QInputDialog::InputDialogOptions opts;
185 QString textValue;
186 QPointer<QObject> receiverToDisconnectOnClose;
187 QByteArray memberToDisconnectOnClose;
188};
189
190QInputDialogPrivate::QInputDialogPrivate()
191 : label(nullptr), buttonBox(nullptr), lineEdit(nullptr), plainTextEdit(nullptr), intSpinBox(nullptr), doubleSpinBox(nullptr),
192 comboBox(nullptr), listView(nullptr), inputWidget(nullptr), mainLayout(nullptr)
193{
194}
195
196void QInputDialogPrivate::ensureLayout()
197{
198 Q_Q(QInputDialog);
199
200 if (mainLayout)
201 return;
202
203 if (!inputWidget) {
204 ensureLineEdit();
205 inputWidget = lineEdit;
206 }
207
208 if (!label)
209 label = new QLabel(QInputDialog::tr(s: "Enter a value:"), q);
210#ifndef QT_NO_SHORTCUT
211 label->setBuddy(inputWidget);
212#endif
213 label->setSizePolicy(hor: QSizePolicy::Minimum, ver: QSizePolicy::Fixed);
214
215 buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);
216 QObject::connect(sender: buttonBox, signal: &QDialogButtonBox::accepted, context: q, slot: &QDialog::accept);
217 QObject::connect(sender: buttonBox, signal: &QDialogButtonBox::rejected, context: q, slot: &QDialog::reject);
218
219 mainLayout = new QVBoxLayout(q);
220 mainLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
221 mainLayout->addWidget(label);
222 mainLayout->addWidget(inputWidget);
223 mainLayout->addWidget(buttonBox);
224 ensureEnabledConnection(spinBox: qobject_cast<QAbstractSpinBox *>(object: inputWidget));
225 inputWidget->show();
226}
227
228void QInputDialogPrivate::ensureLineEdit()
229{
230 Q_Q(QInputDialog);
231 if (!lineEdit) {
232 lineEdit = new QLineEdit(q);
233#ifndef QT_NO_IM
234 qt_widget_private(widget: lineEdit)->inheritsInputMethodHints = 1;
235#endif
236 lineEdit->hide();
237 QObjectPrivate::connect(sender: lineEdit, signal: &QLineEdit::textChanged,
238 receiverPrivate: this, slot: &QInputDialogPrivate::textChanged);
239 }
240}
241
242void QInputDialogPrivate::ensurePlainTextEdit()
243{
244 Q_Q(QInputDialog);
245 if (!plainTextEdit) {
246 plainTextEdit = new QPlainTextEdit(q);
247 plainTextEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
248#ifndef QT_NO_IM
249 qt_widget_private(widget: plainTextEdit)->inheritsInputMethodHints = 1;
250#endif
251 plainTextEdit->hide();
252 QObjectPrivate::connect(sender: plainTextEdit, signal: &QPlainTextEdit::textChanged,
253 receiverPrivate: this, slot: &QInputDialogPrivate::plainTextEditTextChanged);
254 }
255}
256
257void QInputDialogPrivate::ensureComboBox()
258{
259 Q_Q(QInputDialog);
260 if (!comboBox) {
261 comboBox = new QComboBox(q);
262#ifndef QT_NO_IM
263 qt_widget_private(widget: comboBox)->inheritsInputMethodHints = 1;
264#endif
265 comboBox->hide();
266 QObjectPrivate::connect(sender: comboBox, signal: &QComboBox::editTextChanged,
267 receiverPrivate: this, slot: &QInputDialogPrivate::textChanged);
268 QObjectPrivate::connect(sender: comboBox, signal: &QComboBox::currentTextChanged,
269 receiverPrivate: this, slot: &QInputDialogPrivate::textChanged);
270 }
271}
272
273void QInputDialogPrivate::ensureListView()
274{
275 Q_Q(QInputDialog);
276 if (!listView) {
277 ensureComboBox();
278 listView = new QInputDialogListView(q);
279 listView->hide();
280 listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
281 listView->setSelectionMode(QAbstractItemView::SingleSelection);
282 listView->setModel(comboBox->model());
283 listView->setCurrentIndex(QModelIndex()); // ###
284 QObjectPrivate::connect(sender: listView->selectionModel(),
285 signal: &QItemSelectionModel::currentRowChanged,
286 receiverPrivate: this, slot: &QInputDialogPrivate::currentRowChanged);
287 }
288}
289
290void QInputDialogPrivate::ensureIntSpinBox()
291{
292 Q_Q(QInputDialog);
293 if (!intSpinBox) {
294 intSpinBox = new QInputDialogSpinBox(q);
295 intSpinBox->hide();
296 QObject::connect(sender: intSpinBox, signal: &QInputDialogSpinBox::valueChanged,
297 context: q, slot: &QInputDialog::intValueChanged);
298 }
299}
300
301void QInputDialogPrivate::ensureDoubleSpinBox()
302{
303 Q_Q(QInputDialog);
304 if (!doubleSpinBox) {
305 doubleSpinBox = new QInputDialogDoubleSpinBox(q);
306 doubleSpinBox->hide();
307 QObject::connect(sender: doubleSpinBox, signal: &QInputDialogDoubleSpinBox::valueChanged,
308 context: q, slot: &QInputDialog::doubleValueChanged);
309 }
310}
311
312void QInputDialogPrivate::ensureEnabledConnection(QAbstractSpinBox *spinBox)
313{
314 if (spinBox) {
315 QAbstractButton *okButton = buttonBox->button(which: QDialogButtonBox::Ok);
316 QObject::connect(sender: spinBox, SIGNAL(textChanged(bool)), receiver: okButton, SLOT(setEnabled(bool)), Qt::UniqueConnection);
317 }
318}
319
320void QInputDialogPrivate::setInputWidget(QWidget *widget)
321{
322 Q_ASSERT(widget);
323 if (inputWidget == widget)
324 return;
325
326 if (mainLayout) {
327 Q_ASSERT(inputWidget);
328 mainLayout->removeWidget(w: inputWidget);
329 inputWidget->hide();
330 mainLayout->insertWidget(index: 1, widget);
331 widget->show();
332
333 // disconnect old input widget
334 QAbstractButton *okButton = buttonBox->button(which: QDialogButtonBox::Ok);
335 if (QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(object: inputWidget))
336 QObject::disconnect(sender: spinBox, SIGNAL(textChanged(bool)), receiver: okButton, SLOT(setEnabled(bool)));
337
338 // connect new input widget and update enabled state of OK button
339 QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(object: widget);
340 ensureEnabledConnection(spinBox);
341 okButton->setEnabled(!spinBox || spinBox->hasAcceptableInput());
342 }
343
344 inputWidget = widget;
345
346 // synchronize the text shown in the new text editor with the current
347 // textValue
348 if (widget == lineEdit) {
349 lineEdit->setText(textValue);
350 } else if (widget == plainTextEdit) {
351 plainTextEdit->setPlainText(textValue);
352 } else if (widget == comboBox) {
353 setComboBoxText(textValue);
354 } else if (widget == listView) {
355 setListViewText(textValue);
356 ensureLayout();
357 buttonBox->button(which: QDialogButtonBox::Ok)->setEnabled(listView->selectionModel()->hasSelection());
358 }
359}
360
361void QInputDialogPrivate::chooseRightTextInputWidget()
362{
363 QWidget *widget;
364
365 if (useComboBoxOrListView()) {
366 if ((opts & QInputDialog::UseListViewForComboBoxItems) && !comboBox->isEditable()) {
367 ensureListView();
368 widget = listView;
369 } else {
370 widget = comboBox;
371 }
372 } else if (opts & QInputDialog::UsePlainTextEditForTextInput) {
373 ensurePlainTextEdit();
374 widget = plainTextEdit;
375 } else {
376 ensureLineEdit();
377 widget = lineEdit;
378 }
379
380 setInputWidget(widget);
381
382 if (inputWidget == comboBox) {
383 textChanged(text: comboBox->currentText());
384 } else if (inputWidget == listView) {
385 textChanged(text: listViewText());
386 }
387}
388
389void QInputDialogPrivate::setComboBoxText(const QString &text)
390{
391 int index = comboBox->findText(text);
392 if (index != -1) {
393 comboBox->setCurrentIndex(index);
394 } else if (comboBox->isEditable()) {
395 comboBox->setEditText(text);
396 }
397}
398
399void QInputDialogPrivate::setListViewText(const QString &text)
400{
401 int row = comboBox->findText(text);
402 if (row != -1) {
403 QModelIndex index(comboBox->model()->index(row, column: 0));
404 listView->selectionModel()->setCurrentIndex(index, command: QItemSelectionModel::Clear
405 | QItemSelectionModel::SelectCurrent);
406 }
407}
408
409QString QInputDialogPrivate::listViewText() const
410{
411 if (listView->selectionModel()->hasSelection()) {
412 int row = listView->selectionModel()->selectedRows().value(i: 0).row();
413 return comboBox->itemText(index: row);
414 } else {
415 return QString();
416 }
417}
418
419void QInputDialogPrivate::textChanged(const QString &text)
420{
421 Q_Q(QInputDialog);
422 if (textValue != text) {
423 textValue = text;
424 emit q->textValueChanged(text);
425 }
426}
427
428void QInputDialogPrivate::plainTextEditTextChanged()
429{
430 Q_Q(QInputDialog);
431 QString text = plainTextEdit->toPlainText();
432 if (textValue != text) {
433 textValue = text;
434 emit q->textValueChanged(text);
435 }
436}
437
438void QInputDialogPrivate::currentRowChanged(const QModelIndex &newIndex,
439 const QModelIndex & /* oldIndex */)
440{
441 textChanged(text: comboBox->model()->data(index: newIndex).toString());
442 buttonBox->button(which: QDialogButtonBox::Ok)->setEnabled(true);
443}
444
445/*!
446 \class QInputDialog
447 \brief The QInputDialog class provides a simple convenience dialog to get a
448 single value from the user.
449 \ingroup standard-dialogs
450 \inmodule QtWidgets
451
452 The input value can be a string, a number or an item from a list. A label
453 must be set to tell the user what they should enter.
454
455 Five static convenience functions are provided: getText(), getMultiLineText(),
456 getInt(), getDouble(), and getItem(). All the functions can be used in a similar way,
457 for example:
458
459 \snippet dialogs/standarddialogs/dialog.cpp 3
460
461 The \c ok variable is set to true if the user clicks \uicontrol OK; otherwise, it
462 is set to false.
463
464 \image inputdialogs.png Input Dialogs
465
466 The \l{dialogs/standarddialogs}{Standard Dialogs} example shows how to use
467 QInputDialog as well as other built-in Qt dialogs.
468
469 \sa QMessageBox, {Standard Dialogs Example}
470*/
471
472/*!
473 \enum QInputDialog::InputMode
474
475 This enum describes the different modes of input that can be selected for
476 the dialog.
477
478 \value TextInput Used to input text strings.
479 \value IntInput Used to input integers.
480 \value DoubleInput Used to input floating point numbers with double
481 precision accuracy.
482
483 \sa inputMode
484*/
485
486/*!
487 Constructs a new input dialog with the given \a parent and window \a flags.
488*/
489QInputDialog::QInputDialog(QWidget *parent, Qt::WindowFlags flags)
490 : QDialog(*new QInputDialogPrivate, parent, flags)
491{
492}
493
494/*!
495 Destroys the input dialog.
496*/
497QInputDialog::~QInputDialog()
498{
499}
500
501/*!
502 \property QInputDialog::inputMode
503
504 \brief the mode used for input
505
506 This property helps determine which widget is used for entering input into
507 the dialog.
508*/
509void QInputDialog::setInputMode(InputMode mode)
510{
511 Q_D(QInputDialog);
512
513 QWidget *widget;
514
515 /*
516 Warning: Some functions in QInputDialog rely on implementation details
517 of the code below. Look for the comments that accompany the calls to
518 setInputMode() throughout this file before you change the code below.
519 */
520
521 switch (mode) {
522 case IntInput:
523 d->ensureIntSpinBox();
524 widget = d->intSpinBox;
525 break;
526 case DoubleInput:
527 d->ensureDoubleSpinBox();
528 widget = d->doubleSpinBox;
529 break;
530 default:
531 Q_ASSERT(mode == TextInput);
532 d->chooseRightTextInputWidget();
533 return;
534 }
535
536 d->setInputWidget(widget);
537}
538
539QInputDialog::InputMode QInputDialog::inputMode() const
540{
541 Q_D(const QInputDialog);
542
543 if (d->inputWidget) {
544 if (d->inputWidget == d->intSpinBox) {
545 return IntInput;
546 } else if (d->inputWidget == d->doubleSpinBox) {
547 return DoubleInput;
548 }
549 }
550
551 return TextInput;
552}
553
554/*!
555 \property QInputDialog::labelText
556
557 \brief the label's text which describes what needs to be input
558*/
559void QInputDialog::setLabelText(const QString &text)
560{
561 Q_D(QInputDialog);
562 if (!d->label) {
563 d->label = new QLabel(text, this);
564 } else {
565 d->label->setText(text);
566 }
567}
568
569QString QInputDialog::labelText() const
570{
571 Q_D(const QInputDialog);
572 d->ensureLayout();
573 return d->label->text();
574}
575
576/*!
577 \enum QInputDialog::InputDialogOption
578
579 This enum specifies various options that affect the look and feel
580 of an input dialog.
581
582 \value NoButtons Don't display \uicontrol{OK} and \uicontrol{Cancel} buttons (useful for "live dialogs").
583 \value UseListViewForComboBoxItems Use a QListView rather than a non-editable QComboBox for
584 displaying the items set with setComboBoxItems().
585 \value UsePlainTextEditForTextInput Use a QPlainTextEdit for multiline text input. This value was
586 introduced in 5.2.
587
588 \sa options, setOption(), testOption()
589*/
590
591/*!
592 Sets the given \a option to be enabled if \a on is true;
593 otherwise, clears the given \a option.
594
595 \sa options, testOption()
596*/
597void QInputDialog::setOption(InputDialogOption option, bool on)
598{
599 Q_D(QInputDialog);
600 if (!(d->opts & option) != !on)
601 setOptions(d->opts ^ option);
602}
603
604/*!
605 Returns \c true if the given \a option is enabled; otherwise, returns
606 false.
607
608 \sa options, setOption()
609*/
610bool QInputDialog::testOption(InputDialogOption option) const
611{
612 Q_D(const QInputDialog);
613 return (d->opts & option) != 0;
614}
615
616/*!
617 \property QInputDialog::options
618 \brief the various options that affect the look and feel of the dialog
619
620 By default, all options are disabled.
621
622 \sa setOption(), testOption()
623*/
624void QInputDialog::setOptions(InputDialogOptions options)
625{
626 Q_D(QInputDialog);
627
628 InputDialogOptions changed = (options ^ d->opts);
629 if (!changed)
630 return;
631
632 d->opts = options;
633 d->ensureLayout();
634
635 if (changed & NoButtons)
636 d->buttonBox->setVisible(!(options & NoButtons));
637 if ((changed & UseListViewForComboBoxItems) && inputMode() == TextInput)
638 d->chooseRightTextInputWidget();
639 if ((changed & UsePlainTextEditForTextInput) && inputMode() == TextInput)
640 d->chooseRightTextInputWidget();
641}
642
643QInputDialog::InputDialogOptions QInputDialog::options() const
644{
645 Q_D(const QInputDialog);
646 return d->opts;
647}
648
649/*!
650 \property QInputDialog::textValue
651
652 \brief the text value for the input dialog
653
654 This property is only relevant when the input dialog is used in
655 TextInput mode.
656*/
657void QInputDialog::setTextValue(const QString &text)
658{
659 Q_D(QInputDialog);
660
661 setInputMode(TextInput);
662 if (d->inputWidget == d->lineEdit) {
663 d->lineEdit->setText(text);
664 } else if (d->inputWidget == d->plainTextEdit) {
665 d->plainTextEdit->setPlainText(text);
666 } else if (d->inputWidget == d->comboBox) {
667 d->setComboBoxText(text);
668 } else {
669 d->setListViewText(text);
670 }
671}
672
673QString QInputDialog::textValue() const
674{
675 Q_D(const QInputDialog);
676 return d->textValue;
677}
678
679/*!
680 \property QInputDialog::textEchoMode
681
682 \brief the echo mode for the text value
683
684 This property is only relevant when the input dialog is used in
685 TextInput mode.
686*/
687void QInputDialog::setTextEchoMode(QLineEdit::EchoMode mode)
688{
689 Q_D(QInputDialog);
690 d->ensureLineEdit();
691 d->lineEdit->setEchoMode(mode);
692}
693
694QLineEdit::EchoMode QInputDialog::textEchoMode() const
695{
696 Q_D(const QInputDialog);
697 if (d->lineEdit) {
698 return d->lineEdit->echoMode();
699 } else {
700 return QLineEdit::Normal;
701 }
702}
703
704/*!
705 \property QInputDialog::comboBoxEditable
706
707 \brief whether or not the combo box used in the input dialog is editable
708*/
709void QInputDialog::setComboBoxEditable(bool editable)
710{
711 Q_D(QInputDialog);
712 d->ensureComboBox();
713 d->comboBox->setEditable(editable);
714 if (inputMode() == TextInput)
715 d->chooseRightTextInputWidget();
716}
717
718bool QInputDialog::isComboBoxEditable() const
719{
720 Q_D(const QInputDialog);
721 if (d->comboBox) {
722 return d->comboBox->isEditable();
723 } else {
724 return false;
725 }
726}
727
728/*!
729 \property QInputDialog::comboBoxItems
730
731 \brief the items used in the combo box for the input dialog
732*/
733void QInputDialog::setComboBoxItems(const QStringList &items)
734{
735 Q_D(QInputDialog);
736
737 d->ensureComboBox();
738 {
739 const QSignalBlocker blocker(d->comboBox);
740 d->comboBox->clear();
741 d->comboBox->addItems(texts: items);
742 }
743
744 if (inputMode() == TextInput)
745 d->chooseRightTextInputWidget();
746}
747
748QStringList QInputDialog::comboBoxItems() const
749{
750 Q_D(const QInputDialog);
751 QStringList result;
752 if (d->comboBox) {
753 const int count = d->comboBox->count();
754 result.reserve(asize: count);
755 for (int i = 0; i < count; ++i)
756 result.append(t: d->comboBox->itemText(index: i));
757 }
758 return result;
759}
760
761/*!
762 \property QInputDialog::intValue
763 \brief the current integer value accepted as input
764
765 This property is only relevant when the input dialog is used in
766 IntInput mode.
767*/
768void QInputDialog::setIntValue(int value)
769{
770 Q_D(QInputDialog);
771 setInputMode(IntInput);
772 d->intSpinBox->setValue(value);
773}
774
775int QInputDialog::intValue() const
776{
777 Q_D(const QInputDialog);
778 if (d->intSpinBox) {
779 return d->intSpinBox->value();
780 } else {
781 return 0;
782 }
783}
784
785/*!
786 \property QInputDialog::intMinimum
787 \brief the minimum integer value accepted as input
788
789 This property is only relevant when the input dialog is used in
790 IntInput mode.
791*/
792void QInputDialog::setIntMinimum(int min)
793{
794 Q_D(QInputDialog);
795 d->ensureIntSpinBox();
796 d->intSpinBox->setMinimum(min);
797}
798
799int QInputDialog::intMinimum() const
800{
801 Q_D(const QInputDialog);
802 if (d->intSpinBox) {
803 return d->intSpinBox->minimum();
804 } else {
805 return 0;
806 }
807}
808
809/*!
810 \property QInputDialog::intMaximum
811 \brief the maximum integer value accepted as input
812
813 This property is only relevant when the input dialog is used in
814 IntInput mode.
815*/
816void QInputDialog::setIntMaximum(int max)
817{
818 Q_D(QInputDialog);
819 d->ensureIntSpinBox();
820 d->intSpinBox->setMaximum(max);
821}
822
823int QInputDialog::intMaximum() const
824{
825 Q_D(const QInputDialog);
826 if (d->intSpinBox) {
827 return d->intSpinBox->maximum();
828 } else {
829 return 99;
830 }
831}
832
833/*!
834 Sets the range of integer values accepted by the dialog when used in
835 IntInput mode, with minimum and maximum values specified by \a min and
836 \a max respectively.
837*/
838void QInputDialog::setIntRange(int min, int max)
839{
840 Q_D(QInputDialog);
841 d->ensureIntSpinBox();
842 d->intSpinBox->setRange(min, max);
843}
844
845/*!
846 \property QInputDialog::intStep
847 \brief the step by which the integer value is increased and decreased
848
849 This property is only relevant when the input dialog is used in
850 IntInput mode.
851*/
852void QInputDialog::setIntStep(int step)
853{
854 Q_D(QInputDialog);
855 d->ensureIntSpinBox();
856 d->intSpinBox->setSingleStep(step);
857}
858
859int QInputDialog::intStep() const
860{
861 Q_D(const QInputDialog);
862 if (d->intSpinBox) {
863 return d->intSpinBox->singleStep();
864 } else {
865 return 1;
866 }
867}
868
869/*!
870 \property QInputDialog::doubleValue
871 \brief the current double precision floating point value accepted as input
872
873 This property is only relevant when the input dialog is used in
874 DoubleInput mode.
875*/
876void QInputDialog::setDoubleValue(double value)
877{
878 Q_D(QInputDialog);
879 setInputMode(DoubleInput);
880 d->doubleSpinBox->setValue(value);
881}
882
883double QInputDialog::doubleValue() const
884{
885 Q_D(const QInputDialog);
886 if (d->doubleSpinBox) {
887 return d->doubleSpinBox->value();
888 } else {
889 return 0.0;
890 }
891}
892
893/*!
894 \property QInputDialog::doubleMinimum
895 \brief the minimum double precision floating point value accepted as input
896
897 This property is only relevant when the input dialog is used in
898 DoubleInput mode.
899*/
900void QInputDialog::setDoubleMinimum(double min)
901{
902 Q_D(QInputDialog);
903 d->ensureDoubleSpinBox();
904 d->doubleSpinBox->setMinimum(min);
905}
906
907double QInputDialog::doubleMinimum() const
908{
909 Q_D(const QInputDialog);
910 if (d->doubleSpinBox) {
911 return d->doubleSpinBox->minimum();
912 } else {
913 return 0.0;
914 }
915}
916
917/*!
918 \property QInputDialog::doubleMaximum
919 \brief the maximum double precision floating point value accepted as input
920
921 This property is only relevant when the input dialog is used in
922 DoubleInput mode.
923*/
924void QInputDialog::setDoubleMaximum(double max)
925{
926 Q_D(QInputDialog);
927 d->ensureDoubleSpinBox();
928 d->doubleSpinBox->setMaximum(max);
929}
930
931double QInputDialog::doubleMaximum() const
932{
933 Q_D(const QInputDialog);
934 if (d->doubleSpinBox) {
935 return d->doubleSpinBox->maximum();
936 } else {
937 return 99.99;
938 }
939}
940
941/*!
942 Sets the range of double precision floating point values accepted by the
943 dialog when used in DoubleInput mode, with minimum and maximum values
944 specified by \a min and \a max respectively.
945*/
946void QInputDialog::setDoubleRange(double min, double max)
947{
948 Q_D(QInputDialog);
949 d->ensureDoubleSpinBox();
950 d->doubleSpinBox->setRange(min, max);
951}
952
953/*!
954 \property QInputDialog::doubleDecimals
955
956 \brief sets the precision of the double spinbox in decimals
957
958 \sa QDoubleSpinBox::setDecimals()
959*/
960void QInputDialog::setDoubleDecimals(int decimals)
961{
962 Q_D(QInputDialog);
963 d->ensureDoubleSpinBox();
964 d->doubleSpinBox->setDecimals(decimals);
965}
966
967int QInputDialog::doubleDecimals() const
968{
969 Q_D(const QInputDialog);
970 if (d->doubleSpinBox) {
971 return d->doubleSpinBox->decimals();
972 } else {
973 return 2;
974 }
975}
976
977/*!
978 \property QInputDialog::okButtonText
979
980 \brief the text for the button used to accept the entry in the dialog
981*/
982void QInputDialog::setOkButtonText(const QString &text)
983{
984 Q_D(const QInputDialog);
985 d->ensureLayout();
986 d->buttonBox->button(which: QDialogButtonBox::Ok)->setText(text);
987}
988
989QString QInputDialog::okButtonText() const
990{
991 Q_D(const QInputDialog);
992 d->ensureLayout();
993 return d->buttonBox->button(which: QDialogButtonBox::Ok)->text();
994}
995
996/*!
997 \property QInputDialog::cancelButtonText
998 \brief the text for the button used to cancel the dialog
999*/
1000void QInputDialog::setCancelButtonText(const QString &text)
1001{
1002 Q_D(const QInputDialog);
1003 d->ensureLayout();
1004 d->buttonBox->button(which: QDialogButtonBox::Cancel)->setText(text);
1005}
1006
1007QString QInputDialog::cancelButtonText() const
1008{
1009 Q_D(const QInputDialog);
1010 d->ensureLayout();
1011 return d->buttonBox->button(which: QDialogButtonBox::Cancel)->text();
1012}
1013
1014/*!
1015 This function connects one of its signals to the slot specified by \a receiver
1016 and \a member. The specific signal depends on the arguments that are specified
1017 in \a member. These are:
1018
1019 \list
1020 \li textValueSelected() if \a member has a QString for its first argument.
1021 \li intValueSelected() if \a member has an int for its first argument.
1022 \li doubleValueSelected() if \a member has a double for its first argument.
1023 \li accepted() if \a member has NO arguments.
1024 \endlist
1025
1026 The signal will be disconnected from the slot when the dialog is closed.
1027*/
1028void QInputDialog::open(QObject *receiver, const char *member)
1029{
1030 Q_D(QInputDialog);
1031 connect(sender: this, signal: signalForMember(member), receiver, member);
1032 d->receiverToDisconnectOnClose = receiver;
1033 d->memberToDisconnectOnClose = member;
1034 QDialog::open();
1035}
1036
1037/*!
1038 \reimp
1039*/
1040QSize QInputDialog::minimumSizeHint() const
1041{
1042 Q_D(const QInputDialog);
1043 d->ensureLayout();
1044 return QDialog::minimumSizeHint();
1045}
1046
1047/*!
1048 \reimp
1049*/
1050QSize QInputDialog::sizeHint() const
1051{
1052 Q_D(const QInputDialog);
1053 d->ensureLayout();
1054 return QDialog::sizeHint();
1055}
1056
1057/*!
1058 \reimp
1059*/
1060void QInputDialog::setVisible(bool visible)
1061{
1062 Q_D(const QInputDialog);
1063 if (visible) {
1064 d->ensureLayout();
1065 d->inputWidget->setFocus();
1066 if (d->inputWidget == d->lineEdit) {
1067 d->lineEdit->selectAll();
1068 } else if (d->inputWidget == d->plainTextEdit) {
1069 d->plainTextEdit->selectAll();
1070 } else if (d->inputWidget == d->intSpinBox) {
1071 d->intSpinBox->selectAll();
1072 } else if (d->inputWidget == d->doubleSpinBox) {
1073 d->doubleSpinBox->selectAll();
1074 }
1075 }
1076 QDialog::setVisible(visible);
1077}
1078
1079/*!
1080 Closes the dialog and sets its result code to \a result. If this dialog
1081 is shown with exec(), done() causes the local event loop to finish,
1082 and exec() to return \a result.
1083
1084 \sa QDialog::done()
1085*/
1086void QInputDialog::done(int result)
1087{
1088 Q_D(QInputDialog);
1089 QDialog::done(result);
1090 if (result) {
1091 InputMode mode = inputMode();
1092 switch (mode) {
1093 case DoubleInput:
1094 emit doubleValueSelected(value: doubleValue());
1095 break;
1096 case IntInput:
1097 emit intValueSelected(value: intValue());
1098 break;
1099 default:
1100 Q_ASSERT(mode == TextInput);
1101 emit textValueSelected(text: textValue());
1102 }
1103 }
1104 if (d->receiverToDisconnectOnClose) {
1105 disconnect(sender: this, signal: signalForMember(member: d->memberToDisconnectOnClose),
1106 receiver: d->receiverToDisconnectOnClose, member: d->memberToDisconnectOnClose);
1107 d->receiverToDisconnectOnClose = nullptr;
1108 }
1109 d->memberToDisconnectOnClose.clear();
1110}
1111
1112/*!
1113 Static convenience function to get a string from the user.
1114
1115 \a title is the text which is displayed in the title bar of the dialog.
1116 \a label is the text which is shown to the user (it should say what should
1117 be entered).
1118 \a text is the default text which is placed in the line edit.
1119 \a mode is the echo mode the line edit will use.
1120 \a inputMethodHints is the input method hints that will be used in the
1121 edit widget if an input method is active.
1122
1123 If \a ok is nonnull \e {*ok} will be set to true if the user pressed
1124 \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
1125 is \a parent. The dialog will be modal and uses the specified widget
1126 \a flags.
1127
1128 If the dialog is accepted, this function returns the text in the dialog's
1129 line edit. If the dialog is rejected, a null QString is returned.
1130
1131 Use this static function like this:
1132
1133 \snippet dialogs/standarddialogs/dialog.cpp 3
1134
1135 \sa getInt(), getDouble(), getItem(), getMultiLineText()
1136*/
1137
1138QString QInputDialog::getText(QWidget *parent, const QString &title, const QString &label,
1139 QLineEdit::EchoMode mode, const QString &text, bool *ok,
1140 Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
1141{
1142 QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));
1143 dialog->setWindowTitle(title);
1144 dialog->setLabelText(label);
1145 dialog->setTextValue(text);
1146 dialog->setTextEchoMode(mode);
1147 dialog->setInputMethodHints(inputMethodHints);
1148
1149 const int ret = dialog->exec();
1150 if (ok)
1151 *ok = !!ret;
1152 if (bool(dialog) && ret) {
1153 return dialog->textValue();
1154 } else {
1155 return QString();
1156 }
1157}
1158
1159/*!
1160 \since 5.2
1161
1162 Static convenience function to get a multiline string from the user.
1163
1164 \a title is the text which is displayed in the title bar of the dialog.
1165 \a label is the text which is shown to the user (it should say what should
1166 be entered).
1167 \a text is the default text which is placed in the plain text edit.
1168 \a inputMethodHints is the input method hints that will be used in the
1169 edit widget if an input method is active.
1170
1171 If \a ok is nonnull \e {*ok} will be set to true if the user pressed
1172 \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
1173 is \a parent. The dialog will be modal and uses the specified widget
1174 \a flags.
1175
1176 If the dialog is accepted, this function returns the text in the dialog's
1177 plain text edit. If the dialog is rejected, a null QString is returned.
1178
1179 Use this static function like this:
1180
1181 \snippet dialogs/standarddialogs/dialog.cpp 4
1182
1183 \sa getInt(), getDouble(), getItem(), getText()
1184*/
1185
1186QString QInputDialog::getMultiLineText(QWidget *parent, const QString &title, const QString &label,
1187 const QString &text, bool *ok, Qt::WindowFlags flags,
1188 Qt::InputMethodHints inputMethodHints)
1189{
1190 QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));
1191 dialog->setOptions(QInputDialog::UsePlainTextEditForTextInput);
1192 dialog->setWindowTitle(title);
1193 dialog->setLabelText(label);
1194 dialog->setTextValue(text);
1195 dialog->setInputMethodHints(inputMethodHints);
1196
1197 const int ret = dialog->exec();
1198 if (ok)
1199 *ok = !!ret;
1200 if (bool(dialog) && ret) {
1201 return dialog->textValue();
1202 } else {
1203 return QString();
1204 }
1205}
1206
1207/*!
1208 Static convenience function to get an integer input from the user.
1209
1210 \a title is the text which is displayed in the title bar of the dialog.
1211 \a label is the text which is shown to the user (it should say what should
1212 be entered).
1213 \a value is the default integer which the spinbox will be set to.
1214 \a min and \a max are the minimum and maximum values the user may choose.
1215 \a step is the amount by which the values change as the user presses the
1216 arrow buttons to increment or decrement the value.
1217
1218 If \a ok is nonnull *\a ok will be set to true if the user pressed \uicontrol OK
1219 and to false if the user pressed \uicontrol Cancel. The dialog's parent is
1220 \a parent. The dialog will be modal and uses the widget \a flags.
1221
1222 On success, this function returns the integer which has been entered by the
1223 user; on failure, it returns the initial \a value.
1224
1225 Use this static function like this:
1226
1227 \snippet dialogs/standarddialogs/dialog.cpp 0
1228
1229 \sa getText(), getDouble(), getItem(), getMultiLineText()
1230*/
1231
1232int QInputDialog::getInt(QWidget *parent, const QString &title, const QString &label, int value,
1233 int min, int max, int step, bool *ok, Qt::WindowFlags flags)
1234{
1235 QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));
1236 dialog->setWindowTitle(title);
1237 dialog->setLabelText(label);
1238 dialog->setIntRange(min, max);
1239 dialog->setIntValue(value);
1240 dialog->setIntStep(step);
1241
1242 const int ret = dialog->exec();
1243 if (ok)
1244 *ok = !!ret;
1245 if (bool(dialog) && ret) {
1246 return dialog->intValue();
1247 } else {
1248 return value;
1249 }
1250}
1251
1252/*!
1253 Static convenience function to get a floating point number from the user.
1254
1255 \a title is the text which is displayed in the title bar of the dialog.
1256 \a label is the text which is shown to the user (it should say what should
1257 be entered).
1258 \a value is the default floating point number that the line edit will be
1259 set to.
1260 \a min and \a max are the minimum and maximum values the user may choose.
1261 \a decimals is the maximum number of decimal places the number may have.
1262 \a step is the amount by which the values change as the user presses the
1263 arrow buttons to increment or decrement the value.
1264
1265 If \a ok is nonnull, *\a ok will be set to true if the user pressed \uicontrol OK
1266 and to false if the user pressed \uicontrol Cancel. The dialog's parent is
1267 \a parent. The dialog will be modal and uses the widget \a flags.
1268
1269 This function returns the floating point number which has been entered by
1270 the user.
1271
1272 Use this static function like this:
1273
1274 \snippet dialogs/standarddialogs/dialog.cpp 1
1275
1276 \sa getText(), getInt(), getItem(), getMultiLineText()
1277*/
1278
1279double QInputDialog::getDouble(QWidget *parent, const QString &title, const QString &label,
1280 double value, double min, double max, int decimals, bool *ok,
1281 Qt::WindowFlags flags, double step)
1282{
1283 QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));
1284 dialog->setWindowTitle(title);
1285 dialog->setLabelText(label);
1286 dialog->setDoubleDecimals(decimals);
1287 dialog->setDoubleRange(min, max);
1288 dialog->setDoubleValue(value);
1289 dialog->setDoubleStep(step);
1290
1291 const int ret = dialog->exec();
1292 if (ok)
1293 *ok = !!ret;
1294 if (bool(dialog) && ret) {
1295 return dialog->doubleValue();
1296 } else {
1297 return value;
1298 }
1299}
1300
1301/*!
1302 Static convenience function to let the user select an item from a string
1303 list.
1304
1305 \a title is the text which is displayed in the title bar of the dialog.
1306 \a label is the text which is shown to the user (it should say what should
1307 be entered).
1308 \a items is the string list which is inserted into the combo box.
1309 \a current is the number of the item which should be the current item.
1310 \a inputMethodHints is the input method hints that will be used if the
1311 combo box is editable and an input method is active.
1312
1313 If \a editable is true the user can enter their own text; otherwise, the
1314 user may only select one of the existing items.
1315
1316 If \a ok is nonnull \e {*ok} will be set to true if the user pressed
1317 \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
1318 is \a parent. The dialog will be modal and uses the widget \a flags.
1319
1320 This function returns the text of the current item, or if \a editable is
1321 true, the current text of the combo box.
1322
1323 Use this static function like this:
1324
1325 \snippet dialogs/standarddialogs/dialog.cpp 2
1326
1327 \sa getText(), getInt(), getDouble(), getMultiLineText()
1328*/
1329
1330QString QInputDialog::getItem(QWidget *parent, const QString &title, const QString &label,
1331 const QStringList &items, int current, bool editable, bool *ok,
1332 Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
1333{
1334 QString text(items.value(i: current));
1335
1336 QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));
1337 dialog->setWindowTitle(title);
1338 dialog->setLabelText(label);
1339 dialog->setComboBoxItems(items);
1340 dialog->setTextValue(text);
1341 dialog->setComboBoxEditable(editable);
1342 dialog->setInputMethodHints(inputMethodHints);
1343
1344 const int ret = dialog->exec();
1345 if (ok)
1346 *ok = !!ret;
1347 if (bool(dialog) && ret) {
1348 return dialog->textValue();
1349 } else {
1350 return text;
1351 }
1352}
1353
1354/*!
1355 \property QInputDialog::doubleStep
1356 \since 5.10
1357 \brief the step by which the double value is increased and decreased
1358
1359 This property is only relevant when the input dialog is used in
1360 DoubleInput mode.
1361*/
1362
1363void QInputDialog::setDoubleStep(double step)
1364{
1365 Q_D(QInputDialog);
1366 d->ensureDoubleSpinBox();
1367 d->doubleSpinBox->setSingleStep(step);
1368}
1369
1370double QInputDialog::doubleStep() const
1371{
1372 Q_D(const QInputDialog);
1373 if (d->doubleSpinBox)
1374 return d->doubleSpinBox->singleStep();
1375 else
1376 return 1.0;
1377}
1378
1379/*!
1380 \fn void QInputDialog::doubleValueChanged(double value)
1381
1382 This signal is emitted whenever the double value changes in the dialog.
1383 The current value is specified by \a value.
1384
1385 This signal is only relevant when the input dialog is used in
1386 DoubleInput mode.
1387*/
1388
1389/*!
1390 \fn void QInputDialog::doubleValueSelected(double value)
1391
1392 This signal is emitted whenever the user selects a double value by
1393 accepting the dialog; for example, by clicking the \uicontrol{OK} button.
1394 The selected value is specified by \a value.
1395
1396 This signal is only relevant when the input dialog is used in
1397 DoubleInput mode.
1398*/
1399
1400/*!
1401 \fn void QInputDialog::intValueChanged(int value)
1402
1403 This signal is emitted whenever the integer value changes in the dialog.
1404 The current value is specified by \a value.
1405
1406 This signal is only relevant when the input dialog is used in
1407 IntInput mode.
1408*/
1409
1410/*!
1411 \fn void QInputDialog::intValueSelected(int value)
1412
1413 This signal is emitted whenever the user selects a integer value by
1414 accepting the dialog; for example, by clicking the \uicontrol{OK} button.
1415 The selected value is specified by \a value.
1416
1417 This signal is only relevant when the input dialog is used in
1418 IntInput mode.
1419*/
1420
1421/*!
1422 \fn void QInputDialog::textValueChanged(const QString &text)
1423
1424 This signal is emitted whenever the text string changes in the dialog.
1425 The current string is specified by \a text.
1426
1427 This signal is only relevant when the input dialog is used in
1428 TextInput mode.
1429*/
1430
1431/*!
1432 \fn void QInputDialog::textValueSelected(const QString &text)
1433
1434 This signal is emitted whenever the user selects a text string by
1435 accepting the dialog; for example, by clicking the \uicontrol{OK} button.
1436 The selected string is specified by \a text.
1437
1438 This signal is only relevant when the input dialog is used in
1439 TextInput mode.
1440*/
1441
1442QT_END_NAMESPACE
1443
1444#include "qinputdialog.moc"
1445#include "moc_qinputdialog.cpp"
1446

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/widgets/dialogs/qinputdialog.cpp