| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the documentation of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:FDL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Free Documentation License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Free |
| ** Documentation License version 1.3 as published by the Free Software |
| ** Foundation and appearing in the file included in the packaging of |
| ** this file. Please review the following information to ensure |
| ** the GNU Free Documentation License version 1.3 requirements |
| ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /*! |
| \example widgets/icons |
| \title Icons Example |
| \ingroup examples-widgets |
| \brief The Icons example shows how QIcon can generate pixmaps reflecting |
| an icon's state, mode and size. |
| |
| These pixmaps are generated from the set of pixmaps made available to the |
| icon, and are used by Qt widgets to show an icon representing a particular |
| action. |
| |
| \image icons-example.png Screenshot of the Icons example |
| |
| Contents: |
| |
| \tableofcontents |
| |
| \section1 QIcon Overview |
| |
| The QIcon class provides scalable icons in different modes and |
| states. An icon's state and mode are depending on the intended use |
| of the icon. Qt currently defines four modes: |
| |
| \table |
| \header \li Mode \li Description |
| \row |
| \li QIcon::Normal |
| \li Display the pixmap when the user is not interacting with the |
| icon, but the functionality represented by the icon is |
| available. |
| \row |
| \li QIcon::Active |
| \li Display the pixmap when the functionality represented by the |
| icon is available and the user is interacting with the icon, |
| for example, moving the mouse over it or clicking it. |
| \row |
| \li QIcon::Disabled |
| \li Display the pixmap when the functionality represented by |
| the icon is not available. |
| \row |
| \li QIcon::Selected |
| \li Display the pixmap when the icon is selected. |
| \endtable |
| |
| QIcon's states are QIcon::On and QIcon::Off, which will display |
| the pixmap when the widget is in the respective state. The most |
| common usage of QIcon's states are when displaying checkable tool |
| buttons or menu entries (see QAbstractButton::setCheckable() and |
| QAction::setCheckable()). When a tool button or menu entry is |
| checked, the QIcon's state is \l{QIcon::}{On}, otherwise it's |
| \l{QIcon::}{Off}. You can, for example, use the QIcon's states to |
| display differing pixmaps depending on whether the tool button or |
| menu entry is checked or not. |
| |
| A QIcon can generate smaller, larger, active, disabled, and |
| selected pixmaps from the set of pixmaps it is given. Such |
| pixmaps are used by Qt widgets to show an icon representing a |
| particular action. |
| |
| \section1 Overview of the Icons Application |
| |
| With the Icons application you get a preview of an icon's |
| generated pixmaps reflecting its different states, modes and size. |
| |
| When an image is loaded into the application, it is converted into |
| a pixmap and becomes a part of the set of pixmaps available to the |
| icon. An image can be excluded from this set by checking off the |
| related checkbox. The application provides a sub directory |
| containing sets of images explicitly designed to illustrate how Qt |
| renders an icon in different modes and states. |
| |
| The application allows you to manipulate the icon size with some |
| predefined sizes and a spin box. The predefined sizes are style |
| dependent, but most of the styles have the same values. Only the |
| \macos style differs by using 32 pixels instead of 16 pixels |
| for toolbar buttons. You can navigate between the available styles |
| using the \uicontrol View menu. |
| |
| \image icons-view-menu.png Screenshot of the View menu |
| |
| The \uicontrol View menu also provide the option to make the application |
| guess the icon state and mode from an image's file name. The \uicontrol |
| File menu provide the options of adding an image and removing all |
| images. These last options are also available through a context |
| menu that appears if you press the right mouse button within the |
| table of image files. In addition, the \uicontrol File menu provide an |
| \uicontrol Exit option, and the \uicontrol Help menu provide information about |
| the example and about Qt. |
| |
| \image icons_find_normal.png Screenshot of the Find Files |
| |
| The screenshot above shows the application with one image file |
| loaded. The \uicontrol {Guess Image Mode/State} is enabled and the |
| style is Plastique. |
| |
| When QIcon is provided with only one available pixmap, that |
| pixmap is used for all the states and modes. In this case the |
| pixmap's icon mode is set to normal, and the generated pixmaps |
| for the normal and active modes will look the same. But in |
| disabled and selected mode, Qt will generate a slightly different |
| pixmap. |
| |
| The next screenshot shows the application with an additional file |
| loaded, providing QIcon with two available pixmaps. Note that the |
| new image file's mode is set to disabled. When rendering the \uicontrol |
| Disabled mode pixmaps, Qt will now use the new image. We can see |
| the difference: The generated disabled pixmap in the first |
| screenshot is slightly darker than the pixmap with the originally |
| set disabled mode in the second screenshot. |
| |
| \image icons_find_normal_disabled.png Screenshot of the Find Files |
| |
| When Qt renders the icon's pixmaps it searches through the set of |
| available pixmaps following a particular algorithm. The algorithm |
| is documented in QIcon, but we will describe some particular cases |
| below. |
| |
| \image icons_monkey_active.png Screenshot of the Find Files |
| |
| In the screenshot above, we have set \c monkey_on_32x32 to be an |
| Active/On pixmap and \c monkey_off_64x64 to be Normal/Off. To |
| render the other six mode/state combinations, QIcon uses the |
| search algorithm described in the table below: |
| |
| \table 100% |
| \header \li{2,1} Requested Pixmap \li {8,1} Preferred Alternatives (mode/state) |
| \header \li Mode \li State \li 1 \li 2 \li 3 \li 4 \li 5 \li 6 \li 7 \li 8 |
| \row \li{1,2} Normal \li Off \li \b N0 \li A0 \li N1 \li A1 \li D0 \li S0 \li D1 \li S1 |
| \row \li On \li N1 \li \b A1 \li N0 \li A0 \li D1 \li S1 \li D0 \li S0 |
| \row \li{1,2} Active \li Off \li A0 \li \b N0 \li A1 \li N1 \li D0 \li S0 \li D1 \li S1 |
| \row \li On \li \b A1 \li N1 \li A0 \li N0 \li D1 \li S1 \li D0 \li S0 |
| \row \li{1,2} Disabled \li Off \li D0 \li \b {N0'} \li A0' \li D1 \li N1' \li A1' \li S0' \li S1' |
| \row \li On \li D1 \li N1' \li \b {A1'} \li D0 \li N0' \li A0' \li S1' \li S0' |
| \row \li{1,2} Selected \li Off \li S0 \li \b {N0''} \li A0'' \li S1 \li N1'' \li A1'' \li D0'' \li D1'' |
| \row \li On \li S1 \li N1'' \li \b {A1''} \li S0 \li N0'' \li A0'' \li D1'' \li D0'' |
| \endtable |
| |
| In the table, "0" and "1" stand for "Off" and "On", respectively. |
| Single quotes indicates that QIcon generates a disabled ("grayed |
| out") version of the pixmap; similarly, double quuote indicate |
| that QIcon generates a selected ("blued out") version of the |
| pixmap. |
| |
| The alternatives used in the screenshot above are shown in bold. |
| For example, the Disabled/Off pixmap is derived by graying out |
| the Normal/Off pixmap (\c monkey_off_64x64). |
| |
| In the next screenshots, we loaded the whole set of monkey |
| images. By checking or unchecking file names from the image list, |
| we get different results: |
| |
| \table |
| \row |
| \li \inlineimage icons_monkey.png Screenshot of the Monkey Files |
| \li \inlineimage icons_monkey_mess.png Screenshot of the Monkey Files |
| \endtable |
| |
| For any given mode/state combination, it is possible to specify |
| several images at different resolutions. When rendering an |
| icon, QIcon will automatically pick the most suitable image |
| and scale it down if necessary. (QIcon never scales up images, |
| because this rarely looks good.) |
| |
| The screenshots below shows what happens when we provide QIcon |
| with three images (\c qt_extended_16x16.png, \c qt_extended_32x32.png, \c |
| qt_extended_48x48.png) and try to render the QIcon at various |
| resolutions: |
| |
| \table |
| \row |
| \li |
| \li \inlineimage icons_qt_extended_8x8.png Qt Extended icon at 8 x 8 |
| \li \inlineimage icons_qt_extended_16x16.png Qt Extended icon at 16 x 16 |
| \li \inlineimage icons_qt_extended_17x17.png Qt Extended icon at 17 x 17 |
| \row |
| \li |
| \li 8 x 8 |
| \li \b {16 x 16} |
| \li 17 x 17 |
| \row |
| \li \inlineimage icons_qt_extended_32x32.png Qt Extended icon at 32 x 32 |
| \li \inlineimage icons_qt_extended_33x33.png Qt Extended icon at 33 x 33 |
| \li \inlineimage icons_qt_extended_48x48.png Qt Extended icon at 48 x 48 |
| \li \inlineimage icons_qt_extended_64x64.png Qt Extended icon at 64 x 64 |
| \row |
| \li \b {32 x 32} |
| \li 33 x 33 |
| \li \b {48 x 48} |
| \li 64 x 64 |
| \endtable |
| |
| For sizes up to 16 x 16, QIcon uses \c qt_extended_16x16.png and |
| scales it down if necessary. For sizes between 17 x 17 and 32 x |
| 32, it uses \c qt_extended_32x32.png. For sizes above 32 x 32, it uses |
| \c qt_extended_48x48.png. |
| |
| \section1 Line-by-Line Walkthrough |
| |
| The Icons example consists of four classes: |
| |
| \list |
| \li \c MainWindow inherits QMainWindow and is the main application |
| window. |
| \li \c IconPreviewArea is a custom widget that displays all |
| combinations of states and modes for a given icon. |
| \li \c IconSizeSpinBox is a subclass of QSpinBox that lets the |
| user enter icon sizes (e.g., "48 x 48"). |
| \li \c ImageDelegate is a subclass of QStyledItemDelegate that |
| provides comboboxes for letting the user set the mode and state |
| associated with an image. |
| \endlist |
| |
| We will start by reviewing the \c IconPreviewArea class before we |
| take a look at the \c MainWindow class. Finally, we will review the |
| \c IconSizeSpinBox and \c ImageDelegate classes. |
| |
| \section2 IconPreviewArea Class Definition |
| |
| An \c IconPreviewArea widget consists of a group box containing a grid of |
| QLabel widgets displaying headers and pixmaps. |
| |
| \image icons_preview_area.png Screenshot of IconPreviewArea. |
| |
| \snippet widgets/icons/iconpreviewarea.h 0 |
| |
| The \c IconPreviewArea class inherits QWidget. It displays the |
| generated pixmaps corresponding to an icon's possible states and |
| modes at a given size. |
| |
| \snippet widgets/icons/iconpreviewarea.cpp 42 |
| |
| We would like the table columns to be in the order QIcon::Normal, |
| QIcon::Active, QIcon::Disabled, QIcon::Selected and the rows in the order |
| QIcon::Off, QIcon::On, which does not match the enumeration. The above code |
| provides arrays allowing to map from enumeration value to row/column |
| (by using QVector::indexOf()) and back by using the array index and lists |
| of the matching strings. Qt's containers can be easily populated by |
| using C++ 11 initializer lists. |
| |
| We need two public functions to set the current icon and the |
| icon's size. In addition the class has three private functions: We |
| use the \c createHeaderLabel() and \c createPixmapLabel() |
| functions when constructing the preview area, and we need the \c |
| updatePixmapLabels() function to update the preview area when |
| the icon or the icon's size has changed. |
| |
| The \c NumModes and \c NumStates constants reflect \l{QIcon}'s |
| number of currently defined modes and states. |
| |
| \section2 IconPreviewArea Class Implementation |
| |
| \snippet widgets/icons/iconpreviewarea.cpp 0 |
| |
| In the constructor we create the labels displaying the headers and |
| the icon's generated pixmaps, and add them to a grid layout. |
| |
| When creating the header labels, we make sure the enums \c |
| NumModes and \c NumStates defined in the \c .h file, correspond |
| with the number of labels that we create. Then if the enums at |
| some point are changed, the \c Q_ASSERT() macro will alert that this |
| part of the \c .cpp file needs to be updated as well. |
| |
| If the application is built in debug mode, the \c Q_ASSERT() |
| macro will expand to |
| |
| \code |
| if (!condition) |
| qFatal("ASSERT: "condition" in file ..."); |
| \endcode |
| |
| In release mode, the macro simply disappear. The mode can be set |
| in the application's \c .pro file. One way to do so is to add an |
| option to \c qmake when building the application: |
| |
| \code |
| qmake "CONFIG += debug" icons.pro |
| \endcode |
| |
| or |
| |
| \code |
| qmake "CONFIG += release" icons.pro |
| \endcode |
| |
| Another approach is to add this line directly to the \c .pro |
| file. |
| |
| \snippet widgets/icons/iconpreviewarea.cpp 1 |
| \codeline |
| \snippet widgets/icons/iconpreviewarea.cpp 2 |
| |
| The public \c setIcon() and \c setSize() functions change the icon |
| or the icon size, and make sure that the generated pixmaps are |
| updated. |
| |
| \snippet widgets/icons/iconpreviewarea.cpp 3 |
| \codeline |
| \snippet widgets/icons/iconpreviewarea.cpp 4 |
| |
| We use the \c createHeaderLabel() and \c createPixmapLabel() |
| functions to create the preview area's labels displaying the |
| headers and the icon's generated pixmaps. Both functions return |
| the QLabel that is created. |
| |
| \snippet widgets/icons/iconpreviewarea.cpp 5 |
| |
| We use the private \c updatePixmapLabel() function to update the |
| generated pixmaps displayed in the preview area. |
| |
| For each mode, and for each state, we retrieve a pixmap using the |
| QIcon::pixmap() function, which generates a pixmap corresponding |
| to the given state, mode and size. We pass the QWindows instance |
| obtained by calling QWidget::windowHandle() on the top level |
| widget (QWidget::nativeParentWidget()) in order to retrieve |
| the pixmap that matches best. |
| We format a tooltip displaying size, actual size and device pixel |
| ratio. |
| |
| \section2 MainWindow Class Definition |
| |
| The \c MainWindow widget consists of three main elements: an |
| images group box, an icon size group box and a preview area. |
| |
| \image icons-example.png Screenshot of the Icons example |
| |
| \snippet widgets/icons/mainwindow.h 0 |
| |
| The MainWindow class inherits from QMainWindow. We reimplement the |
| constructor, and declare several private slots: |
| |
| \list |
| \li The \c about() slot simply provides information about the example. |
| \li The \c changeStyle() slot changes the application's GUI style and |
| adjust the style dependent size options. |
| \li The \c changeSize() slot changes the size of the preview area's icon. |
| \li The \c changeIcon() slot updates the set of pixmaps available to the |
| icon displayed in the preview area. |
| \li The \c addSampleImages() slot allows the user to load a new image |
| from the samples provided into the application. |
| \li The \c addOtherImages() slot allows the user to load a new image from |
| the directory obtained by calling |
| QStandardPaths::standardLocations(QStandardPaths::PicturesLocation). |
| \li The \c screenChanged() updates the display in the \uicontrol{High DPI} |
| group box to correctly display the parameters of the current screen |
| the window is located on. |
| \endlist |
| |
| In addition we declare several private functions to simplify the |
| constructor. |
| |
| \section2 MainWindow Class Implementation |
| |
| \snippet widgets/icons/mainwindow.cpp 0 |
| |
| In the constructor we first create the main window's central |
| widget and its child widgets, and put them in a grid layout. Then |
| we create the menus with their associated entries and actions. |
| |
| We set the window title and determine the current style for the |
| application. We also enable the icon size spin box by clicking the |
| associated radio button, making the current value of the spin box |
| the icon's initial size. |
| |
| \snippet widgets/icons/mainwindow.cpp 1 |
| |
| The \c about() slot displays a message box using the static |
| QMessageBox::about() function. In this example it displays a |
| simple box with information about the example. |
| |
| The \c about() function looks for a suitable icon in four |
| locations: It prefers its parent's icon if that exists. If it |
| doesn't, the function tries the top-level widget containing |
| parent, and if that fails, it tries the active window. As a last |
| resort it uses the QMessageBox's Information icon. |
| |
| \snippet widgets/icons/mainwindow.cpp 2 |
| |
| In the \c changeStyle() slot we first check the slot's |
| parameter. If it is false we immediately return, otherwise we find |
| out which style to change to, i.e. which action that triggered the |
| slot, using the QObject::sender() function. |
| |
| This function returns the sender as a QObject pointer. Since we |
| know that the sender is a QAction object, we can safely cast the |
| QObject. We could have used a C-style cast or a C++ \c |
| static_cast(), but as a defensive programming technique we use a |
| \l qobject_cast(). The advantage is that if the object has the |
| wrong type, a null pointer is returned. Crashes due to null |
| pointers are much easier to diagnose than crashes due to unsafe |
| casts. |
| |
| \snippet widgets/icons/mainwindow.cpp 3 |
| \snippet widgets/icons/mainwindow.cpp 4 |
| |
| Once we have the action, we extract the style name using |
| QAction::data(). Then we create a QStyle object using the static |
| QStyleFactory::create() function. |
| |
| Although we can assume that the style is supported by the |
| QStyleFactory: To be on the safe side, we use the \c Q_ASSERT() |
| macro to check if the created style is valid before we use the |
| QApplication::setStyle() function to set the application's GUI |
| style to the new style. QApplication will automatically delete |
| the style object when a new style is set or when the application |
| exits. |
| |
| The predefined icon size options provided in the application are |
| style dependent, so we need to update the labels in the icon size |
| group box and in the end call the \c changeSize() slot to update |
| the icon's size. |
| |
| \snippet widgets/icons/mainwindow.cpp 5 |
| |
| The \c changeSize() slot sets the size for the preview area's |
| icon. |
| |
| It is invoked by the QButtonGroup whose members are radio buttons for |
| controlling the icon size. In \c createIconSizeGroupBox(), each button is |
| assigned a QStyle::PixelMetric value as an id, which is passed as a |
| parameter to the slot. |
| |
| The special value \c OtherSize indicates that the spin box is |
| enabled. If it is, we extract the extent of the new size from the |
| box. If it's not, we query the style for the metric. Then we create |
| a QSize object based on the extent, and use that object to set the |
| size of the preview area's icon. |
| |
| \snippet widgets/icons/mainwindow.cpp 12 |
| |
| The function \c addImages() is called by the slot addSampleImages() |
| passing the samples directory, or by the slot addOtherImages() |
| passing the directory obtained by querying |
| QStandardPaths::standardLocations(). |
| |
| The first thing we do is to show a file dialog to the user. |
| We initialize it to show the filters returned by |
| QImageReader::supportedMimeTypes(). |
| |
| For each of the files the file dialog returns, we add a row to the |
| table widget. The table widget is listing the images the user has |
| loaded into the application. |
| |
| \snippet widgets/icons/mainwindow.cpp 13 |
| |
| We retrieve the image name using the QFileInfo::baseName() |
| function that returns the base name of the file without the path, |
| and create the first table widget item in the row. |
| We check if a high resolution version of the image exists (identified by |
| the suffix \c @2x on the base name) and display that along with the size |
| in the tooltip. |
| |
| We add the file's complete name to the item's data. Since an item can |
| hold several information pieces, we need to assign the file name a role |
| that will distinguish it from other data. This role can be Qt::UserRole |
| or any value above it. |
| |
| We also make sure that the item is not editable by removing the |
| Qt::ItemIsEditable flag. Table items are editable by default. |
| |
| \snippet widgets/icons/mainwindow.cpp 15 |
| |
| Then we create the second and third items in the row making the |
| default mode Normal and the default state Off. But if the \uicontrol |
| {Guess Image Mode/State} option is checked, and the file name |
| contains "_act", "_dis", or "_sel", the modes are changed to |
| Active, Disabled, or Selected. And if the file name contains |
| "_on", the state is changed to On. The sample files in the |
| example's \c images subdirectory respect this naming convention. |
| |
| \snippet widgets/icons/mainwindow.cpp 18 |
| |
| In the end we add the items to the associated row, and use the |
| QTableWidget::openPersistentEditor() function to create |
| comboboxes for the mode and state columns of the items. |
| |
| Due to the connection between the table widget's \l |
| {QTableWidget::itemChanged()}{itemChanged()} signal and the \c |
| changeIcon() slot, the new image is automatically converted into a |
| pixmap and made part of the set of pixmaps available to the icon |
| in the preview area. So, corresponding to this fact, we need to |
| make sure that the new image's check box is enabled. |
| |
| \snippet widgets/icons/mainwindow.cpp 6 |
| |
| The \c changeIcon() slot is called when the user alters the set |
| of images listed in the QTableWidget, to update the QIcon object |
| rendered by the \c IconPreviewArea. |
| |
| We first create a QIcon object, and then we run through the |
| QTableWidget, which lists the images the user has loaded into the |
| application. |
| |
| \snippet widgets/icons/mainwindow.cpp 8 |
| |
| We also extract the image file's name using the |
| QTableWidgetItem::data() function. This function takes a |
| Qt::DataItemRole as an argument to retrieve the right data |
| (remember that an item can hold several pieces of information) |
| and returns it as a QVariant. Then we use the |
| QVariant::toString() function to get the file name as a QString. |
| |
| To create a pixmap from the file, we need to first create an |
| image and then convert this image into a pixmap using |
| QPixmap::fromImage(). Once we have the final pixmap, we add it, |
| with its associated mode and state, to the QIcon's set of |
| available pixmaps. |
| |
| \snippet widgets/icons/mainwindow.cpp 11 |
| |
| After running through the entire list of images, we change the |
| icon of the preview area to the one we just created. |
| |
| \snippet widgets/icons/mainwindow.cpp 20 |
| |
| In the \c removeAllImages() slot, we simply set the table widget's |
| row count to zero, automatically removing all the images the user |
| has loaded into the application. Then we update the set of pixmaps |
| available to the preview area's icon using the \c changeIcon() |
| slot. |
| |
| \image icons_images_groupbox.png Screenshot of the images group box |
| |
| The \c createImagesGroupBox() function is implemented to simplify |
| the constructor. The main purpose of the function is to create a |
| QTableWidget that will keep track of the images the user has |
| loaded into the application. |
| |
| \snippet widgets/icons/mainwindow.cpp 21 |
| |
| First we create a group box that will contain the table widget. |
| Then we create a QTableWidget and customize it to suit our |
| purposes. |
| |
| We call QAbstractItemView::setSelectionMode() to prevent the user |
| from selecting items. |
| |
| The QAbstractItemView::setItemDelegate() call sets the item |
| delegate for the table widget. We create a \c ImageDelegate that |
| we make the item delegate for our view. |
| |
| The QStyledItemDelegate class can be used to provide an editor for an item view |
| class that is subclassed from QAbstractItemView. Using a delegate |
| for this purpose allows the editing mechanism to be customized and |
| developed independently from the model and view. |
| |
| In this example we derive \c ImageDelegate from QStyledItemDelegate. |
| QStyledItemDelegate usually provides line editors, while our subclass |
| \c ImageDelegate, provides comboboxes for the mode and state |
| fields. |
| |
| \snippet widgets/icons/mainwindow.cpp 22 |
| |
| Then we customize the QTableWidget's horizontal header, and hide |
| the vertical header. |
| |
| \snippet widgets/icons/mainwindow.cpp 24 |
| |
| At the end, we connect the QTableWidget::itemChanged() signal to |
| the \c changeIcon() slot to ensure that the preview area is in |
| sync with the image table. |
| |
| \image icons_size_groupbox.png Screenshot of the icon size group box |
| |
| The \c createIconSizeGroupBox() function is called from the |
| constructor. It creates the widgets controlling the size of the |
| preview area's icon. |
| |
| \snippet widgets/icons/mainwindow.cpp 26 |
| |
| First we create a group box that will contain all the widgets; |
| then we create the radio buttons and the spin box. We add the |
| radio buttons to an instance of QButtonGroup, using the value |
| of the QStyle::PixelMetric they represent as an integer id. |
| |
| \snippet widgets/icons/mainwindow.cpp 40 |
| |
| We introduce an enumeration constant \c OtherSize to represent |
| a custom size. |
| |
| The spin box is not a regular QSpinBox but an \c IconSizeSpinBox. |
| The \c IconSizeSpinBox class inherits QSpinBox and reimplements |
| two functions: QSpinBox::textFromValue() and |
| QSpinBox::valueFromText(). The \c IconSizeSpinBox is designed to |
| handle icon sizes, e.g., "32 x 32", instead of plain integer |
| values. |
| |
| \snippet widgets/icons/mainwindow.cpp 27 |
| |
| Then we connect all of the radio buttons |
| \l{QRadioButton::toggled()}{toggled()} signals and the spin box's |
| \l {QSpinBox::valueChanged()}{valueChanged()} signal to the \c |
| changeSize() slot to make sure that the size of the preview |
| area's icon is updated whenever the user changes the icon size. |
| In the end we put the widgets in a layout that we install on the |
| group box. |
| |
| \snippet widgets/icons/mainwindow.cpp 28 |
| |
| In the \c createActions() function we create and customize all the |
| actions needed to implement the functionality associated with the |
| menu entries in the application. |
| |
| In particular we create the \c styleActionGroup based on the |
| currently available GUI styles using |
| QStyleFactory. QStyleFactory::keys() returns a list of valid keys, |
| typically including "windows" and "fusion". Depending on the platform, |
| "windowsvista" and "macintosh" may be available. |
| |
| We create one action for each key, and adds the action to the |
| action group. Also, for each action, we call QAction::setData() |
| with the style name. We will retrieve it later using |
| QAction::data(). |
| |
| As we go along, we create the \uicontrol File, \uicontrol View and |
| \uicontrol Help menus and add the actions to them. |
| |
| The QMenu class provides a menu widget for use in menu bars, |
| context menus, and other popup menus. We put each menu in the |
| application's menu bar, which we retrieve using |
| QMainWindow::menuBar(). |
| |
| \snippet widgets/icons/mainwindow.cpp 30 |
| |
| QWidgets have a \l{QWidget::contextMenuPolicy}{contextMenuPolicy} |
| property that controls how the widget should behave when the user |
| requests a context menu (e.g., by right-clicking). We set the |
| QTableWidget's context menu policy to Qt::ActionsContextMenu, |
| meaning that the \l{QAction}s associated with the widget should |
| appear in its context menu. |
| |
| Then we add the \uicontrol{Add Image} and \uicontrol{Remove All Images} |
| actions to the table widget. They will then appear in the table |
| widget's context menu. |
| |
| \snippet widgets/icons/mainwindow.cpp 31 |
| |
| In the \c checkCurrentStyle() function we go through the group of |
| style actions, looking for the current GUI style. |
| |
| For each action, we first extract the style name using |
| QAction::data(). Since this is only a QStyleFactory key (e.g., |
| "macintosh"), we cannot compare it directly to the current |
| style's class name. We need to create a QStyle object using the |
| static QStyleFactory::create() function and compare the class |
| name of the created QStyle object with that of the current style. |
| As soon as we are done with a QStyle candidate, we delete it. |
| |
| For all QObject subclasses that use the \c Q_OBJECT macro, the |
| class name of an object is available through its |
| \l{QObject::metaObject()}{meta-object}. |
| |
| We can assume that the style is supported by |
| QStyleFactory, but to be on the safe side we use the \c |
| Q_ASSERT() macro to make sure that QStyleFactory::create() |
| returned a valid pointer. |
| |
| \snippet widgets/icons/mainwindow.cpp 44 |
| |
| We overload the show() function to set up the updating of the |
| current screen in \c screenChanged(). After calling QWidget::show(), |
| the QWindow associated with the QWidget is created and we can |
| connect to its QWindow::screenChanged() signal. |
| |
| \section2 IconSizeSpinBox Class Definition |
| |
| \snippet widgets/icons/iconsizespinbox.h 0 |
| |
| The \c IconSizeSpinBox class is a subclass of QSpinBox. A plain |
| QSpinBox can only handle integers. But since we want to display |
| the spin box's values in a more sophisticated way, we need to |
| subclass QSpinBox and reimplement the QSpinBox::textFromValue() |
| and QSpinBox::valueFromText() functions. |
| |
| \image icons_size_spinbox.png Screenshot of the icon size spinbox |
| |
| \section2 IconSizeSpinBox Class Implementation |
| |
| \snippet widgets/icons/iconsizespinbox.cpp 0 |
| |
| The constructor is trivial. |
| |
| \snippet widgets/icons/iconsizespinbox.cpp 2 |
| |
| QSpinBox::textFromValue() is used by the spin box whenever it |
| needs to display a value. The default implementation returns a |
| base 10 representation of the \c value parameter. |
| |
| Our reimplementation returns a QString of the form "32 x 32". |
| |
| \snippet widgets/icons/iconsizespinbox.cpp 1 |
| |
| The QSpinBox::valueFromText() function is used by the spin box |
| whenever it needs to interpret text typed in by the user. Since |
| we reimplement the \c textFromValue() function we also need to |
| reimplement the \c valueFromText() function to interpret the |
| parameter text and return the associated int value. |
| |
| We parse the text using a regular expression (a QRegularExpression). We |
| define an expression that matches one or several digits, |
| optionally followed by whitespace, an "x" or the times symbol, |
| whitespace and one or several digits again. |
| |
| The first digits of the regular expression are captured using |
| parentheses. This enables us to use the QRegularExpressionMatch::captured() |
| or QRegularExpressionMatch::capturedTexts() functions to extract the matched |
| characters. If the first and second numbers of the spin box value |
| differ (e.g., "16 x 24"), we use the first number. |
| |
| When the user presses \uicontrol Enter, QSpinBox first calls |
| QSpinBox::valueFromText() to interpret the text typed by the |
| user, then QSpinBox::textFromValue() to present it in a canonical |
| format (e.g., "16 x 16"). |
| |
| \section2 ImageDelegate Class Definition |
| |
| \snippet widgets/icons/imagedelegate.h 0 |
| |
| The \c ImageDelegate class is a subclass of QStyledItemDelegate. The |
| QStyledItemDelegate class provides display and editing facilities for |
| data items from a model. A single QStyledItemDelegate object is |
| responsible for all items displayed in a item view (in our case, |
| a QTableWidget). |
| |
| A QStyledItemDelegate can be used to provide an editor for an item view |
| class that is subclassed from QAbstractItemView. Using a delegate |
| for this purpose allows the editing mechanism to be customized and |
| developed independently from the model and view. |
| |
| \snippet widgets/icons/imagedelegate.h 1 |
| |
| The default implementation of QStyledItemDelegate creates a QLineEdit. |
| Since we want the editor to be a QComboBox, we need to subclass |
| QStyledItemDelegate and reimplement the QStyledItemDelegate::createEditor(), |
| QStyledItemDelegate::setEditorData() and QStyledItemDelegate::setModelData() |
| functions. |
| |
| \snippet widgets/icons/imagedelegate.h 2 |
| |
| The \c emitCommitData() slot is used to emit the |
| QImageDelegate::commitData() signal with the appropriate |
| argument. |
| |
| \section2 ImageDelegate Class Implementation |
| |
| \snippet widgets/icons/imagedelegate.cpp 0 |
| |
| The constructor is trivial. |
| |
| \snippet widgets/icons/imagedelegate.cpp 1 |
| |
| The default QStyledItemDelegate::createEditor() implementation returns |
| the widget used to edit the item specified by the model and item |
| index for editing. The parent widget and style option are used to |
| control the appearance of the editor widget. |
| |
| Our reimplementation creates and populates a combobox instead of |
| the default line edit. The contents of the combobox depends on |
| the column in the table for which the editor is requested. Column |
| 1 contains the QIcon modes, whereas column 2 contains the QIcon |
| states. |
| |
| In addition, we connect the combobox's \l |
| {QComboBox::activated()}{activated()} signal to the \c |
| emitCommitData() slot to emit the |
| QAbstractItemDelegate::commitData() signal whenever the user |
| chooses an item using the combobox. This ensures that the rest of |
| the application notices the change and updates itself. |
| |
| \snippet widgets/icons/imagedelegate.cpp 2 |
| |
| The QStyledItemDelegate::setEditorData() function is used by |
| QTableWidget to transfer data from a QTableWidgetItem to the |
| editor. The data is stored as a string; we use |
| QComboBox::findText() to locate it in the combobox. |
| |
| Delegates work in terms of models, not items. This makes it |
| possible to use them with any item view class (e.g., QListView, |
| QListWidget, QTreeView, etc.). The transition between model and |
| items is done implicitly by QTableWidget; we don't need to worry |
| about it. |
| |
| \snippet widgets/icons/imagedelegate.cpp 3 |
| |
| The QStyledItemDelegate::setEditorData() function is used by QTableWidget |
| to transfer data back from the editor to the \l{QTableWidgetItem}. |
| |
| \snippet widgets/icons/imagedelegate.cpp 4 |
| |
| The \c emitCommitData() slot simply emit the |
| QAbstractItemDelegate::commitData() signal for the editor that |
| triggered the slot. This signal must be emitted when the editor |
| widget has completed editing the data, and wants to write it back |
| into the model. |
| |
| \section2 The Implementation of the Function main() |
| |
| \snippet widgets/icons/main.cpp 45 |
| |
| We use QCommandLineParser to handle any command line options or parameters |
| passed to the application. Then, we resize the main window according |
| to the available screen geometry and show it. |
| */ |