From f4b338833e0222db68f37914ecfa21ff11fd718a Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Mon, 15 May 2023 12:08:45 +0200 Subject: Move the addressbook tutorial into manual tests The tutorial is building an elaborate UI around a QMap. It doesn't use structured data, and it doesn't use model/view (which the dedicated addressbook example in itemviews does). It's not a good way of building an application, and the individual APIs for creating layouts, dialogs, or import/export are explained well enough in other examples. Pick-to: 6.5 Change-Id: Iffe47a0f6e04a933edb917c877ae845f50b74b4a Reviewed-by: Axel Spoerl --- examples/widgets/doc/src/addressbook-tutorial.qdoc | 948 --------------------- examples/widgets/tutorials/CMakeLists.txt | 1 - .../widgets/tutorials/addressbook/CMakeLists.txt | 10 - examples/widgets/tutorials/addressbook/README | 40 - .../widgets/tutorials/addressbook/addressbook.pro | 6 - .../tutorials/addressbook/part1/CMakeLists.txt | 37 - .../tutorials/addressbook/part1/addressbook.cpp | 30 - .../tutorials/addressbook/part1/addressbook.h | 29 - .../widgets/tutorials/addressbook/part1/main.cpp | 17 - .../widgets/tutorials/addressbook/part1/part1.pro | 11 - .../tutorials/addressbook/part2/CMakeLists.txt | 37 - .../tutorials/addressbook/part2/addressbook.cpp | 123 --- .../tutorials/addressbook/part2/addressbook.h | 47 - .../widgets/tutorials/addressbook/part2/main.cpp | 17 - .../widgets/tutorials/addressbook/part2/part2.pro | 11 - .../tutorials/addressbook/part3/CMakeLists.txt | 37 - .../tutorials/addressbook/part3/addressbook.cpp | 182 ---- .../tutorials/addressbook/part3/addressbook.h | 49 -- .../widgets/tutorials/addressbook/part3/main.cpp | 15 - .../widgets/tutorials/addressbook/part3/part3.pro | 11 - .../tutorials/addressbook/part4/CMakeLists.txt | 37 - .../tutorials/addressbook/part4/addressbook.cpp | 258 ------ .../tutorials/addressbook/part4/addressbook.h | 62 -- .../widgets/tutorials/addressbook/part4/main.cpp | 15 - .../widgets/tutorials/addressbook/part4/part4.pro | 11 - .../tutorials/addressbook/part5/CMakeLists.txt | 38 - .../tutorials/addressbook/part5/addressbook.cpp | 283 ------ .../tutorials/addressbook/part5/addressbook.h | 65 -- .../tutorials/addressbook/part5/finddialog.cpp | 51 -- .../tutorials/addressbook/part5/finddialog.h | 31 - .../widgets/tutorials/addressbook/part5/main.cpp | 15 - .../widgets/tutorials/addressbook/part5/part5.pro | 13 - .../tutorials/addressbook/part6/CMakeLists.txt | 38 - .../tutorials/addressbook/part6/addressbook.cpp | 366 -------- .../tutorials/addressbook/part6/addressbook.h | 66 -- .../tutorials/addressbook/part6/finddialog.cpp | 47 - .../tutorials/addressbook/part6/finddialog.h | 31 - .../widgets/tutorials/addressbook/part6/main.cpp | 15 - .../widgets/tutorials/addressbook/part6/part6.pro | 14 - .../tutorials/addressbook/part7/CMakeLists.txt | 38 - .../tutorials/addressbook/part7/addressbook.cpp | 419 --------- .../tutorials/addressbook/part7/addressbook.h | 68 -- .../tutorials/addressbook/part7/finddialog.cpp | 47 - .../tutorials/addressbook/part7/finddialog.h | 31 - .../widgets/tutorials/addressbook/part7/main.cpp | 15 - .../widgets/tutorials/addressbook/part7/part7.pro | 14 - examples/widgets/tutorials/tutorials.pro | 2 +- .../addressbook-tutorial-part1-labeled-layout.png | Bin 19114 -> 0 bytes ...dressbook-tutorial-part1-labeled-screenshot.png | Bin 23223 -> 0 bytes .../addressbook-tutorial-part1-screenshot.png | Bin 9872 -> 0 bytes .../addressbook-tutorial-part2-add-contact.png | Bin 12936 -> 0 bytes .../addressbook-tutorial-part2-add-flowchart.png | Bin 23533 -> 0 bytes .../addressbook-tutorial-part2-add-successful.png | Bin 10825 -> 0 bytes .../addressbook-tutorial-part2-labeled-layout.png | Bin 27103 -> 0 bytes ...ddressbook-tutorial-part2-signals-and-slots.png | Bin 9968 -> 0 bytes .../addressbook-tutorial-part2-stretch-effects.png | Bin 12268 -> 0 bytes .../addressbook-tutorial-part3-labeled-layout.png | Bin 27467 -> 0 bytes .../addressbook-tutorial-part3-linkedlist.png | Bin 10209 -> 0 bytes .../addressbook-tutorial-part3-screenshot.png | Bin 14041 -> 0 bytes .../images/addressbook-tutorial-part4-remove.png | Bin 22248 -> 0 bytes .../addressbook-tutorial-part5-finddialog.png | Bin 10046 -> 0 bytes .../images/addressbook-tutorial-part5-notfound.png | Bin 10789 -> 0 bytes .../addressbook-tutorial-part5-screenshot.png | Bin 15849 -> 0 bytes ...ddressbook-tutorial-part5-signals-and-slots.png | Bin 5542 -> 0 bytes .../doc/images/addressbook-tutorial-part6-load.png | Bin 24797 -> 0 bytes .../doc/images/addressbook-tutorial-part6-save.png | Bin 24747 -> 0 bytes .../addressbook-tutorial-part6-screenshot.png | Bin 16819 -> 0 bytes .../addressbook-tutorial-part7-screenshot.png | Bin 18369 -> 0 bytes .../doc/images/addressbook-tutorial-screenshot.png | Bin 15275 -> 0 bytes .../widgets/tutorials/addressbook/CMakeLists.txt | 10 + .../examples/widgets/tutorials/addressbook/README | 40 + .../addressbook-tutorial-part1-labeled-layout.png | Bin 0 -> 19114 bytes ...dressbook-tutorial-part1-labeled-screenshot.png | Bin 0 -> 23223 bytes .../addressbook-tutorial-part1-screenshot.png | Bin 0 -> 9872 bytes .../addressbook-tutorial-part2-add-contact.png | Bin 0 -> 12936 bytes .../addressbook-tutorial-part2-add-flowchart.png | Bin 0 -> 23533 bytes .../addressbook-tutorial-part2-add-successful.png | Bin 0 -> 10825 bytes .../addressbook-tutorial-part2-labeled-layout.png | Bin 0 -> 27103 bytes ...ddressbook-tutorial-part2-signals-and-slots.png | Bin 0 -> 9968 bytes .../addressbook-tutorial-part2-stretch-effects.png | Bin 0 -> 12268 bytes .../addressbook-tutorial-part3-labeled-layout.png | Bin 0 -> 27467 bytes .../addressbook-tutorial-part3-linkedlist.png | Bin 0 -> 10209 bytes .../addressbook-tutorial-part3-screenshot.png | Bin 0 -> 14041 bytes .../addressbook-tutorial-part4-remove.png | Bin 0 -> 22248 bytes .../addressbook-tutorial-part5-finddialog.png | Bin 0 -> 10046 bytes .../addressbook-tutorial-part5-notfound.png | Bin 0 -> 10789 bytes .../addressbook-tutorial-part5-screenshot.png | Bin 0 -> 15849 bytes ...ddressbook-tutorial-part5-signals-and-slots.png | Bin 0 -> 5542 bytes .../addressbook-tutorial-part6-load.png | Bin 0 -> 24797 bytes .../addressbook-tutorial-part6-save.png | Bin 0 -> 24747 bytes .../addressbook-tutorial-part6-screenshot.png | Bin 0 -> 16819 bytes .../addressbook-tutorial-part7-screenshot.png | Bin 0 -> 18369 bytes .../addressbook-tutorial-screenshot.png | Bin 0 -> 15275 bytes .../addressbook/addressbook-tutorial.qdoc | 948 +++++++++++++++++++++ .../widgets/tutorials/addressbook/addressbook.pro | 6 + .../tutorials/addressbook/part1/CMakeLists.txt | 37 + .../tutorials/addressbook/part1/addressbook.cpp | 30 + .../tutorials/addressbook/part1/addressbook.h | 29 + .../widgets/tutorials/addressbook/part1/main.cpp | 17 + .../widgets/tutorials/addressbook/part1/part1.pro | 11 + .../tutorials/addressbook/part2/CMakeLists.txt | 37 + .../tutorials/addressbook/part2/addressbook.cpp | 123 +++ .../tutorials/addressbook/part2/addressbook.h | 47 + .../widgets/tutorials/addressbook/part2/main.cpp | 17 + .../widgets/tutorials/addressbook/part2/part2.pro | 11 + .../tutorials/addressbook/part3/CMakeLists.txt | 37 + .../tutorials/addressbook/part3/addressbook.cpp | 182 ++++ .../tutorials/addressbook/part3/addressbook.h | 49 ++ .../widgets/tutorials/addressbook/part3/main.cpp | 15 + .../widgets/tutorials/addressbook/part3/part3.pro | 11 + .../tutorials/addressbook/part4/CMakeLists.txt | 37 + .../tutorials/addressbook/part4/addressbook.cpp | 258 ++++++ .../tutorials/addressbook/part4/addressbook.h | 62 ++ .../widgets/tutorials/addressbook/part4/main.cpp | 15 + .../widgets/tutorials/addressbook/part4/part4.pro | 11 + .../tutorials/addressbook/part5/CMakeLists.txt | 38 + .../tutorials/addressbook/part5/addressbook.cpp | 283 ++++++ .../tutorials/addressbook/part5/addressbook.h | 65 ++ .../tutorials/addressbook/part5/finddialog.cpp | 51 ++ .../tutorials/addressbook/part5/finddialog.h | 31 + .../widgets/tutorials/addressbook/part5/main.cpp | 15 + .../widgets/tutorials/addressbook/part5/part5.pro | 13 + .../tutorials/addressbook/part6/CMakeLists.txt | 38 + .../tutorials/addressbook/part6/addressbook.cpp | 366 ++++++++ .../tutorials/addressbook/part6/addressbook.h | 66 ++ .../tutorials/addressbook/part6/finddialog.cpp | 47 + .../tutorials/addressbook/part6/finddialog.h | 31 + .../widgets/tutorials/addressbook/part6/main.cpp | 15 + .../widgets/tutorials/addressbook/part6/part6.pro | 14 + .../tutorials/addressbook/part7/CMakeLists.txt | 38 + .../tutorials/addressbook/part7/addressbook.cpp | 419 +++++++++ .../tutorials/addressbook/part7/addressbook.h | 68 ++ .../tutorials/addressbook/part7/finddialog.cpp | 47 + .../tutorials/addressbook/part7/finddialog.h | 31 + .../widgets/tutorials/addressbook/part7/main.cpp | 15 + .../widgets/tutorials/addressbook/part7/part7.pro | 14 + 136 files changed, 3746 insertions(+), 3747 deletions(-) delete mode 100644 examples/widgets/doc/src/addressbook-tutorial.qdoc delete mode 100644 examples/widgets/tutorials/addressbook/CMakeLists.txt delete mode 100644 examples/widgets/tutorials/addressbook/README delete mode 100644 examples/widgets/tutorials/addressbook/addressbook.pro delete mode 100644 examples/widgets/tutorials/addressbook/part1/CMakeLists.txt delete mode 100644 examples/widgets/tutorials/addressbook/part1/addressbook.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part1/addressbook.h delete mode 100644 examples/widgets/tutorials/addressbook/part1/main.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part1/part1.pro delete mode 100644 examples/widgets/tutorials/addressbook/part2/CMakeLists.txt delete mode 100644 examples/widgets/tutorials/addressbook/part2/addressbook.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part2/addressbook.h delete mode 100644 examples/widgets/tutorials/addressbook/part2/main.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part2/part2.pro delete mode 100644 examples/widgets/tutorials/addressbook/part3/CMakeLists.txt delete mode 100644 examples/widgets/tutorials/addressbook/part3/addressbook.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part3/addressbook.h delete mode 100644 examples/widgets/tutorials/addressbook/part3/main.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part3/part3.pro delete mode 100644 examples/widgets/tutorials/addressbook/part4/CMakeLists.txt delete mode 100644 examples/widgets/tutorials/addressbook/part4/addressbook.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part4/addressbook.h delete mode 100644 examples/widgets/tutorials/addressbook/part4/main.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part4/part4.pro delete mode 100644 examples/widgets/tutorials/addressbook/part5/CMakeLists.txt delete mode 100644 examples/widgets/tutorials/addressbook/part5/addressbook.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part5/addressbook.h delete mode 100644 examples/widgets/tutorials/addressbook/part5/finddialog.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part5/finddialog.h delete mode 100644 examples/widgets/tutorials/addressbook/part5/main.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part5/part5.pro delete mode 100644 examples/widgets/tutorials/addressbook/part6/CMakeLists.txt delete mode 100644 examples/widgets/tutorials/addressbook/part6/addressbook.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part6/addressbook.h delete mode 100644 examples/widgets/tutorials/addressbook/part6/finddialog.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part6/finddialog.h delete mode 100644 examples/widgets/tutorials/addressbook/part6/main.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part6/part6.pro delete mode 100644 examples/widgets/tutorials/addressbook/part7/CMakeLists.txt delete mode 100644 examples/widgets/tutorials/addressbook/part7/addressbook.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part7/addressbook.h delete mode 100644 examples/widgets/tutorials/addressbook/part7/finddialog.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part7/finddialog.h delete mode 100644 examples/widgets/tutorials/addressbook/part7/main.cpp delete mode 100644 examples/widgets/tutorials/addressbook/part7/part7.pro delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part1-labeled-layout.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part1-labeled-screenshot.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part1-screenshot.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part2-add-contact.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part2-add-flowchart.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part2-add-successful.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part2-labeled-layout.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part2-signals-and-slots.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part2-stretch-effects.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part3-labeled-layout.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part3-linkedlist.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part3-screenshot.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part4-remove.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part5-finddialog.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part5-notfound.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part5-screenshot.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part5-signals-and-slots.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part6-load.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part6-save.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part6-screenshot.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-part7-screenshot.png delete mode 100644 src/widgets/doc/images/addressbook-tutorial-screenshot.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/CMakeLists.txt create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/README create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-labeled-layout.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-labeled-screenshot.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-screenshot.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-contact.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-flowchart.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-successful.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-labeled-layout.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-signals-and-slots.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-stretch-effects.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-labeled-layout.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-linkedlist.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-screenshot.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part4-remove.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-finddialog.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-notfound.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-screenshot.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-signals-and-slots.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-load.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-save.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-screenshot.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part7-screenshot.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-screenshot.png create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial.qdoc create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/addressbook.pro create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part1/CMakeLists.txt create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part1/addressbook.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part1/addressbook.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part1/main.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part1/part1.pro create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part2/CMakeLists.txt create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part2/addressbook.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part2/addressbook.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part2/main.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part2/part2.pro create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part3/CMakeLists.txt create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part3/addressbook.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part3/addressbook.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part3/main.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part3/part3.pro create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part4/CMakeLists.txt create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part4/addressbook.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part4/addressbook.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part4/main.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part4/part4.pro create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part5/CMakeLists.txt create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part5/addressbook.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part5/addressbook.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part5/finddialog.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part5/finddialog.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part5/main.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part5/part5.pro create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part6/CMakeLists.txt create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part6/addressbook.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part6/addressbook.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part6/finddialog.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part6/finddialog.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part6/main.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part6/part6.pro create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part7/CMakeLists.txt create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part7/addressbook.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part7/addressbook.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part7/finddialog.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part7/finddialog.h create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part7/main.cpp create mode 100644 tests/manual/examples/widgets/tutorials/addressbook/part7/part7.pro diff --git a/examples/widgets/doc/src/addressbook-tutorial.qdoc b/examples/widgets/doc/src/addressbook-tutorial.qdoc deleted file mode 100644 index 2f7884bee8..0000000000 --- a/examples/widgets/doc/src/addressbook-tutorial.qdoc +++ /dev/null @@ -1,948 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \page tutorials-addressbook.html - - \title Address Book Tutorial - \ingroup examples-layout - \brief An introduction to GUI programming, showing how to put together a - simple yet fully-functioning application. - - This tutorial is an introduction to GUI programming with the Qt - cross-platform framework. - - \image addressbook-tutorial-screenshot.png - - \omit - It doesn't cover everything; the emphasis is on teaching the programming - philosophy of GUI programming, and Qt's features are introduced as needed. - Some commonly used features are never used in this tutorial. - \endomit - - In this tutorial, you will learn about some of the basic - components of Qt, including: - - \list - \li Widgets and layout managers - \li Container classes - \li Signals and slots - \li Input and output devices - \endlist - - Tutorial contents: - - \list 1 - \li \l{tutorials/addressbook/part1}{Designing the User Interface} - \li \l{tutorials/addressbook/part2}{Adding Addresses} - \li \l{tutorials/addressbook/part3}{Navigating between Entries} - \li \l{tutorials/addressbook/part4}{Editing and Removing Addresses} - \li \l{tutorials/addressbook/part5}{Adding a Find Function} - \li \l{tutorials/addressbook/part6}{Loading and Saving} - \li \l{tutorials/addressbook/part7}{Additional Features} - \endlist - - The tutorial source code is located in \c{tutorials/addressbook}. - - Although this little application does not look much like a - fully-fledged modern GUI application, it uses many of the basic - elements that are used in more complex applications. After you - have worked through this tutorial, we recommend reading the - \l{mainwindows/application}{Application} example, which presents a - small GUI application, with menus, toolbars, a status bar, and so - on. -*/ - -/*! - \example tutorials/addressbook/part1 - \title Part 1 - Designing the User Interface - \brief Describes how to code the user interface of the Address Book Example. - This first part covers the design of the basic graphical user - interface (GUI) for our address book application. - - The first step in creating a GUI program is to design the user - interface. Here the our goal is to set up the labels and input - fields to implement a basic address book. The figure below is a - screenshot of the expected output. - - \image addressbook-tutorial-part1-screenshot.png - - We require two QLabel objects, \c nameLabel and \c addressLabel, as well - as two input fields, a QLineEdit object, \c nameLine, and a QTextEdit - object, \c addressText, to enable the user to enter a contact's name and - address. The widgets used and their positions are shown in the figure - below. - - \image addressbook-tutorial-part1-labeled-screenshot.png - - There are three files used to implement this address book: - - \list - \li \c{addressbook.h} - the definition file for the \c AddressBook - class, - \li \c{addressbook.cpp} - the implementation file for the - \c AddressBook class, and - \li \c{main.cpp} - the file containing a \c main() function, with - an instance of \c AddressBook. - \endlist - - \section1 Qt Programming - Subclassing - - When writing Qt programs, we usually subclass Qt objects to add - functionality. This is one of the essential concepts behind creating - custom widgets or collections of standard widgets. Subclassing to - extend or change the behavior of a widget has the following advantages: - - \list - \li We can write implementations of virtual or pure virtual functions to - obtain exactly what we need, falling back on the base class's implementation - when necessary. - \li It allows us to encapsulate parts of the user interface within a class, - so that the other parts of the application don't need to know about the - individual widgets in the user interface. - \li The subclass can be used to create multiple custom widgets in the same - application or library, and the code for the subclass can be reused in other - projects. - \endlist - - Since Qt does not provide a specific address book widget, we subclass a - standard Qt widget class and add features to it. The \c AddressBook class - we create in this tutorial can be reused in situations where a basic address - book widget is needed. - - \section1 Defining the AddressBook Class - - The \c{tutorials/addressbook/part1/addressbook.h} file is - used to define the \c AddressBook class. - - We start by defining \c AddressBook as a QWidget subclass and declaring - a constructor. We also use the Q_OBJECT macro to indicate that the class - uses internationalization and Qt's signals and slots features, even - if we do not use all of these features at this stage. - - \snippet tutorials/addressbook/part1/addressbook.h class definition - - The class holds declarations of \c nameLine and \c addressText, - the private instances of QLineEdit and QTextEdit mentioned - earlier. The data stored in \c nameLine and \c addressText will - be needed for many of the address book functions. - - We don't include declarations of the QLabel objects we will use - because we will not need to reference them once they have been - created. The way Qt tracks the ownership of objects is explained - in the next section. - - The Q_OBJECT macro itself implements some of the more advanced features of Qt. - For now, it is useful to think of the Q_OBJECT macro as a shortcut which allows - us to use the \l{QObject::}{tr()} and \l{QObject::}{connect()} functions. - - We have now completed the \c addressbook.h file and we move on to - implement the corresponding \c addressbook.cpp file. - - \section1 Implementing the AddressBook Class - - The constructor of \c AddressBook accepts a QWidget parameter, \a parent. - By convention, we pass this parameter to the base class's constructor. - This concept of ownership, where a parent can have one or more children, - is useful for grouping widgets in Qt. For example, if you delete a parent, - all of its children will be deleted as well. - - \snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields - - In this constructor, the QLabel objects \c nameLabel and \c - addressLabel are instantiated, as well as \c nameLine and \c - addressText. The \l{QObject::tr()}{tr()} function returns a - translated version of the string, if there is one - available. Otherwise it returns the string itself. This function - marks its QString parameter as one that should be translated into - other languages. It should be used wherever a translatable string - appears. - - When programming with Qt, it is useful to know how layouts work. - Qt provides three main layout classes: QHBoxLayout, QVBoxLayout - and QGridLayout to handle the positioning of widgets. - - \image addressbook-tutorial-part1-labeled-layout.png - - We use a QGridLayout to position our labels and input fields in a - structured manner. QGridLayout divides the available space into a grid and - places widgets in the cells we specify with row and column numbers. The - diagram above shows the layout cells and the position of our widgets, and - we specify this arrangement using the following code: - - \snippet tutorials/addressbook/part1/addressbook.cpp layout - - Notice that \c addressLabel is positioned using Qt::AlignTop as an - additional argument. This is to make sure it is not vertically centered in - cell (1,0). For a basic overview on Qt Layouts, refer to the - \l{Layout Management} documentation. - - In order to install the layout object onto the widget, we have to invoke - the widget's \l{QWidget::setLayout()}{setLayout()} function: - - \snippet tutorials/addressbook/part1/addressbook.cpp setting the layout - - Lastly, we set the widget's title to "Simple Address Book". - - \section1 Running the Application - - A separate file, \c main.cpp, is used for the \c main() function. Within - this function, we instantiate a QApplication object, \c app. QApplication - is responsible for various application-wide resources, such as the default - font and cursor, and for running an event loop. Hence, there is always one - QApplication object in every GUI application using Qt. - - \snippet tutorials/addressbook/part1/main.cpp main function - - We construct a new \c AddressBook widget on the stack and invoke - its \l{QWidget::show()}{show()} function to display it. - However, the widget will not be shown until the application's event loop - is started. We start the event loop by calling the application's - \l{QApplication::}{exec()} function; the result returned by this function - is used as the return value from the \c main() function. At this point, - it becomes apparent why we instantiated \c AddressBook on the stack: It - will now go out of scope. Therefore, \c AddressBook and all its child widgets - will be deleted, thus preventing memory leaks. -*/ - -/*! - \example tutorials/addressbook/part2 - \title Part 2 - Adding Addresses - \brief Describes the code for inserting records in the Address Book Example. - - The next step in creating the address book is to implement some - user interactions. - - \image addressbook-tutorial-part2-add-contact.png - - We will provide a push button that the user can click to add a new contact. - Also, some form of data structure is needed to store these contacts in an - organized way. - - \section1 Defining the AddressBook Class - - Now that we have the labels and input fields set up, we add push buttons to - complete the process of adding a contact. This means that our - \c addressbook.h file now has three QPushButton objects declared and three - corresponding public slots. - - \snippet tutorials/addressbook/part2/addressbook.h slots - - A slot is a function that responds to a particular signal. We will discuss - this concept in further detail when implementing the \c AddressBook class. - However, for an overview of Qt's signals and slots concept, you can refer - to the \l{Signals and Slots} document. - - Three QPushButton objects (\c addButton, \c submitButton, and - \c cancelButton) are now included in our private variable declarations, - along with \c nameLine and \c addressText. - - \snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration - - We need a container to store our address book contacts, so that we can - traverse and display them. A QMap object, \c contacts, is used for this - purpose as it holds a key-value pair: the contact's name as the \e key, - and the contact's address as the \e{value}. - - \snippet tutorials/addressbook/part2/addressbook.h remaining private variables - - We also declare two private QString objects, \c oldName and \c oldAddress. - These objects are needed to hold the name and address of the contact that - was last displayed, before the user clicked \uicontrol Add. So, when the user clicks - \uicontrol Cancel, we can revert to displaying the details of the last contact. - - \section1 Implementing the AddressBook Class - - Within the constructor of \c AddressBook, we set the \c nameLine and - \c addressText to read-only, so that we can only display but not edit - existing contact details. - - \dots - \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 1 - \dots - \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 2 - - Then, we instantiate our push buttons: \c addButton, \c submitButton, and - \c cancelButton. - - \snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration - - The \c addButton is displayed by invoking the \l{QPushButton::show()} - {show()} function, while the \c submitButton and \c cancelButton are - hidden by invoking \l{QPushButton::hide()}{hide()}. These two push - buttons will only be displayed when the user clicks \uicontrol Add and this is - handled by the \c addContact() function discussed below. - - \snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots - - We connect the push buttons' \l{QPushButton::clicked()}{clicked()} signal - to their respective slots. The figure below illustrates this. - - \image addressbook-tutorial-part2-signals-and-slots.png - - Next, we arrange our push buttons neatly to the right of our address book - widget, using a QVBoxLayout to line them up vertically. - - \snippet tutorials/addressbook/part2/addressbook.cpp vertical layout - - The \l{QBoxLayout::addStretch()}{addStretch()} function is used to ensure - the push buttons are not evenly spaced, but arranged closer to the top of - the widget. The figure below shows the difference between using - \l{QBoxLayout::addStretch()}{addStretch()} and not using it. - - \image addressbook-tutorial-part2-stretch-effects.png - - We then add \c buttonLayout1 to \c mainLayout, using - \l{QGridLayout::addLayout()}{addLayout()}. This gives us nested layouts - as \c buttonLayout1 is now a child of \c mainLayout. - - \snippet tutorials/addressbook/part2/addressbook.cpp grid layout - - Our layout coordinates now look like this: - - \image addressbook-tutorial-part2-labeled-layout.png - - In the \c addContact() function, we store the last displayed contact - details in \c oldName and \c oldAddress. Then we clear these input - fields and turn off the read-only mode. The focus is set on \c nameLine - and we display \c submitButton and \c cancelButton. - - \snippet tutorials/addressbook/part2/addressbook.cpp addContact - - The \c submitContact() function can be divided into three parts: - - \list 1 - \li We extract the contact's details from \c nameLine and \c addressText - and store them in QString objects. We also validate to make sure that the - user did not click \uicontrol Submit with empty input fields; otherwise, a - QMessageBox is displayed to remind the user for a name and address. - - \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1 - - \li We then proceed to check if the contact already exists. If it does not - exist, we add the contact to \c contacts and we display a QMessageBox to - inform the user that the contact has been added. - - \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2 - - If the contact already exists, again, we display a QMessageBox to inform - the user about this, preventing the user from adding duplicate contacts. - Our \c contacts object is based on key-value pairs of name and address, - hence, we want to ensure that \e key is unique. - - \li Once we have handled both cases mentioned above, we restore the push - buttons to their normal state with the following code: - - \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3 - - \endlist - - The screenshot below shows the QMessageBox object we use to display - information messages to the user. - - \image addressbook-tutorial-part2-add-successful.png - - The \c cancel() function restores the last displayed contact details and - enables \c addButton, as well as hides \c submitButton and - \c cancelButton. - - \snippet tutorials/addressbook/part2/addressbook.cpp cancel - - The general idea behind adding a contact is to give the user the - flexibility to click \uicontrol Submit or \uicontrol Cancel at any time. The flowchart below - further explains this concept: - - \image addressbook-tutorial-part2-add-flowchart.png -*/ - -/*! - \example tutorials/addressbook/part3 - \title Part 3 - Navigating between Entries - \brief Explains the code that enables navigating the contacts. - - The address book is now about half complete. We should add the - capability to navigate the contacts, but first we must - decide what sort of a data structure we need for containing these - contacts. - - In the previous section, we used a QMap of key-value pairs with - the contact's name as the \e key, and the contact's address as the - \e value. This works well for our case. However, in order to - navigate and display each entry, a little bit of enhancement is - needed. - - We enhance the QMap by making it replicate a data structure similar to a - circularly-linked list, where all elements are connected, including the - first element and the last element. The figure below illustrates this data - structure. - - \image addressbook-tutorial-part3-linkedlist.png - - \section1 Defining the AddressBook Class - - To add navigation functions to the address book, we must add two - more slots to the \c AddressBook class: \c next() and \c - previous() to the \c addressbook.h file: - - \snippet tutorials/addressbook/part3/addressbook.h navigation functions - - We also require another two QPushButton objects, so we declare \c nextButton - and \c previousButton as private variables: - - \snippet tutorials/addressbook/part3/addressbook.h navigation pushbuttons - - \section1 Implementing the AddressBook Class - - In the \c AddressBook constructor in \c addressbook.cpp, we instantiate - \c nextButton and \c previousButton and disable them by default. This is - because navigation is only enabled when there is more than one contact - in the address book. - - \snippet tutorials/addressbook/part3/addressbook.cpp navigation pushbuttons - - We then connect these push buttons to their respective slots: - - \snippet tutorials/addressbook/part3/addressbook.cpp connecting navigation signals - - The image below is the expected graphical user interface. - - \image addressbook-tutorial-part3-screenshot.png - - We follow basic conventions for \c next() and \c previous() functions by - placing the \c nextButton on the right and the \c previousButton on the - left. In order to achieve this intuitive layout, we use QHBoxLayout to - place the widgets side-by-side: - - \snippet tutorials/addressbook/part3/addressbook.cpp navigation layout - - The QHBoxLayout object, \c buttonLayout2, is then added to \c mainLayout. - - \snippet tutorials/addressbook/part3/addressbook.cpp adding navigation layout - - The figure below shows the coordinates of the widgets in \c mainLayout. - \image addressbook-tutorial-part3-labeled-layout.png - - Within our \c addContact() function, we have to disable these buttons so - that the user does not attempt to navigate while adding a contact. - - \snippet tutorials/addressbook/part3/addressbook.cpp disabling navigation - - Also, in our \c submitContact() function, we enable the navigation - buttons, \c nextButton and \c previousButton, depending on the size - of \c contacts. As mentioned earlier, navigation is only enabled when - there is more than one contact in the address book. The following lines - of code demonstrates how to do this: - - \snippet tutorials/addressbook/part3/addressbook.cpp enabling navigation - - We also include these lines of code in the \c cancel() function. - - Recall that we intend to emulate a circularly-linked list with our QMap - object, \c contacts. So, in the \c next() function, we obtain an iterator - for \c contacts and then: - - \list - \li If the iterator is not at the end of \c contacts, we increment it - by one. - \li If the iterator is at the end of \c contacts, we move it to the - beginning of \c contacts. This gives us the illusion that our QMap is - working like a circularly-linked list. - \endlist - - \snippet tutorials/addressbook/part3/addressbook.cpp next() function - - Once we have iterated to the correct object in \c contacts, we display - its contents on \c nameLine and \c addressText. - - Similarly, for the \c previous() function, we obtain an iterator for - \c contacts and then: - - \list - \li If the iterator is at the end of \c contacts, we clear the - display and return. - \li If the iterator is at the beginning of \c contacts, we move it to - the end. - \li We then decrement the iterator by one. - \endlist - - \snippet tutorials/addressbook/part3/addressbook.cpp previous() function - - Again, we display the contents of the current object in \c contacts. - -*/ - -/*! - \example tutorials/addressbook/part4 - \title Part 4 - Editing and Removing Addresses - \brief Explains how to add edit and remove functionality. - - Now we look at ways to modify the contents of contacts stored in - the address book. - - \image addressbook-tutorial-screenshot.png - - We now have an address book that not only holds contacts in an - organized manner, but also allows navigation. It would be - convenient to include edit and remove functions so that a - contact's details can be changed when needed. However, this - requires a little improvement, in the form of enums. We defined - two modes: \c{AddingMode} and \c{NavigationMode}, but they were - not defined as enum values. Instead, we enabled and disabled the - corresponding buttons manually, resulting in multiple lines of - repeated code. - - Here we define the \c Mode enum with three different values: - - \list - \li \c{NavigationMode}, - \li \c{AddingMode}, and - \li \c{EditingMode}. - \endlist - - \section1 Defining the AddressBook Class - - The \c addressbook.h file is updated to contain the \c Mode enum: - - \snippet tutorials/addressbook/part4/addressbook.h Mode enum - - We also add two new slots, \c editContact() and \c removeContact(), to - our current list of public slots. - - \snippet tutorials/addressbook/part4/addressbook.h edit and remove slots - - In order to switch between modes, we introduce the \c updateInterface() function - to control the enabling and disabling of all QPushButton objects. We also - add two new push buttons, \c editButton and \c removeButton, for the edit - and remove functions mentioned earlier. - - \snippet tutorials/addressbook/part4/addressbook.h updateInterface() declaration - \dots - \snippet tutorials/addressbook/part4/addressbook.h buttons declaration - \dots - \snippet tutorials/addressbook/part4/addressbook.h mode declaration - - Lastly, we declare \c currentMode to keep track of the enum's current mode. - - \section1 Implementing the AddressBook Class - - We now implement the mode-changing features of the address - book. The \c editButton and \c removeButton are instantiated and - disabled by default. The address book starts with zero contacts - in memory. - - \snippet tutorials/addressbook/part4/addressbook.cpp edit and remove buttons - - These buttons are then connected to their respective slots, \c editContact() - and \c removeContact(), and we add them to \c buttonLayout1. - - \snippet tutorials/addressbook/part4/addressbook.cpp connecting edit and remove - \dots - \snippet tutorials/addressbook/part4/addressbook.cpp adding edit and remove to the layout - - The \c editContact() function stores the contact's old details in - \c oldName and \c oldAddress, before switching the mode to \c EditingMode. - In this mode, the \c submitButton and \c cancelButton are both enabled, - hence, the user can change the contact's details and click either button. - - \snippet tutorials/addressbook/part4/addressbook.cpp editContact() function - - The \c submitContact() function has been divided in two with an \c{if-else} - statement. We check \c currentMode to see if it's in \c AddingMode. If it is, - we proceed with our adding process. - - \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function beginning - \dots - \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part1 - - Otherwise, we check to see if \c currentMode is in \c EditingMode. If it - is, we compare \c oldName with \c name. If the name has changed, we remove - the old contact from \c contacts and insert the newly updated contact. - - \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part2 - - If only the address has changed (i.e., \c oldAddress is not the same as \c address), - we update the contact's address. Lastly, we set \c currentMode to - \c NavigationMode. This is an important step as it re-enables all the - disabled push buttons. - - To remove a contact from the address book, we implement the - \c removeContact() function. This function checks to see if the contact - exists in \c contacts. - - \snippet tutorials/addressbook/part4/addressbook.cpp removeContact() function - - If it does, we display a QMessageBox, to confirm the removal with the - user. Once the user has confirmed, we call \c previous() to ensure that the - user interface shows another contact, and we remove the contact using \l{QMap}'s - \l{QMap::remove()}{remove()} function. As a courtesy, we display a QMessageBox - to inform the user. Both the message boxes used in this function are shown below: - - \image addressbook-tutorial-part4-remove.png - - \section2 Updating the User Interface - - We mentioned the \c updateInterface() function earlier as a means to - enable and disable the push buttons depending on the current mode. - The function updates the current mode according to the \c mode argument - passed to it, assigning it to \c currentMode before checking its value. - - Each of the push buttons is then enabled or disabled, depending on the - current mode. The code for \c AddingMode and \c EditingMode is shown below: - - \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 1 - - For \c NavigationMode, however, we include conditions within the parameters - of the QPushButton::setEnabled() function. This is to ensure that - \c editButton and \c removeButton are enabled when there is at least one - contact in the address book; \c nextButton and \c previousButton are only - enabled when there is more than one contact in the address book. - - \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 2 - - By setting the mode and updating the user interface in the same - function, we avoid the possibility of the user interface getting - out of sync with the internal state of the application. - */ - -/*! - \example tutorials/addressbook/part5 - \title Part 5 - Adding a Find Function - \brief Describes how to add a find function. - - Here we look at ways to locate contacts and addresses in the - address book. - - \image addressbook-tutorial-part5-screenshot.png - - As we add contacts to our address book, it becomes tedious to - navigate the list with the \e Next and \e Previous buttons. A \e - Find function would be more efficient. The screenshot above shows - the \e Find button and its position on the panel of buttons. - - When the user clicks on the \e Find button, it is useful to - display a dialog that prompts for a contact's name. Qt provides - QDialog, which we subclass here to implement a \c FindDialog - class. - - \section1 Defining the FindDialog Class - - \image addressbook-tutorial-part5-finddialog.png - - In order to subclass QDialog, we first include the header for QDialog in - the \c finddialog.h file. Also, we use forward declaration to declare - QLineEdit and QPushButton since we will be using those widgets in our - dialog class. - - As in our \c AddressBook class, the \c FindDialog class includes - the Q_OBJECT macro and its constructor is defined to accept a parent - QWidget, even though the dialog will be opened as a separate window. - - \snippet tutorials/addressbook/part5/finddialog.h FindDialog header - - We define a public function, \c getFindText(), to be used by classes that - instantiate \c FindDialog. This function allows these classes to obtain the - search string entered by the user. A public slot, \c findClicked(), is also - defined to handle the search string when the user clicks the \uicontrol Find - button. - - Lastly, we define the private variables, \c findButton, \c lineEdit - and \c findText, corresponding to the \uicontrol Find button, the line edit - into which the user types the search string, and an internal string - used to store the search string for later use. - - \section1 Implementing the FindDialog Class - - Within the constructor of \c FindDialog, we set up the private variables, - \c lineEdit, \c findButton and \c findText. We use a QHBoxLayout to - position the widgets. - - \snippet tutorials/addressbook/part5/finddialog.cpp constructor - - We set the layout and window title, as well as connect the signals to their - respective slots. Notice that \c{findButton}'s \l{QPushButton::clicked()} - {clicked()} signal is connected to \c findClicked() and - \l{QDialog::accept()}{accept()}. The \l{QDialog::accept()}{accept()} slot - provided by QDialog hides the dialog and sets the result code to - \l{QDialog::}{Accepted}. We use this function to help \c{AddressBook}'s - \c findContact() function know when the \c FindDialog object has been - closed. We will explain this logic in further detail when discussing the - \c findContact() function. - - \image addressbook-tutorial-part5-signals-and-slots.png - - In \c findClicked(), we validate \c lineEdit to ensure that the user - did not click the \uicontrol Find button without entering a contact's name. Then, we set - \c findText to the search string, extracted from \c lineEdit. After that, - we clear the contents of \c lineEdit and hide the dialog. - - \snippet tutorials/addressbook/part5/finddialog.cpp findClicked() function - - The \c findText variable has a public getter function, \c getFindText(), - associated with it. Since we only ever set \c findText directly in both the - constructor and in the \c findClicked() function, we do not create a - setter function to accompany \c getFindText(). - Because \c getFindText() is public, classes instantiating and using - \c FindDialog can always access the search string that the user has - entered and accepted. - - \snippet tutorials/addressbook/part5/finddialog.cpp getFindText() function - - \section1 Defining the AddressBook Class - - To ensure we can use \c FindDialog from within our \c AddressBook class, we - include \c finddialog.h in the \c addressbook.h file. - - \snippet tutorials/addressbook/part5/addressbook.h include finddialog's header - - So far, all our address book features have a QPushButton and a - corresponding slot. Similarly, for the \uicontrol Find feature we have - \c findButton and \c findContact(). - - The \c findButton is declared as a private variable and the - \c findContact() function is declared as a public slot. - - \snippet tutorials/addressbook/part5/addressbook.h findContact() declaration - \dots - \snippet tutorials/addressbook/part5/addressbook.h findButton declaration - - Lastly, we declare the private variable, \c dialog, which we will use to - refer to an instance of \c FindDialog. - - \snippet tutorials/addressbook/part5/addressbook.h FindDialog declaration - - Once we have instantiated a dialog, we will want to use it more than once; - using a private variable allows us to refer to it from more than one place - in the class. - - \section1 Implementing the AddressBook Class - - Within the \c AddressBook class's constructor, we instantiate our private - objects, \c findButton and \c findDialog: - - \snippet tutorials/addressbook/part5/addressbook.cpp instantiating findButton - \dots - \snippet tutorials/addressbook/part5/addressbook.cpp instantiating FindDialog - - Next, we connect the \c{findButton}'s - \l{QPushButton::clicked()}{clicked()} signal to \c findContact(). - - \snippet tutorials/addressbook/part5/addressbook.cpp signals and slots for find - - Now all that is left is the code for our \c findContact() function: - - \snippet tutorials/addressbook/part5/addressbook.cpp findContact() function - - We start out by displaying the \c FindDialog instance, \c dialog. This is - when the user enters a contact name to look up. Once the user clicks - the dialog's \c findButton, the dialog is hidden and the result code is - set to QDialog::Accepted. This ensures that - our \c if statement is always true. - - We then proceed to extract the search string, which in this case is - \c contactName, using \c{FindDialog}'s \c getFindText() function. If the - contact exists in our address book, we display it immediately. Otherwise, - we display the QMessageBox shown below to indicate that their search - failed. - - \image addressbook-tutorial-part5-notfound.png -*/ - -/*! - \example tutorials/addressbook/part6 - \title Part 6 - Loading and Saving - \brief Describes how to add save and load functionality. - - This part covers the Qt file handling features we use to write - loading and saving routines for the address book. - - \image addressbook-tutorial-part6-screenshot.png - - Although browsing and searching the contact list are useful - features, our address book is not complete until we can save - existing contacts and load them again at a later time. - - Qt provides a number of classes for \l{Input/Output and Networking} - {input and output}, but we have chosen to use two which are simple to use - in combination: QFile and QDataStream. - - A QFile object represents a file on disk that can be read from and written - to. QFile is a subclass of the more general QIODevice class which - represents many different kinds of devices. - - A QDataStream object is used to serialize binary data so that it can be - stored in a QIODevice and retrieved again later. Reading from a QIODevice - and writing to it is as simple as opening the stream - with the respective - device as a parameter - and reading from or writing to it. - - - \section1 Defining the AddressBook Class - - We declare two public slots, \c saveToFile() and \c loadFromFile(), as well - as two QPushButton objects, \c loadButton and \c saveButton. - - \snippet tutorials/addressbook/part6/addressbook.h save and load functions declaration - \dots - \snippet tutorials/addressbook/part6/addressbook.h save and load buttons declaration - - \section1 Implementing the AddressBook Class - - In our constructor, we instantiate \c loadButton and \c saveButton. - Ideally, it would be more user-friendly to set the push buttons' labels - to "Load contacts from a file" and "Save contacts to a file". However, due - to the size of our other push buttons, we set the labels to \uicontrol{Load...} - and \uicontrol{Save...}. Fortunately, Qt provides a simple way to set tooltips with - \l{QWidget::setToolTip()}{setToolTip()} and we use it in the following way - for our push buttons: - - \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 1 - \dots - \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 2 - - Although it is not shown here, just like the other features we implemented, - we add the push buttons to the layout panel on the right, \c buttonLayout1, - and we connect the push buttons' \l{QPushButton::clicked()}{clicked()} - signals to their respective slots. - - For the saving feature, we first obtain \c fileName using - QFileDialog::getSaveFileName(). This is a convenience function provided - by QFileDialog, which pops up a modal file dialog and allows the user to - enter a file name or select any existing \c{.abk} file. The \c{.abk} file - is our Address Book extension that we create when we save contacts. - - \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part1 - - The file dialog that pops up is displayed in the screenshot below: - - \image addressbook-tutorial-part6-save.png - - If \c fileName is not empty, we create a QFile object, \c file, with - \c fileName. QFile works with QDataStream as QFile is a QIODevice. - - Next, we attempt to open the file in \l{QIODeviceBase::}{WriteOnly} mode. - If this is unsuccessful, we display a QMessageBox to inform the user. - - \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part2 - - Otherwise, we instantiate a QDataStream object, \c out, to write the open - file. QDataStream requires that the same version of the stream is used - for reading and writing. We ensure that this is the case by setting the - version used to the \l{QDataStream::Qt_4_5}{version introduced with Qt 4.5} - before serializing the data to \c file. - - \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part3 - - For the loading feature, we also obtain \c fileName using - QFileDialog::getOpenFileName(). This function, the counterpart to - QFileDialog::getSaveFileName(), also pops up the modal file dialog and - allows the user to enter a file name or select any existing \c{.abk} file - to load it into the address book. - - \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part1 - - On Windows, for example, this function pops up a native file dialog, as - shown in the following screenshot. - - \image addressbook-tutorial-part6-load.png - - If \c fileName is not empty, again, we use a QFile object, \c file, and - attempt to open it in \l{QIODeviceBase::}{ReadOnly} mode. Similar to our - implementation of \c saveToFile(), if this attempt is unsuccessful, we - display a QMessageBox to inform the user. - - \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part2 - - Otherwise, we instantiate a QDataStream object, \c in, set its version as - above and read the serialized data into the \c contacts data structure. - The \c contacts object is emptied before data is read into it to simplify - the file reading process. A more advanced method would be to read the - contacts into a temporary QMap object, and copy over non-duplicate contacts - into \c contacts. - - \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part3 - - To display the contacts that have been read from the file, we must first - validate the data obtained to ensure that the file we read from actually - contains address book contacts. If it does, we display the first contact; - otherwise, we display a QMessageBox to inform the user about the problem. - Lastly, we update the interface to enable and disable the push buttons - accordingly. -*/ - -/*! - \example tutorials/addressbook/part7 - \title Part 7 - Additional Features - \brief Describes how to export data in VCard format. - - This part covers some additional features that make the address - book more convenient for the frequent user. - - \image addressbook-tutorial-part7-screenshot.png - - Although our address book is useful in isolation, it would be - better if we could exchange contact data with other applications. - The vCard format is a popular file format that can be used for - this purpose. Here we extend our address book client to allow - contacts to be exported to vCard \c{.vcf} files. - - \section1 Defining the AddressBook Class - - We add a QPushButton object, \c exportButton, and a corresponding public - slot, \c exportAsVCard() to our \c AddressBook class in the - \c addressbook.h file. - - \snippet tutorials/addressbook/part7/addressbook.h exportAsVCard() declaration - \dots - \snippet tutorials/addressbook/part7/addressbook.h exportButton declaration - - \section1 Implementing the AddressBook Class - - Within the \c AddressBook constructor, we connect \c{exportButton}'s - \l{QPushButton::clicked()}{clicked()} signal to \c exportAsVCard(). - We also add this button to our \c buttonLayout1, the layout responsible - for our panel of buttons on the right. - - In our \c exportAsVCard() function, we start by extracting the contact's - name into \c name. We declare \c firstName, \c lastName and \c nameList. - Next, we look for the index of the first white space in \c name. If there - is a white space, we split the contact's name into \c firstName and - \c lastName. Then, we replace the space with an underscore ("_"). - Alternately, if there is no white space, we assume that the contact only - has a first name. - - \snippet tutorials/addressbook/part7/addressbook.cpp export function part1 - - As with the \c saveToFile() function, we open a file dialog to let the user - choose a location for the file. Using the file name chosen, we create an - instance of QFile to write to. - - We attempt to open the file in \l{QIODeviceBase::}{WriteOnly} mode. If this - process fails, we display a QMessageBox to inform the user about the - problem and return. Otherwise, we pass the file as a parameter to a - QTextStream object, \c out. Like QDataStream, the QTextStream class - provides functionality to read and write plain text to files. As a result, - the \c{.vcf} file generated can be opened for editing in a text editor. - - \snippet tutorials/addressbook/part7/addressbook.cpp export function part2 - - We then write out a vCard file with the \c{BEGIN:VCARD} tag, followed by - the \c{VERSION:2.1} tag. The contact's name is written with the \c{N:} - tag. For the \c{FN:} tag, which fills in the "File as" property of a vCard, - we have to check whether the contact has a last name or not. If the contact - does, we use the details in \c nameList to fill it. Otherwise, we write - \c firstName only. - - \snippet tutorials/addressbook/part7/addressbook.cpp export function part3 - - We proceed to write the contact's address. The semicolons in the address - are escaped with "\\", the newlines are replaced with semicolons, and the - commas are replaced with spaces. Lastly, we write the \c{ADR;HOME:;} - tag, followed by \c address and then the \c{END:VCARD} tag. - - \snippet tutorials/addressbook/part7/addressbook.cpp export function part4 - - In the end, a QMessageBox is displayed to inform the user that the vCard - has been successfully exported. - - \e{vCard is a trademark of the \l{http://www.imc.org} - {Internet Mail Consortium}}. -*/ diff --git a/examples/widgets/tutorials/CMakeLists.txt b/examples/widgets/tutorials/CMakeLists.txt index 02d196db90..6aef3f657b 100644 --- a/examples/widgets/tutorials/CMakeLists.txt +++ b/examples/widgets/tutorials/CMakeLists.txt @@ -1,7 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -add_subdirectory(addressbook) add_subdirectory(widgets) add_subdirectory(modelview) add_subdirectory(gettingStarted) diff --git a/examples/widgets/tutorials/addressbook/CMakeLists.txt b/examples/widgets/tutorials/addressbook/CMakeLists.txt deleted file mode 100644 index c33e586df9..0000000000 --- a/examples/widgets/tutorials/addressbook/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -qt_internal_add_example(part1) -qt_internal_add_example(part2) -qt_internal_add_example(part3) -qt_internal_add_example(part4) -qt_internal_add_example(part5) -qt_internal_add_example(part6) -qt_internal_add_example(part7) diff --git a/examples/widgets/tutorials/addressbook/README b/examples/widgets/tutorials/addressbook/README deleted file mode 100644 index 07897b9683..0000000000 --- a/examples/widgets/tutorials/addressbook/README +++ /dev/null @@ -1,40 +0,0 @@ -The Address Book Tutorial shows how to put together a simple yet -fully-functioning GUI application. The tutorial chapters can be found in the -Qt documentation, which can be viewed using Qt Assistant or a Web browser. - -The tutorial is also available online at - -http://qt-project.org/doc/qt-5.0/qtwidgets/tutorials-addressbook.html - -All programs corresponding to the chapters in the tutorial should -automatically be built when Qt is compiled, or will be provided as -pre-built executables if you have obtained a binary package of Qt. - -If you have only compiled the Qt libraries, use the following instructions -to build the tutorial. - -On Linux/Unix: - -Typing 'make' in this directory builds all the programs (part1/part1, -part2/part2, part3/part3 and so on). Typing 'make' in each subdirectory -builds just that tutorial program. - -On Windows: - -Create a single Visual Studio project for the tutorial directory in -the usual way. You can do this by typing the following at the command -line: - -qmake -tp vc - -You should now be able to open the project file in Visual Studio and -build all of the tutorial programs at the same time. - -On Mac OS X: - -Create an Xcode project with the .pro file in the tutorial directory. -You can do this by typing the following at the command line: - -qmake -spec macx-xcode - -Then open the generated Xcode project in Xcode and build it. diff --git a/examples/widgets/tutorials/addressbook/addressbook.pro b/examples/widgets/tutorials/addressbook/addressbook.pro deleted file mode 100644 index d31424998e..0000000000 --- a/examples/widgets/tutorials/addressbook/addressbook.pro +++ /dev/null @@ -1,6 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = part1 part2 part3 part4 part5 part6 part7 - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook -INSTALLS += target diff --git a/examples/widgets/tutorials/addressbook/part1/CMakeLists.txt b/examples/widgets/tutorials/addressbook/part1/CMakeLists.txt deleted file mode 100644 index 9d3fd8ce07..0000000000 --- a/examples/widgets/tutorials/addressbook/part1/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(part1 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part1") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(part1 - addressbook.cpp addressbook.h - main.cpp -) - -set_target_properties(part1 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(part1 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS part1 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/addressbook/part1/addressbook.cpp b/examples/widgets/tutorials/addressbook/part1/addressbook.cpp deleted file mode 100644 index eae818dbbf..0000000000 --- a/examples/widgets/tutorials/addressbook/part1/addressbook.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -//! [constructor and input fields] -AddressBook::AddressBook(QWidget *parent) - : QWidget(parent) -{ - QLabel *nameLabel = new QLabel(tr("Name:")); - nameLine = new QLineEdit; - - QLabel *addressLabel = new QLabel(tr("Address:")); - addressText = new QTextEdit; -//! [constructor and input fields] - -//! [layout] - QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(nameLabel, 0, 0); - mainLayout->addWidget(nameLine, 0, 1); - mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); - mainLayout->addWidget(addressText, 1, 1); -//! [layout] - -//![setting the layout] - setLayout(mainLayout); - setWindowTitle(tr("Simple Address Book")); -} -//! [setting the layout] diff --git a/examples/widgets/tutorials/addressbook/part1/addressbook.h b/examples/widgets/tutorials/addressbook/part1/addressbook.h deleted file mode 100644 index f2e28b4135..0000000000 --- a/examples/widgets/tutorials/addressbook/part1/addressbook.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef ADDRESSBOOK_H -#define ADDRESSBOOK_H - -#include - -QT_BEGIN_NAMESPACE -class QLabel; -class QLineEdit; -class QTextEdit; -QT_END_NAMESPACE - -//! [class definition] -class AddressBook : public QWidget -{ - Q_OBJECT - -public: - AddressBook(QWidget *parent = nullptr); - -private: - QLineEdit *nameLine; - QTextEdit *addressText; -}; -//! [class definition] - -#endif diff --git a/examples/widgets/tutorials/addressbook/part1/main.cpp b/examples/widgets/tutorials/addressbook/part1/main.cpp deleted file mode 100644 index 879fb606a2..0000000000 --- a/examples/widgets/tutorials/addressbook/part1/main.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -//! [main function] -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - AddressBook addressBook; - addressBook.show(); - - return app.exec(); -} -//! [main function] diff --git a/examples/widgets/tutorials/addressbook/part1/part1.pro b/examples/widgets/tutorials/addressbook/part1/part1.pro deleted file mode 100644 index 35d4a0152e..0000000000 --- a/examples/widgets/tutorials/addressbook/part1/part1.pro +++ /dev/null @@ -1,11 +0,0 @@ -QT += widgets - -SOURCES = addressbook.cpp \ - main.cpp -HEADERS = addressbook.h - -QMAKE_PROJECT_NAME = ab_part1 - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part1 -INSTALLS += target diff --git a/examples/widgets/tutorials/addressbook/part2/CMakeLists.txt b/examples/widgets/tutorials/addressbook/part2/CMakeLists.txt deleted file mode 100644 index 35bd202f9a..0000000000 --- a/examples/widgets/tutorials/addressbook/part2/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(part2 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part2") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(part2 - addressbook.cpp addressbook.h - main.cpp -) - -set_target_properties(part2 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(part2 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS part2 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/addressbook/part2/addressbook.cpp b/examples/widgets/tutorials/addressbook/part2/addressbook.cpp deleted file mode 100644 index 085103c791..0000000000 --- a/examples/widgets/tutorials/addressbook/part2/addressbook.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -AddressBook::AddressBook(QWidget *parent) - : QWidget(parent) -{ - QLabel *nameLabel = new QLabel(tr("Name:")); - nameLine = new QLineEdit; -//! [setting readonly 1] - nameLine->setReadOnly(true); -//! [setting readonly 1] - QLabel *addressLabel = new QLabel(tr("Address:")); - addressText = new QTextEdit; -//! [setting readonly 2] - addressText->setReadOnly(true); -//! [setting readonly 2] - -//! [pushbutton declaration] - addButton = new QPushButton(tr("&Add")); - addButton->show(); - submitButton = new QPushButton(tr("&Submit")); - submitButton->hide(); - cancelButton = new QPushButton(tr("&Cancel")); - cancelButton->hide(); -//! [pushbutton declaration] -//! [connecting signals and slots] - connect(addButton, &QPushButton::clicked, - this, &AddressBook::addContact); - connect(submitButton, &QPushButton::clicked, - this, &AddressBook::submitContact); - connect(cancelButton, &QPushButton::clicked, - this, &AddressBook::cancel); -//! [connecting signals and slots] -//! [vertical layout] - QVBoxLayout *buttonLayout1 = new QVBoxLayout; - buttonLayout1->addWidget(addButton, Qt::AlignTop); - buttonLayout1->addWidget(submitButton); - buttonLayout1->addWidget(cancelButton); - buttonLayout1->addStretch(); -//! [vertical layout] -//! [grid layout] - QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(nameLabel, 0, 0); - mainLayout->addWidget(nameLine, 0, 1); - mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); - mainLayout->addWidget(addressText, 1, 1); - mainLayout->addLayout(buttonLayout1, 1, 2); -//! [grid layout] - setLayout(mainLayout); - setWindowTitle(tr("Simple Address Book")); -} -//! [addContact] -void AddressBook::addContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - nameLine->clear(); - addressText->clear(); - - nameLine->setReadOnly(false); - nameLine->setFocus(Qt::OtherFocusReason); - addressText->setReadOnly(false); - - addButton->setEnabled(false); - submitButton->show(); - cancelButton->show(); -} -//! [addContact] - -//! [submitContact part1] -void AddressBook::submitContact() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (name.isEmpty() || address.isEmpty()) { - QMessageBox::information(this, tr("Empty Field"), - tr("Please enter a name and address.")); - return; - } -//! [submitContact part1] -//! [submitContact part2] - if (!contacts.contains(name)) { - contacts.insert(name, address); - QMessageBox::information(this, tr("Add Successful"), - tr("\"%1\" has been added to your address book.").arg(name)); - } else { - QMessageBox::information(this, tr("Add Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - return; - } -//! [submitContact part2] -//! [submitContact part3] - if (contacts.isEmpty()) { - nameLine->clear(); - addressText->clear(); - } - - nameLine->setReadOnly(true); - addressText->setReadOnly(true); - addButton->setEnabled(true); - submitButton->hide(); - cancelButton->hide(); -} -//! [submitContact part3] -//! [cancel] -void AddressBook::cancel() -{ - nameLine->setText(oldName); - nameLine->setReadOnly(true); - - addressText->setText(oldAddress); - addressText->setReadOnly(true); - - addButton->setEnabled(true); - submitButton->hide(); - cancelButton->hide(); -} -//! [cancel] diff --git a/examples/widgets/tutorials/addressbook/part2/addressbook.h b/examples/widgets/tutorials/addressbook/part2/addressbook.h deleted file mode 100644 index ecc1a71cee..0000000000 --- a/examples/widgets/tutorials/addressbook/part2/addressbook.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef ADDRESSBOOK_H -#define ADDRESSBOOK_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QLabel; -class QLineEdit; -class QPushButton; -class QTextEdit; -QT_END_NAMESPACE - -class AddressBook : public QWidget -{ - Q_OBJECT - -public: - AddressBook(QWidget *parent = nullptr); - -//! [slots] -public slots: - void addContact(); - void submitContact(); - void cancel(); -//! [slots] - -//! [pushbutton declaration] -private: - QPushButton *addButton; - QPushButton *submitButton; - QPushButton *cancelButton; - QLineEdit *nameLine; - QTextEdit *addressText; -//! [pushbutton declaration] - -//! [remaining private variables] - QMap contacts; - QString oldName; - QString oldAddress; -}; -//! [remaining private variables] - -#endif diff --git a/examples/widgets/tutorials/addressbook/part2/main.cpp b/examples/widgets/tutorials/addressbook/part2/main.cpp deleted file mode 100644 index 879fb606a2..0000000000 --- a/examples/widgets/tutorials/addressbook/part2/main.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -//! [main function] -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - AddressBook addressBook; - addressBook.show(); - - return app.exec(); -} -//! [main function] diff --git a/examples/widgets/tutorials/addressbook/part2/part2.pro b/examples/widgets/tutorials/addressbook/part2/part2.pro deleted file mode 100644 index 643ffcfebd..0000000000 --- a/examples/widgets/tutorials/addressbook/part2/part2.pro +++ /dev/null @@ -1,11 +0,0 @@ -QT += widgets - -SOURCES = addressbook.cpp \ - main.cpp -HEADERS = addressbook.h - -QMAKE_PROJECT_NAME = ab_part2 - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part2 -INSTALLS += target diff --git a/examples/widgets/tutorials/addressbook/part3/CMakeLists.txt b/examples/widgets/tutorials/addressbook/part3/CMakeLists.txt deleted file mode 100644 index 04c1779485..0000000000 --- a/examples/widgets/tutorials/addressbook/part3/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(part3 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part3") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(part3 - addressbook.cpp addressbook.h - main.cpp -) - -set_target_properties(part3 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(part3 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS part3 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/addressbook/part3/addressbook.cpp b/examples/widgets/tutorials/addressbook/part3/addressbook.cpp deleted file mode 100644 index 1b37e56880..0000000000 --- a/examples/widgets/tutorials/addressbook/part3/addressbook.cpp +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -AddressBook::AddressBook(QWidget *parent) - : QWidget(parent) -{ - QLabel *nameLabel = new QLabel(tr("Name:")); - nameLine = new QLineEdit; - nameLine->setReadOnly(true); - - QLabel *addressLabel = new QLabel(tr("Address:")); - addressText = new QTextEdit; - addressText->setReadOnly(true); - - addButton = new QPushButton(tr("&Add")); - addButton->show(); - submitButton = new QPushButton(tr("&Submit")); - submitButton->hide(); - cancelButton = new QPushButton(tr("&Cancel")); - cancelButton->hide(); -//! [navigation pushbuttons] - nextButton = new QPushButton(tr("&Next")); - nextButton->setEnabled(false); - previousButton = new QPushButton(tr("&Previous")); - previousButton->setEnabled(false); -//! [navigation pushbuttons] - connect(addButton, &QPushButton::clicked, - this, &AddressBook::addContact); - connect(submitButton, &QPushButton::clicked, - this, &AddressBook::submitContact); - connect(cancelButton, &QPushButton::clicked, - this, &AddressBook::cancel); -//! [connecting navigation signals] - connect(nextButton, &QPushButton::clicked, - this, &AddressBook::next); - connect(previousButton, &QPushButton::clicked, - this, &AddressBook::previous); -//! [connecting navigation signals] - - QVBoxLayout *buttonLayout1 = new QVBoxLayout; - buttonLayout1->addWidget(addButton, Qt::AlignTop); - buttonLayout1->addWidget(submitButton); - buttonLayout1->addWidget(cancelButton); - buttonLayout1->addStretch(); -//! [navigation layout] - QHBoxLayout *buttonLayout2 = new QHBoxLayout; - buttonLayout2->addWidget(previousButton); - buttonLayout2->addWidget(nextButton); -//! [ navigation layout] - QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(nameLabel, 0, 0); - mainLayout->addWidget(nameLine, 0, 1); - mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); - mainLayout->addWidget(addressText, 1, 1); - mainLayout->addLayout(buttonLayout1, 1, 2); -//! [adding navigation layout] - mainLayout->addLayout(buttonLayout2, 2, 1); -//! [adding navigation layout] - setLayout(mainLayout); - setWindowTitle(tr("Simple Address Book")); -} - -void AddressBook::addContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - nameLine->clear(); - addressText->clear(); - - nameLine->setReadOnly(false); - nameLine->setFocus(Qt::OtherFocusReason); - addressText->setReadOnly(false); - - addButton->setEnabled(false); -//! [disabling navigation] - nextButton->setEnabled(false); - previousButton->setEnabled(false); -//! [disabling navigation] - submitButton->show(); - cancelButton->show(); -} - -void AddressBook::submitContact() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (name.isEmpty() || address.isEmpty()) { - QMessageBox::information(this, tr("Empty Field"), - tr("Please enter a name and address.")); - return; - } - - if (!contacts.contains(name)) { - contacts.insert(name, address); - QMessageBox::information(this, tr("Add Successful"), - tr("\"%1\" has been added to your address book.").arg(name)); - } else { - QMessageBox::information(this, tr("Add Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - } - - if (contacts.isEmpty()) { - nameLine->clear(); - addressText->clear(); - } - - nameLine->setReadOnly(true); - addressText->setReadOnly(true); - addButton->setEnabled(true); - -//! [enabling navigation] - int number = contacts.size(); - nextButton->setEnabled(number > 1); - previousButton->setEnabled(number > 1); -//! [enabling navigation] - submitButton->hide(); - cancelButton->hide(); -} - -void AddressBook::cancel() -{ - nameLine->setText(oldName); - addressText->setText(oldAddress); - - if (contacts.isEmpty()) { - nameLine->clear(); - addressText->clear(); - } - - nameLine->setReadOnly(true); - addressText->setReadOnly(true); - addButton->setEnabled(true); - - int number = contacts.size(); - nextButton->setEnabled(number > 1); - previousButton->setEnabled(number > 1); - - submitButton->hide(); - cancelButton->hide(); -} - -//! [next() function] -void AddressBook::next() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i != contacts.end()) - i++; - - if (i == contacts.end()) - i = contacts.begin(); - - nameLine->setText(i.key()); - addressText->setText(i.value()); -} -//! [next() function] -//! [previous() function] -void AddressBook::previous() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i == contacts.end()){ - nameLine->clear(); - addressText->clear(); - return; - } - - if (i == contacts.begin()) - i = contacts.end(); - - i--; - nameLine->setText(i.key()); - addressText->setText(i.value()); -} -//! [previous() function] diff --git a/examples/widgets/tutorials/addressbook/part3/addressbook.h b/examples/widgets/tutorials/addressbook/part3/addressbook.h deleted file mode 100644 index 0e3aea1e05..0000000000 --- a/examples/widgets/tutorials/addressbook/part3/addressbook.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef ADDRESSBOOK_H -#define ADDRESSBOOK_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QLabel; -class QLineEdit; -class QPushButton; -class QTextEdit; -QT_END_NAMESPACE - -class AddressBook : public QWidget -{ - Q_OBJECT - -public: - AddressBook(QWidget *parent = nullptr); - -public slots: - void addContact(); - void submitContact(); - void cancel(); -//! [navigation functions] - void next(); - void previous(); -//! [navigation functions] - -private: - QPushButton *addButton; - QPushButton *submitButton; - QPushButton *cancelButton; -//! [navigation pushbuttons] - QPushButton *nextButton; - QPushButton *previousButton; -//! [navigation pushbuttons] - QLineEdit *nameLine; - QTextEdit *addressText; - - QMap contacts; - QString oldName; - QString oldAddress; -}; - -#endif diff --git a/examples/widgets/tutorials/addressbook/part3/main.cpp b/examples/widgets/tutorials/addressbook/part3/main.cpp deleted file mode 100644 index 1f3aac3397..0000000000 --- a/examples/widgets/tutorials/addressbook/part3/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - AddressBook addressBook; - addressBook.show(); - - return app.exec(); -} diff --git a/examples/widgets/tutorials/addressbook/part3/part3.pro b/examples/widgets/tutorials/addressbook/part3/part3.pro deleted file mode 100644 index 3bacdd9501..0000000000 --- a/examples/widgets/tutorials/addressbook/part3/part3.pro +++ /dev/null @@ -1,11 +0,0 @@ -QT += widgets - -SOURCES = addressbook.cpp \ - main.cpp -HEADERS = addressbook.h - -QMAKE_PROJECT_NAME = ab_part3 - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part3 -INSTALLS += target diff --git a/examples/widgets/tutorials/addressbook/part4/CMakeLists.txt b/examples/widgets/tutorials/addressbook/part4/CMakeLists.txt deleted file mode 100644 index 65289e9adf..0000000000 --- a/examples/widgets/tutorials/addressbook/part4/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(part4 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part4") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(part4 - addressbook.cpp addressbook.h - main.cpp -) - -set_target_properties(part4 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(part4 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS part4 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/addressbook/part4/addressbook.cpp b/examples/widgets/tutorials/addressbook/part4/addressbook.cpp deleted file mode 100644 index a54a888073..0000000000 --- a/examples/widgets/tutorials/addressbook/part4/addressbook.cpp +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -AddressBook::AddressBook(QWidget *parent) - : QWidget(parent) -{ - QLabel *nameLabel = new QLabel(tr("Name:")); - nameLine = new QLineEdit; - nameLine->setReadOnly(true); - - QLabel *addressLabel = new QLabel(tr("Address:")); - addressText = new QTextEdit; - addressText->setReadOnly(true); - - addButton = new QPushButton(tr("&Add")); -//! [edit and remove buttons] - editButton = new QPushButton(tr("&Edit")); - editButton->setEnabled(false); - removeButton = new QPushButton(tr("&Remove")); - removeButton->setEnabled(false); -//! [edit and remove buttons] - submitButton = new QPushButton(tr("&Submit")); - submitButton->hide(); - cancelButton = new QPushButton(tr("&Cancel")); - cancelButton->hide(); - - nextButton = new QPushButton(tr("&Next")); - nextButton->setEnabled(false); - previousButton = new QPushButton(tr("&Previous")); - previousButton->setEnabled(false); - - connect(addButton, &QPushButton::clicked, - this, &AddressBook::addContact); - connect(submitButton, &QPushButton::clicked, - this, &AddressBook::submitContact); -//! [connecting edit and remove] - connect(editButton, &QPushButton::clicked, - this, &AddressBook::editContact); - connect(removeButton, &QPushButton::clicked, - this, &AddressBook::removeContact); -//! [connecting edit and remove] - connect(cancelButton, &QPushButton::clicked, - this, &AddressBook::cancel); - connect(nextButton, &QPushButton::clicked, - this, &AddressBook::next); - connect(previousButton, &QPushButton::clicked, - this, &AddressBook::previous); - - QVBoxLayout *buttonLayout1 = new QVBoxLayout; - buttonLayout1->addWidget(addButton); -//! [adding edit and remove to the layout] - buttonLayout1->addWidget(editButton); - buttonLayout1->addWidget(removeButton); -//! [adding edit and remove to the layout] - buttonLayout1->addWidget(submitButton); - buttonLayout1->addWidget(cancelButton); - buttonLayout1->addStretch(); - - QHBoxLayout *buttonLayout2 = new QHBoxLayout; - buttonLayout2->addWidget(previousButton); - buttonLayout2->addWidget(nextButton); - - QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(nameLabel, 0, 0); - mainLayout->addWidget(nameLine, 0, 1); - mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); - mainLayout->addWidget(addressText, 1, 1); - mainLayout->addLayout(buttonLayout1, 1, 2); - mainLayout->addLayout(buttonLayout2, 2, 1); - - setLayout(mainLayout); - setWindowTitle(tr("Simple Address Book")); -} - -void AddressBook::addContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - nameLine->clear(); - addressText->clear(); - - updateInterface(AddingMode); -} -//! [editContact() function] -void AddressBook::editContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - updateInterface(EditingMode); -} -//! [editContact() function] -//! [submitContact() function beginning] -void AddressBook::submitContact() -{ -//! [submitContact() function beginning] - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (name.isEmpty() || address.isEmpty()) { - QMessageBox::information(this, tr("Empty Field"), - tr("Please enter a name and address.")); - return; - } -//! [submitContact() function part1] - if (currentMode == AddingMode) { - - if (!contacts.contains(name)) { - contacts.insert(name, address); - QMessageBox::information(this, tr("Add Successful"), - tr("\"%1\" has been added to your address book.").arg(name)); - } else { - QMessageBox::information(this, tr("Add Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - } -//! [submitContact() function part1] -//! [submitContact() function part2] - } else if (currentMode == EditingMode) { - - if (oldName != name) { - if (!contacts.contains(name)) { - QMessageBox::information(this, tr("Edit Successful"), - tr("\"%1\" has been edited in your address book.").arg(oldName)); - contacts.remove(oldName); - contacts.insert(name, address); - } else { - QMessageBox::information(this, tr("Edit Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - } - } else if (oldAddress != address) { - QMessageBox::information(this, tr("Edit Successful"), - tr("\"%1\" has been edited in your address book.").arg(name)); - contacts[name] = address; - } - } - - updateInterface(NavigationMode); -} -//! [submitContact() function part2] - -void AddressBook::cancel() -{ - nameLine->setText(oldName); - addressText->setText(oldAddress); - updateInterface(NavigationMode); -} -//! [removeContact() function] -void AddressBook::removeContact() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (contacts.contains(name)) { - - int button = QMessageBox::question(this, - tr("Confirm Remove"), - tr("Are you sure you want to remove \"%1\"?").arg(name), - QMessageBox::Yes | QMessageBox::No); - - if (button == QMessageBox::Yes) { - - previous(); - contacts.remove(name); - - QMessageBox::information(this, tr("Remove Successful"), - tr("\"%1\" has been removed from your address book.").arg(name)); - } - } - - updateInterface(NavigationMode); -} -//! [removeContact() function] -void AddressBook::next() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i != contacts.end()) - i++; - - if (i == contacts.end()) - i = contacts.begin(); - - nameLine->setText(i.key()); - addressText->setText(i.value()); -} - -void AddressBook::previous() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i == contacts.end()) { - nameLine->clear(); - addressText->clear(); - return; - } - - if (i == contacts.begin()) - i = contacts.end(); - - i--; - nameLine->setText(i.key()); - addressText->setText(i.value()); -} -//! [update interface() part 1] -void AddressBook::updateInterface(Mode mode) -{ - currentMode = mode; - - switch (currentMode) { - - case AddingMode: - case EditingMode: - - nameLine->setReadOnly(false); - nameLine->setFocus(Qt::OtherFocusReason); - addressText->setReadOnly(false); - - addButton->setEnabled(false); - editButton->setEnabled(false); - removeButton->setEnabled(false); - - nextButton->setEnabled(false); - previousButton->setEnabled(false); - - submitButton->show(); - cancelButton->show(); - break; -//! [update interface() part 1] -//! [update interface() part 2] - case NavigationMode: - - if (contacts.isEmpty()) { - nameLine->clear(); - addressText->clear(); - } - - nameLine->setReadOnly(true); - addressText->setReadOnly(true); - addButton->setEnabled(true); - - int number = contacts.size(); - editButton->setEnabled(number >= 1); - removeButton->setEnabled(number >= 1); - nextButton->setEnabled(number > 1); - previousButton->setEnabled(number >1 ); - - submitButton->hide(); - cancelButton->hide(); - break; - } -} -//! [update interface() part 2] diff --git a/examples/widgets/tutorials/addressbook/part4/addressbook.h b/examples/widgets/tutorials/addressbook/part4/addressbook.h deleted file mode 100644 index e77bbd3961..0000000000 --- a/examples/widgets/tutorials/addressbook/part4/addressbook.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef ADDRESSBOOK_H -#define ADDRESSBOOK_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QPushButton; -class QLabel; -class QLineEdit; -class QTextEdit; -QT_END_NAMESPACE - -class AddressBook : public QWidget -{ - Q_OBJECT - -public: - AddressBook(QWidget *parent = nullptr); -//! [Mode enum] - enum Mode { NavigationMode, AddingMode, EditingMode }; -//! [Mode enum] - -public slots: - void addContact(); - void submitContact(); - void cancel(); -//! [edit and remove slots] - void editContact(); - void removeContact(); -//! [edit and remove slots] - void next(); - void previous(); - -private: -//! [updateInterface() declaration] - void updateInterface(Mode mode); -//! [updateInterface() declaration] - QPushButton *addButton; -//! [buttons declaration] - QPushButton *editButton; - QPushButton *removeButton; -//! [buttons declaration] - QPushButton *submitButton; - QPushButton *cancelButton; - QPushButton *nextButton; - QPushButton *previousButton; - QLineEdit *nameLine; - QTextEdit *addressText; - - QMap contacts; - QString oldName; - QString oldAddress; -//! [mode declaration] - Mode currentMode; -//! [mode declaration] -}; - -#endif diff --git a/examples/widgets/tutorials/addressbook/part4/main.cpp b/examples/widgets/tutorials/addressbook/part4/main.cpp deleted file mode 100644 index 1f3aac3397..0000000000 --- a/examples/widgets/tutorials/addressbook/part4/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - AddressBook addressBook; - addressBook.show(); - - return app.exec(); -} diff --git a/examples/widgets/tutorials/addressbook/part4/part4.pro b/examples/widgets/tutorials/addressbook/part4/part4.pro deleted file mode 100644 index 02cc5b8e07..0000000000 --- a/examples/widgets/tutorials/addressbook/part4/part4.pro +++ /dev/null @@ -1,11 +0,0 @@ -QT += widgets - -SOURCES = addressbook.cpp \ - main.cpp -HEADERS = addressbook.h - -QMAKE_PROJECT_NAME = ab_part4 - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part4 -INSTALLS += target diff --git a/examples/widgets/tutorials/addressbook/part5/CMakeLists.txt b/examples/widgets/tutorials/addressbook/part5/CMakeLists.txt deleted file mode 100644 index 2abb1c6454..0000000000 --- a/examples/widgets/tutorials/addressbook/part5/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(part5 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part5") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(part5 - addressbook.cpp addressbook.h - finddialog.cpp finddialog.h - main.cpp -) - -set_target_properties(part5 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(part5 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS part5 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/addressbook/part5/addressbook.cpp b/examples/widgets/tutorials/addressbook/part5/addressbook.cpp deleted file mode 100644 index 52aa5a0b28..0000000000 --- a/examples/widgets/tutorials/addressbook/part5/addressbook.cpp +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -AddressBook::AddressBook(QWidget *parent) - : QWidget(parent) -{ - QLabel *nameLabel = new QLabel(tr("Name:")); - nameLine = new QLineEdit; - nameLine->setReadOnly(true); - - QLabel *addressLabel = new QLabel(tr("Address:")); - addressText = new QTextEdit; - addressText->setReadOnly(true); - - addButton = new QPushButton(tr("&Add")); - - editButton = new QPushButton(tr("&Edit")); - editButton->setEnabled(false); - removeButton = new QPushButton(tr("&Remove")); - removeButton->setEnabled(false); -//! [instantiating findButton] - findButton = new QPushButton(tr("&Find")); - findButton->setEnabled(false); -//! [instantiating findButton] - submitButton = new QPushButton(tr("&Submit")); - submitButton->hide(); - cancelButton = new QPushButton(tr("&Cancel")); - cancelButton->hide(); - - nextButton = new QPushButton(tr("&Next")); - nextButton->setEnabled(false); - previousButton = new QPushButton(tr("&Previous")); - previousButton->setEnabled(false); - -//! [instantiating FindDialog] - dialog = new FindDialog(this); -//! [instantiating FindDialog] - - connect(addButton, &QPushButton::clicked, - this, &AddressBook::addContact); - connect(submitButton, &QPushButton::clicked, - this, &AddressBook::submitContact); - connect(editButton, &QPushButton::clicked, - this, &AddressBook::editContact); - connect(removeButton, &QPushButton::clicked, - this, &AddressBook::removeContact); - connect(cancelButton, &QPushButton::clicked, - this, &AddressBook::cancel); -//! [signals and slots for find] - connect(findButton, &QPushButton::clicked, - this, &AddressBook::findContact); -//! [signals and slots for find] - connect(nextButton, &QPushButton::clicked, - this, &AddressBook::next); - connect(previousButton, &QPushButton::clicked, - this, &AddressBook::previous); - - QVBoxLayout *buttonLayout1 = new QVBoxLayout; - buttonLayout1->addWidget(addButton); - buttonLayout1->addWidget(editButton); - buttonLayout1->addWidget(removeButton); -//! [adding findButton to layout] - buttonLayout1->addWidget(findButton); -//! [adding findButton to layout] - buttonLayout1->addWidget(submitButton); - buttonLayout1->addWidget(cancelButton); - buttonLayout1->addStretch(); - - QHBoxLayout *buttonLayout2 = new QHBoxLayout; - buttonLayout2->addWidget(previousButton); - buttonLayout2->addWidget(nextButton); - - QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(nameLabel, 0, 0); - mainLayout->addWidget(nameLine, 0, 1); - mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); - mainLayout->addWidget(addressText, 1, 1); - mainLayout->addLayout(buttonLayout1, 1, 2); - mainLayout->addLayout(buttonLayout2, 2, 1); - - setLayout(mainLayout); - setWindowTitle(tr("Simple Address Book")); -} - -void AddressBook::addContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - nameLine->clear(); - addressText->clear(); - - updateInterface(AddingMode); -} - -void AddressBook::editContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - updateInterface(EditingMode); -} - -void AddressBook::submitContact() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (name.isEmpty() || address.isEmpty()) { - QMessageBox::information(this, tr("Empty Field"), - tr("Please enter a name and address.")); - return; - } - - if (currentMode == AddingMode) { - - if (!contacts.contains(name)) { - contacts.insert(name, address); - QMessageBox::information(this, tr("Add Successful"), - tr("\"%1\" has been added to your address book.").arg(name)); - } else { - QMessageBox::information(this, tr("Add Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - } - } else if (currentMode == EditingMode) { - - if (oldName != name) { - if (!contacts.contains(name)) { - QMessageBox::information(this, tr("Edit Successful"), - tr("\"%1\" has been edited in your address book.").arg(oldName)); - contacts.remove(oldName); - contacts.insert(name, address); - } else { - QMessageBox::information(this, tr("Edit Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - } - } else if (oldAddress != address) { - QMessageBox::information(this, tr("Edit Successful"), - tr("\"%1\" has been edited in your address book.").arg(name)); - contacts[name] = address; - } - } - - updateInterface(NavigationMode); -} - -void AddressBook::cancel() -{ - nameLine->setText(oldName); - addressText->setText(oldAddress); - updateInterface(NavigationMode); -} - -void AddressBook::removeContact() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (contacts.contains(name)) { - - int button = QMessageBox::question(this, - tr("Confirm Remove"), - tr("Are you sure you want to remove \"%1\"?").arg(name), - QMessageBox::Yes | QMessageBox::No); - - if (button == QMessageBox::Yes) { - - previous(); - contacts.remove(name); - - QMessageBox::information(this, tr("Remove Successful"), - tr("\"%1\" has been removed from your address book.").arg(name)); - } - } - - updateInterface(NavigationMode); -} - -void AddressBook::next() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i != contacts.end()) - i++; - - if (i == contacts.end()) - i = contacts.begin(); - - nameLine->setText(i.key()); - addressText->setText(i.value()); -} - -void AddressBook::previous() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i == contacts.end()) { - nameLine->clear(); - addressText->clear(); - return; - } - - if (i == contacts.begin()) - i = contacts.end(); - - i--; - nameLine->setText(i.key()); - addressText->setText(i.value()); -} -//! [findContact() function] -void AddressBook::findContact() -{ - dialog->show(); - - if (dialog->exec() == QDialog::Accepted) { - QString contactName = dialog->getFindText(); - - if (contacts.contains(contactName)) { - nameLine->setText(contactName); - addressText->setText(contacts.value(contactName)); - } else { - QMessageBox::information(this, tr("Contact Not Found"), - tr("Sorry, \"%1\" is not in your address book.").arg(contactName)); - return; - } - } - - updateInterface(NavigationMode); -} -//! [findContact() function] - -void AddressBook::updateInterface(Mode mode) -{ - currentMode = mode; - - switch (currentMode) { - - case AddingMode: - case EditingMode: - - nameLine->setReadOnly(false); - nameLine->setFocus(Qt::OtherFocusReason); - addressText->setReadOnly(false); - - addButton->setEnabled(false); - editButton->setEnabled(false); - removeButton->setEnabled(false); - - nextButton->setEnabled(false); - previousButton->setEnabled(false); - - submitButton->show(); - cancelButton->show(); - break; - - case NavigationMode: - - if (contacts.isEmpty()) { - nameLine->clear(); - addressText->clear(); - } - - nameLine->setReadOnly(true); - addressText->setReadOnly(true); - addButton->setEnabled(true); - - int number = contacts.size(); - editButton->setEnabled(number >= 1); - removeButton->setEnabled(number >= 1); - findButton->setEnabled(number > 2); - nextButton->setEnabled(number > 1); - previousButton->setEnabled(number > 1); - - submitButton->hide(); - cancelButton->hide(); - break; - } -} diff --git a/examples/widgets/tutorials/addressbook/part5/addressbook.h b/examples/widgets/tutorials/addressbook/part5/addressbook.h deleted file mode 100644 index 93da08038c..0000000000 --- a/examples/widgets/tutorials/addressbook/part5/addressbook.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef ADDRESSBOOK_H -#define ADDRESSBOOK_H - -#include -#include -//! [include finddialog's header] -#include "finddialog.h" -//! [include finddialog's header] -QT_BEGIN_NAMESPACE -class QPushButton; -class QLabel; -class QLineEdit; -class QTextEdit; -QT_END_NAMESPACE - - -class AddressBook : public QWidget -{ - Q_OBJECT - -public: - AddressBook(QWidget *parent = nullptr); - enum Mode { NavigationMode, AddingMode, EditingMode }; - -public slots: - void addContact(); - void editContact(); - void submitContact(); - void cancel(); - void removeContact(); -//! [findContact() declaration] - void findContact(); -//! [findContact() declaration] - void next(); - void previous(); - -private: - void updateInterface(Mode mode); - - QPushButton *addButton; - QPushButton *editButton; - QPushButton *removeButton; -//! [findButton declaration] - QPushButton *findButton; -//! [findButton declaration] - QPushButton *submitButton; - QPushButton *cancelButton; - QPushButton *nextButton; - QPushButton *previousButton; - QLineEdit *nameLine; - QTextEdit *addressText; - - QMap contacts; -//! [FindDialog declaration] - FindDialog *dialog; -//! [FindDialog declaration] - QString oldName; - QString oldAddress; - Mode currentMode; -}; - -#endif diff --git a/examples/widgets/tutorials/addressbook/part5/finddialog.cpp b/examples/widgets/tutorials/addressbook/part5/finddialog.cpp deleted file mode 100644 index d5daa661d0..0000000000 --- a/examples/widgets/tutorials/addressbook/part5/finddialog.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "finddialog.h" - -//! [constructor] -FindDialog::FindDialog(QWidget *parent) - : QDialog(parent) -{ - QLabel *findLabel = new QLabel(tr("Enter the name of a contact:")); - lineEdit = new QLineEdit; - - findButton = new QPushButton(tr("&Find")); - findText = ""; - - QHBoxLayout *layout = new QHBoxLayout; - layout->addWidget(findLabel); - layout->addWidget(lineEdit); - layout->addWidget(findButton); - - setLayout(layout); - setWindowTitle(tr("Find a Contact")); - connect(findButton, &QPushButton::clicked, - this, &FindDialog::findClicked); - connect(findButton, &QPushButton::clicked, - this, &FindDialog::accept); -} -//! [constructor] -//! [findClicked() function] -void FindDialog::findClicked() -{ - QString text = lineEdit->text(); - - if (text.isEmpty()) { - QMessageBox::information(this, tr("Empty Field"), - tr("Please enter a name.")); - return; - } else { - findText = text; - lineEdit->clear(); - hide(); - } -} -//! [findClicked() function] -//! [getFindText() function] -QString FindDialog::getFindText() -{ - return findText; -} -//! [getFindText() function] diff --git a/examples/widgets/tutorials/addressbook/part5/finddialog.h b/examples/widgets/tutorials/addressbook/part5/finddialog.h deleted file mode 100644 index 7cedcffa60..0000000000 --- a/examples/widgets/tutorials/addressbook/part5/finddialog.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef FINDDIALOG_H -#define FINDDIALOG_H -//! [FindDialog header] -#include - -QT_BEGIN_NAMESPACE -class QLineEdit; -class QPushButton; -QT_END_NAMESPACE - -class FindDialog : public QDialog -{ - Q_OBJECT - -public: - FindDialog(QWidget *parent = nullptr); - QString getFindText(); - -public slots: - void findClicked(); - -private: - QPushButton *findButton; - QLineEdit *lineEdit; - QString findText; -}; -//! [FindDialog header] -#endif diff --git a/examples/widgets/tutorials/addressbook/part5/main.cpp b/examples/widgets/tutorials/addressbook/part5/main.cpp deleted file mode 100644 index 1f3aac3397..0000000000 --- a/examples/widgets/tutorials/addressbook/part5/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - AddressBook addressBook; - addressBook.show(); - - return app.exec(); -} diff --git a/examples/widgets/tutorials/addressbook/part5/part5.pro b/examples/widgets/tutorials/addressbook/part5/part5.pro deleted file mode 100644 index da5469f655..0000000000 --- a/examples/widgets/tutorials/addressbook/part5/part5.pro +++ /dev/null @@ -1,13 +0,0 @@ -QT += widgets - -SOURCES = addressbook.cpp \ - finddialog.cpp \ - main.cpp -HEADERS = addressbook.h \ - finddialog.h - -QMAKE_PROJECT_NAME = ab_part5 - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part5 -INSTALLS += target diff --git a/examples/widgets/tutorials/addressbook/part6/CMakeLists.txt b/examples/widgets/tutorials/addressbook/part6/CMakeLists.txt deleted file mode 100644 index 8e954c51ab..0000000000 --- a/examples/widgets/tutorials/addressbook/part6/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(part6 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part6") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(part6 - addressbook.cpp addressbook.h - finddialog.cpp finddialog.h - main.cpp -) - -set_target_properties(part6 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(part6 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS part6 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/addressbook/part6/addressbook.cpp b/examples/widgets/tutorials/addressbook/part6/addressbook.cpp deleted file mode 100644 index 455ccc899a..0000000000 --- a/examples/widgets/tutorials/addressbook/part6/addressbook.cpp +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -AddressBook::AddressBook(QWidget *parent) - : QWidget(parent) -{ - QLabel *nameLabel = new QLabel(tr("Name:")); - nameLine = new QLineEdit; - nameLine->setReadOnly(true); - - QLabel *addressLabel = new QLabel(tr("Address:")); - addressText = new QTextEdit; - addressText->setReadOnly(true); - - addButton = new QPushButton(tr("&Add")); - - editButton = new QPushButton(tr("&Edit")); - editButton->setEnabled(false); - removeButton = new QPushButton(tr("&Remove")); - removeButton->setEnabled(false); - findButton = new QPushButton(tr("&Find")); - findButton->setEnabled(false); - submitButton = new QPushButton(tr("&Submit")); - submitButton->hide(); - cancelButton = new QPushButton(tr("&Cancel")); - cancelButton->hide(); - - nextButton = new QPushButton(tr("&Next")); - nextButton->setEnabled(false); - previousButton = new QPushButton(tr("&Previous")); - previousButton->setEnabled(false); - - loadButton = new QPushButton(tr("&Load...")); -//! [tooltip 1] - loadButton->setToolTip(tr("Load contacts from a file")); -//! [tooltip 1] - saveButton = new QPushButton(tr("&Save...")); -//! [tooltip 2] - saveButton->setToolTip(tr("Save contacts to a file")); -//! [tooltip 2] - saveButton->setEnabled(false); - - dialog = new FindDialog(this); - - connect(addButton, &QPushButton::clicked, - this, &AddressBook::addContact); - connect(submitButton, &QPushButton::clicked, - this, &AddressBook::submitContact); - connect(editButton, &QPushButton::clicked, - this, &AddressBook::editContact); - connect(removeButton, &QPushButton::clicked, - this, &AddressBook::removeContact); - connect(cancelButton, &QPushButton::clicked, - this, &AddressBook::cancel); - connect(findButton, &QPushButton::clicked, - this, &AddressBook::findContact); - connect(nextButton, &QPushButton::clicked, - this, &AddressBook::next); - connect(previousButton, &QPushButton::clicked, - this, &AddressBook::previous); - connect(loadButton, &QPushButton::clicked, - this, &AddressBook::loadFromFile); - connect(saveButton, &QPushButton::clicked, - this, &AddressBook::saveToFile); - - QVBoxLayout *buttonLayout1 = new QVBoxLayout; - buttonLayout1->addWidget(addButton); - buttonLayout1->addWidget(editButton); - buttonLayout1->addWidget(removeButton); - buttonLayout1->addWidget(findButton); - buttonLayout1->addWidget(submitButton); - buttonLayout1->addWidget(cancelButton); - buttonLayout1->addWidget(loadButton); - buttonLayout1->addWidget(saveButton); - buttonLayout1->addStretch(); - - QHBoxLayout *buttonLayout2 = new QHBoxLayout; - buttonLayout2->addWidget(previousButton); - buttonLayout2->addWidget(nextButton); - - QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(nameLabel, 0, 0); - mainLayout->addWidget(nameLine, 0, 1); - mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); - mainLayout->addWidget(addressText, 1, 1); - mainLayout->addLayout(buttonLayout1, 1, 2); - mainLayout->addLayout(buttonLayout2, 2, 1); - - setLayout(mainLayout); - setWindowTitle(tr("Simple Address Book")); -} - -void AddressBook::addContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - nameLine->clear(); - addressText->clear(); - - updateInterface(AddingMode); -} - -void AddressBook::editContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - updateInterface(EditingMode); -} - -void AddressBook::submitContact() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (name.isEmpty() || address.isEmpty()) { - QMessageBox::information(this, tr("Empty Field"), - tr("Please enter a name and address.")); - return; - } - - if (currentMode == AddingMode) { - - if (!contacts.contains(name)) { - contacts.insert(name, address); - QMessageBox::information(this, tr("Add Successful"), - tr("\"%1\" has been added to your address book.").arg(name)); - } else { - QMessageBox::information(this, tr("Add Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - } - } else if (currentMode == EditingMode) { - - if (oldName != name) { - if (!contacts.contains(name)) { - QMessageBox::information(this, tr("Edit Successful"), - tr("\"%1\" has been edited in your address book.").arg(oldName)); - contacts.remove(oldName); - contacts.insert(name, address); - } else { - QMessageBox::information(this, tr("Edit Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - } - } else if (oldAddress != address) { - QMessageBox::information(this, tr("Edit Successful"), - tr("\"%1\" has been edited in your address book.").arg(name)); - contacts[name] = address; - } - } - - updateInterface(NavigationMode); -} - -void AddressBook::cancel() -{ - nameLine->setText(oldName); - addressText->setText(oldAddress); - updateInterface(NavigationMode); -} - -void AddressBook::removeContact() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (contacts.contains(name)) { - - int button = QMessageBox::question(this, - tr("Confirm Remove"), - tr("Are you sure you want to remove \"%1\"?").arg(name), - QMessageBox::Yes | QMessageBox::No); - - if (button == QMessageBox::Yes) { - - previous(); - contacts.remove(name); - - QMessageBox::information(this, tr("Remove Successful"), - tr("\"%1\" has been removed from your address book.").arg(name)); - } - } - - updateInterface(NavigationMode); -} - -void AddressBook::next() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i != contacts.end()) - i++; - - if (i == contacts.end()) - i = contacts.begin(); - - nameLine->setText(i.key()); - addressText->setText(i.value()); -} - -void AddressBook::previous() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i == contacts.end()) { - nameLine->clear(); - addressText->clear(); - return; - } - - if (i == contacts.begin()) - i = contacts.end(); - - i--; - nameLine->setText(i.key()); - addressText->setText(i.value()); -} - -void AddressBook::findContact() -{ - dialog->show(); - - if (dialog->exec() == 1) { - QString contactName = dialog->getFindText(); - - if (contacts.contains(contactName)) { - nameLine->setText(contactName); - addressText->setText(contacts.value(contactName)); - } else { - QMessageBox::information(this, tr("Contact Not Found"), - tr("Sorry, \"%1\" is not in your address book.").arg(contactName)); - return; - } - } - - updateInterface(NavigationMode); -} - -void AddressBook::updateInterface(Mode mode) -{ - currentMode = mode; - - switch (currentMode) { - - case AddingMode: - case EditingMode: - - nameLine->setReadOnly(false); - nameLine->setFocus(Qt::OtherFocusReason); - addressText->setReadOnly(false); - - addButton->setEnabled(false); - editButton->setEnabled(false); - removeButton->setEnabled(false); - - nextButton->setEnabled(false); - previousButton->setEnabled(false); - - submitButton->show(); - cancelButton->show(); - - loadButton->setEnabled(false); - saveButton->setEnabled(false); - break; - - case NavigationMode: - - if (contacts.isEmpty()) { - nameLine->clear(); - addressText->clear(); - } - - nameLine->setReadOnly(true); - addressText->setReadOnly(true); - addButton->setEnabled(true); - - int number = contacts.size(); - editButton->setEnabled(number >= 1); - removeButton->setEnabled(number >= 1); - findButton->setEnabled(number > 2); - nextButton->setEnabled(number > 1); - previousButton->setEnabled(number > 1); - - submitButton->hide(); - cancelButton->hide(); - - loadButton->setEnabled(true); - saveButton->setEnabled(number >= 1); - break; - } -} - -//! [saveToFile() function part1] -void AddressBook::saveToFile() -{ - QString fileName = QFileDialog::getSaveFileName(this, - tr("Save Address Book"), "", - tr("Address Book (*.abk);;All Files (*)")); - -//! [saveToFile() function part1] -//! [saveToFile() function part2] - if (fileName.isEmpty()) - return; - else { - QFile file(fileName); - if (!file.open(QIODevice::WriteOnly)) { - QMessageBox::information(this, tr("Unable to open file"), - file.errorString()); - return; - } - -//! [saveToFile() function part2] -//! [saveToFile() function part3] - QDataStream out(&file); - out.setVersion(QDataStream::Qt_4_5); - out << contacts; - } -} -//! [saveToFile() function part3] - -//! [loadFromFile() function part1] -void AddressBook::loadFromFile() -{ - QString fileName = QFileDialog::getOpenFileName(this, - tr("Open Address Book"), "", - tr("Address Book (*.abk);;All Files (*)")); -//! [loadFromFile() function part1] - -//! [loadFromFile() function part2] - if (fileName.isEmpty()) - return; - else { - - QFile file(fileName); - - if (!file.open(QIODevice::ReadOnly)) { - QMessageBox::information(this, tr("Unable to open file"), - file.errorString()); - return; - } - - QDataStream in(&file); - in.setVersion(QDataStream::Qt_4_5); - contacts.clear(); // clear existing contacts - in >> contacts; -//! [loadFromFile() function part2] - -//! [loadFromFile() function part3] - if (contacts.isEmpty()) { - QMessageBox::information(this, tr("No contacts in file"), - tr("The file you are attempting to open contains no contacts.")); - } else { - QMap::iterator i = contacts.begin(); - nameLine->setText(i.key()); - addressText->setText(i.value()); - } - } - - updateInterface(NavigationMode); -} -//! [loadFromFile() function part3] diff --git a/examples/widgets/tutorials/addressbook/part6/addressbook.h b/examples/widgets/tutorials/addressbook/part6/addressbook.h deleted file mode 100644 index 26389d7446..0000000000 --- a/examples/widgets/tutorials/addressbook/part6/addressbook.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef ADDRESSBOOK_H -#define ADDRESSBOOK_H - -#include -#include -#include "finddialog.h" - -QT_BEGIN_NAMESPACE -class QPushButton; -class QLabel; -class QLineEdit; -class QTextEdit; -QT_END_NAMESPACE - - -class AddressBook : public QWidget -{ - Q_OBJECT - -public: - AddressBook(QWidget *parent = nullptr); - enum Mode { NavigationMode, AddingMode, EditingMode }; - -public slots: - void addContact(); - void editContact(); - void submitContact(); - void cancel(); - void removeContact(); - void findContact(); - void next(); - void previous(); -//! [save and load functions declaration] - void saveToFile(); - void loadFromFile(); -//! [save and load functions declaration] - -private: - void updateInterface(Mode mode); - - QPushButton *addButton; - QPushButton *editButton; - QPushButton *removeButton; - QPushButton *findButton; - QPushButton *submitButton; - QPushButton *cancelButton; - QPushButton *nextButton; - QPushButton *previousButton; -//! [save and load buttons declaration] - QPushButton *loadButton; - QPushButton *saveButton; -//! [save and load buttons declaration] - QLineEdit *nameLine; - QTextEdit *addressText; - - QMap contacts; - FindDialog *dialog; - QString oldName; - QString oldAddress; - Mode currentMode; -}; - -#endif diff --git a/examples/widgets/tutorials/addressbook/part6/finddialog.cpp b/examples/widgets/tutorials/addressbook/part6/finddialog.cpp deleted file mode 100644 index 90729d9c12..0000000000 --- a/examples/widgets/tutorials/addressbook/part6/finddialog.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "finddialog.h" - -FindDialog::FindDialog(QWidget *parent) - : QDialog(parent) -{ - QLabel *findLabel = new QLabel(tr("Enter the name of a contact:")); - lineEdit = new QLineEdit; - - findButton = new QPushButton(tr("&Find")); - findText = ""; - - QHBoxLayout *layout = new QHBoxLayout; - layout->addWidget(findLabel); - layout->addWidget(lineEdit); - layout->addWidget(findButton); - - setLayout(layout); - setWindowTitle(tr("Find a Contact")); - connect(findButton, &QPushButton::clicked, - this, &FindDialog::findClicked); - connect(findButton, &QPushButton::clicked, - this, &FindDialog::accept); -} - -void FindDialog::findClicked() -{ - QString text = lineEdit->text(); - - if (text.isEmpty()) { - QMessageBox::information(this, tr("Empty Field"), - tr("Please enter a name.")); - return; - } else { - findText = text; - lineEdit->clear(); - hide(); - } -} - -QString FindDialog::getFindText() -{ - return findText; -} diff --git a/examples/widgets/tutorials/addressbook/part6/finddialog.h b/examples/widgets/tutorials/addressbook/part6/finddialog.h deleted file mode 100644 index 7c9a3af30f..0000000000 --- a/examples/widgets/tutorials/addressbook/part6/finddialog.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef FINDDIALOG_H -#define FINDDIALOG_H - -#include - -QT_BEGIN_NAMESPACE -class QLineEdit; -class QPushButton; -QT_END_NAMESPACE - -class FindDialog : public QDialog -{ - Q_OBJECT - -public: - FindDialog(QWidget *parent = nullptr); - QString getFindText(); - -public slots: - void findClicked(); - -private: - QPushButton *findButton; - QLineEdit *lineEdit; - QString findText; -}; - -#endif diff --git a/examples/widgets/tutorials/addressbook/part6/main.cpp b/examples/widgets/tutorials/addressbook/part6/main.cpp deleted file mode 100644 index 1f3aac3397..0000000000 --- a/examples/widgets/tutorials/addressbook/part6/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - AddressBook addressBook; - addressBook.show(); - - return app.exec(); -} diff --git a/examples/widgets/tutorials/addressbook/part6/part6.pro b/examples/widgets/tutorials/addressbook/part6/part6.pro deleted file mode 100644 index 6796f30a73..0000000000 --- a/examples/widgets/tutorials/addressbook/part6/part6.pro +++ /dev/null @@ -1,14 +0,0 @@ -QT += widgets -requires(qtConfig(filedialog)) - -SOURCES = addressbook.cpp \ - finddialog.cpp \ - main.cpp -HEADERS = addressbook.h \ - finddialog.h - -QMAKE_PROJECT_NAME = ab_part6 - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part6 -INSTALLS += target diff --git a/examples/widgets/tutorials/addressbook/part7/CMakeLists.txt b/examples/widgets/tutorials/addressbook/part7/CMakeLists.txt deleted file mode 100644 index fe4ace86ad..0000000000 --- a/examples/widgets/tutorials/addressbook/part7/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(part7 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part7") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(part7 - addressbook.cpp addressbook.h - finddialog.cpp finddialog.h - main.cpp -) - -set_target_properties(part7 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(part7 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS part7 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/addressbook/part7/addressbook.cpp b/examples/widgets/tutorials/addressbook/part7/addressbook.cpp deleted file mode 100644 index 30878d7bbc..0000000000 --- a/examples/widgets/tutorials/addressbook/part7/addressbook.cpp +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -AddressBook::AddressBook(QWidget *parent) - : QWidget(parent) -{ - QLabel *nameLabel = new QLabel(tr("Name:")); - nameLine = new QLineEdit; - nameLine->setReadOnly(true); - - QLabel *addressLabel = new QLabel(tr("Address:")); - addressText = new QTextEdit; - addressText->setReadOnly(true); - - addButton = new QPushButton(tr("&Add")); - - editButton = new QPushButton(tr("&Edit")); - editButton->setEnabled(false); - removeButton = new QPushButton(tr("&Remove")); - removeButton->setEnabled(false); - findButton = new QPushButton(tr("&Find")); - findButton->setEnabled(false); - submitButton = new QPushButton(tr("&Submit")); - submitButton->hide(); - cancelButton = new QPushButton(tr("&Cancel")); - cancelButton->hide(); - - nextButton = new QPushButton(tr("&Next")); - nextButton->setEnabled(false); - previousButton = new QPushButton(tr("&Previous")); - previousButton->setEnabled(false); - - loadButton = new QPushButton(tr("&Load...")); - loadButton->setToolTip(tr("Load contacts from a file")); - saveButton = new QPushButton(tr("&Save...")); - saveButton->setToolTip(tr("Save contacts to a file")); - saveButton->setEnabled(false); - - exportButton = new QPushButton(tr("E&xport")); - exportButton->setToolTip(tr("Export as vCard")); - exportButton->setEnabled(false); - - dialog = new FindDialog(this); - - connect(addButton, &QPushButton::clicked, - this, &AddressBook::addContact); - connect(submitButton, &QPushButton::clicked, - this, &AddressBook::submitContact); - connect(editButton, &QPushButton::clicked, - this, &AddressBook::editContact); - connect(removeButton, &QPushButton::clicked, - this, &AddressBook::removeContact); - connect(cancelButton, &QPushButton::clicked, - this, &AddressBook::cancel); - connect(findButton, &QPushButton::clicked, - this, &AddressBook::findContact); - connect(nextButton, &QPushButton::clicked, - this, &AddressBook::next); - connect(previousButton, &QPushButton::clicked, - this, &AddressBook::previous); - connect(loadButton, &QPushButton::clicked, - this, &AddressBook::loadFromFile); - connect(saveButton, &QPushButton::clicked, - this, &AddressBook::saveToFile); - connect(exportButton, &QPushButton::clicked, - this, &AddressBook::exportAsVCard); - - QVBoxLayout *buttonLayout1 = new QVBoxLayout; - buttonLayout1->addWidget(addButton); - buttonLayout1->addWidget(editButton); - buttonLayout1->addWidget(removeButton); - buttonLayout1->addWidget(findButton); - buttonLayout1->addWidget(submitButton); - buttonLayout1->addWidget(cancelButton); - buttonLayout1->addWidget(loadButton); - buttonLayout1->addWidget(saveButton); - buttonLayout1->addWidget(exportButton); - buttonLayout1->addStretch(); - - QHBoxLayout *buttonLayout2 = new QHBoxLayout; - buttonLayout2->addWidget(previousButton); - buttonLayout2->addWidget(nextButton); - - QGridLayout *mainLayout = new QGridLayout; - mainLayout->addWidget(nameLabel, 0, 0); - mainLayout->addWidget(nameLine, 0, 1); - mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); - mainLayout->addWidget(addressText, 1, 1); - mainLayout->addLayout(buttonLayout1, 1, 2); - mainLayout->addLayout(buttonLayout2, 2, 1); - - setLayout(mainLayout); - setWindowTitle(tr("Simple Address Book")); -} - -void AddressBook::addContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - nameLine->clear(); - addressText->clear(); - - updateInterface(AddingMode); -} - -void AddressBook::editContact() -{ - oldName = nameLine->text(); - oldAddress = addressText->toPlainText(); - - updateInterface(EditingMode); -} - -void AddressBook::submitContact() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (name.isEmpty() || address.isEmpty()) { - QMessageBox::information(this, tr("Empty Field"), - tr("Please enter a name and address.")); - return; - } - - if (currentMode == AddingMode) { - - if (!contacts.contains(name)) { - contacts.insert(name, address); - QMessageBox::information(this, tr("Add Successful"), - tr("\"%1\" has been added to your address book.").arg(name)); - } else { - QMessageBox::information(this, tr("Add Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - } - } else if (currentMode == EditingMode) { - - if (oldName != name) { - if (!contacts.contains(name)) { - QMessageBox::information(this, tr("Edit Successful"), - tr("\"%1\" has been edited in your address book.").arg(oldName)); - contacts.remove(oldName); - contacts.insert(name, address); - } else { - QMessageBox::information(this, tr("Edit Unsuccessful"), - tr("Sorry, \"%1\" is already in your address book.").arg(name)); - } - } else if (oldAddress != address) { - QMessageBox::information(this, tr("Edit Successful"), - tr("\"%1\" has been edited in your address book.").arg(name)); - contacts[name] = address; - } - } - - updateInterface(NavigationMode); -} - -void AddressBook::cancel() -{ - nameLine->setText(oldName); - addressText->setText(oldAddress); - updateInterface(NavigationMode); -} - -void AddressBook::removeContact() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - - if (contacts.contains(name)) { - - int button = QMessageBox::question(this, - tr("Confirm Remove"), - tr("Are you sure you want to remove \"%1\"?").arg(name), - QMessageBox::Yes | QMessageBox::No); - - if (button == QMessageBox::Yes) { - - previous(); - contacts.remove(name); - - QMessageBox::information(this, tr("Remove Successful"), - tr("\"%1\" has been removed from your address book.").arg(name)); - } - } - - updateInterface(NavigationMode); -} - -void AddressBook::next() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i != contacts.end()) - i++; - - if (i == contacts.end()) - i = contacts.begin(); - - nameLine->setText(i.key()); - addressText->setText(i.value()); -} - -void AddressBook::previous() -{ - QString name = nameLine->text(); - QMap::iterator i = contacts.find(name); - - if (i == contacts.end()) { - nameLine->clear(); - addressText->clear(); - return; - } - - if (i == contacts.begin()) - i = contacts.end(); - - i--; - nameLine->setText(i.key()); - addressText->setText(i.value()); -} - -void AddressBook::findContact() -{ - dialog->show(); - - if (dialog->exec() == 1) { - QString contactName = dialog->getFindText(); - - if (contacts.contains(contactName)) { - nameLine->setText(contactName); - addressText->setText(contacts.value(contactName)); - } else { - QMessageBox::information(this, tr("Contact Not Found"), - tr("Sorry, \"%1\" is not in your address book.").arg(contactName)); - return; - } - } - - updateInterface(NavigationMode); -} -void AddressBook::updateInterface(Mode mode) -{ - currentMode = mode; - - switch (currentMode) { - - case AddingMode: - case EditingMode: - - nameLine->setReadOnly(false); - nameLine->setFocus(Qt::OtherFocusReason); - addressText->setReadOnly(false); - - addButton->setEnabled(false); - editButton->setEnabled(false); - removeButton->setEnabled(false); - - nextButton->setEnabled(false); - previousButton->setEnabled(false); - - submitButton->show(); - cancelButton->show(); - - loadButton->setEnabled(false); - saveButton->setEnabled(false); - exportButton->setEnabled(false); - break; - - case NavigationMode: - - if (contacts.isEmpty()) { - nameLine->clear(); - addressText->clear(); - } - - nameLine->setReadOnly(true); - addressText->setReadOnly(true); - addButton->setEnabled(true); - - int number = contacts.size(); - editButton->setEnabled(number >= 1); - removeButton->setEnabled(number >= 1); - findButton->setEnabled(number > 2); - nextButton->setEnabled(number > 1); - previousButton->setEnabled(number > 1); - - submitButton->hide(); - cancelButton->hide(); - - exportButton->setEnabled(number >= 1); - - loadButton->setEnabled(true); - saveButton->setEnabled(number >= 1); - break; - } -} - -void AddressBook::saveToFile() -{ - QString fileName = QFileDialog::getSaveFileName(this, - tr("Save Address Book"), "", - tr("Address Book (*.abk);;All Files (*)")); - - if (fileName.isEmpty()) - return; - else { - QFile file(fileName); - - if (!file.open(QIODevice::WriteOnly)) { - QMessageBox::information(this, tr("Unable to open file"), - file.errorString()); - return; - } - - QDataStream out(&file); - out.setVersion(QDataStream::Qt_4_3); - out << contacts; - } - - updateInterface(NavigationMode); -} - -void AddressBook::loadFromFile() -{ - QString fileName = QFileDialog::getOpenFileName(this, - tr("Open Address Book"), "", - tr("Address Book (*.abk);;All Files (*)")); - - if (fileName.isEmpty()) - return; - else { - QFile file(fileName); - - if (!file.open(QIODevice::ReadOnly)) { - QMessageBox::information(this, tr("Unable to open file"), - file.errorString()); - return; - } - - QDataStream in(&file); - in.setVersion(QDataStream::Qt_4_3); - in >> contacts; - - QMap::iterator i = contacts.begin(); - nameLine->setText(i.key()); - addressText->setText(i.value()); - } - - updateInterface(NavigationMode); -} - -//! [export function part1] -void AddressBook::exportAsVCard() -{ - QString name = nameLine->text(); - QString address = addressText->toPlainText(); - QString firstName; - QString lastName; - QStringList nameList; - - int index = name.indexOf(" "); - - if (index != -1) { - nameList = name.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts); - firstName = nameList.first(); - lastName = nameList.last(); - } else { - firstName = name; - lastName = ""; - } - - QString fileName = QFileDialog::getSaveFileName(this, - tr("Export Contact"), "", - tr("vCard Files (*.vcf);;All Files (*)")); - - if (fileName.isEmpty()) - return; - - QFile file(fileName); -//! [export function part1] - -//! [export function part2] - if (!file.open(QIODevice::WriteOnly)) { - QMessageBox::information(this, tr("Unable to open file"), - file.errorString()); - return; - } - - QTextStream out(&file); -//! [export function part2] - -//! [export function part3] - out << "BEGIN:VCARD" << '\n'; - out << "VERSION:2.1" << '\n'; - out << "N:" << lastName << ';' << firstName << '\n'; - - if (!nameList.isEmpty()) - out << "FN:" << nameList.join(' ') << '\n'; - else - out << "FN:" << firstName << '\n'; -//! [export function part3] - -//! [export function part4] - address.replace(";", "\\;", Qt::CaseInsensitive); - address.replace('\n', ";", Qt::CaseInsensitive); - address.replace(",", " ", Qt::CaseInsensitive); - - out << "ADR;HOME:;" << address << '\n'; - out << "END:VCARD" << '\n'; - - QMessageBox::information(this, tr("Export Successful"), - tr("\"%1\" has been exported as a vCard.").arg(name)); -} -//! [export function part4] diff --git a/examples/widgets/tutorials/addressbook/part7/addressbook.h b/examples/widgets/tutorials/addressbook/part7/addressbook.h deleted file mode 100644 index c408a97642..0000000000 --- a/examples/widgets/tutorials/addressbook/part7/addressbook.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef ADDRESSBOOK_H -#define ADDRESSBOOK_H - -#include -#include -#include "finddialog.h" - -QT_BEGIN_NAMESPACE -class QPushButton; -class QLabel; -class QLineEdit; -class QTextEdit; -QT_END_NAMESPACE - - -class AddressBook : public QWidget -{ - Q_OBJECT - -public: - AddressBook(QWidget *parent = nullptr); - enum Mode { NavigationMode, AddingMode, EditingMode }; - -public slots: - void addContact(); - void editContact(); - void submitContact(); - void cancel(); - void removeContact(); - void findContact(); - void next(); - void previous(); - void saveToFile(); - void loadFromFile(); -//! [exportAsVCard() declaration] - void exportAsVCard(); -//! [exportAsVCard() declaration] - -private: - void updateInterface(Mode mode); - - QPushButton *addButton; - QPushButton *editButton; - QPushButton *removeButton; - QPushButton *findButton; - QPushButton *submitButton; - QPushButton *cancelButton; - QPushButton *nextButton; - QPushButton *previousButton; - QPushButton *loadButton; - QPushButton *saveButton; -//! [exportButton declaration] - QPushButton *exportButton; -//! [exportButton declaration] - QLineEdit *nameLine; - QTextEdit *addressText; - - QMap contacts; - FindDialog *dialog; - QString oldName; - QString oldAddress; - Mode currentMode; -}; - -#endif diff --git a/examples/widgets/tutorials/addressbook/part7/finddialog.cpp b/examples/widgets/tutorials/addressbook/part7/finddialog.cpp deleted file mode 100644 index 90729d9c12..0000000000 --- a/examples/widgets/tutorials/addressbook/part7/finddialog.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "finddialog.h" - -FindDialog::FindDialog(QWidget *parent) - : QDialog(parent) -{ - QLabel *findLabel = new QLabel(tr("Enter the name of a contact:")); - lineEdit = new QLineEdit; - - findButton = new QPushButton(tr("&Find")); - findText = ""; - - QHBoxLayout *layout = new QHBoxLayout; - layout->addWidget(findLabel); - layout->addWidget(lineEdit); - layout->addWidget(findButton); - - setLayout(layout); - setWindowTitle(tr("Find a Contact")); - connect(findButton, &QPushButton::clicked, - this, &FindDialog::findClicked); - connect(findButton, &QPushButton::clicked, - this, &FindDialog::accept); -} - -void FindDialog::findClicked() -{ - QString text = lineEdit->text(); - - if (text.isEmpty()) { - QMessageBox::information(this, tr("Empty Field"), - tr("Please enter a name.")); - return; - } else { - findText = text; - lineEdit->clear(); - hide(); - } -} - -QString FindDialog::getFindText() -{ - return findText; -} diff --git a/examples/widgets/tutorials/addressbook/part7/finddialog.h b/examples/widgets/tutorials/addressbook/part7/finddialog.h deleted file mode 100644 index 7c9a3af30f..0000000000 --- a/examples/widgets/tutorials/addressbook/part7/finddialog.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef FINDDIALOG_H -#define FINDDIALOG_H - -#include - -QT_BEGIN_NAMESPACE -class QLineEdit; -class QPushButton; -QT_END_NAMESPACE - -class FindDialog : public QDialog -{ - Q_OBJECT - -public: - FindDialog(QWidget *parent = nullptr); - QString getFindText(); - -public slots: - void findClicked(); - -private: - QPushButton *findButton; - QLineEdit *lineEdit; - QString findText; -}; - -#endif diff --git a/examples/widgets/tutorials/addressbook/part7/main.cpp b/examples/widgets/tutorials/addressbook/part7/main.cpp deleted file mode 100644 index 1f3aac3397..0000000000 --- a/examples/widgets/tutorials/addressbook/part7/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include -#include "addressbook.h" - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - AddressBook addressBook; - addressBook.show(); - - return app.exec(); -} diff --git a/examples/widgets/tutorials/addressbook/part7/part7.pro b/examples/widgets/tutorials/addressbook/part7/part7.pro deleted file mode 100644 index 6a99799c67..0000000000 --- a/examples/widgets/tutorials/addressbook/part7/part7.pro +++ /dev/null @@ -1,14 +0,0 @@ -QT += widgets -requires(qtConfig(filedialog)) - -SOURCES = addressbook.cpp \ - finddialog.cpp \ - main.cpp -HEADERS = addressbook.h \ - finddialog.h - -QMAKE_PROJECT_NAME = ab_part7 - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part7 -INSTALLS += target diff --git a/examples/widgets/tutorials/tutorials.pro b/examples/widgets/tutorials/tutorials.pro index 0aaa119d8f..5f6da54b2a 100644 --- a/examples/widgets/tutorials/tutorials.pro +++ b/examples/widgets/tutorials/tutorials.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS += addressbook widgets modelview gettingStarted notepad +SUBDIRS += widgets modelview gettingStarted notepad diff --git a/src/widgets/doc/images/addressbook-tutorial-part1-labeled-layout.png b/src/widgets/doc/images/addressbook-tutorial-part1-labeled-layout.png deleted file mode 100644 index b19cb360a1..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part1-labeled-layout.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part1-labeled-screenshot.png b/src/widgets/doc/images/addressbook-tutorial-part1-labeled-screenshot.png deleted file mode 100644 index f9b91eebe6..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part1-labeled-screenshot.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part1-screenshot.png b/src/widgets/doc/images/addressbook-tutorial-part1-screenshot.png deleted file mode 100644 index 454b0959e6..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part1-screenshot.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part2-add-contact.png b/src/widgets/doc/images/addressbook-tutorial-part2-add-contact.png deleted file mode 100644 index 6f2b947b21..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part2-add-contact.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part2-add-flowchart.png b/src/widgets/doc/images/addressbook-tutorial-part2-add-flowchart.png deleted file mode 100644 index ca9af3720d..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part2-add-flowchart.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part2-add-successful.png b/src/widgets/doc/images/addressbook-tutorial-part2-add-successful.png deleted file mode 100644 index 99a2154007..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part2-add-successful.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part2-labeled-layout.png b/src/widgets/doc/images/addressbook-tutorial-part2-labeled-layout.png deleted file mode 100644 index 1e000c8f31..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part2-labeled-layout.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part2-signals-and-slots.png b/src/widgets/doc/images/addressbook-tutorial-part2-signals-and-slots.png deleted file mode 100644 index e49f8dc262..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part2-signals-and-slots.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part2-stretch-effects.png b/src/widgets/doc/images/addressbook-tutorial-part2-stretch-effects.png deleted file mode 100644 index d9f7f31227..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part2-stretch-effects.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part3-labeled-layout.png b/src/widgets/doc/images/addressbook-tutorial-part3-labeled-layout.png deleted file mode 100644 index 1981ba8cb6..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part3-labeled-layout.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part3-linkedlist.png b/src/widgets/doc/images/addressbook-tutorial-part3-linkedlist.png deleted file mode 100644 index e7f4725dce..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part3-linkedlist.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part3-screenshot.png b/src/widgets/doc/images/addressbook-tutorial-part3-screenshot.png deleted file mode 100644 index 75159b4045..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part3-screenshot.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part4-remove.png b/src/widgets/doc/images/addressbook-tutorial-part4-remove.png deleted file mode 100644 index 8eb259ef02..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part4-remove.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part5-finddialog.png b/src/widgets/doc/images/addressbook-tutorial-part5-finddialog.png deleted file mode 100644 index 743d92ef6f..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part5-finddialog.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part5-notfound.png b/src/widgets/doc/images/addressbook-tutorial-part5-notfound.png deleted file mode 100644 index 2d35766ab5..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part5-notfound.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part5-screenshot.png b/src/widgets/doc/images/addressbook-tutorial-part5-screenshot.png deleted file mode 100644 index 3abe2775c2..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part5-screenshot.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part5-signals-and-slots.png b/src/widgets/doc/images/addressbook-tutorial-part5-signals-and-slots.png deleted file mode 100644 index 1771e7bbbf..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part5-signals-and-slots.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part6-load.png b/src/widgets/doc/images/addressbook-tutorial-part6-load.png deleted file mode 100644 index a027a1decb..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part6-load.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part6-save.png b/src/widgets/doc/images/addressbook-tutorial-part6-save.png deleted file mode 100644 index 757feeb9ac..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part6-save.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part6-screenshot.png b/src/widgets/doc/images/addressbook-tutorial-part6-screenshot.png deleted file mode 100644 index 7bb2f749bf..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part6-screenshot.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-part7-screenshot.png b/src/widgets/doc/images/addressbook-tutorial-part7-screenshot.png deleted file mode 100644 index 3e7b3ca522..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-part7-screenshot.png and /dev/null differ diff --git a/src/widgets/doc/images/addressbook-tutorial-screenshot.png b/src/widgets/doc/images/addressbook-tutorial-screenshot.png deleted file mode 100644 index 3fba6e849e..0000000000 Binary files a/src/widgets/doc/images/addressbook-tutorial-screenshot.png and /dev/null differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/CMakeLists.txt b/tests/manual/examples/widgets/tutorials/addressbook/CMakeLists.txt new file mode 100644 index 0000000000..c33e586df9 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_example(part1) +qt_internal_add_example(part2) +qt_internal_add_example(part3) +qt_internal_add_example(part4) +qt_internal_add_example(part5) +qt_internal_add_example(part6) +qt_internal_add_example(part7) diff --git a/tests/manual/examples/widgets/tutorials/addressbook/README b/tests/manual/examples/widgets/tutorials/addressbook/README new file mode 100644 index 0000000000..07897b9683 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/README @@ -0,0 +1,40 @@ +The Address Book Tutorial shows how to put together a simple yet +fully-functioning GUI application. The tutorial chapters can be found in the +Qt documentation, which can be viewed using Qt Assistant or a Web browser. + +The tutorial is also available online at + +http://qt-project.org/doc/qt-5.0/qtwidgets/tutorials-addressbook.html + +All programs corresponding to the chapters in the tutorial should +automatically be built when Qt is compiled, or will be provided as +pre-built executables if you have obtained a binary package of Qt. + +If you have only compiled the Qt libraries, use the following instructions +to build the tutorial. + +On Linux/Unix: + +Typing 'make' in this directory builds all the programs (part1/part1, +part2/part2, part3/part3 and so on). Typing 'make' in each subdirectory +builds just that tutorial program. + +On Windows: + +Create a single Visual Studio project for the tutorial directory in +the usual way. You can do this by typing the following at the command +line: + +qmake -tp vc + +You should now be able to open the project file in Visual Studio and +build all of the tutorial programs at the same time. + +On Mac OS X: + +Create an Xcode project with the .pro file in the tutorial directory. +You can do this by typing the following at the command line: + +qmake -spec macx-xcode + +Then open the generated Xcode project in Xcode and build it. diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-labeled-layout.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-labeled-layout.png new file mode 100644 index 0000000000..b19cb360a1 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-labeled-layout.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-labeled-screenshot.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-labeled-screenshot.png new file mode 100644 index 0000000000..f9b91eebe6 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-labeled-screenshot.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-screenshot.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-screenshot.png new file mode 100644 index 0000000000..454b0959e6 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part1-screenshot.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-contact.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-contact.png new file mode 100644 index 0000000000..6f2b947b21 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-contact.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-flowchart.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-flowchart.png new file mode 100644 index 0000000000..ca9af3720d Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-flowchart.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-successful.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-successful.png new file mode 100644 index 0000000000..99a2154007 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-add-successful.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-labeled-layout.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-labeled-layout.png new file mode 100644 index 0000000000..1e000c8f31 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-labeled-layout.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-signals-and-slots.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-signals-and-slots.png new file mode 100644 index 0000000000..e49f8dc262 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-signals-and-slots.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-stretch-effects.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-stretch-effects.png new file mode 100644 index 0000000000..d9f7f31227 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part2-stretch-effects.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-labeled-layout.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-labeled-layout.png new file mode 100644 index 0000000000..1981ba8cb6 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-labeled-layout.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-linkedlist.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-linkedlist.png new file mode 100644 index 0000000000..e7f4725dce Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-linkedlist.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-screenshot.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-screenshot.png new file mode 100644 index 0000000000..75159b4045 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part3-screenshot.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part4-remove.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part4-remove.png new file mode 100644 index 0000000000..8eb259ef02 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part4-remove.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-finddialog.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-finddialog.png new file mode 100644 index 0000000000..743d92ef6f Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-finddialog.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-notfound.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-notfound.png new file mode 100644 index 0000000000..2d35766ab5 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-notfound.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-screenshot.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-screenshot.png new file mode 100644 index 0000000000..3abe2775c2 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-screenshot.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-signals-and-slots.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-signals-and-slots.png new file mode 100644 index 0000000000..1771e7bbbf Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part5-signals-and-slots.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-load.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-load.png new file mode 100644 index 0000000000..a027a1decb Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-load.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-save.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-save.png new file mode 100644 index 0000000000..757feeb9ac Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-save.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-screenshot.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-screenshot.png new file mode 100644 index 0000000000..7bb2f749bf Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part6-screenshot.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part7-screenshot.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part7-screenshot.png new file mode 100644 index 0000000000..3e7b3ca522 Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-part7-screenshot.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-screenshot.png b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-screenshot.png new file mode 100644 index 0000000000..3fba6e849e Binary files /dev/null and b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial-screenshot.png differ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial.qdoc b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial.qdoc new file mode 100644 index 0000000000..2f7884bee8 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/addressbook-tutorial.qdoc @@ -0,0 +1,948 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \page tutorials-addressbook.html + + \title Address Book Tutorial + \ingroup examples-layout + \brief An introduction to GUI programming, showing how to put together a + simple yet fully-functioning application. + + This tutorial is an introduction to GUI programming with the Qt + cross-platform framework. + + \image addressbook-tutorial-screenshot.png + + \omit + It doesn't cover everything; the emphasis is on teaching the programming + philosophy of GUI programming, and Qt's features are introduced as needed. + Some commonly used features are never used in this tutorial. + \endomit + + In this tutorial, you will learn about some of the basic + components of Qt, including: + + \list + \li Widgets and layout managers + \li Container classes + \li Signals and slots + \li Input and output devices + \endlist + + Tutorial contents: + + \list 1 + \li \l{tutorials/addressbook/part1}{Designing the User Interface} + \li \l{tutorials/addressbook/part2}{Adding Addresses} + \li \l{tutorials/addressbook/part3}{Navigating between Entries} + \li \l{tutorials/addressbook/part4}{Editing and Removing Addresses} + \li \l{tutorials/addressbook/part5}{Adding a Find Function} + \li \l{tutorials/addressbook/part6}{Loading and Saving} + \li \l{tutorials/addressbook/part7}{Additional Features} + \endlist + + The tutorial source code is located in \c{tutorials/addressbook}. + + Although this little application does not look much like a + fully-fledged modern GUI application, it uses many of the basic + elements that are used in more complex applications. After you + have worked through this tutorial, we recommend reading the + \l{mainwindows/application}{Application} example, which presents a + small GUI application, with menus, toolbars, a status bar, and so + on. +*/ + +/*! + \example tutorials/addressbook/part1 + \title Part 1 - Designing the User Interface + \brief Describes how to code the user interface of the Address Book Example. + This first part covers the design of the basic graphical user + interface (GUI) for our address book application. + + The first step in creating a GUI program is to design the user + interface. Here the our goal is to set up the labels and input + fields to implement a basic address book. The figure below is a + screenshot of the expected output. + + \image addressbook-tutorial-part1-screenshot.png + + We require two QLabel objects, \c nameLabel and \c addressLabel, as well + as two input fields, a QLineEdit object, \c nameLine, and a QTextEdit + object, \c addressText, to enable the user to enter a contact's name and + address. The widgets used and their positions are shown in the figure + below. + + \image addressbook-tutorial-part1-labeled-screenshot.png + + There are three files used to implement this address book: + + \list + \li \c{addressbook.h} - the definition file for the \c AddressBook + class, + \li \c{addressbook.cpp} - the implementation file for the + \c AddressBook class, and + \li \c{main.cpp} - the file containing a \c main() function, with + an instance of \c AddressBook. + \endlist + + \section1 Qt Programming - Subclassing + + When writing Qt programs, we usually subclass Qt objects to add + functionality. This is one of the essential concepts behind creating + custom widgets or collections of standard widgets. Subclassing to + extend or change the behavior of a widget has the following advantages: + + \list + \li We can write implementations of virtual or pure virtual functions to + obtain exactly what we need, falling back on the base class's implementation + when necessary. + \li It allows us to encapsulate parts of the user interface within a class, + so that the other parts of the application don't need to know about the + individual widgets in the user interface. + \li The subclass can be used to create multiple custom widgets in the same + application or library, and the code for the subclass can be reused in other + projects. + \endlist + + Since Qt does not provide a specific address book widget, we subclass a + standard Qt widget class and add features to it. The \c AddressBook class + we create in this tutorial can be reused in situations where a basic address + book widget is needed. + + \section1 Defining the AddressBook Class + + The \c{tutorials/addressbook/part1/addressbook.h} file is + used to define the \c AddressBook class. + + We start by defining \c AddressBook as a QWidget subclass and declaring + a constructor. We also use the Q_OBJECT macro to indicate that the class + uses internationalization and Qt's signals and slots features, even + if we do not use all of these features at this stage. + + \snippet tutorials/addressbook/part1/addressbook.h class definition + + The class holds declarations of \c nameLine and \c addressText, + the private instances of QLineEdit and QTextEdit mentioned + earlier. The data stored in \c nameLine and \c addressText will + be needed for many of the address book functions. + + We don't include declarations of the QLabel objects we will use + because we will not need to reference them once they have been + created. The way Qt tracks the ownership of objects is explained + in the next section. + + The Q_OBJECT macro itself implements some of the more advanced features of Qt. + For now, it is useful to think of the Q_OBJECT macro as a shortcut which allows + us to use the \l{QObject::}{tr()} and \l{QObject::}{connect()} functions. + + We have now completed the \c addressbook.h file and we move on to + implement the corresponding \c addressbook.cpp file. + + \section1 Implementing the AddressBook Class + + The constructor of \c AddressBook accepts a QWidget parameter, \a parent. + By convention, we pass this parameter to the base class's constructor. + This concept of ownership, where a parent can have one or more children, + is useful for grouping widgets in Qt. For example, if you delete a parent, + all of its children will be deleted as well. + + \snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields + + In this constructor, the QLabel objects \c nameLabel and \c + addressLabel are instantiated, as well as \c nameLine and \c + addressText. The \l{QObject::tr()}{tr()} function returns a + translated version of the string, if there is one + available. Otherwise it returns the string itself. This function + marks its QString parameter as one that should be translated into + other languages. It should be used wherever a translatable string + appears. + + When programming with Qt, it is useful to know how layouts work. + Qt provides three main layout classes: QHBoxLayout, QVBoxLayout + and QGridLayout to handle the positioning of widgets. + + \image addressbook-tutorial-part1-labeled-layout.png + + We use a QGridLayout to position our labels and input fields in a + structured manner. QGridLayout divides the available space into a grid and + places widgets in the cells we specify with row and column numbers. The + diagram above shows the layout cells and the position of our widgets, and + we specify this arrangement using the following code: + + \snippet tutorials/addressbook/part1/addressbook.cpp layout + + Notice that \c addressLabel is positioned using Qt::AlignTop as an + additional argument. This is to make sure it is not vertically centered in + cell (1,0). For a basic overview on Qt Layouts, refer to the + \l{Layout Management} documentation. + + In order to install the layout object onto the widget, we have to invoke + the widget's \l{QWidget::setLayout()}{setLayout()} function: + + \snippet tutorials/addressbook/part1/addressbook.cpp setting the layout + + Lastly, we set the widget's title to "Simple Address Book". + + \section1 Running the Application + + A separate file, \c main.cpp, is used for the \c main() function. Within + this function, we instantiate a QApplication object, \c app. QApplication + is responsible for various application-wide resources, such as the default + font and cursor, and for running an event loop. Hence, there is always one + QApplication object in every GUI application using Qt. + + \snippet tutorials/addressbook/part1/main.cpp main function + + We construct a new \c AddressBook widget on the stack and invoke + its \l{QWidget::show()}{show()} function to display it. + However, the widget will not be shown until the application's event loop + is started. We start the event loop by calling the application's + \l{QApplication::}{exec()} function; the result returned by this function + is used as the return value from the \c main() function. At this point, + it becomes apparent why we instantiated \c AddressBook on the stack: It + will now go out of scope. Therefore, \c AddressBook and all its child widgets + will be deleted, thus preventing memory leaks. +*/ + +/*! + \example tutorials/addressbook/part2 + \title Part 2 - Adding Addresses + \brief Describes the code for inserting records in the Address Book Example. + + The next step in creating the address book is to implement some + user interactions. + + \image addressbook-tutorial-part2-add-contact.png + + We will provide a push button that the user can click to add a new contact. + Also, some form of data structure is needed to store these contacts in an + organized way. + + \section1 Defining the AddressBook Class + + Now that we have the labels and input fields set up, we add push buttons to + complete the process of adding a contact. This means that our + \c addressbook.h file now has three QPushButton objects declared and three + corresponding public slots. + + \snippet tutorials/addressbook/part2/addressbook.h slots + + A slot is a function that responds to a particular signal. We will discuss + this concept in further detail when implementing the \c AddressBook class. + However, for an overview of Qt's signals and slots concept, you can refer + to the \l{Signals and Slots} document. + + Three QPushButton objects (\c addButton, \c submitButton, and + \c cancelButton) are now included in our private variable declarations, + along with \c nameLine and \c addressText. + + \snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration + + We need a container to store our address book contacts, so that we can + traverse and display them. A QMap object, \c contacts, is used for this + purpose as it holds a key-value pair: the contact's name as the \e key, + and the contact's address as the \e{value}. + + \snippet tutorials/addressbook/part2/addressbook.h remaining private variables + + We also declare two private QString objects, \c oldName and \c oldAddress. + These objects are needed to hold the name and address of the contact that + was last displayed, before the user clicked \uicontrol Add. So, when the user clicks + \uicontrol Cancel, we can revert to displaying the details of the last contact. + + \section1 Implementing the AddressBook Class + + Within the constructor of \c AddressBook, we set the \c nameLine and + \c addressText to read-only, so that we can only display but not edit + existing contact details. + + \dots + \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 1 + \dots + \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 2 + + Then, we instantiate our push buttons: \c addButton, \c submitButton, and + \c cancelButton. + + \snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration + + The \c addButton is displayed by invoking the \l{QPushButton::show()} + {show()} function, while the \c submitButton and \c cancelButton are + hidden by invoking \l{QPushButton::hide()}{hide()}. These two push + buttons will only be displayed when the user clicks \uicontrol Add and this is + handled by the \c addContact() function discussed below. + + \snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots + + We connect the push buttons' \l{QPushButton::clicked()}{clicked()} signal + to their respective slots. The figure below illustrates this. + + \image addressbook-tutorial-part2-signals-and-slots.png + + Next, we arrange our push buttons neatly to the right of our address book + widget, using a QVBoxLayout to line them up vertically. + + \snippet tutorials/addressbook/part2/addressbook.cpp vertical layout + + The \l{QBoxLayout::addStretch()}{addStretch()} function is used to ensure + the push buttons are not evenly spaced, but arranged closer to the top of + the widget. The figure below shows the difference between using + \l{QBoxLayout::addStretch()}{addStretch()} and not using it. + + \image addressbook-tutorial-part2-stretch-effects.png + + We then add \c buttonLayout1 to \c mainLayout, using + \l{QGridLayout::addLayout()}{addLayout()}. This gives us nested layouts + as \c buttonLayout1 is now a child of \c mainLayout. + + \snippet tutorials/addressbook/part2/addressbook.cpp grid layout + + Our layout coordinates now look like this: + + \image addressbook-tutorial-part2-labeled-layout.png + + In the \c addContact() function, we store the last displayed contact + details in \c oldName and \c oldAddress. Then we clear these input + fields and turn off the read-only mode. The focus is set on \c nameLine + and we display \c submitButton and \c cancelButton. + + \snippet tutorials/addressbook/part2/addressbook.cpp addContact + + The \c submitContact() function can be divided into three parts: + + \list 1 + \li We extract the contact's details from \c nameLine and \c addressText + and store them in QString objects. We also validate to make sure that the + user did not click \uicontrol Submit with empty input fields; otherwise, a + QMessageBox is displayed to remind the user for a name and address. + + \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1 + + \li We then proceed to check if the contact already exists. If it does not + exist, we add the contact to \c contacts and we display a QMessageBox to + inform the user that the contact has been added. + + \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2 + + If the contact already exists, again, we display a QMessageBox to inform + the user about this, preventing the user from adding duplicate contacts. + Our \c contacts object is based on key-value pairs of name and address, + hence, we want to ensure that \e key is unique. + + \li Once we have handled both cases mentioned above, we restore the push + buttons to their normal state with the following code: + + \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3 + + \endlist + + The screenshot below shows the QMessageBox object we use to display + information messages to the user. + + \image addressbook-tutorial-part2-add-successful.png + + The \c cancel() function restores the last displayed contact details and + enables \c addButton, as well as hides \c submitButton and + \c cancelButton. + + \snippet tutorials/addressbook/part2/addressbook.cpp cancel + + The general idea behind adding a contact is to give the user the + flexibility to click \uicontrol Submit or \uicontrol Cancel at any time. The flowchart below + further explains this concept: + + \image addressbook-tutorial-part2-add-flowchart.png +*/ + +/*! + \example tutorials/addressbook/part3 + \title Part 3 - Navigating between Entries + \brief Explains the code that enables navigating the contacts. + + The address book is now about half complete. We should add the + capability to navigate the contacts, but first we must + decide what sort of a data structure we need for containing these + contacts. + + In the previous section, we used a QMap of key-value pairs with + the contact's name as the \e key, and the contact's address as the + \e value. This works well for our case. However, in order to + navigate and display each entry, a little bit of enhancement is + needed. + + We enhance the QMap by making it replicate a data structure similar to a + circularly-linked list, where all elements are connected, including the + first element and the last element. The figure below illustrates this data + structure. + + \image addressbook-tutorial-part3-linkedlist.png + + \section1 Defining the AddressBook Class + + To add navigation functions to the address book, we must add two + more slots to the \c AddressBook class: \c next() and \c + previous() to the \c addressbook.h file: + + \snippet tutorials/addressbook/part3/addressbook.h navigation functions + + We also require another two QPushButton objects, so we declare \c nextButton + and \c previousButton as private variables: + + \snippet tutorials/addressbook/part3/addressbook.h navigation pushbuttons + + \section1 Implementing the AddressBook Class + + In the \c AddressBook constructor in \c addressbook.cpp, we instantiate + \c nextButton and \c previousButton and disable them by default. This is + because navigation is only enabled when there is more than one contact + in the address book. + + \snippet tutorials/addressbook/part3/addressbook.cpp navigation pushbuttons + + We then connect these push buttons to their respective slots: + + \snippet tutorials/addressbook/part3/addressbook.cpp connecting navigation signals + + The image below is the expected graphical user interface. + + \image addressbook-tutorial-part3-screenshot.png + + We follow basic conventions for \c next() and \c previous() functions by + placing the \c nextButton on the right and the \c previousButton on the + left. In order to achieve this intuitive layout, we use QHBoxLayout to + place the widgets side-by-side: + + \snippet tutorials/addressbook/part3/addressbook.cpp navigation layout + + The QHBoxLayout object, \c buttonLayout2, is then added to \c mainLayout. + + \snippet tutorials/addressbook/part3/addressbook.cpp adding navigation layout + + The figure below shows the coordinates of the widgets in \c mainLayout. + \image addressbook-tutorial-part3-labeled-layout.png + + Within our \c addContact() function, we have to disable these buttons so + that the user does not attempt to navigate while adding a contact. + + \snippet tutorials/addressbook/part3/addressbook.cpp disabling navigation + + Also, in our \c submitContact() function, we enable the navigation + buttons, \c nextButton and \c previousButton, depending on the size + of \c contacts. As mentioned earlier, navigation is only enabled when + there is more than one contact in the address book. The following lines + of code demonstrates how to do this: + + \snippet tutorials/addressbook/part3/addressbook.cpp enabling navigation + + We also include these lines of code in the \c cancel() function. + + Recall that we intend to emulate a circularly-linked list with our QMap + object, \c contacts. So, in the \c next() function, we obtain an iterator + for \c contacts and then: + + \list + \li If the iterator is not at the end of \c contacts, we increment it + by one. + \li If the iterator is at the end of \c contacts, we move it to the + beginning of \c contacts. This gives us the illusion that our QMap is + working like a circularly-linked list. + \endlist + + \snippet tutorials/addressbook/part3/addressbook.cpp next() function + + Once we have iterated to the correct object in \c contacts, we display + its contents on \c nameLine and \c addressText. + + Similarly, for the \c previous() function, we obtain an iterator for + \c contacts and then: + + \list + \li If the iterator is at the end of \c contacts, we clear the + display and return. + \li If the iterator is at the beginning of \c contacts, we move it to + the end. + \li We then decrement the iterator by one. + \endlist + + \snippet tutorials/addressbook/part3/addressbook.cpp previous() function + + Again, we display the contents of the current object in \c contacts. + +*/ + +/*! + \example tutorials/addressbook/part4 + \title Part 4 - Editing and Removing Addresses + \brief Explains how to add edit and remove functionality. + + Now we look at ways to modify the contents of contacts stored in + the address book. + + \image addressbook-tutorial-screenshot.png + + We now have an address book that not only holds contacts in an + organized manner, but also allows navigation. It would be + convenient to include edit and remove functions so that a + contact's details can be changed when needed. However, this + requires a little improvement, in the form of enums. We defined + two modes: \c{AddingMode} and \c{NavigationMode}, but they were + not defined as enum values. Instead, we enabled and disabled the + corresponding buttons manually, resulting in multiple lines of + repeated code. + + Here we define the \c Mode enum with three different values: + + \list + \li \c{NavigationMode}, + \li \c{AddingMode}, and + \li \c{EditingMode}. + \endlist + + \section1 Defining the AddressBook Class + + The \c addressbook.h file is updated to contain the \c Mode enum: + + \snippet tutorials/addressbook/part4/addressbook.h Mode enum + + We also add two new slots, \c editContact() and \c removeContact(), to + our current list of public slots. + + \snippet tutorials/addressbook/part4/addressbook.h edit and remove slots + + In order to switch between modes, we introduce the \c updateInterface() function + to control the enabling and disabling of all QPushButton objects. We also + add two new push buttons, \c editButton and \c removeButton, for the edit + and remove functions mentioned earlier. + + \snippet tutorials/addressbook/part4/addressbook.h updateInterface() declaration + \dots + \snippet tutorials/addressbook/part4/addressbook.h buttons declaration + \dots + \snippet tutorials/addressbook/part4/addressbook.h mode declaration + + Lastly, we declare \c currentMode to keep track of the enum's current mode. + + \section1 Implementing the AddressBook Class + + We now implement the mode-changing features of the address + book. The \c editButton and \c removeButton are instantiated and + disabled by default. The address book starts with zero contacts + in memory. + + \snippet tutorials/addressbook/part4/addressbook.cpp edit and remove buttons + + These buttons are then connected to their respective slots, \c editContact() + and \c removeContact(), and we add them to \c buttonLayout1. + + \snippet tutorials/addressbook/part4/addressbook.cpp connecting edit and remove + \dots + \snippet tutorials/addressbook/part4/addressbook.cpp adding edit and remove to the layout + + The \c editContact() function stores the contact's old details in + \c oldName and \c oldAddress, before switching the mode to \c EditingMode. + In this mode, the \c submitButton and \c cancelButton are both enabled, + hence, the user can change the contact's details and click either button. + + \snippet tutorials/addressbook/part4/addressbook.cpp editContact() function + + The \c submitContact() function has been divided in two with an \c{if-else} + statement. We check \c currentMode to see if it's in \c AddingMode. If it is, + we proceed with our adding process. + + \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function beginning + \dots + \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part1 + + Otherwise, we check to see if \c currentMode is in \c EditingMode. If it + is, we compare \c oldName with \c name. If the name has changed, we remove + the old contact from \c contacts and insert the newly updated contact. + + \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part2 + + If only the address has changed (i.e., \c oldAddress is not the same as \c address), + we update the contact's address. Lastly, we set \c currentMode to + \c NavigationMode. This is an important step as it re-enables all the + disabled push buttons. + + To remove a contact from the address book, we implement the + \c removeContact() function. This function checks to see if the contact + exists in \c contacts. + + \snippet tutorials/addressbook/part4/addressbook.cpp removeContact() function + + If it does, we display a QMessageBox, to confirm the removal with the + user. Once the user has confirmed, we call \c previous() to ensure that the + user interface shows another contact, and we remove the contact using \l{QMap}'s + \l{QMap::remove()}{remove()} function. As a courtesy, we display a QMessageBox + to inform the user. Both the message boxes used in this function are shown below: + + \image addressbook-tutorial-part4-remove.png + + \section2 Updating the User Interface + + We mentioned the \c updateInterface() function earlier as a means to + enable and disable the push buttons depending on the current mode. + The function updates the current mode according to the \c mode argument + passed to it, assigning it to \c currentMode before checking its value. + + Each of the push buttons is then enabled or disabled, depending on the + current mode. The code for \c AddingMode and \c EditingMode is shown below: + + \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 1 + + For \c NavigationMode, however, we include conditions within the parameters + of the QPushButton::setEnabled() function. This is to ensure that + \c editButton and \c removeButton are enabled when there is at least one + contact in the address book; \c nextButton and \c previousButton are only + enabled when there is more than one contact in the address book. + + \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 2 + + By setting the mode and updating the user interface in the same + function, we avoid the possibility of the user interface getting + out of sync with the internal state of the application. + */ + +/*! + \example tutorials/addressbook/part5 + \title Part 5 - Adding a Find Function + \brief Describes how to add a find function. + + Here we look at ways to locate contacts and addresses in the + address book. + + \image addressbook-tutorial-part5-screenshot.png + + As we add contacts to our address book, it becomes tedious to + navigate the list with the \e Next and \e Previous buttons. A \e + Find function would be more efficient. The screenshot above shows + the \e Find button and its position on the panel of buttons. + + When the user clicks on the \e Find button, it is useful to + display a dialog that prompts for a contact's name. Qt provides + QDialog, which we subclass here to implement a \c FindDialog + class. + + \section1 Defining the FindDialog Class + + \image addressbook-tutorial-part5-finddialog.png + + In order to subclass QDialog, we first include the header for QDialog in + the \c finddialog.h file. Also, we use forward declaration to declare + QLineEdit and QPushButton since we will be using those widgets in our + dialog class. + + As in our \c AddressBook class, the \c FindDialog class includes + the Q_OBJECT macro and its constructor is defined to accept a parent + QWidget, even though the dialog will be opened as a separate window. + + \snippet tutorials/addressbook/part5/finddialog.h FindDialog header + + We define a public function, \c getFindText(), to be used by classes that + instantiate \c FindDialog. This function allows these classes to obtain the + search string entered by the user. A public slot, \c findClicked(), is also + defined to handle the search string when the user clicks the \uicontrol Find + button. + + Lastly, we define the private variables, \c findButton, \c lineEdit + and \c findText, corresponding to the \uicontrol Find button, the line edit + into which the user types the search string, and an internal string + used to store the search string for later use. + + \section1 Implementing the FindDialog Class + + Within the constructor of \c FindDialog, we set up the private variables, + \c lineEdit, \c findButton and \c findText. We use a QHBoxLayout to + position the widgets. + + \snippet tutorials/addressbook/part5/finddialog.cpp constructor + + We set the layout and window title, as well as connect the signals to their + respective slots. Notice that \c{findButton}'s \l{QPushButton::clicked()} + {clicked()} signal is connected to \c findClicked() and + \l{QDialog::accept()}{accept()}. The \l{QDialog::accept()}{accept()} slot + provided by QDialog hides the dialog and sets the result code to + \l{QDialog::}{Accepted}. We use this function to help \c{AddressBook}'s + \c findContact() function know when the \c FindDialog object has been + closed. We will explain this logic in further detail when discussing the + \c findContact() function. + + \image addressbook-tutorial-part5-signals-and-slots.png + + In \c findClicked(), we validate \c lineEdit to ensure that the user + did not click the \uicontrol Find button without entering a contact's name. Then, we set + \c findText to the search string, extracted from \c lineEdit. After that, + we clear the contents of \c lineEdit and hide the dialog. + + \snippet tutorials/addressbook/part5/finddialog.cpp findClicked() function + + The \c findText variable has a public getter function, \c getFindText(), + associated with it. Since we only ever set \c findText directly in both the + constructor and in the \c findClicked() function, we do not create a + setter function to accompany \c getFindText(). + Because \c getFindText() is public, classes instantiating and using + \c FindDialog can always access the search string that the user has + entered and accepted. + + \snippet tutorials/addressbook/part5/finddialog.cpp getFindText() function + + \section1 Defining the AddressBook Class + + To ensure we can use \c FindDialog from within our \c AddressBook class, we + include \c finddialog.h in the \c addressbook.h file. + + \snippet tutorials/addressbook/part5/addressbook.h include finddialog's header + + So far, all our address book features have a QPushButton and a + corresponding slot. Similarly, for the \uicontrol Find feature we have + \c findButton and \c findContact(). + + The \c findButton is declared as a private variable and the + \c findContact() function is declared as a public slot. + + \snippet tutorials/addressbook/part5/addressbook.h findContact() declaration + \dots + \snippet tutorials/addressbook/part5/addressbook.h findButton declaration + + Lastly, we declare the private variable, \c dialog, which we will use to + refer to an instance of \c FindDialog. + + \snippet tutorials/addressbook/part5/addressbook.h FindDialog declaration + + Once we have instantiated a dialog, we will want to use it more than once; + using a private variable allows us to refer to it from more than one place + in the class. + + \section1 Implementing the AddressBook Class + + Within the \c AddressBook class's constructor, we instantiate our private + objects, \c findButton and \c findDialog: + + \snippet tutorials/addressbook/part5/addressbook.cpp instantiating findButton + \dots + \snippet tutorials/addressbook/part5/addressbook.cpp instantiating FindDialog + + Next, we connect the \c{findButton}'s + \l{QPushButton::clicked()}{clicked()} signal to \c findContact(). + + \snippet tutorials/addressbook/part5/addressbook.cpp signals and slots for find + + Now all that is left is the code for our \c findContact() function: + + \snippet tutorials/addressbook/part5/addressbook.cpp findContact() function + + We start out by displaying the \c FindDialog instance, \c dialog. This is + when the user enters a contact name to look up. Once the user clicks + the dialog's \c findButton, the dialog is hidden and the result code is + set to QDialog::Accepted. This ensures that + our \c if statement is always true. + + We then proceed to extract the search string, which in this case is + \c contactName, using \c{FindDialog}'s \c getFindText() function. If the + contact exists in our address book, we display it immediately. Otherwise, + we display the QMessageBox shown below to indicate that their search + failed. + + \image addressbook-tutorial-part5-notfound.png +*/ + +/*! + \example tutorials/addressbook/part6 + \title Part 6 - Loading and Saving + \brief Describes how to add save and load functionality. + + This part covers the Qt file handling features we use to write + loading and saving routines for the address book. + + \image addressbook-tutorial-part6-screenshot.png + + Although browsing and searching the contact list are useful + features, our address book is not complete until we can save + existing contacts and load them again at a later time. + + Qt provides a number of classes for \l{Input/Output and Networking} + {input and output}, but we have chosen to use two which are simple to use + in combination: QFile and QDataStream. + + A QFile object represents a file on disk that can be read from and written + to. QFile is a subclass of the more general QIODevice class which + represents many different kinds of devices. + + A QDataStream object is used to serialize binary data so that it can be + stored in a QIODevice and retrieved again later. Reading from a QIODevice + and writing to it is as simple as opening the stream - with the respective + device as a parameter - and reading from or writing to it. + + + \section1 Defining the AddressBook Class + + We declare two public slots, \c saveToFile() and \c loadFromFile(), as well + as two QPushButton objects, \c loadButton and \c saveButton. + + \snippet tutorials/addressbook/part6/addressbook.h save and load functions declaration + \dots + \snippet tutorials/addressbook/part6/addressbook.h save and load buttons declaration + + \section1 Implementing the AddressBook Class + + In our constructor, we instantiate \c loadButton and \c saveButton. + Ideally, it would be more user-friendly to set the push buttons' labels + to "Load contacts from a file" and "Save contacts to a file". However, due + to the size of our other push buttons, we set the labels to \uicontrol{Load...} + and \uicontrol{Save...}. Fortunately, Qt provides a simple way to set tooltips with + \l{QWidget::setToolTip()}{setToolTip()} and we use it in the following way + for our push buttons: + + \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 1 + \dots + \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 2 + + Although it is not shown here, just like the other features we implemented, + we add the push buttons to the layout panel on the right, \c buttonLayout1, + and we connect the push buttons' \l{QPushButton::clicked()}{clicked()} + signals to their respective slots. + + For the saving feature, we first obtain \c fileName using + QFileDialog::getSaveFileName(). This is a convenience function provided + by QFileDialog, which pops up a modal file dialog and allows the user to + enter a file name or select any existing \c{.abk} file. The \c{.abk} file + is our Address Book extension that we create when we save contacts. + + \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part1 + + The file dialog that pops up is displayed in the screenshot below: + + \image addressbook-tutorial-part6-save.png + + If \c fileName is not empty, we create a QFile object, \c file, with + \c fileName. QFile works with QDataStream as QFile is a QIODevice. + + Next, we attempt to open the file in \l{QIODeviceBase::}{WriteOnly} mode. + If this is unsuccessful, we display a QMessageBox to inform the user. + + \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part2 + + Otherwise, we instantiate a QDataStream object, \c out, to write the open + file. QDataStream requires that the same version of the stream is used + for reading and writing. We ensure that this is the case by setting the + version used to the \l{QDataStream::Qt_4_5}{version introduced with Qt 4.5} + before serializing the data to \c file. + + \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part3 + + For the loading feature, we also obtain \c fileName using + QFileDialog::getOpenFileName(). This function, the counterpart to + QFileDialog::getSaveFileName(), also pops up the modal file dialog and + allows the user to enter a file name or select any existing \c{.abk} file + to load it into the address book. + + \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part1 + + On Windows, for example, this function pops up a native file dialog, as + shown in the following screenshot. + + \image addressbook-tutorial-part6-load.png + + If \c fileName is not empty, again, we use a QFile object, \c file, and + attempt to open it in \l{QIODeviceBase::}{ReadOnly} mode. Similar to our + implementation of \c saveToFile(), if this attempt is unsuccessful, we + display a QMessageBox to inform the user. + + \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part2 + + Otherwise, we instantiate a QDataStream object, \c in, set its version as + above and read the serialized data into the \c contacts data structure. + The \c contacts object is emptied before data is read into it to simplify + the file reading process. A more advanced method would be to read the + contacts into a temporary QMap object, and copy over non-duplicate contacts + into \c contacts. + + \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part3 + + To display the contacts that have been read from the file, we must first + validate the data obtained to ensure that the file we read from actually + contains address book contacts. If it does, we display the first contact; + otherwise, we display a QMessageBox to inform the user about the problem. + Lastly, we update the interface to enable and disable the push buttons + accordingly. +*/ + +/*! + \example tutorials/addressbook/part7 + \title Part 7 - Additional Features + \brief Describes how to export data in VCard format. + + This part covers some additional features that make the address + book more convenient for the frequent user. + + \image addressbook-tutorial-part7-screenshot.png + + Although our address book is useful in isolation, it would be + better if we could exchange contact data with other applications. + The vCard format is a popular file format that can be used for + this purpose. Here we extend our address book client to allow + contacts to be exported to vCard \c{.vcf} files. + + \section1 Defining the AddressBook Class + + We add a QPushButton object, \c exportButton, and a corresponding public + slot, \c exportAsVCard() to our \c AddressBook class in the + \c addressbook.h file. + + \snippet tutorials/addressbook/part7/addressbook.h exportAsVCard() declaration + \dots + \snippet tutorials/addressbook/part7/addressbook.h exportButton declaration + + \section1 Implementing the AddressBook Class + + Within the \c AddressBook constructor, we connect \c{exportButton}'s + \l{QPushButton::clicked()}{clicked()} signal to \c exportAsVCard(). + We also add this button to our \c buttonLayout1, the layout responsible + for our panel of buttons on the right. + + In our \c exportAsVCard() function, we start by extracting the contact's + name into \c name. We declare \c firstName, \c lastName and \c nameList. + Next, we look for the index of the first white space in \c name. If there + is a white space, we split the contact's name into \c firstName and + \c lastName. Then, we replace the space with an underscore ("_"). + Alternately, if there is no white space, we assume that the contact only + has a first name. + + \snippet tutorials/addressbook/part7/addressbook.cpp export function part1 + + As with the \c saveToFile() function, we open a file dialog to let the user + choose a location for the file. Using the file name chosen, we create an + instance of QFile to write to. + + We attempt to open the file in \l{QIODeviceBase::}{WriteOnly} mode. If this + process fails, we display a QMessageBox to inform the user about the + problem and return. Otherwise, we pass the file as a parameter to a + QTextStream object, \c out. Like QDataStream, the QTextStream class + provides functionality to read and write plain text to files. As a result, + the \c{.vcf} file generated can be opened for editing in a text editor. + + \snippet tutorials/addressbook/part7/addressbook.cpp export function part2 + + We then write out a vCard file with the \c{BEGIN:VCARD} tag, followed by + the \c{VERSION:2.1} tag. The contact's name is written with the \c{N:} + tag. For the \c{FN:} tag, which fills in the "File as" property of a vCard, + we have to check whether the contact has a last name or not. If the contact + does, we use the details in \c nameList to fill it. Otherwise, we write + \c firstName only. + + \snippet tutorials/addressbook/part7/addressbook.cpp export function part3 + + We proceed to write the contact's address. The semicolons in the address + are escaped with "\\", the newlines are replaced with semicolons, and the + commas are replaced with spaces. Lastly, we write the \c{ADR;HOME:;} + tag, followed by \c address and then the \c{END:VCARD} tag. + + \snippet tutorials/addressbook/part7/addressbook.cpp export function part4 + + In the end, a QMessageBox is displayed to inform the user that the vCard + has been successfully exported. + + \e{vCard is a trademark of the \l{http://www.imc.org} + {Internet Mail Consortium}}. +*/ diff --git a/tests/manual/examples/widgets/tutorials/addressbook/addressbook.pro b/tests/manual/examples/widgets/tutorials/addressbook/addressbook.pro new file mode 100644 index 0000000000..d31424998e --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/addressbook.pro @@ -0,0 +1,6 @@ +TEMPLATE = subdirs +SUBDIRS = part1 part2 part3 part4 part5 part6 part7 + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook +INSTALLS += target diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part1/CMakeLists.txt b/tests/manual/examples/widgets/tutorials/addressbook/part1/CMakeLists.txt new file mode 100644 index 0000000000..9d3fd8ce07 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part1/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(part1 LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part1") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(part1 + addressbook.cpp addressbook.h + main.cpp +) + +set_target_properties(part1 PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(part1 PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS part1 + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part1/addressbook.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part1/addressbook.cpp new file mode 100644 index 0000000000..eae818dbbf --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part1/addressbook.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +//! [constructor and input fields] +AddressBook::AddressBook(QWidget *parent) + : QWidget(parent) +{ + QLabel *nameLabel = new QLabel(tr("Name:")); + nameLine = new QLineEdit; + + QLabel *addressLabel = new QLabel(tr("Address:")); + addressText = new QTextEdit; +//! [constructor and input fields] + +//! [layout] + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(nameLabel, 0, 0); + mainLayout->addWidget(nameLine, 0, 1); + mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); + mainLayout->addWidget(addressText, 1, 1); +//! [layout] + +//![setting the layout] + setLayout(mainLayout); + setWindowTitle(tr("Simple Address Book")); +} +//! [setting the layout] diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part1/addressbook.h b/tests/manual/examples/widgets/tutorials/addressbook/part1/addressbook.h new file mode 100644 index 0000000000..f2e28b4135 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part1/addressbook.h @@ -0,0 +1,29 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ADDRESSBOOK_H +#define ADDRESSBOOK_H + +#include + +QT_BEGIN_NAMESPACE +class QLabel; +class QLineEdit; +class QTextEdit; +QT_END_NAMESPACE + +//! [class definition] +class AddressBook : public QWidget +{ + Q_OBJECT + +public: + AddressBook(QWidget *parent = nullptr); + +private: + QLineEdit *nameLine; + QTextEdit *addressText; +}; +//! [class definition] + +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part1/main.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part1/main.cpp new file mode 100644 index 0000000000..879fb606a2 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part1/main.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +//! [main function] +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + AddressBook addressBook; + addressBook.show(); + + return app.exec(); +} +//! [main function] diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part1/part1.pro b/tests/manual/examples/widgets/tutorials/addressbook/part1/part1.pro new file mode 100644 index 0000000000..35d4a0152e --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part1/part1.pro @@ -0,0 +1,11 @@ +QT += widgets + +SOURCES = addressbook.cpp \ + main.cpp +HEADERS = addressbook.h + +QMAKE_PROJECT_NAME = ab_part1 + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part1 +INSTALLS += target diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part2/CMakeLists.txt b/tests/manual/examples/widgets/tutorials/addressbook/part2/CMakeLists.txt new file mode 100644 index 0000000000..35bd202f9a --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part2/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(part2 LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part2") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(part2 + addressbook.cpp addressbook.h + main.cpp +) + +set_target_properties(part2 PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(part2 PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS part2 + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part2/addressbook.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part2/addressbook.cpp new file mode 100644 index 0000000000..085103c791 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part2/addressbook.cpp @@ -0,0 +1,123 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +AddressBook::AddressBook(QWidget *parent) + : QWidget(parent) +{ + QLabel *nameLabel = new QLabel(tr("Name:")); + nameLine = new QLineEdit; +//! [setting readonly 1] + nameLine->setReadOnly(true); +//! [setting readonly 1] + QLabel *addressLabel = new QLabel(tr("Address:")); + addressText = new QTextEdit; +//! [setting readonly 2] + addressText->setReadOnly(true); +//! [setting readonly 2] + +//! [pushbutton declaration] + addButton = new QPushButton(tr("&Add")); + addButton->show(); + submitButton = new QPushButton(tr("&Submit")); + submitButton->hide(); + cancelButton = new QPushButton(tr("&Cancel")); + cancelButton->hide(); +//! [pushbutton declaration] +//! [connecting signals and slots] + connect(addButton, &QPushButton::clicked, + this, &AddressBook::addContact); + connect(submitButton, &QPushButton::clicked, + this, &AddressBook::submitContact); + connect(cancelButton, &QPushButton::clicked, + this, &AddressBook::cancel); +//! [connecting signals and slots] +//! [vertical layout] + QVBoxLayout *buttonLayout1 = new QVBoxLayout; + buttonLayout1->addWidget(addButton, Qt::AlignTop); + buttonLayout1->addWidget(submitButton); + buttonLayout1->addWidget(cancelButton); + buttonLayout1->addStretch(); +//! [vertical layout] +//! [grid layout] + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(nameLabel, 0, 0); + mainLayout->addWidget(nameLine, 0, 1); + mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); + mainLayout->addWidget(addressText, 1, 1); + mainLayout->addLayout(buttonLayout1, 1, 2); +//! [grid layout] + setLayout(mainLayout); + setWindowTitle(tr("Simple Address Book")); +} +//! [addContact] +void AddressBook::addContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + nameLine->clear(); + addressText->clear(); + + nameLine->setReadOnly(false); + nameLine->setFocus(Qt::OtherFocusReason); + addressText->setReadOnly(false); + + addButton->setEnabled(false); + submitButton->show(); + cancelButton->show(); +} +//! [addContact] + +//! [submitContact part1] +void AddressBook::submitContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (name.isEmpty() || address.isEmpty()) { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name and address.")); + return; + } +//! [submitContact part1] +//! [submitContact part2] + if (!contacts.contains(name)) { + contacts.insert(name, address); + QMessageBox::information(this, tr("Add Successful"), + tr("\"%1\" has been added to your address book.").arg(name)); + } else { + QMessageBox::information(this, tr("Add Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + return; + } +//! [submitContact part2] +//! [submitContact part3] + if (contacts.isEmpty()) { + nameLine->clear(); + addressText->clear(); + } + + nameLine->setReadOnly(true); + addressText->setReadOnly(true); + addButton->setEnabled(true); + submitButton->hide(); + cancelButton->hide(); +} +//! [submitContact part3] +//! [cancel] +void AddressBook::cancel() +{ + nameLine->setText(oldName); + nameLine->setReadOnly(true); + + addressText->setText(oldAddress); + addressText->setReadOnly(true); + + addButton->setEnabled(true); + submitButton->hide(); + cancelButton->hide(); +} +//! [cancel] diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part2/addressbook.h b/tests/manual/examples/widgets/tutorials/addressbook/part2/addressbook.h new file mode 100644 index 0000000000..ecc1a71cee --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part2/addressbook.h @@ -0,0 +1,47 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ADDRESSBOOK_H +#define ADDRESSBOOK_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QLabel; +class QLineEdit; +class QPushButton; +class QTextEdit; +QT_END_NAMESPACE + +class AddressBook : public QWidget +{ + Q_OBJECT + +public: + AddressBook(QWidget *parent = nullptr); + +//! [slots] +public slots: + void addContact(); + void submitContact(); + void cancel(); +//! [slots] + +//! [pushbutton declaration] +private: + QPushButton *addButton; + QPushButton *submitButton; + QPushButton *cancelButton; + QLineEdit *nameLine; + QTextEdit *addressText; +//! [pushbutton declaration] + +//! [remaining private variables] + QMap contacts; + QString oldName; + QString oldAddress; +}; +//! [remaining private variables] + +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part2/main.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part2/main.cpp new file mode 100644 index 0000000000..879fb606a2 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part2/main.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +//! [main function] +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + AddressBook addressBook; + addressBook.show(); + + return app.exec(); +} +//! [main function] diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part2/part2.pro b/tests/manual/examples/widgets/tutorials/addressbook/part2/part2.pro new file mode 100644 index 0000000000..643ffcfebd --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part2/part2.pro @@ -0,0 +1,11 @@ +QT += widgets + +SOURCES = addressbook.cpp \ + main.cpp +HEADERS = addressbook.h + +QMAKE_PROJECT_NAME = ab_part2 + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part2 +INSTALLS += target diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part3/CMakeLists.txt b/tests/manual/examples/widgets/tutorials/addressbook/part3/CMakeLists.txt new file mode 100644 index 0000000000..04c1779485 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part3/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(part3 LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part3") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(part3 + addressbook.cpp addressbook.h + main.cpp +) + +set_target_properties(part3 PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(part3 PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS part3 + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part3/addressbook.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part3/addressbook.cpp new file mode 100644 index 0000000000..1b37e56880 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part3/addressbook.cpp @@ -0,0 +1,182 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +AddressBook::AddressBook(QWidget *parent) + : QWidget(parent) +{ + QLabel *nameLabel = new QLabel(tr("Name:")); + nameLine = new QLineEdit; + nameLine->setReadOnly(true); + + QLabel *addressLabel = new QLabel(tr("Address:")); + addressText = new QTextEdit; + addressText->setReadOnly(true); + + addButton = new QPushButton(tr("&Add")); + addButton->show(); + submitButton = new QPushButton(tr("&Submit")); + submitButton->hide(); + cancelButton = new QPushButton(tr("&Cancel")); + cancelButton->hide(); +//! [navigation pushbuttons] + nextButton = new QPushButton(tr("&Next")); + nextButton->setEnabled(false); + previousButton = new QPushButton(tr("&Previous")); + previousButton->setEnabled(false); +//! [navigation pushbuttons] + connect(addButton, &QPushButton::clicked, + this, &AddressBook::addContact); + connect(submitButton, &QPushButton::clicked, + this, &AddressBook::submitContact); + connect(cancelButton, &QPushButton::clicked, + this, &AddressBook::cancel); +//! [connecting navigation signals] + connect(nextButton, &QPushButton::clicked, + this, &AddressBook::next); + connect(previousButton, &QPushButton::clicked, + this, &AddressBook::previous); +//! [connecting navigation signals] + + QVBoxLayout *buttonLayout1 = new QVBoxLayout; + buttonLayout1->addWidget(addButton, Qt::AlignTop); + buttonLayout1->addWidget(submitButton); + buttonLayout1->addWidget(cancelButton); + buttonLayout1->addStretch(); +//! [navigation layout] + QHBoxLayout *buttonLayout2 = new QHBoxLayout; + buttonLayout2->addWidget(previousButton); + buttonLayout2->addWidget(nextButton); +//! [ navigation layout] + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(nameLabel, 0, 0); + mainLayout->addWidget(nameLine, 0, 1); + mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); + mainLayout->addWidget(addressText, 1, 1); + mainLayout->addLayout(buttonLayout1, 1, 2); +//! [adding navigation layout] + mainLayout->addLayout(buttonLayout2, 2, 1); +//! [adding navigation layout] + setLayout(mainLayout); + setWindowTitle(tr("Simple Address Book")); +} + +void AddressBook::addContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + nameLine->clear(); + addressText->clear(); + + nameLine->setReadOnly(false); + nameLine->setFocus(Qt::OtherFocusReason); + addressText->setReadOnly(false); + + addButton->setEnabled(false); +//! [disabling navigation] + nextButton->setEnabled(false); + previousButton->setEnabled(false); +//! [disabling navigation] + submitButton->show(); + cancelButton->show(); +} + +void AddressBook::submitContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (name.isEmpty() || address.isEmpty()) { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name and address.")); + return; + } + + if (!contacts.contains(name)) { + contacts.insert(name, address); + QMessageBox::information(this, tr("Add Successful"), + tr("\"%1\" has been added to your address book.").arg(name)); + } else { + QMessageBox::information(this, tr("Add Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + + if (contacts.isEmpty()) { + nameLine->clear(); + addressText->clear(); + } + + nameLine->setReadOnly(true); + addressText->setReadOnly(true); + addButton->setEnabled(true); + +//! [enabling navigation] + int number = contacts.size(); + nextButton->setEnabled(number > 1); + previousButton->setEnabled(number > 1); +//! [enabling navigation] + submitButton->hide(); + cancelButton->hide(); +} + +void AddressBook::cancel() +{ + nameLine->setText(oldName); + addressText->setText(oldAddress); + + if (contacts.isEmpty()) { + nameLine->clear(); + addressText->clear(); + } + + nameLine->setReadOnly(true); + addressText->setReadOnly(true); + addButton->setEnabled(true); + + int number = contacts.size(); + nextButton->setEnabled(number > 1); + previousButton->setEnabled(number > 1); + + submitButton->hide(); + cancelButton->hide(); +} + +//! [next() function] +void AddressBook::next() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i != contacts.end()) + i++; + + if (i == contacts.end()) + i = contacts.begin(); + + nameLine->setText(i.key()); + addressText->setText(i.value()); +} +//! [next() function] +//! [previous() function] +void AddressBook::previous() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i == contacts.end()){ + nameLine->clear(); + addressText->clear(); + return; + } + + if (i == contacts.begin()) + i = contacts.end(); + + i--; + nameLine->setText(i.key()); + addressText->setText(i.value()); +} +//! [previous() function] diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part3/addressbook.h b/tests/manual/examples/widgets/tutorials/addressbook/part3/addressbook.h new file mode 100644 index 0000000000..0e3aea1e05 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part3/addressbook.h @@ -0,0 +1,49 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ADDRESSBOOK_H +#define ADDRESSBOOK_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QLabel; +class QLineEdit; +class QPushButton; +class QTextEdit; +QT_END_NAMESPACE + +class AddressBook : public QWidget +{ + Q_OBJECT + +public: + AddressBook(QWidget *parent = nullptr); + +public slots: + void addContact(); + void submitContact(); + void cancel(); +//! [navigation functions] + void next(); + void previous(); +//! [navigation functions] + +private: + QPushButton *addButton; + QPushButton *submitButton; + QPushButton *cancelButton; +//! [navigation pushbuttons] + QPushButton *nextButton; + QPushButton *previousButton; +//! [navigation pushbuttons] + QLineEdit *nameLine; + QTextEdit *addressText; + + QMap contacts; + QString oldName; + QString oldAddress; +}; + +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part3/main.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part3/main.cpp new file mode 100644 index 0000000000..1f3aac3397 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part3/main.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + AddressBook addressBook; + addressBook.show(); + + return app.exec(); +} diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part3/part3.pro b/tests/manual/examples/widgets/tutorials/addressbook/part3/part3.pro new file mode 100644 index 0000000000..3bacdd9501 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part3/part3.pro @@ -0,0 +1,11 @@ +QT += widgets + +SOURCES = addressbook.cpp \ + main.cpp +HEADERS = addressbook.h + +QMAKE_PROJECT_NAME = ab_part3 + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part3 +INSTALLS += target diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part4/CMakeLists.txt b/tests/manual/examples/widgets/tutorials/addressbook/part4/CMakeLists.txt new file mode 100644 index 0000000000..65289e9adf --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part4/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(part4 LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part4") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(part4 + addressbook.cpp addressbook.h + main.cpp +) + +set_target_properties(part4 PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(part4 PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS part4 + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part4/addressbook.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part4/addressbook.cpp new file mode 100644 index 0000000000..a54a888073 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part4/addressbook.cpp @@ -0,0 +1,258 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +AddressBook::AddressBook(QWidget *parent) + : QWidget(parent) +{ + QLabel *nameLabel = new QLabel(tr("Name:")); + nameLine = new QLineEdit; + nameLine->setReadOnly(true); + + QLabel *addressLabel = new QLabel(tr("Address:")); + addressText = new QTextEdit; + addressText->setReadOnly(true); + + addButton = new QPushButton(tr("&Add")); +//! [edit and remove buttons] + editButton = new QPushButton(tr("&Edit")); + editButton->setEnabled(false); + removeButton = new QPushButton(tr("&Remove")); + removeButton->setEnabled(false); +//! [edit and remove buttons] + submitButton = new QPushButton(tr("&Submit")); + submitButton->hide(); + cancelButton = new QPushButton(tr("&Cancel")); + cancelButton->hide(); + + nextButton = new QPushButton(tr("&Next")); + nextButton->setEnabled(false); + previousButton = new QPushButton(tr("&Previous")); + previousButton->setEnabled(false); + + connect(addButton, &QPushButton::clicked, + this, &AddressBook::addContact); + connect(submitButton, &QPushButton::clicked, + this, &AddressBook::submitContact); +//! [connecting edit and remove] + connect(editButton, &QPushButton::clicked, + this, &AddressBook::editContact); + connect(removeButton, &QPushButton::clicked, + this, &AddressBook::removeContact); +//! [connecting edit and remove] + connect(cancelButton, &QPushButton::clicked, + this, &AddressBook::cancel); + connect(nextButton, &QPushButton::clicked, + this, &AddressBook::next); + connect(previousButton, &QPushButton::clicked, + this, &AddressBook::previous); + + QVBoxLayout *buttonLayout1 = new QVBoxLayout; + buttonLayout1->addWidget(addButton); +//! [adding edit and remove to the layout] + buttonLayout1->addWidget(editButton); + buttonLayout1->addWidget(removeButton); +//! [adding edit and remove to the layout] + buttonLayout1->addWidget(submitButton); + buttonLayout1->addWidget(cancelButton); + buttonLayout1->addStretch(); + + QHBoxLayout *buttonLayout2 = new QHBoxLayout; + buttonLayout2->addWidget(previousButton); + buttonLayout2->addWidget(nextButton); + + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(nameLabel, 0, 0); + mainLayout->addWidget(nameLine, 0, 1); + mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); + mainLayout->addWidget(addressText, 1, 1); + mainLayout->addLayout(buttonLayout1, 1, 2); + mainLayout->addLayout(buttonLayout2, 2, 1); + + setLayout(mainLayout); + setWindowTitle(tr("Simple Address Book")); +} + +void AddressBook::addContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + nameLine->clear(); + addressText->clear(); + + updateInterface(AddingMode); +} +//! [editContact() function] +void AddressBook::editContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + updateInterface(EditingMode); +} +//! [editContact() function] +//! [submitContact() function beginning] +void AddressBook::submitContact() +{ +//! [submitContact() function beginning] + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (name.isEmpty() || address.isEmpty()) { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name and address.")); + return; + } +//! [submitContact() function part1] + if (currentMode == AddingMode) { + + if (!contacts.contains(name)) { + contacts.insert(name, address); + QMessageBox::information(this, tr("Add Successful"), + tr("\"%1\" has been added to your address book.").arg(name)); + } else { + QMessageBox::information(this, tr("Add Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } +//! [submitContact() function part1] +//! [submitContact() function part2] + } else if (currentMode == EditingMode) { + + if (oldName != name) { + if (!contacts.contains(name)) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(oldName)); + contacts.remove(oldName); + contacts.insert(name, address); + } else { + QMessageBox::information(this, tr("Edit Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + } else if (oldAddress != address) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(name)); + contacts[name] = address; + } + } + + updateInterface(NavigationMode); +} +//! [submitContact() function part2] + +void AddressBook::cancel() +{ + nameLine->setText(oldName); + addressText->setText(oldAddress); + updateInterface(NavigationMode); +} +//! [removeContact() function] +void AddressBook::removeContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (contacts.contains(name)) { + + int button = QMessageBox::question(this, + tr("Confirm Remove"), + tr("Are you sure you want to remove \"%1\"?").arg(name), + QMessageBox::Yes | QMessageBox::No); + + if (button == QMessageBox::Yes) { + + previous(); + contacts.remove(name); + + QMessageBox::information(this, tr("Remove Successful"), + tr("\"%1\" has been removed from your address book.").arg(name)); + } + } + + updateInterface(NavigationMode); +} +//! [removeContact() function] +void AddressBook::next() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i != contacts.end()) + i++; + + if (i == contacts.end()) + i = contacts.begin(); + + nameLine->setText(i.key()); + addressText->setText(i.value()); +} + +void AddressBook::previous() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i == contacts.end()) { + nameLine->clear(); + addressText->clear(); + return; + } + + if (i == contacts.begin()) + i = contacts.end(); + + i--; + nameLine->setText(i.key()); + addressText->setText(i.value()); +} +//! [update interface() part 1] +void AddressBook::updateInterface(Mode mode) +{ + currentMode = mode; + + switch (currentMode) { + + case AddingMode: + case EditingMode: + + nameLine->setReadOnly(false); + nameLine->setFocus(Qt::OtherFocusReason); + addressText->setReadOnly(false); + + addButton->setEnabled(false); + editButton->setEnabled(false); + removeButton->setEnabled(false); + + nextButton->setEnabled(false); + previousButton->setEnabled(false); + + submitButton->show(); + cancelButton->show(); + break; +//! [update interface() part 1] +//! [update interface() part 2] + case NavigationMode: + + if (contacts.isEmpty()) { + nameLine->clear(); + addressText->clear(); + } + + nameLine->setReadOnly(true); + addressText->setReadOnly(true); + addButton->setEnabled(true); + + int number = contacts.size(); + editButton->setEnabled(number >= 1); + removeButton->setEnabled(number >= 1); + nextButton->setEnabled(number > 1); + previousButton->setEnabled(number >1 ); + + submitButton->hide(); + cancelButton->hide(); + break; + } +} +//! [update interface() part 2] diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part4/addressbook.h b/tests/manual/examples/widgets/tutorials/addressbook/part4/addressbook.h new file mode 100644 index 0000000000..e77bbd3961 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part4/addressbook.h @@ -0,0 +1,62 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ADDRESSBOOK_H +#define ADDRESSBOOK_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QPushButton; +class QLabel; +class QLineEdit; +class QTextEdit; +QT_END_NAMESPACE + +class AddressBook : public QWidget +{ + Q_OBJECT + +public: + AddressBook(QWidget *parent = nullptr); +//! [Mode enum] + enum Mode { NavigationMode, AddingMode, EditingMode }; +//! [Mode enum] + +public slots: + void addContact(); + void submitContact(); + void cancel(); +//! [edit and remove slots] + void editContact(); + void removeContact(); +//! [edit and remove slots] + void next(); + void previous(); + +private: +//! [updateInterface() declaration] + void updateInterface(Mode mode); +//! [updateInterface() declaration] + QPushButton *addButton; +//! [buttons declaration] + QPushButton *editButton; + QPushButton *removeButton; +//! [buttons declaration] + QPushButton *submitButton; + QPushButton *cancelButton; + QPushButton *nextButton; + QPushButton *previousButton; + QLineEdit *nameLine; + QTextEdit *addressText; + + QMap contacts; + QString oldName; + QString oldAddress; +//! [mode declaration] + Mode currentMode; +//! [mode declaration] +}; + +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part4/main.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part4/main.cpp new file mode 100644 index 0000000000..1f3aac3397 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part4/main.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + AddressBook addressBook; + addressBook.show(); + + return app.exec(); +} diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part4/part4.pro b/tests/manual/examples/widgets/tutorials/addressbook/part4/part4.pro new file mode 100644 index 0000000000..02cc5b8e07 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part4/part4.pro @@ -0,0 +1,11 @@ +QT += widgets + +SOURCES = addressbook.cpp \ + main.cpp +HEADERS = addressbook.h + +QMAKE_PROJECT_NAME = ab_part4 + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part4 +INSTALLS += target diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part5/CMakeLists.txt b/tests/manual/examples/widgets/tutorials/addressbook/part5/CMakeLists.txt new file mode 100644 index 0000000000..2abb1c6454 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part5/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(part5 LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part5") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(part5 + addressbook.cpp addressbook.h + finddialog.cpp finddialog.h + main.cpp +) + +set_target_properties(part5 PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(part5 PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS part5 + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part5/addressbook.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part5/addressbook.cpp new file mode 100644 index 0000000000..52aa5a0b28 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part5/addressbook.cpp @@ -0,0 +1,283 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +AddressBook::AddressBook(QWidget *parent) + : QWidget(parent) +{ + QLabel *nameLabel = new QLabel(tr("Name:")); + nameLine = new QLineEdit; + nameLine->setReadOnly(true); + + QLabel *addressLabel = new QLabel(tr("Address:")); + addressText = new QTextEdit; + addressText->setReadOnly(true); + + addButton = new QPushButton(tr("&Add")); + + editButton = new QPushButton(tr("&Edit")); + editButton->setEnabled(false); + removeButton = new QPushButton(tr("&Remove")); + removeButton->setEnabled(false); +//! [instantiating findButton] + findButton = new QPushButton(tr("&Find")); + findButton->setEnabled(false); +//! [instantiating findButton] + submitButton = new QPushButton(tr("&Submit")); + submitButton->hide(); + cancelButton = new QPushButton(tr("&Cancel")); + cancelButton->hide(); + + nextButton = new QPushButton(tr("&Next")); + nextButton->setEnabled(false); + previousButton = new QPushButton(tr("&Previous")); + previousButton->setEnabled(false); + +//! [instantiating FindDialog] + dialog = new FindDialog(this); +//! [instantiating FindDialog] + + connect(addButton, &QPushButton::clicked, + this, &AddressBook::addContact); + connect(submitButton, &QPushButton::clicked, + this, &AddressBook::submitContact); + connect(editButton, &QPushButton::clicked, + this, &AddressBook::editContact); + connect(removeButton, &QPushButton::clicked, + this, &AddressBook::removeContact); + connect(cancelButton, &QPushButton::clicked, + this, &AddressBook::cancel); +//! [signals and slots for find] + connect(findButton, &QPushButton::clicked, + this, &AddressBook::findContact); +//! [signals and slots for find] + connect(nextButton, &QPushButton::clicked, + this, &AddressBook::next); + connect(previousButton, &QPushButton::clicked, + this, &AddressBook::previous); + + QVBoxLayout *buttonLayout1 = new QVBoxLayout; + buttonLayout1->addWidget(addButton); + buttonLayout1->addWidget(editButton); + buttonLayout1->addWidget(removeButton); +//! [adding findButton to layout] + buttonLayout1->addWidget(findButton); +//! [adding findButton to layout] + buttonLayout1->addWidget(submitButton); + buttonLayout1->addWidget(cancelButton); + buttonLayout1->addStretch(); + + QHBoxLayout *buttonLayout2 = new QHBoxLayout; + buttonLayout2->addWidget(previousButton); + buttonLayout2->addWidget(nextButton); + + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(nameLabel, 0, 0); + mainLayout->addWidget(nameLine, 0, 1); + mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); + mainLayout->addWidget(addressText, 1, 1); + mainLayout->addLayout(buttonLayout1, 1, 2); + mainLayout->addLayout(buttonLayout2, 2, 1); + + setLayout(mainLayout); + setWindowTitle(tr("Simple Address Book")); +} + +void AddressBook::addContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + nameLine->clear(); + addressText->clear(); + + updateInterface(AddingMode); +} + +void AddressBook::editContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + updateInterface(EditingMode); +} + +void AddressBook::submitContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (name.isEmpty() || address.isEmpty()) { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name and address.")); + return; + } + + if (currentMode == AddingMode) { + + if (!contacts.contains(name)) { + contacts.insert(name, address); + QMessageBox::information(this, tr("Add Successful"), + tr("\"%1\" has been added to your address book.").arg(name)); + } else { + QMessageBox::information(this, tr("Add Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + } else if (currentMode == EditingMode) { + + if (oldName != name) { + if (!contacts.contains(name)) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(oldName)); + contacts.remove(oldName); + contacts.insert(name, address); + } else { + QMessageBox::information(this, tr("Edit Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + } else if (oldAddress != address) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(name)); + contacts[name] = address; + } + } + + updateInterface(NavigationMode); +} + +void AddressBook::cancel() +{ + nameLine->setText(oldName); + addressText->setText(oldAddress); + updateInterface(NavigationMode); +} + +void AddressBook::removeContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (contacts.contains(name)) { + + int button = QMessageBox::question(this, + tr("Confirm Remove"), + tr("Are you sure you want to remove \"%1\"?").arg(name), + QMessageBox::Yes | QMessageBox::No); + + if (button == QMessageBox::Yes) { + + previous(); + contacts.remove(name); + + QMessageBox::information(this, tr("Remove Successful"), + tr("\"%1\" has been removed from your address book.").arg(name)); + } + } + + updateInterface(NavigationMode); +} + +void AddressBook::next() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i != contacts.end()) + i++; + + if (i == contacts.end()) + i = contacts.begin(); + + nameLine->setText(i.key()); + addressText->setText(i.value()); +} + +void AddressBook::previous() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i == contacts.end()) { + nameLine->clear(); + addressText->clear(); + return; + } + + if (i == contacts.begin()) + i = contacts.end(); + + i--; + nameLine->setText(i.key()); + addressText->setText(i.value()); +} +//! [findContact() function] +void AddressBook::findContact() +{ + dialog->show(); + + if (dialog->exec() == QDialog::Accepted) { + QString contactName = dialog->getFindText(); + + if (contacts.contains(contactName)) { + nameLine->setText(contactName); + addressText->setText(contacts.value(contactName)); + } else { + QMessageBox::information(this, tr("Contact Not Found"), + tr("Sorry, \"%1\" is not in your address book.").arg(contactName)); + return; + } + } + + updateInterface(NavigationMode); +} +//! [findContact() function] + +void AddressBook::updateInterface(Mode mode) +{ + currentMode = mode; + + switch (currentMode) { + + case AddingMode: + case EditingMode: + + nameLine->setReadOnly(false); + nameLine->setFocus(Qt::OtherFocusReason); + addressText->setReadOnly(false); + + addButton->setEnabled(false); + editButton->setEnabled(false); + removeButton->setEnabled(false); + + nextButton->setEnabled(false); + previousButton->setEnabled(false); + + submitButton->show(); + cancelButton->show(); + break; + + case NavigationMode: + + if (contacts.isEmpty()) { + nameLine->clear(); + addressText->clear(); + } + + nameLine->setReadOnly(true); + addressText->setReadOnly(true); + addButton->setEnabled(true); + + int number = contacts.size(); + editButton->setEnabled(number >= 1); + removeButton->setEnabled(number >= 1); + findButton->setEnabled(number > 2); + nextButton->setEnabled(number > 1); + previousButton->setEnabled(number > 1); + + submitButton->hide(); + cancelButton->hide(); + break; + } +} diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part5/addressbook.h b/tests/manual/examples/widgets/tutorials/addressbook/part5/addressbook.h new file mode 100644 index 0000000000..93da08038c --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part5/addressbook.h @@ -0,0 +1,65 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ADDRESSBOOK_H +#define ADDRESSBOOK_H + +#include +#include +//! [include finddialog's header] +#include "finddialog.h" +//! [include finddialog's header] +QT_BEGIN_NAMESPACE +class QPushButton; +class QLabel; +class QLineEdit; +class QTextEdit; +QT_END_NAMESPACE + + +class AddressBook : public QWidget +{ + Q_OBJECT + +public: + AddressBook(QWidget *parent = nullptr); + enum Mode { NavigationMode, AddingMode, EditingMode }; + +public slots: + void addContact(); + void editContact(); + void submitContact(); + void cancel(); + void removeContact(); +//! [findContact() declaration] + void findContact(); +//! [findContact() declaration] + void next(); + void previous(); + +private: + void updateInterface(Mode mode); + + QPushButton *addButton; + QPushButton *editButton; + QPushButton *removeButton; +//! [findButton declaration] + QPushButton *findButton; +//! [findButton declaration] + QPushButton *submitButton; + QPushButton *cancelButton; + QPushButton *nextButton; + QPushButton *previousButton; + QLineEdit *nameLine; + QTextEdit *addressText; + + QMap contacts; +//! [FindDialog declaration] + FindDialog *dialog; +//! [FindDialog declaration] + QString oldName; + QString oldAddress; + Mode currentMode; +}; + +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part5/finddialog.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part5/finddialog.cpp new file mode 100644 index 0000000000..d5daa661d0 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part5/finddialog.cpp @@ -0,0 +1,51 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "finddialog.h" + +//! [constructor] +FindDialog::FindDialog(QWidget *parent) + : QDialog(parent) +{ + QLabel *findLabel = new QLabel(tr("Enter the name of a contact:")); + lineEdit = new QLineEdit; + + findButton = new QPushButton(tr("&Find")); + findText = ""; + + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(findLabel); + layout->addWidget(lineEdit); + layout->addWidget(findButton); + + setLayout(layout); + setWindowTitle(tr("Find a Contact")); + connect(findButton, &QPushButton::clicked, + this, &FindDialog::findClicked); + connect(findButton, &QPushButton::clicked, + this, &FindDialog::accept); +} +//! [constructor] +//! [findClicked() function] +void FindDialog::findClicked() +{ + QString text = lineEdit->text(); + + if (text.isEmpty()) { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name.")); + return; + } else { + findText = text; + lineEdit->clear(); + hide(); + } +} +//! [findClicked() function] +//! [getFindText() function] +QString FindDialog::getFindText() +{ + return findText; +} +//! [getFindText() function] diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part5/finddialog.h b/tests/manual/examples/widgets/tutorials/addressbook/part5/finddialog.h new file mode 100644 index 0000000000..7cedcffa60 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part5/finddialog.h @@ -0,0 +1,31 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef FINDDIALOG_H +#define FINDDIALOG_H +//! [FindDialog header] +#include + +QT_BEGIN_NAMESPACE +class QLineEdit; +class QPushButton; +QT_END_NAMESPACE + +class FindDialog : public QDialog +{ + Q_OBJECT + +public: + FindDialog(QWidget *parent = nullptr); + QString getFindText(); + +public slots: + void findClicked(); + +private: + QPushButton *findButton; + QLineEdit *lineEdit; + QString findText; +}; +//! [FindDialog header] +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part5/main.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part5/main.cpp new file mode 100644 index 0000000000..1f3aac3397 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part5/main.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + AddressBook addressBook; + addressBook.show(); + + return app.exec(); +} diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part5/part5.pro b/tests/manual/examples/widgets/tutorials/addressbook/part5/part5.pro new file mode 100644 index 0000000000..da5469f655 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part5/part5.pro @@ -0,0 +1,13 @@ +QT += widgets + +SOURCES = addressbook.cpp \ + finddialog.cpp \ + main.cpp +HEADERS = addressbook.h \ + finddialog.h + +QMAKE_PROJECT_NAME = ab_part5 + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part5 +INSTALLS += target diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part6/CMakeLists.txt b/tests/manual/examples/widgets/tutorials/addressbook/part6/CMakeLists.txt new file mode 100644 index 0000000000..8e954c51ab --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part6/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(part6 LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part6") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(part6 + addressbook.cpp addressbook.h + finddialog.cpp finddialog.h + main.cpp +) + +set_target_properties(part6 PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(part6 PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS part6 + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part6/addressbook.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part6/addressbook.cpp new file mode 100644 index 0000000000..455ccc899a --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part6/addressbook.cpp @@ -0,0 +1,366 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +AddressBook::AddressBook(QWidget *parent) + : QWidget(parent) +{ + QLabel *nameLabel = new QLabel(tr("Name:")); + nameLine = new QLineEdit; + nameLine->setReadOnly(true); + + QLabel *addressLabel = new QLabel(tr("Address:")); + addressText = new QTextEdit; + addressText->setReadOnly(true); + + addButton = new QPushButton(tr("&Add")); + + editButton = new QPushButton(tr("&Edit")); + editButton->setEnabled(false); + removeButton = new QPushButton(tr("&Remove")); + removeButton->setEnabled(false); + findButton = new QPushButton(tr("&Find")); + findButton->setEnabled(false); + submitButton = new QPushButton(tr("&Submit")); + submitButton->hide(); + cancelButton = new QPushButton(tr("&Cancel")); + cancelButton->hide(); + + nextButton = new QPushButton(tr("&Next")); + nextButton->setEnabled(false); + previousButton = new QPushButton(tr("&Previous")); + previousButton->setEnabled(false); + + loadButton = new QPushButton(tr("&Load...")); +//! [tooltip 1] + loadButton->setToolTip(tr("Load contacts from a file")); +//! [tooltip 1] + saveButton = new QPushButton(tr("&Save...")); +//! [tooltip 2] + saveButton->setToolTip(tr("Save contacts to a file")); +//! [tooltip 2] + saveButton->setEnabled(false); + + dialog = new FindDialog(this); + + connect(addButton, &QPushButton::clicked, + this, &AddressBook::addContact); + connect(submitButton, &QPushButton::clicked, + this, &AddressBook::submitContact); + connect(editButton, &QPushButton::clicked, + this, &AddressBook::editContact); + connect(removeButton, &QPushButton::clicked, + this, &AddressBook::removeContact); + connect(cancelButton, &QPushButton::clicked, + this, &AddressBook::cancel); + connect(findButton, &QPushButton::clicked, + this, &AddressBook::findContact); + connect(nextButton, &QPushButton::clicked, + this, &AddressBook::next); + connect(previousButton, &QPushButton::clicked, + this, &AddressBook::previous); + connect(loadButton, &QPushButton::clicked, + this, &AddressBook::loadFromFile); + connect(saveButton, &QPushButton::clicked, + this, &AddressBook::saveToFile); + + QVBoxLayout *buttonLayout1 = new QVBoxLayout; + buttonLayout1->addWidget(addButton); + buttonLayout1->addWidget(editButton); + buttonLayout1->addWidget(removeButton); + buttonLayout1->addWidget(findButton); + buttonLayout1->addWidget(submitButton); + buttonLayout1->addWidget(cancelButton); + buttonLayout1->addWidget(loadButton); + buttonLayout1->addWidget(saveButton); + buttonLayout1->addStretch(); + + QHBoxLayout *buttonLayout2 = new QHBoxLayout; + buttonLayout2->addWidget(previousButton); + buttonLayout2->addWidget(nextButton); + + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(nameLabel, 0, 0); + mainLayout->addWidget(nameLine, 0, 1); + mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); + mainLayout->addWidget(addressText, 1, 1); + mainLayout->addLayout(buttonLayout1, 1, 2); + mainLayout->addLayout(buttonLayout2, 2, 1); + + setLayout(mainLayout); + setWindowTitle(tr("Simple Address Book")); +} + +void AddressBook::addContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + nameLine->clear(); + addressText->clear(); + + updateInterface(AddingMode); +} + +void AddressBook::editContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + updateInterface(EditingMode); +} + +void AddressBook::submitContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (name.isEmpty() || address.isEmpty()) { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name and address.")); + return; + } + + if (currentMode == AddingMode) { + + if (!contacts.contains(name)) { + contacts.insert(name, address); + QMessageBox::information(this, tr("Add Successful"), + tr("\"%1\" has been added to your address book.").arg(name)); + } else { + QMessageBox::information(this, tr("Add Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + } else if (currentMode == EditingMode) { + + if (oldName != name) { + if (!contacts.contains(name)) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(oldName)); + contacts.remove(oldName); + contacts.insert(name, address); + } else { + QMessageBox::information(this, tr("Edit Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + } else if (oldAddress != address) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(name)); + contacts[name] = address; + } + } + + updateInterface(NavigationMode); +} + +void AddressBook::cancel() +{ + nameLine->setText(oldName); + addressText->setText(oldAddress); + updateInterface(NavigationMode); +} + +void AddressBook::removeContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (contacts.contains(name)) { + + int button = QMessageBox::question(this, + tr("Confirm Remove"), + tr("Are you sure you want to remove \"%1\"?").arg(name), + QMessageBox::Yes | QMessageBox::No); + + if (button == QMessageBox::Yes) { + + previous(); + contacts.remove(name); + + QMessageBox::information(this, tr("Remove Successful"), + tr("\"%1\" has been removed from your address book.").arg(name)); + } + } + + updateInterface(NavigationMode); +} + +void AddressBook::next() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i != contacts.end()) + i++; + + if (i == contacts.end()) + i = contacts.begin(); + + nameLine->setText(i.key()); + addressText->setText(i.value()); +} + +void AddressBook::previous() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i == contacts.end()) { + nameLine->clear(); + addressText->clear(); + return; + } + + if (i == contacts.begin()) + i = contacts.end(); + + i--; + nameLine->setText(i.key()); + addressText->setText(i.value()); +} + +void AddressBook::findContact() +{ + dialog->show(); + + if (dialog->exec() == 1) { + QString contactName = dialog->getFindText(); + + if (contacts.contains(contactName)) { + nameLine->setText(contactName); + addressText->setText(contacts.value(contactName)); + } else { + QMessageBox::information(this, tr("Contact Not Found"), + tr("Sorry, \"%1\" is not in your address book.").arg(contactName)); + return; + } + } + + updateInterface(NavigationMode); +} + +void AddressBook::updateInterface(Mode mode) +{ + currentMode = mode; + + switch (currentMode) { + + case AddingMode: + case EditingMode: + + nameLine->setReadOnly(false); + nameLine->setFocus(Qt::OtherFocusReason); + addressText->setReadOnly(false); + + addButton->setEnabled(false); + editButton->setEnabled(false); + removeButton->setEnabled(false); + + nextButton->setEnabled(false); + previousButton->setEnabled(false); + + submitButton->show(); + cancelButton->show(); + + loadButton->setEnabled(false); + saveButton->setEnabled(false); + break; + + case NavigationMode: + + if (contacts.isEmpty()) { + nameLine->clear(); + addressText->clear(); + } + + nameLine->setReadOnly(true); + addressText->setReadOnly(true); + addButton->setEnabled(true); + + int number = contacts.size(); + editButton->setEnabled(number >= 1); + removeButton->setEnabled(number >= 1); + findButton->setEnabled(number > 2); + nextButton->setEnabled(number > 1); + previousButton->setEnabled(number > 1); + + submitButton->hide(); + cancelButton->hide(); + + loadButton->setEnabled(true); + saveButton->setEnabled(number >= 1); + break; + } +} + +//! [saveToFile() function part1] +void AddressBook::saveToFile() +{ + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save Address Book"), "", + tr("Address Book (*.abk);;All Files (*)")); + +//! [saveToFile() function part1] +//! [saveToFile() function part2] + if (fileName.isEmpty()) + return; + else { + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::information(this, tr("Unable to open file"), + file.errorString()); + return; + } + +//! [saveToFile() function part2] +//! [saveToFile() function part3] + QDataStream out(&file); + out.setVersion(QDataStream::Qt_4_5); + out << contacts; + } +} +//! [saveToFile() function part3] + +//! [loadFromFile() function part1] +void AddressBook::loadFromFile() +{ + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open Address Book"), "", + tr("Address Book (*.abk);;All Files (*)")); +//! [loadFromFile() function part1] + +//! [loadFromFile() function part2] + if (fileName.isEmpty()) + return; + else { + + QFile file(fileName); + + if (!file.open(QIODevice::ReadOnly)) { + QMessageBox::information(this, tr("Unable to open file"), + file.errorString()); + return; + } + + QDataStream in(&file); + in.setVersion(QDataStream::Qt_4_5); + contacts.clear(); // clear existing contacts + in >> contacts; +//! [loadFromFile() function part2] + +//! [loadFromFile() function part3] + if (contacts.isEmpty()) { + QMessageBox::information(this, tr("No contacts in file"), + tr("The file you are attempting to open contains no contacts.")); + } else { + QMap::iterator i = contacts.begin(); + nameLine->setText(i.key()); + addressText->setText(i.value()); + } + } + + updateInterface(NavigationMode); +} +//! [loadFromFile() function part3] diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part6/addressbook.h b/tests/manual/examples/widgets/tutorials/addressbook/part6/addressbook.h new file mode 100644 index 0000000000..26389d7446 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part6/addressbook.h @@ -0,0 +1,66 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ADDRESSBOOK_H +#define ADDRESSBOOK_H + +#include +#include +#include "finddialog.h" + +QT_BEGIN_NAMESPACE +class QPushButton; +class QLabel; +class QLineEdit; +class QTextEdit; +QT_END_NAMESPACE + + +class AddressBook : public QWidget +{ + Q_OBJECT + +public: + AddressBook(QWidget *parent = nullptr); + enum Mode { NavigationMode, AddingMode, EditingMode }; + +public slots: + void addContact(); + void editContact(); + void submitContact(); + void cancel(); + void removeContact(); + void findContact(); + void next(); + void previous(); +//! [save and load functions declaration] + void saveToFile(); + void loadFromFile(); +//! [save and load functions declaration] + +private: + void updateInterface(Mode mode); + + QPushButton *addButton; + QPushButton *editButton; + QPushButton *removeButton; + QPushButton *findButton; + QPushButton *submitButton; + QPushButton *cancelButton; + QPushButton *nextButton; + QPushButton *previousButton; +//! [save and load buttons declaration] + QPushButton *loadButton; + QPushButton *saveButton; +//! [save and load buttons declaration] + QLineEdit *nameLine; + QTextEdit *addressText; + + QMap contacts; + FindDialog *dialog; + QString oldName; + QString oldAddress; + Mode currentMode; +}; + +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part6/finddialog.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part6/finddialog.cpp new file mode 100644 index 0000000000..90729d9c12 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part6/finddialog.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "finddialog.h" + +FindDialog::FindDialog(QWidget *parent) + : QDialog(parent) +{ + QLabel *findLabel = new QLabel(tr("Enter the name of a contact:")); + lineEdit = new QLineEdit; + + findButton = new QPushButton(tr("&Find")); + findText = ""; + + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(findLabel); + layout->addWidget(lineEdit); + layout->addWidget(findButton); + + setLayout(layout); + setWindowTitle(tr("Find a Contact")); + connect(findButton, &QPushButton::clicked, + this, &FindDialog::findClicked); + connect(findButton, &QPushButton::clicked, + this, &FindDialog::accept); +} + +void FindDialog::findClicked() +{ + QString text = lineEdit->text(); + + if (text.isEmpty()) { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name.")); + return; + } else { + findText = text; + lineEdit->clear(); + hide(); + } +} + +QString FindDialog::getFindText() +{ + return findText; +} diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part6/finddialog.h b/tests/manual/examples/widgets/tutorials/addressbook/part6/finddialog.h new file mode 100644 index 0000000000..7c9a3af30f --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part6/finddialog.h @@ -0,0 +1,31 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef FINDDIALOG_H +#define FINDDIALOG_H + +#include + +QT_BEGIN_NAMESPACE +class QLineEdit; +class QPushButton; +QT_END_NAMESPACE + +class FindDialog : public QDialog +{ + Q_OBJECT + +public: + FindDialog(QWidget *parent = nullptr); + QString getFindText(); + +public slots: + void findClicked(); + +private: + QPushButton *findButton; + QLineEdit *lineEdit; + QString findText; +}; + +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part6/main.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part6/main.cpp new file mode 100644 index 0000000000..1f3aac3397 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part6/main.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + AddressBook addressBook; + addressBook.show(); + + return app.exec(); +} diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part6/part6.pro b/tests/manual/examples/widgets/tutorials/addressbook/part6/part6.pro new file mode 100644 index 0000000000..6796f30a73 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part6/part6.pro @@ -0,0 +1,14 @@ +QT += widgets +requires(qtConfig(filedialog)) + +SOURCES = addressbook.cpp \ + finddialog.cpp \ + main.cpp +HEADERS = addressbook.h \ + finddialog.h + +QMAKE_PROJECT_NAME = ab_part6 + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part6 +INSTALLS += target diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part7/CMakeLists.txt b/tests/manual/examples/widgets/tutorials/addressbook/part7/CMakeLists.txt new file mode 100644 index 0000000000..fe4ace86ad --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part7/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(part7 LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/addressbook/part7") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(part7 + addressbook.cpp addressbook.h + finddialog.cpp finddialog.h + main.cpp +) + +set_target_properties(part7 PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(part7 PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS part7 + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part7/addressbook.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part7/addressbook.cpp new file mode 100644 index 0000000000..30878d7bbc --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part7/addressbook.cpp @@ -0,0 +1,419 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +AddressBook::AddressBook(QWidget *parent) + : QWidget(parent) +{ + QLabel *nameLabel = new QLabel(tr("Name:")); + nameLine = new QLineEdit; + nameLine->setReadOnly(true); + + QLabel *addressLabel = new QLabel(tr("Address:")); + addressText = new QTextEdit; + addressText->setReadOnly(true); + + addButton = new QPushButton(tr("&Add")); + + editButton = new QPushButton(tr("&Edit")); + editButton->setEnabled(false); + removeButton = new QPushButton(tr("&Remove")); + removeButton->setEnabled(false); + findButton = new QPushButton(tr("&Find")); + findButton->setEnabled(false); + submitButton = new QPushButton(tr("&Submit")); + submitButton->hide(); + cancelButton = new QPushButton(tr("&Cancel")); + cancelButton->hide(); + + nextButton = new QPushButton(tr("&Next")); + nextButton->setEnabled(false); + previousButton = new QPushButton(tr("&Previous")); + previousButton->setEnabled(false); + + loadButton = new QPushButton(tr("&Load...")); + loadButton->setToolTip(tr("Load contacts from a file")); + saveButton = new QPushButton(tr("&Save...")); + saveButton->setToolTip(tr("Save contacts to a file")); + saveButton->setEnabled(false); + + exportButton = new QPushButton(tr("E&xport")); + exportButton->setToolTip(tr("Export as vCard")); + exportButton->setEnabled(false); + + dialog = new FindDialog(this); + + connect(addButton, &QPushButton::clicked, + this, &AddressBook::addContact); + connect(submitButton, &QPushButton::clicked, + this, &AddressBook::submitContact); + connect(editButton, &QPushButton::clicked, + this, &AddressBook::editContact); + connect(removeButton, &QPushButton::clicked, + this, &AddressBook::removeContact); + connect(cancelButton, &QPushButton::clicked, + this, &AddressBook::cancel); + connect(findButton, &QPushButton::clicked, + this, &AddressBook::findContact); + connect(nextButton, &QPushButton::clicked, + this, &AddressBook::next); + connect(previousButton, &QPushButton::clicked, + this, &AddressBook::previous); + connect(loadButton, &QPushButton::clicked, + this, &AddressBook::loadFromFile); + connect(saveButton, &QPushButton::clicked, + this, &AddressBook::saveToFile); + connect(exportButton, &QPushButton::clicked, + this, &AddressBook::exportAsVCard); + + QVBoxLayout *buttonLayout1 = new QVBoxLayout; + buttonLayout1->addWidget(addButton); + buttonLayout1->addWidget(editButton); + buttonLayout1->addWidget(removeButton); + buttonLayout1->addWidget(findButton); + buttonLayout1->addWidget(submitButton); + buttonLayout1->addWidget(cancelButton); + buttonLayout1->addWidget(loadButton); + buttonLayout1->addWidget(saveButton); + buttonLayout1->addWidget(exportButton); + buttonLayout1->addStretch(); + + QHBoxLayout *buttonLayout2 = new QHBoxLayout; + buttonLayout2->addWidget(previousButton); + buttonLayout2->addWidget(nextButton); + + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(nameLabel, 0, 0); + mainLayout->addWidget(nameLine, 0, 1); + mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); + mainLayout->addWidget(addressText, 1, 1); + mainLayout->addLayout(buttonLayout1, 1, 2); + mainLayout->addLayout(buttonLayout2, 2, 1); + + setLayout(mainLayout); + setWindowTitle(tr("Simple Address Book")); +} + +void AddressBook::addContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + nameLine->clear(); + addressText->clear(); + + updateInterface(AddingMode); +} + +void AddressBook::editContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + updateInterface(EditingMode); +} + +void AddressBook::submitContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (name.isEmpty() || address.isEmpty()) { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name and address.")); + return; + } + + if (currentMode == AddingMode) { + + if (!contacts.contains(name)) { + contacts.insert(name, address); + QMessageBox::information(this, tr("Add Successful"), + tr("\"%1\" has been added to your address book.").arg(name)); + } else { + QMessageBox::information(this, tr("Add Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + } else if (currentMode == EditingMode) { + + if (oldName != name) { + if (!contacts.contains(name)) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(oldName)); + contacts.remove(oldName); + contacts.insert(name, address); + } else { + QMessageBox::information(this, tr("Edit Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + } else if (oldAddress != address) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(name)); + contacts[name] = address; + } + } + + updateInterface(NavigationMode); +} + +void AddressBook::cancel() +{ + nameLine->setText(oldName); + addressText->setText(oldAddress); + updateInterface(NavigationMode); +} + +void AddressBook::removeContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (contacts.contains(name)) { + + int button = QMessageBox::question(this, + tr("Confirm Remove"), + tr("Are you sure you want to remove \"%1\"?").arg(name), + QMessageBox::Yes | QMessageBox::No); + + if (button == QMessageBox::Yes) { + + previous(); + contacts.remove(name); + + QMessageBox::information(this, tr("Remove Successful"), + tr("\"%1\" has been removed from your address book.").arg(name)); + } + } + + updateInterface(NavigationMode); +} + +void AddressBook::next() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i != contacts.end()) + i++; + + if (i == contacts.end()) + i = contacts.begin(); + + nameLine->setText(i.key()); + addressText->setText(i.value()); +} + +void AddressBook::previous() +{ + QString name = nameLine->text(); + QMap::iterator i = contacts.find(name); + + if (i == contacts.end()) { + nameLine->clear(); + addressText->clear(); + return; + } + + if (i == contacts.begin()) + i = contacts.end(); + + i--; + nameLine->setText(i.key()); + addressText->setText(i.value()); +} + +void AddressBook::findContact() +{ + dialog->show(); + + if (dialog->exec() == 1) { + QString contactName = dialog->getFindText(); + + if (contacts.contains(contactName)) { + nameLine->setText(contactName); + addressText->setText(contacts.value(contactName)); + } else { + QMessageBox::information(this, tr("Contact Not Found"), + tr("Sorry, \"%1\" is not in your address book.").arg(contactName)); + return; + } + } + + updateInterface(NavigationMode); +} +void AddressBook::updateInterface(Mode mode) +{ + currentMode = mode; + + switch (currentMode) { + + case AddingMode: + case EditingMode: + + nameLine->setReadOnly(false); + nameLine->setFocus(Qt::OtherFocusReason); + addressText->setReadOnly(false); + + addButton->setEnabled(false); + editButton->setEnabled(false); + removeButton->setEnabled(false); + + nextButton->setEnabled(false); + previousButton->setEnabled(false); + + submitButton->show(); + cancelButton->show(); + + loadButton->setEnabled(false); + saveButton->setEnabled(false); + exportButton->setEnabled(false); + break; + + case NavigationMode: + + if (contacts.isEmpty()) { + nameLine->clear(); + addressText->clear(); + } + + nameLine->setReadOnly(true); + addressText->setReadOnly(true); + addButton->setEnabled(true); + + int number = contacts.size(); + editButton->setEnabled(number >= 1); + removeButton->setEnabled(number >= 1); + findButton->setEnabled(number > 2); + nextButton->setEnabled(number > 1); + previousButton->setEnabled(number > 1); + + submitButton->hide(); + cancelButton->hide(); + + exportButton->setEnabled(number >= 1); + + loadButton->setEnabled(true); + saveButton->setEnabled(number >= 1); + break; + } +} + +void AddressBook::saveToFile() +{ + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save Address Book"), "", + tr("Address Book (*.abk);;All Files (*)")); + + if (fileName.isEmpty()) + return; + else { + QFile file(fileName); + + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::information(this, tr("Unable to open file"), + file.errorString()); + return; + } + + QDataStream out(&file); + out.setVersion(QDataStream::Qt_4_3); + out << contacts; + } + + updateInterface(NavigationMode); +} + +void AddressBook::loadFromFile() +{ + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open Address Book"), "", + tr("Address Book (*.abk);;All Files (*)")); + + if (fileName.isEmpty()) + return; + else { + QFile file(fileName); + + if (!file.open(QIODevice::ReadOnly)) { + QMessageBox::information(this, tr("Unable to open file"), + file.errorString()); + return; + } + + QDataStream in(&file); + in.setVersion(QDataStream::Qt_4_3); + in >> contacts; + + QMap::iterator i = contacts.begin(); + nameLine->setText(i.key()); + addressText->setText(i.value()); + } + + updateInterface(NavigationMode); +} + +//! [export function part1] +void AddressBook::exportAsVCard() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + QString firstName; + QString lastName; + QStringList nameList; + + int index = name.indexOf(" "); + + if (index != -1) { + nameList = name.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts); + firstName = nameList.first(); + lastName = nameList.last(); + } else { + firstName = name; + lastName = ""; + } + + QString fileName = QFileDialog::getSaveFileName(this, + tr("Export Contact"), "", + tr("vCard Files (*.vcf);;All Files (*)")); + + if (fileName.isEmpty()) + return; + + QFile file(fileName); +//! [export function part1] + +//! [export function part2] + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::information(this, tr("Unable to open file"), + file.errorString()); + return; + } + + QTextStream out(&file); +//! [export function part2] + +//! [export function part3] + out << "BEGIN:VCARD" << '\n'; + out << "VERSION:2.1" << '\n'; + out << "N:" << lastName << ';' << firstName << '\n'; + + if (!nameList.isEmpty()) + out << "FN:" << nameList.join(' ') << '\n'; + else + out << "FN:" << firstName << '\n'; +//! [export function part3] + +//! [export function part4] + address.replace(";", "\\;", Qt::CaseInsensitive); + address.replace('\n', ";", Qt::CaseInsensitive); + address.replace(",", " ", Qt::CaseInsensitive); + + out << "ADR;HOME:;" << address << '\n'; + out << "END:VCARD" << '\n'; + + QMessageBox::information(this, tr("Export Successful"), + tr("\"%1\" has been exported as a vCard.").arg(name)); +} +//! [export function part4] diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part7/addressbook.h b/tests/manual/examples/widgets/tutorials/addressbook/part7/addressbook.h new file mode 100644 index 0000000000..c408a97642 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part7/addressbook.h @@ -0,0 +1,68 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ADDRESSBOOK_H +#define ADDRESSBOOK_H + +#include +#include +#include "finddialog.h" + +QT_BEGIN_NAMESPACE +class QPushButton; +class QLabel; +class QLineEdit; +class QTextEdit; +QT_END_NAMESPACE + + +class AddressBook : public QWidget +{ + Q_OBJECT + +public: + AddressBook(QWidget *parent = nullptr); + enum Mode { NavigationMode, AddingMode, EditingMode }; + +public slots: + void addContact(); + void editContact(); + void submitContact(); + void cancel(); + void removeContact(); + void findContact(); + void next(); + void previous(); + void saveToFile(); + void loadFromFile(); +//! [exportAsVCard() declaration] + void exportAsVCard(); +//! [exportAsVCard() declaration] + +private: + void updateInterface(Mode mode); + + QPushButton *addButton; + QPushButton *editButton; + QPushButton *removeButton; + QPushButton *findButton; + QPushButton *submitButton; + QPushButton *cancelButton; + QPushButton *nextButton; + QPushButton *previousButton; + QPushButton *loadButton; + QPushButton *saveButton; +//! [exportButton declaration] + QPushButton *exportButton; +//! [exportButton declaration] + QLineEdit *nameLine; + QTextEdit *addressText; + + QMap contacts; + FindDialog *dialog; + QString oldName; + QString oldAddress; + Mode currentMode; +}; + +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part7/finddialog.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part7/finddialog.cpp new file mode 100644 index 0000000000..90729d9c12 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part7/finddialog.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "finddialog.h" + +FindDialog::FindDialog(QWidget *parent) + : QDialog(parent) +{ + QLabel *findLabel = new QLabel(tr("Enter the name of a contact:")); + lineEdit = new QLineEdit; + + findButton = new QPushButton(tr("&Find")); + findText = ""; + + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(findLabel); + layout->addWidget(lineEdit); + layout->addWidget(findButton); + + setLayout(layout); + setWindowTitle(tr("Find a Contact")); + connect(findButton, &QPushButton::clicked, + this, &FindDialog::findClicked); + connect(findButton, &QPushButton::clicked, + this, &FindDialog::accept); +} + +void FindDialog::findClicked() +{ + QString text = lineEdit->text(); + + if (text.isEmpty()) { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name.")); + return; + } else { + findText = text; + lineEdit->clear(); + hide(); + } +} + +QString FindDialog::getFindText() +{ + return findText; +} diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part7/finddialog.h b/tests/manual/examples/widgets/tutorials/addressbook/part7/finddialog.h new file mode 100644 index 0000000000..7c9a3af30f --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part7/finddialog.h @@ -0,0 +1,31 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef FINDDIALOG_H +#define FINDDIALOG_H + +#include + +QT_BEGIN_NAMESPACE +class QLineEdit; +class QPushButton; +QT_END_NAMESPACE + +class FindDialog : public QDialog +{ + Q_OBJECT + +public: + FindDialog(QWidget *parent = nullptr); + QString getFindText(); + +public slots: + void findClicked(); + +private: + QPushButton *findButton; + QLineEdit *lineEdit; + QString findText; +}; + +#endif diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part7/main.cpp b/tests/manual/examples/widgets/tutorials/addressbook/part7/main.cpp new file mode 100644 index 0000000000..1f3aac3397 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part7/main.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include +#include "addressbook.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + AddressBook addressBook; + addressBook.show(); + + return app.exec(); +} diff --git a/tests/manual/examples/widgets/tutorials/addressbook/part7/part7.pro b/tests/manual/examples/widgets/tutorials/addressbook/part7/part7.pro new file mode 100644 index 0000000000..6a99799c67 --- /dev/null +++ b/tests/manual/examples/widgets/tutorials/addressbook/part7/part7.pro @@ -0,0 +1,14 @@ +QT += widgets +requires(qtConfig(filedialog)) + +SOURCES = addressbook.cpp \ + finddialog.cpp \ + main.cpp +HEADERS = addressbook.h \ + finddialog.h + +QMAKE_PROJECT_NAME = ab_part7 + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/addressbook/part7 +INSTALLS += target -- cgit v1.2.1