diff options
author | Kai Koehne <kai.koehne@qt.io> | 2017-06-16 17:38:29 +0200 |
---|---|---|
committer | Kai Koehne <kai.koehne@qt.io> | 2017-06-22 09:50:33 +0000 |
commit | 4ba1f6ec607f05807f39a271e7e4c457fe3b0803 (patch) | |
tree | 977e9cfec3222eac47f4a50445405ba53e7fc996 /examples | |
parent | 6da03454544364ffe414b7c03cfcb0810abb43d4 (diff) |
TextFinder: Improve code and documentation
Task-number: QTBUG-61419
Change-Id: Ib00152f0a04546d275a40a5d57fe046b82ebc421
GPush-Base: 8abb03b0d84a3a94f7db41e010f69955488ea893
Reviewed-by: Martin Smith <martin.smith@qt.io>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/uitools/doc/src/multipleinheritance.qdoc | 5 | ||||
-rw-r--r-- | examples/uitools/doc/src/textfinder.qdoc | 149 | ||||
-rw-r--r-- | examples/uitools/textfinder/forms/input.txt | 12 | ||||
-rw-r--r-- | examples/uitools/textfinder/main.cpp | 9 | ||||
-rw-r--r-- | examples/uitools/textfinder/textfinder.cpp | 85 | ||||
-rw-r--r-- | examples/uitools/textfinder/textfinder.h | 12 | ||||
-rw-r--r-- | examples/uitools/textfinder/textfinder.pro | 12 |
7 files changed, 144 insertions, 140 deletions
diff --git a/examples/uitools/doc/src/multipleinheritance.qdoc b/examples/uitools/doc/src/multipleinheritance.qdoc index ae6511f87..da39d4b90 100644 --- a/examples/uitools/doc/src/multipleinheritance.qdoc +++ b/examples/uitools/doc/src/multipleinheritance.qdoc @@ -33,7 +33,7 @@ \brief Using a form created with Qt Designer in an application. The Multiple Inheritance Example shows how to use a form created with - Qt Designer in an application by subclassing both QWidget and the user + \l{Qt Designer} in an application by subclassing both QWidget and the user interface class, which is \c{Ui::CalculatorForm}. \image multipleinheritance-example.png @@ -67,8 +67,7 @@ \section1 CalculatorForm Implementation In the constructor, we call \c setupUi() to load the user interface file. - Note that we do not need the \c{ui} prefix as \c CalculatorForm is a - subclass of the user interface class. + Note that setupUi is a method of \c Ui::CalculatorForm. \snippet multipleinheritance/calculatorform.cpp 0 diff --git a/examples/uitools/doc/src/textfinder.qdoc b/examples/uitools/doc/src/textfinder.qdoc index d561c2b87..b6d1936ee 100644 --- a/examples/uitools/doc/src/textfinder.qdoc +++ b/examples/uitools/doc/src/textfinder.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -30,13 +30,15 @@ \ingroup examples-qtuitools \title Text Finder Example - \brief Dynamically processing forms using Qt UI Tools. + \brief Dynamically loading .ui files using QUiLoader. + + The TextFinder example shows how to load and setup a \c{.ui} file + dynamically using the \l{QUiLoader} class that is part of the + \l{Qt UI Tools} library. - Dynamic form processing enables a form to - be processed at run-time only by changing the UI file for the project. The program allows the user to look up a particular word within the - contents of a text file. This text file is included in the project's - resource and is loaded into the display at startup. + contents of a text. The visual elements and layout of the user interface is + loaded at runtime, from a the program resources. \table \row \li \inlineimage textfinder-example-find.png @@ -45,40 +47,47 @@ \section1 Setting Up The Resource File - The resources required for Text Finder are: + The resources required for the example are: \list - \li \e{textfinder.ui} - the user interface file created in QtDesigner - \li \e{input.txt} - a text file containing some text to be displayed - in the QTextEdit + \li \c{textfinder.ui} - the user interface file created in + \l{Qt Designer} + \li \c{input.txt} - a text file containing some text to be displayed in + a QTextEdit \endlist - \e{textfinder.ui} contains all the necessary QWidget objects for the - Text Finder. A QLineEdit is used for the user input, a QTextEdit is - used to display the contents of \e{input.txt}, a QLabel is used to - display the text "Keyword", and a QPushButton is used for the "Find" - button. The screenshot below shows the preview obtained in QtDesigner. + \c textfinder.ui contains all the necessary QWidget objects for the Text + Finder. A QLineEdit is used for the user input, a QTextEdit is used to + display the contents of \c input.txt, a QLabel is used to display the text + "Keyword", and a QPushButton is used for the \uicontrol Find button. Note + that all the widgets have sensible \c{objectName}'s assigned. These are + used in code to identify them. + + The screenshot below shows the preview obtained in \l{Qt Designer}. \image textfinder-example-userinterface.png - A \e{textfinder.qrc} file is used to store both the \e{textfinder.ui} - and \e{input.txt} in the application's executable. The file contains - the following code: + In this example, we store both resources in the applicaton's executable by + including the \c{textfinder.qrc} file. Alternatively, the files could also + be loaded at runtime from the file system, or from an external binary + resource \c{.rcc} file. For more information on resource files, see + \l{The Qt Resource System}. - \quotefile textfinder/textfinder.qrc + The \c{textfinder.qrc} file lists all files that should be included as a + resource: - For more information on resource files, see \l{The Qt Resource System}. + \quotefile textfinder/textfinder.qrc To generate a form at run-time, the example is linked against the - QtUiTools module library. This is done in the \c{textfinder.pro} file - that contains the following lines: + \l{Qt Ui Tools} library. This is done in the \c{textfinder.pro} file: - \snippet textfinder/doc_src_examples_textfinder.pro 0 + \snippet textfinder/textfinder.pro 0 \section1 TextFinder Class Definition - The \c TextFinder class is a subclass of QWidget and it hosts the - \l{QWidget}s we need to access in the user interface. The QLabel in the - user interface is not declared here as we do not need to access it. + The \c TextFinder class contains the main user interface. It declares + pointers to the QPushButton, QTextEdit and QLineEdit elements described + above. The QLabel in the user interface is not declared here as we do + not need to access it from code. \snippet textfinder/textfinder.h 0 @@ -87,75 +96,83 @@ {Automatic Connection} naming convention required by \c uic. + \section1 Loading the Resources + + We use QFile to load the data from the program resources at runtime. The + code for this is in two method methods on top of \c{textfinder.cpp}: + \c{loadUiFile} and \c{loadTextFile}. + + The \c{loadUiFile} function loads the user interface file previously + created in \l{Qt Designer}. First, the content of the \c{textfinder.ui} + file is loaded from the resource system. Then a QUiLoader instance is + created, and the QUiLoader::load() function is called, with the first + argument being the open file, and the second argument being the pointer of + the widget that should be set as the parent. The created QWidget is + returned. + + \snippet textfinder/textfinder.cpp 4 + + In a similar vein, the \c loadTextFile function loads \c{input.txt} from + the resources. Data is read using QTextStream into a QString with the + QTextStream::readAll() function. We explicitly set the encoding to + \e{UTF-8}, because QTextStream by default uses the current system locale. + Finally, the loaded text is returned. + + \snippet textfinder/textfinder.cpp 5 + \section1 TextFinder Class Implementation - The \c TextFinder class's constructor calls the \c loadUiFile() function - and then uses \c qFindChild() to access the user interface's - \l{QWidget}s. + The \c TextFinder class's constructor does not instantiate any child widgets + directly. Instead, it calls the \c loadUiFile() function, and then uses + QObject::findChild() to locate the created \l{QWidget}s by object name. \snippet textfinder/textfinder.cpp 0 - We then use QMetaObject's system to enable signal and slot connections. + We then use QMetaObject::connectSlotsByName() to enable the automatic + calling of the \c on_findButton_clicked() slot. \snippet textfinder/textfinder.cpp 2 - The loadTextFile() function is called to load \c{input.txt} into - QTextEdit to displays its contents. + The \c loadTextFile function is called to get the text to be shown in the + QTextEdit. \snippet textfinder/textfinder.cpp 3a - The \c{TextFinder}'s layout is set with \l{QWidget::}{setLayout()}. + The dynamically loaded user interface in \c formWidget is now properly set + up. We now embed \c formWidget through a \c QVBoxLayout. \snippet textfinder/textfinder.cpp 3b - Finally, the window title is set to \e {Text Finder} and \c isFirstTime is - set to true. - - \c isFirstTime is used as a flag to indicate whether the search operation - has been performed more than once. This is further explained with the - \c{on_findButton_clicked()} function. + At the end of the constructor we set a window title. - The \c{loadUiFile()} function is used to load the user interface file - previously created in QtDesigner. The QUiLoader class is instantiated - and its \c load() function is used to load the form into \c{formWidget} - that acts as a place holder for the user interface. The function then - returns \c{formWidget} to its caller. - - \snippet textfinder/textfinder.cpp 4 - - As mentioned earlier, the loadTextFile() function loads \e{input.txt} - into QTextEdit to display its contents. Data is read using QTextStream - into a QString object, \c line with the QTextStream::readAll() function. - The contents of \c line are then appended to \c{ui_textEdit}. - - \snippet textfinder/textfinder.cpp 5 + \snippet textfinder/textfinder.cpp 3c The \c{on_findButton_clicked()} function is a slot that is connected to \c{ui_findButton}'s \c clicked() signal. The \c searchString is extracted - from the \c ui_lineEdit and the \c document is extracted from \c textEdit. - In event there is an empty \c searchString, a QMessageBox is used, - requesting the user to enter a word. Otherwise, we traverse through the - words in \c ui_textEdit, and highlight all ocurrences of the - \c searchString . Two QTextCursor objects are used: One to traverse through + from the \c ui_lineEdit and the \c document is extracted from + \c ui_textEdit. If there is an empty \c searchString, a QMessageBox is + used, requesting the user to enter a word. Otherwise, we traverse through + the words in \c ui_textEdit, and highlight all ocurrences of the + \c searchString. Two QTextCursor objects are used: One to traverse through the words in \c line and another to keep track of the edit blocks. \snippet textfinder/textfinder.cpp 7 - The \c isFirstTime flag is set to false the moment \c findButton is - clicked. This is necessary to undo the previous text highlight before - highlighting the user's next search string. Also, the \c found flag - is used to indicate if the \c searchString was found within the contents - of \c ui_textEdit. If it was not found, a QMessageBox is used - to inform the user. + The \c found flag is used to indicate if the \c searchString was found + within the contents of \c ui_textEdit. If it was not found, a QMessageBox + is used to inform the user. \snippet textfinder/textfinder.cpp 9 \section1 \c main() Function + The \c main() function instantiates and shows \c TextFinder. + \snippet textfinder/main.cpp 0 - The \c main() function initialises the \e{textfinder.qrc} resource file - and instantiates as well as displays \c TextFinder. + There are various approaches to include forms into applications. Using + QUILoader is just one of them. See \l{Using a Designer UI File in Your + Application} for more information on the other approaches available. \sa {Calculator Builder Example}, {World Time Clock Builder Example} */ diff --git a/examples/uitools/textfinder/forms/input.txt b/examples/uitools/textfinder/forms/input.txt index 96e8c3047..4dc15ce4e 100644 --- a/examples/uitools/textfinder/forms/input.txt +++ b/examples/uitools/textfinder/forms/input.txt @@ -1,9 +1,3 @@ -These forms are processed at run-time to produce dynamically-generated user interfaces. -In order to generate a form at run-time, a resource file containing a UI file is needed. -Applications that use the form handling classes need to be configured to be built against -the QtUiTools module. This is done by including the following declaration in a qmake project -file to ensure that the application is compiled and linked appropriately. A form loader object, -provided by the QUiLoader class, is used to construct the user interface. This user interface -can be retrieved from any QIODevice; for example, a QFile object can be used to obtain a form -stored in a project's resources. The QUiLoader::load() function takes the user interface -description contained in the file and constructs the form widget.
\ No newline at end of file +This user interface was loaded and processed at run-time. + +Applications that want to load .ui files at run-time must be configured to be link against the QtUiTools module. A form loader object, provided by the QUiLoader class, is used to construct the user interface. This user interface can be retrieved from any QIODevice; for example, a QFile object can be used to obtain a form stored in a project's resources. The QUiLoader::load() function takes the user interface description contained in the file and constructs the form widget. diff --git a/examples/uitools/textfinder/main.cpp b/examples/uitools/textfinder/main.cpp index 9dab51e19..3db26ebe7 100644 --- a/examples/uitools/textfinder/main.cpp +++ b/examples/uitools/textfinder/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. @@ -48,17 +48,16 @@ ** ****************************************************************************/ -#include <QApplication> #include "textfinder.h" +#include <QApplication> //! [0] int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(textfinder); QApplication app(argc, argv); - TextFinder *textFinder = new TextFinder; - textFinder->show(); + TextFinder textFinder; + textFinder.show(); return app.exec(); } diff --git a/examples/uitools/textfinder/textfinder.cpp b/examples/uitools/textfinder/textfinder.cpp index a40be8886..a18505c8c 100644 --- a/examples/uitools/textfinder/textfinder.cpp +++ b/examples/uitools/textfinder/textfinder.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. @@ -48,15 +48,43 @@ ** ****************************************************************************/ -#include <QtUiTools> -#include <QtWidgets> #include "textfinder.h" +#include <QFile> +#include <QLineEdit> +#include <QMessageBox> +#include <QPushButton> +#include <QTextEdit> +#include <QTextStream> +#include <QUiLoader> +#include <QVBoxLayout> + +//! [4] +static QWidget *loadUiFile(QWidget *parent) +{ + QFile file(":/forms/textfinder.ui"); + file.open(QIODevice::ReadOnly); + + QUiLoader loader; + return loader.load(&file, parent); +} +//! [4] + +//! [5] +static QString loadTextFile() +{ + QFile inputFile(":/forms/input.txt"); + inputFile.open(QIODevice::ReadOnly); + QTextStream in(&inputFile); + in.setCodec("UTF-8"); + return in.readAll(); +} +//! [5] //! [0] TextFinder::TextFinder(QWidget *parent) : QWidget(parent) { - QWidget *formWidget = loadUiFile(); + QWidget *formWidget = loadUiFile(this); //! [1] ui_findButton = findChild<QPushButton*>("findButton"); @@ -69,7 +97,7 @@ TextFinder::TextFinder(QWidget *parent) //! [2] //! [3a] - loadTextFile(); + ui_textEdit->setText(loadTextFile()); //! [3a] //! [3b] @@ -80,40 +108,9 @@ TextFinder::TextFinder(QWidget *parent) //! [3c] setWindowTitle(tr("Text Finder")); - isFirstTime = true; } //! [3c] -//! [4] -QWidget* TextFinder::loadUiFile() -{ - QUiLoader loader; - - QFile file(":/forms/textfinder.ui"); - file.open(QFile::ReadOnly); - - QWidget *formWidget = loader.load(&file, this); - file.close(); - - return formWidget; -} -//! [4] - -//! [5] -void TextFinder::loadTextFile() -{ - QFile inputFile(":/forms/input.txt"); - inputFile.open(QIODevice::ReadOnly); - QTextStream in(&inputFile); - QString line = in.readAll(); - inputFile.close(); - - ui_textEdit->append(line); - ui_textEdit->setUndoRedoEnabled(false); - ui_textEdit->setUndoRedoEnabled(true); -} -//! [5] - //! [6] //! [7] void TextFinder::on_findButton_clicked() { @@ -122,14 +119,14 @@ void TextFinder::on_findButton_clicked() bool found = false; - if (isFirstTime == false) - document->undo(); + // undo previous change (if any) + document->undo(); if (searchString.isEmpty()) { QMessageBox::information(this, tr("Empty Search Field"), - "The search field is empty. Please enter a word and click Find."); + tr("The search field is empty. " + "Please enter a word and click Find.")); } else { - QTextCursor highlightCursor(document); QTextCursor cursor(document); @@ -141,12 +138,13 @@ void TextFinder::on_findButton_clicked() colorFormat.setForeground(Qt::red); while (!highlightCursor.isNull() && !highlightCursor.atEnd()) { - highlightCursor = document->find(searchString, highlightCursor, QTextDocument::FindWholeWords); + highlightCursor = document->find(searchString, highlightCursor, + QTextDocument::FindWholeWords); if (!highlightCursor.isNull()) { found = true; highlightCursor.movePosition(QTextCursor::WordRight, - QTextCursor::KeepAnchor); + QTextCursor::KeepAnchor); highlightCursor.mergeCharFormat(colorFormat); } } @@ -154,11 +152,10 @@ void TextFinder::on_findButton_clicked() //! [8] cursor.endEditBlock(); //! [7] //! [9] - isFirstTime = false; if (found == false) { QMessageBox::information(this, tr("Word Not Found"), - "Sorry, the word cannot be found."); + tr("Sorry, the word cannot be found.")); } } } diff --git a/examples/uitools/textfinder/textfinder.h b/examples/uitools/textfinder/textfinder.h index a28defa49..17336d260 100644 --- a/examples/uitools/textfinder/textfinder.h +++ b/examples/uitools/textfinder/textfinder.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. @@ -54,9 +54,9 @@ #include <QWidget> QT_BEGIN_NAMESPACE +class QLineEdit; class QPushButton; class QTextEdit; -class QLineEdit; QT_END_NAMESPACE //! [0] @@ -65,20 +65,16 @@ class TextFinder : public QWidget Q_OBJECT public: - TextFinder(QWidget *parent = 0); + explicit TextFinder(QWidget *parent = nullptr); private slots: void on_findButton_clicked(); private: - QWidget* loadUiFile(); - void loadTextFile(); - QPushButton *ui_findButton; QTextEdit *ui_textEdit; QLineEdit *ui_lineEdit; - bool isFirstTime; }; //! [0] -#endif +#endif // TEXTFINDER_H diff --git a/examples/uitools/textfinder/textfinder.pro b/examples/uitools/textfinder/textfinder.pro index 667711dda..8f66814c4 100644 --- a/examples/uitools/textfinder/textfinder.pro +++ b/examples/uitools/textfinder/textfinder.pro @@ -1,8 +1,10 @@ -HEADERS = textfinder.h -RESOURCES = textfinder.qrc -SOURCES = textfinder.cpp main.cpp +#! [0] +QT += widgets uitools + +HEADERS = textfinder.h +SOURCES = textfinder.cpp main.cpp +RESOURCES = textfinder.qrc +#! [0] target.path = $$[QT_INSTALL_EXAMPLES]/uitools/textfinder INSTALLS += target - -QT += widgets uitools |