mainwindow.cpp Example File
widgets/icons/mainwindow.cpp
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtWidgets>
#include "iconpreviewarea.h"
#include "iconsizespinbox.h"
#include "imagedelegate.h"
#include "mainwindow.h"
enum { OtherSize = QStyle :: PM_CustomBase };
MainWindow:: MainWindow()
{
QWidget * centralWidget = new QWidget (this );
setCentralWidget(centralWidget);
createActions();
QGridLayout * mainLayout = new QGridLayout (centralWidget);
QGroupBox * previewGroupBox = new QGroupBox (tr("Preview" ));
previewArea = new IconPreviewArea(previewGroupBox);
QVBoxLayout * previewLayout = new QVBoxLayout (previewGroupBox);
previewLayout- > addWidget(previewArea);
mainLayout- > addWidget(previewGroupBox, 0 , 0 , 1 , 2 );
mainLayout- > addWidget(createImagesGroupBox(), 1 , 0 );
QVBoxLayout * vBox = new QVBoxLayout ;
vBox- > addWidget(createIconSizeGroupBox());
vBox- > addWidget(createHighDpiIconSizeGroupBox());
vBox- > addItem(new QSpacerItem (0 , 0 , QSizePolicy :: Ignored, QSizePolicy :: MinimumExpanding));
mainLayout- > addLayout(vBox, 1 , 1 );
createContextMenu();
setWindowTitle(tr("Icons" ));
checkCurrentStyle();
sizeButtonGroup- > button(OtherSize)- > click();
}
void MainWindow:: show()
{
QMainWindow :: show();
connect(windowHandle(), & QWindow :: screenChanged, this , & MainWindow:: screenChanged);
screenChanged();
}
void MainWindow:: about()
{
QMessageBox :: about(this , tr("About Icons" ),
tr("The <b>Icons</b> example illustrates how Qt renders an icon in "
"different modes (active, normal, disabled, and selected) and "
"states (on and off) based on a set of images." ));
}
void MainWindow:: changeStyle(bool checked)
{
if (! checked)
return ;
const QAction * action = qobject_cast< QAction * > (sender());
QStyle * style = QStyleFactory :: create(action- > data(). toString());
Q_ASSERT(style);
QApplication :: setStyle(style);
foreach (QAbstractButton * button, sizeButtonGroup- > buttons()) {
const QStyle :: PixelMetric metric = static_cast < QStyle :: PixelMetric> (sizeButtonGroup- > id(button));
const int value = style- > pixelMetric(metric);
switch (metric) {
case QStyle :: PM_SmallIconSize:
button- > setText(tr("Small (%1 x %1)" ). arg(value));
break ;
case QStyle :: PM_LargeIconSize:
button- > setText(tr("Large (%1 x %1)" ). arg(value));
break ;
case QStyle :: PM_ToolBarIconSize:
button- > setText(tr("Toolbars (%1 x %1)" ). arg(value));
break ;
case QStyle :: PM_ListViewIconSize:
button- > setText(tr("List views (%1 x %1)" ). arg(value));
break ;
case QStyle :: PM_IconViewIconSize:
button- > setText(tr("Icon views (%1 x %1)" ). arg(value));
break ;
case QStyle :: PM_TabBarIconSize:
button- > setText(tr("Tab bars (%1 x %1)" ). arg(value));
break ;
default :
break ;
}
}
triggerChangeSize();
}
void MainWindow:: changeSize(int id, bool checked)
{
if (! checked)
return ;
const bool other = id = = int (OtherSize);
const int extent = other
? otherSpinBox- > value()
: QApplication :: style()- > pixelMetric(static_cast < QStyle :: PixelMetric> (id));
previewArea- > setSize(QSize (extent, extent));
otherSpinBox- > setEnabled(other);
}
void MainWindow:: triggerChangeSize()
{
changeSize(sizeButtonGroup- > checkedId(), true );
}
void MainWindow:: changeIcon()
{
QIcon icon;
for (int row = 0 ; row < imagesTable- > rowCount(); + + row) {
const QTableWidgetItem * fileItem = imagesTable- > item(row, 0 );
const QTableWidgetItem * modeItem = imagesTable- > item(row, 1 );
const QTableWidgetItem * stateItem = imagesTable- > item(row, 2 );
if (fileItem- > checkState() = = Qt :: Checked) {
const int modeIndex = IconPreviewArea:: iconModeNames(). indexOf(modeItem- > text());
Q_ASSERT(modeIndex > = 0 );
const int stateIndex = IconPreviewArea:: iconStateNames(). indexOf(stateItem- > text());
Q_ASSERT(stateIndex > = 0 );
const QIcon :: Mode mode = IconPreviewArea:: iconModes(). at(modeIndex);
const QIcon :: State state = IconPreviewArea:: iconStates(). at(stateIndex);
const QString fileName = fileItem- > data(Qt :: UserRole). toString();
QImage image(fileName);
if (! image. isNull())
icon. addPixmap(QPixmap :: fromImage(image), mode, state);
}
}
previewArea- > setIcon(icon);
}
void MainWindow:: addSampleImages()
{
addImages(QLatin1String(SRCDIR) + QLatin1String("/images" ));
}
void MainWindow:: addOtherImages()
{
static bool firstInvocation = true ;
QString directory;
if (firstInvocation) {
firstInvocation = false ;
directory = QStandardPaths :: standardLocations(QStandardPaths :: PicturesLocation). value(0 , QString ());
}
addImages(directory);
}
void MainWindow:: addImages(const QString & directory)
{
QFileDialog fileDialog(this , tr("Open Images" ), directory);
QStringList mimeTypeFilters;
foreach (const QByteArray & mimeTypeName, QImageReader :: supportedMimeTypes())
mimeTypeFilters. append(mimeTypeName);
mimeTypeFilters. sort();
fileDialog. setMimeTypeFilters(mimeTypeFilters);
fileDialog. selectMimeTypeFilter(QLatin1String("image/png" ));
fileDialog. setAcceptMode(QFileDialog :: AcceptOpen);
fileDialog. setFileMode(QFileDialog :: ExistingFiles);
if (! nativeFileDialogAct- > isChecked())
fileDialog. setOption(QFileDialog :: DontUseNativeDialog);
if (fileDialog. exec() = = QDialog :: Accepted)
loadImages(fileDialog. selectedFiles());
}
void MainWindow:: loadImages(const QStringList & fileNames)
{
foreach (const QString & fileName, fileNames) {
const int row = imagesTable- > rowCount();
imagesTable- > setRowCount(row + 1 );
const QFileInfo fileInfo(fileName);
const QString imageName = fileInfo. baseName();
const QString fileName2x = fileInfo. absolutePath()
+ QLatin1Char('/' ) + imageName + QLatin1String("@2x." ) + fileInfo. suffix();
const QFileInfo fileInfo2x(fileName2x);
const QImage image(fileName);
const QString toolTip =
tr("Directory: %1\nFile: %2\nFile@2x: %3\nSize: %4x%5" )
. arg(QDir :: toNativeSeparators(fileInfo. absolutePath()), fileInfo. fileName())
. arg(fileInfo2x. exists() ? fileInfo2x. fileName() : tr("<None>" ))
. arg(image. width()). arg(image. height());
QTableWidgetItem * fileItem = new QTableWidgetItem (imageName);
fileItem- > setData(Qt :: UserRole, fileName);
fileItem- > setIcon(QPixmap :: fromImage(image));
fileItem- > setFlags((fileItem- > flags() | Qt :: ItemIsUserCheckable) & ~ Qt :: ItemIsEditable);
fileItem- > setToolTip(toolTip);
QIcon :: Mode mode = QIcon :: Normal;
QIcon :: State state = QIcon :: Off;
if (guessModeStateAct- > isChecked()) {
if (imageName. contains(QLatin1String("_act" ), Qt :: CaseInsensitive))
mode = QIcon :: Active;
else if (imageName. contains(QLatin1String("_dis" ), Qt :: CaseInsensitive))
mode = QIcon :: Disabled;
else if (imageName. contains(QLatin1String("_sel" ), Qt :: CaseInsensitive))
mode = QIcon :: Selected;
if (imageName. contains(QLatin1String("_on" ), Qt :: CaseInsensitive))
state = QIcon :: On;
}
imagesTable- > setItem(row, 0 , fileItem);
QTableWidgetItem * modeItem =
new QTableWidgetItem (IconPreviewArea:: iconModeNames(). at(IconPreviewArea:: iconModes(). indexOf(mode)));
modeItem- > setToolTip(toolTip);
imagesTable- > setItem(row, 1 , modeItem);
QTableWidgetItem * stateItem =
new QTableWidgetItem (IconPreviewArea:: iconStateNames(). at(IconPreviewArea:: iconStates(). indexOf(state)));
stateItem- > setToolTip(toolTip);
imagesTable- > setItem(row, 2 , stateItem);
imagesTable- > openPersistentEditor(modeItem);
imagesTable- > openPersistentEditor(stateItem);
fileItem- > setCheckState(Qt :: Checked);
}
}
void MainWindow:: useHighDpiPixmapsChanged(int checkState)
{
QCoreApplication :: setAttribute(Qt :: AA_UseHighDpiPixmaps, checkState = = Qt :: Checked);
changeIcon();
}
void MainWindow:: removeAllImages()
{
imagesTable- > setRowCount(0 );
changeIcon();
}
QWidget * MainWindow:: createImagesGroupBox()
{
QGroupBox * imagesGroupBox = new QGroupBox (tr("Images" ));
imagesTable = new QTableWidget ;
imagesTable- > setSelectionMode(QAbstractItemView :: NoSelection);
imagesTable- > setItemDelegate(new ImageDelegate(this ));
QStringList labels;
labels < < tr("Image" ) < < tr("Mode" ) < < tr("State" );
imagesTable- > horizontalHeader()- > setDefaultSectionSize(90 );
imagesTable- > setColumnCount(3 );
imagesTable- > setHorizontalHeaderLabels(labels);
imagesTable- > horizontalHeader()- > setSectionResizeMode(0 , QHeaderView :: Stretch);
imagesTable- > horizontalHeader()- > setSectionResizeMode(1 , QHeaderView :: Fixed);
imagesTable- > horizontalHeader()- > setSectionResizeMode(2 , QHeaderView :: Fixed);
imagesTable- > verticalHeader()- > hide();
connect(imagesTable, & QTableWidget :: itemChanged,
this , & MainWindow:: changeIcon);
QVBoxLayout * layout = new QVBoxLayout (imagesGroupBox);
layout- > addWidget(imagesTable);
return imagesGroupBox;
}
QWidget * MainWindow:: createIconSizeGroupBox()
{
QGroupBox * iconSizeGroupBox = new QGroupBox (tr("Icon Size" ));
sizeButtonGroup = new QButtonGroup (this );
sizeButtonGroup- > setExclusive(true );
connect(sizeButtonGroup, QOverload < int , bool> :: of(& QButtonGroup :: buttonToggled),
this , & MainWindow:: changeSize);
QRadioButton * smallRadioButton = new QRadioButton ;
sizeButtonGroup- > addButton(smallRadioButton, QStyle :: PM_SmallIconSize);
QRadioButton * largeRadioButton = new QRadioButton ;
sizeButtonGroup- > addButton(largeRadioButton, QStyle :: PM_LargeIconSize);
QRadioButton * toolBarRadioButton = new QRadioButton ;
sizeButtonGroup- > addButton(toolBarRadioButton, QStyle :: PM_ToolBarIconSize);
QRadioButton * listViewRadioButton = new QRadioButton ;
sizeButtonGroup- > addButton(listViewRadioButton, QStyle :: PM_ListViewIconSize);
QRadioButton * iconViewRadioButton = new QRadioButton ;
sizeButtonGroup- > addButton(iconViewRadioButton, QStyle :: PM_IconViewIconSize);
QRadioButton * tabBarRadioButton = new QRadioButton ;
sizeButtonGroup- > addButton(tabBarRadioButton, QStyle :: PM_TabBarIconSize);
QRadioButton * otherRadioButton = new QRadioButton (tr("Other:" ));
sizeButtonGroup- > addButton(otherRadioButton, OtherSize);
otherSpinBox = new IconSizeSpinBox;
otherSpinBox- > setRange(8 , 256 );
const QString spinBoxToolTip =
tr("Enter a custom size within %1..%2" )
. arg(otherSpinBox- > minimum()). arg(otherSpinBox- > maximum());
otherSpinBox- > setValue(64 );
otherSpinBox- > setToolTip(spinBoxToolTip);
otherRadioButton- > setToolTip(spinBoxToolTip);
connect(otherSpinBox, QOverload < int > :: of(& QSpinBox :: valueChanged),
this , & MainWindow:: triggerChangeSize);
QHBoxLayout * otherSizeLayout = new QHBoxLayout ;
otherSizeLayout- > addWidget(otherRadioButton);
otherSizeLayout- > addWidget(otherSpinBox);
otherSizeLayout- > addStretch();
QGridLayout * layout = new QGridLayout (iconSizeGroupBox);
layout- > addWidget(smallRadioButton, 0 , 0 );
layout- > addWidget(largeRadioButton, 1 , 0 );
layout- > addWidget(toolBarRadioButton, 2 , 0 );
layout- > addWidget(listViewRadioButton, 0 , 1 );
layout- > addWidget(iconViewRadioButton, 1 , 1 );
layout- > addWidget(tabBarRadioButton, 2 , 1 );
layout- > addLayout(otherSizeLayout, 3 , 0 , 1 , 2 );
layout- > setRowStretch(4 , 1 );
return iconSizeGroupBox;
}
void MainWindow:: screenChanged()
{
devicePixelRatioLabel- > setText(QString :: number(devicePixelRatioF()));
if (const QWindow * window = windowHandle()) {
const QScreen * screen = window- > screen();
const QString screenDescription =
tr("\"%1\" (%2x%3)" ). arg(screen- > name())
. arg(screen- > geometry(). width()). arg(screen- > geometry(). height());
screenNameLabel- > setText(screenDescription);
}
changeIcon();
}
QWidget * MainWindow:: createHighDpiIconSizeGroupBox()
{
QGroupBox * highDpiGroupBox = new QGroupBox (tr("High DPI Scaling" ));
QFormLayout * layout = new QFormLayout (highDpiGroupBox);
devicePixelRatioLabel = new QLabel (highDpiGroupBox);
screenNameLabel = new QLabel (highDpiGroupBox);
layout- > addRow(tr("Screen:" ), screenNameLabel);
layout- > addRow(tr("Device pixel ratio:" ), devicePixelRatioLabel);
QCheckBox * highDpiPixmapsCheckBox = new QCheckBox (QLatin1String("Qt::AA_UseHighDpiPixmaps" ));
highDpiPixmapsCheckBox- > setChecked(QCoreApplication :: testAttribute(Qt :: AA_UseHighDpiPixmaps));
connect(highDpiPixmapsCheckBox, & QCheckBox :: stateChanged, this , & MainWindow:: useHighDpiPixmapsChanged);
layout- > addRow(highDpiPixmapsCheckBox);
return highDpiGroupBox;
}
void MainWindow:: createActions()
{
QMenu * fileMenu = menuBar()- > addMenu(tr("&File" ));
addSampleImagesAct = new QAction (tr("Add &Sample Images..." ), this );
addSampleImagesAct- > setShortcut(tr("Ctrl+A" ));
connect(addSampleImagesAct, & QAction :: triggered, this , & MainWindow:: addSampleImages);
fileMenu- > addAction(addSampleImagesAct);
addOtherImagesAct = new QAction (tr("&Add Images..." ), this );
addOtherImagesAct- > setShortcut(QKeySequence :: Open);
connect(addOtherImagesAct, & QAction :: triggered, this , & MainWindow:: addOtherImages);
fileMenu- > addAction(addOtherImagesAct);
removeAllImagesAct = new QAction (tr("&Remove All Images" ), this );
removeAllImagesAct- > setShortcut(tr("Ctrl+R" ));
connect(removeAllImagesAct, & QAction :: triggered,
this , & MainWindow:: removeAllImages);
fileMenu- > addAction(removeAllImagesAct);
fileMenu- > addSeparator();
QAction * exitAct = fileMenu- > addAction(tr("&Quit" ), this , & QWidget :: close);
exitAct- > setShortcuts(QKeySequence :: Quit);
QMenu * viewMenu = menuBar()- > addMenu(tr("&View" ));
styleActionGroup = new QActionGroup (this );
foreach (const QString & styleName, QStyleFactory :: keys()) {
QAction * action = new QAction (tr("%1 Style" ). arg(styleName), styleActionGroup);
action- > setData(styleName);
action- > setCheckable(true );
connect(action, & QAction :: triggered, this , & MainWindow:: changeStyle);
viewMenu- > addAction(action);
}
QMenu * settingsMenu = menuBar()- > addMenu(tr("&Settings" ));
guessModeStateAct = new QAction (tr("&Guess Image Mode/State" ), this );
guessModeStateAct- > setCheckable(true );
guessModeStateAct- > setChecked(true );
settingsMenu- > addAction(guessModeStateAct);
nativeFileDialogAct = new QAction (tr("&Use Native File Dialog" ), this );
nativeFileDialogAct- > setCheckable(true );
nativeFileDialogAct- > setChecked(true );
settingsMenu- > addAction(nativeFileDialogAct);
QMenu * helpMenu = menuBar()- > addMenu(tr("&Help" ));
helpMenu- > addAction(tr("&About" ), this , & MainWindow:: about);
helpMenu- > addAction(tr("About &Qt" ), qApp, & QApplication :: aboutQt);
}
void MainWindow:: createContextMenu()
{
imagesTable- > setContextMenuPolicy(Qt :: ActionsContextMenu);
imagesTable- > addAction(addSampleImagesAct);
imagesTable- > addAction(addOtherImagesAct);
imagesTable- > addAction(removeAllImagesAct);
}
void MainWindow:: checkCurrentStyle()
{
foreach (QAction * action, styleActionGroup- > actions()) {
QString styleName = action- > data(). toString();
QScopedPointer < QStyle > candidate(QStyleFactory :: create(styleName));
Q_ASSERT(! candidate. isNull());
if (candidate- > metaObject()- > className()
= = QApplication :: style()- > metaObject()- > className()) {
action- > trigger();
return ;
}
}
}