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

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