qt5base-lts/examples/widgets/gallery/widgetgallery.cpp
Friedemann Kleint 7b0f341872 Add a widget gallery example
Since 072ca960f5 changed the default
of the styles example back to Norwegian Wood, it is no longer
suited as gallery example.

Extract the dialog from it and re-add it as a gallery example Add a
tooltip displaying the class name and a help shortcut opening the
documentation.

Restructure the group boxes to add more widgets.

Remove the gallery meta-tag from the styles example.

Task-number: PYSIDE-1112
Change-Id: Ie6f13084012771bd8f5bf9cad23b58d0720fdd92
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
2020-01-09 13:52:25 +01:00

475 lines
17 KiB
C++

/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "widgetgallery.h"
#include <QApplication>
#include <QCheckBox>
#include <QComboBox>
#include <QCommandLinkButton>
#include <QDateTimeEdit>
#include <QDial>
#include <QDialogButtonBox>
#include <QFileSystemModel>
#include <QGridLayout>
#include <QGroupBox>
#include <QMenu>
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
#include <QPlainTextEdit>
#include <QProgressBar>
#include <QPushButton>
#include <QRadioButton>
#include <QScrollBar>
#include <QShortcut>
#include <QSpinBox>
#include <QStandardItemModel>
#include <QStyle>
#include <QStyleFactory>
#include <QTextBrowser>
#include <QTreeView>
#include <QTableWidget>
#include <QTextEdit>
#include <QToolBox>
#include <QToolButton>
#include <QIcon>
#include <QDesktopServices>
#include <QScreen>
#include <QWindow>
#include <QDebug>
#include <QLibraryInfo>
#include <QSysInfo>
#include <QTextStream>
#include <QTimer>
static inline QString className(const QObject *o)
{
return QString::fromUtf8(o->metaObject()->className());
}
static inline void setClassNameToolTip(QWidget *w)
{
w->setToolTip(className(w));
}
static QString helpUrl(const QString &page)
{
QString result;
QTextStream(&result) << "https://doc.qt.io/qt-" << QT_VERSION_MAJOR
<< '/' << page << ".html";
return result;
}
static inline QString helpUrl(const QWidget *w)
{
return helpUrl(className(w).toLower());
}
static void launchHelp(const QWidget *w)
{
QDesktopServices::openUrl(helpUrl(w));
}
static void launchModuleHelp()
{
QDesktopServices::openUrl(helpUrl(QLatin1String("qtwidgets-index")));
}
template <class Widget>
Widget *createWidget(const char *name, QWidget *parent = nullptr)
{
auto result = new Widget(parent);
result->setObjectName(QLatin1String(name));
setClassNameToolTip(result);
return result;
}
template <class Widget, class Parameter>
Widget *createWidget1(const Parameter &p1, const char *name, QWidget *parent = nullptr)
{
auto result = new Widget(p1, parent);
result->setObjectName(QLatin1String(name));
setClassNameToolTip(result);
return result;
}
QTextStream &operator<<(QTextStream &str, const QRect &r)
{
str << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y()
<< Qt::noforcesign;
return str;
}
static QString highDpiScaleFactorRoundingPolicy()
{
QString result;
QDebug(&result) << QGuiApplication::highDpiScaleFactorRoundingPolicy();
if (result.endsWith(QLatin1Char(')')))
result.chop(1);
const int lastSep = result.lastIndexOf(QLatin1String("::"));
if (lastSep != -1)
result.remove(0, lastSep + 2);
return result;
}
WidgetGallery::WidgetGallery(QWidget *parent)
: QDialog(parent)
, progressBar(createProgressBar())
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
auto styleComboBox = createWidget<QComboBox>("styleComboBox");
const QString defaultStyleName = QApplication::style()->objectName();
QStringList styleNames = QStyleFactory::keys();
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);
auto styleLabel = createWidget1<QLabel>(tr("&Style:"), "styleLabel");
styleLabel->setBuddy(styleComboBox);
auto helpLabel = createWidget1<QLabel>(tr("Press F1 over a widget to see Documentation"), "helpLabel");
auto disableWidgetsCheckBox = createWidget1<QCheckBox>(tr("&Disable widgets"), "disableWidgetsCheckBox");
auto buttonsGroupBox = createButtonsGroupBox();
auto itemViewTabWidget = createItemViewTabWidget();
auto simpleInputWidgetsGroupBox = createSimpleInputWidgetsGroupBox();
auto textToolBox = createTextToolBox();
connect(styleComboBox, &QComboBox::textActivated,
this, &WidgetGallery::changeStyle);
connect(disableWidgetsCheckBox, &QCheckBox::toggled,
buttonsGroupBox, &QWidget::setDisabled);
connect(disableWidgetsCheckBox, &QCheckBox::toggled,
textToolBox, &QWidget::setDisabled);
connect(disableWidgetsCheckBox, &QCheckBox::toggled,
itemViewTabWidget, &QWidget::setDisabled);
connect(disableWidgetsCheckBox, &QCheckBox::toggled,
simpleInputWidgetsGroupBox, &QWidget::setDisabled);
auto topLayout = new QHBoxLayout;
topLayout->addWidget(styleLabel);
topLayout->addWidget(styleComboBox);
topLayout->addStretch(1);
topLayout->addWidget(helpLabel);
topLayout->addStretch(1);
topLayout->addWidget(disableWidgetsCheckBox);
auto dialogButtonBox = createWidget1<QDialogButtonBox>(QDialogButtonBox::Help | QDialogButtonBox::Close,
"dialogButtonBox");
connect(dialogButtonBox, &QDialogButtonBox::helpRequested, this, launchModuleHelp);
connect(dialogButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto mainLayout = new QGridLayout(this);
mainLayout->addLayout(topLayout, 0, 0, 1, 2);
mainLayout->addWidget(buttonsGroupBox, 1, 0);
mainLayout->addWidget(simpleInputWidgetsGroupBox, 1, 1);
mainLayout->addWidget(itemViewTabWidget, 2, 0);
mainLayout->addWidget(textToolBox, 2, 1);
mainLayout->addWidget(progressBar, 3, 0, 1, 2);
mainLayout->addWidget(dialogButtonBox, 4, 0, 1, 2);
setWindowTitle(tr("Widget Gallery Qt %1").arg(QT_VERSION_STR));
new QShortcut(QKeySequence::HelpContents, this, this, &WidgetGallery::helpOnCurrentWidget);
}
void WidgetGallery::setVisible(bool visible)
{
QDialog::setVisible(visible);
if (visible) {
connect(windowHandle(), &QWindow::screenChanged, this, &WidgetGallery::updateSystemInfo);
updateSystemInfo();
}
}
void WidgetGallery::changeStyle(const QString &styleName)
{
QApplication::setStyle(QStyleFactory::create(styleName));
}
void WidgetGallery::advanceProgressBar()
{
int curVal = progressBar->value();
int maxVal = progressBar->maximum();
progressBar->setValue(curVal + (maxVal - curVal) / 100);
}
QGroupBox *WidgetGallery::createButtonsGroupBox()
{
auto result = createWidget1<QGroupBox>(tr("Buttons"), "buttonsGroupBox");
auto defaultPushButton = createWidget1<QPushButton>(tr("Default Push Button"), "defaultPushButton");
defaultPushButton->setDefault(true);
auto togglePushButton = createWidget1<QPushButton>(tr("Toggle Push Button"), "togglePushButton");
togglePushButton->setCheckable(true);
togglePushButton->setChecked(true);
auto flatPushButton = createWidget1<QPushButton>(tr("Flat Push Button"), "flatPushButton");
flatPushButton->setFlat(true);
auto toolButton = createWidget<QToolButton>("toolButton");
toolButton->setText(tr("Tool Button"));
auto menuToolButton = createWidget<QToolButton>("menuButton");
menuToolButton->setText(tr("Menu Button"));
auto toolMenu = new QMenu(menuToolButton);
menuToolButton->setPopupMode(QToolButton::InstantPopup);
toolMenu->addAction("Option");
toolMenu->addSeparator();
auto action = toolMenu->addAction("Checkable Option");
action->setCheckable(true);
menuToolButton->setMenu(toolMenu);
auto toolLayout = new QHBoxLayout;
toolLayout->addWidget(toolButton);
toolLayout->addWidget(menuToolButton);
auto commandLinkButton = createWidget1<QCommandLinkButton>(tr("Command Link Button"), "commandLinkButton");
commandLinkButton->setDescription(tr("Description"));
auto buttonLayout = new QVBoxLayout;
buttonLayout->addWidget(defaultPushButton);
buttonLayout->addWidget(togglePushButton);
buttonLayout->addWidget(flatPushButton);
buttonLayout->addLayout(toolLayout);
buttonLayout->addWidget(commandLinkButton);
buttonLayout->addStretch(1);
auto radioButton1 = createWidget1<QRadioButton>(tr("Radio button 1"), "radioButton1");
auto radioButton2 = createWidget1<QRadioButton>(tr("Radio button 2"), "radioButton2");
auto radioButton3 = createWidget1<QRadioButton>(tr("Radio button 3"), "radioButton3");
radioButton1->setChecked(true);
auto checkBox = createWidget1<QCheckBox>(tr("Tri-state check box"), "checkBox");
checkBox->setTristate(true);
checkBox->setCheckState(Qt::PartiallyChecked);
auto checkableLayout = new QVBoxLayout;
checkableLayout->addWidget(radioButton1);
checkableLayout->addWidget(radioButton2);
checkableLayout->addWidget(radioButton3);
checkableLayout->addWidget(checkBox);
checkableLayout->addStretch(1);
auto mainLayout = new QHBoxLayout(result);
mainLayout->addLayout(buttonLayout);
mainLayout->addLayout(checkableLayout);
mainLayout->addStretch();
return result;
}
static QWidget *embedIntoHBoxLayout(QWidget *w, int margin = 5)
{
auto result = new QWidget;
auto layout = new QHBoxLayout(result);
layout->setContentsMargins(margin, margin, margin, margin);
layout->addWidget(w);
return result;
}
QToolBox *WidgetGallery::createTextToolBox()
{
auto result = createWidget<QToolBox>("toolBox");
const QString plainText = 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");
// Create centered/italic HTML rich text
QString richText = QLatin1String("<html><head/><body><i>");
for (const auto &line : plainText.splitRef(QLatin1Char('\n')))
richText += QLatin1String("<center>") + line + QLatin1String("</center>");
richText += QLatin1String("</i></body></html>");
auto textEdit = createWidget1<QTextEdit>(richText, "textEdit");
auto plainTextEdit = createWidget1<QPlainTextEdit>(plainText, "plainTextEdit");
systemInfoTextBrowser = createWidget<QTextBrowser>("systemInfoTextBrowser");
result->addItem(embedIntoHBoxLayout(textEdit), tr("Text Edit"));
result->addItem(embedIntoHBoxLayout(plainTextEdit), tr("Plain Text Edit"));
result->addItem(embedIntoHBoxLayout(systemInfoTextBrowser), tr("Text Browser"));
return result;
}
QTabWidget *WidgetGallery::createItemViewTabWidget()
{
auto result = createWidget<QTabWidget>("bottomLeftTabWidget");
result->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
auto treeView = createWidget<QTreeView>("treeView");
auto fileSystemModel = new QFileSystemModel(treeView);
fileSystemModel->setRootPath(QDir::rootPath());
treeView->setModel(fileSystemModel);
auto tableWidget = createWidget<QTableWidget>("tableWidget");
tableWidget->setRowCount(10);
tableWidget->setColumnCount(10);
auto listModel = new QStandardItemModel(0, 1, result);
listModel->appendRow(new QStandardItem(QIcon(QLatin1String(":/qt-project.org/styles/commonstyle/images/diropen-128.png")),
tr("Directory")));
listModel->appendRow(new QStandardItem(QIcon(QLatin1String(":/qt-project.org/styles/commonstyle/images/computer-32.png")),
tr("Computer")));
auto listView = createWidget<QListView>("listView");
listView->setModel(listModel);
auto iconModeListView = createWidget<QListView>("iconModeListView");
iconModeListView->setViewMode(QListView::IconMode);
iconModeListView->setModel(listModel);
result->addTab(embedIntoHBoxLayout(treeView), tr("&Tree View"));
result->addTab(embedIntoHBoxLayout(tableWidget), tr("T&able"));
result->addTab(embedIntoHBoxLayout(listView), tr("&List"));
result->addTab(embedIntoHBoxLayout(iconModeListView), tr("&Icon Mode List"));
return result;
}
QGroupBox *WidgetGallery::createSimpleInputWidgetsGroupBox()
{
auto result = createWidget1<QGroupBox>(tr("Simple Input Widgets"), "bottomRightGroupBox");
result->setCheckable(true);
result->setChecked(true);
auto lineEdit = createWidget1<QLineEdit>("s3cRe7", "lineEdit");
lineEdit->setClearButtonEnabled(true);
lineEdit->setEchoMode(QLineEdit::Password);
auto spinBox = createWidget<QSpinBox>("spinBox", result);
spinBox->setValue(50);
auto dateTimeEdit = createWidget<QDateTimeEdit>("dateTimeEdit", result);
dateTimeEdit->setDateTime(QDateTime::currentDateTime());
auto slider = createWidget<QSlider>("slider", result);
slider->setOrientation(Qt::Horizontal);
slider->setValue(40);
auto scrollBar = createWidget<QScrollBar>("scrollBar", result);
scrollBar->setOrientation(Qt::Horizontal);
setClassNameToolTip(scrollBar);
scrollBar->setValue(60);
auto dial = createWidget<QDial>("dial", result);
dial->setValue(30);
dial->setNotchesVisible(true);
auto layout = new QGridLayout(result);
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);
return result;
}
QProgressBar *WidgetGallery::createProgressBar()
{
auto result = createWidget<QProgressBar>("progressBar");
result->setRange(0, 10000);
result->setValue(0);
auto timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &WidgetGallery::advanceProgressBar);
timer->start(1000);
return result;
}
void WidgetGallery::updateSystemInfo()
{
QString systemInfo;
QTextStream str(&systemInfo);
str << "<html><head/><body><h3>Build</h3><p>" << QLibraryInfo::build() << "</p>"
<< "<h3>Operating System</h3><p>" << QSysInfo::prettyProductName() << "</p>"
<< "<h3>Screens</h3><p>High DPI scale factor rounding policy: "
<< highDpiScaleFactorRoundingPolicy() << "</p><ol>";
const auto screens = QGuiApplication::screens();
for (auto screen : screens) {
const bool current = screen == this->screen();
str << "<li>";
if (current)
str << "<i>";
str << '"' << screen->name() << "\" " << screen->geometry() << ", "
<< screen->logicalDotsPerInchX() << "DPI, DPR="
<< screen->devicePixelRatio();
if (current)
str << "</i>";
str << "</li>";
}
str << "</ol></body></html>";
systemInfoTextBrowser->setHtml(systemInfo);
}
void WidgetGallery::helpOnCurrentWidget()
{
// Skip over internal widgets
for (auto w = QApplication::widgetAt(QCursor::pos(screen())); w; w = w->parentWidget()) {
const QString name = w->objectName();
if (!name.isEmpty() && !name.startsWith(QLatin1String("qt_"))) {
launchHelp(w);
break;
}
}
}