| 1 | /**************************************************************************** | 
|---|
| 2 | ** | 
|---|
| 3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). | 
|---|
| 4 | ** Contact: Qt Software Information (qt-info@nokia.com) | 
|---|
| 5 | ** | 
|---|
| 6 | ** This file is part of the documentation of the Qt Toolkit. | 
|---|
| 7 | ** | 
|---|
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | 
|---|
| 9 | ** Commercial Usage | 
|---|
| 10 | ** Licensees holding valid Qt Commercial licenses may use this file in | 
|---|
| 11 | ** accordance with the Qt Commercial License Agreement provided with the | 
|---|
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
|---|
| 13 | ** a written agreement between you and Nokia. | 
|---|
| 14 | ** | 
|---|
| 15 | ** GNU Lesser General Public License Usage | 
|---|
| 16 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
|---|
| 17 | ** General Public License version 2.1 as published by the Free Software | 
|---|
| 18 | ** Foundation and appearing in the file LICENSE.LGPL included in the | 
|---|
| 19 | ** packaging of this file.  Please review the following information to | 
|---|
| 20 | ** ensure the GNU Lesser General Public License version 2.1 requirements | 
|---|
| 21 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | 
|---|
| 22 | ** | 
|---|
| 23 | ** In addition, as a special exception, Nokia gives you certain | 
|---|
| 24 | ** additional rights. These rights are described in the Nokia Qt LGPL | 
|---|
| 25 | ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this | 
|---|
| 26 | ** package. | 
|---|
| 27 | ** | 
|---|
| 28 | ** GNU General Public License Usage | 
|---|
| 29 | ** Alternatively, this file may be used under the terms of the GNU | 
|---|
| 30 | ** General Public License version 3.0 as published by the Free Software | 
|---|
| 31 | ** Foundation and appearing in the file LICENSE.GPL included in the | 
|---|
| 32 | ** packaging of this file.  Please review the following information to | 
|---|
| 33 | ** ensure the GNU General Public License version 3.0 requirements will be | 
|---|
| 34 | ** met: http://www.gnu.org/copyleft/gpl.html. | 
|---|
| 35 | ** | 
|---|
| 36 | ** If you are unsure which license is appropriate for your use, please | 
|---|
| 37 | ** contact the sales department at qt-sales@nokia.com. | 
|---|
| 38 | ** $QT_END_LICENSE$ | 
|---|
| 39 | ** | 
|---|
| 40 | ****************************************************************************/ | 
|---|
| 41 |  | 
|---|
| 42 | /*! | 
|---|
| 43 | \example desktop/screenshot | 
|---|
| 44 | \title Screenshot Example | 
|---|
| 45 |  | 
|---|
| 46 | The Screenshot example shows how to take a screenshot of the | 
|---|
| 47 | desktop using QApplication and QDesktopWidget. It also shows how | 
|---|
| 48 | to use QTimer to provide a single-shot timer, and how to | 
|---|
| 49 | reimplement the QWidget::resizeEvent() event handler to make sure | 
|---|
| 50 | that an application resizes smoothly and without data loss. | 
|---|
| 51 |  | 
|---|
| 52 | \image screenshot-example.png | 
|---|
| 53 |  | 
|---|
| 54 | With the application the users can take a screenshot of their | 
|---|
| 55 | desktop. They are provided with a couple of options: | 
|---|
| 56 |  | 
|---|
| 57 | \list | 
|---|
| 58 | \o Delaying the screenshot, giving them time to rearrange | 
|---|
| 59 | their desktop. | 
|---|
| 60 | \o Hiding the application's window while the screenshot is taken. | 
|---|
| 61 | \endlist | 
|---|
| 62 |  | 
|---|
| 63 | In addition the application allows the users to save their | 
|---|
| 64 | screenshot if they want to. | 
|---|
| 65 |  | 
|---|
| 66 | \section1 Screenshot Class Definition | 
|---|
| 67 |  | 
|---|
| 68 | \snippet examples/desktop/screenshot/screenshot.h 0 | 
|---|
| 69 |  | 
|---|
| 70 | The \c Screenshot class inherits QWidget and is the application's | 
|---|
| 71 | main widget. It displays the application options and a preview of | 
|---|
| 72 | the screenshot. | 
|---|
| 73 |  | 
|---|
| 74 | We reimplement the QWidget::resizeEvent() function to make sure | 
|---|
| 75 | that the preview of the screenshot scales properly when the user | 
|---|
| 76 | resizes the application widget. We also need several private slots | 
|---|
| 77 | to facilitate the options: | 
|---|
| 78 |  | 
|---|
| 79 | \list | 
|---|
| 80 | \o The \c newScreenshot() slot prepares a new screenshot. | 
|---|
| 81 | \o The \c saveScreenshot() slot saves the last screenshot. | 
|---|
| 82 | \o The \c shootScreen() slot takes the screenshot. | 
|---|
| 83 | \o The \c updateCheckBox() slot enables or disables the | 
|---|
| 84 | \gui {Hide This Window} option. | 
|---|
| 85 | \endlist | 
|---|
| 86 |  | 
|---|
| 87 | We also declare some private functions: We use the \c | 
|---|
| 88 | createOptionsGroupBox(), \c createButtonsLayout() and \c | 
|---|
| 89 | createButton() functions when we construct the widget. And we call | 
|---|
| 90 | the private \c updateScreenshotLabel() function whenever a new | 
|---|
| 91 | screenshot is taken or when a resize event changes the size of the | 
|---|
| 92 | screenshot preview label. | 
|---|
| 93 |  | 
|---|
| 94 | In addition we need to store the screenshot's original pixmap. The | 
|---|
| 95 | reason is that when we display the preview of the screenshot, we | 
|---|
| 96 | need to scale its pixmap, storing the original we make sure that | 
|---|
| 97 | no data are lost in that process. | 
|---|
| 98 |  | 
|---|
| 99 | \section1 Screenshot Class Implementation | 
|---|
| 100 |  | 
|---|
| 101 | \snippet examples/desktop/screenshot/screenshot.cpp 0 | 
|---|
| 102 |  | 
|---|
| 103 | In the constructor we first create the QLabel displaying the | 
|---|
| 104 | screenshot preview. | 
|---|
| 105 |  | 
|---|
| 106 | We set the QLabel's size policy to be QSizePolicy::Expanding both | 
|---|
| 107 | horizontally and vertically. This means that the QLabel's size | 
|---|
| 108 | hint is a sensible size, but the widget can be shrunk and still be | 
|---|
| 109 | useful. Also, the widget can make use of extra space, so it should | 
|---|
| 110 | get as much space as possible. Then we make sure the QLabel is | 
|---|
| 111 | aligned in the center of the \c Screenshot widget, and set its | 
|---|
| 112 | minimum size. | 
|---|
| 113 |  | 
|---|
| 114 | We create the applications's buttons and the group box containing | 
|---|
| 115 | the application's options, and put it all into a main | 
|---|
| 116 | layout. Finally we take the initial screenshot, and set the inital | 
|---|
| 117 | delay and the window title, before we resize the widget to a | 
|---|
| 118 | suitable size. | 
|---|
| 119 |  | 
|---|
| 120 | \snippet examples/desktop/screenshot/screenshot.cpp 1 | 
|---|
| 121 |  | 
|---|
| 122 | The \c resizeEvent() function is reimplemented to receive the | 
|---|
| 123 | resize events dispatched to the widget. The purpose is to scale | 
|---|
| 124 | the preview screenshot pixmap without deformation of its content, | 
|---|
| 125 | and also make sure that the application can be resized smoothly. | 
|---|
| 126 |  | 
|---|
| 127 | To achieve the first goal, we scale the screenshot pixmap using | 
|---|
| 128 | Qt::KeepAspectRatio. We scale the pixmap to a rectangle as large | 
|---|
| 129 | as possible inside the current size of the screenshot preview | 
|---|
| 130 | label, preserving the aspect ratio. This means that if the user | 
|---|
| 131 | resizes the application window in only one direction, the preview | 
|---|
| 132 | screenshot keeps the same size. | 
|---|
| 133 |  | 
|---|
| 134 | To reach our second goal, we make sure that the preview screenshot | 
|---|
| 135 | only is repainted (using the private \c updateScreenshotLabel() | 
|---|
| 136 | function) when it actually changes its size. | 
|---|
| 137 |  | 
|---|
| 138 | \snippet examples/desktop/screenshot/screenshot.cpp 2 | 
|---|
| 139 |  | 
|---|
| 140 | The private \c newScreenshot() slot is called when the user | 
|---|
| 141 | requests a new screenshot; but the slot only prepares a new | 
|---|
| 142 | screenshot. | 
|---|
| 143 |  | 
|---|
| 144 | First we see if the \gui {Hide This Window} option is checked, if | 
|---|
| 145 | it is we hide the \c Screenshot widget. Then we disable the \gui | 
|---|
| 146 | {New Screenshot} button, to make sure the user only can request | 
|---|
| 147 | one screenshot at a time. | 
|---|
| 148 |  | 
|---|
| 149 | We create a timer using the QTimer class which provides repetitive | 
|---|
| 150 | and single-shot timers. We set the timer to time out only once, | 
|---|
| 151 | using the static QTimer::singleShot() function. This function | 
|---|
| 152 | calls the private \c shootScreen() slot after the time interval | 
|---|
| 153 | specified by the \gui {Screenshot Delay} option. It is \c | 
|---|
| 154 | shootScreen() that actually performs the screenshot. | 
|---|
| 155 |  | 
|---|
| 156 | \snippet examples/desktop/screenshot/screenshot.cpp 3 | 
|---|
| 157 |  | 
|---|
| 158 | The \c saveScreenshot() slot is called when the user push the \gui | 
|---|
| 159 | Save button, and it presents a file dialog using the QFileDialog | 
|---|
| 160 | class. | 
|---|
| 161 |  | 
|---|
| 162 | QFileDialog enables a user to traverse the file system in order to | 
|---|
| 163 | select one or many files or a directory. The easiest way to create | 
|---|
| 164 | a QFileDialog is to use the convenience static | 
|---|
| 165 | functions. | 
|---|
| 166 |  | 
|---|
| 167 | We define the default file format to be png, and we make the file | 
|---|
| 168 | dialog's initial path the path the application is run from. We | 
|---|
| 169 | create the file dialog using the static | 
|---|
| 170 | QFileDialog::getSaveFileName() function which returns a file name | 
|---|
| 171 | selected by the user. The file does not have to exist. If the file | 
|---|
| 172 | name is valid, we use the QPixmap::save() function to save the | 
|---|
| 173 | screenshot's original pixmap in that file. | 
|---|
| 174 |  | 
|---|
| 175 | \snippet examples/desktop/screenshot/screenshot.cpp 4 | 
|---|
| 176 |  | 
|---|
| 177 | The \c shootScreen() slot is called to take the screenshot. If the | 
|---|
| 178 | user has chosen to delay the screenshot, we make the application | 
|---|
| 179 | beep when the screenshot is taken using the static | 
|---|
| 180 | QApplication::beep() function. | 
|---|
| 181 |  | 
|---|
| 182 | The QApplication class manages the GUI application's control flow | 
|---|
| 183 | and main settings. It contains the main event loop, where all | 
|---|
| 184 | events from the window system and other sources are processed and | 
|---|
| 185 | dispatched. | 
|---|
| 186 |  | 
|---|
| 187 | \snippet examples/desktop/screenshot/screenshot.cpp 5 | 
|---|
| 188 |  | 
|---|
| 189 | We take the screenshot using the static QPixmap::grabWindow() | 
|---|
| 190 | function. The function grabs the contents of the window passed as | 
|---|
| 191 | an argument, makes a pixmap out of it and returns that pixmap. | 
|---|
| 192 |  | 
|---|
| 193 | We identify the argument window using the QWidget::winID() | 
|---|
| 194 | function which returns the window system identifier. Here it | 
|---|
| 195 | returns the identifier of the current QDesktopWidget retrieved by | 
|---|
| 196 | the QApplication::desktop() function. The QDesktopWidget class | 
|---|
| 197 | provides access to screen information, and inherits | 
|---|
| 198 | QWidget::winID(). | 
|---|
| 199 |  | 
|---|
| 200 | We update the screenshot preview label using the private \c | 
|---|
| 201 | updateScreenshotLabel() function. Then we enable the \gui {New | 
|---|
| 202 | Screenshot} button, and finally we make the \c Screenshot widget | 
|---|
| 203 | visible if it was hidden during the screenshot. | 
|---|
| 204 |  | 
|---|
| 205 | \snippet examples/desktop/screenshot/screenshot.cpp 6 | 
|---|
| 206 |  | 
|---|
| 207 | The \gui {Hide This Window} option is enabled or disabled | 
|---|
| 208 | depending on the delay of the screenshot. If there is no delay, | 
|---|
| 209 | the application window cannot be hidden and the option's checkbox | 
|---|
| 210 | is disabled. | 
|---|
| 211 |  | 
|---|
| 212 | The \c updateCheckBox() slot is called whenever the user changes | 
|---|
| 213 | the delay using the \gui {Screenshot Delay} option. | 
|---|
| 214 |  | 
|---|
| 215 | \snippet examples/desktop/screenshot/screenshot.cpp 7 | 
|---|
| 216 |  | 
|---|
| 217 | The private \c createOptionsGroupBox() function is called from the | 
|---|
| 218 | constructor. | 
|---|
| 219 |  | 
|---|
| 220 | First we create a group box that will contain all of the options' | 
|---|
| 221 | widgets. Then we create a QSpinBox and a QLabel for the \gui | 
|---|
| 222 | {Screenshot Delay} option, and connect the spinbox to the \c | 
|---|
| 223 | updateCheckBox() slot. Finally, we create a QCheckBox for the \gui | 
|---|
| 224 | {Hide This Window} option, add all the options' widgets to a | 
|---|
| 225 | QGridLayout and install the layout on the group box. | 
|---|
| 226 |  | 
|---|
| 227 | Note that we don't have to specify any parents for the widgets | 
|---|
| 228 | when we create them. The reason is that when we add a widget to a | 
|---|
| 229 | layout and install the layout on another widget, the layout's | 
|---|
| 230 | widgets are automatically reparented to the widget the layout is | 
|---|
| 231 | installed on. | 
|---|
| 232 |  | 
|---|
| 233 | \snippet examples/desktop/screenshot/screenshot.cpp 8 | 
|---|
| 234 |  | 
|---|
| 235 | The private \c createButtonsLayout() function is called from the | 
|---|
| 236 | constructor. We create the application's buttons using the private | 
|---|
| 237 | \c createButton() function, and add them to a QHBoxLayout. | 
|---|
| 238 |  | 
|---|
| 239 | \snippet examples/desktop/screenshot/screenshot.cpp 9 | 
|---|
| 240 |  | 
|---|
| 241 | The private \c createButton() function is called from the \c | 
|---|
| 242 | createButtonsLayout() function. It simply creates a QPushButton | 
|---|
| 243 | with the provided text, connects it to the provided receiver and | 
|---|
| 244 | slot, and returns a pointer to the button. | 
|---|
| 245 |  | 
|---|
| 246 | \snippet examples/desktop/screenshot/screenshot.cpp 10 | 
|---|
| 247 |  | 
|---|
| 248 | The private \c updateScreenshotLabel() function is called whenever | 
|---|
| 249 | the screenshot changes, or when a resize event changes the size of | 
|---|
| 250 | the screenshot preview label. It updates the screenshot preview's | 
|---|
| 251 | label using the QLabel::setPixmap() and QPixmap::scaled() | 
|---|
| 252 | functions. | 
|---|
| 253 |  | 
|---|
| 254 | QPixmap::scaled() returns a copy of the given pixmap scaled to a | 
|---|
| 255 | rectangle of the given size according to the given | 
|---|
| 256 | Qt::AspectRatioMode and Qt::TransformationMode. | 
|---|
| 257 |  | 
|---|
| 258 | We scale the original pixmap to fit the current screenshot label's | 
|---|
| 259 | size, preserving the aspect ratio and giving the resulting pixmap | 
|---|
| 260 | smoothed edges. | 
|---|
| 261 | */ | 
|---|
| 262 |  | 
|---|