diff options
Diffstat (limited to 'tests/manual/examples/widgets/widgets')
125 files changed, 6786 insertions, 0 deletions
diff --git a/tests/manual/examples/widgets/widgets/charactermap/CMakeLists.txt b/tests/manual/examples/widgets/widgets/charactermap/CMakeLists.txt new file mode 100644 index 0000000000..f02ac52689 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/charactermap/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(charactermap LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/charactermap") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(charactermap + characterwidget.cpp characterwidget.h + main.cpp + mainwindow.cpp mainwindow.h +) + +set_target_properties(charactermap PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(charactermap PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS charactermap + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/widgets/charactermap/charactermap.pro b/tests/manual/examples/widgets/widgets/charactermap/charactermap.pro new file mode 100644 index 0000000000..373aabca73 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/charactermap/charactermap.pro @@ -0,0 +1,12 @@ +QT += widgets +requires(qtConfig(combobox)) + +HEADERS = characterwidget.h \ + mainwindow.h +SOURCES = characterwidget.cpp \ + mainwindow.cpp \ + main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/charactermap +INSTALLS += target diff --git a/tests/manual/examples/widgets/widgets/charactermap/characterwidget.cpp b/tests/manual/examples/widgets/widgets/charactermap/characterwidget.cpp new file mode 100644 index 0000000000..6287a44e80 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/charactermap/characterwidget.cpp @@ -0,0 +1,145 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "characterwidget.h" + +#include <QFontDatabase> +#include <QMouseEvent> +#include <QPainter> +#include <QToolTip> + +//! [0] +CharacterWidget::CharacterWidget(QWidget *parent) + : QWidget(parent) +{ + calculateSquareSize(); + setMouseTracking(true); +} +//! [0] + +//! [1] +void CharacterWidget::updateFont(const QFont &font) +{ + displayFont.setFamily(font.family()); + calculateSquareSize(); + adjustSize(); + update(); +} +//! [1] + +//! [2] +void CharacterWidget::updateSize(const QString &fontSize) +{ + displayFont.setPointSize(fontSize.toInt()); + calculateSquareSize(); + adjustSize(); + update(); +} +//! [2] + +void CharacterWidget::updateStyle(const QString &fontStyle) +{ + const QFont::StyleStrategy oldStrategy = displayFont.styleStrategy(); + displayFont = QFontDatabase::font(displayFont.family(), fontStyle, displayFont.pointSize()); + displayFont.setStyleStrategy(oldStrategy); + calculateSquareSize(); + adjustSize(); + update(); +} + +void CharacterWidget::updateFontMerging(bool enable) +{ + if (enable) + displayFont.setStyleStrategy(QFont::PreferDefault); + else + displayFont.setStyleStrategy(QFont::NoFontMerging); + adjustSize(); + update(); +} + +void CharacterWidget::calculateSquareSize() +{ + squareSize = qMax(16, 4 + QFontMetrics(displayFont, this).height()); +} + +//! [3] +QSize CharacterWidget::sizeHint() const +{ + return QSize(columns*squareSize, (65536 / columns) * squareSize); +} +//! [3] + +//! [4] +void CharacterWidget::mouseMoveEvent(QMouseEvent *event) +{ + QPoint widgetPosition = mapFromGlobal(event->globalPosition().toPoint()); + uint key = (widgetPosition.y() / squareSize) * columns + widgetPosition.x() / squareSize; + + QString text = QString::fromLatin1("<p>Character: <span style=\"font-size: 24pt; font-family: %1\">").arg(displayFont.family()) + + QChar(key) + + QString::fromLatin1("</span><p>Value: 0x") + + QString::number(key, 16); + QToolTip::showText(event->globalPosition().toPoint(), text, this); +} +//! [4] + +//! [5] +void CharacterWidget::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + lastKey = (event->position().toPoint().y() / squareSize) * columns + event->position().toPoint().x() / squareSize; + if (QChar(lastKey).category() != QChar::Other_NotAssigned) + emit characterSelected(QString(QChar(lastKey))); + update(); + } + else + QWidget::mousePressEvent(event); +} +//! [5] + +//! [6] +void CharacterWidget::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + painter.fillRect(event->rect(), QBrush(Qt::white)); + painter.setFont(displayFont); +//! [6] + +//! [7] + QRect redrawRect = event->rect(); + int beginRow = redrawRect.top() / squareSize; + int endRow = redrawRect.bottom() / squareSize; + int beginColumn = redrawRect.left() / squareSize; + int endColumn = redrawRect.right() / squareSize; +//! [7] + +//! [8] + painter.setPen(QPen(Qt::gray)); + for (int row = beginRow; row <= endRow; ++row) { + for (int column = beginColumn; column <= endColumn; ++column) { + painter.drawRect(column * squareSize, row * squareSize, squareSize, squareSize); + } +//! [8] //! [9] + } +//! [9] + +//! [10] + QFontMetrics fontMetrics(displayFont); + painter.setPen(QPen(Qt::black)); + for (int row = beginRow; row <= endRow; ++row) { + for (int column = beginColumn; column <= endColumn; ++column) { + int key = row * columns + column; + painter.setClipRect(column * squareSize, row * squareSize, squareSize, squareSize); + + if (key == lastKey) + painter.fillRect(column * squareSize + 1, row * squareSize + 1, + squareSize, squareSize, QBrush(Qt::red)); + + painter.drawText(column * squareSize + (squareSize / 2) - + fontMetrics.horizontalAdvance(QChar(key)) / 2, + row * squareSize + 4 + fontMetrics.ascent(), + QString(QChar(key))); + } + } +} +//! [10] diff --git a/tests/manual/examples/widgets/widgets/charactermap/characterwidget.h b/tests/manual/examples/widgets/widgets/charactermap/characterwidget.h new file mode 100644 index 0000000000..b8aa76d111 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/charactermap/characterwidget.h @@ -0,0 +1,50 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CHARACTERWIDGET_H +#define CHARACTERWIDGET_H + +#include <QFont> +#include <QSize> +#include <QString> +#include <QWidget> + +QT_BEGIN_NAMESPACE +class QMouseEvent; +class QPaintEvent; +QT_END_NAMESPACE + +//! [0] +class CharacterWidget : public QWidget +{ + Q_OBJECT + +public: + CharacterWidget(QWidget *parent = nullptr); + QSize sizeHint() const override; + +public slots: + void updateFont(const QFont &font); + void updateSize(const QString &fontSize); + void updateStyle(const QString &fontStyle); + void updateFontMerging(bool enable); + +signals: + void characterSelected(const QString &character); + +protected: + void mouseMoveEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void paintEvent(QPaintEvent *event) override; + +private: + void calculateSquareSize(); + + QFont displayFont; + int columns = 16; + int lastKey = -1; + int squareSize = 0; +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/charactermap/main.cpp b/tests/manual/examples/widgets/widgets/charactermap/main.cpp new file mode 100644 index 0000000000..7d7cf3e573 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/charactermap/main.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QApplication> + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MainWindow window; + window.show(); + return app.exec(); +} diff --git a/tests/manual/examples/widgets/widgets/charactermap/mainwindow.cpp b/tests/manual/examples/widgets/widgets/charactermap/mainwindow.cpp new file mode 100644 index 0000000000..fcc00f9642 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/charactermap/mainwindow.cpp @@ -0,0 +1,264 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "mainwindow.h" +#include "characterwidget.h" + +#include <QApplication> +#include <QBoxLayout> +#include <QCheckBox> +#include <QClipboard> +#include <QDialog> +#include <QDialogButtonBox> +#include <QFontComboBox> +#include <QLabel> +#include <QLineEdit> +#include <QMenuBar> +#include <QPlainTextEdit> +#include <QPushButton> +#include <QScreen> +#include <QScrollArea> +#include <QStatusBar> +#include <QTextStream> + +//! [0] +Q_DECLARE_METATYPE(QFontComboBox::FontFilter) + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + QMenu *fileMenu = menuBar()->addMenu(tr("File")); + fileMenu->addAction(tr("Quit"), this, &QWidget::close); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(tr("Show Font Info"), this, &MainWindow::showInfo); + helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); + + QWidget *centralWidget = new QWidget; + + QLabel *filterLabel = new QLabel(tr("Filter:")); + filterCombo = new QComboBox; + filterCombo->addItem(tr("All"), QVariant::fromValue(QFontComboBox::AllFonts)); + filterCombo->addItem(tr("Scalable"), QVariant::fromValue(QFontComboBox::ScalableFonts)); + filterCombo->addItem(tr("Monospaced"), QVariant::fromValue(QFontComboBox::MonospacedFonts)); + filterCombo->addItem(tr("Proportional"), QVariant::fromValue(QFontComboBox::ProportionalFonts)); + filterCombo->setCurrentIndex(0); + connect(filterCombo, &QComboBox::currentIndexChanged, + this, &MainWindow::filterChanged); + + QLabel *fontLabel = new QLabel(tr("Font:")); + fontCombo = new QFontComboBox; + QLabel *sizeLabel = new QLabel(tr("Size:")); + sizeCombo = new QComboBox; + QLabel *styleLabel = new QLabel(tr("Style:")); + styleCombo = new QComboBox; + QLabel *fontMergingLabel = new QLabel(tr("Automatic Font Merging:")); + fontMerging = new QCheckBox; + fontMerging->setChecked(true); + + scrollArea = new QScrollArea; + characterWidget = new CharacterWidget; + scrollArea->setWidget(characterWidget); +//! [0] + +//! [1] + findStyles(fontCombo->currentFont()); +//! [1] + findSizes(fontCombo->currentFont()); + +//! [2] + lineEdit = new QLineEdit; + lineEdit->setClearButtonEnabled(true); +#ifndef QT_NO_CLIPBOARD + QPushButton *clipboardButton = new QPushButton(tr("&To clipboard")); +//! [2] + +#endif + +//! [4] + connect(fontCombo, &QFontComboBox::currentFontChanged, + this, &MainWindow::findStyles); + connect(fontCombo, &QFontComboBox::currentFontChanged, + this, &MainWindow::findSizes); + connect(fontCombo, &QFontComboBox::currentFontChanged, + characterWidget, &CharacterWidget::updateFont); + connect(sizeCombo, &QComboBox::currentTextChanged, + characterWidget, &CharacterWidget::updateSize); + connect(styleCombo, &QComboBox::currentTextChanged, + characterWidget, &CharacterWidget::updateStyle); +//! [4] //! [5] + connect(characterWidget, &CharacterWidget::characterSelected, + this, &MainWindow::insertCharacter); + +#ifndef QT_NO_CLIPBOARD + connect(clipboardButton, &QAbstractButton::clicked, this, &MainWindow::updateClipboard); +#endif +//! [5] + connect(fontMerging, &QAbstractButton::toggled, characterWidget, &CharacterWidget::updateFontMerging); + +//! [6] + QHBoxLayout *controlsLayout = new QHBoxLayout; + controlsLayout->addWidget(filterLabel); + controlsLayout->addWidget(filterCombo, 1); + controlsLayout->addWidget(fontLabel); + controlsLayout->addWidget(fontCombo, 1); + controlsLayout->addWidget(sizeLabel); + controlsLayout->addWidget(sizeCombo, 1); + controlsLayout->addWidget(styleLabel); + controlsLayout->addWidget(styleCombo, 1); + controlsLayout->addWidget(fontMergingLabel); + controlsLayout->addWidget(fontMerging, 1); + controlsLayout->addStretch(1); + + QHBoxLayout *lineLayout = new QHBoxLayout; + lineLayout->addWidget(lineEdit, 1); + lineLayout->addSpacing(12); +#ifndef QT_NO_CLIPBOARD + lineLayout->addWidget(clipboardButton); +#endif + + QVBoxLayout *centralLayout = new QVBoxLayout; + centralLayout->addLayout(controlsLayout); + centralLayout->addWidget(scrollArea, 1); + centralLayout->addSpacing(4); + centralLayout->addLayout(lineLayout); + centralWidget->setLayout(centralLayout); + + setCentralWidget(centralWidget); + setWindowTitle(tr("Character Map")); +} +//! [6] + +//! [7] +void MainWindow::findStyles(const QFont &font) +{ + QString currentItem = styleCombo->currentText(); + styleCombo->clear(); +//! [7] + +//! [8] + const QStringList styles = QFontDatabase::styles(font.family()); + for (const QString &style : styles) + styleCombo->addItem(style); + + int styleIndex = styleCombo->findText(currentItem); + + if (styleIndex == -1) + styleCombo->setCurrentIndex(0); + else + styleCombo->setCurrentIndex(styleIndex); +} +//! [8] + +void MainWindow::filterChanged(int f) +{ + const QFontComboBox::FontFilter filter = + qvariant_cast<QFontComboBox::FontFilter>(filterCombo->itemData(f)); + fontCombo->setFontFilters(filter); + statusBar()->showMessage(tr("%n font(s) found", nullptr, fontCombo->count())); +} + +void MainWindow::findSizes(const QFont &font) +{ + QString currentSize = sizeCombo->currentText(); + + { + const QSignalBlocker blocker(sizeCombo); + // sizeCombo signals are now blocked until end of scope + sizeCombo->clear(); + + if (QFontDatabase::isSmoothlyScalable(font.family(), QFontDatabase::styleString(font))) { + const QList<int> sizes = QFontDatabase::standardSizes(); + for (const int size : sizes) { + sizeCombo->addItem(QVariant(size).toString()); + sizeCombo->setEditable(true); + } + + } else { + const QList<int> sizes = QFontDatabase::smoothSizes(font.family(), QFontDatabase::styleString(font)); + for (const int size : sizes ) { + sizeCombo->addItem(QVariant(size).toString()); + sizeCombo->setEditable(false); + } + } + } + + int sizeIndex = sizeCombo->findText(currentSize); + + if(sizeIndex == -1) + sizeCombo->setCurrentIndex(qMax(0, sizeCombo->count() / 3)); + else + sizeCombo->setCurrentIndex(sizeIndex); +} + +//! [9] +void MainWindow::insertCharacter(const QString &character) +{ + lineEdit->insert(character); +} +//! [9] + +//! [10] +#ifndef QT_NO_CLIPBOARD +void MainWindow::updateClipboard() +{ +//! [11] + QGuiApplication::clipboard()->setText(lineEdit->text(), QClipboard::Clipboard); +//! [11] + QGuiApplication::clipboard()->setText(lineEdit->text(), QClipboard::Selection); +} +#endif + +class FontInfoDialog : public QDialog +{ +public: + explicit FontInfoDialog(QWidget *parent = nullptr); + +private: + QString text() const; +}; + +FontInfoDialog::FontInfoDialog(QWidget *parent) : QDialog(parent) +{ + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + QVBoxLayout *mainLayout = new QVBoxLayout(this); + QPlainTextEdit *textEdit = new QPlainTextEdit(text(), this); + textEdit->setReadOnly(true); + textEdit->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + mainLayout->addWidget(textEdit); + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, this); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + mainLayout->addWidget(buttonBox); +} + +QString FontInfoDialog::text() const +{ + QString text; + QTextStream str(&text); + const QFont defaultFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont); + const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); + const QFont titleFont = QFontDatabase::systemFont(QFontDatabase::TitleFont); + const QFont smallestReadableFont = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); + + str << "Qt " << QT_VERSION_STR << " on " << QGuiApplication::platformName() + << ", " << logicalDpiX() << "DPI"; + if (!qFuzzyCompare(devicePixelRatio(), qreal(1))) + str << ", device pixel ratio: " << devicePixelRatio(); + str << "\n\nDefault font : " << defaultFont.family() << ", " << defaultFont.pointSizeF() << "pt\n" + << "Fixed font : " << fixedFont.family() << ", " << fixedFont.pointSizeF() << "pt\n" + << "Title font : " << titleFont.family() << ", " << titleFont.pointSizeF() << "pt\n" + << "Smallest font: " << smallestReadableFont.family() << ", " << smallestReadableFont.pointSizeF() << "pt\n"; + + return text; +} + +void MainWindow::showInfo() +{ + const QRect screenGeometry = screen()->geometry(); + FontInfoDialog *dialog = new FontInfoDialog(this); + dialog->setWindowTitle(tr("Fonts")); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->resize(screenGeometry.width() / 4, screenGeometry.height() / 4); + dialog->show(); +} + +//! [10] diff --git a/tests/manual/examples/widgets/widgets/charactermap/mainwindow.h b/tests/manual/examples/widgets/widgets/charactermap/mainwindow.h new file mode 100644 index 0000000000..b8f3c166eb --- /dev/null +++ b/tests/manual/examples/widgets/widgets/charactermap/mainwindow.h @@ -0,0 +1,50 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> +#include <QString> + +QT_BEGIN_NAMESPACE +class QClipboard; +class QComboBox; +class QFontComboBox; +class QLineEdit; +class QScrollArea; +class QCheckBox; +QT_END_NAMESPACE +class CharacterWidget; + +//! [0] +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + +public slots: + void filterChanged(int); + void findStyles(const QFont &font); + void findSizes(const QFont &font); + void insertCharacter(const QString &character); +#ifndef QT_NO_CLIPBOARD + void updateClipboard(); +#endif + void showInfo(); + +private: + CharacterWidget *characterWidget; + QComboBox *filterCombo; + QComboBox *styleCombo; + QComboBox *sizeCombo; + QFontComboBox *fontCombo; + QLineEdit *lineEdit; + QScrollArea *scrollArea; + QCheckBox *fontMerging; +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/digitalclock/CMakeLists.txt b/tests/manual/examples/widgets/widgets/digitalclock/CMakeLists.txt new file mode 100644 index 0000000000..04d9c53ed3 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/digitalclock/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(digitalclock LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/digitalclock") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(digitalclock + digitalclock.cpp digitalclock.h + main.cpp +) + +set_target_properties(digitalclock PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(digitalclock PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS digitalclock + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/widgets/digitalclock/digitalclock.cpp b/tests/manual/examples/widgets/widgets/digitalclock/digitalclock.cpp new file mode 100644 index 0000000000..4eec982c25 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/digitalclock/digitalclock.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "digitalclock.h" + +#include <QTime> +#include <QTimer> + +//! [0] +DigitalClock::DigitalClock(QWidget *parent) + : QLCDNumber(parent) +{ + setSegmentStyle(Filled); + + QTimer *timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &DigitalClock::showTime); + timer->start(1000); + + showTime(); + + setWindowTitle(tr("Digital Clock")); + resize(150, 60); +} +//! [0] + +//! [1] +void DigitalClock::showTime() +//! [1] //! [2] +{ + QTime time = QTime::currentTime(); + QString text = time.toString("hh:mm"); + if ((time.second() % 2) == 0) + text[2] = ' '; + display(text); +} +//! [2] diff --git a/tests/manual/examples/widgets/widgets/digitalclock/digitalclock.h b/tests/manual/examples/widgets/widgets/digitalclock/digitalclock.h new file mode 100644 index 0000000000..7b028cb06e --- /dev/null +++ b/tests/manual/examples/widgets/widgets/digitalclock/digitalclock.h @@ -0,0 +1,22 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DIGITALCLOCK_H +#define DIGITALCLOCK_H + +#include <QLCDNumber> + +//! [0] +class DigitalClock : public QLCDNumber +{ + Q_OBJECT + +public: + DigitalClock(QWidget *parent = nullptr); + +private slots: + void showTime(); +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/digitalclock/digitalclock.pro b/tests/manual/examples/widgets/widgets/digitalclock/digitalclock.pro new file mode 100644 index 0000000000..4e4bc0f557 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/digitalclock/digitalclock.pro @@ -0,0 +1,9 @@ +QT += widgets + +HEADERS = digitalclock.h +SOURCES = digitalclock.cpp \ + main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/digitalclock +INSTALLS += target diff --git a/tests/manual/examples/widgets/widgets/digitalclock/main.cpp b/tests/manual/examples/widgets/widgets/digitalclock/main.cpp new file mode 100644 index 0000000000..d930e72f23 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/digitalclock/main.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QApplication> + +#include "digitalclock.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + DigitalClock clock; + clock.show(); + return app.exec(); +} diff --git a/tests/manual/examples/widgets/widgets/icons/CMakeLists.txt b/tests/manual/examples/widgets/widgets/icons/CMakeLists.txt new file mode 100644 index 0000000000..f36e47bef6 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(icons LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/icons") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(icons + iconpreviewarea.cpp iconpreviewarea.h + iconsizespinbox.cpp iconsizespinbox.h + imagedelegate.cpp imagedelegate.h + main.cpp + mainwindow.cpp mainwindow.h +) + +set_target_properties(icons PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_compile_definitions(icons PRIVATE + SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}" +) + +target_link_libraries(icons PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS icons + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/widgets/icons/iconpreviewarea.cpp b/tests/manual/examples/widgets/widgets/icons/iconpreviewarea.cpp new file mode 100644 index 0000000000..42a5fa7914 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/iconpreviewarea.cpp @@ -0,0 +1,130 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "iconpreviewarea.h" + +#include <QGridLayout> +#include <QLabel> +#include <QWindow> + +//! [0] +IconPreviewArea::IconPreviewArea(QWidget *parent) + : QWidget(parent) +{ + QGridLayout *mainLayout = new QGridLayout(this); + + 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); + + 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 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] + +//! [42] +QList<QIcon::Mode> IconPreviewArea::iconModes() +{ + static const QList<QIcon::Mode> result = { QIcon::Normal, QIcon::Active, QIcon::Disabled, + QIcon::Selected }; + return result; +} + +QList<QIcon::State> IconPreviewArea::iconStates() +{ + static const QList<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] + +//! [1] +void IconPreviewArea::setIcon(const QIcon &icon) +{ + this->icon = icon; + updatePixmapLabels(); +} +//! [1] + +//! [2] +void IconPreviewArea::setSize(const QSize &size) +{ + if (size != this->size) { + this->size = size; + updatePixmapLabels(); + } +} +//! [2] + +//! [3] +QLabel *IconPreviewArea::createHeaderLabel(const QString &text) +{ + QLabel *label = new QLabel(tr("<b>%1</b>").arg(text)); + label->setAlignment(Qt::AlignCenter); + return label; +} +//! [3] + +//! [4] +QLabel *IconPreviewArea::createPixmapLabel() +{ + QLabel *label = new QLabel; + label->setEnabled(false); + label->setAlignment(Qt::AlignCenter); + label->setFrameShape(QFrame::Box); + label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + label->setBackgroundRole(QPalette::Base); + label->setAutoFillBackground(true); + label->setMinimumSize(132, 132); + return label; +} +//! [4] + +//! [5] +void IconPreviewArea::updatePixmapLabels() +{ + for (int column = 0; column < NumModes; ++column) { + for (int row = 0; row < NumStates; ++row) { + const QPixmap pixmap = + icon.pixmap(size, devicePixelRatio(), 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.devicePixelRatio()); + } + pixmapLabel->setToolTip(toolTip); + } + } +} +//! [5] diff --git a/tests/manual/examples/widgets/widgets/icons/iconpreviewarea.h b/tests/manual/examples/widgets/widgets/icons/iconpreviewarea.h new file mode 100644 index 0000000000..c59ebc42ba --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/iconpreviewarea.h @@ -0,0 +1,47 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ICONPREVIEWAREA_H +#define ICONPREVIEWAREA_H + +#include <QIcon> +#include <QWidget> +#include <QStringList> +#include <QList> + +QT_BEGIN_NAMESPACE +class QLabel; +QT_END_NAMESPACE + +//! [0] +class IconPreviewArea : public QWidget +{ + Q_OBJECT + +public: + explicit IconPreviewArea(QWidget *parent = nullptr); + + void setIcon(const QIcon &icon); + void setSize(const QSize &size); + + static QList<QIcon::Mode> iconModes(); + static QList<QIcon::State> iconStates(); + static QStringList iconModeNames(); + static QStringList iconStateNames(); + +private: + QLabel *createHeaderLabel(const QString &text); + QLabel *createPixmapLabel(); + void updatePixmapLabels(); + + enum { NumModes = 4, NumStates = 2 }; + + QIcon icon; + QSize size; + QLabel *stateLabels[NumStates]; + QLabel *modeLabels[NumModes]; + QLabel *pixmapLabels[NumModes][NumStates]; +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/icons/icons.pro b/tests/manual/examples/widgets/widgets/icons/icons.pro new file mode 100644 index 0000000000..243ce6b092 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/icons.pro @@ -0,0 +1,20 @@ +QT += widgets +requires(qtConfig(combobox)) + +HEADERS = iconpreviewarea.h \ + iconsizespinbox.h \ + imagedelegate.h \ + mainwindow.h +SOURCES = iconpreviewarea.cpp \ + iconsizespinbox.cpp \ + imagedelegate.cpp \ + main.cpp \ + mainwindow.cpp + +DEFINES += SRCDIR=\\\"$$PWD/\\\" + +EXAMPLE_FILES = images/* + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/icons +INSTALLS += target diff --git a/tests/manual/examples/widgets/widgets/icons/iconsizespinbox.cpp b/tests/manual/examples/widgets/widgets/icons/iconsizespinbox.cpp new file mode 100644 index 0000000000..16c88f4dd0 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/iconsizespinbox.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "iconsizespinbox.h" + +#include <QRegularExpression> + +//! [0] +IconSizeSpinBox::IconSizeSpinBox(QWidget *parent) + : QSpinBox(parent) +{ +} +//! [0] + +//! [1] +int IconSizeSpinBox::valueFromText(const QString &text) const +{ + static const QRegularExpression regExp(tr("(\\d+)(\\s*[xx]\\s*\\d+)?")); + Q_ASSERT(regExp.isValid()); + + const QRegularExpressionMatch match = regExp.match(text); + if (match.isValid()) + return match.captured(1).toInt(); + return 0; +} +//! [1] + +//! [2] +QString IconSizeSpinBox::textFromValue(int value) const +{ + return tr("%1 x %1").arg(value); +} +//! [2] diff --git a/tests/manual/examples/widgets/widgets/icons/iconsizespinbox.h b/tests/manual/examples/widgets/widgets/icons/iconsizespinbox.h new file mode 100644 index 0000000000..ac304b4794 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/iconsizespinbox.h @@ -0,0 +1,22 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef ICONSIZESPINBOX_H +#define ICONSIZESPINBOX_H + +#include <QSpinBox> + +//! [0] +class IconSizeSpinBox : public QSpinBox +{ + Q_OBJECT + +public: + explicit IconSizeSpinBox(QWidget *parent = nullptr); + + int valueFromText(const QString &text) const override; + QString textFromValue(int value) const override; +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/icons/imagedelegate.cpp b/tests/manual/examples/widgets/widgets/icons/imagedelegate.cpp new file mode 100644 index 0000000000..ec3c227c71 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/imagedelegate.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "imagedelegate.h" +#include "iconpreviewarea.h" + +#include <QComboBox> + +//! [0] +ImageDelegate::ImageDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{} +//! [0] + +//! [1] +QWidget *ImageDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem & /* option */, + const QModelIndex &index) const +{ + QComboBox *comboBox = new QComboBox(parent); + if (index.column() == 1) + comboBox->addItems(IconPreviewArea::iconModeNames()); + else if (index.column() == 2) + comboBox->addItems(IconPreviewArea::iconStateNames()); + + connect(comboBox, &QComboBox::activated, + this, &ImageDelegate::emitCommitData); + + return comboBox; +} +//! [1] + +//! [2] +void ImageDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const +{ + QComboBox *comboBox = qobject_cast<QComboBox *>(editor); + if (!comboBox) + return; + + int pos = comboBox->findText(index.model()->data(index).toString(), + Qt::MatchExactly); + comboBox->setCurrentIndex(pos); +} +//! [2] + +//! [3] +void ImageDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + QComboBox *comboBox = qobject_cast<QComboBox *>(editor); + if (!comboBox) + return; + + model->setData(index, comboBox->currentText()); +} +//! [3] + +//! [4] +void ImageDelegate::emitCommitData() +{ + emit commitData(qobject_cast<QWidget *>(sender())); +} +//! [4] diff --git a/tests/manual/examples/widgets/widgets/icons/imagedelegate.h b/tests/manual/examples/widgets/widgets/icons/imagedelegate.h new file mode 100644 index 0000000000..29707e68c6 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/imagedelegate.h @@ -0,0 +1,31 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef IMAGEDELEGATE_H +#define IMAGEDELEGATE_H + +#include <QStyledItemDelegate> + +//! [0] +class ImageDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit ImageDelegate(QObject *parent = nullptr); +//! [0] + +//! [1] + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const override; + void setEditorData(QWidget *editor, const QModelIndex &index) const override; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const override; + +//! [1] //! [2] +private slots: + void emitCommitData(); +//! [2] +}; + +#endif diff --git a/tests/manual/examples/widgets/widgets/icons/images/designer.png b/tests/manual/examples/widgets/widgets/icons/images/designer.png Binary files differnew file mode 100644 index 0000000000..9f8578b49e --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/designer.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/find_disabled.png b/tests/manual/examples/widgets/widgets/icons/images/find_disabled.png Binary files differnew file mode 100644 index 0000000000..e85e33fe05 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/find_disabled.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/find_normal.png b/tests/manual/examples/widgets/widgets/icons/images/find_normal.png Binary files differnew file mode 100644 index 0000000000..728c27f905 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/find_normal.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/monkey_off_128x128.png b/tests/manual/examples/widgets/widgets/icons/images/monkey_off_128x128.png Binary files differnew file mode 100644 index 0000000000..f878267287 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/monkey_off_128x128.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/monkey_off_16x16.png b/tests/manual/examples/widgets/widgets/icons/images/monkey_off_16x16.png Binary files differnew file mode 100644 index 0000000000..0ac57d7d4f --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/monkey_off_16x16.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/monkey_off_32x32.png b/tests/manual/examples/widgets/widgets/icons/images/monkey_off_32x32.png Binary files differnew file mode 100644 index 0000000000..1f7fab694c --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/monkey_off_32x32.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/monkey_off_64x64.png b/tests/manual/examples/widgets/widgets/icons/images/monkey_off_64x64.png Binary files differnew file mode 100644 index 0000000000..47d8f6de35 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/monkey_off_64x64.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/monkey_on_128x128.png b/tests/manual/examples/widgets/widgets/icons/images/monkey_on_128x128.png Binary files differnew file mode 100644 index 0000000000..8e1c7468bf --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/monkey_on_128x128.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/monkey_on_16x16.png b/tests/manual/examples/widgets/widgets/icons/images/monkey_on_16x16.png Binary files differnew file mode 100644 index 0000000000..082e8527f1 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/monkey_on_16x16.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/monkey_on_32x32.png b/tests/manual/examples/widgets/widgets/icons/images/monkey_on_32x32.png Binary files differnew file mode 100644 index 0000000000..bf9acc6cae --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/monkey_on_32x32.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/monkey_on_64x64.png b/tests/manual/examples/widgets/widgets/icons/images/monkey_on_64x64.png Binary files differnew file mode 100644 index 0000000000..990f604d98 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/monkey_on_64x64.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/qt_extended_16x16.png b/tests/manual/examples/widgets/widgets/icons/images/qt_extended_16x16.png Binary files differnew file mode 100644 index 0000000000..30bcb45ed2 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/qt_extended_16x16.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/qt_extended_32x32.png b/tests/manual/examples/widgets/widgets/icons/images/qt_extended_32x32.png Binary files differnew file mode 100644 index 0000000000..d609c1e1e5 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/qt_extended_32x32.png diff --git a/tests/manual/examples/widgets/widgets/icons/images/qt_extended_48x48.png b/tests/manual/examples/widgets/widgets/icons/images/qt_extended_48x48.png Binary files differnew file mode 100644 index 0000000000..0e524fed5f --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/images/qt_extended_48x48.png diff --git a/tests/manual/examples/widgets/widgets/icons/main.cpp b/tests/manual/examples/widgets/widgets/icons/main.cpp new file mode 100644 index 0000000000..b7ed18ff94 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/main.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QApplication> +#include <QCommandLineParser> +#include <QScreen> + +#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(); + commandLineParser.addPositionalArgument(MainWindow::tr("[file]"), MainWindow::tr("Icon file(s) to open.")); + commandLineParser.process(QCoreApplication::arguments()); + + MainWindow mainWin; + if (!commandLineParser.positionalArguments().isEmpty()) + mainWin.loadImages(commandLineParser.positionalArguments()); + + const QRect availableGeometry = mainWin.screen()->availableGeometry(); + 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/tests/manual/examples/widgets/widgets/icons/mainwindow.cpp b/tests/manual/examples/widgets/widgets/icons/mainwindow.cpp new file mode 100644 index 0000000000..f893575f76 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/mainwindow.cpp @@ -0,0 +1,478 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "mainwindow.h" +#include "iconpreviewarea.h" +#include "iconsizespinbox.h" +#include "imagedelegate.h" + +#include <QActionGroup> +#include <QApplication> +#include <QButtonGroup> +#include <QCheckBox> +#include <QFileDialog> +#include <QHeaderView> +#include <QFormLayout> +#include <QGridLayout> +#include <QGroupBox> +#include <QImageReader> +#include <QLabel> +#include <QMenuBar> +#include <QMessageBox> +#include <QRadioButton> +#include <QScreen> +#include <QStandardPaths> +#include <QStyleFactory> +#include <QTableWidget> +#include <QWindow> + +//! [40] +enum { OtherSize = QStyle::PM_CustomBase }; +//! [40] + +//! [0] +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + 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(); +} +//! [0] + +//! [44] +void MainWindow::show() +{ + QMainWindow::show(); + connect(windowHandle(), &QWindow::screenChanged, this, &MainWindow::screenChanged); + screenChanged(); +} +//! [44] + +//! [1] +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.")); +} +//! [1] + +//! [2] +void MainWindow::changeStyle(bool checked) +{ + if (!checked) + return; + + const QAction *action = qobject_cast<QAction *>(sender()); +//! [2] //! [3] + QStyle *style = QStyleFactory::create(action->data().toString()); +//! [3] //! [4] + Q_ASSERT(style); + QApplication::setStyle(style); + + const QList<QAbstractButton*> buttons = sizeButtonGroup->buttons(); + for (QAbstractButton *button : 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(QAbstractButton *button, bool checked) +{ + if (!checked) + return; + + const int index = sizeButtonGroup->id(button); + const bool other = index == int(OtherSize); + const int extent = other + ? otherSpinBox->value() + : QApplication::style()->pixelMetric(static_cast<QStyle::PixelMetric>(index)); + + previewArea->setSize(QSize(extent, extent)); + otherSpinBox->setEnabled(other); +} + +void MainWindow::triggerChangeSize() +{ + changeSize(sizeButtonGroup->checkedButton(), true); +} +//! [5] + +//! [6] +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); +//! [6] + +//! [8] + const QString fileName = fileItem->data(Qt::UserRole).toString(); + QImage image(fileName); + if (!image.isNull()) + icon.addPixmap(QPixmap::fromImage(image), mode, state); +//! [8] + } + } +//! [11] + previewArea->setIcon(icon); +//! [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(const QString &directory) +{ + QFileDialog fileDialog(this, tr("Open Images"), directory); + QStringList mimeTypeFilters; + const QList<QByteArray> mimeTypes = QImageReader::supportedMimeTypes(); + for (const QByteArray &mimeTypeName : mimeTypes) + 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) +{ + for (const QString &fileName : fileNames) { + const int row = imagesTable->rowCount(); + imagesTable->setRowCount(row + 1); +//! [13] + 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); +//! [13] + +//! [15] + 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; +//! [15] + } + +//! [18] + 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); +//! [18] + } +} + +//! [20] +void MainWindow::removeAllImages() +{ + imagesTable->setRowCount(0); + changeIcon(); +} +//! [20] + +//! [21] +QWidget *MainWindow::createImagesGroupBox() +{ + QGroupBox *imagesGroupBox = new QGroupBox(tr("Images")); + + imagesTable = new QTableWidget; + imagesTable->setSelectionMode(QAbstractItemView::NoSelection); + imagesTable->setItemDelegate(new ImageDelegate(this)); +//! [21] + +//! [22] + const QStringList 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(); +//! [22] + +//! [24] + connect(imagesTable, &QTableWidget::itemChanged, + this, &MainWindow::changeIcon); + + QVBoxLayout *layout = new QVBoxLayout(imagesGroupBox); + layout->addWidget(imagesTable); + return imagesGroupBox; +//! [24] +} + +//! [26] +QWidget *MainWindow::createIconSizeGroupBox() +{ + QGroupBox *iconSizeGroupBox = new QGroupBox(tr("Icon Size")); + + sizeButtonGroup = new QButtonGroup(this); + sizeButtonGroup->setExclusive(true); + + connect(sizeButtonGroup, &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); +//! [26] + +//! [27] + connect(otherSpinBox, &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; +//! [27] +} + +void MainWindow::screenChanged() +{ + devicePixelRatioLabel->setText(QString::number(devicePixelRatio())); + 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); + return highDpiGroupBox; +} + +//! [28] +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"), qApp, &QCoreApplication::quit); + exitAct->setShortcuts(QKeySequence::Quit); + + QMenu *viewMenu = menuBar()->addMenu(tr("&View")); + + styleActionGroup = new QActionGroup(this); + const QStringList styleKeys = QStyleFactory::keys(); + for (const QString &styleName : styleKeys) { + 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); +} +//! [28] + +//! [30] +void MainWindow::createContextMenu() +{ + imagesTable->setContextMenuPolicy(Qt::ActionsContextMenu); + imagesTable->addAction(addSampleImagesAct); + imagesTable->addAction(addOtherImagesAct); + imagesTable->addAction(removeAllImagesAct); +} +//! [30] + +//! [31] +void MainWindow::checkCurrentStyle() +{ + const QList<QAction *> actions = styleActionGroup->actions(); + for (QAction *action : actions) { + const QString styleName = action->data().toString(); + const std::unique_ptr<QStyle> candidate{QStyleFactory::create(styleName)}; + Q_ASSERT(candidate); + if (candidate->metaObject()->className() + == QApplication::style()->metaObject()->className()) { + action->trigger(); + return; + } + } +} +//! [31] diff --git a/tests/manual/examples/widgets/widgets/icons/mainwindow.h b/tests/manual/examples/widgets/widgets/icons/mainwindow.h new file mode 100644 index 0000000000..fb6e0493f7 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/icons/mainwindow.h @@ -0,0 +1,74 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QIcon> +#include <QList> +#include <QMainWindow> +#include <QPixmap> + +QT_BEGIN_NAMESPACE +class QAction; +class QActionGroup; +class QLabel; +class QButtonGroup; +class QTableWidget; +class QAbstractButton; +QT_END_NAMESPACE +class IconPreviewArea; +class IconSizeSpinBox; + +//! [0] +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + + void loadImages(const QStringList &fileNames); + + void show(); + +private slots: + void about(); + void changeStyle(bool checked); + void changeSize(QAbstractButton *button, bool); + void triggerChangeSize(); + void changeIcon(); + void addSampleImages(); + void addOtherImages(); + void removeAllImages(); + void screenChanged(); + +private: + QWidget *createImagesGroupBox(); + QWidget *createIconSizeGroupBox(); + QWidget *createHighDpiIconSizeGroupBox(); + void createActions(); + void createContextMenu(); + void checkCurrentStyle(); + void addImages(const QString &directory); + + IconPreviewArea *previewArea; + + QTableWidget *imagesTable; + + QButtonGroup *sizeButtonGroup; + IconSizeSpinBox *otherSpinBox; + + QLabel *devicePixelRatioLabel; + QLabel *screenNameLabel; + + QAction *addOtherImagesAct; + QAction *addSampleImagesAct; + QAction *removeAllImagesAct; + QAction *guessModeStateAct; + QAction *nativeFileDialogAct; + QActionGroup *styleActionGroup; +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/imageviewer/CMakeLists.txt b/tests/manual/examples/widgets/widgets/imageviewer/CMakeLists.txt new file mode 100644 index 0000000000..fd2f051210 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/imageviewer/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(imageviewer LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/imageviewer") + +find_package(Qt6 + REQUIRED COMPONENTS Core Gui Widgets + OPTIONAL_COMPONENTS PrintSupport +) + +qt_standard_project_setup() + +qt_add_executable(imageviewer + imageviewer.cpp imageviewer.h + main.cpp +) + +set_target_properties(imageviewer PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(imageviewer PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +if (TARGET Qt6::PrintSupport) + target_link_libraries(imageviewer PRIVATE Qt6::PrintSupport) +endif() + +install(TARGETS imageviewer + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/widgets/imageviewer/imageviewer.cpp b/tests/manual/examples/widgets/widgets/imageviewer/imageviewer.cpp new file mode 100644 index 0000000000..72a93dbf1b --- /dev/null +++ b/tests/manual/examples/widgets/widgets/imageviewer/imageviewer.cpp @@ -0,0 +1,364 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "imageviewer.h" + +#include <QApplication> +#include <QClipboard> +#include <QColorSpace> +#include <QDir> +#include <QFileDialog> +#include <QImageReader> +#include <QImageWriter> +#include <QLabel> +#include <QMenuBar> +#include <QMessageBox> +#include <QMimeData> +#include <QPainter> +#include <QScreen> +#include <QScrollArea> +#include <QScrollBar> +#include <QStandardPaths> +#include <QStatusBar> + +#if defined(QT_PRINTSUPPORT_LIB) +# include <QtPrintSupport/qtprintsupportglobal.h> + +# if QT_CONFIG(printdialog) +# include <QPrintDialog> +# endif +#endif + +//! [0] +ImageViewer::ImageViewer(QWidget *parent) + : QMainWindow(parent), imageLabel(new QLabel) + , scrollArea(new QScrollArea) +{ + imageLabel->setBackgroundRole(QPalette::Base); + imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); + imageLabel->setScaledContents(true); + + scrollArea->setBackgroundRole(QPalette::Dark); + scrollArea->setWidget(imageLabel); + scrollArea->setVisible(false); + setCentralWidget(scrollArea); + + createActions(); + + resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5); +} + +//! [0] +//! [2] + +bool ImageViewer::loadFile(const QString &fileName) +{ + QImageReader reader(fileName); + reader.setAutoTransform(true); + const QImage newImage = reader.read(); + if (newImage.isNull()) { + QMessageBox::information(this, QGuiApplication::applicationDisplayName(), + tr("Cannot load %1: %2") + .arg(QDir::toNativeSeparators(fileName), reader.errorString())); + return false; + } +//! [2] + + setImage(newImage); + + setWindowFilePath(fileName); + + const QString description = image.colorSpace().isValid() + ? image.colorSpace().description() : tr("unknown"); + const QString message = tr("Opened \"%1\", %2x%3, Depth: %4 (%5)") + .arg(QDir::toNativeSeparators(fileName)).arg(image.width()).arg(image.height()) + .arg(image.depth()).arg(description); + statusBar()->showMessage(message); + return true; +} + +void ImageViewer::setImage(const QImage &newImage) +{ + if (newImage.colorSpace().isValid()) + image = newImage.convertedToColorSpace(QColorSpace::SRgb); + else + image = newImage; + imageLabel->setPixmap(QPixmap::fromImage(image, Qt::NoFormatConversion)); +//! [4] + scaleFactor = 1.0; + + scrollArea->setVisible(true); + printAct->setEnabled(true); + fitToWindowAct->setEnabled(true); + updateActions(); + + if (!fitToWindowAct->isChecked()) + imageLabel->adjustSize(); +} + +//! [4] + +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] + +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; + const QByteArrayList supportedMimeTypes = acceptMode == QFileDialog::AcceptOpen + ? QImageReader::supportedMimeTypes() : QImageWriter::supportedMimeTypes(); + for (const QByteArray &mimeTypeName : supportedMimeTypes) + mimeTypeFilters.append(mimeTypeName); + mimeTypeFilters.sort(); + dialog.setMimeTypeFilters(mimeTypeFilters); + dialog.selectMimeTypeFilter("image/jpeg"); + dialog.setAcceptMode(acceptMode); + 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().constFirst())) {} +} +//! [1] + +void ImageViewer::saveAs() +{ + QFileDialog dialog(this, tr("Save File As")); + initializeImageFileDialog(dialog, QFileDialog::AcceptSave); + + while (dialog.exec() == QDialog::Accepted && !saveFile(dialog.selectedFiles().constFirst())) {} +} + +//! [5] +void ImageViewer::print() +//! [5] //! [6] +{ + Q_ASSERT(!imageLabel->pixmap().isNull()); +#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog) +//! [6] //! [7] + QPrintDialog dialog(&printer, this); +//! [7] //! [8] + if (dialog.exec()) { + QPainter painter(&printer); + QPixmap pixmap = imageLabel->pixmap(); + QRect rect = painter.viewport(); + QSize size = pixmap.size(); + size.scale(rect.size(), Qt::KeepAspectRatio); + painter.setViewport(rect.x(), rect.y(), size.width(), size.height()); + painter.setWindow(pixmap.rect()); + painter.drawPixmap(0, 0, pixmap); + } +#endif +} +//! [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] +{ + scaleImage(1.25); +} + +void ImageViewer::zoomOut() +{ + scaleImage(0.8); +} + +//! [10] //! [11] +void ImageViewer::normalSize() +//! [11] //! [12] +{ + imageLabel->adjustSize(); + scaleFactor = 1.0; +} +//! [12] + +//! [13] +void ImageViewer::fitToWindow() +//! [13] //! [14] +{ + bool fitToWindow = fitToWindowAct->isChecked(); + scrollArea->setWidgetResizable(fitToWindow); + if (!fitToWindow) + normalSize(); + updateActions(); +} +//! [14] + + +//! [15] +void ImageViewer::about() +//! [15] //! [16] +{ + QMessageBox::about(this, tr("About Image Viewer"), + tr("<p>The <b>Image Viewer</b> example shows how to combine QLabel " + "and QScrollArea to display an image. QLabel is typically used " + "for displaying a text, but it can also display an image. " + "QScrollArea provides a scrolling view around another widget. " + "If the child widget exceeds the size of the frame, QScrollArea " + "automatically provides scroll bars. </p><p>The example " + "demonstrates how QLabel's ability to scale its contents " + "(QLabel::scaledContents), and QScrollArea's ability to " + "automatically resize its contents " + "(QScrollArea::widgetResizable), can be used to implement " + "zooming and scaling features. </p><p>In addition the example " + "shows how to use QPainter to print an image.</p>")); +} +//! [16] + +//! [17] +void ImageViewer::createActions() +//! [17] //! [18] +{ + 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 = fileMenu->addAction(tr("&Print..."), this, &ImageViewer::print); + printAct->setShortcut(QKeySequence::Print); + printAct->setEnabled(false); + + fileMenu->addSeparator(); + + QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close); + exitAct->setShortcut(tr("Ctrl+Q")); + + 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); + + zoomOutAct = viewMenu->addAction(tr("Zoom &Out (25%)"), this, &ImageViewer::zoomOut); + zoomOutAct->setShortcut(QKeySequence::ZoomOut); + zoomOutAct->setEnabled(false); + + normalSizeAct = viewMenu->addAction(tr("&Normal Size"), this, &ImageViewer::normalSize); + normalSizeAct->setShortcut(tr("Ctrl+S")); + normalSizeAct->setEnabled(false); + + viewMenu->addSeparator(); + + fitToWindowAct = viewMenu->addAction(tr("&Fit to Window"), this, &ImageViewer::fitToWindow); + fitToWindowAct->setEnabled(false); + fitToWindowAct->setCheckable(true); + fitToWindowAct->setShortcut(tr("Ctrl+F")); + + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + + helpMenu->addAction(tr("&About"), this, &ImageViewer::about); + helpMenu->addAction(tr("About &Qt"), this, &QApplication::aboutQt); +} +//! [18] + +//! [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()); +} +//! [22] + +//! [23] +void ImageViewer::scaleImage(double factor) +//! [23] //! [24] +{ + scaleFactor *= factor; + imageLabel->resize(scaleFactor * imageLabel->pixmap().size()); + + adjustScrollBar(scrollArea->horizontalScrollBar(), factor); + adjustScrollBar(scrollArea->verticalScrollBar(), factor); + + zoomInAct->setEnabled(scaleFactor < 3.0); + zoomOutAct->setEnabled(scaleFactor > 0.333); +} +//! [24] + +//! [25] +void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor) +//! [25] //! [26] +{ + scrollBar->setValue(int(factor * scrollBar->value() + + ((factor - 1) * scrollBar->pageStep()/2))); +} +//! [26] diff --git a/tests/manual/examples/widgets/widgets/imageviewer/imageviewer.h b/tests/manual/examples/widgets/widgets/imageviewer/imageviewer.h new file mode 100644 index 0000000000..e9e6858c74 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/imageviewer/imageviewer.h @@ -0,0 +1,74 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef IMAGEVIEWER_H +#define IMAGEVIEWER_H + +#include <QMainWindow> +#include <QImage> +#if defined(QT_PRINTSUPPORT_LIB) +# include <QtPrintSupport/qtprintsupportglobal.h> + +# if QT_CONFIG(printer) +# include <QPrinter> +# endif +#endif + +QT_BEGIN_NAMESPACE +class QAction; +class QLabel; +class QMenu; +class QScrollArea; +class QScrollBar; +QT_END_NAMESPACE + +//! [0] +class ImageViewer : public QMainWindow +{ + Q_OBJECT + +public: + ImageViewer(QWidget *parent = nullptr); + bool loadFile(const QString &); + +private slots: + void open(); + void saveAs(); + void print(); + void copy(); + void paste(); + void zoomIn(); + void zoomOut(); + void normalSize(); + void fitToWindow(); + void about(); + +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 = 1; + +#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer) + QPrinter printer; +#endif + + QAction *saveAsAct; + QAction *printAct; + QAction *copyAct; + QAction *zoomInAct; + QAction *zoomOutAct; + QAction *normalSizeAct; + QAction *fitToWindowAct; +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/imageviewer/imageviewer.pro b/tests/manual/examples/widgets/widgets/imageviewer/imageviewer.pro new file mode 100644 index 0000000000..d3db63ec20 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/imageviewer/imageviewer.pro @@ -0,0 +1,11 @@ +QT += widgets +requires(qtConfig(filedialog)) +qtHaveModule(printsupport): QT += printsupport + +HEADERS = imageviewer.h +SOURCES = imageviewer.cpp \ + main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/imageviewer +INSTALLS += target diff --git a/tests/manual/examples/widgets/widgets/imageviewer/main.cpp b/tests/manual/examples/widgets/widgets/imageviewer/main.cpp new file mode 100644 index 0000000000..013f7d8689 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/imageviewer/main.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QApplication> +#include <QCommandLineParser> + +#include "imageviewer.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + QGuiApplication::setApplicationDisplayName(ImageViewer::tr("Image Viewer")); + QCommandLineParser commandLineParser; + commandLineParser.addHelpOption(); + commandLineParser.addPositionalArgument(ImageViewer::tr("[file]"), ImageViewer::tr("Image file to open.")); + commandLineParser.process(QCoreApplication::arguments()); + ImageViewer imageViewer; + if (!commandLineParser.positionalArguments().isEmpty() + && !imageViewer.loadFile(commandLineParser.positionalArguments().constFirst())) { + return -1; + } + imageViewer.show(); + return app.exec(); +} diff --git a/tests/manual/examples/widgets/widgets/movie/CMakeLists.txt b/tests/manual/examples/widgets/widgets/movie/CMakeLists.txt new file mode 100644 index 0000000000..49b766a11d --- /dev/null +++ b/tests/manual/examples/widgets/widgets/movie/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(movie LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/movie") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(movie + main.cpp + movieplayer.cpp movieplayer.h +) + +set_target_properties(movie PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(movie PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS movie + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/widgets/movie/animation.gif b/tests/manual/examples/widgets/widgets/movie/animation.gif Binary files differnew file mode 100644 index 0000000000..f674369efc --- /dev/null +++ b/tests/manual/examples/widgets/widgets/movie/animation.gif diff --git a/tests/manual/examples/widgets/widgets/movie/main.cpp b/tests/manual/examples/widgets/widgets/movie/main.cpp new file mode 100644 index 0000000000..e5d4d3f040 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/movie/main.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QApplication> + +#include "movieplayer.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MoviePlayer player; + player.show(); + player.show(); + return app.exec(); +} diff --git a/tests/manual/examples/widgets/widgets/movie/movie.pro b/tests/manual/examples/widgets/widgets/movie/movie.pro new file mode 100644 index 0000000000..f9f89109e4 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/movie/movie.pro @@ -0,0 +1,12 @@ +QT += widgets +requires(qtConfig(filedialog)) + +HEADERS = movieplayer.h +SOURCES = main.cpp \ + movieplayer.cpp + +EXAMPLE_FILES = animation.gif + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/movie +INSTALLS += target diff --git a/tests/manual/examples/widgets/widgets/movie/movieplayer.cpp b/tests/manual/examples/widgets/widgets/movie/movieplayer.cpp new file mode 100644 index 0000000000..6f6ec14bb1 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/movie/movieplayer.cpp @@ -0,0 +1,180 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "movieplayer.h" + +#include <QCheckBox> +#include <QFileDialog> +#include <QLabel> +#include <QMovie> +#include <QSlider> +#include <QSpinBox> +#include <QStyle> +#include <QToolButton> +#include <QVBoxLayout> + +MoviePlayer::MoviePlayer(QWidget *parent) + : QWidget(parent) +{ + movie = new QMovie(this); + movie->setCacheMode(QMovie::CacheAll); + + movieLabel = new QLabel(tr("No movie loaded")); + movieLabel->setAlignment(Qt::AlignCenter); + movieLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); + movieLabel->setBackgroundRole(QPalette::Dark); + movieLabel->setAutoFillBackground(true); + + currentMovieDirectory = "movies"; + + createControls(); + createButtons(); + + connect(movie, &QMovie::frameChanged, this, &MoviePlayer::updateFrameSlider); + connect(movie, &QMovie::stateChanged, this, &MoviePlayer::updateButtons); + connect(fitCheckBox, &QCheckBox::clicked, this, &MoviePlayer::fitToWindow); + connect(frameSlider, &QSlider::valueChanged, this, &MoviePlayer::goToFrame); + connect(speedSpinBox, &QSpinBox::valueChanged, + movie, &QMovie::setSpeed); + + mainLayout = new QVBoxLayout; + mainLayout->addWidget(movieLabel); + mainLayout->addLayout(controlsLayout); + mainLayout->addLayout(buttonsLayout); + setLayout(mainLayout); + + updateFrameSlider(); + updateButtons(); + + setWindowTitle(tr("Movie Player")); + resize(400, 400); +} + +void MoviePlayer::open() +{ + QString fileName = QFileDialog::getOpenFileName(this, tr("Open a Movie"), + currentMovieDirectory); + if (!fileName.isEmpty()) + openFile(fileName); +} + +void MoviePlayer::openFile(const QString &fileName) +{ + currentMovieDirectory = QFileInfo(fileName).path(); + + movie->stop(); + movieLabel->setMovie(movie); + movie->setFileName(fileName); + movie->start(); + + updateFrameSlider(); + updateButtons(); +} + +void MoviePlayer::goToFrame(int frame) +{ + movie->jumpToFrame(frame); +} + +void MoviePlayer::fitToWindow() +{ + movieLabel->setScaledContents(fitCheckBox->isChecked()); +} + +void MoviePlayer::updateFrameSlider() +{ + bool hasFrames = (movie->currentFrameNumber() >= 0); + + if (hasFrames) { + if (movie->frameCount() > 0) { + frameSlider->setMaximum(movie->frameCount() - 1); + } else { + if (movie->currentFrameNumber() > frameSlider->maximum()) + frameSlider->setMaximum(movie->currentFrameNumber()); + } + frameSlider->setValue(movie->currentFrameNumber()); + } else { + frameSlider->setMaximum(0); + } + frameLabel->setEnabled(hasFrames); + frameSlider->setEnabled(hasFrames); +} + +void MoviePlayer::updateButtons() +{ + playButton->setEnabled(movie->isValid() && movie->frameCount() != 1 + && movie->state() == QMovie::NotRunning); + pauseButton->setEnabled(movie->state() != QMovie::NotRunning); + pauseButton->setChecked(movie->state() == QMovie::Paused); + stopButton->setEnabled(movie->state() != QMovie::NotRunning); +} + +void MoviePlayer::createControls() +{ + fitCheckBox = new QCheckBox(tr("Fit to Window")); + + frameLabel = new QLabel(tr("Current frame:")); + + frameSlider = new QSlider(Qt::Horizontal); + frameSlider->setTickPosition(QSlider::TicksBelow); + frameSlider->setTickInterval(10); + + speedLabel = new QLabel(tr("Speed:")); + + speedSpinBox = new QSpinBox; + speedSpinBox->setRange(1, 9999); + speedSpinBox->setValue(100); + speedSpinBox->setSuffix(tr("%")); + + controlsLayout = new QGridLayout; + controlsLayout->addWidget(fitCheckBox, 0, 0, 1, 2); + controlsLayout->addWidget(frameLabel, 1, 0); + controlsLayout->addWidget(frameSlider, 1, 1, 1, 2); + controlsLayout->addWidget(speedLabel, 2, 0); + controlsLayout->addWidget(speedSpinBox, 2, 1); +} + +void MoviePlayer::createButtons() +{ + QSize iconSize(36, 36); + + openButton = new QToolButton; + openButton->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton)); + openButton->setIconSize(iconSize); + openButton->setToolTip(tr("Open File")); + connect(openButton, &QToolButton::clicked, this, &MoviePlayer::open); + + playButton = new QToolButton; + playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + playButton->setIconSize(iconSize); + playButton->setToolTip(tr("Play")); + connect(playButton, &QToolButton::clicked, movie, &QMovie::start); + + pauseButton = new QToolButton; + pauseButton->setCheckable(true); + pauseButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); + pauseButton->setIconSize(iconSize); + pauseButton->setToolTip(tr("Pause")); + connect(pauseButton, &QToolButton::clicked, movie, &QMovie::setPaused); + + stopButton = new QToolButton; + stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop)); + stopButton->setIconSize(iconSize); + stopButton->setToolTip(tr("Stop")); + connect(stopButton, &QToolButton::clicked, movie, &QMovie::stop); + + quitButton = new QToolButton; + quitButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton)); + quitButton->setIconSize(iconSize); + quitButton->setToolTip(tr("Quit")); + connect(quitButton, &QToolButton::clicked, this, &MoviePlayer::close); + + buttonsLayout = new QHBoxLayout; + buttonsLayout->addStretch(); + buttonsLayout->addWidget(openButton); + buttonsLayout->addWidget(playButton); + buttonsLayout->addWidget(pauseButton); + buttonsLayout->addWidget(stopButton); + buttonsLayout->addWidget(quitButton); + buttonsLayout->addStretch(); +} diff --git a/tests/manual/examples/widgets/widgets/movie/movieplayer.h b/tests/manual/examples/widgets/widgets/movie/movieplayer.h new file mode 100644 index 0000000000..362fd50535 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/movie/movieplayer.h @@ -0,0 +1,59 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef MOVIEPLAYER_H +#define MOVIEPLAYER_H + +#include <QWidget> + +QT_BEGIN_NAMESPACE +class QCheckBox; +class QGridLayout; +class QHBoxLayout; +class QLabel; +class QMovie; +class QSlider; +class QSpinBox; +class QToolButton; +class QVBoxLayout; +QT_END_NAMESPACE + +class MoviePlayer : public QWidget +{ + Q_OBJECT + +public: + MoviePlayer(QWidget *parent = nullptr); + void openFile(const QString &fileName); + +private slots: + void open(); + void goToFrame(int frame); + void fitToWindow(); + void updateButtons(); + void updateFrameSlider(); + +private: + void createControls(); + void createButtons(); + + QString currentMovieDirectory; + QLabel *movieLabel; + QMovie *movie; + QToolButton *openButton; + QToolButton *playButton; + QToolButton *pauseButton; + QToolButton *stopButton; + QToolButton *quitButton; + QCheckBox *fitCheckBox; + QSlider *frameSlider; + QSpinBox *speedSpinBox; + QLabel *frameLabel; + QLabel *speedLabel; + + QGridLayout *controlsLayout; + QHBoxLayout *buttonsLayout; + QVBoxLayout *mainLayout; +}; + +#endif diff --git a/tests/manual/examples/widgets/widgets/styles/CMakeLists.txt b/tests/manual/examples/widgets/widgets/styles/CMakeLists.txt new file mode 100644 index 0000000000..ff1d64b9d9 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(styles LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/styles") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(styles + main.cpp + norwegianwoodstyle.cpp norwegianwoodstyle.h + widgetgallery.cpp widgetgallery.h +) + +set_target_properties(styles PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(styles PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +# Resources: +set(styles_resource_files + "images/woodbackground.png" + "images/woodbutton.png" +) + +qt_add_resources(styles "styles" + PREFIX + "/" + FILES + ${styles_resource_files} +) + +install(TARGETS styles + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/widgets/styles/images/woodbackground.png b/tests/manual/examples/widgets/widgets/styles/images/woodbackground.png Binary files differnew file mode 100644 index 0000000000..8be3366bb4 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/images/woodbackground.png diff --git a/tests/manual/examples/widgets/widgets/styles/images/woodbutton.png b/tests/manual/examples/widgets/widgets/styles/images/woodbutton.png Binary files differnew file mode 100644 index 0000000000..adb59ef633 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/images/woodbutton.png diff --git a/tests/manual/examples/widgets/widgets/styles/main.cpp b/tests/manual/examples/widgets/widgets/styles/main.cpp new file mode 100644 index 0000000000..5c33895ea4 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/main.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QApplication> + +#include "norwegianwoodstyle.h" +#include "widgetgallery.h" + +int main(int argc, char *argv[]) +{ + QApplication::setStyle(new NorwegianWoodStyle); + + QApplication app(argc, argv); + WidgetGallery gallery; + gallery.show(); + return app.exec(); +} diff --git a/tests/manual/examples/widgets/widgets/styles/norwegianwoodstyle.cpp b/tests/manual/examples/widgets/widgets/styles/norwegianwoodstyle.cpp new file mode 100644 index 0000000000..a8969dfd54 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/norwegianwoodstyle.cpp @@ -0,0 +1,310 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "norwegianwoodstyle.h" + +#include <QComboBox> +#include <QPainter> +#include <QPainterPath> +#include <QPushButton> +#include <QStyleFactory> + +NorwegianWoodStyle::NorwegianWoodStyle() : + QProxyStyle(QStyleFactory::create("windows")) +{ + setObjectName("NorwegianWood"); +} + +//! [0] +QPalette NorwegianWoodStyle::standardPalette() const +{ + if (!m_standardPalette.isBrushSet(QPalette::Disabled, QPalette::Mid)) { + QColor brown(212, 140, 95); + QColor beige(236, 182, 120); + QColor slightlyOpaqueBlack(0, 0, 0, 63); + + QImage backgroundImage(":/images/woodbackground.png"); + QImage buttonImage(":/images/woodbutton.png"); + QImage midImage = buttonImage.convertToFormat(QImage::Format_RGB32); + + QPainter painter; + painter.begin(&midImage); + painter.setPen(Qt::NoPen); + painter.fillRect(midImage.rect(), slightlyOpaqueBlack); + painter.end(); + //! [0] + + //! [1] + QPalette palette(brown); + + palette.setBrush(QPalette::BrightText, Qt::white); + palette.setBrush(QPalette::Base, beige); + palette.setBrush(QPalette::Highlight, Qt::darkGreen); + setTexture(palette, QPalette::Button, buttonImage); + setTexture(palette, QPalette::Mid, midImage); + setTexture(palette, QPalette::Window, backgroundImage); + + QBrush brush = palette.window(); + brush.setColor(brush.color().darker()); + + palette.setBrush(QPalette::Disabled, QPalette::WindowText, brush); + palette.setBrush(QPalette::Disabled, QPalette::Text, brush); + palette.setBrush(QPalette::Disabled, QPalette::ButtonText, brush); + palette.setBrush(QPalette::Disabled, QPalette::Base, brush); + palette.setBrush(QPalette::Disabled, QPalette::Button, brush); + palette.setBrush(QPalette::Disabled, QPalette::Mid, brush); + + m_standardPalette = palette; + } + + return m_standardPalette; +} +//! [1] + +//! [3] +void NorwegianWoodStyle::polish(QWidget *widget) +//! [3] //! [4] +{ + if (qobject_cast<QPushButton *>(widget) + || qobject_cast<QComboBox *>(widget)) + widget->setAttribute(Qt::WA_Hover, true); +} +//! [4] + +//! [5] +void NorwegianWoodStyle::unpolish(QWidget *widget) +//! [5] //! [6] +{ + if (qobject_cast<QPushButton *>(widget) + || qobject_cast<QComboBox *>(widget)) + widget->setAttribute(Qt::WA_Hover, false); +} +//! [6] + +//! [7] +int NorwegianWoodStyle::pixelMetric(PixelMetric metric, +//! [7] //! [8] + const QStyleOption *option, + const QWidget *widget) const +{ + switch (metric) { + case PM_ComboBoxFrameWidth: + return 8; + case PM_ScrollBarExtent: + return QProxyStyle::pixelMetric(metric, option, widget) + 4; + default: + return QProxyStyle::pixelMetric(metric, option, widget); + } +} +//! [8] + +//! [9] +int NorwegianWoodStyle::styleHint(StyleHint hint, const QStyleOption *option, +//! [9] //! [10] + const QWidget *widget, + QStyleHintReturn *returnData) const +{ + switch (hint) { + case SH_DitherDisabledText: + return int(false); + case SH_EtchDisabledText: + return int(true); + default: + return QProxyStyle::styleHint(hint, option, widget, returnData); + } +} +//! [10] + +//! [11] +void NorwegianWoodStyle::drawPrimitive(PrimitiveElement element, +//! [11] //! [12] + const QStyleOption *option, + QPainter *painter, + const QWidget *widget) const +{ + switch (element) { + case PE_PanelButtonCommand: + { + int delta = (option->state & State_MouseOver) ? 64 : 0; + QColor slightlyOpaqueBlack(0, 0, 0, 63); + QColor semiTransparentWhite(255, 255, 255, 127 + delta); + QColor semiTransparentBlack(0, 0, 0, 127 - delta); + + int x, y, width, height; + option->rect.getRect(&x, &y, &width, &height); +//! [12] + +//! [13] + QPainterPath roundRect = roundRectPath(option->rect); +//! [13] //! [14] + int radius = qMin(width, height) / 2; +//! [14] + +//! [15] + QBrush brush; +//! [15] //! [16] + bool darker; + + const QStyleOptionButton *buttonOption = + qstyleoption_cast<const QStyleOptionButton *>(option); + if (buttonOption + && (buttonOption->features & QStyleOptionButton::Flat)) { + brush = option->palette.window(); + darker = (option->state & (State_Sunken | State_On)); + } else { + if (option->state & (State_Sunken | State_On)) { + brush = option->palette.mid(); + darker = !(option->state & State_Sunken); + } else { + brush = option->palette.button(); + darker = false; +//! [16] //! [17] + } +//! [17] //! [18] + } +//! [18] + +//! [19] + painter->save(); +//! [19] //! [20] + painter->setRenderHint(QPainter::Antialiasing, true); +//! [20] //! [21] + painter->fillPath(roundRect, brush); +//! [21] //! [22] + if (darker) +//! [22] //! [23] + painter->fillPath(roundRect, slightlyOpaqueBlack); +//! [23] + +//! [24] + int penWidth; +//! [24] //! [25] + if (radius < 10) + penWidth = 3; + else if (radius < 20) + penWidth = 5; + else + penWidth = 7; + + QPen topPen(semiTransparentWhite, penWidth); + QPen bottomPen(semiTransparentBlack, penWidth); + + if (option->state & (State_Sunken | State_On)) + qSwap(topPen, bottomPen); +//! [25] + +//! [26] + int x1 = x; + int x2 = x + radius; + int x3 = x + width - radius; + int x4 = x + width; + + if (option->direction == Qt::RightToLeft) { + qSwap(x1, x4); + qSwap(x2, x3); + } + + QPolygon topHalf; + topHalf << QPoint(x1, y) + << QPoint(x4, y) + << QPoint(x3, y + radius) + << QPoint(x2, y + height - radius) + << QPoint(x1, y + height); + + painter->setClipPath(roundRect); + painter->setClipRegion(topHalf, Qt::IntersectClip); + painter->setPen(topPen); + painter->drawPath(roundRect); +//! [26] //! [32] + + QPolygon bottomHalf = topHalf; + bottomHalf[0] = QPoint(x4, y + height); + + painter->setClipPath(roundRect); + painter->setClipRegion(bottomHalf, Qt::IntersectClip); + painter->setPen(bottomPen); + painter->drawPath(roundRect); + + painter->setPen(option->palette.windowText().color()); + painter->setClipping(false); + painter->drawPath(roundRect); + + painter->restore(); + } + break; +//! [32] //! [33] + default: +//! [33] //! [34] + QProxyStyle::drawPrimitive(element, option, painter, widget); + } +} +//! [34] + +//! [35] +void NorwegianWoodStyle::drawControl(ControlElement element, +//! [35] //! [36] + const QStyleOption *option, + QPainter *painter, + const QWidget *widget) const +{ + switch (element) { + case CE_PushButtonLabel: + { + QStyleOptionButton myButtonOption; + const QStyleOptionButton *buttonOption = + qstyleoption_cast<const QStyleOptionButton *>(option); + if (buttonOption) { + myButtonOption = *buttonOption; + if (myButtonOption.palette.currentColorGroup() + != QPalette::Disabled) { + if (myButtonOption.state & (State_Sunken | State_On)) { + myButtonOption.palette.setBrush(QPalette::ButtonText, + myButtonOption.palette.brightText()); + } + } + } + QProxyStyle::drawControl(element, &myButtonOption, painter, widget); + } + break; + default: + QProxyStyle::drawControl(element, option, painter, widget); + } +} +//! [36] + +//! [37] +void NorwegianWoodStyle::setTexture(QPalette &palette, QPalette::ColorRole role, +//! [37] //! [38] + const QImage &image) +{ + for (int i = 0; i < QPalette::NColorGroups; ++i) { + QBrush brush(image); + brush.setColor(palette.brush(QPalette::ColorGroup(i), role).color()); + palette.setBrush(QPalette::ColorGroup(i), role, brush); + } +} +//! [38] + +//! [39] +QPainterPath NorwegianWoodStyle::roundRectPath(const QRect &rect) +//! [39] //! [40] +{ + int radius = qMin(rect.width(), rect.height()) / 2; + int diam = 2 * radius; + + int x1, y1, x2, y2; + rect.getCoords(&x1, &y1, &x2, &y2); + + QPainterPath path; + path.moveTo(x2, y1 + radius); + path.arcTo(QRect(x2 - diam, y1, diam, diam), 0.0, +90.0); + path.lineTo(x1 + radius, y1); + path.arcTo(QRect(x1, y1, diam, diam), 90.0, +90.0); + path.lineTo(x1, y2 - radius); + path.arcTo(QRect(x1, y2 - diam, diam, diam), 180.0, +90.0); + path.lineTo(x1 + radius, y2); + path.arcTo(QRect(x2 - diam, y2 - diam, diam, diam), 270.0, +90.0); + path.closeSubpath(); + return path; +} +//! [40] diff --git a/tests/manual/examples/widgets/widgets/styles/norwegianwoodstyle.h b/tests/manual/examples/widgets/widgets/styles/norwegianwoodstyle.h new file mode 100644 index 0000000000..5af2171f35 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/norwegianwoodstyle.h @@ -0,0 +1,43 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef NORWEGIANWOODSTYLE_H +#define NORWEGIANWOODSTYLE_H + +#include <QProxyStyle> +#include <QPalette> + +QT_BEGIN_NAMESPACE +class QPainterPath; +QT_END_NAMESPACE + +//! [0] +class NorwegianWoodStyle : public QProxyStyle +{ + Q_OBJECT + +public: + NorwegianWoodStyle(); + + QPalette standardPalette() const override; + + void polish(QWidget *widget) override; + void unpolish(QWidget *widget) override; + int pixelMetric(PixelMetric metric, const QStyleOption *option, + const QWidget *widget) const override; + int styleHint(StyleHint hint, const QStyleOption *option, + const QWidget *widget, QStyleHintReturn *returnData) const override; + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const override; + void drawControl(ControlElement control, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const override; + +private: + static void setTexture(QPalette &palette, QPalette::ColorRole role, + const QImage &image); + static QPainterPath roundRectPath(const QRect &rect); + mutable QPalette m_standardPalette; +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/styles/styles.pro b/tests/manual/examples/widgets/widgets/styles/styles.pro new file mode 100644 index 0000000000..87dee7e04c --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/styles.pro @@ -0,0 +1,13 @@ +QT += widgets +requires(qtConfig(combobox)) + +HEADERS = norwegianwoodstyle.h \ + widgetgallery.h +SOURCES = main.cpp \ + norwegianwoodstyle.cpp \ + widgetgallery.cpp +RESOURCES = styles.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/styles +INSTALLS += target diff --git a/tests/manual/examples/widgets/widgets/styles/styles.qrc b/tests/manual/examples/widgets/widgets/styles/styles.qrc new file mode 100644 index 0000000000..4fdad8d914 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/styles.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>images/woodbutton.png</file> + <file>images/woodbackground.png</file> +</qresource> +</RCC> diff --git a/tests/manual/examples/widgets/widgets/styles/widgetgallery.cpp b/tests/manual/examples/widgets/widgets/styles/widgetgallery.cpp new file mode 100644 index 0000000000..83cb99a52c --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/widgetgallery.cpp @@ -0,0 +1,277 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "widgetgallery.h" +#include "norwegianwoodstyle.h" + +#include <QApplication> +#include <QCheckBox> +#include <QComboBox> +#include <QDateTimeEdit> +#include <QDial> +#include <QGridLayout> +#include <QGroupBox> +#include <QLabel> +#include <QLineEdit> +#include <QProgressBar> +#include <QPushButton> +#include <QRadioButton> +#include <QScrollBar> +#include <QSpinBox> +#include <QStyle> +#include <QStyleFactory> +#include <QTableWidget> +#include <QTextEdit> +#include <QTimer> + +//! [0] +WidgetGallery::WidgetGallery(QWidget *parent) + : QDialog(parent) +{ + styleComboBox = new QComboBox; + const QString defaultStyleName = QApplication::style()->objectName(); + QStringList styleNames = QStyleFactory::keys(); + styleNames.append("NorwegianWood"); + for (int i = 1, size = styleNames.size(); i < size; ++i) { + if (defaultStyleName.compare(styleNames.at(i), Qt::CaseInsensitive) == 0) { + styleNames.swapItemsAt(0, i); + break; + } + } + styleComboBox->addItems(styleNames); + + styleLabel = new QLabel(tr("&Style:")); + styleLabel->setBuddy(styleComboBox); + + useStylePaletteCheckBox = new QCheckBox(tr("&Use style's standard palette")); + useStylePaletteCheckBox->setChecked(true); + + disableWidgetsCheckBox = new QCheckBox(tr("&Disable widgets")); + + createTopLeftGroupBox(); + createTopRightGroupBox(); + createBottomLeftTabWidget(); + createBottomRightGroupBox(); + createProgressBar(); +//! [0] + +//! [1] + connect(styleComboBox, &QComboBox::textActivated, +//! [1] //! [2] + this, &WidgetGallery::changeStyle); + connect(useStylePaletteCheckBox, &QCheckBox::toggled, + this, &WidgetGallery::changePalette); + connect(disableWidgetsCheckBox, &QCheckBox::toggled, + topLeftGroupBox, &QGroupBox::setDisabled); + connect(disableWidgetsCheckBox, &QCheckBox::toggled, + topRightGroupBox, &QGroupBox::setDisabled); + connect(disableWidgetsCheckBox, &QCheckBox::toggled, + bottomLeftTabWidget, &QGroupBox::setDisabled); + connect(disableWidgetsCheckBox, &QCheckBox::toggled, + bottomRightGroupBox, &QGroupBox::setDisabled); +//! [2] + +//! [3] + QHBoxLayout *topLayout = new QHBoxLayout; +//! [3] //! [4] + topLayout->addWidget(styleLabel); + topLayout->addWidget(styleComboBox); + topLayout->addStretch(1); + topLayout->addWidget(useStylePaletteCheckBox); + topLayout->addWidget(disableWidgetsCheckBox); + + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addLayout(topLayout, 0, 0, 1, 2); + mainLayout->addWidget(topLeftGroupBox, 1, 0); + mainLayout->addWidget(topRightGroupBox, 1, 1); + mainLayout->addWidget(bottomLeftTabWidget, 2, 0); + mainLayout->addWidget(bottomRightGroupBox, 2, 1); + mainLayout->addWidget(progressBar, 3, 0, 1, 2); + mainLayout->setRowStretch(1, 1); + mainLayout->setRowStretch(2, 1); + mainLayout->setColumnStretch(0, 1); + mainLayout->setColumnStretch(1, 1); + setLayout(mainLayout); + + setWindowTitle(tr("Styles")); + styleChanged(); +} +//! [4] + +//! [5] +void WidgetGallery::changeStyle(const QString &styleName) +//! [5] //! [6] +{ + if (styleName == "NorwegianWood") + QApplication::setStyle(new NorwegianWoodStyle); + else + QApplication::setStyle(QStyleFactory::create(styleName)); +} +//! [6] + +//! [7] +void WidgetGallery::changePalette() +//! [7] //! [8] +{ + QApplication::setPalette(useStylePaletteCheckBox->isChecked() ? + QApplication::style()->standardPalette() : QPalette()); +} +//! [8] + +void WidgetGallery::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::StyleChange) + styleChanged(); +} + +void WidgetGallery::styleChanged() +{ + auto styleName = QApplication::style()->objectName(); + for (int i = 0; i < styleComboBox->count(); ++i) { + if (QString::compare(styleComboBox->itemText(i), styleName, Qt::CaseInsensitive) == 0) { + styleComboBox->setCurrentIndex(i); + break; + } + } + + changePalette(); +} + +//! [9] +void WidgetGallery::advanceProgressBar() +//! [9] //! [10] +{ + int curVal = progressBar->value(); + int maxVal = progressBar->maximum(); + progressBar->setValue(curVal + (maxVal - curVal) / 100); +} +//! [10] + +//! [11] +void WidgetGallery::createTopLeftGroupBox() +//! [11] //! [12] +{ + topLeftGroupBox = new QGroupBox(tr("Group 1")); + + radioButton1 = new QRadioButton(tr("Radio button 1")); + radioButton2 = new QRadioButton(tr("Radio button 2")); + radioButton3 = new QRadioButton(tr("Radio button 3")); + radioButton1->setChecked(true); + + checkBox = new QCheckBox(tr("Tri-state check box")); + checkBox->setTristate(true); + checkBox->setCheckState(Qt::PartiallyChecked); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(radioButton1); + layout->addWidget(radioButton2); + layout->addWidget(radioButton3); + layout->addWidget(checkBox); + layout->addStretch(1); + topLeftGroupBox->setLayout(layout); +} +//! [12] + +void WidgetGallery::createTopRightGroupBox() +{ + topRightGroupBox = new QGroupBox(tr("Group 2")); + + defaultPushButton = new QPushButton(tr("Default Push Button")); + defaultPushButton->setDefault(true); + + togglePushButton = new QPushButton(tr("Toggle Push Button")); + togglePushButton->setCheckable(true); + togglePushButton->setChecked(true); + + flatPushButton = new QPushButton(tr("Flat Push Button")); + flatPushButton->setFlat(true); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(defaultPushButton); + layout->addWidget(togglePushButton); + layout->addWidget(flatPushButton); + layout->addStretch(1); + topRightGroupBox->setLayout(layout); +} + +void WidgetGallery::createBottomLeftTabWidget() +{ + bottomLeftTabWidget = new QTabWidget; + bottomLeftTabWidget->setSizePolicy(QSizePolicy::Preferred, + QSizePolicy::Ignored); + + QWidget *tab1 = new QWidget; + tableWidget = new QTableWidget(10, 10); + + QHBoxLayout *tab1hbox = new QHBoxLayout; + tab1hbox->setContentsMargins(5,5, 5, 5); + tab1hbox->addWidget(tableWidget); + tab1->setLayout(tab1hbox); + + QWidget *tab2 = new QWidget; + textEdit = new QTextEdit; + + textEdit->setPlainText(tr("Twinkle, twinkle, little star,\n" + "How I wonder what you are.\n" + "Up above the world so high,\n" + "Like a diamond in the sky.\n" + "Twinkle, twinkle, little star,\n" + "How I wonder what you are!\n")); + + QHBoxLayout *tab2hbox = new QHBoxLayout; + tab2hbox->setContentsMargins(5, 5, 5, 5); + tab2hbox->addWidget(textEdit); + tab2->setLayout(tab2hbox); + + bottomLeftTabWidget->addTab(tab1, tr("&Table")); + bottomLeftTabWidget->addTab(tab2, tr("Text &Edit")); +} + +void WidgetGallery::createBottomRightGroupBox() +{ + bottomRightGroupBox = new QGroupBox(tr("Group 3")); + bottomRightGroupBox->setCheckable(true); + bottomRightGroupBox->setChecked(true); + + lineEdit = new QLineEdit("s3cRe7"); + lineEdit->setEchoMode(QLineEdit::Password); + + spinBox = new QSpinBox(bottomRightGroupBox); + spinBox->setValue(50); + + dateTimeEdit = new QDateTimeEdit(bottomRightGroupBox); + dateTimeEdit->setDateTime(QDateTime::currentDateTime()); + + slider = new QSlider(Qt::Horizontal, bottomRightGroupBox); + slider->setValue(40); + + scrollBar = new QScrollBar(Qt::Horizontal, bottomRightGroupBox); + scrollBar->setValue(60); + + dial = new QDial(bottomRightGroupBox); + dial->setValue(30); + dial->setNotchesVisible(true); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(lineEdit, 0, 0, 1, 2); + layout->addWidget(spinBox, 1, 0, 1, 2); + layout->addWidget(dateTimeEdit, 2, 0, 1, 2); + layout->addWidget(slider, 3, 0); + layout->addWidget(scrollBar, 4, 0); + layout->addWidget(dial, 3, 1, 2, 1); + layout->setRowStretch(5, 1); + bottomRightGroupBox->setLayout(layout); +} + +//! [13] +void WidgetGallery::createProgressBar() +{ + progressBar = new QProgressBar; + progressBar->setRange(0, 10000); + progressBar->setValue(0); + + QTimer *timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &WidgetGallery::advanceProgressBar); + timer->start(1000); +} +//! [13] diff --git a/tests/manual/examples/widgets/widgets/styles/widgetgallery.h b/tests/manual/examples/widgets/widgets/styles/widgetgallery.h new file mode 100644 index 0000000000..f4c43e7b4f --- /dev/null +++ b/tests/manual/examples/widgets/widgets/styles/widgetgallery.h @@ -0,0 +1,86 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef WIDGETGALLERY_H +#define WIDGETGALLERY_H + +#include <QDialog> + +QT_BEGIN_NAMESPACE +class QCheckBox; +class QComboBox; +class QDateTimeEdit; +class QDial; +class QGroupBox; +class QLabel; +class QLineEdit; +class QProgressBar; +class QPushButton; +class QRadioButton; +class QScrollBar; +class QSlider; +class QSpinBox; +class QTabWidget; +class QTableWidget; +class QTextEdit; +QT_END_NAMESPACE + +//! [0] +class WidgetGallery : public QDialog +{ + Q_OBJECT + +public: + WidgetGallery(QWidget *parent = nullptr); + +protected: + void changeEvent(QEvent *) override; + +private slots: + void changeStyle(const QString &styleName); + void styleChanged(); + void changePalette(); + void advanceProgressBar(); + +private: + void createTopLeftGroupBox(); + void createTopRightGroupBox(); + void createBottomLeftTabWidget(); + void createBottomRightGroupBox(); + void createProgressBar(); + + QLabel *styleLabel; + QComboBox *styleComboBox; + QCheckBox *useStylePaletteCheckBox; + QCheckBox *disableWidgetsCheckBox; +//! [0] + + QGroupBox *topLeftGroupBox; + QRadioButton *radioButton1; + QRadioButton *radioButton2; + QRadioButton *radioButton3; + QCheckBox *checkBox; + + QGroupBox *topRightGroupBox; + QPushButton *defaultPushButton; + QPushButton *togglePushButton; + QPushButton *flatPushButton; + + QTabWidget *bottomLeftTabWidget; + QTableWidget *tableWidget; + QTextEdit *textEdit; + + QGroupBox *bottomRightGroupBox; + QLineEdit *lineEdit; + QSpinBox *spinBox; + QDateTimeEdit *dateTimeEdit; + QSlider *slider; + QScrollBar *scrollBar; + QDial *dial; + + QProgressBar *progressBar; +//! [1] +}; +//! [1] + +#endif diff --git a/tests/manual/examples/widgets/widgets/stylesheet/CMakeLists.txt b/tests/manual/examples/widgets/widgets/stylesheet/CMakeLists.txt new file mode 100644 index 0000000000..7937f6076f --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/CMakeLists.txt @@ -0,0 +1,84 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(stylesheet LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/stylesheet") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(stylesheet + main.cpp + mainwindow.cpp mainwindow.h mainwindow.ui + stylesheeteditor.cpp stylesheeteditor.h stylesheeteditor.ui +) + +set_target_properties(stylesheet PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(stylesheet PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +# Resources: +set(stylesheet_resource_files + "images/checkbox_checked.png" + "images/checkbox_checked_hover.png" + "images/checkbox_checked_pressed.png" + "images/checkbox_unchecked.png" + "images/checkbox_unchecked_hover.png" + "images/checkbox_unchecked_pressed.png" + "images/down_arrow.png" + "images/down_arrow_disabled.png" + "images/frame.png" + "images/pagefold.png" + "images/pushbutton.png" + "images/pushbutton_hover.png" + "images/pushbutton_pressed.png" + "images/radiobutton_checked.png" + "images/radiobutton_checked_hover.png" + "images/radiobutton_checked_pressed.png" + "images/radiobutton_unchecked.png" + "images/radiobutton_unchecked_hover.png" + "images/radiobutton_unchecked_pressed.png" + "images/sizegrip.png" + "images/spindown.png" + "images/spindown_hover.png" + "images/spindown_off.png" + "images/spindown_pressed.png" + "images/spinup.png" + "images/spinup_hover.png" + "images/spinup_off.png" + "images/spinup_pressed.png" + "images/up_arrow.png" + "images/up_arrow_disabled.png" + "layouts/default.ui" + "layouts/pagefold.ui" + "qss/coffee.qss" + "qss/default.qss" + "qss/pagefold.qss" +) + +qt_add_resources(stylesheet "stylesheet" + PREFIX + "/" + FILES + ${stylesheet_resource_files} +) + +install(TARGETS stylesheet + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_checked.png b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_checked.png Binary files differnew file mode 100644 index 0000000000..cbf06f6513 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_checked.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_checked_hover.png b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_checked_hover.png Binary files differnew file mode 100644 index 0000000000..fb4d4d3fdb --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_checked_hover.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_checked_pressed.png b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_checked_pressed.png Binary files differnew file mode 100644 index 0000000000..852fcc0306 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_checked_pressed.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_unchecked.png b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_unchecked.png Binary files differnew file mode 100644 index 0000000000..5f5465582a --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_unchecked.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_unchecked_hover.png b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_unchecked_hover.png Binary files differnew file mode 100644 index 0000000000..687364497e --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_unchecked_hover.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_unchecked_pressed.png b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_unchecked_pressed.png Binary files differnew file mode 100644 index 0000000000..6a768c44de --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/checkbox_unchecked_pressed.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/down_arrow.png b/tests/manual/examples/widgets/widgets/stylesheet/images/down_arrow.png Binary files differnew file mode 100644 index 0000000000..85004aeaf6 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/down_arrow.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/down_arrow_disabled.png b/tests/manual/examples/widgets/widgets/stylesheet/images/down_arrow_disabled.png Binary files differnew file mode 100644 index 0000000000..d9eefed4c8 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/down_arrow_disabled.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/frame.png b/tests/manual/examples/widgets/widgets/stylesheet/images/frame.png Binary files differnew file mode 100644 index 0000000000..05a600502e --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/frame.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/pagefold.png b/tests/manual/examples/widgets/widgets/stylesheet/images/pagefold.png Binary files differnew file mode 100644 index 0000000000..69be8f2a38 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/pagefold.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/pushbutton.png b/tests/manual/examples/widgets/widgets/stylesheet/images/pushbutton.png Binary files differnew file mode 100644 index 0000000000..c7529ba02d --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/pushbutton.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/pushbutton_hover.png b/tests/manual/examples/widgets/widgets/stylesheet/images/pushbutton_hover.png Binary files differnew file mode 100644 index 0000000000..af0ef9d561 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/pushbutton_hover.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/pushbutton_pressed.png b/tests/manual/examples/widgets/widgets/stylesheet/images/pushbutton_pressed.png Binary files differnew file mode 100644 index 0000000000..f7381f752a --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/pushbutton_pressed.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_checked.png b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_checked.png Binary files differnew file mode 100644 index 0000000000..8ab9157578 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_checked.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_checked_hover.png b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_checked_hover.png Binary files differnew file mode 100644 index 0000000000..d68cb009a7 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_checked_hover.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_checked_pressed.png b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_checked_pressed.png Binary files differnew file mode 100644 index 0000000000..e3cd5a59e4 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_checked_pressed.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_unchecked.png b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_unchecked.png Binary files differnew file mode 100644 index 0000000000..321a9a1558 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_unchecked.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_unchecked_hover.png b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_unchecked_hover.png Binary files differnew file mode 100644 index 0000000000..666a3b0bdd --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_unchecked_hover.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_unchecked_pressed.png b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_unchecked_pressed.png Binary files differnew file mode 100644 index 0000000000..c4b0567aa9 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/radiobutton_unchecked_pressed.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/sizegrip.png b/tests/manual/examples/widgets/widgets/stylesheet/images/sizegrip.png Binary files differnew file mode 100644 index 0000000000..350583aaac --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/sizegrip.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/spindown.png b/tests/manual/examples/widgets/widgets/stylesheet/images/spindown.png Binary files differnew file mode 100644 index 0000000000..7ff3c64926 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/spindown.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/spindown_hover.png b/tests/manual/examples/widgets/widgets/stylesheet/images/spindown_hover.png Binary files differnew file mode 100644 index 0000000000..1486c4dfe4 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/spindown_hover.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/spindown_off.png b/tests/manual/examples/widgets/widgets/stylesheet/images/spindown_off.png Binary files differnew file mode 100644 index 0000000000..a90ab3f038 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/spindown_off.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/spindown_pressed.png b/tests/manual/examples/widgets/widgets/stylesheet/images/spindown_pressed.png Binary files differnew file mode 100644 index 0000000000..f6271cbde2 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/spindown_pressed.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/spinup.png b/tests/manual/examples/widgets/widgets/stylesheet/images/spinup.png Binary files differnew file mode 100644 index 0000000000..1069dd00df --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/spinup.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/spinup_hover.png b/tests/manual/examples/widgets/widgets/stylesheet/images/spinup_hover.png Binary files differnew file mode 100644 index 0000000000..884c8d77c5 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/spinup_hover.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/spinup_off.png b/tests/manual/examples/widgets/widgets/stylesheet/images/spinup_off.png Binary files differnew file mode 100644 index 0000000000..02dad1fb29 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/spinup_off.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/spinup_pressed.png b/tests/manual/examples/widgets/widgets/stylesheet/images/spinup_pressed.png Binary files differnew file mode 100644 index 0000000000..b1843e2a1f --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/spinup_pressed.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/up_arrow.png b/tests/manual/examples/widgets/widgets/stylesheet/images/up_arrow.png Binary files differnew file mode 100644 index 0000000000..e7f7ddb3a6 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/up_arrow.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/images/up_arrow_disabled.png b/tests/manual/examples/widgets/widgets/stylesheet/images/up_arrow_disabled.png Binary files differnew file mode 100644 index 0000000000..4d2c27770f --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/images/up_arrow_disabled.png diff --git a/tests/manual/examples/widgets/widgets/stylesheet/layouts/default.ui b/tests/manual/examples/widgets/widgets/stylesheet/layouts/default.ui new file mode 100644 index 0000000000..431a40956e --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/layouts/default.ui @@ -0,0 +1,329 @@ +<ui version="4.0" > + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>388</width> + <height>413</height> + </rect> + </property> + <property name="windowTitle" > + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget" > + <layout class="QGridLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="0" column="0" > + <widget class="QLabel" name="nameLabel" > + <property name="text" > + <string>&Name:</string> + </property> + <property name="buddy" > + <cstring>nameCombo</cstring> + </property> + </widget> + </item> + <item row="0" column="1" colspan="3" > + <widget class="QComboBox" name="nameCombo" > + <property name="toolTip" > + <string>Specify your name</string> + </property> + <property name="editable" > + <bool>true</bool> + </property> + <property name="currentIndex" > + <number>-1</number> + </property> + <item> + <property name="text" > + <string>Girish</string> + </property> + </item> + <item> + <property name="text" > + <string>Jasmin</string> + </property> + </item> + <item> + <property name="text" > + <string>Simon</string> + </property> + </item> + <item> + <property name="text" > + <string>Zack</string> + </property> + </item> + </widget> + </item> + <item row="1" column="3" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="2" > + <widget class="QRadioButton" name="femaleRadioButton" > + <property name="toolTip" > + <string>Check this if you are female</string> + </property> + <property name="text" > + <string>&Female</string> + </property> + </widget> + </item> + <item row="6" column="0" colspan="4" > + <widget class="QCheckBox" name="agreeCheckBox" > + <property name="toolTip" > + <string>Please read the license before checking this</string> + </property> + <property name="text" > + <string>I &accept the terms and conditions</string> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QRadioButton" name="maleRadioButton" > + <property name="toolTip" > + <string>Check this if you are male</string> + </property> + <property name="text" > + <string>&Male</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="genderLabel" > + <property name="text" > + <string>Gender:</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="3" > + <widget class="QSpinBox" name="ageSpinBox" > + <property name="toolTip" > + <string>Specify your age</string> + </property> + <property name="statusTip" > + <string>Specify your age here</string> + </property> + <property name="minimum" > + <number>12</number> + </property> + <property name="value" > + <number>22</number> + </property> + </widget> + </item> + <item row="7" column="2" colspan="2" > + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="ageLabel" > + <property name="text" > + <string>&Age:</string> + </property> + <property name="buddy" > + <cstring>ageSpinBox</cstring> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="passwordLabel" > + <property name="text" > + <string>&Password:</string> + </property> + <property name="buddy" > + <cstring>passwordEdit</cstring> + </property> + </widget> + </item> + <item row="3" column="1" colspan="3" > + <widget class="QLineEdit" name="passwordEdit" > + <property name="toolTip" > + <string>Specify your password</string> + </property> + <property name="statusTip" > + <string>Specify your password here</string> + </property> + <property name="text" > + <string>Password</string> + </property> + <property name="echoMode" > + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + <item row="5" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Profession</string> + </property> + <property name="buddy" > + <cstring>professionList</cstring> + </property> + </widget> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="countryLabel" > + <property name="text" > + <string>&Country</string> + </property> + <property name="buddy" > + <cstring>professionList</cstring> + </property> + </widget> + </item> + <item row="5" column="1" colspan="3" > + <widget class="QListWidget" name="professionList" > + <property name="toolTip" > + <string>Select your profession</string> + </property> + <property name="statusTip" > + <string>Select your profession</string> + </property> + <property name="whatsThis" > + <string>Select your profession</string> + </property> + <property name="currentRow" > + <number>1</number> + </property> + <item> + <property name="text" > + <string>Developer</string> + </property> + </item> + <item> + <property name="text" > + <string>Student</string> + </property> + </item> + <item> + <property name="text" > + <string>Fisherman</string> + </property> + </item> + </widget> + </item> + <item row="4" column="1" colspan="3" > + <widget class="QComboBox" name="countryCombo" > + <property name="toolTip" > + <string>Specify your country</string> + </property> + <property name="statusTip" > + <string>Specify your country here</string> + </property> + <property name="currentIndex" > + <number>2</number> + </property> + <item> + <property name="text" > + <string>Germany</string> + </property> + </item> + <item> + <property name="text" > + <string>India</string> + </property> + </item> + <item> + <property name="text" > + <string>Norway</string> + </property> + </item> + <item> + <property name="text" > + <string>United States Of America</string> + </property> + </item> + <item> + <property name="text" > + <string>United Kingdom</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>388</width> + <height>21</height> + </rect> + </property> + <widget class="QMenu" name="menu_File" > + <property name="title" > + <string>&File</string> + </property> + <addaction name="editStyleAction" /> + <addaction name="separator" /> + <addaction name="exitAction" /> + </widget> + <widget class="QMenu" name="menu_Help" > + <property name="title" > + <string>&Help</string> + </property> + <addaction name="aboutAction" /> + <addaction name="separator" /> + <addaction name="aboutQtAction" /> + </widget> + <addaction name="menu_File" /> + <addaction name="menu_Help" /> + </widget> + <widget class="QStatusBar" name="statusbar" /> + <action name="exitAction" > + <property name="text" > + <string>&Exit</string> + </property> + </action> + <action name="aboutQtAction" > + <property name="text" > + <string>About Qt</string> + </property> + </action> + <action name="editStyleAction" > + <property name="text" > + <string>Edit &Style</string> + </property> + </action> + <action name="aboutAction" > + <property name="text" > + <string>About</string> + </property> + </action> + </widget> + <tabstops> + <tabstop>maleRadioButton</tabstop> + <tabstop>femaleRadioButton</tabstop> + <tabstop>ageSpinBox</tabstop> + <tabstop>passwordEdit</tabstop> + <tabstop>professionList</tabstop> + <tabstop>agreeCheckBox</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> diff --git a/tests/manual/examples/widgets/widgets/stylesheet/layouts/pagefold.ui b/tests/manual/examples/widgets/widgets/stylesheet/layouts/pagefold.ui new file mode 100644 index 0000000000..7ae313c331 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/layouts/pagefold.ui @@ -0,0 +1,349 @@ +<ui version="4.0" > + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>392</width> + <height>412</height> + </rect> + </property> + <property name="windowTitle" > + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget" > + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QFrame" name="mainFrame" > + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="0" column="1" colspan="3" > + <widget class="QComboBox" name="nameCombo" > + <property name="toolTip" > + <string>Specify your name</string> + </property> + <property name="editable" > + <bool>true</bool> + </property> + <property name="currentIndex" > + <number>-1</number> + </property> + <item> + <property name="text" > + <string>Girish</string> + </property> + </item> + <item> + <property name="text" > + <string>Jasmin</string> + </property> + </item> + <item> + <property name="text" > + <string>Simon</string> + </property> + </item> + <item> + <property name="text" > + <string>Zack</string> + </property> + </item> + </widget> + </item> + <item row="1" column="3" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="2" > + <widget class="QRadioButton" name="femaleRadioButton" > + <property name="styleSheet" > + <string>Check this if you are female</string> + </property> + <property name="text" > + <string>&Female</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="genderLabel" > + <property name="text" > + <string>Gender:</string> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="ageLabel" > + <property name="text" > + <string>&Age:</string> + </property> + <property name="buddy" > + <cstring>ageSpinBox</cstring> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QRadioButton" name="maleRadioButton" > + <property name="toolTip" > + <string>Check this if you are male</string> + </property> + <property name="text" > + <string>&Male</string> + </property> + </widget> + </item> + <item row="0" column="0" > + <widget class="QLabel" name="nameLabel" > + <property name="text" > + <string>&Name:</string> + </property> + <property name="buddy" > + <cstring>nameCombo</cstring> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="passwordLabel" > + <property name="text" > + <string>&Password:</string> + </property> + <property name="buddy" > + <cstring>passwordEdit</cstring> + </property> + </widget> + </item> + <item row="2" column="1" colspan="3" > + <widget class="QSpinBox" name="ageSpinBox" > + <property name="toolTip" > + <string>Specify your age</string> + </property> + <property name="statusTip" > + <string>Specify your age</string> + </property> + <property name="minimum" > + <number>12</number> + </property> + <property name="value" > + <number>22</number> + </property> + </widget> + </item> + <item row="7" column="2" colspan="2" > + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="6" column="0" colspan="4" > + <widget class="QCheckBox" name="agreeCheckBox" > + <property name="toolTip" > + <string>Please read the LICENSE file before checking</string> + </property> + <property name="text" > + <string>I &accept the terms and &conditions</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="3" > + <widget class="QLineEdit" name="passwordEdit" > + <property name="toolTip" > + <string>Specify your password</string> + </property> + <property name="statusTip" > + <string>Specify your password</string> + </property> + <property name="text" > + <string>Password</string> + </property> + <property name="echoMode" > + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + <item row="5" column="1" colspan="3" > + <widget class="QListWidget" name="professionList" > + <property name="toolTip" > + <string>Select your profession</string> + </property> + <property name="statusTip" > + <string>Specify your name here</string> + </property> + <property name="whatsThis" > + <string>Specify your name here</string> + </property> + <property name="currentRow" > + <number>0</number> + </property> + <item> + <property name="text" > + <string>Developer</string> + </property> + </item> + <item> + <property name="text" > + <string>Student</string> + </property> + </item> + <item> + <property name="text" > + <string>Fisherman</string> + </property> + </item> + </widget> + </item> + <item row="5" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Profession:</string> + </property> + <property name="buddy" > + <cstring>professionList</cstring> + </property> + </widget> + </item> + <item row="4" column="1" colspan="3" > + <widget class="QComboBox" name="countryCombo" > + <property name="toolTip" > + <string>Specify country of origin</string> + </property> + <property name="statusTip" > + <string>Specify country of origin</string> + </property> + <property name="currentIndex" > + <number>6</number> + </property> + <item> + <property name="text" > + <string>Egypt</string> + </property> + </item> + <item> + <property name="text" > + <string>France</string> + </property> + </item> + <item> + <property name="text" > + <string>Germany</string> + </property> + </item> + <item> + <property name="text" > + <string>India</string> + </property> + </item> + <item> + <property name="text" > + <string>Italy</string> + </property> + </item> + <item> + <property name="text" > + <string>Korea</string> + </property> + </item> + <item> + <property name="text" > + <string>Norway</string> + </property> + </item> + </widget> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="countryLabel" > + <property name="text" > + <string>Pro&fession</string> + </property> + <property name="buddy" > + <cstring>professionList</cstring> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>392</width> + <height>25</height> + </rect> + </property> + <widget class="QMenu" name="menu_File" > + <property name="title" > + <string>&File</string> + </property> + <addaction name="editStyleAction" /> + <addaction name="separator" /> + <addaction name="exitAction" /> + </widget> + <widget class="QMenu" name="menu_Help" > + <property name="title" > + <string>&Help</string> + </property> + <addaction name="aboutAction" /> + <addaction name="separator" /> + <addaction name="aboutQtAction" /> + </widget> + <addaction name="menu_File" /> + <addaction name="menu_Help" /> + </widget> + <widget class="QStatusBar" name="statusbar" /> + <action name="exitAction" > + <property name="text" > + <string>&Exit</string> + </property> + </action> + <action name="aboutQtAction" > + <property name="text" > + <string>About Qt</string> + </property> + </action> + <action name="editStyleAction" > + <property name="text" > + <string>Edit &Style</string> + </property> + </action> + <action name="aboutAction" > + <property name="text" > + <string>About</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tests/manual/examples/widgets/widgets/stylesheet/main.cpp b/tests/manual/examples/widgets/widgets/stylesheet/main.cpp new file mode 100644 index 0000000000..7d7cf3e573 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/main.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QApplication> + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MainWindow window; + window.show(); + return app.exec(); +} diff --git a/tests/manual/examples/widgets/widgets/stylesheet/mainwindow.cpp b/tests/manual/examples/widgets/widgets/stylesheet/mainwindow.cpp new file mode 100644 index 0000000000..a43613c757 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/mainwindow.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "mainwindow.h" +#include "stylesheeteditor.h" + +#include <QMessageBox> + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); + + ui.nameLabel->setProperty("class", "mandatory QLabel"); + ui.nameCombo->lineEdit()->setPlaceholderText(tr("Last, First")); + + styleSheetEditor = new StyleSheetEditor(this); + + statusBar()->addWidget(new QLabel(tr("Ready"))); + + connect(ui.exitAction, &QAction::triggered, qApp, &QApplication::quit); + connect(ui.aboutQtAction, &QAction::triggered, qApp, &QApplication::aboutQt); +} + +void MainWindow::on_editStyleAction_triggered() +{ + styleSheetEditor->show(); + styleSheetEditor->activateWindow(); +} + +void MainWindow::on_aboutAction_triggered() +{ + const QString url = QStringLiteral("http://doc.qt.io/qt-%1/stylesheet.html") + .arg(QT_VERSION_MAJOR); + QMessageBox::about(this, tr("About Style sheet"), + tr("The <b>Style Sheet</b> example shows how widgets can be styled " + "using <a href=\"%1\">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.").arg(url)); +} diff --git a/tests/manual/examples/widgets/widgets/stylesheet/mainwindow.h b/tests/manual/examples/widgets/widgets/stylesheet/mainwindow.h new file mode 100644 index 0000000000..877636bddf --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/mainwindow.h @@ -0,0 +1,29 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> + +#include "ui_mainwindow.h" + +class StyleSheetEditor; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + +private slots: + void on_editStyleAction_triggered(); + void on_aboutAction_triggered(); + +private: + StyleSheetEditor *styleSheetEditor; + Ui::MainWindow ui; +}; + +#endif diff --git a/tests/manual/examples/widgets/widgets/stylesheet/mainwindow.ui b/tests/manual/examples/widgets/widgets/stylesheet/mainwindow.ui new file mode 100644 index 0000000000..cc29257afb --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/mainwindow.ui @@ -0,0 +1,356 @@ +<ui version="4.0" > + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>413</height> + </rect> + </property> + <property name="windowTitle" > + <string>Style Sheet</string> + </property> + <widget class="QWidget" name="centralwidget" > + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QFrame" name="mainFrame" > + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="6" column="0" colspan="5" > + <widget class="QCheckBox" name="agreeCheckBox" > + <property name="toolTip" > + <string>Please read the LICENSE file before checking</string> + </property> + <property name="text" > + <string>I accept the terms and &conditions</string> + </property> + </widget> + </item> + <item row="5" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Profession:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set> + </property> + <property name="buddy" > + <cstring>professionList</cstring> + </property> + </widget> + </item> + <item row="0" column="0" > + <widget class="QLabel" name="nameLabel" > + <property name="text" > + <string>&Name:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy" > + <cstring>nameCombo</cstring> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QRadioButton" name="maleRadioButton" > + <property name="toolTip" > + <string>Check this if you are male</string> + </property> + <property name="text" > + <string>&Male</string> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="passwordLabel" > + <property name="text" > + <string>&Password:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy" > + <cstring>passwordEdit</cstring> + </property> + </widget> + </item> + <item row="4" column="1" colspan="4" > + <widget class="QComboBox" name="countryCombo" > + <property name="toolTip" > + <string>Specify country of origin</string> + </property> + <property name="statusTip" > + <string>Specify country of origin</string> + </property> + <property name="currentIndex" > + <number>6</number> + </property> + <item> + <property name="text" > + <string>Egypt</string> + </property> + </item> + <item> + <property name="text" > + <string>France</string> + </property> + </item> + <item> + <property name="text" > + <string>Germany</string> + </property> + </item> + <item> + <property name="text" > + <string>India</string> + </property> + </item> + <item> + <property name="text" > + <string>Italy</string> + </property> + </item> + <item> + <property name="text" > + <string>Norway</string> + </property> + </item> + <item> + <property name="text" > + <string>Pakistan</string> + </property> + </item> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="ageLabel" > + <property name="text" > + <string>&Age:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy" > + <cstring>ageSpinBox</cstring> + </property> + </widget> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="countryLabel" > + <property name="text" > + <string>Country:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy" > + <cstring>countryCombo</cstring> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="genderLabel" > + <property name="text" > + <string>Gender:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="1" colspan="4" > + <widget class="QLineEdit" name="passwordEdit" > + <property name="toolTip" > + <string>Specify your password</string> + </property> + <property name="statusTip" > + <string>Specify your password</string> + </property> + <property name="text" > + <string>Password</string> + </property> + <property name="echoMode" > + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + <item row="1" column="2" colspan="2" > + <widget class="QRadioButton" name="femaleRadioButton" > + <property name="toolTip"> + <string>Check this if you are female</string> + </property> + <property name="text" > + <string>&Female</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2" > + <widget class="QSpinBox" name="ageSpinBox" > + <property name="toolTip" > + <string>Specify your age</string> + </property> + <property name="statusTip" > + <string>Specify your age</string> + </property> + <property name="minimum" > + <number>12</number> + </property> + <property name="value" > + <number>22</number> + </property> + </widget> + </item> + <item row="0" column="1" colspan="4" > + <widget class="QComboBox" name="nameCombo" > + <property name="toolTip" > + <string>Specify your name</string> + </property> + <property name="editable" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="4" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="3" colspan="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>61</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="7" column="3" colspan="2" > + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="5" column="1" colspan="4" > + <widget class="QListWidget" name="professionList" > + <property name="toolTip" > + <string>Select your profession</string> + </property> + <property name="statusTip" > + <string>Specify your name here</string> + </property> + <property name="whatsThis" > + <string>Specify your name here</string> + </property> + <property name="currentRow" > + <number>0</number> + </property> + <item> + <property name="text" > + <string>Developer</string> + </property> + </item> + <item> + <property name="text" > + <string>Student</string> + </property> + </item> + <item> + <property name="text" > + <string>Fisherman</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>29</height> + </rect> + </property> + <widget class="QMenu" name="menu_File" > + <property name="title" > + <string>&File</string> + </property> + <addaction name="editStyleAction" /> + <addaction name="separator" /> + <addaction name="exitAction" /> + </widget> + <widget class="QMenu" name="menu_Help" > + <property name="title" > + <string>&Help</string> + </property> + <addaction name="aboutAction" /> + <addaction name="aboutQtAction" /> + </widget> + <addaction name="menu_File" /> + <addaction name="menu_Help" /> + </widget> + <widget class="QStatusBar" name="statusbar" /> + <action name="exitAction" > + <property name="text" > + <string>&Exit</string> + </property> + </action> + <action name="aboutQtAction" > + <property name="text" > + <string>About Qt</string> + </property> + </action> + <action name="editStyleAction" > + <property name="text" > + <string>Edit &Style...</string> + </property> + </action> + <action name="aboutAction" > + <property name="text" > + <string>About</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tests/manual/examples/widgets/widgets/stylesheet/qss/coffee.qss b/tests/manual/examples/widgets/widgets/stylesheet/qss/coffee.qss new file mode 100644 index 0000000000..8f72a15ee5 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/qss/coffee.qss @@ -0,0 +1,117 @@ +.QWidget { + background-color: beige; +} + +/* Nice Windows-XP-style password character. */ +QLineEdit[echoMode="2"] { + lineedit-password-character: 9679; +} + +/* We provide a min-width and min-height for push buttons + so that they look elegant regardless of the width of the text. */ +QPushButton { + background-color: palegoldenrod; + border-width: 2px; + border-color: darkkhaki; + border-style: solid; + border-radius: 5; + padding: 3px; + min-width: 9ex; + min-height: 2.5ex; +} + +QPushButton:hover { + background-color: khaki; +} + +/* Increase the padding, so the text is shifted when the button is + pressed. */ +QPushButton:pressed { + padding-left: 5px; + padding-top: 5px; + background-color: #d0d67c; +} + +QLabel, QAbstractButton { + font: bold; +} + +/* Mark mandatory fields with a brownish color. */ +.mandatory { + color: brown; +} + +/* Bold text on status bar looks awful. */ +QStatusBar QLabel { + font: normal; +} + +QStatusBar::item { + border-width: 1; + border-color: darkkhaki; + border-style: solid; + border-radius: 2; +} + +QComboBox, QLineEdit, QSpinBox, QTextEdit, QListView { + background-color: cornsilk; + selection-color: #0a214c; + selection-background-color: #C19A6B; +} + +/* Make placeholder text a matching semi-transparent color */ +QComboBox, QLineEdit { + placeholder-text-color: #80C19A6B; +} + +QListView { + show-decoration-selected: 1; +} + +QListView::item:hover { + background-color: wheat; +} + +/* We reserve 1 pixel space in padding. When we get the focus, + we kill the padding and enlarge the border. This makes the items + glow. */ +QLineEdit, QFrame { + border-width: 2px; + padding: 1px; + border-style: solid; + border-color: darkkhaki; + border-radius: 5px; +} + +/* As mentioned above, eliminate the padding and increase the border. */ +QLineEdit:focus, QFrame:focus { + border-width: 3px; + padding: 0px; +} + +/* A QLabel is a QFrame ... */ +QLabel { + border: none; + padding: 0; + background: none; +} + +/* A QToolTip is a QLabel ... */ +QToolTip { + border: 2px solid darkkhaki; + padding: 5px; + border-radius: 3px; + opacity: 200; +} + +/* Nice to have the background color change when hovered. */ +QRadioButton:hover, QCheckBox:hover { + background-color: wheat; +} + +/* Force the dialog's buttons to follow the Windows guidelines. */ +QDialogButtonBox { + button-layout: 0; +} + + diff --git a/tests/manual/examples/widgets/widgets/stylesheet/qss/default.qss b/tests/manual/examples/widgets/widgets/stylesheet/qss/default.qss new file mode 100644 index 0000000000..84eb5e0bc2 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/qss/default.qss @@ -0,0 +1 @@ +/* empty stylesheet */ diff --git a/tests/manual/examples/widgets/widgets/stylesheet/qss/pagefold.qss b/tests/manual/examples/widgets/widgets/stylesheet/qss/pagefold.qss new file mode 100644 index 0000000000..3701fc713c --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/qss/pagefold.qss @@ -0,0 +1,299 @@ +/* Customize any plain widget that is a child of a QMainWindow. */ +QMainWindow > .QWidget { + background-color: gainsboro; + background-image: url(:/images/pagefold.png); + background-position: top right; + background-repeat: no-repeat +} + +/* Provide a padding for the layout inside the frame. The frame + exists only to provide a padding for the top-right image, so we + explicitly disable the border. */ +#mainFrame { + padding-right: 30px; + border-style: none; + border-image: none; /* since we set a border-image below */ +} + +/* mainFrame won't have this border-image since we have + explicitly set it to 'none' using a more specific selector. */ +QFrame, QLineEdit, QComboBox[editable="true"], QSpinBox { + border-image: url(:/images/frame.png) 4; + border-width: 3; +} + +QLabel { + border: none; + border-image: none; + padding: 0; + background: none; +} + +/* Make text in message boxes selectable. */ +QMessageBox { + /* LinksAccessibleByMouse | TextSelectableByMouse */ + messagebox-text-interaction-flags: 5; +} + +/* Set the selection colors for all widgets. */ +QWidget { + selection-color: black; + selection-background-color: Silver; + color: black; +} + +/* Make the entire row selected in item views. */ +QAbstractItemView { + show-decoration-selected: 1; +} + +/* Nice WindowsXP-style password character for password line edits. */ +QLineEdit[echoMode="2"] { + lineedit-password-character: 9679; +} + +/* Customize tooltips. */ +QToolTip { + background-color: rgb(200,200,255); + border-color: darkslategray; + border-width: 1px; + border-style: solid; + padding: 3px; + font: bold; + border-radius: 3px; + opacity: 200; +} + +/* Customize radio buttons. */ + +QRadioButton { + spacing: 5px; +} + +QRadioButton::indicator { + width: 13px; + height: 13px; +} + +QRadioButton::indicator::unchecked { + image: url(:/images/radiobutton_unchecked.png); +} + +QRadioButton::indicator:unchecked:hover { + image: url(:/images/radiobutton_unchecked_hover.png); +} + +QRadioButton::indicator:unchecked:pressed { + image: url(:/images/radiobutton_unchecked_pressed.png); +} + +QRadioButton::indicator::checked { + image: url(:/images/radiobutton_checked.png); +} + +QRadioButton::indicator:checked:hover { + image: url(:/images/radiobutton_checked_hover.png); +} + +QRadioButton::indicator:checked:pressed { + image: url(:/images/radiobutton_checked_pressed.png); +} + +/* Customize arrows. */ + +*::down-arrow, *::menu-indicator { + image: url(:/images/down_arrow.png); + width: 7px; + height: 7px; +} + +*::down-arrow:disabled, *::down-arrow:off { + image: url(:/images/down_arrow_disabled.png); +} + +*::up-arrow { + image: url(:/images/up_arrow.png); + width: 7px; + height: 7px; +} + +*::up-arrow:disabled, *::up-arrow:off { + image: url(:/images/up_arrow_disabled.png); +} + +/* Customize push buttons and comboboxes. Our read-only combobox + is very similar to a push button, so they share the same border image. */ + +QPushButton { + min-width: 4em; +} + +QPushButton, QComboBox[editable="false"], +QComboBox[editable="true"]::drop-down { + border-image: url(:/images/pushbutton.png) 5; + border-width: 5; +} + +QPushButton:hover, QComboBox[editable="false"]:hover, +QComboBox[editable="true"]::drop-down:hover, QMenuBar::item:hover { + border-image: url(:/images/pushbutton_hover.png) 5; + border-width: 5; +} + +QPushButton:pressed, QComboBox[editable="false"]:on, +QComboBox[editable="true"]::drop-down:on, QMenuBar::item:on { + border-image: url(:/images/pushbutton_pressed.png) 5; + border-width: 5; +} + +/* Customize read-only comboboxes. */ + +QComboBox[editable="false"] { + padding-left: 3px; + padding-right: 20px; /* space for the arrow */ +} + +QComboBox[editable="false"]::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 15px; + border-left-style: solid; + border-left-color: darkgray; + border-left-width: 1px; +} + +QComboBox[editable="false"]::down-arrow { + subcontrol-origin: content; + subcontrol-position: center; + position: relative; + left: 1px; /* 1 pixel dropdown border */ +} + +/* The combobox arrow is on when the popup is open. */ +QComboBox[editable="false"]::down-arrow:on { + position: relative; + top: 1px; + left: 2px; +} + +/* Customize editable comboboxes. */ + +QComboBox[editable="true"] { + padding-right: 16px; +} + +QComboBox[editable="true"]::drop-down { + subcontrol-origin: border; + subcontrol-position: top right; + width: 13px; + position: absolute; + top: 2px; + bottom: 2px; + right: 2px; +} + +QComboBox[editable="true"]::drop-down, +QComboBox[editable="true"]::drop-down:hover, +QComboBox[editable="true"]::drop-down:on { + border-width: 0px; + border-left-width: 3px; /* we need only left and center part */ +} + +/* Shift the arrow when it's open. */ +QComboBox[editable="true"]::down-arrow:on { + position: relative; + top: 1px; + left: 1px; +} + +/* Customize check boxes. */ +QCheckBox { + spacing: 5px; +} + +QCheckBox::indicator { + width: 13px; + height: 13px; +} + +QCheckBox::indicator:unchecked { + image: url(:/images/checkbox_unchecked.png); +} + +QCheckBox::indicator:unchecked:hover { + image: url(:/images/checkbox_unchecked_hover.png); +} + +QCheckBox::indicator:unchecked:pressed { + image: url(:/images/checkbox_unchecked_pressed.png); +} + +QCheckBox::indicator:checked { + image: url(:/images/checkbox_checked.png); +} + +QCheckBox::indicator:checked:hover { + image: url(:/images/checkbox_checked_hover.png); +} + +QCheckBox::indicator:checked:pressed { + image: url(:/images/checkbox_checked_pressed.png); +} + +/* Customize the size grip. */ +QSizeGrip { + image: url(:/images/sizegrip.png); + width: 16px; + height: 16px; +} + +/* Customize the menu bar. */ +QMenuBar { + border-image: none; + border-style: none; + border-width: 1px; + border-bottom-style: solid; + border-bottom-color: darkslategray; + padding: 2px; +} + +/* Customize spin boxes. */ + +QSpinBox { + padding-right: 15px; +} + +QSpinBox::up-button { + subcontrol-origin: border; + subcontrol-position: top right; + + width: 16px; /* 16 + 2*1px border-width = 15px padding + 3px parent border */ + border-image: url(:/images/spinup.png) 1; + border-width: 1px; +} + +QSpinBox::up-button:hover { + border-image: url(:/images/spinup_hover.png) 1; +} + +QSpinBox::up-button:pressed { + border-image: url(:/images/spinup_pressed.png) 1; +} + +QSpinBox::down-button { + subcontrol-origin: border; + subcontrol-position: bottom right; + + width: 16px; + border-image: url(:/images/spindown.png) 1; + border-width: 1px; + border-top-width: 0; +} + +QSpinBox::down-button:hover { + border-image: url(:/images/spindown_hover.png) 1; +} + +QSpinBox::down-button:pressed { + border-image: url(:/images/spindown_pressed.png) 1; +} diff --git a/tests/manual/examples/widgets/widgets/stylesheet/stylesheet.pro b/tests/manual/examples/widgets/widgets/stylesheet/stylesheet.pro new file mode 100644 index 0000000000..0fe3187f63 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/stylesheet.pro @@ -0,0 +1,15 @@ +QT += widgets +requires(qtConfig(combobox)) + +HEADERS = mainwindow.h \ + stylesheeteditor.h +FORMS = mainwindow.ui \ + stylesheeteditor.ui +RESOURCES = stylesheet.qrc +SOURCES = main.cpp \ + mainwindow.cpp \ + stylesheeteditor.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/stylesheet +INSTALLS += target diff --git a/tests/manual/examples/widgets/widgets/stylesheet/stylesheet.qrc b/tests/manual/examples/widgets/widgets/stylesheet/stylesheet.qrc new file mode 100644 index 0000000000..e1e61a920a --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/stylesheet.qrc @@ -0,0 +1,39 @@ +<RCC> +<qresource prefix="/"> + <file>layouts/default.ui</file> + <file>layouts/pagefold.ui</file> + <file>qss/coffee.qss</file> + <file>qss/default.qss</file> + <file>qss/pagefold.qss</file> + <file>images/pagefold.png</file> + <file>images/frame.png</file> + <file>images/radiobutton_unchecked.png</file> + <file>images/radiobutton_unchecked_pressed.png</file> + <file>images/radiobutton_unchecked_hover.png</file> + <file>images/radiobutton_checked.png</file> + <file>images/radiobutton_checked_pressed.png</file> + <file>images/radiobutton_checked_hover.png</file> + <file>images/pushbutton.png</file> + <file>images/pushbutton_hover.png</file> + <file>images/pushbutton_pressed.png</file> + <file>images/checkbox_unchecked.png</file> + <file>images/checkbox_unchecked_pressed.png</file> + <file>images/checkbox_unchecked_hover.png</file> + <file>images/checkbox_checked.png</file> + <file>images/checkbox_checked_pressed.png</file> + <file>images/checkbox_checked_hover.png</file> + <file>images/down_arrow.png</file> + <file>images/down_arrow_disabled.png</file> + <file>images/up_arrow.png</file> + <file>images/up_arrow_disabled.png</file> + <file>images/sizegrip.png</file> + <file>images/spinup.png</file> + <file>images/spinup_off.png</file> + <file>images/spinup_hover.png</file> + <file>images/spinup_pressed.png</file> + <file>images/spindown.png</file> + <file>images/spindown_off.png</file> + <file>images/spindown_hover.png</file> + <file>images/spindown_pressed.png</file> +</qresource> +</RCC> diff --git a/tests/manual/examples/widgets/widgets/stylesheet/stylesheeteditor.cpp b/tests/manual/examples/widgets/widgets/stylesheet/stylesheeteditor.cpp new file mode 100644 index 0000000000..84fda79a16 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/stylesheeteditor.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "stylesheeteditor.h" + +#include <QFile> +#include <QRegularExpression> +#include <QStyleFactory> + +StyleSheetEditor::StyleSheetEditor(QWidget *parent) + : QDialog(parent) +{ + ui.setupUi(this); + + connect(ui.styleCombo, &QComboBox::textActivated, this, &StyleSheetEditor::setStyleName); + connect(ui.styleSheetCombo, &QComboBox::textActivated, this, &StyleSheetEditor::setStyleSheetName); + connect(ui.styleTextEdit, &QTextEdit::textChanged, this, &StyleSheetEditor::setModified); + connect(ui.applyButton, &QAbstractButton::clicked, this, &StyleSheetEditor::apply); + + QRegularExpression regExp("^.(.*)\\+?Style$"); + QString defaultStyle = QApplication::style()->metaObject()->className(); + QRegularExpressionMatch match = regExp.match(defaultStyle); + + if (match.hasMatch()) + defaultStyle = match.captured(1); + + ui.styleCombo->addItems(QStyleFactory::keys()); + ui.styleCombo->setCurrentIndex(ui.styleCombo->findText(defaultStyle, Qt::MatchContains)); + ui.styleSheetCombo->setCurrentIndex(ui.styleSheetCombo->findText("Coffee")); + loadStyleSheet("Coffee"); +} + +void StyleSheetEditor::setStyleName(const QString &styleName) +{ + qApp->setStyle(styleName); + ui.applyButton->setEnabled(false); +} + +void StyleSheetEditor::setStyleSheetName(const QString &sheetName) +{ + loadStyleSheet(sheetName); +} + +void StyleSheetEditor::setModified() +{ + ui.applyButton->setEnabled(true); +} + +void StyleSheetEditor::apply() +{ + qApp->setStyleSheet(ui.styleTextEdit->toPlainText()); + ui.applyButton->setEnabled(false); +} + +void StyleSheetEditor::loadStyleSheet(const QString &sheetName) +{ + QFile file(":/qss/" + sheetName.toLower() + ".qss"); + file.open(QFile::ReadOnly); + QString styleSheet = QString::fromLatin1(file.readAll()); + + ui.styleTextEdit->setPlainText(styleSheet); + qApp->setStyleSheet(styleSheet); + ui.applyButton->setEnabled(false); +} diff --git a/tests/manual/examples/widgets/widgets/stylesheet/stylesheeteditor.h b/tests/manual/examples/widgets/widgets/stylesheet/stylesheeteditor.h new file mode 100644 index 0000000000..e61534a4f9 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/stylesheeteditor.h @@ -0,0 +1,30 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef STYLESHEETEDITOR_H +#define STYLESHEETEDITOR_H + +#include <QDialog> + +#include "ui_stylesheeteditor.h" + +class StyleSheetEditor : public QDialog +{ + Q_OBJECT + +public: + StyleSheetEditor(QWidget *parent = nullptr); + +private slots: + void setStyleName(const QString &styleName); + void setStyleSheetName(const QString &styleSheetName); + void setModified(); + void apply(); + +private: + void loadStyleSheet(const QString &sheetName); + + Ui::StyleSheetEditor ui; +}; + +#endif diff --git a/tests/manual/examples/widgets/widgets/stylesheet/stylesheeteditor.ui b/tests/manual/examples/widgets/widgets/stylesheet/stylesheeteditor.ui new file mode 100644 index 0000000000..34cd7f6d04 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/stylesheet/stylesheeteditor.ui @@ -0,0 +1,171 @@ +<ui version="4.0" > + <class>StyleSheetEditor</class> + <widget class="QWidget" name="StyleSheetEditor" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>445</width> + <height>289</height> + </rect> + </property> + <property name="windowTitle" > + <string>Style Editor</string> + </property> + <layout class="QGridLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="0" column="6" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" > + <size> + <width>32</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" > + <size> + <width>32</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="5" > + <widget class="QComboBox" name="styleSheetCombo" > + <item> + <property name="text" > + <string>Default</string> + </property> + </item> + <item> + <property name="text" > + <string>Coffee</string> + </property> + </item> + <item> + <property name="text" > + <string>Pagefold</string> + </property> + </item> + </widget> + </item> + <item row="0" column="3" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" > + <size> + <width>10</width> + <height>16</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="2" > + <widget class="QComboBox" name="styleCombo" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QLabel" name="label_7" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Style:</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="7" > + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>321</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="applyButton" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>&Apply</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0" colspan="7" > + <widget class="QTextEdit" name="styleTextEdit" /> + </item> + <item row="0" column="4" > + <widget class="QLabel" name="label_8" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Style Sheet:</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tests/manual/examples/widgets/widgets/tetrix/CMakeLists.txt b/tests/manual/examples/widgets/widgets/tetrix/CMakeLists.txt new file mode 100644 index 0000000000..c591684ee6 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/tetrix/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(tetrix LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/tetrix") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(tetrix + main.cpp + tetrixboard.cpp tetrixboard.h + tetrixpiece.cpp tetrixpiece.h + tetrixwindow.cpp tetrixwindow.h +) + +set_target_properties(tetrix PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(tetrix PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS tetrix + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/widgets/tetrix/main.cpp b/tests/manual/examples/widgets/widgets/tetrix/main.cpp new file mode 100644 index 0000000000..24791bde26 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/tetrix/main.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "tetrixwindow.h" + +#include <QApplication> + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + TetrixWindow window; + window.show(); + return app.exec(); +} diff --git a/tests/manual/examples/widgets/widgets/tetrix/tetrix.pro b/tests/manual/examples/widgets/widgets/tetrix/tetrix.pro new file mode 100644 index 0000000000..bb9f855fb0 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/tetrix/tetrix.pro @@ -0,0 +1,13 @@ +QT += widgets + +HEADERS = tetrixboard.h \ + tetrixpiece.h \ + tetrixwindow.h +SOURCES = main.cpp \ + tetrixboard.cpp \ + tetrixpiece.cpp \ + tetrixwindow.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/tetrix +INSTALLS += target diff --git a/tests/manual/examples/widgets/widgets/tetrix/tetrixboard.cpp b/tests/manual/examples/widgets/widgets/tetrix/tetrixboard.cpp new file mode 100644 index 0000000000..0c5771ad89 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/tetrix/tetrixboard.cpp @@ -0,0 +1,371 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "tetrixboard.h" + +#include <QKeyEvent> +#include <QLabel> +#include <QPainter> + +//! [0] +TetrixBoard::TetrixBoard(QWidget *parent) + : QFrame(parent), isStarted(false), isPaused(false) +{ + setFrameStyle(QFrame::Panel | QFrame::Sunken); + setFocusPolicy(Qt::StrongFocus); + clearBoard(); + + nextPiece.setRandomShape(); +} +//! [0] + +//! [1] +void TetrixBoard::setNextPieceLabel(QLabel *label) +{ + nextPieceLabel = label; +} +//! [1] + +//! [2] +QSize TetrixBoard::sizeHint() const +{ + return QSize(BoardWidth * 15 + frameWidth() * 2, + BoardHeight * 15 + frameWidth() * 2); +} + +QSize TetrixBoard::minimumSizeHint() const +//! [2] //! [3] +{ + return QSize(BoardWidth * 5 + frameWidth() * 2, + BoardHeight * 5 + frameWidth() * 2); +} +//! [3] + +//! [4] +void TetrixBoard::start() +{ + if (isPaused) + return; + + isStarted = true; + isWaitingAfterLine = false; + numLinesRemoved = 0; + numPiecesDropped = 0; + score = 0; + level = 1; + clearBoard(); + + emit linesRemovedChanged(numLinesRemoved); + emit scoreChanged(score); + emit levelChanged(level); + + newPiece(); + timer.start(timeoutTime(), this); +} +//! [4] + +//! [5] +void TetrixBoard::pause() +{ + if (!isStarted) + return; + + isPaused = !isPaused; + if (isPaused) { + timer.stop(); + } else { + timer.start(timeoutTime(), this); + } + update(); +//! [5] //! [6] +} +//! [6] + +//! [7] +void TetrixBoard::paintEvent(QPaintEvent *event) +{ + QFrame::paintEvent(event); + + QPainter painter(this); + QRect rect = contentsRect(); +//! [7] + + if (isPaused) { + painter.drawText(rect, Qt::AlignCenter, tr("Pause")); + return; + } + +//! [8] + int boardTop = rect.bottom() - BoardHeight*squareHeight(); + + for (int i = 0; i < BoardHeight; ++i) { + for (int j = 0; j < BoardWidth; ++j) { + TetrixShape shape = shapeAt(j, BoardHeight - i - 1); + if (shape != NoShape) + drawSquare(painter, rect.left() + j * squareWidth(), + boardTop + i * squareHeight(), shape); + } +//! [8] //! [9] + } +//! [9] + +//! [10] + if (curPiece.shape() != NoShape) { + for (int i = 0; i < 4; ++i) { + int x = curX + curPiece.x(i); + int y = curY - curPiece.y(i); + drawSquare(painter, rect.left() + x * squareWidth(), + boardTop + (BoardHeight - y - 1) * squareHeight(), + curPiece.shape()); + } +//! [10] //! [11] + } +//! [11] //! [12] +} +//! [12] + +//! [13] +void TetrixBoard::keyPressEvent(QKeyEvent *event) +{ + if (!isStarted || isPaused || curPiece.shape() == NoShape) { + QFrame::keyPressEvent(event); + return; + } +//! [13] + +//! [14] + switch (event->key()) { + case Qt::Key_Left: + tryMove(curPiece, curX - 1, curY); + break; + case Qt::Key_Right: + tryMove(curPiece, curX + 1, curY); + break; + case Qt::Key_Down: + tryMove(curPiece.rotatedRight(), curX, curY); + break; + case Qt::Key_Up: + tryMove(curPiece.rotatedLeft(), curX, curY); + break; + case Qt::Key_Space: + dropDown(); + break; + case Qt::Key_D: + oneLineDown(); + break; + default: + QFrame::keyPressEvent(event); + } +//! [14] +} + +//! [15] +void TetrixBoard::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == timer.timerId()) { + if (isWaitingAfterLine) { + isWaitingAfterLine = false; + newPiece(); + timer.start(timeoutTime(), this); + } else { + oneLineDown(); + } + } else { + QFrame::timerEvent(event); +//! [15] //! [16] + } +//! [16] //! [17] +} +//! [17] + +//! [18] +void TetrixBoard::clearBoard() +{ + for (int i = 0; i < BoardHeight * BoardWidth; ++i) + board[i] = NoShape; +} +//! [18] + +//! [19] +void TetrixBoard::dropDown() +{ + int dropHeight = 0; + int newY = curY; + while (newY > 0) { + if (!tryMove(curPiece, curX, newY - 1)) + break; + --newY; + ++dropHeight; + } + pieceDropped(dropHeight); +//! [19] //! [20] +} +//! [20] + +//! [21] +void TetrixBoard::oneLineDown() +{ + if (!tryMove(curPiece, curX, curY - 1)) + pieceDropped(0); +} +//! [21] + +//! [22] +void TetrixBoard::pieceDropped(int dropHeight) +{ + for (int i = 0; i < 4; ++i) { + int x = curX + curPiece.x(i); + int y = curY - curPiece.y(i); + shapeAt(x, y) = curPiece.shape(); + } + + ++numPiecesDropped; + if (numPiecesDropped % 25 == 0) { + ++level; + timer.start(timeoutTime(), this); + emit levelChanged(level); + } + + score += dropHeight + 7; + emit scoreChanged(score); + removeFullLines(); + + if (!isWaitingAfterLine) + newPiece(); +//! [22] //! [23] +} +//! [23] + +//! [24] +void TetrixBoard::removeFullLines() +{ + int numFullLines = 0; + + for (int i = BoardHeight - 1; i >= 0; --i) { + bool lineIsFull = true; + + for (int j = 0; j < BoardWidth; ++j) { + if (shapeAt(j, i) == NoShape) { + lineIsFull = false; + break; + } + } + + if (lineIsFull) { +//! [24] //! [25] + ++numFullLines; + for (int k = i; k < BoardHeight - 1; ++k) { + for (int j = 0; j < BoardWidth; ++j) + shapeAt(j, k) = shapeAt(j, k + 1); + } +//! [25] //! [26] + for (int j = 0; j < BoardWidth; ++j) + shapeAt(j, BoardHeight - 1) = NoShape; + } +//! [26] //! [27] + } +//! [27] + +//! [28] + if (numFullLines > 0) { + numLinesRemoved += numFullLines; + score += 10 * numFullLines; + emit linesRemovedChanged(numLinesRemoved); + emit scoreChanged(score); + + timer.start(500, this); + isWaitingAfterLine = true; + curPiece.setShape(NoShape); + update(); + } +//! [28] //! [29] +} +//! [29] + +//! [30] +void TetrixBoard::newPiece() +{ + curPiece = nextPiece; + nextPiece.setRandomShape(); + showNextPiece(); + curX = BoardWidth / 2 + 1; + curY = BoardHeight - 1 + curPiece.minY(); + + if (!tryMove(curPiece, curX, curY)) { + curPiece.setShape(NoShape); + timer.stop(); + isStarted = false; + } +//! [30] //! [31] +} +//! [31] + +//! [32] +void TetrixBoard::showNextPiece() +{ + if (!nextPieceLabel) + return; + + int dx = nextPiece.maxX() - nextPiece.minX() + 1; + int dy = nextPiece.maxY() - nextPiece.minY() + 1; + + QPixmap pixmap(dx * squareWidth(), dy * squareHeight()); + QPainter painter(&pixmap); + painter.fillRect(pixmap.rect(), nextPieceLabel->palette().window()); + + for (int i = 0; i < 4; ++i) { + int x = nextPiece.x(i) - nextPiece.minX(); + int y = nextPiece.y(i) - nextPiece.minY(); + drawSquare(painter, x * squareWidth(), y * squareHeight(), + nextPiece.shape()); + } + nextPieceLabel->setPixmap(pixmap); +//! [32] //! [33] +} +//! [33] + +//! [34] +bool TetrixBoard::tryMove(const TetrixPiece &newPiece, int newX, int newY) +{ + for (int i = 0; i < 4; ++i) { + int x = newX + newPiece.x(i); + int y = newY - newPiece.y(i); + if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight) + return false; + if (shapeAt(x, y) != NoShape) + return false; + } +//! [34] + +//! [35] + curPiece = newPiece; + curX = newX; + curY = newY; + update(); + return true; +} +//! [35] + +//! [36] +void TetrixBoard::drawSquare(QPainter &painter, int x, int y, TetrixShape shape) +{ + static constexpr QRgb colorTable[8] = { + 0x000000, 0xCC6666, 0x66CC66, 0x6666CC, + 0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00 + }; + + QColor color = colorTable[int(shape)]; + painter.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2, + color); + + painter.setPen(color.lighter()); + painter.drawLine(x, y + squareHeight() - 1, x, y); + painter.drawLine(x, y, x + squareWidth() - 1, y); + + painter.setPen(color.darker()); + painter.drawLine(x + 1, y + squareHeight() - 1, + x + squareWidth() - 1, y + squareHeight() - 1); + painter.drawLine(x + squareWidth() - 1, y + squareHeight() - 1, + x + squareWidth() - 1, y + 1); +} +//! [36] diff --git a/tests/manual/examples/widgets/widgets/tetrix/tetrixboard.h b/tests/manual/examples/widgets/widgets/tetrix/tetrixboard.h new file mode 100644 index 0000000000..c2fe3fd01e --- /dev/null +++ b/tests/manual/examples/widgets/widgets/tetrix/tetrixboard.h @@ -0,0 +1,79 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef TETRIXBOARD_H +#define TETRIXBOARD_H + +#include <QBasicTimer> +#include <QFrame> +#include <QPointer> + +#include "tetrixpiece.h" + +QT_BEGIN_NAMESPACE +class QLabel; +QT_END_NAMESPACE + +//! [0] +class TetrixBoard : public QFrame +{ + Q_OBJECT + +public: + TetrixBoard(QWidget *parent = nullptr); + + void setNextPieceLabel(QLabel *label); + QSize sizeHint() const override; + QSize minimumSizeHint() const override; + +public slots: + void start(); + void pause(); + +signals: + void scoreChanged(int score); + void levelChanged(int level); + void linesRemovedChanged(int numLines); + +protected: + void paintEvent(QPaintEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void timerEvent(QTimerEvent *event) override; +//! [0] + +//! [1] +private: + enum { BoardWidth = 10, BoardHeight = 22 }; + + TetrixShape &shapeAt(int x, int y) { return board[(y * BoardWidth) + x]; } + int timeoutTime() { return 1000 / (1 + level); } + int squareWidth() { return contentsRect().width() / BoardWidth; } + int squareHeight() { return contentsRect().height() / BoardHeight; } + void clearBoard(); + void dropDown(); + void oneLineDown(); + void pieceDropped(int dropHeight); + void removeFullLines(); + void newPiece(); + void showNextPiece(); + bool tryMove(const TetrixPiece &newPiece, int newX, int newY); + void drawSquare(QPainter &painter, int x, int y, TetrixShape shape); + + QBasicTimer timer; + QPointer<QLabel> nextPieceLabel; + bool isStarted; + bool isPaused; + bool isWaitingAfterLine; + TetrixPiece curPiece; + TetrixPiece nextPiece; + int curX; + int curY; + int numLinesRemoved; + int numPiecesDropped; + int score; + int level; + TetrixShape board[BoardWidth * BoardHeight]; +}; +//! [1] + +#endif diff --git a/tests/manual/examples/widgets/widgets/tetrix/tetrixpiece.cpp b/tests/manual/examples/widgets/widgets/tetrix/tetrixpiece.cpp new file mode 100644 index 0000000000..5dc9e11c49 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/tetrix/tetrixpiece.cpp @@ -0,0 +1,106 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "tetrixpiece.h" + +#include <QtCore> + +//! [0] +void TetrixPiece::setRandomShape() +{ + setShape(TetrixShape(QRandomGenerator::global()->bounded(7) + 1)); +} +//! [0] + +//! [1] +void TetrixPiece::setShape(TetrixShape shape) +{ + static constexpr int coordsTable[8][4][2] = { + { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 0, -1 }, { 0, 0 }, { -1, 0 }, { -1, 1 } }, + { { 0, -1 }, { 0, 0 }, { 1, 0 }, { 1, 1 } }, + { { 0, -1 }, { 0, 0 }, { 0, 1 }, { 0, 2 } }, + { { -1, 0 }, { 0, 0 }, { 1, 0 }, { 0, 1 } }, + { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }, + { { -1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } }, + { { 1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } } + }; + + for (int i = 0; i < 4 ; i++) { + for (int j = 0; j < 2; ++j) + coords[i][j] = coordsTable[shape][i][j]; + } + pieceShape = shape; +//! [1] //! [2] +} +//! [2] + +//! [3] +int TetrixPiece::minX() const +{ + int min = coords[0][0]; + for (int i = 1; i < 4; ++i) + min = qMin(min, coords[i][0]); + return min; +} + +int TetrixPiece::maxX() const +//! [3] //! [4] +{ + int max = coords[0][0]; + for (int i = 1; i < 4; ++i) + max = qMax(max, coords[i][0]); + return max; +} +//! [4] + +//! [5] +int TetrixPiece::minY() const +{ + int min = coords[0][1]; + for (int i = 1; i < 4; ++i) + min = qMin(min, coords[i][1]); + return min; +} + +int TetrixPiece::maxY() const +//! [5] //! [6] +{ + int max = coords[0][1]; + for (int i = 1; i < 4; ++i) + max = qMax(max, coords[i][1]); + return max; +} +//! [6] + +//! [7] +TetrixPiece TetrixPiece::rotatedLeft() const +{ + if (pieceShape == SquareShape) + return *this; + + TetrixPiece result; + result.pieceShape = pieceShape; + for (int i = 0; i < 4; ++i) { + result.setX(i, y(i)); + result.setY(i, -x(i)); + } +//! [7] + return result; +} + +//! [9] +TetrixPiece TetrixPiece::rotatedRight() const +{ + if (pieceShape == SquareShape) + return *this; + + TetrixPiece result; + result.pieceShape = pieceShape; + for (int i = 0; i < 4; ++i) { + result.setX(i, -y(i)); + result.setY(i, x(i)); + } +//! [9] + return result; +} diff --git a/tests/manual/examples/widgets/widgets/tetrix/tetrixpiece.h b/tests/manual/examples/widgets/widgets/tetrix/tetrixpiece.h new file mode 100644 index 0000000000..86a513a76e --- /dev/null +++ b/tests/manual/examples/widgets/widgets/tetrix/tetrixpiece.h @@ -0,0 +1,38 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef TETRIXPIECE_H +#define TETRIXPIECE_H + +enum TetrixShape { NoShape, ZShape, SShape, LineShape, TShape, SquareShape, + LShape, MirroredLShape }; + +//! [0] +class TetrixPiece +{ +public: + TetrixPiece() { setShape(NoShape); } + + void setRandomShape(); + void setShape(TetrixShape shape); + + TetrixShape shape() const { return pieceShape; } + int x(int index) const { return coords[index][0]; } + int y(int index) const { return coords[index][1]; } + int minX() const; + int maxX() const; + int minY() const; + int maxY() const; + TetrixPiece rotatedLeft() const; + TetrixPiece rotatedRight() const; + +private: + void setX(int index, int x) { coords[index][0] = x; } + void setY(int index, int y) { coords[index][1] = y; } + + TetrixShape pieceShape; + int coords[4][2]; +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/tetrix/tetrixwindow.cpp b/tests/manual/examples/widgets/widgets/tetrix/tetrixwindow.cpp new file mode 100644 index 0000000000..ae10a778e7 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/tetrix/tetrixwindow.cpp @@ -0,0 +1,82 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "tetrixboard.h" +#include "tetrixwindow.h" + +#include <QCoreApplication> +#include <QGridLayout> +#include <QLabel> +#include <QLCDNumber> +#include <QPushButton> + +//! [0] +TetrixWindow::TetrixWindow(QWidget *parent) + : QWidget(parent), board(new TetrixBoard) +{ +//! [0] + nextPieceLabel = new QLabel; + nextPieceLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + nextPieceLabel->setAlignment(Qt::AlignCenter); + board->setNextPieceLabel(nextPieceLabel); +//! [1] + scoreLcd = new QLCDNumber(5); + scoreLcd->setSegmentStyle(QLCDNumber::Filled); +//! [1] + levelLcd = new QLCDNumber(2); + levelLcd->setSegmentStyle(QLCDNumber::Filled); + linesLcd = new QLCDNumber(5); + linesLcd->setSegmentStyle(QLCDNumber::Filled); + +//! [2] + startButton = new QPushButton(tr("&Start")); + startButton->setFocusPolicy(Qt::NoFocus); + quitButton = new QPushButton(tr("&Quit")); + quitButton->setFocusPolicy(Qt::NoFocus); + pauseButton = new QPushButton(tr("&Pause")); +//! [2] //! [3] + pauseButton->setFocusPolicy(Qt::NoFocus); +//! [3] //! [4] + + connect(startButton, &QPushButton::clicked, board, &TetrixBoard::start); +//! [4] //! [5] + connect(quitButton , &QPushButton::clicked, qApp, &QCoreApplication::quit); + connect(pauseButton, &QPushButton::clicked, board, &TetrixBoard::pause); + connect(board, &TetrixBoard::scoreChanged, + scoreLcd, qOverload<int>(&QLCDNumber::display)); + connect(board, &TetrixBoard::levelChanged, + levelLcd, qOverload<int>(&QLCDNumber::display)); + connect(board, &TetrixBoard::linesRemovedChanged, + linesLcd, qOverload<int>(&QLCDNumber::display)); +//! [5] + +//! [6] + QGridLayout *layout = new QGridLayout; + layout->addWidget(createLabel(tr("NEXT")), 0, 0); + layout->addWidget(nextPieceLabel, 1, 0); + layout->addWidget(createLabel(tr("LEVEL")), 2, 0); + layout->addWidget(levelLcd, 3, 0); + layout->addWidget(startButton, 4, 0); + layout->addWidget(board, 0, 1, 6, 1); + layout->addWidget(createLabel(tr("SCORE")), 0, 2); + layout->addWidget(scoreLcd, 1, 2); + layout->addWidget(createLabel(tr("LINES REMOVED")), 2, 2); + layout->addWidget(linesLcd, 3, 2); + layout->addWidget(quitButton, 4, 2); + layout->addWidget(pauseButton, 5, 2); + setLayout(layout); + + setWindowTitle(tr("Tetrix")); + resize(550, 370); +} +//! [6] + +//! [7] +QLabel *TetrixWindow::createLabel(const QString &text) +{ + QLabel *label = new QLabel(text); + label->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); + return label; +} +//! [7] + diff --git a/tests/manual/examples/widgets/widgets/tetrix/tetrixwindow.h b/tests/manual/examples/widgets/widgets/tetrix/tetrixwindow.h new file mode 100644 index 0000000000..2ed468717d --- /dev/null +++ b/tests/manual/examples/widgets/widgets/tetrix/tetrixwindow.h @@ -0,0 +1,38 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef TETRIXWINDOW_H +#define TETRIXWINDOW_H + +#include <QWidget> + +QT_BEGIN_NAMESPACE +class QLCDNumber; +class QLabel; +class QPushButton; +QT_END_NAMESPACE +class TetrixBoard; + +//! [0] +class TetrixWindow : public QWidget +{ + Q_OBJECT + +public: + TetrixWindow(QWidget *parent = nullptr); + +private: + QLabel *createLabel(const QString &text); + + TetrixBoard *board; + QLabel *nextPieceLabel; + QLCDNumber *scoreLcd; + QLCDNumber *levelLcd; + QLCDNumber *linesLcd; + QPushButton *startButton; + QPushButton *quitButton; + QPushButton *pauseButton; +}; +//! [0] + +#endif diff --git a/tests/manual/examples/widgets/widgets/validators/CMakeLists.txt b/tests/manual/examples/widgets/widgets/validators/CMakeLists.txt new file mode 100644 index 0000000000..653b8eba78 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(validators LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/validators") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(validators + ledwidget.cpp ledwidget.h + localeselector.cpp localeselector.h + main.cpp + validators.ui + validatorwidget.cpp validatorwidget.h +) + +set_target_properties(validators PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(validators PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +# Resources: +set(validators_resource_files + "ledoff.png" + "ledon.png" +) + +qt_add_resources(validators "validators" + PREFIX + "/" + FILES + ${validators_resource_files} +) + +install(TARGETS validators + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/examples/widgets/widgets/validators/ledoff.png b/tests/manual/examples/widgets/widgets/validators/ledoff.png Binary files differnew file mode 100644 index 0000000000..8b1f2ed123 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/ledoff.png diff --git a/tests/manual/examples/widgets/widgets/validators/ledon.png b/tests/manual/examples/widgets/widgets/validators/ledon.png Binary files differnew file mode 100644 index 0000000000..601c34d5a8 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/ledon.png diff --git a/tests/manual/examples/widgets/widgets/validators/ledwidget.cpp b/tests/manual/examples/widgets/widgets/validators/ledwidget.cpp new file mode 100644 index 0000000000..5b95595a75 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/ledwidget.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "ledwidget.h" + +LEDWidget::LEDWidget(QWidget *parent) + : QLabel(parent), onPixmap(":/ledon.png"), offPixmap(":/ledoff.png") +{ + setPixmap(offPixmap); + flashTimer.setInterval(200); + flashTimer.setSingleShot(true); + connect(&flashTimer, &QTimer::timeout, this, &LEDWidget::extinguish); +}; + +void LEDWidget::extinguish() +{ + setPixmap(offPixmap); +} + +void LEDWidget::flash() +{ + setPixmap(onPixmap); + flashTimer.start(); +} + diff --git a/tests/manual/examples/widgets/widgets/validators/ledwidget.h b/tests/manual/examples/widgets/widgets/validators/ledwidget.h new file mode 100644 index 0000000000..81215b668f --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/ledwidget.h @@ -0,0 +1,27 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef LEDWIDGET_H +#define LEDWIDGET_H + +#include <QLabel> +#include <QPixmap> +#include <QTimer> + +class LEDWidget : public QLabel +{ + Q_OBJECT +public: + LEDWidget(QWidget *parent = nullptr); +public slots: + void flash(); + +private slots: + void extinguish(); + +private: + QPixmap onPixmap, offPixmap; + QTimer flashTimer; +}; + +#endif // LEDWIDGET_H diff --git a/tests/manual/examples/widgets/widgets/validators/localeselector.cpp b/tests/manual/examples/widgets/widgets/validators/localeselector.cpp new file mode 100644 index 0000000000..c74faa8c9d --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/localeselector.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "localeselector.h" + +#include <QLocale> + +LocaleSelector::LocaleSelector(QWidget *parent) + : QComboBox(parent) +{ + int curIndex = -1; + int index = 0; + for (int _lang = QLocale::C; _lang <= QLocale::LastLanguage; ++_lang) { + QLocale::Language lang = static_cast<QLocale::Language>(_lang); + const QList<QLocale> locales = + QLocale::matchingLocales(lang, QLocale::AnyScript, QLocale::AnyTerritory); + for (const QLocale &l : locales) { + QString label = QLocale::languageToString(l.language()); + label += QLatin1Char('/'); + label += QLocale::territoryToString(l.territory()); + // distinguish locales by script, if there are more than one script for a language/territory pair + if (QLocale::matchingLocales(l.language(), QLocale::AnyScript, l.territory()).size() > 1) + label += QLatin1String(" (") + QLocale::scriptToString(l.script()) + QLatin1Char(')'); + + addItem(label, QVariant::fromValue(l)); + + if (l.language() == locale().language() && l.territory() == locale().territory() + && (locale().script() == QLocale::AnyScript || l.script() == locale().script())) { + curIndex = index; + } + ++index; + } + } + if (curIndex != -1) + setCurrentIndex(curIndex); + + connect(this, QOverload<int>::of(&LocaleSelector::activated), + this, &LocaleSelector::emitLocaleSelected); +} + +void LocaleSelector::emitLocaleSelected(int index) +{ + QVariant v = itemData(index); + if (!v.isValid()) + return; + const QLocale l = qvariant_cast<QLocale>(v); + emit localeSelected(l); +} diff --git a/tests/manual/examples/widgets/widgets/validators/localeselector.h b/tests/manual/examples/widgets/widgets/validators/localeselector.h new file mode 100644 index 0000000000..c684e18d40 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/localeselector.h @@ -0,0 +1,23 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef LOCALESELECTOR_H +#define LOCALESELECTOR_H + +#include <QComboBox> + +class LocaleSelector : public QComboBox +{ + Q_OBJECT + +public: + LocaleSelector(QWidget *parent = nullptr); + +signals: + void localeSelected(const QLocale &locale); + +private slots: + void emitLocaleSelected(int index); +}; + +#endif //LOCALESELECTOR_H diff --git a/tests/manual/examples/widgets/widgets/validators/main.cpp b/tests/manual/examples/widgets/widgets/validators/main.cpp new file mode 100644 index 0000000000..c09d428416 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/main.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "validatorwidget.h" + +#include <QApplication> + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + ValidatorWidget w; + w.show(); + + return app.exec(); +} diff --git a/tests/manual/examples/widgets/widgets/validators/validators.pro b/tests/manual/examples/widgets/widgets/validators/validators.pro new file mode 100644 index 0000000000..029cf95aca --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/validators.pro @@ -0,0 +1,12 @@ +QT += widgets +requires(qtConfig(combobox)) + +FORMS += validators.ui +RESOURCES += validators.qrc + +SOURCES += main.cpp ledwidget.cpp localeselector.cpp validatorwidget.cpp +HEADERS += ledwidget.h localeselector.h validatorwidget.h + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/validators +INSTALLS += target diff --git a/tests/manual/examples/widgets/widgets/validators/validators.qrc b/tests/manual/examples/widgets/widgets/validators/validators.qrc new file mode 100644 index 0000000000..94874317a8 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/validators.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/" > + <file>ledoff.png</file> + <file>ledon.png</file> + </qresource> +</RCC> diff --git a/tests/manual/examples/widgets/widgets/validators/validators.ui b/tests/manual/examples/widgets/widgets/validators/validators.ui new file mode 100644 index 0000000000..cd984e6b97 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/validators.ui @@ -0,0 +1,468 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ValidatorsForm</class> + <widget class="QWidget" name="ValidatorsForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>526</width> + <height>443</height> + </rect> + </property> + <property name="windowTitle"> + <string>Validators</string> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>9</number> + </property> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="LocaleSelector" name="localeSelector"/> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>QIntValidator</string> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>9</number> + </property> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QGridLayout"> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Min:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSpinBox" name="minVal"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimum"> + <number>-1000000</number> + </property> + <property name="maximum"> + <number>1000000</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Max:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="maxVal"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimum"> + <number>-1000000</number> + </property> + <property name="maximum"> + <number>1000000</number> + </property> + <property name="value"> + <number>1000</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QFrame" name="frame"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>9</number> + </property> + <item> + <widget class="LEDWidget" name="ledWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="pixmap"> + <pixmap resource="validators.qrc">:/ledoff.png</pixmap> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>editingFinished()</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="editor"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>QDoubleValidator</string> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>9</number> + </property> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QGridLayout"> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Min:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QDoubleSpinBox" name="doubleMinVal"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimum"> + <double>-100000.000000000000000</double> + </property> + <property name="maximum"> + <double>100000.000000000000000</double> + </property> + <property name="value"> + <double>0.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Format:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QComboBox" name="doubleFormat"> + <item> + <property name="text"> + <string>Standard</string> + </property> + </item> + <item> + <property name="text"> + <string>Scientific</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Max:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QDoubleSpinBox" name="doubleMaxVal"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimum"> + <double>-100000.000000000000000</double> + </property> + <property name="maximum"> + <double>100000.000000000000000</double> + </property> + <property name="value"> + <double>1000.000000000000000</double> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Decimals:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QSpinBox" name="doubleDecimals"> + <property name="value"> + <number>2</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QFrame" name="frame_2"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>9</number> + </property> + <item> + <widget class="LEDWidget" name="doubleLedWidget"> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="validators.qrc">:/ledoff.png</pixmap> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>editingFinished()</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="doubleEditor"/> + </item> + </layout> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>111</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton"> + <property name="text"> + <string>Quit</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>LEDWidget</class> + <extends>QLabel</extends> + <header>ledwidget.h</header> + </customwidget> + <customwidget> + <class>LocaleSelector</class> + <extends>QComboBox</extends> + <header>localeselector.h</header> + </customwidget> + </customwidgets> + <resources> + <include location="validators.qrc"/> + </resources> + <connections> + <connection> + <sender>pushButton</sender> + <signal>clicked()</signal> + <receiver>ValidatorsForm</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>94</x> + <y>274</y> + </hint> + <hint type="destinationlabel"> + <x>131</x> + <y>260</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tests/manual/examples/widgets/widgets/validators/validatorwidget.cpp b/tests/manual/examples/widgets/widgets/validators/validatorwidget.cpp new file mode 100644 index 0000000000..7782342221 --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/validatorwidget.cpp @@ -0,0 +1,75 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "validatorwidget.h" + +#include <QIntValidator> + +ValidatorWidget::ValidatorWidget(QWidget *parent) + : QWidget(parent) +{ + setupUi(this); + + connect(localeSelector, &LocaleSelector::localeSelected, + this, &ValidatorWidget::setLocale); + connect(localeSelector, &LocaleSelector::localeSelected, + this, &ValidatorWidget::updateValidator); + connect(localeSelector, &LocaleSelector::localeSelected, + this, &ValidatorWidget::updateDoubleValidator); + + connect(minVal, &QSpinBox::editingFinished, + this, &ValidatorWidget::updateValidator); + connect(maxVal, &QSpinBox::editingFinished, + this, &ValidatorWidget::updateValidator); + connect(editor, &QLineEdit::editingFinished, + ledWidget, &LEDWidget::flash); + + connect(doubleMaxVal, &QDoubleSpinBox::editingFinished, + this, &ValidatorWidget::updateDoubleValidator); + connect(doubleMinVal, &QDoubleSpinBox::editingFinished, + this, &ValidatorWidget::updateDoubleValidator); + connect(doubleDecimals, &QSpinBox::valueChanged, + this, &ValidatorWidget::updateDoubleValidator); + connect(doubleFormat, &QComboBox::activated, + this, &ValidatorWidget::updateDoubleValidator); + connect(doubleEditor, &QLineEdit::editingFinished, + doubleLedWidget, &LEDWidget::flash); + + updateValidator(); + updateDoubleValidator(); +} + +void ValidatorWidget::updateValidator() +{ + QIntValidator *v = new QIntValidator(minVal->value(), maxVal->value(), this); + v->setLocale(locale()); + delete editor->validator(); + editor->setValidator(v); + + QString s = editor->text(); + int i = 0; + if (v->validate(s, i) == QValidator::Invalid) { + editor->clear(); + } else { + editor->setText(s); + } +} + +void ValidatorWidget::updateDoubleValidator() +{ + QDoubleValidator *v + = new QDoubleValidator(doubleMinVal->value(), doubleMaxVal->value(), + doubleDecimals->value(), this); + v->setNotation(static_cast<QDoubleValidator::Notation>(doubleFormat->currentIndex())); + v->setLocale(locale()); + delete doubleEditor->validator(); + doubleEditor->setValidator(v); + + QString s = doubleEditor->text(); + int i = 0; + if (v->validate(s, i) == QValidator::Invalid) { + doubleEditor->clear(); + } else { + doubleEditor->setText(s); + } +} diff --git a/tests/manual/examples/widgets/widgets/validators/validatorwidget.h b/tests/manual/examples/widgets/widgets/validators/validatorwidget.h new file mode 100644 index 0000000000..d186c5863b --- /dev/null +++ b/tests/manual/examples/widgets/widgets/validators/validatorwidget.h @@ -0,0 +1,22 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef VALIDATORWIDGET_H +#define VALIDATORWIDGET_H + +#include <QWidget> + +#include "ui_validators.h" + +class ValidatorWidget : public QWidget, public Ui::ValidatorsForm +{ + Q_OBJECT +public: + ValidatorWidget(QWidget *parent = nullptr); + +private slots: + void updateValidator(); + void updateDoubleValidator(); +}; + +#endif // VALIDATORWIDGET_H |