diff options
Diffstat (limited to 'examples/widgets/widgets')
26 files changed, 733 insertions, 435 deletions
diff --git a/examples/widgets/widgets/calculator/calculator.cpp b/examples/widgets/widgets/calculator/calculator.cpp index e76011ee0d..87061a9868 100644 --- a/examples/widgets/widgets/calculator/calculator.cpp +++ b/examples/widgets/widgets/calculator/calculator.cpp @@ -276,7 +276,7 @@ void Calculator::pointClicked() { if (waitingForOperand) display->setText("0"); - if (!display->text().contains(".")) + if (!display->text().contains('.')) display->setText(display->text() + tr(".")); waitingForOperand = false; } diff --git a/examples/widgets/widgets/icons/iconpreviewarea.cpp b/examples/widgets/widgets/icons/iconpreviewarea.cpp index 0736261a02..090615e64d 100644 --- a/examples/widgets/widgets/icons/iconpreviewarea.cpp +++ b/examples/widgets/widgets/icons/iconpreviewarea.cpp @@ -46,33 +46,95 @@ IconPreviewArea::IconPreviewArea(QWidget *parent) : QWidget(parent) { - QGridLayout *mainLayout = new QGridLayout; - setLayout(mainLayout); + QGridLayout *mainLayout = new QGridLayout(this); - stateLabels[0] = createHeaderLabel(tr("Off")); - stateLabels[1] = createHeaderLabel(tr("On")); + for (int row = 0; row < NumStates; ++row) { + stateLabels[row] = createHeaderLabel(IconPreviewArea::iconStateNames().at(row)); + mainLayout->addWidget(stateLabels[row], row + 1, 0); + } Q_ASSERT(NumStates == 2); - modeLabels[0] = createHeaderLabel(tr("Normal")); - modeLabels[1] = createHeaderLabel(tr("Active")); - modeLabels[2] = createHeaderLabel(tr("Disabled")); - modeLabels[3] = createHeaderLabel(tr("Selected")); + for (int column = 0; column < NumModes; ++column) { + modeLabels[column] = createHeaderLabel(IconPreviewArea::iconModeNames().at(column)); + mainLayout->addWidget(modeLabels[column], 0, column + 1); + } Q_ASSERT(NumModes == 4); - for (int j = 0; j < NumStates; ++j) - mainLayout->addWidget(stateLabels[j], j + 1, 0); - - for (int i = 0; i < NumModes; ++i) { - mainLayout->addWidget(modeLabels[i], 0, i + 1); - - for (int j = 0; j < NumStates; ++j) { - pixmapLabels[i][j] = createPixmapLabel(); - mainLayout->addWidget(pixmapLabels[i][j], j + 1, i + 1); + for (int column = 0; column < NumModes; ++column) { + for (int row = 0; row < NumStates; ++row) { + pixmapLabels[column][row] = createPixmapLabel(); + mainLayout->addWidget(pixmapLabels[column][row], row + 1, column + 1); } } } //! [0] +#ifdef Q_COMPILER_INITIALIZER_LISTS + +//! [42] +QVector<QIcon::Mode> IconPreviewArea::iconModes() +{ + static const QVector<QIcon::Mode> result = {QIcon::Normal, QIcon::Active, QIcon::Disabled, QIcon::Selected}; + return result; +} + +QVector<QIcon::State> IconPreviewArea::iconStates() +{ + static const QVector<QIcon::State> result = {QIcon::Off, QIcon::On}; + return result; +} + +QStringList IconPreviewArea::iconModeNames() +{ + static const QStringList result = {tr("Normal"), tr("Active"), tr("Disabled"), tr("Selected")}; + return result; +} + +QStringList IconPreviewArea::iconStateNames() +{ + static const QStringList result = {tr("Off"), tr("On")}; + return result; +} +//! [42] + +#else // Q_COMPILER_INITIALIZER_LISTS + +//! [43] +QVector<QIcon::Mode> IconPreviewArea::iconModes() +{ + static QVector<QIcon::Mode> result; + if (result.isEmpty()) + result << QIcon::Normal << QIcon::Active << QIcon::Disabled << QIcon::Selected; + return result; +} +//! [43] + +QVector<QIcon::State> IconPreviewArea::iconStates() +{ + static QVector<QIcon::State> result; + if (result.isEmpty()) + result << QIcon::Off << QIcon::On; + return result; +} + +QStringList IconPreviewArea::iconModeNames() +{ + static QStringList result; + if (result.isEmpty()) + result << tr("Normal") << tr("Active") << tr("Disabled") << tr("Selected"); + return result; +} + +QStringList IconPreviewArea::iconStateNames() +{ + static QStringList result; + if (result.isEmpty()) + result << tr("Off") << tr("On"); + return result; +} + +#endif // !Q_COMPILER_INITIALIZER_LISTS + //! [1] void IconPreviewArea::setIcon(const QIcon &icon) { @@ -118,23 +180,27 @@ QLabel *IconPreviewArea::createPixmapLabel() //! [5] void IconPreviewArea::updatePixmapLabels() { - for (int i = 0; i < NumModes; ++i) { - QIcon::Mode mode; - if (i == 0) { - mode = QIcon::Normal; - } else if (i == 1) { - mode = QIcon::Active; - } else if (i == 2) { - mode = QIcon::Disabled; - } else { - mode = QIcon::Selected; - } - - for (int j = 0; j < NumStates; ++j) { - QIcon::State state = (j == 0) ? QIcon::Off : QIcon::On; - QPixmap pixmap = icon.pixmap(size, mode, state); - pixmapLabels[i][j]->setPixmap(pixmap); - pixmapLabels[i][j]->setEnabled(!pixmap.isNull()); + QWindow *window = Q_NULLPTR; + if (const QWidget *nativeParent = nativeParentWidget()) + window = nativeParent->windowHandle(); + for (int column = 0; column < NumModes; ++column) { + for (int row = 0; row < NumStates; ++row) { + const QPixmap pixmap = + icon.pixmap(window, size, IconPreviewArea::iconModes().at(column), + IconPreviewArea::iconStates().at(row)); + QLabel *pixmapLabel = pixmapLabels[column][row]; + pixmapLabel->setPixmap(pixmap); + pixmapLabel->setEnabled(!pixmap.isNull()); + QString toolTip; + if (!pixmap.isNull()) { + const QSize actualSize = icon.actualSize(size); + toolTip = + tr("Size: %1x%2\nActual size: %3x%4\nDevice pixel ratio: %5") + .arg(size.width()).arg(size.height()) + .arg(actualSize.width()).arg(actualSize.height()) + .arg(pixmap.devicePixelRatioF()); + } + pixmapLabel->setToolTip(toolTip); } } } diff --git a/examples/widgets/widgets/icons/iconpreviewarea.h b/examples/widgets/widgets/icons/iconpreviewarea.h index c2e0a7b79d..693f8811d8 100644 --- a/examples/widgets/widgets/icons/iconpreviewarea.h +++ b/examples/widgets/widgets/icons/iconpreviewarea.h @@ -43,6 +43,8 @@ #include <QIcon> #include <QWidget> +#include <QStringList> +#include <QVector> QT_BEGIN_NAMESPACE class QLabel; @@ -54,11 +56,16 @@ class IconPreviewArea : public QWidget Q_OBJECT public: - IconPreviewArea(QWidget *parent = 0); + explicit IconPreviewArea(QWidget *parent = Q_NULLPTR); void setIcon(const QIcon &icon); void setSize(const QSize &size); + static QVector<QIcon::Mode> iconModes(); + static QVector<QIcon::State> iconStates(); + static QStringList iconModeNames(); + static QStringList iconStateNames(); + private: QLabel *createHeaderLabel(const QString &text); QLabel *createPixmapLabel(); diff --git a/examples/widgets/widgets/icons/icons.pro b/examples/widgets/widgets/icons/icons.pro index 21165163aa..4ee95592c8 100644 --- a/examples/widgets/widgets/icons/icons.pro +++ b/examples/widgets/widgets/icons/icons.pro @@ -10,6 +10,8 @@ SOURCES = iconpreviewarea.cpp \ main.cpp \ mainwindow.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" + EXAMPLE_FILES = images/* # install @@ -24,5 +26,5 @@ wince { } else { imageFiles.path = images } - DEPLOYMENT += imageFiles + INSTALLS += imageFiles } diff --git a/examples/widgets/widgets/icons/iconsizespinbox.cpp b/examples/widgets/widgets/icons/iconsizespinbox.cpp index f3796040b3..1916803eea 100644 --- a/examples/widgets/widgets/icons/iconsizespinbox.cpp +++ b/examples/widgets/widgets/icons/iconsizespinbox.cpp @@ -52,13 +52,13 @@ IconSizeSpinBox::IconSizeSpinBox(QWidget *parent) //! [1] int IconSizeSpinBox::valueFromText(const QString &text) const { - QRegExp regExp(tr("(\\d+)(\\s*[xx]\\s*\\d+)?")); + static const QRegularExpression regExp(tr("(\\d+)(\\s*[xx]\\s*\\d+)?")); + Q_ASSERT(regExp.isValid()); - if (regExp.exactMatch(text)) { - return regExp.cap(1).toInt(); - } else { - return 0; - } + const QRegularExpressionMatch match = regExp.match(text); + if (match.isValid()) + return match.captured(1).toInt(); + return 0; } //! [1] diff --git a/examples/widgets/widgets/icons/iconsizespinbox.h b/examples/widgets/widgets/icons/iconsizespinbox.h index 08105c771c..96b277de39 100644 --- a/examples/widgets/widgets/icons/iconsizespinbox.h +++ b/examples/widgets/widgets/icons/iconsizespinbox.h @@ -49,7 +49,7 @@ class IconSizeSpinBox : public QSpinBox Q_OBJECT public: - IconSizeSpinBox(QWidget *parent = 0); + explicit IconSizeSpinBox(QWidget *parent = Q_NULLPTR); int valueFromText(const QString &text) const Q_DECL_OVERRIDE; QString textFromValue(int value) const Q_DECL_OVERRIDE; diff --git a/examples/widgets/widgets/icons/imagedelegate.cpp b/examples/widgets/widgets/icons/imagedelegate.cpp index a6df8f3b04..7c393594ca 100644 --- a/examples/widgets/widgets/icons/imagedelegate.cpp +++ b/examples/widgets/widgets/icons/imagedelegate.cpp @@ -41,6 +41,7 @@ #include <QtWidgets> #include "imagedelegate.h" +#include "iconpreviewarea.h" //! [0] ImageDelegate::ImageDelegate(QObject *parent) @@ -55,17 +56,14 @@ QWidget *ImageDelegate::createEditor(QWidget *parent, const QModelIndex &index) const { QComboBox *comboBox = new QComboBox(parent); - if (index.column() == 1) { - comboBox->addItem(tr("Normal")); - comboBox->addItem(tr("Active")); - comboBox->addItem(tr("Disabled")); - comboBox->addItem(tr("Selected")); - } else if (index.column() == 2) { - comboBox->addItem(tr("Off")); - comboBox->addItem(tr("On")); - } + if (index.column() == 1) + comboBox->addItems(IconPreviewArea::iconModeNames()); + else if (index.column() == 2) + comboBox->addItems(IconPreviewArea::iconStateNames()); - connect(comboBox, SIGNAL(activated(int)), this, SLOT(emitCommitData())); + typedef void (QComboBox::*QComboBoxIntSignal)(int); + connect(comboBox, static_cast<QComboBoxIntSignal>(&QComboBox::activated), + this, &ImageDelegate::emitCommitData); return comboBox; } diff --git a/examples/widgets/widgets/icons/imagedelegate.h b/examples/widgets/widgets/icons/imagedelegate.h index a828251013..ed1d8210d5 100644 --- a/examples/widgets/widgets/icons/imagedelegate.h +++ b/examples/widgets/widgets/icons/imagedelegate.h @@ -49,7 +49,7 @@ class ImageDelegate : public QItemDelegate Q_OBJECT public: - ImageDelegate(QObject *parent = 0); + explicit ImageDelegate(QObject *parent = Q_NULLPTR); //! [0] //! [1] diff --git a/examples/widgets/widgets/icons/main.cpp b/examples/widgets/widgets/icons/main.cpp index 842a474405..d6a823f1c7 100644 --- a/examples/widgets/widgets/icons/main.cpp +++ b/examples/widgets/widgets/icons/main.cpp @@ -39,13 +39,39 @@ ****************************************************************************/ #include <QApplication> +#include <QCommandLineParser> +#include <QDesktopWidget> #include "mainwindow.h" +//! [45] int main(int argc, char *argv[]) { QApplication app(argc, argv); + QCoreApplication::setApplicationName(MainWindow::tr("Icons")); + QCoreApplication::setApplicationVersion(QT_VERSION_STR); + QCommandLineParser commandLineParser; + commandLineParser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); + commandLineParser.addHelpOption(); + commandLineParser.addVersionOption(); + QCommandLineOption noHighDpiPixmapOption("no-highdpi-pixmaps", + "Disable High DPI image loading (Qt::AA_UseHighDpiPixmaps)"); + commandLineParser.addOption(noHighDpiPixmapOption); + commandLineParser.addPositionalArgument(MainWindow::tr("[file]"), MainWindow::tr("Icon file(s) to open.")); + commandLineParser.process(QCoreApplication::arguments()); + + if (!commandLineParser.isSet(noHighDpiPixmapOption)) + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + MainWindow mainWin; + if (!commandLineParser.positionalArguments().isEmpty()) + mainWin.loadImages(commandLineParser.positionalArguments()); + + const QRect availableGeometry = QApplication::desktop()->availableGeometry(&mainWin); + mainWin.resize(availableGeometry.width() / 2, availableGeometry.height() * 2 / 3); + mainWin.move((availableGeometry.width() - mainWin.width()) / 2, (availableGeometry.height() - mainWin.height()) / 2); + mainWin.show(); return app.exec(); } +//! [45] diff --git a/examples/widgets/widgets/icons/mainwindow.cpp b/examples/widgets/widgets/icons/mainwindow.cpp index 86d18cd62a..4c76b0ee16 100644 --- a/examples/widgets/widgets/icons/mainwindow.cpp +++ b/examples/widgets/widgets/icons/mainwindow.cpp @@ -45,34 +45,49 @@ #include "imagedelegate.h" #include "mainwindow.h" +//! [40] +enum { OtherSize = QStyle::PM_CustomBase }; +//! [40] + //! [0] MainWindow::MainWindow() { - centralWidget = new QWidget; + QWidget *centralWidget = new QWidget(this); setCentralWidget(centralWidget); - createPreviewGroupBox(); - createImagesGroupBox(); - createIconSizeGroupBox(); - createActions(); - createMenus(); - createContextMenu(); - QGridLayout *mainLayout = new QGridLayout; + 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(imagesGroupBox, 1, 0); - mainLayout->addWidget(iconSizeGroupBox, 1, 1); - centralWidget->setLayout(mainLayout); + 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(); - otherRadioButton->click(); - - resize(minimumSizeHint()); + sizeButtonGroup->button(OtherSize)->click(); } //! [0] +//! [44] +void MainWindow::show() +{ + QMainWindow::show(); + connect(windowHandle(), &QWindow::screenChanged, this, &MainWindow::screenChanged); + screenChanged(); +} +//! [44] + //! [1] void MainWindow::about() { @@ -89,60 +104,62 @@ void MainWindow::changeStyle(bool checked) if (!checked) return; - QAction *action = qobject_cast<QAction *>(sender()); + const QAction *action = qobject_cast<QAction *>(sender()); //! [2] //! [3] QStyle *style = QStyleFactory::create(action->data().toString()); //! [3] //! [4] Q_ASSERT(style); QApplication::setStyle(style); - smallRadioButton->setText(tr("Small (%1 x %1)") - .arg(style->pixelMetric(QStyle::PM_SmallIconSize))); - largeRadioButton->setText(tr("Large (%1 x %1)") - .arg(style->pixelMetric(QStyle::PM_LargeIconSize))); - toolBarRadioButton->setText(tr("Toolbars (%1 x %1)") - .arg(style->pixelMetric(QStyle::PM_ToolBarIconSize))); - listViewRadioButton->setText(tr("List views (%1 x %1)") - .arg(style->pixelMetric(QStyle::PM_ListViewIconSize))); - iconViewRadioButton->setText(tr("Icon views (%1 x %1)") - .arg(style->pixelMetric(QStyle::PM_IconViewIconSize))); - tabBarRadioButton->setText(tr("Tab bars (%1 x %1)") - .arg(style->pixelMetric(QStyle::PM_TabBarIconSize))); - - changeSize(); + 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(); } //! [4] //! [5] -void MainWindow::changeSize(bool checked) +void MainWindow::changeSize(int id, bool checked) { if (!checked) return; - int extent; - - if (otherRadioButton->isChecked()) { - extent = otherSpinBox->value(); - } else { - QStyle::PixelMetric metric; - - if (smallRadioButton->isChecked()) { - metric = QStyle::PM_SmallIconSize; - } else if (largeRadioButton->isChecked()) { - metric = QStyle::PM_LargeIconSize; - } else if (toolBarRadioButton->isChecked()) { - metric = QStyle::PM_ToolBarIconSize; - } else if (listViewRadioButton->isChecked()) { - metric = QStyle::PM_ListViewIconSize; - } else if (iconViewRadioButton->isChecked()) { - metric = QStyle::PM_IconViewIconSize; - } else { - metric = QStyle::PM_TabBarIconSize; - } - extent = QApplication::style()->pixelMetric(metric); - } + 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(otherRadioButton->isChecked()); + otherSpinBox->setEnabled(other); +} + +void MainWindow::triggerChangeSize() +{ + changeSize(sizeButtonGroup->checkedId(), true); } //! [5] @@ -152,33 +169,21 @@ void MainWindow::changeIcon() QIcon icon; for (int row = 0; row < imagesTable->rowCount(); ++row) { - QTableWidgetItem *item0 = imagesTable->item(row, 0); - QTableWidgetItem *item1 = imagesTable->item(row, 1); - QTableWidgetItem *item2 = imagesTable->item(row, 2); - - if (item0->checkState() == Qt::Checked) { - QIcon::Mode mode; - if (item1->text() == tr("Normal")) { - mode = QIcon::Normal; - } else if (item1->text() == tr("Active")) { - mode = QIcon::Active; - } else if (item1->text() == tr("Disabled")) { - mode = QIcon::Disabled; - } else { - mode = QIcon::Selected; - } - - QIcon::State state; - if (item2->text() == tr("On")) { - state = QIcon::On; - } else { - state = QIcon::Off; -//! [6] //! [7] - } -//! [7] + 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); +//! [6] //! [8] - QString fileName = item0->data(Qt::UserRole).toString(); + const QString fileName = fileItem->data(Qt::UserRole).toString(); QImage image(fileName); if (!image.isNull()) icon.addPixmap(QPixmap::fromImage(image), mode, state); @@ -193,61 +198,109 @@ void MainWindow::changeIcon() } //! [11] +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); +} + //! [12] -void MainWindow::addImages() +void MainWindow::addImages(const QString &directory) { - QStringList fileNames = QFileDialog::getOpenFileNames(this, - tr("Open Images"), "", - tr("Images (*.png *.xpm *.jpg);;" - "All Files (*)")); - if (!fileNames.isEmpty()) { - foreach (QString fileName, fileNames) { - int row = imagesTable->rowCount(); - imagesTable->setRowCount(row + 1); + 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()); //! [12] +} +void MainWindow::loadImages(const QStringList &fileNames) +{ + foreach (const QString &fileName, fileNames) { + const int row = imagesTable->rowCount(); + imagesTable->setRowCount(row + 1); //! [13] - QString imageName = QFileInfo(fileName).baseName(); + 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()); //! [13] //! [14] - QTableWidgetItem *item0 = new QTableWidgetItem(imageName); - item0->setData(Qt::UserRole, fileName); - item0->setFlags(item0->flags() & ~Qt::ItemIsEditable); + 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); //! [14] //! [15] - QTableWidgetItem *item1 = new QTableWidgetItem(tr("Normal")); + QIcon::Mode mode = QIcon::Normal; //! [15] //! [16] - QTableWidgetItem *item2 = new QTableWidgetItem(tr("Off")); - - if (guessModeStateAct->isChecked()) { - if (fileName.contains("_act")) { - item1->setText(tr("Active")); - } else if (fileName.contains("_dis")) { - item1->setText(tr("Disabled")); - } else if (fileName.contains("_sel")) { - item1->setText(tr("Selected")); - } - - if (fileName.contains("_on")) - item2->setText(tr("On")); + 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; //! [16] //! [17] - } + } //! [17] //! [18] - imagesTable->setItem(row, 0, item0); + imagesTable->setItem(row, 0, fileItem); //! [18] //! [19] - imagesTable->setItem(row, 1, item1); - imagesTable->setItem(row, 2, item2); - imagesTable->openPersistentEditor(item1); - imagesTable->openPersistentEditor(item2); - - item0->setCheckState(Qt::Checked); - } + 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); } } //! [19] +void MainWindow::useHighDpiPixmapsChanged(int checkState) +{ + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, checkState == Qt::Checked); + changeIcon(); +} + //! [20] void MainWindow::removeAllImages() { @@ -256,21 +309,10 @@ void MainWindow::removeAllImages() } //! [20] -void MainWindow::createPreviewGroupBox() -{ - previewGroupBox = new QGroupBox(tr("Preview")); - - previewArea = new IconPreviewArea; - - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(previewArea); - previewGroupBox->setLayout(layout); -} - //! [21] -void MainWindow::createImagesGroupBox() +QWidget *MainWindow::createImagesGroupBox() { - imagesGroupBox = new QGroupBox(tr("Images")); + QGroupBox *imagesGroupBox = new QGroupBox(tr("Images")); imagesTable = new QTableWidget; imagesTable->setSelectionMode(QAbstractItemView::NoSelection); @@ -292,57 +334,63 @@ void MainWindow::createImagesGroupBox() //! [23] //! [24] - connect(imagesTable, SIGNAL(itemChanged(QTableWidgetItem*)), + connect(imagesTable, &QTableWidget::itemChanged, //! [24] //! [25] - this, SLOT(changeIcon())); + this, &MainWindow::changeIcon); - QVBoxLayout *layout = new QVBoxLayout; + QVBoxLayout *layout = new QVBoxLayout(imagesGroupBox); layout->addWidget(imagesTable); - imagesGroupBox->setLayout(layout); + return imagesGroupBox; } //! [25] //! [26] -void MainWindow::createIconSizeGroupBox() +QWidget *MainWindow::createIconSizeGroupBox() { - iconSizeGroupBox = new QGroupBox(tr("Icon Size")); - - smallRadioButton = new QRadioButton; - largeRadioButton = new QRadioButton; - toolBarRadioButton = new QRadioButton; - listViewRadioButton = new QRadioButton; - iconViewRadioButton = new QRadioButton; - tabBarRadioButton = new QRadioButton; - otherRadioButton = new QRadioButton(tr("Other:")); - + QGroupBox *iconSizeGroupBox = new QGroupBox(tr("Icon Size")); + + sizeButtonGroup = new QButtonGroup(this); + sizeButtonGroup->setExclusive(true); + + typedef void (QButtonGroup::*QButtonGroupIntBoolSignal)(int, bool); + connect(sizeButtonGroup, static_cast<QButtonGroupIntBoolSignal>(&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, 128); + 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); //! [26] //! [27] - connect(smallRadioButton, SIGNAL(toggled(bool)), - this, SLOT(changeSize(bool))); - connect(largeRadioButton, SIGNAL(toggled(bool)), - this, SLOT(changeSize(bool))); - connect(toolBarRadioButton, SIGNAL(toggled(bool)), - this, SLOT(changeSize(bool))); - connect(listViewRadioButton, SIGNAL(toggled(bool)), - this, SLOT(changeSize(bool))); - connect(iconViewRadioButton, SIGNAL(toggled(bool)), - this, SLOT(changeSize(bool))); - connect(tabBarRadioButton, SIGNAL(toggled(bool)), - this, SLOT(changeSize(bool))); - connect(otherRadioButton, SIGNAL(toggled(bool)), - this, SLOT(changeSize(bool))); - connect(otherSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeSize())); + typedef void (QSpinBox::*QSpinBoxIntSignal)(int); + connect(otherSpinBox, static_cast<QSpinBoxIntSignal>(&QSpinBox::valueChanged), + this, &MainWindow::triggerChangeSize); QHBoxLayout *otherSizeLayout = new QHBoxLayout; otherSizeLayout->addWidget(otherRadioButton); otherSizeLayout->addWidget(otherSpinBox); otherSizeLayout->addStretch(); - QGridLayout *layout = new QGridLayout; + QGridLayout *layout = new QGridLayout(iconSizeGroupBox); layout->addWidget(smallRadioButton, 0, 0); layout->addWidget(largeRadioButton, 1, 0); layout->addWidget(toolBarRadioButton, 2, 0); @@ -351,75 +399,99 @@ void MainWindow::createIconSizeGroupBox() layout->addWidget(tabBarRadioButton, 2, 1); layout->addLayout(otherSizeLayout, 3, 0, 1, 2); layout->setRowStretch(4, 1); - iconSizeGroupBox->setLayout(layout); + return iconSizeGroupBox; } //! [27] +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; +} + //! [28] void MainWindow::createActions() { - addImagesAct = new QAction(tr("&Add Images..."), this); - addImagesAct->setShortcut(tr("Ctrl+A")); - connect(addImagesAct, SIGNAL(triggered()), this, SLOT(addImages())); + 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, SIGNAL(triggered()), - this, SLOT(removeAllImages())); + connect(removeAllImagesAct, &QAction::triggered, + this, &MainWindow::removeAllImages); + fileMenu->addAction(removeAllImagesAct); - exitAct = new QAction(tr("&Quit"), this); + fileMenu->addSeparator(); + + QAction *exitAct = fileMenu->addAction(tr("&Quit"), this, &QWidget::close); exitAct->setShortcuts(QKeySequence::Quit); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); + + QMenu *viewMenu = menuBar()->addMenu(tr("&View")); styleActionGroup = new QActionGroup(this); - foreach (QString styleName, QStyleFactory::keys()) { - QAction *action = new QAction(styleActionGroup); - action->setText(tr("%1 Style").arg(styleName)); + foreach (const QString &styleName, QStyleFactory::keys()) { + QAction *action = new QAction(tr("%1 Style").arg(styleName), styleActionGroup); action->setData(styleName); action->setCheckable(true); - connect(action, SIGNAL(triggered(bool)), this, SLOT(changeStyle(bool))); + 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); - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); + nativeFileDialogAct = new QAction(tr("&Use Native File Dialog"), this); + nativeFileDialogAct->setCheckable(true); + nativeFileDialogAct->setChecked(true); + settingsMenu->addAction(nativeFileDialogAct); - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(tr("&About"), this, &MainWindow::about); + helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); } //! [28] -//! [29] -void MainWindow::createMenus() -{ - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(addImagesAct); - fileMenu->addAction(removeAllImagesAct); - fileMenu->addSeparator(); - fileMenu->addAction(exitAct); - - viewMenu = menuBar()->addMenu(tr("&View")); - foreach (QAction *action, styleActionGroup->actions()) - viewMenu->addAction(action); - viewMenu->addSeparator(); - viewMenu->addAction(guessModeStateAct); - - menuBar()->addSeparator(); - - helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); -} -//! [29] - //! [30] void MainWindow::createContextMenu() { imagesTable->setContextMenuPolicy(Qt::ActionsContextMenu); - imagesTable->addAction(addImagesAct); + imagesTable->addAction(addSampleImagesAct); + imagesTable->addAction(addOtherImagesAct); imagesTable->addAction(removeAllImagesAct); } //! [30] @@ -429,14 +501,13 @@ void MainWindow::checkCurrentStyle() { foreach (QAction *action, styleActionGroup->actions()) { QString styleName = action->data().toString(); - QStyle *candidate = QStyleFactory::create(styleName); - Q_ASSERT(candidate); + QScopedPointer<QStyle> candidate(QStyleFactory::create(styleName)); + Q_ASSERT(!candidate.isNull()); if (candidate->metaObject()->className() == QApplication::style()->metaObject()->className()) { action->trigger(); return; } - delete candidate; } } //! [31] diff --git a/examples/widgets/widgets/icons/mainwindow.h b/examples/widgets/widgets/icons/mainwindow.h index 3628038878..207986f741 100644 --- a/examples/widgets/widgets/icons/mainwindow.h +++ b/examples/widgets/widgets/icons/mainwindow.h @@ -49,9 +49,10 @@ QT_BEGIN_NAMESPACE class QAction; class QActionGroup; -class QGroupBox; +class QLabel; class QMenu; class QRadioButton; +class QButtonGroup; class QTableWidget; QT_END_NAMESPACE class IconPreviewArea; @@ -65,51 +66,47 @@ class MainWindow : public QMainWindow public: MainWindow(); + void loadImages(const QStringList &fileNames); + + void show(); + private slots: void about(); void changeStyle(bool checked); - void changeSize(bool checked = true); + void changeSize(int, bool); + void triggerChangeSize(); void changeIcon(); - void addImages(); + void addSampleImages(); + void addOtherImages(); void removeAllImages(); + void useHighDpiPixmapsChanged(int checkState); + void screenChanged(); private: - void createPreviewGroupBox(); - void createImagesGroupBox(); - void createIconSizeGroupBox(); + QWidget *createImagesGroupBox(); + QWidget *createIconSizeGroupBox(); + QWidget *createHighDpiIconSizeGroupBox(); void createActions(); - void createMenus(); void createContextMenu(); void checkCurrentStyle(); + void addImages(const QString &directory); - QWidget *centralWidget; - - QGroupBox *previewGroupBox; IconPreviewArea *previewArea; - QGroupBox *imagesGroupBox; QTableWidget *imagesTable; - QGroupBox *iconSizeGroupBox; - QRadioButton *smallRadioButton; - QRadioButton *largeRadioButton; - QRadioButton *toolBarRadioButton; - QRadioButton *listViewRadioButton; - QRadioButton *iconViewRadioButton; - QRadioButton *tabBarRadioButton; - QRadioButton *otherRadioButton; + QButtonGroup *sizeButtonGroup; IconSizeSpinBox *otherSpinBox; - QMenu *fileMenu; - QMenu *viewMenu; - QMenu *helpMenu; - QAction *addImagesAct; + QLabel *devicePixelRatioLabel; + QLabel *screenNameLabel; + + QAction *addOtherImagesAct; + QAction *addSampleImagesAct; QAction *removeAllImagesAct; - QAction *exitAct; QAction *guessModeStateAct; + QAction *nativeFileDialogAct; QActionGroup *styleActionGroup; - QAction *aboutAct; - QAction *aboutQtAct; }; //! [0] diff --git a/examples/widgets/widgets/imageviewer/imageviewer.cpp b/examples/widgets/widgets/imageviewer/imageviewer.cpp index 93b88e9c18..844acbd62f 100644 --- a/examples/widgets/widgets/imageviewer/imageviewer.cpp +++ b/examples/widgets/widgets/imageviewer/imageviewer.cpp @@ -47,19 +47,20 @@ //! [0] ImageViewer::ImageViewer() + : imageLabel(new QLabel) + , scrollArea(new QScrollArea) + , scaleFactor(1) { - imageLabel = new QLabel; imageLabel->setBackgroundRole(QPalette::Base); imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); imageLabel->setScaledContents(true); - scrollArea = new QScrollArea; scrollArea->setBackgroundRole(QPalette::Dark); scrollArea->setWidget(imageLabel); + scrollArea->setVisible(false); setCentralWidget(scrollArea); createActions(); - createMenus(); resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5); } @@ -71,53 +72,99 @@ bool ImageViewer::loadFile(const QString &fileName) { QImageReader reader(fileName); reader.setAutoTransform(true); - const QImage image = reader.read(); - if (image.isNull()) { + const QImage newImage = reader.read(); + if (newImage.isNull()) { QMessageBox::information(this, QGuiApplication::applicationDisplayName(), - tr("Cannot load %1.").arg(QDir::toNativeSeparators(fileName))); - setWindowFilePath(QString()); - imageLabel->setPixmap(QPixmap()); - imageLabel->adjustSize(); + tr("Cannot load %1: %2") + .arg(QDir::toNativeSeparators(fileName), reader.errorString())); return false; } -//! [2] //! [3] +//! [2] + + setImage(newImage); + + setWindowFilePath(fileName); + + const QString message = tr("Opened \"%1\", %2x%3, Depth: %4") + .arg(QDir::toNativeSeparators(fileName)).arg(image.width()).arg(image.height()).arg(image.depth()); + statusBar()->showMessage(message); + return true; +} + +void ImageViewer::setImage(const QImage &newImage) +{ + image = newImage; imageLabel->setPixmap(QPixmap::fromImage(image)); -//! [3] //! [4] +//! [4] scaleFactor = 1.0; + scrollArea->setVisible(true); printAct->setEnabled(true); fitToWindowAct->setEnabled(true); updateActions(); if (!fitToWindowAct->isChecked()) imageLabel->adjustSize(); - - setWindowFilePath(fileName); - return true; } //! [4] -//! [2] +bool ImageViewer::saveFile(const QString &fileName) +{ + QImageWriter writer(fileName); + + if (!writer.write(image)) { + QMessageBox::information(this, QGuiApplication::applicationDisplayName(), + tr("Cannot write %1: %2") + .arg(QDir::toNativeSeparators(fileName)), writer.errorString()); + return false; + } + const QString message = tr("Wrote \"%1\"").arg(QDir::toNativeSeparators(fileName)); + statusBar()->showMessage(message); + return true; +} //! [1] -void ImageViewer::open() + +static void initializeImageFileDialog(QFileDialog &dialog, QFileDialog::AcceptMode acceptMode) { + static bool firstDialog = true; + + if (firstDialog) { + firstDialog = false; + const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); + dialog.setDirectory(picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.last()); + } + QStringList mimeTypeFilters; - foreach (const QByteArray &mimeTypeName, QImageReader::supportedMimeTypes()) + const QByteArrayList supportedMimeTypes = acceptMode == QFileDialog::AcceptOpen + ? QImageReader::supportedMimeTypes() : QImageWriter::supportedMimeTypes(); + foreach (const QByteArray &mimeTypeName, supportedMimeTypes) mimeTypeFilters.append(mimeTypeName); mimeTypeFilters.sort(); - const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); - QFileDialog dialog(this, tr("Open File"), - picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.last()); - dialog.setAcceptMode(QFileDialog::AcceptOpen); dialog.setMimeTypeFilters(mimeTypeFilters); dialog.selectMimeTypeFilter("image/jpeg"); + if (acceptMode == QFileDialog::AcceptSave) + dialog.setDefaultSuffix("jpg"); +} + +void ImageViewer::open() +{ + QFileDialog dialog(this, tr("Open File")); + initializeImageFileDialog(dialog, QFileDialog::AcceptOpen); while (dialog.exec() == QDialog::Accepted && !loadFile(dialog.selectedFiles().first())) {} } //! [1] +void ImageViewer::saveAs() +{ + QFileDialog dialog(this, tr("Save File As")); + initializeImageFileDialog(dialog, QFileDialog::AcceptSave); + + while (dialog.exec() == QDialog::Accepted && !saveFile(dialog.selectedFiles().first())) {} +} + //! [5] void ImageViewer::print() //! [5] //! [6] @@ -140,6 +187,43 @@ void ImageViewer::print() } //! [8] +void ImageViewer::copy() +{ +#ifndef QT_NO_CLIPBOARD + QGuiApplication::clipboard()->setImage(image); +#endif // !QT_NO_CLIPBOARD +} + +#ifndef QT_NO_CLIPBOARD +static QImage clipboardImage() +{ + if (const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData()) { + if (mimeData->hasImage()) { + const QImage image = qvariant_cast<QImage>(mimeData->imageData()); + if (!image.isNull()) + return image; + } + } + return QImage(); +} +#endif // !QT_NO_CLIPBOARD + +void ImageViewer::paste() +{ +#ifndef QT_NO_CLIPBOARD + const QImage newImage = clipboardImage(); + if (newImage.isNull()) { + statusBar()->showMessage(tr("No image in clipboard")); + } else { + setImage(newImage); + setWindowFilePath(QString()); + const QString message = tr("Obtained image from clipboard, %1x%2, Depth: %3") + .arg(newImage.width()).arg(newImage.height()).arg(newImage.depth()); + statusBar()->showMessage(message); + } +#endif // !QT_NO_CLIPBOARD +} + //! [9] void ImageViewer::zoomIn() //! [9] //! [10] @@ -167,9 +251,8 @@ void ImageViewer::fitToWindow() { bool fitToWindow = fitToWindowAct->isChecked(); scrollArea->setWidgetResizable(fitToWindow); - if (!fitToWindow) { + if (!fitToWindow) normalSize(); - } updateActions(); } //! [14] @@ -199,79 +282,66 @@ void ImageViewer::about() void ImageViewer::createActions() //! [17] //! [18] { - openAct = new QAction(tr("&Open..."), this); - openAct->setShortcut(tr("Ctrl+O")); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + + QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &ImageViewer::open); + openAct->setShortcut(QKeySequence::Open); + + saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &ImageViewer::saveAs); + saveAsAct->setEnabled(false); - printAct = new QAction(tr("&Print..."), this); - printAct->setShortcut(tr("Ctrl+P")); + printAct = fileMenu->addAction(tr("&Print..."), this, &ImageViewer::print); + printAct->setShortcut(QKeySequence::Print); printAct->setEnabled(false); - connect(printAct, SIGNAL(triggered()), this, SLOT(print())); - exitAct = new QAction(tr("E&xit"), this); + fileMenu->addSeparator(); + + QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close); exitAct->setShortcut(tr("Ctrl+Q")); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); - zoomInAct = new QAction(tr("Zoom &In (25%)"), this); - zoomInAct->setShortcut(tr("Ctrl++")); + QMenu *editMenu = menuBar()->addMenu(tr("&Edit")); + + copyAct = editMenu->addAction(tr("&Copy"), this, &ImageViewer::copy); + copyAct->setShortcut(QKeySequence::Copy); + copyAct->setEnabled(false); + + QAction *pasteAct = editMenu->addAction(tr("&Paste"), this, &ImageViewer::paste); + pasteAct->setShortcut(QKeySequence::Paste); + + QMenu *viewMenu = menuBar()->addMenu(tr("&View")); + + zoomInAct = viewMenu->addAction(tr("Zoom &In (25%)"), this, &ImageViewer::zoomIn); + zoomInAct->setShortcut(QKeySequence::ZoomIn); zoomInAct->setEnabled(false); - connect(zoomInAct, SIGNAL(triggered()), this, SLOT(zoomIn())); - zoomOutAct = new QAction(tr("Zoom &Out (25%)"), this); - zoomOutAct->setShortcut(tr("Ctrl+-")); + zoomOutAct = viewMenu->addAction(tr("Zoom &Out (25%)"), this, &ImageViewer::zoomOut); + zoomOutAct->setShortcut(QKeySequence::ZoomOut); zoomOutAct->setEnabled(false); - connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOut())); - normalSizeAct = new QAction(tr("&Normal Size"), this); + normalSizeAct = viewMenu->addAction(tr("&Normal Size"), this, &ImageViewer::normalSize); normalSizeAct->setShortcut(tr("Ctrl+S")); normalSizeAct->setEnabled(false); - connect(normalSizeAct, SIGNAL(triggered()), this, SLOT(normalSize())); - fitToWindowAct = new QAction(tr("&Fit to Window"), this); + viewMenu->addSeparator(); + + fitToWindowAct = viewMenu->addAction(tr("&Fit to Window"), this, &ImageViewer::fitToWindow); fitToWindowAct->setEnabled(false); fitToWindowAct->setCheckable(true); fitToWindowAct->setShortcut(tr("Ctrl+F")); - connect(fitToWindowAct, SIGNAL(triggered()), this, SLOT(fitToWindow())); - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + helpMenu->addAction(tr("&About"), this, &ImageViewer::about); + helpMenu->addAction(tr("About &Qt"), &QApplication::aboutQt); } //! [18] -//! [19] -void ImageViewer::createMenus() -//! [19] //! [20] -{ - fileMenu = new QMenu(tr("&File"), this); - fileMenu->addAction(openAct); - fileMenu->addAction(printAct); - fileMenu->addSeparator(); - fileMenu->addAction(exitAct); - - viewMenu = new QMenu(tr("&View"), this); - viewMenu->addAction(zoomInAct); - viewMenu->addAction(zoomOutAct); - viewMenu->addAction(normalSizeAct); - viewMenu->addSeparator(); - viewMenu->addAction(fitToWindowAct); - - helpMenu = new QMenu(tr("&Help"), this); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); - - menuBar()->addMenu(fileMenu); - menuBar()->addMenu(viewMenu); - menuBar()->addMenu(helpMenu); -} -//! [20] - //! [21] void ImageViewer::updateActions() //! [21] //! [22] { + saveAsAct->setEnabled(!image.isNull()); + copyAct->setEnabled(!image.isNull()); zoomInAct->setEnabled(!fitToWindowAct->isChecked()); zoomOutAct->setEnabled(!fitToWindowAct->isChecked()); normalSizeAct->setEnabled(!fitToWindowAct->isChecked()); diff --git a/examples/widgets/widgets/imageviewer/imageviewer.h b/examples/widgets/widgets/imageviewer/imageviewer.h index 7b35e3ee9e..7084bf98d1 100644 --- a/examples/widgets/widgets/imageviewer/imageviewer.h +++ b/examples/widgets/widgets/imageviewer/imageviewer.h @@ -42,6 +42,7 @@ #define IMAGEVIEWER_H #include <QMainWindow> +#include <QImage> #ifndef QT_NO_PRINTER #include <QPrinter> #endif @@ -65,7 +66,10 @@ public: private slots: void open(); + void saveAs(); void print(); + void copy(); + void paste(); void zoomIn(); void zoomOut(); void normalSize(); @@ -76,9 +80,12 @@ private: void createActions(); void createMenus(); void updateActions(); + bool saveFile(const QString &fileName); + void setImage(const QImage &newImage); void scaleImage(double factor); void adjustScrollBar(QScrollBar *scrollBar, double factor); + QImage image; QLabel *imageLabel; QScrollArea *scrollArea; double scaleFactor; @@ -87,19 +94,13 @@ private: QPrinter printer; #endif - QAction *openAct; + QAction *saveAsAct; QAction *printAct; - QAction *exitAct; + QAction *copyAct; QAction *zoomInAct; QAction *zoomOutAct; QAction *normalSizeAct; QAction *fitToWindowAct; - QAction *aboutAct; - QAction *aboutQtAct; - - QMenu *fileMenu; - QMenu *viewMenu; - QMenu *helpMenu; }; //! [0] diff --git a/examples/widgets/widgets/movie/movie.pro b/examples/widgets/widgets/movie/movie.pro index 86d85552c2..94d86454d8 100644 --- a/examples/widgets/widgets/movie/movie.pro +++ b/examples/widgets/widgets/movie/movie.pro @@ -14,5 +14,5 @@ INSTALLS += target wince { addFiles.files += *.gif addFiles.path = . - DEPLOYMENT += addFiles + INSTALLS += addFiles } diff --git a/examples/widgets/widgets/stylesheet/mainwindow.cpp b/examples/widgets/widgets/stylesheet/mainwindow.cpp index a49c06dfd2..6d84897c77 100644 --- a/examples/widgets/widgets/stylesheet/mainwindow.cpp +++ b/examples/widgets/widgets/stylesheet/mainwindow.cpp @@ -67,7 +67,7 @@ void MainWindow::on_aboutAction_triggered() { QMessageBox::about(this, tr("About Style sheet"), tr("The <b>Style Sheet</b> example shows how widgets can be styled " - "using <a href=\"http://doc.qt.digia.com/4.5/stylesheet.html\">Qt " + "using <a href=\"http://doc.qt.io/qt-5/stylesheet.html\">Qt " "Style Sheets</a>. Click <b>File|Edit Style Sheet</b> to pop up the " "style editor, and either choose an existing style sheet or design " "your own.")); diff --git a/examples/widgets/widgets/tablet/images.qrc b/examples/widgets/widgets/tablet/images.qrc new file mode 100644 index 0000000000..eb3eabbace --- /dev/null +++ b/examples/widgets/widgets/tablet/images.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource> + <file>images/cursor-airbrush.png</file> + <file>images/cursor-eraser.png</file> + <file>images/cursor-felt-marker.png</file> + <file>images/cursor-pencil.png</file> + </qresource> +</RCC> diff --git a/examples/widgets/widgets/tablet/images/cursor-airbrush.png b/examples/widgets/widgets/tablet/images/cursor-airbrush.png Binary files differnew file mode 100644 index 0000000000..bea756ed6f --- /dev/null +++ b/examples/widgets/widgets/tablet/images/cursor-airbrush.png diff --git a/examples/widgets/widgets/tablet/images/cursor-eraser.png b/examples/widgets/widgets/tablet/images/cursor-eraser.png Binary files differnew file mode 100644 index 0000000000..e5488a89f2 --- /dev/null +++ b/examples/widgets/widgets/tablet/images/cursor-eraser.png diff --git a/examples/widgets/widgets/tablet/images/cursor-felt-marker.png b/examples/widgets/widgets/tablet/images/cursor-felt-marker.png Binary files differnew file mode 100644 index 0000000000..132f09aa39 --- /dev/null +++ b/examples/widgets/widgets/tablet/images/cursor-felt-marker.png diff --git a/examples/widgets/widgets/tablet/images/cursor-pencil.png b/examples/widgets/widgets/tablet/images/cursor-pencil.png Binary files differnew file mode 100644 index 0000000000..cc2f447d02 --- /dev/null +++ b/examples/widgets/widgets/tablet/images/cursor-pencil.png diff --git a/examples/widgets/widgets/tablet/mainwindow.cpp b/examples/widgets/widgets/tablet/mainwindow.cpp index aed84c50df..5e84f5b6a2 100644 --- a/examples/widgets/widgets/tablet/mainwindow.cpp +++ b/examples/widgets/widgets/tablet/mainwindow.cpp @@ -52,7 +52,7 @@ MainWindow::MainWindow(TabletCanvas *canvas) myCanvas->setColor(Qt::red); myCanvas->setLineWidthType(TabletCanvas::LineWidthPressure); - myCanvas->setAlphaChannelType(TabletCanvas::NoAlpha); + myCanvas->setAlphaChannelType(TabletCanvas::AlphaTangentialPressure); myCanvas->setColorSaturationType(TabletCanvas::NoSaturation); setWindowTitle(tr("Tablet Example")); @@ -75,6 +75,8 @@ void MainWindow::alphaActionTriggered(QAction *action) { if (action == alphaChannelPressureAction) { myCanvas->setAlphaChannelType(TabletCanvas::AlphaPressure); + } else if (action == alphaChannelTangentialPressureAction) { + myCanvas->setAlphaChannelType(TabletCanvas::AlphaTangentialPressure); } else if (action == alphaChannelTiltAction) { myCanvas->setAlphaChannelType(TabletCanvas::AlphaTilt); } else { @@ -157,15 +159,19 @@ void MainWindow::createActions() alphaChannelPressureAction = new QAction(tr("&Pressure"), this); alphaChannelPressureAction->setCheckable(true); + alphaChannelTangentialPressureAction = new QAction(tr("T&angential Pressure"), this); + alphaChannelTangentialPressureAction->setCheckable(true); + alphaChannelTangentialPressureAction->setChecked(true); + alphaChannelTiltAction = new QAction(tr("&Tilt"), this); alphaChannelTiltAction->setCheckable(true); noAlphaChannelAction = new QAction(tr("No Alpha Channel"), this); noAlphaChannelAction->setCheckable(true); - noAlphaChannelAction->setChecked(true); alphaChannelGroup = new QActionGroup(this); alphaChannelGroup->addAction(alphaChannelPressureAction); + alphaChannelGroup->addAction(alphaChannelTangentialPressureAction); alphaChannelGroup->addAction(alphaChannelTiltAction); alphaChannelGroup->addAction(noAlphaChannelAction); connect(alphaChannelGroup, SIGNAL(triggered(QAction*)), @@ -259,6 +265,7 @@ void MainWindow::createMenus() alphaChannelMenu = tabletMenu->addMenu(tr("&Alpha Channel")); alphaChannelMenu->addAction(alphaChannelPressureAction); + alphaChannelMenu->addAction(alphaChannelTangentialPressureAction); alphaChannelMenu->addAction(alphaChannelTiltAction); alphaChannelMenu->addAction(noAlphaChannelAction); diff --git a/examples/widgets/widgets/tablet/mainwindow.h b/examples/widgets/widgets/tablet/mainwindow.h index 5e77ea1acf..c6ac2e6026 100644 --- a/examples/widgets/widgets/tablet/mainwindow.h +++ b/examples/widgets/widgets/tablet/mainwindow.h @@ -79,6 +79,7 @@ private: QActionGroup *alphaChannelGroup; QAction *alphaChannelPressureAction; + QAction *alphaChannelTangentialPressureAction; QAction *alphaChannelTiltAction; QAction *noAlphaChannelAction; diff --git a/examples/widgets/widgets/tablet/tablet.pro b/examples/widgets/widgets/tablet/tablet.pro index de81e7b198..9b8927f483 100644 --- a/examples/widgets/widgets/tablet/tablet.pro +++ b/examples/widgets/widgets/tablet/tablet.pro @@ -1,12 +1,13 @@ QT += widgets HEADERS = mainwindow.h \ - tabletcanvas.h \ - tabletapplication.h + tabletcanvas.h \ + tabletapplication.h SOURCES = mainwindow.cpp \ - main.cpp \ - tabletcanvas.cpp \ - tabletapplication.cpp + main.cpp \ + tabletcanvas.cpp \ + tabletapplication.cpp +RESOURCES += images.qrc # install target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/tablet diff --git a/examples/widgets/widgets/tablet/tabletapplication.cpp b/examples/widgets/widgets/tablet/tabletapplication.cpp index c3210f822c..3e1356ee9c 100644 --- a/examples/widgets/widgets/tablet/tabletapplication.cpp +++ b/examples/widgets/widgets/tablet/tabletapplication.cpp @@ -47,8 +47,7 @@ bool TabletApplication::event(QEvent *event) { if (event->type() == QEvent::TabletEnterProximity || event->type() == QEvent::TabletLeaveProximity) { - myCanvas->setTabletDevice( - static_cast<QTabletEvent *>(event)->device()); + myCanvas->setTabletDevice(static_cast<QTabletEvent *>(event)); return true; } return QApplication::event(event); diff --git a/examples/widgets/widgets/tablet/tabletcanvas.cpp b/examples/widgets/widgets/tablet/tabletcanvas.cpp index 20d6291292..8ff3d41e0e 100644 --- a/examples/widgets/widgets/tablet/tabletcanvas.cpp +++ b/examples/widgets/widgets/tablet/tabletcanvas.cpp @@ -47,14 +47,13 @@ TabletCanvas::TabletCanvas() { resize(500, 500); - myBrush = QBrush(); - myPen = QPen(); + myColor = Qt::red; + myBrush = QBrush(myColor); + myPen = QPen(myBrush, 1.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); initPixmap(); setAutoFillBackground(true); deviceDown = false; - myColor = Qt::red; - myTabletDevice = QTabletEvent::Stylus; - alphaChannelType = NoAlpha; + alphaChannelType = AlphaTangentialPressure; colorSaturationType = NoSaturation; lineWidthType = LineWidthPressure; } @@ -99,24 +98,25 @@ void TabletCanvas::tabletEvent(QTabletEvent *event) case QEvent::TabletPress: if (!deviceDown) { deviceDown = true; - polyLine[0] = polyLine[1] = polyLine[2] = event->pos(); + lastPoint.pos = event->posF(); + lastPoint.rotation = event->rotation(); } break; - case QEvent::TabletRelease: - if (deviceDown) - deviceDown = false; - break; case QEvent::TabletMove: - polyLine[2] = polyLine[1]; - polyLine[1] = polyLine[0]; - polyLine[0] = event->pos(); - + if (event->device() == QTabletEvent::RotationStylus) + updateCursor(event); if (deviceDown) { updateBrush(event); QPainter painter(&pixmap); paintPixmap(painter, event); + lastPoint.pos = event->posF(); + lastPoint.rotation = event->rotation(); } break; + case QEvent::TabletRelease: + if (deviceDown && event->buttons() == Qt::NoButton) + deviceDown = false; + break; default: break; } @@ -135,23 +135,44 @@ void TabletCanvas::paintEvent(QPaintEvent *) //! [5] void TabletCanvas::paintPixmap(QPainter &painter, QTabletEvent *event) { - QPoint brushAdjust(10, 10); + painter.setRenderHint(QPainter::Antialiasing); - switch (myTabletDevice) { + switch (event->device()) { +//! [6] case QTabletEvent::Airbrush: - myBrush.setColor(myColor); - myBrush.setStyle(brushPattern(event->pressure())); - painter.setPen(Qt::NoPen); - painter.setBrush(myBrush); - - for (int i = 0; i < 3; ++i) { - painter.drawEllipse(QRect(polyLine[i] - brushAdjust, - polyLine[i] + brushAdjust)); + { + painter.setPen(Qt::NoPen); + QRadialGradient grad(lastPoint.pos, myPen.widthF() * 10.0); + QColor color = myBrush.color(); + color.setAlphaF(color.alphaF() * 0.25); + grad.setColorAt(0, myBrush.color()); + grad.setColorAt(0.5, Qt::transparent); + painter.setBrush(grad); + qreal radius = grad.radius(); + painter.drawEllipse(event->posF(), radius, radius); + } + break; + case QTabletEvent::RotationStylus: + { + myBrush.setStyle(Qt::SolidPattern); + painter.setPen(Qt::NoPen); + painter.setBrush(myBrush); + QPolygonF poly; + qreal halfWidth = myPen.widthF(); + QPointF brushAdjust(qSin(qDegreesToRadians(lastPoint.rotation)) * halfWidth, + qCos(qDegreesToRadians(lastPoint.rotation)) * halfWidth); + poly << lastPoint.pos + brushAdjust; + poly << lastPoint.pos - brushAdjust; + brushAdjust = QPointF(qSin(qDegreesToRadians(event->rotation())) * halfWidth, + qCos(qDegreesToRadians(event->rotation())) * halfWidth); + poly << event->posF() - brushAdjust; + poly << event->posF() + brushAdjust; + painter.drawConvexPolygon(poly); } break; +//! [6] case QTabletEvent::Puck: case QTabletEvent::FourDMouse: - case QTabletEvent::RotationStylus: { const QString error(tr("This input device is not supported by the example.")); #ifndef QT_NO_STATUSTIP @@ -174,42 +195,15 @@ void TabletCanvas::paintPixmap(QPainter &painter, QTabletEvent *event) } // FALL-THROUGH case QTabletEvent::Stylus: - painter.setBrush(myBrush); painter.setPen(myPen); - painter.drawLine(polyLine[1], event->pos()); + painter.drawLine(lastPoint.pos, event->posF()); break; } } //! [5] -//! [6] -Qt::BrushStyle TabletCanvas::brushPattern(qreal value) -{ - int pattern = int((value) * 100.0) % 7; - - switch (pattern) { - case 0: - return Qt::SolidPattern; - case 1: - return Qt::Dense1Pattern; - case 2: - return Qt::Dense2Pattern; - case 3: - return Qt::Dense3Pattern; - case 4: - return Qt::Dense4Pattern; - case 5: - return Qt::Dense5Pattern; - case 6: - return Qt::Dense6Pattern; - default: - return Qt::Dense7Pattern; - } -} -//! [6] - //! [7] -void TabletCanvas::updateBrush(QTabletEvent *event) +void TabletCanvas::updateBrush(const QTabletEvent *event) { int hue, saturation, value, alpha; myColor.getHsv(&hue, &saturation, &value, &alpha); @@ -220,7 +214,13 @@ void TabletCanvas::updateBrush(QTabletEvent *event) switch (alphaChannelType) { case AlphaPressure: - myColor.setAlpha(int(event->pressure() * 255.0)); + myColor.setAlphaF(event->pressure()); + break; + case AlphaTangentialPressure: + if (event->device() == QTabletEvent::Airbrush) + myColor.setAlphaF(qMax(0.01, (event->tangentialPressure() + 1.0) / 2.0)); + else + myColor.setAlpha(255); break; case AlphaTilt: myColor.setAlpha(maximum(abs(vValue - 127), abs(hValue - 127))); @@ -268,8 +268,47 @@ void TabletCanvas::updateBrush(QTabletEvent *event) } //! [11] +void TabletCanvas::updateCursor(const QTabletEvent *event) +{ + QCursor cursor; + if (event->type() != QEvent::TabletLeaveProximity) { + if (event->pointerType() == QTabletEvent::Eraser) { + cursor = QCursor(QPixmap(":/images/cursor-eraser.png"), 3, 28); + } else { + switch (event->device()) { + case QTabletEvent::Stylus: + cursor = QCursor(QPixmap(":/images/cursor-pencil.png"), 0, 0); + break; + case QTabletEvent::Airbrush: + cursor = QCursor(QPixmap(":/images/cursor-airbrush.png"), 3, 4); + break; + case QTabletEvent::RotationStylus: { + QImage origImg(QLatin1String(":/images/cursor-felt-marker.png")); + QImage img(32, 32, QImage::Format_ARGB32); + QColor solid = myColor; + solid.setAlpha(255); + img.fill(solid); + QPainter painter(&img); + QTransform transform = painter.transform(); + transform.translate(16, 16); + transform.rotate(-event->rotation()); + painter.setTransform(transform); + painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + painter.drawImage(-24, -24, origImg); + painter.setCompositionMode(QPainter::CompositionMode_HardLight); + painter.drawImage(-24, -24, origImg); + painter.end(); + cursor = QCursor(QPixmap::fromImage(img), 16, 16); + } break; + default: + break; + } + } + } + setCursor(cursor); +} + void TabletCanvas::resizeEvent(QResizeEvent *) { initPixmap(); - polyLine[0] = polyLine[1] = polyLine[2] = QPoint(); } diff --git a/examples/widgets/widgets/tablet/tabletcanvas.h b/examples/widgets/widgets/tablet/tabletcanvas.h index 873f3a7ab0..a7335dbaf0 100644 --- a/examples/widgets/widgets/tablet/tabletcanvas.h +++ b/examples/widgets/widgets/tablet/tabletcanvas.h @@ -61,7 +61,7 @@ class TabletCanvas : public QWidget Q_OBJECT public: - enum AlphaChannelType { AlphaPressure, AlphaTilt, NoAlpha }; + enum AlphaChannelType { AlphaPressure, AlphaTangentialPressure, AlphaTilt, NoAlpha }; enum ColorSaturationType { SaturationVTilt, SaturationHTilt, SaturationPressure, NoSaturation }; enum LineWidthType { LineWidthPressure, LineWidthTilt, NoLineWidth }; @@ -80,8 +80,8 @@ public: { myColor = color; } QColor color() const { return myColor; } - void setTabletDevice(QTabletEvent::TabletDevice device) - { myTabletDevice = device; } + void setTabletDevice(QTabletEvent *event) + { myTabletDevice = event->device(); updateCursor(event); } int maximum(int a, int b) { return a > b ? a : b; } @@ -94,7 +94,8 @@ private: void initPixmap(); void paintPixmap(QPainter &painter, QTabletEvent *event); Qt::BrushStyle brushPattern(qreal value); - void updateBrush(QTabletEvent *event); + void updateBrush(const QTabletEvent *event); + void updateCursor(const QTabletEvent *event); AlphaChannelType alphaChannelType; ColorSaturationType colorSaturationType; @@ -107,7 +108,11 @@ private: QBrush myBrush; QPen myPen; bool deviceDown; - QPoint polyLine[3]; + + struct Point { + QPointF pos; + qreal rotation; + } lastPoint; }; //! [0] |