1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the examples of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:BSD$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** BSD License Usage |
18 | ** Alternatively, you may use this file under the terms of the BSD license |
19 | ** as follows: |
20 | ** |
21 | ** "Redistribution and use in source and binary forms, with or without |
22 | ** modification, are permitted provided that the following conditions are |
23 | ** met: |
24 | ** * Redistributions of source code must retain the above copyright |
25 | ** notice, this list of conditions and the following disclaimer. |
26 | ** * Redistributions in binary form must reproduce the above copyright |
27 | ** notice, this list of conditions and the following disclaimer in |
28 | ** the documentation and/or other materials provided with the |
29 | ** distribution. |
30 | ** * Neither the name of The Qt Company Ltd nor the names of its |
31 | ** contributors may be used to endorse or promote products derived |
32 | ** from this software without specific prior written permission. |
33 | ** |
34 | ** |
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
46 | ** |
47 | ** $QT_END_LICENSE$ |
48 | ** |
49 | ****************************************************************************/ |
50 | |
51 | #include "mainwindow.h" |
52 | #include "iconpreviewarea.h" |
53 | #include "iconsizespinbox.h" |
54 | #include "imagedelegate.h" |
55 | |
56 | #include <QApplication> |
57 | #include <QButtonGroup> |
58 | #include <QCheckBox> |
59 | #include <QFileDialog> |
60 | #include <QHeaderView> |
61 | #include <QFormLayout> |
62 | #include <QGridLayout> |
63 | #include <QGroupBox> |
64 | #include <QImageReader> |
65 | #include <QLabel> |
66 | #include <QMenuBar> |
67 | #include <QMessageBox> |
68 | #include <QRadioButton> |
69 | #include <QScreen> |
70 | #include <QStandardPaths> |
71 | #include <QStyleFactory> |
72 | #include <QTableWidget> |
73 | #include <QWindow> |
74 | |
75 | //! [40] |
76 | enum { OtherSize = QStyle::PM_CustomBase }; |
77 | //! [40] |
78 | |
79 | //! [0] |
80 | MainWindow::MainWindow(QWidget *parent) |
81 | : QMainWindow(parent) |
82 | { |
83 | QWidget *centralWidget = new QWidget(this); |
84 | setCentralWidget(centralWidget); |
85 | |
86 | createActions(); |
87 | |
88 | QGridLayout *mainLayout = new QGridLayout(centralWidget); |
89 | |
90 | QGroupBox *previewGroupBox = new QGroupBox(tr(s: "Preview" )); |
91 | previewArea = new IconPreviewArea(previewGroupBox); |
92 | QVBoxLayout *previewLayout = new QVBoxLayout(previewGroupBox); |
93 | previewLayout->addWidget(previewArea); |
94 | |
95 | mainLayout->addWidget(previewGroupBox, row: 0, column: 0, rowSpan: 1, columnSpan: 2); |
96 | mainLayout->addWidget(createImagesGroupBox(), row: 1, column: 0); |
97 | QVBoxLayout *vBox = new QVBoxLayout; |
98 | vBox->addWidget(createIconSizeGroupBox()); |
99 | vBox->addWidget(createHighDpiIconSizeGroupBox()); |
100 | vBox->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); |
101 | mainLayout->addLayout(vBox, row: 1, column: 1); |
102 | createContextMenu(); |
103 | |
104 | setWindowTitle(tr(s: "Icons" )); |
105 | checkCurrentStyle(); |
106 | sizeButtonGroup->button(id: OtherSize)->click(); |
107 | } |
108 | //! [0] |
109 | |
110 | //! [44] |
111 | void MainWindow::show() |
112 | { |
113 | QMainWindow::show(); |
114 | connect(sender: windowHandle(), signal: &QWindow::screenChanged, receiver: this, slot: &MainWindow::screenChanged); |
115 | screenChanged(); |
116 | } |
117 | //! [44] |
118 | |
119 | //! [1] |
120 | void MainWindow::about() |
121 | { |
122 | QMessageBox::about(parent: this, title: tr(s: "About Icons" ), |
123 | text: tr(s: "The <b>Icons</b> example illustrates how Qt renders an icon in " |
124 | "different modes (active, normal, disabled, and selected) and " |
125 | "states (on and off) based on a set of images." )); |
126 | } |
127 | //! [1] |
128 | |
129 | //! [2] |
130 | void MainWindow::changeStyle(bool checked) |
131 | { |
132 | if (!checked) |
133 | return; |
134 | |
135 | const QAction *action = qobject_cast<QAction *>(object: sender()); |
136 | //! [2] //! [3] |
137 | QStyle *style = QStyleFactory::create(action->data().toString()); |
138 | //! [3] //! [4] |
139 | Q_ASSERT(style); |
140 | QApplication::setStyle(style); |
141 | |
142 | const QList<QAbstractButton*> buttons = sizeButtonGroup->buttons(); |
143 | for (QAbstractButton *button : buttons) { |
144 | const QStyle::PixelMetric metric = static_cast<QStyle::PixelMetric>(sizeButtonGroup->id(button)); |
145 | const int value = style->pixelMetric(metric); |
146 | switch (metric) { |
147 | case QStyle::PM_SmallIconSize: |
148 | button->setText(tr(s: "Small (%1 x %1)" ).arg(a: value)); |
149 | break; |
150 | case QStyle::PM_LargeIconSize: |
151 | button->setText(tr(s: "Large (%1 x %1)" ).arg(a: value)); |
152 | break; |
153 | case QStyle::PM_ToolBarIconSize: |
154 | button->setText(tr(s: "Toolbars (%1 x %1)" ).arg(a: value)); |
155 | break; |
156 | case QStyle::PM_ListViewIconSize: |
157 | button->setText(tr(s: "List views (%1 x %1)" ).arg(a: value)); |
158 | break; |
159 | case QStyle::PM_IconViewIconSize: |
160 | button->setText(tr(s: "Icon views (%1 x %1)" ).arg(a: value)); |
161 | break; |
162 | case QStyle::PM_TabBarIconSize: |
163 | button->setText(tr(s: "Tab bars (%1 x %1)" ).arg(a: value)); |
164 | break; |
165 | default: |
166 | break; |
167 | } |
168 | } |
169 | |
170 | triggerChangeSize(); |
171 | } |
172 | //! [4] |
173 | |
174 | //! [5] |
175 | void MainWindow::changeSize(int id, bool checked) |
176 | { |
177 | if (!checked) |
178 | return; |
179 | |
180 | const bool other = id == int(OtherSize); |
181 | const int extent = other |
182 | ? otherSpinBox->value() |
183 | : QApplication::style()->pixelMetric(metric: static_cast<QStyle::PixelMetric>(id)); |
184 | |
185 | previewArea->setSize(QSize(extent, extent)); |
186 | otherSpinBox->setEnabled(other); |
187 | } |
188 | |
189 | void MainWindow::triggerChangeSize() |
190 | { |
191 | changeSize(id: sizeButtonGroup->checkedId(), checked: true); |
192 | } |
193 | //! [5] |
194 | |
195 | //! [6] |
196 | void MainWindow::changeIcon() |
197 | { |
198 | QIcon icon; |
199 | |
200 | for (int row = 0; row < imagesTable->rowCount(); ++row) { |
201 | const QTableWidgetItem *fileItem = imagesTable->item(row, column: 0); |
202 | const QTableWidgetItem *modeItem = imagesTable->item(row, column: 1); |
203 | const QTableWidgetItem *stateItem = imagesTable->item(row, column: 2); |
204 | |
205 | if (fileItem->checkState() == Qt::Checked) { |
206 | const int modeIndex = IconPreviewArea::iconModeNames().indexOf(t: modeItem->text()); |
207 | Q_ASSERT(modeIndex >= 0); |
208 | const int stateIndex = IconPreviewArea::iconStateNames().indexOf(t: stateItem->text()); |
209 | Q_ASSERT(stateIndex >= 0); |
210 | const QIcon::Mode mode = IconPreviewArea::iconModes().at(i: modeIndex); |
211 | const QIcon::State state = IconPreviewArea::iconStates().at(i: stateIndex); |
212 | //! [6] |
213 | |
214 | //! [8] |
215 | const QString fileName = fileItem->data(role: Qt::UserRole).toString(); |
216 | QImage image(fileName); |
217 | if (!image.isNull()) |
218 | icon.addPixmap(pixmap: QPixmap::fromImage(image), mode, state); |
219 | //! [8] |
220 | } |
221 | } |
222 | //! [11] |
223 | previewArea->setIcon(icon); |
224 | //! [11] |
225 | } |
226 | |
227 | void MainWindow::addSampleImages() |
228 | { |
229 | addImages(directory: QLatin1String(SRCDIR) + QLatin1String("/images" )); |
230 | } |
231 | |
232 | void MainWindow::addOtherImages() |
233 | { |
234 | static bool firstInvocation = true; |
235 | QString directory; |
236 | if (firstInvocation) { |
237 | firstInvocation = false; |
238 | directory = QStandardPaths::standardLocations(type: QStandardPaths::PicturesLocation).value(i: 0, defaultValue: QString()); |
239 | } |
240 | addImages(directory); |
241 | } |
242 | |
243 | //! [12] |
244 | void MainWindow::addImages(const QString &directory) |
245 | { |
246 | QFileDialog fileDialog(this, tr(s: "Open Images" ), directory); |
247 | QStringList mimeTypeFilters; |
248 | const QList<QByteArray> mimeTypes = QImageReader::supportedMimeTypes(); |
249 | for (const QByteArray &mimeTypeName : mimeTypes) |
250 | mimeTypeFilters.append(t: mimeTypeName); |
251 | mimeTypeFilters.sort(); |
252 | fileDialog.setMimeTypeFilters(mimeTypeFilters); |
253 | fileDialog.selectMimeTypeFilter(filter: QLatin1String("image/png" )); |
254 | fileDialog.setAcceptMode(QFileDialog::AcceptOpen); |
255 | fileDialog.setFileMode(QFileDialog::ExistingFiles); |
256 | if (!nativeFileDialogAct->isChecked()) |
257 | fileDialog.setOption(option: QFileDialog::DontUseNativeDialog); |
258 | if (fileDialog.exec() == QDialog::Accepted) |
259 | loadImages(fileNames: fileDialog.selectedFiles()); |
260 | //! [12] |
261 | } |
262 | |
263 | void MainWindow::loadImages(const QStringList &fileNames) |
264 | { |
265 | for (const QString &fileName : fileNames) { |
266 | const int row = imagesTable->rowCount(); |
267 | imagesTable->setRowCount(row + 1); |
268 | //! [13] |
269 | const QFileInfo fileInfo(fileName); |
270 | const QString imageName = fileInfo.baseName(); |
271 | const QString fileName2x = fileInfo.absolutePath() |
272 | + QLatin1Char('/') + imageName + QLatin1String("@2x." ) + fileInfo.suffix(); |
273 | const QFileInfo fileInfo2x(fileName2x); |
274 | const QImage image(fileName); |
275 | const QString toolTip = |
276 | tr(s: "Directory: %1\nFile: %2\nFile@2x: %3\nSize: %4x%5" ) |
277 | .arg(args: QDir::toNativeSeparators(pathName: fileInfo.absolutePath()), args: fileInfo.fileName()) |
278 | .arg(a: fileInfo2x.exists() ? fileInfo2x.fileName() : tr(s: "<None>" )) |
279 | .arg(a: image.width()).arg(a: image.height()); |
280 | QTableWidgetItem *fileItem = new QTableWidgetItem(imageName); |
281 | fileItem->setData(role: Qt::UserRole, value: fileName); |
282 | fileItem->setIcon(QPixmap::fromImage(image)); |
283 | fileItem->setFlags((fileItem->flags() | Qt::ItemIsUserCheckable) & ~Qt::ItemIsEditable); |
284 | fileItem->setToolTip(toolTip); |
285 | //! [13] |
286 | |
287 | //! [15] |
288 | QIcon::Mode mode = QIcon::Normal; |
289 | QIcon::State state = QIcon::Off; |
290 | if (guessModeStateAct->isChecked()) { |
291 | if (imageName.contains(s: QLatin1String("_act" ), cs: Qt::CaseInsensitive)) |
292 | mode = QIcon::Active; |
293 | else if (imageName.contains(s: QLatin1String("_dis" ), cs: Qt::CaseInsensitive)) |
294 | mode = QIcon::Disabled; |
295 | else if (imageName.contains(s: QLatin1String("_sel" ), cs: Qt::CaseInsensitive)) |
296 | mode = QIcon::Selected; |
297 | |
298 | if (imageName.contains(s: QLatin1String("_on" ), cs: Qt::CaseInsensitive)) |
299 | state = QIcon::On; |
300 | //! [15] |
301 | } |
302 | |
303 | //! [18] |
304 | imagesTable->setItem(row, column: 0, item: fileItem); |
305 | QTableWidgetItem *modeItem = |
306 | new QTableWidgetItem(IconPreviewArea::iconModeNames().at(i: IconPreviewArea::iconModes().indexOf(t: mode))); |
307 | modeItem->setToolTip(toolTip); |
308 | imagesTable->setItem(row, column: 1, item: modeItem); |
309 | QTableWidgetItem *stateItem = |
310 | new QTableWidgetItem(IconPreviewArea::iconStateNames().at(i: IconPreviewArea::iconStates().indexOf(t: state))); |
311 | stateItem->setToolTip(toolTip); |
312 | imagesTable->setItem(row, column: 2, item: stateItem); |
313 | imagesTable->openPersistentEditor(item: modeItem); |
314 | imagesTable->openPersistentEditor(item: stateItem); |
315 | |
316 | fileItem->setCheckState(Qt::Checked); |
317 | //! [18] |
318 | } |
319 | } |
320 | |
321 | void MainWindow::useHighDpiPixmapsChanged(int checkState) |
322 | { |
323 | QCoreApplication::setAttribute(attribute: Qt::AA_UseHighDpiPixmaps, on: checkState == Qt::Checked); |
324 | changeIcon(); |
325 | } |
326 | |
327 | //! [20] |
328 | void MainWindow::removeAllImages() |
329 | { |
330 | imagesTable->setRowCount(0); |
331 | changeIcon(); |
332 | } |
333 | //! [20] |
334 | |
335 | //! [21] |
336 | QWidget *MainWindow::createImagesGroupBox() |
337 | { |
338 | QGroupBox *imagesGroupBox = new QGroupBox(tr(s: "Images" )); |
339 | |
340 | imagesTable = new QTableWidget; |
341 | imagesTable->setSelectionMode(QAbstractItemView::NoSelection); |
342 | imagesTable->setItemDelegate(new ImageDelegate(this)); |
343 | //! [21] |
344 | |
345 | //! [22] |
346 | const QStringList labels({tr(s: "Image" ), tr(s: "Mode" ), tr(s: "State" )}); |
347 | |
348 | imagesTable->horizontalHeader()->setDefaultSectionSize(90); |
349 | imagesTable->setColumnCount(3); |
350 | imagesTable->setHorizontalHeaderLabels(labels); |
351 | imagesTable->horizontalHeader()->setSectionResizeMode(logicalIndex: 0, mode: QHeaderView::Stretch); |
352 | imagesTable->horizontalHeader()->setSectionResizeMode(logicalIndex: 1, mode: QHeaderView::Fixed); |
353 | imagesTable->horizontalHeader()->setSectionResizeMode(logicalIndex: 2, mode: QHeaderView::Fixed); |
354 | imagesTable->verticalHeader()->hide(); |
355 | //! [22] |
356 | |
357 | //! [24] |
358 | connect(sender: imagesTable, signal: &QTableWidget::itemChanged, |
359 | receiver: this, slot: &MainWindow::changeIcon); |
360 | |
361 | QVBoxLayout *layout = new QVBoxLayout(imagesGroupBox); |
362 | layout->addWidget(imagesTable); |
363 | return imagesGroupBox; |
364 | //! [24] |
365 | } |
366 | |
367 | //! [26] |
368 | QWidget *MainWindow::createIconSizeGroupBox() |
369 | { |
370 | QGroupBox *iconSizeGroupBox = new QGroupBox(tr(s: "Icon Size" )); |
371 | |
372 | sizeButtonGroup = new QButtonGroup(this); |
373 | sizeButtonGroup->setExclusive(true); |
374 | |
375 | connect(sender: sizeButtonGroup, signal: QOverload<int, bool>::of(ptr: &QButtonGroup::buttonToggled), |
376 | receiver: this, slot: &MainWindow::changeSize); |
377 | |
378 | QRadioButton *smallRadioButton = new QRadioButton; |
379 | sizeButtonGroup->addButton(smallRadioButton, id: QStyle::PM_SmallIconSize); |
380 | QRadioButton *largeRadioButton = new QRadioButton; |
381 | sizeButtonGroup->addButton(largeRadioButton, id: QStyle::PM_LargeIconSize); |
382 | QRadioButton *toolBarRadioButton = new QRadioButton; |
383 | sizeButtonGroup->addButton(toolBarRadioButton, id: QStyle::PM_ToolBarIconSize); |
384 | QRadioButton *listViewRadioButton = new QRadioButton; |
385 | sizeButtonGroup->addButton(listViewRadioButton, id: QStyle::PM_ListViewIconSize); |
386 | QRadioButton *iconViewRadioButton = new QRadioButton; |
387 | sizeButtonGroup->addButton(iconViewRadioButton, id: QStyle::PM_IconViewIconSize); |
388 | QRadioButton *tabBarRadioButton = new QRadioButton; |
389 | sizeButtonGroup->addButton(tabBarRadioButton, id: QStyle::PM_TabBarIconSize); |
390 | QRadioButton *otherRadioButton = new QRadioButton(tr(s: "Other:" )); |
391 | sizeButtonGroup->addButton(otherRadioButton, id: OtherSize); |
392 | otherSpinBox = new IconSizeSpinBox; |
393 | otherSpinBox->setRange(min: 8, max: 256); |
394 | const QString spinBoxToolTip = |
395 | tr(s: "Enter a custom size within %1..%2" ) |
396 | .arg(a: otherSpinBox->minimum()).arg(a: otherSpinBox->maximum()); |
397 | otherSpinBox->setValue(64); |
398 | otherSpinBox->setToolTip(spinBoxToolTip); |
399 | otherRadioButton->setToolTip(spinBoxToolTip); |
400 | //! [26] |
401 | |
402 | //! [27] |
403 | connect(sender: otherSpinBox, signal: QOverload<int>::of(ptr: &QSpinBox::valueChanged), |
404 | receiver: this, slot: &MainWindow::triggerChangeSize); |
405 | |
406 | QHBoxLayout *otherSizeLayout = new QHBoxLayout; |
407 | otherSizeLayout->addWidget(otherRadioButton); |
408 | otherSizeLayout->addWidget(otherSpinBox); |
409 | otherSizeLayout->addStretch(); |
410 | |
411 | QGridLayout *layout = new QGridLayout(iconSizeGroupBox); |
412 | layout->addWidget(smallRadioButton, row: 0, column: 0); |
413 | layout->addWidget(largeRadioButton, row: 1, column: 0); |
414 | layout->addWidget(toolBarRadioButton, row: 2, column: 0); |
415 | layout->addWidget(listViewRadioButton, row: 0, column: 1); |
416 | layout->addWidget(iconViewRadioButton, row: 1, column: 1); |
417 | layout->addWidget(tabBarRadioButton, row: 2, column: 1); |
418 | layout->addLayout(otherSizeLayout, row: 3, column: 0, rowSpan: 1, columnSpan: 2); |
419 | layout->setRowStretch(row: 4, stretch: 1); |
420 | return iconSizeGroupBox; |
421 | //! [27] |
422 | } |
423 | |
424 | void MainWindow::screenChanged() |
425 | { |
426 | devicePixelRatioLabel->setText(QString::number(devicePixelRatioF())); |
427 | if (const QWindow *window = windowHandle()) { |
428 | const QScreen *screen = window->screen(); |
429 | const QString screenDescription = |
430 | tr(s: "\"%1\" (%2x%3)" ).arg(a: screen->name()) |
431 | .arg(a: screen->geometry().width()).arg(a: screen->geometry().height()); |
432 | screenNameLabel->setText(screenDescription); |
433 | } |
434 | changeIcon(); |
435 | } |
436 | |
437 | QWidget *MainWindow::createHighDpiIconSizeGroupBox() |
438 | { |
439 | QGroupBox *highDpiGroupBox = new QGroupBox(tr(s: "High DPI Scaling" )); |
440 | QFormLayout *layout = new QFormLayout(highDpiGroupBox); |
441 | devicePixelRatioLabel = new QLabel(highDpiGroupBox); |
442 | screenNameLabel = new QLabel(highDpiGroupBox); |
443 | layout->addRow(labelText: tr(s: "Screen:" ), field: screenNameLabel); |
444 | layout->addRow(labelText: tr(s: "Device pixel ratio:" ), field: devicePixelRatioLabel); |
445 | QCheckBox *highDpiPixmapsCheckBox = new QCheckBox(QLatin1String("Qt::AA_UseHighDpiPixmaps" )); |
446 | highDpiPixmapsCheckBox->setChecked(QCoreApplication::testAttribute(attribute: Qt::AA_UseHighDpiPixmaps)); |
447 | connect(sender: highDpiPixmapsCheckBox, signal: &QCheckBox::stateChanged, receiver: this, slot: &MainWindow::useHighDpiPixmapsChanged); |
448 | layout->addRow(widget: highDpiPixmapsCheckBox); |
449 | return highDpiGroupBox; |
450 | } |
451 | |
452 | //! [28] |
453 | void MainWindow::createActions() |
454 | { |
455 | QMenu * = menuBar()->addMenu(title: tr(s: "&File" )); |
456 | |
457 | addSampleImagesAct = new QAction(tr(s: "Add &Sample Images..." ), this); |
458 | addSampleImagesAct->setShortcut(tr(s: "Ctrl+A" )); |
459 | connect(sender: addSampleImagesAct, signal: &QAction::triggered, receiver: this, slot: &MainWindow::addSampleImages); |
460 | fileMenu->addAction(action: addSampleImagesAct); |
461 | |
462 | addOtherImagesAct = new QAction(tr(s: "&Add Images..." ), this); |
463 | addOtherImagesAct->setShortcut(QKeySequence::Open); |
464 | connect(sender: addOtherImagesAct, signal: &QAction::triggered, receiver: this, slot: &MainWindow::addOtherImages); |
465 | fileMenu->addAction(action: addOtherImagesAct); |
466 | |
467 | removeAllImagesAct = new QAction(tr(s: "&Remove All Images" ), this); |
468 | removeAllImagesAct->setShortcut(tr(s: "Ctrl+R" )); |
469 | connect(sender: removeAllImagesAct, signal: &QAction::triggered, |
470 | receiver: this, slot: &MainWindow::removeAllImages); |
471 | fileMenu->addAction(action: removeAllImagesAct); |
472 | |
473 | fileMenu->addSeparator(); |
474 | |
475 | QAction *exitAct = fileMenu->addAction(text: tr(s: "&Quit" ), object: this, slot: &QWidget::close); |
476 | exitAct->setShortcuts(QKeySequence::Quit); |
477 | |
478 | QMenu * = menuBar()->addMenu(title: tr(s: "&View" )); |
479 | |
480 | styleActionGroup = new QActionGroup(this); |
481 | const QStringList styleKeys = QStyleFactory::keys(); |
482 | for (const QString &styleName : styleKeys) { |
483 | QAction *action = new QAction(tr(s: "%1 Style" ).arg(a: styleName), styleActionGroup); |
484 | action->setData(styleName); |
485 | action->setCheckable(true); |
486 | connect(sender: action, signal: &QAction::triggered, receiver: this, slot: &MainWindow::changeStyle); |
487 | viewMenu->addAction(action); |
488 | } |
489 | |
490 | QMenu * = menuBar()->addMenu(title: tr(s: "&Settings" )); |
491 | |
492 | guessModeStateAct = new QAction(tr(s: "&Guess Image Mode/State" ), this); |
493 | guessModeStateAct->setCheckable(true); |
494 | guessModeStateAct->setChecked(true); |
495 | settingsMenu->addAction(action: guessModeStateAct); |
496 | |
497 | nativeFileDialogAct = new QAction(tr(s: "&Use Native File Dialog" ), this); |
498 | nativeFileDialogAct->setCheckable(true); |
499 | nativeFileDialogAct->setChecked(true); |
500 | settingsMenu->addAction(action: nativeFileDialogAct); |
501 | |
502 | QMenu * = menuBar()->addMenu(title: tr(s: "&Help" )); |
503 | helpMenu->addAction(text: tr(s: "&About" ), object: this, slot: &MainWindow::about); |
504 | helpMenu->addAction(text: tr(s: "About &Qt" ), qApp, slot: &QApplication::aboutQt); |
505 | } |
506 | //! [28] |
507 | |
508 | //! [30] |
509 | void MainWindow::createContextMenu() |
510 | { |
511 | imagesTable->setContextMenuPolicy(Qt::ActionsContextMenu); |
512 | imagesTable->addAction(action: addSampleImagesAct); |
513 | imagesTable->addAction(action: addOtherImagesAct); |
514 | imagesTable->addAction(action: removeAllImagesAct); |
515 | } |
516 | //! [30] |
517 | |
518 | //! [31] |
519 | void MainWindow::checkCurrentStyle() |
520 | { |
521 | const QList<QAction *> actions = styleActionGroup->actions(); |
522 | for (QAction *action : actions) { |
523 | const QString styleName = action->data().toString(); |
524 | const std::unique_ptr<QStyle> candidate{QStyleFactory::create(styleName)}; |
525 | Q_ASSERT(candidate); |
526 | if (candidate->metaObject()->className() |
527 | == QApplication::style()->metaObject()->className()) { |
528 | action->trigger(); |
529 | return; |
530 | } |
531 | } |
532 | } |
533 | //! [31] |
534 | |