Icons Example▲
Sélectionnez
/**
**************************************************************************
**
** 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-&
gt;addWidget(previewArea);
mainLayout-&
gt;addWidget(previewGroupBox, 0
, 0
, 1
, 2
);
mainLayout-&
gt;addWidget(createImagesGroupBox(), 1
, 0
);
QVBoxLayout *
vBox =
new
QVBoxLayout;
vBox-&
gt;addWidget(createIconSizeGroupBox());
vBox-&
gt;addWidget(createHighDpiIconSizeGroupBox());
vBox-&
gt;addItem(new
QSpacerItem(0
, 0
, QSizePolicy::
Ignored, QSizePolicy::
MinimumExpanding));
mainLayout-&
gt;addLayout(vBox, 1
, 1
);
createContextMenu();
setWindowTitle(tr("Icons"
));
checkCurrentStyle();
sizeButtonGroup-&
gt;button(OtherSize)-&
gt;click();
}
void
MainWindow::
show()
{
QMainWindow::
show();
connect(windowHandle(), &
amp;QWindow::
screenChanged, this
, &
amp;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&
lt;QAction *&
gt;(sender());
QStyle *
style =
QStyleFactory::
create(action-&
gt;data().toString());
Q_ASSERT(style);
QApplication::
setStyle(style);
foreach (QAbstractButton *
button, sizeButtonGroup-&
gt;buttons()) {
const
QStyle::
PixelMetric metric =
static_cast
&
lt;QStyle::
PixelMetric&
gt;(sizeButtonGroup-&
gt;id(button));
const
int
value =
style-&
gt;pixelMetric(metric);
switch
(metric) {
case
QStyle::
PM_SmallIconSize:
button-&
gt;setText(tr("Small (%1 x %1)"
).arg(value));
break
;
case
QStyle::
PM_LargeIconSize:
button-&
gt;setText(tr("Large (%1 x %1)"
).arg(value));
break
;
case
QStyle::
PM_ToolBarIconSize:
button-&
gt;setText(tr("Toolbars (%1 x %1)"
).arg(value));
break
;
case
QStyle::
PM_ListViewIconSize:
button-&
gt;setText(tr("List views (%1 x %1)"
).arg(value));
break
;
case
QStyle::
PM_IconViewIconSize:
button-&
gt;setText(tr("Icon views (%1 x %1)"
).arg(value));
break
;
case
QStyle::
PM_TabBarIconSize:
button-&
gt;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-&
gt;value()
:
QApplication::
style()-&
gt;pixelMetric(static_cast
&
lt;QStyle::
PixelMetric&
gt;(id));
previewArea-&
gt;setSize(QSize(extent, extent));
otherSpinBox-&
gt;setEnabled(other);
}
void
MainWindow::
triggerChangeSize()
{
changeSize(sizeButtonGroup-&
gt;checkedId(), true
);
}
void
MainWindow::
changeIcon()
{
QIcon icon;
for
(int
row =
0
; row &
lt; imagesTable-&
gt;rowCount(); ++
row) {
const
QTableWidgetItem *
fileItem =
imagesTable-&
gt;item(row, 0
);
const
QTableWidgetItem *
modeItem =
imagesTable-&
gt;item(row, 1
);
const
QTableWidgetItem *
stateItem =
imagesTable-&
gt;item(row, 2
);
if
(fileItem-&
gt;checkState() ==
Qt::
Checked) {
const
int
modeIndex =
IconPreviewArea::
iconModeNames().indexOf(modeItem-&
gt;text());
Q_ASSERT(modeIndex &
gt;=
0
);
const
int
stateIndex =
IconPreviewArea::
iconStateNames().indexOf(stateItem-&
gt;text());
Q_ASSERT(stateIndex &
gt;=
0
);
const
QIcon::
Mode mode =
IconPreviewArea::
iconModes().at(modeIndex);
const
QIcon::
State state =
IconPreviewArea::
iconStates().at(stateIndex);
const
QString fileName =
fileItem-&
gt;data(Qt::
UserRole).toString();
QImage image(fileName);
if
(!
image.isNull())
icon.addPixmap(QPixmap::
fromImage(image), mode, state);
}
}
previewArea-&
gt;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 &
amp;directory)
{
QFileDialog fileDialog(this
, tr("Open Images"
), directory);
QStringList mimeTypeFilters;
foreach (const
QByteArray &
amp;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-&
gt;isChecked())
fileDialog.setOption(QFileDialog::
DontUseNativeDialog);
if
(fileDialog.exec() ==
QDialog::
Accepted)
loadImages(fileDialog.selectedFiles());
}
void
MainWindow::
loadImages(const
QStringList &
amp;fileNames)
{
foreach (const
QString &
amp;fileName, fileNames) {
const
int
row =
imagesTable-&
gt;rowCount();
imagesTable-&
gt;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
\n
File: %2
\n
File@2x: %3
\n
Size: %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-&
gt;setData(Qt::
UserRole, fileName);
fileItem-&
gt;setIcon(QPixmap::
fromImage(image));
fileItem-&
gt;setFlags((fileItem-&
gt;flags() |
Qt::
ItemIsUserCheckable) &
amp; ~
Qt::
ItemIsEditable);
fileItem-&
gt;setToolTip(toolTip);
QIcon::
Mode mode =
QIcon::
Normal;
QIcon::
State state =
QIcon::
Off;
if
(guessModeStateAct-&
gt;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-&
gt;setItem(row, 0
, fileItem);
QTableWidgetItem *
modeItem =
new
QTableWidgetItem(IconPreviewArea::
iconModeNames().at(IconPreviewArea::
iconModes().indexOf(mode)));
modeItem-&
gt;setToolTip(toolTip);
imagesTable-&
gt;setItem(row, 1
, modeItem);
QTableWidgetItem *
stateItem =
new
QTableWidgetItem(IconPreviewArea::
iconStateNames().at(IconPreviewArea::
iconStates().indexOf(state)));
stateItem-&
gt;setToolTip(toolTip);
imagesTable-&
gt;setItem(row, 2
, stateItem);
imagesTable-&
gt;openPersistentEditor(modeItem);
imagesTable-&
gt;openPersistentEditor(stateItem);
fileItem-&
gt;setCheckState(Qt::
Checked);
}
}
void
MainWindow::
useHighDpiPixmapsChanged(int
checkState)
{
QCoreApplication::
setAttribute(Qt::
AA_UseHighDpiPixmaps, checkState ==
Qt::
Checked);
changeIcon();
}
void
MainWindow::
removeAllImages()
{
imagesTable-&
gt;setRowCount(0
);
changeIcon();
}
QWidget *
MainWindow::
createImagesGroupBox()
{
QGroupBox *
imagesGroupBox =
new
QGroupBox(tr("Images"
));
imagesTable =
new
QTableWidget;
imagesTable-&
gt;setSelectionMode(QAbstractItemView::
NoSelection);
imagesTable-&
gt;setItemDelegate(new
ImageDelegate(this
));
QStringList labels;
labels &
lt;&
lt; tr("Image"
) &
lt;&
lt; tr("Mode"
) &
lt;&
lt; tr("State"
);
imagesTable-&
gt;horizontalHeader()-&
gt;setDefaultSectionSize(90
);
imagesTable-&
gt;setColumnCount(3
);
imagesTable-&
gt;setHorizontalHeaderLabels(labels);
imagesTable-&
gt;horizontalHeader()-&
gt;setSectionResizeMode(0
, QHeaderView::
Stretch);
imagesTable-&
gt;horizontalHeader()-&
gt;setSectionResizeMode(1
, QHeaderView::
Fixed);
imagesTable-&
gt;horizontalHeader()-&
gt;setSectionResizeMode(2
, QHeaderView::
Fixed);
imagesTable-&
gt;verticalHeader()-&
gt;hide();
connect(imagesTable, &
amp;QTableWidget::
itemChanged,
this
, &
amp;MainWindow::
changeIcon);
QVBoxLayout *
layout =
new
QVBoxLayout(imagesGroupBox);
layout-&
gt;addWidget(imagesTable);
return
imagesGroupBox;
}
QWidget *
MainWindow::
createIconSizeGroupBox()
{
QGroupBox *
iconSizeGroupBox =
new
QGroupBox(tr("Icon Size"
));
sizeButtonGroup =
new
QButtonGroup(this
);
sizeButtonGroup-&
gt;setExclusive(true
);
connect(sizeButtonGroup, QOverload&
lt;int
, bool
&
gt;::
of(&
amp;QButtonGroup::
buttonToggled),
this
, &
amp;MainWindow::
changeSize);
QRadioButton *
smallRadioButton =
new
QRadioButton;
sizeButtonGroup-&
gt;addButton(smallRadioButton, QStyle::
PM_SmallIconSize);
QRadioButton *
largeRadioButton =
new
QRadioButton;
sizeButtonGroup-&
gt;addButton(largeRadioButton, QStyle::
PM_LargeIconSize);
QRadioButton *
toolBarRadioButton =
new
QRadioButton;
sizeButtonGroup-&
gt;addButton(toolBarRadioButton, QStyle::
PM_ToolBarIconSize);
QRadioButton *
listViewRadioButton =
new
QRadioButton;
sizeButtonGroup-&
gt;addButton(listViewRadioButton, QStyle::
PM_ListViewIconSize);
QRadioButton *
iconViewRadioButton =
new
QRadioButton;
sizeButtonGroup-&
gt;addButton(iconViewRadioButton, QStyle::
PM_IconViewIconSize);
QRadioButton *
tabBarRadioButton =
new
QRadioButton;
sizeButtonGroup-&
gt;addButton(tabBarRadioButton, QStyle::
PM_TabBarIconSize);
QRadioButton *
otherRadioButton =
new
QRadioButton(tr("Other:"
));
sizeButtonGroup-&
gt;addButton(otherRadioButton, OtherSize);
otherSpinBox =
new
IconSizeSpinBox;
otherSpinBox-&
gt;setRange(8
, 256
);
const
QString spinBoxToolTip =
tr("Enter a custom size within %1..%2"
)
.arg(otherSpinBox-&
gt;minimum()).arg(otherSpinBox-&
gt;maximum());
otherSpinBox-&
gt;setValue(64
);
otherSpinBox-&
gt;setToolTip(spinBoxToolTip);
otherRadioButton-&
gt;setToolTip(spinBoxToolTip);
connect(otherSpinBox, QOverload&
lt;int
&
gt;::
of(&
amp;QSpinBox::
valueChanged),
this
, &
amp;MainWindow::
triggerChangeSize);
QHBoxLayout *
otherSizeLayout =
new
QHBoxLayout;
otherSizeLayout-&
gt;addWidget(otherRadioButton);
otherSizeLayout-&
gt;addWidget(otherSpinBox);
otherSizeLayout-&
gt;addStretch();
QGridLayout *
layout =
new
QGridLayout(iconSizeGroupBox);
layout-&
gt;addWidget(smallRadioButton, 0
, 0
);
layout-&
gt;addWidget(largeRadioButton, 1
, 0
);
layout-&
gt;addWidget(toolBarRadioButton, 2
, 0
);
layout-&
gt;addWidget(listViewRadioButton, 0
, 1
);
layout-&
gt;addWidget(iconViewRadioButton, 1
, 1
);
layout-&
gt;addWidget(tabBarRadioButton, 2
, 1
);
layout-&
gt;addLayout(otherSizeLayout, 3
, 0
, 1
, 2
);
layout-&
gt;setRowStretch(4
, 1
);
return
iconSizeGroupBox;
}
void
MainWindow::
screenChanged()
{
devicePixelRatioLabel-&
gt;setText(QString::
number(devicePixelRatioF()));
if
(const
QWindow *
window =
windowHandle()) {
const
QScreen *
screen =
window-&
gt;screen();
const
QString screenDescription =
tr("
\"
%1
\"
(%2x%3)"
).arg(screen-&
gt;name())
.arg(screen-&
gt;geometry().width()).arg(screen-&
gt;geometry().height());
screenNameLabel-&
gt;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-&
gt;addRow(tr("Screen:"
), screenNameLabel);
layout-&
gt;addRow(tr("Device pixel ratio:"
), devicePixelRatioLabel);
QCheckBox *
highDpiPixmapsCheckBox =
new
QCheckBox(QLatin1String("Qt::AA_UseHighDpiPixmaps"
));
highDpiPixmapsCheckBox-&
gt;setChecked(QCoreApplication::
testAttribute(Qt::
AA_UseHighDpiPixmaps));
connect(highDpiPixmapsCheckBox, &
amp;QCheckBox::
stateChanged, this
, &
amp;MainWindow::
useHighDpiPixmapsChanged);
layout-&
gt;addRow(highDpiPixmapsCheckBox);
return
highDpiGroupBox;
}
void
MainWindow::
createActions()
{
QMenu *
fileMenu =
menuBar()-&
gt;addMenu(tr("&File"
));
addSampleImagesAct =
new
QAction(tr("Add &Sample Images..."
), this
);
addSampleImagesAct-&
gt;setShortcut(tr("Ctrl+A"
));
connect(addSampleImagesAct, &
amp;QAction::
triggered, this
, &
amp;MainWindow::
addSampleImages);
fileMenu-&
gt;addAction(addSampleImagesAct);
addOtherImagesAct =
new
QAction(tr("&Add Images..."
), this
);
addOtherImagesAct-&
gt;setShortcut(QKeySequence::
Open);
connect(addOtherImagesAct, &
amp;QAction::
triggered, this
, &
amp;MainWindow::
addOtherImages);
fileMenu-&
gt;addAction(addOtherImagesAct);
removeAllImagesAct =
new
QAction(tr("&Remove All Images"
), this
);
removeAllImagesAct-&
gt;setShortcut(tr("Ctrl+R"
));
connect(removeAllImagesAct, &
amp;QAction::
triggered,
this
, &
amp;MainWindow::
removeAllImages);
fileMenu-&
gt;addAction(removeAllImagesAct);
fileMenu-&
gt;addSeparator();
QAction *
exitAct =
fileMenu-&
gt;addAction(tr("&Quit"
), this
, &
amp;QWidget::
close);
exitAct-&
gt;setShortcuts(QKeySequence::
Quit);
QMenu *
viewMenu =
menuBar()-&
gt;addMenu(tr("&View"
));
styleActionGroup =
new
QActionGroup(this
);
foreach (const
QString &
amp;styleName, QStyleFactory::
keys()) {
QAction *
action =
new
QAction(tr("%1 Style"
).arg(styleName), styleActionGroup);
action-&
gt;setData(styleName);
action-&
gt;setCheckable(true
);
connect(action, &
amp;QAction::
triggered, this
, &
amp;MainWindow::
changeStyle);
viewMenu-&
gt;addAction(action);
}
QMenu *
settingsMenu =
menuBar()-&
gt;addMenu(tr("&Settings"
));
guessModeStateAct =
new
QAction(tr("&Guess Image Mode/State"
), this
);
guessModeStateAct-&
gt;setCheckable(true
);
guessModeStateAct-&
gt;setChecked(true
);
settingsMenu-&
gt;addAction(guessModeStateAct);
nativeFileDialogAct =
new
QAction(tr("&Use Native File Dialog"
), this
);
nativeFileDialogAct-&
gt;setCheckable(true
);
nativeFileDialogAct-&
gt;setChecked(true
);
settingsMenu-&
gt;addAction(nativeFileDialogAct);
QMenu *
helpMenu =
menuBar()-&
gt;addMenu(tr("&Help"
));
helpMenu-&
gt;addAction(tr("&About"
), this
, &
amp;MainWindow::
about);
helpMenu-&
gt;addAction(tr("About &Qt"
), qApp, &
amp;QApplication::
aboutQt);
}
void
MainWindow::
createContextMenu()
{
imagesTable-&
gt;setContextMenuPolicy(Qt::
ActionsContextMenu);
imagesTable-&
gt;addAction(addSampleImagesAct);
imagesTable-&
gt;addAction(addOtherImagesAct);
imagesTable-&
gt;addAction(removeAllImagesAct);
}
void
MainWindow::
checkCurrentStyle()
{
foreach (QAction *
action, styleActionGroup-&
gt;actions()) {
QString styleName =
action-&
gt;data().toString();
QScopedPointer&
lt;QStyle&
gt; candidate(QStyleFactory::
create(styleName));
Q_ASSERT(!
candidate.isNull());
if
(candidate-&
gt;metaObject()-&
gt;className()
==
QApplication::
style()-&
gt;metaObject()-&
gt;className()) {
action-&
gt;trigger();
return
;
}
}
}