6.5.3 clean

This commit is contained in:
kleuter
2023-11-01 18:02:52 +01:00
parent bbe896803b
commit 7018d9e6c8
2170 changed files with 57471 additions and 43550 deletions

View File

@ -9,7 +9,6 @@ if(QT_FEATURE_animation)
endif()
add_subdirectory(desktop)
add_subdirectory(dialogs)
add_subdirectory(effects)
qt_internal_add_example(gallery)
add_subdirectory(gestures)
add_subdirectory(graphicsview)
@ -17,7 +16,6 @@ add_subdirectory(itemviews)
add_subdirectory(layouts)
add_subdirectory(painting)
add_subdirectory(richtext)
add_subdirectory(scroller)
add_subdirectory(tools)
add_subdirectory(touch)
add_subdirectory(tutorials)
@ -28,6 +26,3 @@ endif()
if(QT_FEATURE_cursor)
add_subdirectory(mainwindows)
endif()
if(QT_FEATURE_opengl AND TARGET Qt6::Gui)
qt_internal_add_example(windowcontainer)
endif()

View File

@ -6,7 +6,6 @@
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(easing);
QApplication app(argc, argv);
Window w;

View File

@ -4,6 +4,7 @@
/*!
\example desktop/systray
\title System Tray Icon Example
\examplecategory {Desktop}
\ingroup examples-widgets
\brief The System Tray Icon example shows how to add an icon with a menu
and popup messages to a desktop environment's system tray.

View File

@ -10,8 +10,6 @@
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(systray);
QApplication app(argc, argv);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {

View File

@ -2,12 +2,10 @@
# SPDX-License-Identifier: BSD-3-Clause
if(QT_FEATURE_wizard)
qt_internal_add_example(classwizard)
qt_internal_add_example(trivialwizard)
if(Qt6::PrintSupport)
qt_internal_add_example(licensewizard)
endif()
endif()
qt_internal_add_example(extension)
qt_internal_add_example(standarddialogs)
qt_internal_add_example(tabdialog)
if(QT_FEATURE_wizard AND TARGET Qt6::PrintSupport)
qt_internal_add_example(licensewizard)
endif()

View File

@ -1,55 +0,0 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(classwizard LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/dialogs/classwizard")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(classwizard
classwizard.cpp classwizard.h
main.cpp
)
set_target_properties(classwizard PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(classwizard PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(classwizard_resource_files
"images/background.png"
"images/banner.png"
"images/logo1.png"
"images/logo2.png"
"images/logo3.png"
"images/watermark1.png"
"images/watermark2.png"
)
qt_add_resources(classwizard "classwizard"
PREFIX
"/"
FILES
${classwizard_resource_files}
)
install(TARGETS classwizard
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -1,394 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "classwizard.h"
//! [0] //! [1]
ClassWizard::ClassWizard(QWidget *parent)
: QWizard(parent)
{
addPage(new IntroPage);
addPage(new ClassInfoPage);
addPage(new CodeStylePage);
addPage(new OutputFilesPage);
addPage(new ConclusionPage);
//! [0]
setPixmap(QWizard::BannerPixmap, QPixmap(":/images/banner.png"));
setPixmap(QWizard::BackgroundPixmap, QPixmap(":/images/background.png"));
setWindowTitle(tr("Class Wizard"));
//! [2]
}
//! [1] //! [2]
//! [3]
void ClassWizard::accept()
//! [3] //! [4]
{
QByteArray className = field("className").toByteArray();
QByteArray baseClass = field("baseClass").toByteArray();
QByteArray macroName = field("macroName").toByteArray();
QByteArray baseInclude = field("baseInclude").toByteArray();
QString outputDir = field("outputDir").toString();
QString header = field("header").toString();
QString implementation = field("implementation").toString();
//! [4]
QByteArray block;
if (field("comment").toBool()) {
block += "/*\n";
block += " " + header.toLatin1() + '\n';
block += "*/\n";
block += '\n';
}
if (field("protect").toBool()) {
block += "#ifndef " + macroName + '\n';
block += "#define " + macroName + '\n';
block += '\n';
}
if (field("includeBase").toBool()) {
block += "#include " + baseInclude + '\n';
block += '\n';
}
block += "class " + className;
if (!baseClass.isEmpty())
block += " : public " + baseClass;
block += '\n';
block += "{\n";
/* qmake ignore Q_OBJECT */
if (field("qobjectMacro").toBool()) {
block += " Q_OBJECT\n";
block += '\n';
}
block += "public:\n";
if (field("qobjectCtor").toBool()) {
block += " " + className + "(QObject *parent = nullptr);\n";
} else if (field("qwidgetCtor").toBool()) {
block += " " + className + "(QWidget *parent = nullptr);\n";
} else if (field("defaultCtor").toBool()) {
block += " " + className + "();\n";
if (field("copyCtor").toBool()) {
block += " " + className + "(const " + className + " &other);\n";
block += '\n';
block += " " + className + " &operator=" + "(const " + className
+ " &other);\n";
}
}
block += "};\n";
if (field("protect").toBool()) {
block += '\n';
block += "#endif\n";
}
QFile headerFile(outputDir + '/' + header);
if (!headerFile.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(nullptr, QObject::tr("Simple Wizard"),
QObject::tr("Cannot write file %1:\n%2")
.arg(headerFile.fileName())
.arg(headerFile.errorString()));
return;
}
headerFile.write(block);
block.clear();
if (field("comment").toBool()) {
block += "/*\n";
block += " " + implementation.toLatin1() + '\n';
block += "*/\n";
block += '\n';
}
block += "#include \"" + header.toLatin1() + "\"\n";
block += '\n';
if (field("qobjectCtor").toBool()) {
block += className + "::" + className + "(QObject *parent)\n";
block += " : " + baseClass + "(parent)\n";
block += "{\n";
block += "}\n";
} else if (field("qwidgetCtor").toBool()) {
block += className + "::" + className + "(QWidget *parent)\n";
block += " : " + baseClass + "(parent)\n";
block += "{\n";
block += "}\n";
} else if (field("defaultCtor").toBool()) {
block += className + "::" + className + "()\n";
block += "{\n";
block += " // missing code\n";
block += "}\n";
if (field("copyCtor").toBool()) {
block += "\n";
block += className + "::" + className + "(const " + className
+ " &other)\n";
block += "{\n";
block += " *this = other;\n";
block += "}\n";
block += '\n';
block += className + " &" + className + "::operator=(const "
+ className + " &other)\n";
block += "{\n";
if (!baseClass.isEmpty())
block += " " + baseClass + "::operator=(other);\n";
block += " // missing code\n";
block += " return *this;\n";
block += "}\n";
}
}
QFile implementationFile(outputDir + '/' + implementation);
if (!implementationFile.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(nullptr, QObject::tr("Simple Wizard"),
QObject::tr("Cannot write file %1:\n%2")
.arg(implementationFile.fileName())
.arg(implementationFile.errorString()));
return;
}
implementationFile.write(block);
//! [5]
QDialog::accept();
//! [5] //! [6]
}
//! [6]
//! [7]
IntroPage::IntroPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Introduction"));
setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark1.png"));
label = new QLabel(tr("This wizard will generate a skeleton C++ class "
"definition, including a few functions. You simply "
"need to specify the class name and set a few "
"options to produce a header file and an "
"implementation file for your new C++ class."));
label->setWordWrap(true);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(label);
setLayout(layout);
}
//! [7]
//! [8] //! [9]
ClassInfoPage::ClassInfoPage(QWidget *parent)
: QWizardPage(parent)
{
//! [8]
setTitle(tr("Class Information"));
setSubTitle(tr("Specify basic information about the class for which you "
"want to generate skeleton source code files."));
setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png"));
//! [10]
classNameLabel = new QLabel(tr("&Class name:"));
classNameLineEdit = new QLineEdit;
classNameLabel->setBuddy(classNameLineEdit);
baseClassLabel = new QLabel(tr("B&ase class:"));
baseClassLineEdit = new QLineEdit;
baseClassLabel->setBuddy(baseClassLineEdit);
qobjectMacroCheckBox = new QCheckBox(tr("Generate Q_OBJECT &macro"));
//! [10]
groupBox = new QGroupBox(tr("C&onstructor"));
//! [9]
qobjectCtorRadioButton = new QRadioButton(tr("&QObject-style constructor"));
qwidgetCtorRadioButton = new QRadioButton(tr("Q&Widget-style constructor"));
defaultCtorRadioButton = new QRadioButton(tr("&Default constructor"));
copyCtorCheckBox = new QCheckBox(tr("&Generate copy constructor and "
"operator="));
defaultCtorRadioButton->setChecked(true);
connect(defaultCtorRadioButton, &QAbstractButton::toggled,
copyCtorCheckBox, &QWidget::setEnabled);
//! [11] //! [12]
registerField("className*", classNameLineEdit);
registerField("baseClass", baseClassLineEdit);
registerField("qobjectMacro", qobjectMacroCheckBox);
//! [11]
registerField("qobjectCtor", qobjectCtorRadioButton);
registerField("qwidgetCtor", qwidgetCtorRadioButton);
registerField("defaultCtor", defaultCtorRadioButton);
registerField("copyCtor", copyCtorCheckBox);
QVBoxLayout *groupBoxLayout = new QVBoxLayout;
//! [12]
groupBoxLayout->addWidget(qobjectCtorRadioButton);
groupBoxLayout->addWidget(qwidgetCtorRadioButton);
groupBoxLayout->addWidget(defaultCtorRadioButton);
groupBoxLayout->addWidget(copyCtorCheckBox);
groupBox->setLayout(groupBoxLayout);
QGridLayout *layout = new QGridLayout;
layout->addWidget(classNameLabel, 0, 0);
layout->addWidget(classNameLineEdit, 0, 1);
layout->addWidget(baseClassLabel, 1, 0);
layout->addWidget(baseClassLineEdit, 1, 1);
layout->addWidget(qobjectMacroCheckBox, 2, 0, 1, 2);
layout->addWidget(groupBox, 3, 0, 1, 2);
setLayout(layout);
//! [13]
}
//! [13]
//! [14]
CodeStylePage::CodeStylePage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Code Style Options"));
setSubTitle(tr("Choose the formatting of the generated code."));
setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo2.png"));
commentCheckBox = new QCheckBox(tr("&Start generated files with a "
//! [14]
"comment"));
commentCheckBox->setChecked(true);
protectCheckBox = new QCheckBox(tr("&Protect header file against multiple "
"inclusions"));
protectCheckBox->setChecked(true);
macroNameLabel = new QLabel(tr("&Macro name:"));
macroNameLineEdit = new QLineEdit;
macroNameLabel->setBuddy(macroNameLineEdit);
includeBaseCheckBox = new QCheckBox(tr("&Include base class definition"));
baseIncludeLabel = new QLabel(tr("Base class include:"));
baseIncludeLineEdit = new QLineEdit;
baseIncludeLabel->setBuddy(baseIncludeLineEdit);
connect(protectCheckBox, &QAbstractButton::toggled,
macroNameLabel, &QWidget::setEnabled);
connect(protectCheckBox, &QAbstractButton::toggled,
macroNameLineEdit, &QWidget::setEnabled);
connect(includeBaseCheckBox, &QAbstractButton::toggled,
baseIncludeLabel, &QWidget::setEnabled);
connect(includeBaseCheckBox, &QAbstractButton::toggled,
baseIncludeLineEdit, &QWidget::setEnabled);
registerField("comment", commentCheckBox);
registerField("protect", protectCheckBox);
registerField("macroName", macroNameLineEdit);
registerField("includeBase", includeBaseCheckBox);
registerField("baseInclude", baseIncludeLineEdit);
QGridLayout *layout = new QGridLayout;
layout->setColumnMinimumWidth(0, 20);
layout->addWidget(commentCheckBox, 0, 0, 1, 3);
layout->addWidget(protectCheckBox, 1, 0, 1, 3);
layout->addWidget(macroNameLabel, 2, 1);
layout->addWidget(macroNameLineEdit, 2, 2);
layout->addWidget(includeBaseCheckBox, 3, 0, 1, 3);
layout->addWidget(baseIncludeLabel, 4, 1);
layout->addWidget(baseIncludeLineEdit, 4, 2);
//! [15]
setLayout(layout);
}
//! [15]
//! [16]
void CodeStylePage::initializePage()
{
QString className = field("className").toString();
macroNameLineEdit->setText(className.toUpper() + "_H");
QString baseClass = field("baseClass").toString();
includeBaseCheckBox->setChecked(!baseClass.isEmpty());
includeBaseCheckBox->setEnabled(!baseClass.isEmpty());
baseIncludeLabel->setEnabled(!baseClass.isEmpty());
baseIncludeLineEdit->setEnabled(!baseClass.isEmpty());
QRegularExpression rx("Q[A-Z].*");
if (baseClass.isEmpty()) {
baseIncludeLineEdit->clear();
} else if (rx.match(baseClass).hasMatch()) {
baseIncludeLineEdit->setText('<' + baseClass + '>');
} else {
baseIncludeLineEdit->setText('"' + baseClass.toLower() + ".h\"");
}
}
//! [16]
OutputFilesPage::OutputFilesPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Output Files"));
setSubTitle(tr("Specify where you want the wizard to put the generated "
"skeleton code."));
setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo3.png"));
outputDirLabel = new QLabel(tr("&Output directory:"));
outputDirLineEdit = new QLineEdit;
outputDirLabel->setBuddy(outputDirLineEdit);
headerLabel = new QLabel(tr("&Header file name:"));
headerLineEdit = new QLineEdit;
headerLabel->setBuddy(headerLineEdit);
implementationLabel = new QLabel(tr("&Implementation file name:"));
implementationLineEdit = new QLineEdit;
implementationLabel->setBuddy(implementationLineEdit);
registerField("outputDir*", outputDirLineEdit);
registerField("header*", headerLineEdit);
registerField("implementation*", implementationLineEdit);
QGridLayout *layout = new QGridLayout;
layout->addWidget(outputDirLabel, 0, 0);
layout->addWidget(outputDirLineEdit, 0, 1);
layout->addWidget(headerLabel, 1, 0);
layout->addWidget(headerLineEdit, 1, 1);
layout->addWidget(implementationLabel, 2, 0);
layout->addWidget(implementationLineEdit, 2, 1);
setLayout(layout);
}
//! [17]
void OutputFilesPage::initializePage()
{
QString className = field("className").toString();
headerLineEdit->setText(className.toLower() + ".h");
implementationLineEdit->setText(className.toLower() + ".cpp");
outputDirLineEdit->setText(QDir::toNativeSeparators(QDir::tempPath()));
}
//! [17]
ConclusionPage::ConclusionPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Conclusion"));
setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark2.png"));
label = new QLabel;
label->setWordWrap(true);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(label);
setLayout(layout);
}
void ConclusionPage::initializePage()
{
QString finishText = wizard()->buttonText(QWizard::FinishButton);
finishText.remove('&');
label->setText(tr("Click %1 to generate the class skeleton.")
.arg(finishText));
}

View File

@ -1,119 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef CLASSWIZARD_H
#define CLASSWIZARD_H
#include <QWizard>
QT_BEGIN_NAMESPACE
class QCheckBox;
class QGroupBox;
class QLabel;
class QLineEdit;
class QRadioButton;
QT_END_NAMESPACE
//! [0]
class ClassWizard : public QWizard
{
Q_OBJECT
public:
ClassWizard(QWidget *parent = nullptr);
void accept() override;
};
//! [0]
//! [1]
class IntroPage : public QWizardPage
{
Q_OBJECT
public:
IntroPage(QWidget *parent = nullptr);
private:
QLabel *label;
};
//! [1]
//! [2]
class ClassInfoPage : public QWizardPage
{
Q_OBJECT
public:
ClassInfoPage(QWidget *parent = nullptr);
private:
QLabel *classNameLabel;
QLabel *baseClassLabel;
QLineEdit *classNameLineEdit;
QLineEdit *baseClassLineEdit;
QCheckBox *qobjectMacroCheckBox;
QGroupBox *groupBox;
QRadioButton *qobjectCtorRadioButton;
QRadioButton *qwidgetCtorRadioButton;
QRadioButton *defaultCtorRadioButton;
QCheckBox *copyCtorCheckBox;
};
//! [2]
//! [3]
class CodeStylePage : public QWizardPage
{
Q_OBJECT
public:
CodeStylePage(QWidget *parent = nullptr);
protected:
void initializePage() override;
private:
QCheckBox *commentCheckBox;
QCheckBox *protectCheckBox;
QCheckBox *includeBaseCheckBox;
QLabel *macroNameLabel;
QLabel *baseIncludeLabel;
QLineEdit *macroNameLineEdit;
QLineEdit *baseIncludeLineEdit;
};
//! [3]
class OutputFilesPage : public QWizardPage
{
Q_OBJECT
public:
OutputFilesPage(QWidget *parent = nullptr);
protected:
void initializePage() override;
private:
QLabel *outputDirLabel;
QLabel *headerLabel;
QLabel *implementationLabel;
QLineEdit *outputDirLineEdit;
QLineEdit *headerLineEdit;
QLineEdit *implementationLineEdit;
};
class ConclusionPage : public QWizardPage
{
Q_OBJECT
public:
ConclusionPage(QWidget *parent = nullptr);
protected:
void initializePage() override;
private:
QLabel *label;
};
#endif

View File

@ -1,10 +0,0 @@
QT += widgets
HEADERS = classwizard.h
SOURCES = classwizard.cpp \
main.cpp
RESOURCES = classwizard.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/dialogs/classwizard
INSTALLS += target

View File

@ -1,11 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/background.png</file>
<file>images/banner.png</file>
<file>images/logo1.png</file>
<file>images/logo2.png</file>
<file>images/logo3.png</file>
<file>images/watermark1.png</file>
<file>images/watermark2.png</file>
</qresource>
</RCC>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,28 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTranslator>
#include <QLocale>
#include <QLibraryInfo>
#include "classwizard.h"
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(classwizard);
QApplication app(argc, argv);
#ifndef QT_NO_TRANSLATION
QString translatorFileName = QLatin1String("qtbase_");
translatorFileName += QLocale::system().name();
QTranslator *translator = new QTranslator(&app);
if (translator->load(translatorFileName, QLibraryInfo::path(QLibraryInfo::TranslationsPath)))
app.installTranslator(translator);
#endif
ClassWizard wizard;
wizard.show();
return app.exec();
}

View File

@ -1,9 +1,7 @@
QT_FOR_CONFIG += widgets
TEMPLATE = subdirs
SUBDIRS = classwizard \
extension \
licensewizard \
SUBDIRS = licensewizard \
standarddialogs \
tabdialog \
trivialwizard

View File

@ -1,37 +0,0 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(extension LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/dialogs/extension")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(extension
finddialog.cpp finddialog.h
main.cpp
)
set_target_properties(extension PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(extension PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS extension
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -1,9 +0,0 @@
QT += widgets
HEADERS = finddialog.h
SOURCES = finddialog.cpp \
main.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/dialogs/extension
INSTALLS += target

View File

@ -1,77 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "finddialog.h"
//! [0]
FindDialog::FindDialog(QWidget *parent)
: QDialog(parent)
{
label = new QLabel(tr("Find &what:"));
lineEdit = new QLineEdit;
label->setBuddy(lineEdit);
caseCheckBox = new QCheckBox(tr("Match &case"));
fromStartCheckBox = new QCheckBox(tr("Search from &start"));
fromStartCheckBox->setChecked(true);
//! [1]
findButton = new QPushButton(tr("&Find"));
findButton->setDefault(true);
moreButton = new QPushButton(tr("&More"));
moreButton->setCheckable(true);
//! [0]
moreButton->setAutoDefault(false);
//! [1]
//! [2]
extension = new QWidget;
wholeWordsCheckBox = new QCheckBox(tr("&Whole words"));
backwardCheckBox = new QCheckBox(tr("Search &backward"));
searchSelectionCheckBox = new QCheckBox(tr("Search se&lection"));
//! [2]
//! [3]
buttonBox = new QDialogButtonBox(Qt::Vertical);
buttonBox->addButton(findButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(moreButton, QDialogButtonBox::ActionRole);
connect(moreButton, &QAbstractButton::toggled, extension, &QWidget::setVisible);
QVBoxLayout *extensionLayout = new QVBoxLayout;
extensionLayout->setContentsMargins(QMargins());
extensionLayout->addWidget(wholeWordsCheckBox);
extensionLayout->addWidget(backwardCheckBox);
extensionLayout->addWidget(searchSelectionCheckBox);
extension->setLayout(extensionLayout);
//! [3]
//! [4]
QHBoxLayout *topLeftLayout = new QHBoxLayout;
topLeftLayout->addWidget(label);
topLeftLayout->addWidget(lineEdit);
QVBoxLayout *leftLayout = new QVBoxLayout;
leftLayout->addLayout(topLeftLayout);
leftLayout->addWidget(caseCheckBox);
leftLayout->addWidget(fromStartCheckBox);
QGridLayout *mainLayout = new QGridLayout;
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
mainLayout->addLayout(leftLayout, 0, 0);
mainLayout->addWidget(buttonBox, 0, 1);
mainLayout->addWidget(extension, 1, 0, 1, 2);
mainLayout->setRowStretch(2, 1);
setLayout(mainLayout);
setWindowTitle(tr("Extension"));
//! [4] //! [5]
extension->hide();
}
//! [5]

View File

@ -1,41 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef FINDDIALOG_H
#define FINDDIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE
class QCheckBox;
class QDialogButtonBox;
class QGroupBox;
class QLabel;
class QLineEdit;
class QPushButton;
QT_END_NAMESPACE
//! [0]
class FindDialog : public QDialog
{
Q_OBJECT
public:
FindDialog(QWidget *parent = nullptr);
private:
QLabel *label;
QLineEdit *lineEdit;
QCheckBox *caseCheckBox;
QCheckBox *fromStartCheckBox;
QCheckBox *wholeWordsCheckBox;
QCheckBox *searchSelectionCheckBox;
QCheckBox *backwardCheckBox;
QDialogButtonBox *buttonBox;
QPushButton *findButton;
QPushButton *moreButton;
QWidget *extension;
};
//! [0]
#endif

View File

@ -1,16 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include "finddialog.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
FindDialog dialog;
dialog.show();
return app.exec();
}

View File

@ -288,9 +288,12 @@ void ConclusionPage::initializePage()
"You can use this software for 30 days and make one "
"backup, but you are not allowed to distribute it.");
} else if (wizard()->hasVisitedPage(LicenseWizard::Page_Details)) {
//! [accessField]
const QString emailAddress = field("details.email").toString();
licenseText = tr("<u>First-Time License Agreement:</u> "
"You can use this software subject to the license "
"you will receive by email.");
"you will receive by email sent to %1.").arg(emailAddress);
//! [accessField]
} else {
licenseText = tr("<u>Upgrade License Agreement:</u> "
"This software is licensed under the terms of your "

View File

@ -10,8 +10,6 @@
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(licensewizard);
QApplication app(argc, argv);
#ifndef QT_NO_TRANSLATION

View File

@ -86,10 +86,12 @@ int main(int argc, char *argv[])
app.installTranslator(translator);
#endif
//! [linearAddPage]
QWizard wizard;
wizard.addPage(createIntroPage());
wizard.addPage(createRegistrationPage());
wizard.addPage(createConclusionPage());
//! [linearAddPage]
wizard.setWindowTitle("Trivial Wizard");
wizard.show();

View File

@ -4,6 +4,7 @@
/*!
\example draganddrop/dropsite
\title Drop Site Example
\examplecategory {User Interface Components}
\brief The example shows how to distinguish the various MIME formats available
in a drag and drop operation.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

View File

@ -1,948 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page tutorials-addressbook.html
\title Address Book Tutorial
\ingroup examples-layout
\brief An introduction to GUI programming, showing how to put together a
simple yet fully-functioning application.
This tutorial is an introduction to GUI programming with the Qt
cross-platform framework.
\image addressbook-tutorial-screenshot.png
\omit
It doesn't cover everything; the emphasis is on teaching the programming
philosophy of GUI programming, and Qt's features are introduced as needed.
Some commonly used features are never used in this tutorial.
\endomit
In this tutorial, you will learn about some of the basic
components of Qt, including:
\list
\li Widgets and layout managers
\li Container classes
\li Signals and slots
\li Input and output devices
\endlist
Tutorial contents:
\list 1
\li \l{tutorials/addressbook/part1}{Designing the User Interface}
\li \l{tutorials/addressbook/part2}{Adding Addresses}
\li \l{tutorials/addressbook/part3}{Navigating between Entries}
\li \l{tutorials/addressbook/part4}{Editing and Removing Addresses}
\li \l{tutorials/addressbook/part5}{Adding a Find Function}
\li \l{tutorials/addressbook/part6}{Loading and Saving}
\li \l{tutorials/addressbook/part7}{Additional Features}
\endlist
The tutorial source code is located in \c{tutorials/addressbook}.
Although this little application does not look much like a
fully-fledged modern GUI application, it uses many of the basic
elements that are used in more complex applications. After you
have worked through this tutorial, we recommend reading the
\l{mainwindows/application}{Application} example, which presents a
small GUI application, with menus, toolbars, a status bar, and so
on.
*/
/*!
\example tutorials/addressbook/part1
\title Part 1 - Designing the User Interface
\brief Describes how to code the user interface of the Address Book Example.
This first part covers the design of the basic graphical user
interface (GUI) for our address book application.
The first step in creating a GUI program is to design the user
interface. Here the our goal is to set up the labels and input
fields to implement a basic address book. The figure below is a
screenshot of the expected output.
\image addressbook-tutorial-part1-screenshot.png
We require two QLabel objects, \c nameLabel and \c addressLabel, as well
as two input fields, a QLineEdit object, \c nameLine, and a QTextEdit
object, \c addressText, to enable the user to enter a contact's name and
address. The widgets used and their positions are shown in the figure
below.
\image addressbook-tutorial-part1-labeled-screenshot.png
There are three files used to implement this address book:
\list
\li \c{addressbook.h} - the definition file for the \c AddressBook
class,
\li \c{addressbook.cpp} - the implementation file for the
\c AddressBook class, and
\li \c{main.cpp} - the file containing a \c main() function, with
an instance of \c AddressBook.
\endlist
\section1 Qt Programming - Subclassing
When writing Qt programs, we usually subclass Qt objects to add
functionality. This is one of the essential concepts behind creating
custom widgets or collections of standard widgets. Subclassing to
extend or change the behavior of a widget has the following advantages:
\list
\li We can write implementations of virtual or pure virtual functions to
obtain exactly what we need, falling back on the base class's implementation
when necessary.
\li It allows us to encapsulate parts of the user interface within a class,
so that the other parts of the application don't need to know about the
individual widgets in the user interface.
\li The subclass can be used to create multiple custom widgets in the same
application or library, and the code for the subclass can be reused in other
projects.
\endlist
Since Qt does not provide a specific address book widget, we subclass a
standard Qt widget class and add features to it. The \c AddressBook class
we create in this tutorial can be reused in situations where a basic address
book widget is needed.
\section1 Defining the AddressBook Class
The \c{tutorials/addressbook/part1/addressbook.h} file is
used to define the \c AddressBook class.
We start by defining \c AddressBook as a QWidget subclass and declaring
a constructor. We also use the Q_OBJECT macro to indicate that the class
uses internationalization and Qt's signals and slots features, even
if we do not use all of these features at this stage.
\snippet tutorials/addressbook/part1/addressbook.h class definition
The class holds declarations of \c nameLine and \c addressText,
the private instances of QLineEdit and QTextEdit mentioned
earlier. The data stored in \c nameLine and \c addressText will
be needed for many of the address book functions.
We don't include declarations of the QLabel objects we will use
because we will not need to reference them once they have been
created. The way Qt tracks the ownership of objects is explained
in the next section.
The Q_OBJECT macro itself implements some of the more advanced features of Qt.
For now, it is useful to think of the Q_OBJECT macro as a shortcut which allows
us to use the \l{QObject::}{tr()} and \l{QObject::}{connect()} functions.
We have now completed the \c addressbook.h file and we move on to
implement the corresponding \c addressbook.cpp file.
\section1 Implementing the AddressBook Class
The constructor of \c AddressBook accepts a QWidget parameter, \a parent.
By convention, we pass this parameter to the base class's constructor.
This concept of ownership, where a parent can have one or more children,
is useful for grouping widgets in Qt. For example, if you delete a parent,
all of its children will be deleted as well.
\snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields
In this constructor, the QLabel objects \c nameLabel and \c
addressLabel are instantiated, as well as \c nameLine and \c
addressText. The \l{QObject::tr()}{tr()} function returns a
translated version of the string, if there is one
available. Otherwise it returns the string itself. This function
marks its QString parameter as one that should be translated into
other languages. It should be used wherever a translatable string
appears.
When programming with Qt, it is useful to know how layouts work.
Qt provides three main layout classes: QHBoxLayout, QVBoxLayout
and QGridLayout to handle the positioning of widgets.
\image addressbook-tutorial-part1-labeled-layout.png
We use a QGridLayout to position our labels and input fields in a
structured manner. QGridLayout divides the available space into a grid and
places widgets in the cells we specify with row and column numbers. The
diagram above shows the layout cells and the position of our widgets, and
we specify this arrangement using the following code:
\snippet tutorials/addressbook/part1/addressbook.cpp layout
Notice that \c addressLabel is positioned using Qt::AlignTop as an
additional argument. This is to make sure it is not vertically centered in
cell (1,0). For a basic overview on Qt Layouts, refer to the
\l{Layout Management} documentation.
In order to install the layout object onto the widget, we have to invoke
the widget's \l{QWidget::setLayout()}{setLayout()} function:
\snippet tutorials/addressbook/part1/addressbook.cpp setting the layout
Lastly, we set the widget's title to "Simple Address Book".
\section1 Running the Application
A separate file, \c main.cpp, is used for the \c main() function. Within
this function, we instantiate a QApplication object, \c app. QApplication
is responsible for various application-wide resources, such as the default
font and cursor, and for running an event loop. Hence, there is always one
QApplication object in every GUI application using Qt.
\snippet tutorials/addressbook/part1/main.cpp main function
We construct a new \c AddressBook widget on the stack and invoke
its \l{QWidget::show()}{show()} function to display it.
However, the widget will not be shown until the application's event loop
is started. We start the event loop by calling the application's
\l{QApplication::}{exec()} function; the result returned by this function
is used as the return value from the \c main() function. At this point,
it becomes apparent why we instantiated \c AddressBook on the stack: It
will now go out of scope. Therefore, \c AddressBook and all its child widgets
will be deleted, thus preventing memory leaks.
*/
/*!
\example tutorials/addressbook/part2
\title Part 2 - Adding Addresses
\brief Describes the code for inserting records in the Address Book Example.
The next step in creating the address book is to implement some
user interactions.
\image addressbook-tutorial-part2-add-contact.png
We will provide a push button that the user can click to add a new contact.
Also, some form of data structure is needed to store these contacts in an
organized way.
\section1 Defining the AddressBook Class
Now that we have the labels and input fields set up, we add push buttons to
complete the process of adding a contact. This means that our
\c addressbook.h file now has three QPushButton objects declared and three
corresponding public slots.
\snippet tutorials/addressbook/part2/addressbook.h slots
A slot is a function that responds to a particular signal. We will discuss
this concept in further detail when implementing the \c AddressBook class.
However, for an overview of Qt's signals and slots concept, you can refer
to the \l{Signals and Slots} document.
Three QPushButton objects (\c addButton, \c submitButton, and
\c cancelButton) are now included in our private variable declarations,
along with \c nameLine and \c addressText.
\snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration
We need a container to store our address book contacts, so that we can
traverse and display them. A QMap object, \c contacts, is used for this
purpose as it holds a key-value pair: the contact's name as the \e key,
and the contact's address as the \e{value}.
\snippet tutorials/addressbook/part2/addressbook.h remaining private variables
We also declare two private QString objects, \c oldName and \c oldAddress.
These objects are needed to hold the name and address of the contact that
was last displayed, before the user clicked \uicontrol Add. So, when the user clicks
\uicontrol Cancel, we can revert to displaying the details of the last contact.
\section1 Implementing the AddressBook Class
Within the constructor of \c AddressBook, we set the \c nameLine and
\c addressText to read-only, so that we can only display but not edit
existing contact details.
\dots
\snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 1
\dots
\snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 2
Then, we instantiate our push buttons: \c addButton, \c submitButton, and
\c cancelButton.
\snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration
The \c addButton is displayed by invoking the \l{QPushButton::show()}
{show()} function, while the \c submitButton and \c cancelButton are
hidden by invoking \l{QPushButton::hide()}{hide()}. These two push
buttons will only be displayed when the user clicks \uicontrol Add and this is
handled by the \c addContact() function discussed below.
\snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots
We connect the push buttons' \l{QPushButton::clicked()}{clicked()} signal
to their respective slots. The figure below illustrates this.
\image addressbook-tutorial-part2-signals-and-slots.png
Next, we arrange our push buttons neatly to the right of our address book
widget, using a QVBoxLayout to line them up vertically.
\snippet tutorials/addressbook/part2/addressbook.cpp vertical layout
The \l{QBoxLayout::addStretch()}{addStretch()} function is used to ensure
the push buttons are not evenly spaced, but arranged closer to the top of
the widget. The figure below shows the difference between using
\l{QBoxLayout::addStretch()}{addStretch()} and not using it.
\image addressbook-tutorial-part2-stretch-effects.png
We then add \c buttonLayout1 to \c mainLayout, using
\l{QGridLayout::addLayout()}{addLayout()}. This gives us nested layouts
as \c buttonLayout1 is now a child of \c mainLayout.
\snippet tutorials/addressbook/part2/addressbook.cpp grid layout
Our layout coordinates now look like this:
\image addressbook-tutorial-part2-labeled-layout.png
In the \c addContact() function, we store the last displayed contact
details in \c oldName and \c oldAddress. Then we clear these input
fields and turn off the read-only mode. The focus is set on \c nameLine
and we display \c submitButton and \c cancelButton.
\snippet tutorials/addressbook/part2/addressbook.cpp addContact
The \c submitContact() function can be divided into three parts:
\list 1
\li We extract the contact's details from \c nameLine and \c addressText
and store them in QString objects. We also validate to make sure that the
user did not click \uicontrol Submit with empty input fields; otherwise, a
QMessageBox is displayed to remind the user for a name and address.
\snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1
\li We then proceed to check if the contact already exists. If it does not
exist, we add the contact to \c contacts and we display a QMessageBox to
inform the user that the contact has been added.
\snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2
If the contact already exists, again, we display a QMessageBox to inform
the user about this, preventing the user from adding duplicate contacts.
Our \c contacts object is based on key-value pairs of name and address,
hence, we want to ensure that \e key is unique.
\li Once we have handled both cases mentioned above, we restore the push
buttons to their normal state with the following code:
\snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3
\endlist
The screenshot below shows the QMessageBox object we use to display
information messages to the user.
\image addressbook-tutorial-part2-add-successful.png
The \c cancel() function restores the last displayed contact details and
enables \c addButton, as well as hides \c submitButton and
\c cancelButton.
\snippet tutorials/addressbook/part2/addressbook.cpp cancel
The general idea behind adding a contact is to give the user the
flexibility to click \uicontrol Submit or \uicontrol Cancel at any time. The flowchart below
further explains this concept:
\image addressbook-tutorial-part2-add-flowchart.png
*/
/*!
\example tutorials/addressbook/part3
\title Part 3 - Navigating between Entries
\brief Explains the code that enables navigating the contacts.
The address book is now about half complete. We should add the
capability to navigate the contacts, but first we must
decide what sort of a data structure we need for containing these
contacts.
In the previous section, we used a QMap of key-value pairs with
the contact's name as the \e key, and the contact's address as the
\e value. This works well for our case. However, in order to
navigate and display each entry, a little bit of enhancement is
needed.
We enhance the QMap by making it replicate a data structure similar to a
circularly-linked list, where all elements are connected, including the
first element and the last element. The figure below illustrates this data
structure.
\image addressbook-tutorial-part3-linkedlist.png
\section1 Defining the AddressBook Class
To add navigation functions to the address book, we must add two
more slots to the \c AddressBook class: \c next() and \c
previous() to the \c addressbook.h file:
\snippet tutorials/addressbook/part3/addressbook.h navigation functions
We also require another two QPushButton objects, so we declare \c nextButton
and \c previousButton as private variables:
\snippet tutorials/addressbook/part3/addressbook.h navigation pushbuttons
\section1 Implementing the AddressBook Class
In the \c AddressBook constructor in \c addressbook.cpp, we instantiate
\c nextButton and \c previousButton and disable them by default. This is
because navigation is only enabled when there is more than one contact
in the address book.
\snippet tutorials/addressbook/part3/addressbook.cpp navigation pushbuttons
We then connect these push buttons to their respective slots:
\snippet tutorials/addressbook/part3/addressbook.cpp connecting navigation signals
The image below is the expected graphical user interface.
\image addressbook-tutorial-part3-screenshot.png
We follow basic conventions for \c next() and \c previous() functions by
placing the \c nextButton on the right and the \c previousButton on the
left. In order to achieve this intuitive layout, we use QHBoxLayout to
place the widgets side-by-side:
\snippet tutorials/addressbook/part3/addressbook.cpp navigation layout
The QHBoxLayout object, \c buttonLayout2, is then added to \c mainLayout.
\snippet tutorials/addressbook/part3/addressbook.cpp adding navigation layout
The figure below shows the coordinates of the widgets in \c mainLayout.
\image addressbook-tutorial-part3-labeled-layout.png
Within our \c addContact() function, we have to disable these buttons so
that the user does not attempt to navigate while adding a contact.
\snippet tutorials/addressbook/part3/addressbook.cpp disabling navigation
Also, in our \c submitContact() function, we enable the navigation
buttons, \c nextButton and \c previousButton, depending on the size
of \c contacts. As mentioned earlier, navigation is only enabled when
there is more than one contact in the address book. The following lines
of code demonstrates how to do this:
\snippet tutorials/addressbook/part3/addressbook.cpp enabling navigation
We also include these lines of code in the \c cancel() function.
Recall that we intend to emulate a circularly-linked list with our QMap
object, \c contacts. So, in the \c next() function, we obtain an iterator
for \c contacts and then:
\list
\li If the iterator is not at the end of \c contacts, we increment it
by one.
\li If the iterator is at the end of \c contacts, we move it to the
beginning of \c contacts. This gives us the illusion that our QMap is
working like a circularly-linked list.
\endlist
\snippet tutorials/addressbook/part3/addressbook.cpp next() function
Once we have iterated to the correct object in \c contacts, we display
its contents on \c nameLine and \c addressText.
Similarly, for the \c previous() function, we obtain an iterator for
\c contacts and then:
\list
\li If the iterator is at the end of \c contacts, we clear the
display and return.
\li If the iterator is at the beginning of \c contacts, we move it to
the end.
\li We then decrement the iterator by one.
\endlist
\snippet tutorials/addressbook/part3/addressbook.cpp previous() function
Again, we display the contents of the current object in \c contacts.
*/
/*!
\example tutorials/addressbook/part4
\title Part 4 - Editing and Removing Addresses
\brief Explains how to add edit and remove functionality.
Now we look at ways to modify the contents of contacts stored in
the address book.
\image addressbook-tutorial-screenshot.png
We now have an address book that not only holds contacts in an
organized manner, but also allows navigation. It would be
convenient to include edit and remove functions so that a
contact's details can be changed when needed. However, this
requires a little improvement, in the form of enums. We defined
two modes: \c{AddingMode} and \c{NavigationMode}, but they were
not defined as enum values. Instead, we enabled and disabled the
corresponding buttons manually, resulting in multiple lines of
repeated code.
Here we define the \c Mode enum with three different values:
\list
\li \c{NavigationMode},
\li \c{AddingMode}, and
\li \c{EditingMode}.
\endlist
\section1 Defining the AddressBook Class
The \c addressbook.h file is updated to contain the \c Mode enum:
\snippet tutorials/addressbook/part4/addressbook.h Mode enum
We also add two new slots, \c editContact() and \c removeContact(), to
our current list of public slots.
\snippet tutorials/addressbook/part4/addressbook.h edit and remove slots
In order to switch between modes, we introduce the \c updateInterface() function
to control the enabling and disabling of all QPushButton objects. We also
add two new push buttons, \c editButton and \c removeButton, for the edit
and remove functions mentioned earlier.
\snippet tutorials/addressbook/part4/addressbook.h updateInterface() declaration
\dots
\snippet tutorials/addressbook/part4/addressbook.h buttons declaration
\dots
\snippet tutorials/addressbook/part4/addressbook.h mode declaration
Lastly, we declare \c currentMode to keep track of the enum's current mode.
\section1 Implementing the AddressBook Class
We now implement the mode-changing features of the address
book. The \c editButton and \c removeButton are instantiated and
disabled by default. The address book starts with zero contacts
in memory.
\snippet tutorials/addressbook/part4/addressbook.cpp edit and remove buttons
These buttons are then connected to their respective slots, \c editContact()
and \c removeContact(), and we add them to \c buttonLayout1.
\snippet tutorials/addressbook/part4/addressbook.cpp connecting edit and remove
\dots
\snippet tutorials/addressbook/part4/addressbook.cpp adding edit and remove to the layout
The \c editContact() function stores the contact's old details in
\c oldName and \c oldAddress, before switching the mode to \c EditingMode.
In this mode, the \c submitButton and \c cancelButton are both enabled,
hence, the user can change the contact's details and click either button.
\snippet tutorials/addressbook/part4/addressbook.cpp editContact() function
The \c submitContact() function has been divided in two with an \c{if-else}
statement. We check \c currentMode to see if it's in \c AddingMode. If it is,
we proceed with our adding process.
\snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function beginning
\dots
\snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part1
Otherwise, we check to see if \c currentMode is in \c EditingMode. If it
is, we compare \c oldName with \c name. If the name has changed, we remove
the old contact from \c contacts and insert the newly updated contact.
\snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part2
If only the address has changed (i.e., \c oldAddress is not the same as \c address),
we update the contact's address. Lastly, we set \c currentMode to
\c NavigationMode. This is an important step as it re-enables all the
disabled push buttons.
To remove a contact from the address book, we implement the
\c removeContact() function. This function checks to see if the contact
exists in \c contacts.
\snippet tutorials/addressbook/part4/addressbook.cpp removeContact() function
If it does, we display a QMessageBox, to confirm the removal with the
user. Once the user has confirmed, we call \c previous() to ensure that the
user interface shows another contact, and we remove the contact using \l{QMap}'s
\l{QMap::remove()}{remove()} function. As a courtesy, we display a QMessageBox
to inform the user. Both the message boxes used in this function are shown below:
\image addressbook-tutorial-part4-remove.png
\section2 Updating the User Interface
We mentioned the \c updateInterface() function earlier as a means to
enable and disable the push buttons depending on the current mode.
The function updates the current mode according to the \c mode argument
passed to it, assigning it to \c currentMode before checking its value.
Each of the push buttons is then enabled or disabled, depending on the
current mode. The code for \c AddingMode and \c EditingMode is shown below:
\snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 1
For \c NavigationMode, however, we include conditions within the parameters
of the QPushButton::setEnabled() function. This is to ensure that
\c editButton and \c removeButton are enabled when there is at least one
contact in the address book; \c nextButton and \c previousButton are only
enabled when there is more than one contact in the address book.
\snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 2
By setting the mode and updating the user interface in the same
function, we avoid the possibility of the user interface getting
out of sync with the internal state of the application.
*/
/*!
\example tutorials/addressbook/part5
\title Part 5 - Adding a Find Function
\brief Describes how to add a find function.
Here we look at ways to locate contacts and addresses in the
address book.
\image addressbook-tutorial-part5-screenshot.png
As we add contacts to our address book, it becomes tedious to
navigate the list with the \e Next and \e Previous buttons. A \e
Find function would be more efficient. The screenshot above shows
the \e Find button and its position on the panel of buttons.
When the user clicks on the \e Find button, it is useful to
display a dialog that prompts for a contact's name. Qt provides
QDialog, which we subclass here to implement a \c FindDialog
class.
\section1 Defining the FindDialog Class
\image addressbook-tutorial-part5-finddialog.png
In order to subclass QDialog, we first include the header for QDialog in
the \c finddialog.h file. Also, we use forward declaration to declare
QLineEdit and QPushButton since we will be using those widgets in our
dialog class.
As in our \c AddressBook class, the \c FindDialog class includes
the Q_OBJECT macro and its constructor is defined to accept a parent
QWidget, even though the dialog will be opened as a separate window.
\snippet tutorials/addressbook/part5/finddialog.h FindDialog header
We define a public function, \c getFindText(), to be used by classes that
instantiate \c FindDialog. This function allows these classes to obtain the
search string entered by the user. A public slot, \c findClicked(), is also
defined to handle the search string when the user clicks the \uicontrol Find
button.
Lastly, we define the private variables, \c findButton, \c lineEdit
and \c findText, corresponding to the \uicontrol Find button, the line edit
into which the user types the search string, and an internal string
used to store the search string for later use.
\section1 Implementing the FindDialog Class
Within the constructor of \c FindDialog, we set up the private variables,
\c lineEdit, \c findButton and \c findText. We use a QHBoxLayout to
position the widgets.
\snippet tutorials/addressbook/part5/finddialog.cpp constructor
We set the layout and window title, as well as connect the signals to their
respective slots. Notice that \c{findButton}'s \l{QPushButton::clicked()}
{clicked()} signal is connected to \c findClicked() and
\l{QDialog::accept()}{accept()}. The \l{QDialog::accept()}{accept()} slot
provided by QDialog hides the dialog and sets the result code to
\l{QDialog::}{Accepted}. We use this function to help \c{AddressBook}'s
\c findContact() function know when the \c FindDialog object has been
closed. We will explain this logic in further detail when discussing the
\c findContact() function.
\image addressbook-tutorial-part5-signals-and-slots.png
In \c findClicked(), we validate \c lineEdit to ensure that the user
did not click the \uicontrol Find button without entering a contact's name. Then, we set
\c findText to the search string, extracted from \c lineEdit. After that,
we clear the contents of \c lineEdit and hide the dialog.
\snippet tutorials/addressbook/part5/finddialog.cpp findClicked() function
The \c findText variable has a public getter function, \c getFindText(),
associated with it. Since we only ever set \c findText directly in both the
constructor and in the \c findClicked() function, we do not create a
setter function to accompany \c getFindText().
Because \c getFindText() is public, classes instantiating and using
\c FindDialog can always access the search string that the user has
entered and accepted.
\snippet tutorials/addressbook/part5/finddialog.cpp getFindText() function
\section1 Defining the AddressBook Class
To ensure we can use \c FindDialog from within our \c AddressBook class, we
include \c finddialog.h in the \c addressbook.h file.
\snippet tutorials/addressbook/part5/addressbook.h include finddialog's header
So far, all our address book features have a QPushButton and a
corresponding slot. Similarly, for the \uicontrol Find feature we have
\c findButton and \c findContact().
The \c findButton is declared as a private variable and the
\c findContact() function is declared as a public slot.
\snippet tutorials/addressbook/part5/addressbook.h findContact() declaration
\dots
\snippet tutorials/addressbook/part5/addressbook.h findButton declaration
Lastly, we declare the private variable, \c dialog, which we will use to
refer to an instance of \c FindDialog.
\snippet tutorials/addressbook/part5/addressbook.h FindDialog declaration
Once we have instantiated a dialog, we will want to use it more than once;
using a private variable allows us to refer to it from more than one place
in the class.
\section1 Implementing the AddressBook Class
Within the \c AddressBook class's constructor, we instantiate our private
objects, \c findButton and \c findDialog:
\snippet tutorials/addressbook/part5/addressbook.cpp instantiating findButton
\dots
\snippet tutorials/addressbook/part5/addressbook.cpp instantiating FindDialog
Next, we connect the \c{findButton}'s
\l{QPushButton::clicked()}{clicked()} signal to \c findContact().
\snippet tutorials/addressbook/part5/addressbook.cpp signals and slots for find
Now all that is left is the code for our \c findContact() function:
\snippet tutorials/addressbook/part5/addressbook.cpp findContact() function
We start out by displaying the \c FindDialog instance, \c dialog. This is
when the user enters a contact name to look up. Once the user clicks
the dialog's \c findButton, the dialog is hidden and the result code is
set to QDialog::Accepted. This ensures that
our \c if statement is always true.
We then proceed to extract the search string, which in this case is
\c contactName, using \c{FindDialog}'s \c getFindText() function. If the
contact exists in our address book, we display it immediately. Otherwise,
we display the QMessageBox shown below to indicate that their search
failed.
\image addressbook-tutorial-part5-notfound.png
*/
/*!
\example tutorials/addressbook/part6
\title Part 6 - Loading and Saving
\brief Describes how to add save and load functionality.
This part covers the Qt file handling features we use to write
loading and saving routines for the address book.
\image addressbook-tutorial-part6-screenshot.png
Although browsing and searching the contact list are useful
features, our address book is not complete until we can save
existing contacts and load them again at a later time.
Qt provides a number of classes for \l{Input/Output and Networking}
{input and output}, but we have chosen to use two which are simple to use
in combination: QFile and QDataStream.
A QFile object represents a file on disk that can be read from and written
to. QFile is a subclass of the more general QIODevice class which
represents many different kinds of devices.
A QDataStream object is used to serialize binary data so that it can be
stored in a QIODevice and retrieved again later. Reading from a QIODevice
and writing to it is as simple as opening the stream - with the respective
device as a parameter - and reading from or writing to it.
\section1 Defining the AddressBook Class
We declare two public slots, \c saveToFile() and \c loadFromFile(), as well
as two QPushButton objects, \c loadButton and \c saveButton.
\snippet tutorials/addressbook/part6/addressbook.h save and load functions declaration
\dots
\snippet tutorials/addressbook/part6/addressbook.h save and load buttons declaration
\section1 Implementing the AddressBook Class
In our constructor, we instantiate \c loadButton and \c saveButton.
Ideally, it would be more user-friendly to set the push buttons' labels
to "Load contacts from a file" and "Save contacts to a file". However, due
to the size of our other push buttons, we set the labels to \uicontrol{Load...}
and \uicontrol{Save...}. Fortunately, Qt provides a simple way to set tooltips with
\l{QWidget::setToolTip()}{setToolTip()} and we use it in the following way
for our push buttons:
\snippet tutorials/addressbook/part6/addressbook.cpp tooltip 1
\dots
\snippet tutorials/addressbook/part6/addressbook.cpp tooltip 2
Although it is not shown here, just like the other features we implemented,
we add the push buttons to the layout panel on the right, \c buttonLayout1,
and we connect the push buttons' \l{QPushButton::clicked()}{clicked()}
signals to their respective slots.
For the saving feature, we first obtain \c fileName using
QFileDialog::getSaveFileName(). This is a convenience function provided
by QFileDialog, which pops up a modal file dialog and allows the user to
enter a file name or select any existing \c{.abk} file. The \c{.abk} file
is our Address Book extension that we create when we save contacts.
\snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part1
The file dialog that pops up is displayed in the screenshot below:
\image addressbook-tutorial-part6-save.png
If \c fileName is not empty, we create a QFile object, \c file, with
\c fileName. QFile works with QDataStream as QFile is a QIODevice.
Next, we attempt to open the file in \l{QIODeviceBase::}{WriteOnly} mode.
If this is unsuccessful, we display a QMessageBox to inform the user.
\snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part2
Otherwise, we instantiate a QDataStream object, \c out, to write the open
file. QDataStream requires that the same version of the stream is used
for reading and writing. We ensure that this is the case by setting the
version used to the \l{QDataStream::Qt_4_5}{version introduced with Qt 4.5}
before serializing the data to \c file.
\snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part3
For the loading feature, we also obtain \c fileName using
QFileDialog::getOpenFileName(). This function, the counterpart to
QFileDialog::getSaveFileName(), also pops up the modal file dialog and
allows the user to enter a file name or select any existing \c{.abk} file
to load it into the address book.
\snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part1
On Windows, for example, this function pops up a native file dialog, as
shown in the following screenshot.
\image addressbook-tutorial-part6-load.png
If \c fileName is not empty, again, we use a QFile object, \c file, and
attempt to open it in \l{QIODeviceBase::}{ReadOnly} mode. Similar to our
implementation of \c saveToFile(), if this attempt is unsuccessful, we
display a QMessageBox to inform the user.
\snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part2
Otherwise, we instantiate a QDataStream object, \c in, set its version as
above and read the serialized data into the \c contacts data structure.
The \c contacts object is emptied before data is read into it to simplify
the file reading process. A more advanced method would be to read the
contacts into a temporary QMap object, and copy over non-duplicate contacts
into \c contacts.
\snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part3
To display the contacts that have been read from the file, we must first
validate the data obtained to ensure that the file we read from actually
contains address book contacts. If it does, we display the first contact;
otherwise, we display a QMessageBox to inform the user about the problem.
Lastly, we update the interface to enable and disable the push buttons
accordingly.
*/
/*!
\example tutorials/addressbook/part7
\title Part 7 - Additional Features
\brief Describes how to export data in VCard format.
This part covers some additional features that make the address
book more convenient for the frequent user.
\image addressbook-tutorial-part7-screenshot.png
Although our address book is useful in isolation, it would be
better if we could exchange contact data with other applications.
The vCard format is a popular file format that can be used for
this purpose. Here we extend our address book client to allow
contacts to be exported to vCard \c{.vcf} files.
\section1 Defining the AddressBook Class
We add a QPushButton object, \c exportButton, and a corresponding public
slot, \c exportAsVCard() to our \c AddressBook class in the
\c addressbook.h file.
\snippet tutorials/addressbook/part7/addressbook.h exportAsVCard() declaration
\dots
\snippet tutorials/addressbook/part7/addressbook.h exportButton declaration
\section1 Implementing the AddressBook Class
Within the \c AddressBook constructor, we connect \c{exportButton}'s
\l{QPushButton::clicked()}{clicked()} signal to \c exportAsVCard().
We also add this button to our \c buttonLayout1, the layout responsible
for our panel of buttons on the right.
In our \c exportAsVCard() function, we start by extracting the contact's
name into \c name. We declare \c firstName, \c lastName and \c nameList.
Next, we look for the index of the first white space in \c name. If there
is a white space, we split the contact's name into \c firstName and
\c lastName. Then, we replace the space with an underscore ("_").
Alternately, if there is no white space, we assume that the contact only
has a first name.
\snippet tutorials/addressbook/part7/addressbook.cpp export function part1
As with the \c saveToFile() function, we open a file dialog to let the user
choose a location for the file. Using the file name chosen, we create an
instance of QFile to write to.
We attempt to open the file in \l{QIODeviceBase::}{WriteOnly} mode. If this
process fails, we display a QMessageBox to inform the user about the
problem and return. Otherwise, we pass the file as a parameter to a
QTextStream object, \c out. Like QDataStream, the QTextStream class
provides functionality to read and write plain text to files. As a result,
the \c{.vcf} file generated can be opened for editing in a text editor.
\snippet tutorials/addressbook/part7/addressbook.cpp export function part2
We then write out a vCard file with the \c{BEGIN:VCARD} tag, followed by
the \c{VERSION:2.1} tag. The contact's name is written with the \c{N:}
tag. For the \c{FN:} tag, which fills in the "File as" property of a vCard,
we have to check whether the contact has a last name or not. If the contact
does, we use the details in \c nameList to fill it. Otherwise, we write
\c firstName only.
\snippet tutorials/addressbook/part7/addressbook.cpp export function part3
We proceed to write the contact's address. The semicolons in the address
are escaped with "\\", the newlines are replaced with semicolons, and the
commas are replaced with spaces. Lastly, we write the \c{ADR;HOME:;}
tag, followed by \c address and then the \c{END:VCARD} tag.
\snippet tutorials/addressbook/part7/addressbook.cpp export function part4
In the end, a QMessageBox is displayed to inform the user that the vCard
has been successfully exported.
\e{vCard is a trademark of the \l{http://www.imc.org}
{Internet Mail Consortium}}.
*/

View File

@ -4,6 +4,7 @@
/*!
\example itemviews/addressbook
\title Address Book
\examplecategory {User Interface Components}
\ingroup examples-itemviews
\brief The address book example shows how to use proxy models to display
different views onto data from a single model.

View File

@ -4,8 +4,9 @@
/*!
\example painting/affine
\title Affine Transformations
\examplecategory {Graphics & Multimedia}
\ingroup examples-painting
\brief Demonstrates how affine transformations in QPainter works.
\brief Demonstrates how affine transformations in QPainter work.
\brief In this example we show Qt's ability to perform affine transformations
on painting operations.

View File

@ -3,7 +3,7 @@
/*!
\example widgets/analogclock
\examplecategory {Graphics}
\examplecategory {Graphics & Multimedia}
\meta tags {widgets}
\title Analog Clock

View File

@ -1,370 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example mainwindows/application
\title Qt Widgets - Application Example
\ingroup examples-mainwindow
\brief The Application example shows how to implement a standard
widget application with menus, toolbars, and a status bar. The example
itself is a simple text editor program built around QPlainTextEdit.
\image application.png Screenshot of the Application example
Nearly all of the code for the Application example is in the \c
MainWindow class, which inherits QMainWindow. QMainWindow
provides the framework for windows that have menus, toolbars,
dock windows, and a status bar. The application provides
\uicontrol{File}, \uicontrol{Edit}, and \uicontrol{Help} entries in the menu
bar, with the following popup menus:
\image application-menus.png The Application example's menu system
The status bar at the bottom of the main window shows a
description of the menu item or toolbar button under the cursor.
To keep the example simple, recently opened files aren't shown in
the \uicontrol{File} menu, even though this feature is desired in 90%
of applications. Furthermore, this example can only load one file at a
time. The \l{mainwindows/mdi}{MDI} example shows how to lift these
restrictions and how to implement recently opened files handling.
\section1 MainWindow Class Definition
Here's the class definition:
\snippet mainwindows/application/mainwindow.h 0
The public API is restricted to the constructor. In the \c
protected section, we reimplement QWidget::closeEvent() to detect
when the user attempts to close the window, and warn the user
about unsaved changes. In the \c{private slots} section, we
declare slots that correspond to menu entries, as well as a
mysterious \c documentWasModified() slot. Finally, in the \c
private section of the class, we have various members that will
be explained in due time.
\section1 MainWindow Class Implementation
\snippet mainwindows/application/mainwindow.cpp 0
We start by including \c <QtWidgets>, a header file that contains the
definition of all classes in the Qt Core, Qt GUI and Qt Widgets
modules. This saves us from the trouble of having to include
every class individually. We also include \c mainwindow.h.
You might wonder why we don't include \c <QtWidgets> in \c
mainwindow.h and be done with it. The reason is that including
such a large header from another header file can rapidly degrade
performances. Here, it wouldn't do any harm, but it's still
generally a good idea to include only the header files that are
strictly necessary from another header file.
\snippet mainwindows/application/mainwindow.cpp 1
\snippet mainwindows/application/mainwindow.cpp 2
In the constructor, we start by creating a QPlainTextEdit widget as a
child of the main window (the \c this object). Then we call
QMainWindow::setCentralWidget() to tell that this is going to be
the widget that occupies the central area of the main window,
between the toolbars and the status bar.
Then we call \c createActions() and \c createStatusBar(), two private
functions that set up the user interface. After that, we call \c
readSettings() to restore the user's preferences.
We establish a signal-slot connection between the QPlainTextEdit's
document object and our \c documentWasModified() slot. Whenever
the user modifies the text in the QPlainTextEdit, we want to update
the title bar to show that the file was modified.
At the end, we set the window title using the private
\c setCurrentFile() function. We'll come back to this later.
\target close event handler
\snippet mainwindows/application/mainwindow.cpp 3
\snippet mainwindows/application/mainwindow.cpp 4
When the user attempts to close the window, we call the private
function \c maybeSave() to give the user the possibility to save
pending changes. The function returns true if the user wants the
application to close; otherwise, it returns false. In the first
case, we save the user's preferences to disk and accept the close
event; in the second case, we ignore the close event, meaning
that the application will stay up and running as if nothing
happened.
\snippet mainwindows/application/mainwindow.cpp 5
\snippet mainwindows/application/mainwindow.cpp 6
The \c newFile() slot is invoked when the user selects
\uicontrol{File|New} from the menu. We call \c maybeSave() to save any
pending changes and if the user accepts to go on, we clear the
QPlainTextEdit and call the private function \c setCurrentFile() to
update the window title and clear the
\l{QWidget::windowModified}{windowModified} flag.
\snippet mainwindows/application/mainwindow.cpp 7
\snippet mainwindows/application/mainwindow.cpp 8
The \c open() slot is invoked when the user clicks
\uicontrol{File|Open}. We pop up a QFileDialog asking the user to
choose a file. If the user chooses a file (i.e., \c fileName is
not an empty string), we call the private function \c loadFile()
to actually load the file.
\snippet mainwindows/application/mainwindow.cpp 9
\snippet mainwindows/application/mainwindow.cpp 10
The \c save() slot is invoked when the user clicks
\uicontrol{File|Save}. If the user hasn't provided a name for the file
yet, we call \c saveAs(); otherwise, we call the private function
\c saveFile() to actually save the file.
\snippet mainwindows/application/mainwindow.cpp 11
\snippet mainwindows/application/mainwindow.cpp 12
In \c saveAs(), we start by popping up a QFileDialog asking the
user to provide a name. If the user clicks \uicontrol{Cancel}, the
returned file name is empty, and we do nothing.
\snippet mainwindows/application/mainwindow.cpp 13
\snippet mainwindows/application/mainwindow.cpp 14
The application's About box is done using one statement, using
the QMessageBox::about() static function and relying on its
support for an HTML subset.
The \l{QObject::tr()}{tr()} call around the literal string marks
the string for translation. It is a good habit to call
\l{QObject::tr()}{tr()} on all user-visible strings, in case you
later decide to translate your application to other languages.
The \l{Internationalization with Qt} overview covers
\l{QObject::tr()}{tr()} in more detail.
\snippet mainwindows/application/mainwindow.cpp 15
\snippet mainwindows/application/mainwindow.cpp 16
The \c documentWasModified() slot is invoked each time the text
in the QPlainTextEdit changes because of user edits. We call
QWidget::setWindowModified() to make the title bar show that the
file was modified. How this is done varies on each platform.
\snippet mainwindows/application/mainwindow.cpp 17
\snippet mainwindows/application/mainwindow.cpp 18
\dots
\snippet mainwindows/application/mainwindow.cpp 22
The \c createActions() private function, which is called from the
\c MainWindow constructor, creates \l{QAction}s and populates
the menus and two toolbars. The code is very
repetitive, so we show only the actions corresponding to
\uicontrol{File|New}, \uicontrol{File|Open}, and \uicontrol{Help|About Qt}.
A QAction is an object that represents one user action, such as
saving a file or invoking a dialog. An action can be put in a
QMenu or a QToolBar, or both, or in any other widget that
reimplements QWidget::actionEvent().
An action has a text that is shown in the menu, an icon, a
shortcut key, a tooltip, a status tip (shown in the status bar),
a "What's This?" text, and more. It emits a
\l{QAction::triggered()}{triggered()} signal whenever the user
invokes the action (e.g., by clicking the associated menu item or
toolbar button).
Instances of QAction can be created by passing a parent QObject or
by using one of the convenience functions of QMenu, QMenuBar or QToolBar.
We create the actions that are in a menu as well as in a toolbar
parented on the window to prevent ownership issues. For actions
that are only in the menu, we use the convenience function
QMenu::addAction(), which allows us to pass text, icon and the
target object and its slot member function.
Creating toolbars is very similar to creating menus. The same
actions that we put in the menus can be reused in the toolbars.
After creating the action, we add it to the toolbar using
QToolBar::addAction().
The code above contains one more idiom that must be explained.
For some of the actions, we specify an icon as a QIcon to the
QAction constructor. We use QIcon::fromTheme() to obtain
the correct standard icon from the underlying window system.
If that fails due to the platform not supporting it, we
pass a file name as fallback. Here, the file name starts
with \c{:}. Such file names aren't ordinary file names, but
rather path in the executable's stored resources. We'll come back
to this when we review the \c application.qrc file that's part of
the project.
\snippet mainwindows/application/mainwindow.cpp 23
\snippet mainwindows/application/mainwindow.cpp 24
The \uicontrol{Edit|Cut} and \uicontrol{Edit|Copy} actions must be available
only when the QPlainTextEdit contains selected text. We disable them
by default and connect the QPlainTextEdit::copyAvailable() signal to
the QAction::setEnabled() slot, ensuring that the actions are
disabled when the text editor has no selection.
Just before we create the \uicontrol{Help} menu, we call
QMenuBar::addSeparator(). This has no effect for most widget
styles (e.g., Windows and \macos styles), but for some
styles this makes sure that \uicontrol{Help} is pushed to the right
side of the menu bar.
\snippet mainwindows/application/mainwindow.cpp 32
\snippet mainwindows/application/mainwindow.cpp 33
QMainWindow::statusBar() returns a pointer to the main window's
QStatusBar widget. Like with \l{QMainWindow::menuBar()}, the
widget is automatically created the first time the function is
called.
\snippet mainwindows/application/mainwindow.cpp 34
\snippet mainwindows/application/mainwindow.cpp 36
The \c readSettings() function is called from the constructor to
load the user's preferences and other application settings. The
QSettings class provides a high-level interface for storing
settings permanently on disk. On Windows, it uses the (in)famous
Windows registry; on \macos, it uses the native XML-based
CFPreferences API; on Unix/X11, it uses text files.
The QSettings constructor takes arguments that identify your
company and the name of the product. This ensures that the
settings for different applications are kept separately.
We use QSettings::value() to extract the value of the geometry setting.
The second argument to QSettings::value() is
optional and specifies a default value for the setting if there
exists none. This value is used the first time the application is
run.
We use QWidget::saveGeometry() and Widget::restoreGeometry() to
save the position. They use an opaque QByteArray to store
screen number, geometry and window state.
\snippet mainwindows/application/mainwindow.cpp 37
\snippet mainwindows/application/mainwindow.cpp 39
The \c writeSettings() function is called from \c closeEvent().
Writing settings is similar to reading them, except simpler. The
arguments to the QSettings constructor must be the same as in \c
readSettings().
\snippet mainwindows/application/mainwindow.cpp 40
\snippet mainwindows/application/mainwindow.cpp 41
The \c maybeSave() function is called to save pending changes. If
there are pending changes, it pops up a QMessageBox giving the
user to save the document. The options are QMessageBox::Yes,
QMessageBox::No, and QMessageBox::Cancel. The \uicontrol{Yes} button is
made the default button (the button that is invoked when the user
presses \uicontrol{Return}) using the QMessageBox::Default flag; the
\uicontrol{Cancel} button is made the escape button (the button that is
invoked when the user presses \uicontrol{Esc}) using the
QMessageBox::Escape flag.
The \c maybeSave() function returns \c true in all cases, except
when the user clicks \uicontrol{Cancel} or saving the file fails.
The caller must check the return value and stop whatever it was
doing if the return value is \c false.
\snippet mainwindows/application/mainwindow.cpp 42
\snippet mainwindows/application/mainwindow.cpp 43
In \c loadFile(), we use QFile and QTextStream to read in the
data. The QFile object provides access to the bytes stored in a
file.
We start by opening the file in read-only mode. The QFile::Text
flag indicates that the file is a text file, not a binary file.
On Unix and \macos, this makes no difference, but on Windows,
it ensures that the "\\r\\n" end-of-line sequence is converted to
"\\n" when reading.
If we successfully opened the file, we use a QTextStream object
to read in the data. QTextStream automatically converts the 8-bit
data into a Unicode QString and supports various encodings. If no
encoding is specified, QTextStream assumes the file is encoded in
UTF-8.
Since the call to QTextStream::readAll() might take some time, we
set the cursor to be Qt::WaitCursor for the entire application
while it goes on.
At the end, we call the private \c setCurrentFile() function,
which we'll cover in a moment, and we display the string "File
loaded" in the status bar for 2 seconds (2000 milliseconds).
\snippet mainwindows/application/mainwindow.cpp 44
\snippet mainwindows/application/mainwindow.cpp 45
Saving a file is similar to loading one. We use QSaveFile to ensure
all data are safely written and existing files are not damaged
should writing fail.
We use the QFile::Text flag to make sure that on Windows, "\\n"
is converted into "\\r\\n" to conform to the Windows convention.
\snippet mainwindows/application/mainwindow.cpp 46
\snippet mainwindows/application/mainwindow.cpp 47
The \c setCurrentFile() function is called to reset the state of
a few variables when a file is loaded or saved, or when the user
starts editing a new file (in which case \c fileName is empty).
We update the \c curFile variable, clear the
QTextDocument::modified flag and the associated \c
QWidget:windowModified flag, and update the window title to
contain the new file name (or \c untitled.txt).
The \c strippedName() function call around \c curFile in the
QWidget::setWindowTitle() call shortens the file name to exclude
the path. Here's the function:
\snippet mainwindows/application/mainwindow.cpp 48
\snippet mainwindows/application/mainwindow.cpp 49
\section1 The main() Function
The \c main() function for this application is typical of
applications that contain one main window:
\snippet mainwindows/application/main.cpp 0
The main function uses QCommandLineParser to check whether some file
argument was passed to the application and loads it via
MainWindow::loadFile().
\section1 The Resource File
As you will probably recall, for some of the actions, we
specified icons with file names starting with \c{:} and mentioned
that such file names aren't ordinary file names, but path in the
executable's stored resources. These resources are compiled
The resources associated with an application are specified in a
\c .qrc file, an XML-based file format that lists files on the
disk. Here's the \c application.qrc file that's used by the
Application example:
\quotefile mainwindows/application/application.qrc
The \c .png files listed in the \c application.qrc file are files
that are part of the Application example's source tree. Paths are
relative to the directory where the \c application.qrc file is
located (the \c mainwindows/application directory).
The resource file must be mentioned in the \c application.pro
file so that \c qmake knows about it:
\snippet mainwindows/application/application.pro 0
\c qmake will produce make rules to generate a file called \c
qrc_application.cpp that is linked into the application. This
file contains all the data for the images and other resources as
static C++ arrays of compressed binary data. See
\l{resources.html}{The Qt Resource System} for more information
about resources.
*/

View File

@ -4,6 +4,7 @@
/*!
\example painting/basicdrawing
\title Basic Drawing Example
\examplecategory {Graphics & Multimedia}
\ingroup examples-painting
\brief The Basic Drawing example shows how to display basic
graphics primitives in a variety of styles using the QPainter

View File

@ -4,6 +4,7 @@
/*!
\example graphicsview/basicgraphicslayouts
\title Basic Graphics Layouts Example
\examplecategory {Graphics & Multimedia}
\ingroup examples-graphicsview-layout
\brief Demonstrates how to create basic graphics layout.

View File

@ -4,6 +4,7 @@
/*!
\example layouts/basiclayouts
\title Basic Layouts Example
\examplecategory {User Interface Components}
\brief Shows how to use the standard layout managers.
\e{Basic Layouts} shows how to use the standard layout managers that are

View File

@ -4,6 +4,7 @@
/*!
\example itemviews/basicsortfiltermodel
\title Basic Sort/Filter Model Example
\examplecategory {User Interface Components}
\ingroup examples-itemviews
\brief The Basic Sort/Filter Model example illustrates how to use
QSortFilterProxyModel to perform basic sorting and filtering.

View File

@ -1,46 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example layouts/borderlayout
\title Border Layout Example
\ingroup examples-layout
\brief Shows how to arrange child widgets along a border.
\e{Border Layout} implements a layout that arranges child widgets to
surround the main area.
\image borderlayout-example.png
The constructor of the Window class creates a QTextBrowser object,
to which a BorderLayout named \c layout is added. The declaration
of the BorderLayout class is quoted at the end of this document.
\quotefromfile layouts/borderlayout/window.cpp
\skipto Window::Window()
\printuntil BorderLayout
Several labeled widgets are added to \c layout with the orientation
\c {Center}, \c {North}, \c {West}, \c {East 1}, \c {East 2}, and
\c {South}.
\skipto layout->addWidget
\printuntil setWindowTitle
createLabel() in class \c Window sets the text of the labeled widgets
and the style.
\skipto QLabel *Window::createLabel
\printuntil /^\}/
Class BorderLayout contains all the utilitarian functions for formatting
the widgets it contains.
\quotefromfile layouts/borderlayout/borderlayout.h
\skipto class
\printuntil /^\}/
For more information, visit the \l{Layout Management} page.
\include examples-run.qdocinc
*/

View File

@ -4,6 +4,7 @@
/*!
\example widgets/calculator
\title Calculator Example
\examplecategory {User Interface Components}
\ingroup examples-widgets
\ingroup examples-layout
\brief The example shows how to use signals and slots to implement the

View File

@ -1,202 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example richtext/calendar
\title Calendar Example
\ingroup examples-richtext
\brief The Calendar example shows how to create rich text content
and display it using a rich text editor.
\brief The Calendar example shows how to create rich text content and display it using
a rich text editor.
\image calendar-example.png
Specifically, the example demonstrates the following:
\list
\li Use of a text editor with a text document
\li Insertion of tables and frames into a document
\li Navigation within a table
\li Insert text in different styles
\endlist
The rich text editor used to display the document is used within a main window
application.
\section1 MainWindow Class Definition
The \c MainWindow class provides a text editor widget and some controls to
allow the user to change the month and year shown. The font size used for the
text can also be adjusted.
\snippet richtext/calendar/mainwindow.h 0
The private \c insertCalendar() function performs most of the work, relying on
the \c fontSize and \c selectedDate variables to write useful information to
the \c editor.
\section1 MainWindow Class Implementation
The \c MainWindow constructor sets up the user interface and initializes
variables used to generate a calendar for each month.
\snippet richtext/calendar/mainwindow.cpp 0
We begin by setting default values for the selected date that will be highlighted
in the calendar and the font size to be used. Since we are using a QMainWindow
for the user interface, we construct a widget for use as the central widget.
The user interface will include a line of controls above the generated calendar;
we construct a label and a combobox to allow the month to be selected, and a
spin box for the year. These widgets are configured to provide a reasonable range
of values for the user to try:
\snippet richtext/calendar/mainwindow.cpp 1
We use the \c selectedDate object to obtain the current month and year, and we
set these in the combobox and spin box:
The font size is displayed in a spin box which we restrict to a sensible range
of values:
\snippet richtext/calendar/mainwindow.cpp 2
We construct an editor and use the \c insertCalendar() function to create
a calendar for it. Each calendar is displayed in the same text editor; in
this example we use a QTextBrowser since we do not allow the calendar to be
edited.
The controls used to set the month, year, and font size will not have any
effect on the appearance of the calendar unless we make some signal-slot
connections:
\snippet richtext/calendar/mainwindow.cpp 3
The signals are connected to some simple slots in the \c MainWindow class
which we will describe later.
We create layouts to manage the widgets we constructed:
\snippet richtext/calendar/mainwindow.cpp 4
Finally, the central widget is set for the window.
Each calendar is created for the editor by the \c insertCalendar() function
which uses the date and font size, defined by the private \a selectedDate
and \c fontSize variables, to produce a suitable plan for the specified
month and year.
\snippet richtext/calendar/mainwindow.cpp 5
We begin by clearing the editor's rich text document, and obtain a text
cursor from the editor that we will use to add content. We also create a
QDate object based on the currently selected date.
The calendar is made up of a table with a gray background color that contains
seven columns: one for each day of the week. It is placed in the center of the
page with equal space to the left and right of it. All of these properties are
set in a QTextTableFormat object:
\snippet richtext/calendar/mainwindow.cpp 6
Each cell in the table will be padded and spaced to make the text easier to
read.
We want the columns to have equal widths, so we provide a list containing
percentage widths for each of them and set the constraints in the
QTextTableFormat:
\snippet richtext/calendar/mainwindow.cpp 7
The constraints used for the column widths are only useful if the table has
an appropriate number of columns. With the format for the table defined, we
construct a new table with one row and seven columns at the current cursor
position:
\snippet richtext/calendar/mainwindow.cpp 8
We only need one row to start with; more can be added as we need them. Using
this approach means that we do not need to perform any date calculations
until we add cells to the table.
When inserting objects into a document with the cursor's insertion functions,
the cursor is automatically moved inside the newly inserted object. This means
that we can immediately start modifying the table from within:
\snippet richtext/calendar/mainwindow.cpp 9
Since the table has an outer frame, we obtain the frame and its format so that
we can customize it. After making the changes we want, we set the frame's format
using the modified format object. We have given the table an outer border one
pixel wide.
\snippet richtext/calendar/mainwindow.cpp 10
In a similar way, we obtain the cursor's current character format and
create customized formats based on it.
We do not set the format on the cursor because this would change the default
character format; instead, we use the customized formats explicitly when we
insert text. The following loop inserts the days of the week into the table
as bold text:
\snippet richtext/calendar/mainwindow.cpp 11
For each day of the week, we obtain an existing table cell in the first row
(row 0) using the table's \l{QTextTable::cellAt()}{cellAt()} function. Since
we start counting the days of the week at day 1 (Monday), we subtract 1 from
\c weekDay to ensure that we obtain the cell for the correct column of the
table.
Before text can be inserted into a cell, we must obtain a cursor with the
correct position in the document. The cell provides a function for this
purpose, and we use this cursor to insert text using the \c boldFormat
character format that we created earlier:
\snippet richtext/calendar/mainwindow.cpp 12
Inserting text into document objects usually follows the same pattern.
Each object can provide a new cursor that corresponds to the first valid
position within itself, and this can be used to insert new content. We
continue to use this pattern as we insert the days of the month into the
table.
Since every month has more than seven days, we insert a single row to begin
and add days until we reach the end of the month. If the current date is
encountered, it is inserted with a special format (created earlier) that
makes it stand out:
\snippet richtext/calendar/mainwindow.cpp 13
We add a new row to the table at the end of each week only if the next week
falls within the currently selected month.
For each calendar that we create, we change the window title to reflect the
currently selected month and year:
\snippet richtext/calendar/mainwindow.cpp 14
The \c insertCalendar() function relies on up-to-date values for the month,
year, and font size. These are set in the following slots:
\snippet richtext/calendar/mainwindow.cpp 15
The \c setFontSize() function simply changes the private \c fontSize variable
before updating the calendar.
\snippet richtext/calendar/mainwindow.cpp 16
The \c setMonth slot is called when the QComboBox used to select the month is
updated. The value supplied is the currently selected row in the combobox.
We add 1 to this value to obtain a valid month number, and create a new QDate
based on the existing one. The calendar is then updated to use this new date.
\snippet richtext/calendar/mainwindow.cpp 17
The \c setYear() slot is called when the QDateTimeEdit used to select the
year is updated. The value supplied is a QDate object; this makes
the construction of a new value for \c selectedDate simple. We update the
calendar afterwards to use this new date.
*/

View File

@ -3,6 +3,7 @@
/*!
\title Calendar Widget Example
\examplecategory {Graphics & Multimedia}
\example widgets/calendarwidget
\ingroup examples-widgets
\ingroup examples-layout

View File

@ -1,251 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example widgets/charactermap
\title Character Map Example
\ingroup examples-widgets
\brief The Character Map example shows how to create a custom widget that can
both display its own content and respond to user input.
The example displays an array of characters which the user can click on
to enter text in a line edit. The contents of the line edit can then be
copied into the clipboard, and pasted into other applications. The
purpose behind this sort of tool is to allow users to enter characters
that may be unavailable or difficult to locate on their keyboards.
\borderedimage charactermap-example.png
\caption Screenshot of the Character Map example
The example consists of the following classes:
\list
\li \c CharacterWidget displays the available characters in the current
font and style.
\li \c MainWindow provides a standard main window that contains font and
style information, a view onto the characters, a line edit, and a push
button for submitting text to the clipboard.
\endlist
\section1 CharacterWidget Class Definition
The \c CharacterWidget class is used to display an array of characters in
a user-specified font and style. For flexibility, we subclass QWidget and
reimplement only the functions that we need to provide basic rendering
and interaction features.
The class definition looks like this:
\snippet widgets/charactermap/characterwidget.h 0
The widget does not contain any other widgets, so it must provide its own
size hint to allow its contents to be displayed correctly.
We reimplement \l{QWidget::paintEvent()} to draw custom content. We also
reimplement \l{QWidget::mousePressEvent()} to allow the user to interact
with the widget.
The updateFont() and updateStyle() slots are used to update the font and
style of the characters in the widget whenever the user changes the
settings in the application.
The class defines the characterSelected() signal so that other parts
of the application are informed whenever the user selects a character in
the widget.
As a courtesy, the widget provides a tooltip that shows the current
character value. We reimplement the \l{QWidget::mouseMoveEvent()} event
handler and define showToolTip() to enable this feature.
The \c columns, \c displayFont and \c currentKey private data members
are used to record the number of columns to be shown, the current font,
and the currently highlighted character in the widget.
\section1 CharacterWidget Class Implementation
Since the widget is to be used as a simple canvas, the constructor just
calls the base class constructor and defines some default values for
private data members.
\snippet widgets/charactermap/characterwidget.cpp 0
We initialize \c currentKey with a value of -1 to indicate
that no character is initially selected. We enable mouse tracking to
allow us to follow the movement of the cursor across the widget.
The class provides two functions to allow the font and style to be set up.
Each of these modify the widget's display font and call update():
\snippet widgets/charactermap/characterwidget.cpp 1
\codeline
\snippet widgets/charactermap/characterwidget.cpp 2
We use a fixed size font for the display. Similarly, a fixed size hint is
provided by the sizeHint() function:
\snippet widgets/charactermap/characterwidget.cpp 3
Three standard event functions are implemented so that the widget
can respond to clicks, provide tooltips, and render the available
characters. The paintEvent() shows how the contents of the widget are
arranged and displayed:
\snippet widgets/charactermap/characterwidget.cpp 6
A QPainter is created for the widget and, in all cases, we ensure that the
widget's background is painted. The painter's font is set to the
user-specified display font.
The area of the widget that needs to be redrawn is used to determine which
characters need to be displayed:
\snippet widgets/charactermap/characterwidget.cpp 7
Using integer division, we obtain the row and column numbers of each
characters that should be displayed, and we draw a square on the widget
for each character displayed.
\snippet widgets/charactermap/characterwidget.cpp 8
\snippet widgets/charactermap/characterwidget.cpp 9
The symbols for each character in the array are drawn within each square,
with the symbol for the most recently selected character displayed in red:
\snippet widgets/charactermap/characterwidget.cpp 10
We do not need to take into account the difference between the area
displayed in the viewport and the area we are drawing on because
everything outside the visible area will be clipped.
The mousePressEvent() defines how the widget responds to mouse clicks.
\snippet widgets/charactermap/characterwidget.cpp 5
We are only interested when the user clicks with the left mouse button
over the widget. When this happens, we calculate which character was
selected and emit the characterSelected() signal.
The character's number is found by dividing the x and y-coordinates of
the click by the size of each character's grid square. Since the number
of columns in the widget is defined by the \c columns variable, we
simply multiply the row index by that value and add the column number
to obtain the character number.
If any other mouse button is pressed, the event is passed on to the
QWidget base class. This ensures that the event can be handled properly
by any other interested widgets.
The mouseMoveEvent() maps the mouse cursor's position in global
coordinates to widget coordinates, and determines the character that
was clicked by performing the calculation
\snippet widgets/charactermap/characterwidget.cpp 4
The tooltip is given a position defined in global coordinates.
\section1 MainWindow Class Definition
The \c MainWindow class provides a minimal user interface for the example,
with only a constructor, slots that respond to signals emitted by standard
widgets, and some convenience functions that are used to set up the user
interface.
The class definition looks like this:
\snippet widgets/charactermap/mainwindow.h 0
The main window contains various widgets that are used to control how
the characters will be displayed, and defines the findFonts() function
for clarity and convenience. The findStyles() slot is used by the widgets
to determine the styles that are available, insertCharacter() inserts
a user-selected character into the window's line edit, and
updateClipboard() synchronizes the clipboard with the contents of the
line edit.
\section1 MainWindow Class Implementation
In the constructor, we set up the window's central widget and fill it with
some standard widgets (two comboboxes, a line edit, and a push button).
We also construct a CharacterWidget custom widget, and add a QScrollArea
so that we can view its contents:
\snippet widgets/charactermap/mainwindow.cpp 0
QScrollArea provides a viewport onto the \c CharacterWidget when we set
its widget and handles much of the work needed to provide a scrolling
viewport.
The font combo box is automatically populated with a list of available
fonts. We list the available styles for the current font in the style
combobox using the following function:
\snippet widgets/charactermap/mainwindow.cpp 1
The line edit and push button are used to supply text to the clipboard:
\snippet widgets/charactermap/mainwindow.cpp 2
We also obtain a clipboard object so that we can send text entered by the
user to other applications.
Most of the signals emitted in the example come from standard widgets.
We connect these signals to slots in this class, and to the slots provided
by other widgets.
\snippet widgets/charactermap/mainwindow.cpp 4
The font combobox's
\l{QFontComboBox::currentFontChanged()}{currentFontChanged()} signal is
connected to the findStyles() function so that the list of available styles
can be shown for each font that is used. Since both the font and the style
can be changed by the user, the font combobox's currentFontChanged() signal
and the style combobox's
\l{QComboBox::currentIndexChanged()}{currentIndexChanged()} are connected
directly to the character widget.
The final two connections allow characters to be selected in the character
widget, and text to be inserted into the clipboard:
\snippet widgets/charactermap/mainwindow.cpp 5
The character widget emits the characterSelected() custom signal when
the user clicks on a character, and this is handled by the insertCharacter()
function in this class. The clipboard is changed when the push button emits
the clicked() signal, and we handle this with the updateClipboard() function.
The remaining code in the constructor sets up the layout of the central widget,
and provides a window title:
\snippet widgets/charactermap/mainwindow.cpp 6
The font combobox is automatically populated with a list of available font
families. The styles that can be used with each font are found by the
findStyles() function. This function is called whenever the user selects a
different font in the font combobox.
\snippet widgets/charactermap/mainwindow.cpp 7
We begin by recording the currently selected style, and we clear the
style combobox so that we can insert the styles associated with the
current font family.
\snippet widgets/charactermap/mainwindow.cpp 8
We use the font database to collect the styles that are available for the
current font, and insert them into the style combobox. The current item is
reset if the original style is not available for this font.
The last two functions are slots that respond to signals from the character
widget and the main window's push button. The insertCharacter() function is
used to insert characters from the character widget when the user clicks a
character:
\snippet widgets/charactermap/mainwindow.cpp 9
The character is inserted into the line edit at the current cursor position.
The main window's "To clipboard" push button is connected to the
updateClipboard() function so that, when it is clicked, the clipboard is
updated to contain the contents of the line edit:
\snippet widgets/charactermap/mainwindow.cpp 10
We copy all the text from the line edit to the clipboard, but we do not clear
the line edit.
*/

View File

@ -1,58 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example itemviews/chart
\title Chart Example
\ingroup examples-itemviews
\brief The Chart example shows how to create a custom view for the model/view framework.
\image chart-example.png
In this example, the items in a table model are represented as slices in a pie chart,
relying on the flexibility of the model/view architecture to handle custom editing
and selection features.
\b{Note that you only need to create a new view class if your data requires a
specialized representation.} You should first consider using a standard QListView,
QTableView, or QTreeView with a custom QItemDelegate subclass if you need to
represent data in a special way.
\omit
\section1 PieView Class Definition
The \c PieView class is a subclass of QAbstractItemView. The base class provides
much of the functionality required by view classes, so we only need to provide
implementations for three public functions: visualRect(), scrollTo(), and
indexAt(). However, the view needs to maintain strict control over its look and
feel, so we also provide implementations for a number of other functions:
\snippet itemviews/chart/pieview.h 0
\section1 PieView Class Implementation
The paint event renders the data from the standard item model as a pie chart.
We interpret the data in the following way:
\list
\li Column 0 contains data in two different roles:
The \l{Qt::ItemDataRole}{DisplayRole} contains a label, and the
\l{Qt::ItemDataRole}{DecorationRole} contains the color of the pie slice.
\li Column 1 contains a quantity which we will convert to the angular extent of
the slice.
\endlist
The figure is always drawn with the chart on the left and the key on
the right. This means that we must try and obtain an area that is wider
than it is tall. We do this by imposing a particular aspect ratio on
the chart and applying it to the available vertical space. This ensures
that we always obtain the maximum horizontal space for the aspect ratio
used.
We also apply fixed size margin around the figure.
We use logical coordinates to draw the chart and key, and position them
on the view using viewports.
\endomit
*/

View File

@ -4,6 +4,7 @@
/*!
\example graphicsview/chip
\title 40000 Chips
\examplecategory {Graphics & Multimedia}
\ingroup examples-graphicsview
\brief Visualizes a huge graphic view scene with 40000 chip items.

View File

@ -1,167 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example dialogs/classwizard
\title Class Wizard Example
\ingroup examples-dialogs
\brief The Class Wizard example shows how to implement linear
wizards using QWizard.
\image classwizard.png Screenshot of the Class Wizard example
Most wizards have a linear structure, with page 1 followed by
page 2 and so on until the last page. Some wizards are more
complex in that they allow different traversal paths based on the
information provided by the user. The
\l{dialogs/licensewizard}{License Wizard} example shows how to
create such wizards.
The Class Wizard example consists of the following classes:
\list
\li \c ClassWizard inherits QWizard and provides a
three-step wizard that generates the skeleton of a C++ class
based on the user's input.
\li \c IntroPage, \c ClassInfoPage, \c CodeStylePage, \c
OutputFilesPage, and \c ConclusionPage are QWizardPage
subclasses that implement the wizard pages.
\endlist
\section1 ClassWizard Class Definition
\image classwizard-flow.png The Class Wizard pages
We will see how to subclass QWizard to implement our own wizard.
The concrete wizard class is called \c ClassWizard and provides
five pages:
\list
\li The first page is an introduction page, telling the user what
the wizard is going to do.
\li The second page asks for a class name and a base class, and
allows the user to specify whether the class should have a \c
Q_OBJECT macro and what constructors it should provide.
\li The third page allows the user to set some options related to the code
style, such as the macro used to protect the header file from
multiple inclusion (e.g., \c MYDIALOG_H).
\li The fourth page allows the user to specify the names of the
output files.
\li The fifth page is a conclusion page.
\endlist
Although the program is just an example, if you press \uicontrol Finish
(\uicontrol Done on \macos), actual C++ source files will actually be
generated.
\section1 The ClassWizard Class
Here's the \c ClassWizard definition:
\snippet dialogs/classwizard/classwizard.h 0
The class reimplements QDialog's \l{QDialog::}{accept()} slot.
This slot is called when the user clicks \uicontrol{Finish}.
Here's the constructor:
\snippet dialogs/classwizard/classwizard.cpp 1
We instantiate the five pages and insert them into the wizard
using QWizard::addPage(). The order in which they are inserted
is also the order in which they will be shown later on.
We call QWizard::setPixmap() to set the banner and the
background pixmaps for all pages. The banner is used as a
background for the page header when the wizard's style is
\l{QWizard::}{ModernStyle}; the background is used as the
dialog's background in \l{QWizard::}{MacStyle}. (See \l{Elements
of a Wizard Page} for more information.)
\snippet dialogs/classwizard/classwizard.cpp 3
\snippet dialogs/classwizard/classwizard.cpp 4
\dots
\snippet dialogs/classwizard/classwizard.cpp 5
\snippet dialogs/classwizard/classwizard.cpp 6
If the user clicks \uicontrol Finish, we extract the information from
the various pages using QWizard::field() and generate the files.
The code is long and tedious (and has barely anything to do with
noble art of designing wizards), so most of it is skipped here.
See the actual example in the Qt distribution for the details if
you're curious.
\section1 The IntroPage Class
The pages are defined in \c classwizard.h and implemented in \c
classwizard.cpp, together with \c ClassWizard. We will start with
the easiest page:
\snippet dialogs/classwizard/classwizard.h 1
\codeline
\snippet dialogs/classwizard/classwizard.cpp 7
A page inherits from QWizardPage. We set a
\l{QWizardPage::}{title} and a
\l{QWizard::WatermarkPixmap}{watermark pixmap}. By not setting
any \l{QWizardPage::}{subTitle}, we ensure that no header is
displayed for this page. (On Windows, it is customary for wizards
to display a watermark pixmap on the first and last pages, and to
have a header on the other pages.)
Then we create a QLabel and add it to a layout.
\section1 The ClassInfoPage Class
The second page is defined and implemented as follows:
\snippet dialogs/classwizard/classwizard.h 2
\codeline
\snippet dialogs/classwizard/classwizard.cpp 9
\dots
\snippet dialogs/classwizard/classwizard.cpp 12
\dots
\snippet dialogs/classwizard/classwizard.cpp 13
First, we set the page's \l{QWizardPage::}{title},
\l{QWizardPage::}{subTitle}, and \l{QWizard::LogoPixmap}{logo
pixmap}. The logo pixmap is displayed in the page's header in
\l{QWizard::}{ClassicStyle} and \l{QWizard::}{ModernStyle}.
Then we create the child widgets, create \l{Registering and Using
Fields}{wizard fields} associated with them, and put them into
layouts. The \c className field is created with an asterisk (\c
*) next to its name. This makes it a \l{mandatory fields}{mandatory field}, that
is, a field that must be filled before the user can press the
\uicontrol Next button (\uicontrol Continue on \macos). The fields' values
can be accessed from any other page using QWizardPage::field(),
or from the wizard code using QWizard::field().
\section1 The CodeStylePage Class
The third page is defined and implemented as follows:
\snippet dialogs/classwizard/classwizard.h 3
\codeline
\snippet dialogs/classwizard/classwizard.cpp 14
\dots
\snippet dialogs/classwizard/classwizard.cpp 15
\codeline
\snippet dialogs/classwizard/classwizard.cpp 16
The code in the constructor is very similar to what we did for \c
ClassInfoPage, so we skipped most of it.
The \c initializePage() function is what makes this class
interesting. It is reimplemented from QWizardPage and is used to
initialize some of the page's fields with values from the
previous page (namely, \c className and \c baseClass). For
example, if the class name on page 2 is \c SuperDuperWidget, the
default macro name on page 3 is \c SUPERDUPERWIDGET_H.
The \c OutputFilesPage and \c ConclusionPage classes are very
similar to \c CodeStylePage, so we won't review them here.
\sa QWizard, {License Wizard Example}, {Trivial Wizard Example}
*/

View File

@ -4,6 +4,7 @@
/*!
\example graphicsview/collidingmice
\title Colliding Mice Example
\examplecategory {Graphics & Multimedia}
\brief Demonstrates how to animate items on a graphics view.
\ingroup examples-graphicsview

View File

@ -4,6 +4,7 @@
/*!
\example itemviews/coloreditorfactory
\title Color Editor Factory Example
\examplecategory {User Interface Components}
\ingroup examples-itemviews
\brief This example shows how to create an editor that can be used by
a QItemDelegate.

View File

@ -4,20 +4,14 @@
/*!
\example itemviews/combowidgetmapper
\title Combo Widget Mapper Example
\examplecategory {User Interface Components}
\ingroup examples-itemviews
\brief The Combo Widget Mapper example shows how to use a custom delegate to
map information from a model to specific widgets on a form.
\image combowidgetmapper-example.png
In the \l{Simple Widget Mapper Example}, we showed the basic use of a
widget mapper to relate data exposed by a model to simple input widgets
in a user interface. However, sometimes we want to use input widgets that
expose data as choices to the user, such as QComboBox, and we need a way
to relate their input to the values stored in the model.
This example is very similar to the \l{Simple Widget Mapper Example}.
Again, we create a \c Window class with an almost identical user interface,
We create a \c Window class with an almost identical user interface,
except that, instead of providing a spin box so that each person's age
can be entered, we provide a combo box to allow their addresses to be
classified as "Home", "Work" or "Other".
@ -65,8 +59,7 @@
interfering with the other input widgets. The implementation is shown later.
\endomit
The rest of the constructor is very similar to that of the
\l{Simple Widget Mapper Example}:
The rest of the constructor sets up connections and layouts:
\snippet itemviews/combowidgetmapper/window.cpp Set up connections and layouts

View File

@ -4,6 +4,7 @@
/*!
\example tools/completer
\title Completer Example
\examplecategory {User Interface Components}
\ingroup examples-widgets-tools
\brief The Completer example shows how to provide string-completion facilities
@ -45,7 +46,7 @@
\snippet tools/completer/fsmodel.cpp 0
As mentioned earlier, the \c data() function is reimplemented in order to
get it to return the entire file parth for the display role. For example,
get it to return the entire file path for the display role. For example,
with a QFileSystemModel, you will see "Program Files" in the view. However, with
\c FileSystemModel, you will see "C:\\Program Files".
@ -201,7 +202,7 @@
\snippet tools/completer/mainwindow.cpp 14
The \c changeMaxVisible() update the maximum number of visible items in
The \c changeMaxVisible() updates the maximum number of visible items in
the completer.
\snippet tools/completer/mainwindow.cpp 15

View File

@ -4,6 +4,7 @@
/*!
\example painting/composition
\title Composition Modes
\examplecategory {Graphics & Multimedia}
\ingroup examples-painting
\brief Demonstrates how Composition Modes work in QPainter.
@ -18,5 +19,5 @@
drawn on top of the destination.
In addition to these standard modes, Qt defines the complete set of composition modes
as defined by X. Porter and Y. Duff. See the QPainter documentation for details.
as defined by T. Porter and T. Duff. See the QPainter documentation for details.
*/

View File

@ -4,6 +4,7 @@
/*!
\example painting/concentriccircles
\title Concentric Circles Example
\examplecategory {Graphics & Multimedia}
\ingroup examples-painting
\brief Demonstrates the improved quality that antialiasing and floating point precision gives.
@ -13,7 +14,7 @@
how to do simple animations.
The application's main window displays several widgets which are
drawn using the various combinations of precision and
drawn using various combinations of precision and
anti-aliasing.
\image concentriccircles-example.png

View File

@ -4,6 +4,7 @@
/*!
\example itemviews/customsortfiltermodel
\title Custom Sort/Filter Model Example
\examplecategory {User Interface Components}
\ingroup examples-itemviews
\brief The Custom Sort/Filter Model example illustrates how to subclass
QSortFilterProxyModel to perform advanced sorting and filtering.

View File

@ -4,6 +4,7 @@
/*!
\example painting/deform
\title Vector Deformation
\examplecategory {Graphics & Multimedia}
\ingroup examples-painting
\brief Demonstrates how to manipulate the elements of a QPainterPath.

View File

@ -4,6 +4,7 @@
/*!
\example graphicsview/diagramscene
\title Diagram Scene Example
\examplecategory {Graphics & Multimedia}
\ingroup examples-graphicsview
\brief Demonstrate how to use the Graphics View framework.
@ -12,7 +13,7 @@
The Diagram Scene example is an application in which you can
create a flowchart diagram. It is possible to add flowchart shapes
and text and connect the shapes by arrows as shown in the image
above. The shapes, arrows, and text can be given different
above. The shapes, arrows, and text can be given different
colors, and it is possible to change the font, style, and
underline of the text.
@ -121,9 +122,7 @@
We show an example of the creation of an action. The
functionality the actions trigger is discussed in the slots we
connect the actions to. You can see the \l{Qt Widgets - Application
Example}{application example} if you need a high-level
introduction to actions.
connect the actions to.
The is the \c createMenus() function:
@ -289,7 +288,7 @@
added to the scene. We set the mode of the scene back to the mode
before the item was inserted, which is ItemMove or InsertText
depending on which button is checked in the \c pointerTypeGroup.
We must also uncheck the button in the in the \c buttonGroup.
We must also uncheck the button in the \c buttonGroup.
Here is the implementation of \c textInserted():

View File

@ -1,51 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example widgets/digitalclock
\title Digital Clock Example
\ingroup examples-widgets
\brief The Digital Clock example shows how to use QLCDNumber to display a
number with LCD-like digits.
\borderedimage digitalclock-example.png
\caption Screenshot of the Digital Clock example
This example also demonstrates how QTimer can be used to update a widget
at regular intervals.
\section1 DigitalClock Class Definition
The \c DigitalClock class provides a clock widget showing the time with
hours and minutes separated by a blinking colon. We subclass QLCDNumber
and implement a private slot called \c showTime() to update the clock
display:
\snippet widgets/digitalclock/digitalclock.h 0
\section1 DigitalClock Class Implementation
\snippet widgets/digitalclock/digitalclock.cpp 0
In the constructor, we first change the look of the LCD numbers. The
QLCDNumber::Filled style produces raised segments filled with the
foreground color (typically black). We also set up a one-second timer
to keep track of the current time, and we connect
its \l{QTimer::timeout()}{timeout()} signal to the private \c showTime() slot
so that the display is updated every second. Then, we
call the \c showTime() slot; without this call, there would be a one-second
delay at startup before the time is shown.
\snippet widgets/digitalclock/digitalclock.cpp 1
\snippet widgets/digitalclock/digitalclock.cpp 2
The \c showTime() slot is called whenever the clock display needs
to be updated.
The current time is converted into a string with the format "hh:mm".
When QTime::second() is a even number, the colon in the string is
replaced with a space. This makes the colon appear and vanish every
other second.
Finally, we call QLCDNumber::display() to update the widget.
*/

View File

@ -1,49 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example itemviews/dirview
\title Dir View Example
\ingroup examples-itemviews
\brief This example demonstrates the usage of a tree view, and smooth flicking on a touchscreen.
The Dir View example shows a tree view of the local file
system. It uses the QFileSystemModel class to provide file
and directory information.
\borderedimage dirview-example.png
\quotefromfile itemviews/dirview/main.cpp
\skipto QCommandLineParser parser
\printuntil parser.positionalArguments
The example supports a number of command line options.
These options include:
\list
\li Application description
\li -help option
\li -version option
\li if the optionc {-c} is specified, the application will not
use custom directory options
\endlist
\skipto QFileSystemModel
\printuntil tree.setModel
Declares \c model as data model for reading the local filesystem.
\c model.setRootPath("") sets the current folder as the folder from
which \c model will start reading.
QTreeView object \c tree visualizes the filesystem in a tree structure.
\skipto tree.setAnimated(false)
\printuntil tree.setColumnWidth
Sets layout options for animation, indentation, sorting, and sizing of the
filesystem tree.
\skipto QScroller::grabGesture
\printuntil QScroller::grabGesture
Creates a \l QScroller instance to recognize gestures on touchscreens,
so that you can flick the tree view with your finger.
*/

View File

@ -1,140 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example mainwindows/dockwidgets
\title Dock Widgets Example
\ingroup examples-mainwindow
\brief The Dock Widgets example shows how to add dock windows to an
application. It also shows how to use Qt's rich text engine.
\image dockwidgets-example.png Screenshot of the Dock Widgets example
The application presents a simple business letter template, and has
a list of customer names and addresses and a list of standard
phrases in two dock windows. The user can click a customer to have
their name and address inserted into the template, and click one or
more of the standard phrases. Errors can be corrected by clicking
the Undo button. Once the letter has been prepared it can be printed
or saved as HTML.
\section1 MainWindow Class Definition
Here's the class definition:
\snippet mainwindows/dockwidgets/mainwindow.h 0
We will now review each function in turn.
\section1 MainWindow Class Implementation
\snippet mainwindows/dockwidgets/mainwindow.cpp 0
We start by including \c <QtWidgets>, a header file that contains the
definition of all classes in the Qt Core, Qt GUI and Qt Widgets
modules. This saves us from having to include
every class individually and is especially convenient if we add new
widgets. We also include \c mainwindow.h.
\snippet mainwindows/dockwidgets/mainwindow.cpp 1
In the constructor, we start by creating a QTextEdit widget. Then we call
QMainWindow::setCentralWidget(). This function passes ownership of
the QTextEdit to the \c MainWindow and tells the \c MainWindow that
the QTextEdit will occupy the \c MainWindow's central area.
Then we call \c createActions(), \c createMenus(), \c
createToolBars(), \c createStatusBar(), and \c createDockWindows()
to set up the user interface. Finally we call \c setWindowTitle() to
give the application a title, and \c newLetter() to create a new
letter template.
We won't quote the \c createActions(), \c createMenus(), \c
createToolBars(), and \c createStatusBar() functions since they
follow the same pattern as all the other Qt examples.
\snippet mainwindows/dockwidgets/mainwindow.cpp 9
We create the customers dock window first, and in addition to a
window title, we also pass it a \c this pointer so that it becomes a
child of \c MainWindow. Normally we don't have to pass a parent
because widgets are parented automatically when they are laid out:
but dock windows aren't laid out using layouts.
We've chosen to restrict the customers dock window to the left and
right dock areas. (So the user cannot drag the dock window to the
top or bottom dock areas.) The user can drag the dock window out of
the dock areas entirely so that it becomes a free floating window.
We can change this (and whether the dock window is moveable or
closable) using QDockWidget::setFeatures().
Once we've created the dock window we create a list widget with the
dock window as parent, then we populate the list and make it the
dock window's widget. Finally we add the dock widget to the \c
MainWindow using \c addDockWidget(), choosing to put it in the right
dock area.
We undertake a similar process for the paragraphs dock window,
except that we don't restrict which dock areas it can be dragged to.
Finally we set up the signal-slot connections. If the user clicks a
customer or a paragraph their \c currentTextChanged() signal will be
emitted and we connect these to \c insertCustomer() and
addParagraph() passing the text that was clicked.
We briefly discuss the rest of the implementation, but have now
covered everything relating to dock windows.
\snippet mainwindows/dockwidgets/mainwindow.cpp 2
In this function we clear the QTextEdit so that it is empty. Next we
create a QTextCursor on the QTextEdit. We move the cursor to the
start of the document and create and format a frame. We then create
some character formats and a table format. We insert a table into
the document and insert the company's name and address into a table
using the table and character formats we created earlier. Then we
insert the skeleton of the letter including two markers \c NAME and
\c ADDRESS. We will also use the \c{Yours sincerely,} text as a marker.
\snippet mainwindows/dockwidgets/mainwindow.cpp 6
If the user clicks a customer we split the customer details into
pieces. We then look for the \c NAME marker using the \c find()
function. This function selects the text it finds, so when we call
\c insertText() with the customer's name the name replaces the marker.
We then look for the \c ADDRESS marker and replace it with each line
of the customer's address. Notice that we wrapped all the insertions
between a \c beginEditBlock() and \c endEditBlock() pair. This means
that the entire name and address insertion is treated as a single
operation by the QTextEdit, so a single undo will revert all the
insertions.
\snippet mainwindows/dockwidgets/mainwindow.cpp 7
This function works in a similar way to \c insertCustomer(). First
we look for the marker, in this case, \c {Yours sincerely,}, and then
replace it with the standard paragraph that the user clicked. Again
we use a \c beginEditBlock() ... \c endEditBlock() pair so that the
insertion can be undone as a single operation.
\snippet mainwindows/dockwidgets/mainwindow.cpp 3
Qt's QTextDocument class makes printing documents easy. We simply
take the QTextEdit's QTextDocument, set up the printer and print the
document.
\snippet mainwindows/dockwidgets/mainwindow.cpp 4
QTextEdit can output its contents in HTML format, so we prompt the
user for the name of an HTML file and if they provide one we simply
write the QTextEdit's contents in HTML format to the file.
\snippet mainwindows/dockwidgets/mainwindow.cpp 5
If the focus is in the QTextEdit, pressing \uicontrol Ctrl+Z undoes as
expected. But for the user's convenience we provide an
application-wide undo function that simply calls the QTextEdit's
undo: this means that the user can undo regardless of where the
focus is in the application.
*/

View File

@ -1,18 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example draganddrop/puzzle
\title Drag and Drop Puzzle Example
\brief The Drag and Drop Puzzle example demonstrates a way of using the drag and drop system with
item view widgets.
\image draganddroppuzzle-example.png
This example is an implementation of a simple jigsaw puzzle game using Qt's
drag and drop API.
The \l{Item Views Puzzle Example}{Item View Puzzle} example shows
many of the same features, but takes an alternative approach that uses Qt's
model/view framework to manage drag and drop operations.
*/

View File

@ -4,6 +4,7 @@
/*!
\example graphicsview/dragdroprobot
\title Drag and Drop Robot Example
\examplecategory {Graphics & Multimedia}
\ingroup examples-graphicsview
\brief Demonstrates how to drag and drop items in a graphics view.

View File

@ -4,6 +4,7 @@
/*!
\example draganddrop/draggableicons
\title Draggable Icons Example
\examplecategory {User Interface Components}
\brief The Draggable Icons example shows how to drag and drop image data between widgets
in the same application, and between different applications.

View File

@ -4,6 +4,7 @@
/*!
\example draganddrop/draggabletext
\title Draggable Text Example
\examplecategory {User Interface Components}
\brief Illustrates how to drag and drop text between widgets.
\brief The Draggable Text example shows how to drag and drop textual data between widgets

View File

@ -1,91 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example layouts/dynamiclayouts
\title Dynamic Layouts Example
\brief Shows how to re-orient widgets in running applications.
\e{Dynamic Layouts} implements dynamically placed widgets within running
applications. The widget placement depends on whether \c Horizontal or \c
Vertical is chosen.
\borderedimage dynamiclayouts-example.png
For more information, visit the \l{Layout Management} page.
\section1 Dialog Constructor
To begin with, the application creates the UI components by calling the
following methods:
\list
\li createRotatableGroupBox()
\li createOptionsGroupBox()
\li createButtonBox()
\endlist
It then adds the UI components to a GridLayout (\c mainLayout).
Finally, \c Dialog::rotateWidgets() is called.
\quotefromfile layouts/dynamiclayouts/dialog.cpp
\skipuntil createRotatableGroupBox
\printuntil setWindowTitle
\section1 Creating the Main Widgets
The \c createRotatableGroupBox() method creates a rotatable group box,
then adds a series of widgets:
\list
\li QSpinBox
\li QSlider
\li QDial
\li QProgressBar
\endlist
It goes on to add signals and slots to each widget, and assigns
a QGridLayout called \a rotatableLayout.
\skipto Dialog::createRotatableGroupBox
\printuntil /^\}/
\section1 Adding Options
\c createOptionsGroupBox() creates the following widgets:
\list
\li \c optionsGroupBox
\li \c buttonsOrientationLabel
\li \c buttonsOrientationComboBox. The orientation of the ComboBox is either
\c horizontal (default value) or \c vertical. These two values
are added during the startup of the application. It is not possible
to leave the option empty.
\endlist
\skipto Dialog::createOptionsGroupBox()
\printuntil /^\}/
\section1 Adding Buttons
createButtonBox() constructs a QDialogButtonBox called \c buttonBox
to which are added a \c closeButton, a \c helpButton and a
\c rotateWidgetsButton.
It then assigns a signal and a slot to each button in \c buttonBox.
\skipto Dialog::createButtonBox()
\printuntil /^\}/
\section1 Rotating the Widgets
Removes the current widgets and activates the next widget.
\quotefromfile layouts/dynamiclayouts/dialog.cpp
\skipto Dialog::rotateWidgets()
\printuntil rotatableLayout->addWidget(rotatableWidgets[i]
\printuntil }
\printuntil }
\include examples-run.qdocinc
*/

View File

@ -4,6 +4,7 @@
/*!
\example animation/easing
\title Easing Curves Example
\examplecategory {Graphics & Multimedia}
\brief The Easing Curves example shows how to use easing curves to
control the speed of an animation.

View File

@ -4,6 +4,7 @@
/*!
\example tools/echoplugin
\title Echo Plugin Example
\examplecategory {Data Processing & I/O}
\ingroup examples-widgets-tools
\ingroup examples-layout
@ -175,7 +176,5 @@
create plugins.
We give an example of a plugin that extends Qt in the \l{Style
Plugin Example}{style plugin} example. The \l{Plug & Paint
Example}{plug and paint} example shows how to create static
plugins.
Plugin Example}{style plugin} example.
*/

View File

@ -4,9 +4,10 @@
/*!
\example itemviews/editabletreemodel
\title Editable Tree Model Example
\examplecategory {User Interface Components}
\ingroup examples-itemviews
\brief This example shows how to implement a simple item-based tree model that can
be used with other classes the model/view framework.
be used with other classes in the model/view framework.
\image itemviews-editabletreemodel.png

View File

@ -4,6 +4,7 @@
/*!
\example graphicsview/elasticnodes
\title Elastic Nodes Example
\examplecategory {Graphics & Multimedia}
\ingroup examples-graphicsview
\brief Demonstrates how to interact with graphical items in a scene.

View File

@ -1,15 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example graphicsview/embeddeddialogs
\title Embedded Dialogs
\ingroup examples-graphicsview-layout
\brief Demonstrates how to embed dialogs into a graphics view.
This example shows how to embed standard dialogs into
Graphics View. It also shows how you can customize the
proxy class and add window shadows.
\image embeddeddialogs-demo.png
*/

View File

@ -1,121 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example dialogs/extension
\title Extension Example
\ingroup examples-dialogs
\brief The Extension example shows how to add an extension to a QDialog
using the QAbstractButton::toggled() signal and the
QWidget::setVisible() slot.
\image extension-example.png Screenshot of the Extension example
The Extension application lets the user add search parameters in
a dialog and launch a simple or advanced search.
The simple search has two options: \uicontrol {Match case} and \uicontrol
{Search from start}. The advanced search offers search for \uicontrol {Whole words},
\uicontrol {Search backward}, and \uicontrol {Search selection}. The
application starts with simple search as the default. Click the \uicontrol More button
to show the advanced search options:
\image extension_more.png Screenshot of the Extension example
\section1 FindDialog Class Definition
The \c FindDialog class inherits QDialog. QDialog is the
base class for dialog windows. A dialog window is a top-level
window mostly used for short-term tasks and brief communications
with the user.
\snippet dialogs/extension/finddialog.h 0
The \c FindDialog widget is the main application widget, and
displays the application's search options and controlling
buttons.
In addition to the constructor, there are several child widgets:
\list
\li A QLineEdit with an associated QLabel to let the
user type a word to search for.
\li Several \l {QCheckBox}{QCheckBox}es to facilitate the search options.
\li Three \l {QPushButton}{QPushButton}s:
\list
\li the \uicontrol Find button to start a search
\li the \uicontrol More button to enable an advanced search
\li a QWidget representing the application's extension part
\endlist
\endlist
\section1 FindDialog Class Implementation
Create the standard child widgets for the simple search in the constructor:
the QLineEdit with the associated QLabel, two {QCheckBox}es and all the
\l {QPushButton}{QPushButton}s.
\snippet dialogs/extension/finddialog.cpp 0
This snippet illustrates how you can define a shortcut key
for a widget. A shortcut should be defined by putting the ampersand
character (\c &) in front of the letter that should
become the shortcut.
For example, for \uicontrol {Find what}, pressing \uicontrol Alt
and \uicontrol w transfers focus to the QLineEdit widget.
Shortcuts can also be used for checking on or off a checkmark.
For example, pressing \uicontrol Alt and \uicontrol c puts the check mark
on \uicontrol {Match Case} if it was unchecked and vice versa.
It is the QLabel::setBuddy() method that links a widget to the shortcut
character if it has been defined.
Set the \uicontrol Find button's default property to true, using the
QPushButton::setDefault() function. Then the push button will be
pressed if the user presses the Enter (or Return) key. Note that a
QDialog can only have one default button.
\snippet dialogs/extension/finddialog.cpp 2
Create the extension widget, and the \l {QCheckBox}{QCheckBox}es associated
with the advanced search options.
\snippet dialogs/extension/finddialog.cpp 3
Now that the extension widget is created, connect the \uicontrol
More button's \l{QAbstractButton::toggled()}{toggled()} signal to
the extension widget's \l{QWidget::setVisible()}{setVisible()} slot.
The QAbstractButton::toggled() signal is emitted whenever a
checkable button changes its state. The signal's argument is true
if the button is checked, or false if the button is unchecked. The
QWidget::setVisible() slot sets the widget's visible status. If
the status is true the widget is shown, otherwise the widget is
hidden.
Since the \uicontrol More button is checkable, the connection makes
sure that the extension widget is shown depending on the state of
the \uicontrol More button.
Create checkboxes associated with the advanced search options in
a layout installed on the extension widget.
\snippet dialogs/extension/finddialog.cpp 4
Before creating the main layout, create several child layouts
for the widgets. First align the QLabel and its buddy, the
QLineEdit, using a QHBoxLayout. Then align the QLabel and the QLineEdit
vertically with the checkboxes associated with the simple search,
using a QVBoxLayout. Create also a QVBoxLayout for the buttons.
Finally, lay out the two latter layouts and the extension widget
using a QGridLayout.
\snippet dialogs/extension/finddialog.cpp 5
Hide the extension widget using the QWidget::hide()
function, making the application only show the simple search
options when it starts. When the user wants to access the advanced
search options, the dialog only needs to change the visibility of
the extension widget. Qt's layout management takes care of the
dialog's appearance.
*/

View File

@ -1,15 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example effects/fademessage
\title Fade Message Effect Example
\ingroup examples-graphicsview-graphicseffects
\brief Demonstrates how to apply effects on items in the view.
\div { style="text-align: left"}
\inlineimage fademessageeffect-example.png
\inlineimage fademessageeffect-example-faded.png
\enddiv
*/

View File

@ -4,6 +4,7 @@
/*!
\example itemviews/fetchmore
\title Fetch More Example
\examplecategory {User Interface Components}
\ingroup examples-itemviews
\brief The Fetch More example shows how to add items to an item view
model on demand.

View File

@ -4,6 +4,7 @@
/*!
\example layouts/flowlayout
\title Flow Layout Example
\examplecategory {User Interface Components}
\ingroup examples-layout
\brief Shows how to arrange widgets for different window sizes.

View File

@ -1,13 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example painting/fontsampler
\title Font Sampler Example
\ingroup examples-painting
\brief The Font Sampler example shows how to preview and print multi-page documents.
The Font Sampler example shows how to preview and print multi-page documents.
\image fontsampler-example.png
*/

View File

@ -1,338 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example draganddrop/fridgemagnets
\title Fridge Magnets Example
\brief The Fridge Magnets example illustrates how to move around several types of
MIME-encoded data with drag and drop.
The Fridge Magnets example shows how to supply more than one type
of MIME-encoded data with a drag and drop operation.
\image fridgemagnets-example.png
With this application the user can play around with a collection
of fridge magnets, using drag and drop to form new sentences from
the words on the magnets. The example consists of two classes:
\list
\li \c DragLabel is a custom widget representing one
single fridge magnet.
\li \c DragWidget provides the main application window.
\endlist
We will first take a look at the \c DragLabel class, then we will
examine the \c DragWidget class.
\section1 DragLabel Class Definition
Each fridge magnet is represented by an instance of the \c
DragLabel class:
\snippet draganddrop/fridgemagnets/draglabel.h 0
Each instance of this QLabel subclass will be used to display an
pixmap generated from a text string. Since we cannot store both
text and a pixmap in a standard label, we declare a private variable
to hold the original text, and we define an additional member
function to allow it to be accessed.
\section1 DragLabel Class Implementation
In the \c DragLabel constructor, we first create a QImage object
on which we will draw the fridge magnet's text and frame:
\snippet draganddrop/fridgemagnets/draglabel.cpp 0
Its size depends on the current font size, and its format is
QImage::Format_ARGB32_Premultiplied; i.e., the image is stored
using a premultiplied 32-bit ARGB format (0xAARRGGBB).
We then construct a font object that uses the application's
default font, and set its style strategy. The style strategy tells
the font matching algorithm what type of fonts should be used to
find an appropriate default family. The QFont::ForceOutline forces
the use of outline fonts.
To draw the text and frame onto the image, we use the QPainter
class. QPainter provides highly optimized methods to do most of
the drawing GUI programs require. It can draw everything from
simple lines to complex shapes like pies and chords. It can also
draw aligned text and pixmaps.
\snippet draganddrop/fridgemagnets/draglabel.cpp 1
A painter can be activated by passing a paint device to the
constructor, or by using the \l{QPainter::}{begin()} method as we
do in this example. The \l{QPainter::}{end()} method deactivates
it. Note that the latter function is called automatically upon
destruction when the painter is activated by its constructor. The
QPainter::Antialiasing render hint ensures that the paint engine
will antialias the edges of primitives if possible.
When the painting is done, we convert our image to a pixmap using
QPixmap's \l {QPixmap::}{fromImage()} method. This method also
takes an optional flags argument, and converts the given image to
a pixmap using the specified flags to control the conversion (the
flags argument is a bitwise-OR of the Qt::ImageConversionFlags;
passing 0 for flags sets all the default options).
\snippet draganddrop/fridgemagnets/draglabel.cpp 2
Finally, we set the label's \l{QLabel::pixmap}{pixmap property}
and store the label's text for later use.
\e{Note that setting the pixmap clears any previous content, including
any text previously set using QLabel::setText(), and disables
the label widget's buddy shortcut, if any.}
\section1 DragWidget Class Definition
The \c DragWidget class inherits QWidget, providing support for
drag and drop operations:
\snippet draganddrop/fridgemagnets/dragwidget.h 0
To make the widget responsive to drag and drop operations, we simply
reimplement the \l{QWidget::}{dragEnterEvent()},
\l{QWidget::}{dragMoveEvent()} and \l{QWidget::}{dropEvent()} event
handlers inherited from QWidget.
We also reimplement \l{QWidget::}{mousePressEvent()} to make the
widget responsive to mouse clicks. This is where we will write code
to start drag and drop operations.
\section1 DragWidget Class Implementation
In the constructor, we first open the file containing the words on
our fridge magnets:
\snippet draganddrop/fridgemagnets/dragwidget.cpp 0
QFile is an I/O device for reading and writing text and binary
files and resources, and may be used by itself or in combination
with QTextStream or QDataStream. We have chosen to read the
contents of the file using the QTextStream class that provides a
convenient interface for reading and writing text.
We then create the fridge magnets. As long as there is data (the
QTextStream::atEnd() method returns true if there is no more data
to be read from the stream), we read one line at a time using
QTextStream's \l {QTextStream::}{readLine()} method.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 1
For each line, we create a \c DragLabel object using the read line
as text, we calculate its position and ensure that it is visible by
calling the QWidget::show() method. We set the Qt::WA_DeleteOnClose
attribute on each label to ensure that any unused labels will be
deleted; we will need to create new labels and delete old ones when
they are dragged around, and this ensures that the example does not
leak memory.
We also set the \c FridgeMagnets widget's palette, minimum size
and window title.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 2
Finally, to enable our user to move the fridge magnets around, we
must also set the \c FridgeMagnets widget's
\l{QWidget::acceptDrops}{acceptDrops} property.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 3
Setting this property to true announces to the system that this
widget \e may be able to accept drop events (events that are sent
when drag and drop actions are completed). Later, we will
implement the functions that ensure that the widget accepts the
drop events it is interested in.
\section2 Dragging
Let's take a look at the \l{QWidget::}{mousePressEvent()} event
handler, where drag and drop operations begin:
\snippet draganddrop/fridgemagnets/dragwidget.cpp 13
\snippet draganddrop/fridgemagnets/dragwidget.cpp 14
Mouse events occur when a mouse button is pressed or released
inside a widget, or when the mouse cursor is moved. By
reimplementing the \l{QWidget::}{mousePressEvent()} method we
ensure that we will receive mouse press events for the widget
containing the fridge magnets.
Whenever we receive such an event, we first check to see if the
position of the click coincides with one of the labels. If not,
we simply return.
If the user clicked a label, we determine the position of the
\e{hot spot} (the position of the click relative to the top-left
corner of the label). We create a byte array to store the label's
text and the hot spot, and we use a QDataStream object to stream
the data into the byte array.
With all the information in place, we create a new QMimeData object.
As mentioned above, QMimeData objects associate the data that they
hold with the corresponding MIME types to ensure that information
can be safely transferred between applications. The
\l{QMimeData::}{setData()} method sets the data associated with a
given MIME type. In our case, we associate our item data with the
custom \c application/x-fridgemagnet type.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 15
Note that we also associate the magnet's text with the
\c text/plain MIME type using QMimeData's \l{QMimeData::}{setText()}
method. Below, we will see how our widget detects both these MIME
types with its event handlers.
Finally, we create a QDrag object. It is the QDrag class that
handles most of the details of a drag and drop operation,
providing support for MIME-based drag and drop data transfer. The
data to be transferred by the drag and drop operation is contained
in a QMimeData object. When we call QDrag's
\l{QDrag::}{setMimeData()} method the ownership of our item data is
transferred to the QDrag object.
We call the \l{QDrag::}{setPixmap()} function to set the pixmap used
to represent the data during the drag and drop operation.
Typically, this pixmap shows an icon that represents the MIME type
of the data being transferred, but any pixmap can be used. In this
example, we simply use the pixmap used by the label itself to make
it look like the fridge magnet itself is being moved.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 16
We also specify the cursor's hot spot, its position relative to the
top-level corner of the drag pixmap, to be the point we calculated
above. This makes the process of dragging the label feel more natural
because the cursor always points to the same place on the label
during the drag operation.
We start the drag operation using QDrag's \l{QDrag::}{exec()} function,
requesting that the magnet is copied when the drag is completed.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 17
The function returns the drop action actually performed by the user
(this can be either a copy or a move action in this case); if this
action is equal to Qt::MoveAction we will close the activated
fridge magnet widget because we will create a new one to replace it
(see the \l{drop}{dropEvent()} implementation). Otherwise, if
the drop is outside our main widget, we simply show the widget in
its original position.
\section2 Dropping
When a a drag and drop action enters our widget, we will receive a
drag enter \e event. QDragEnterEvent inherits most of its
functionality from QDragMoveEvent, which in turn inherits most of
its functionality from QDropEvent. Note that we must accept this
event in order to receive the drag move events that are sent while
the drag and drop action is in progress. The drag enter event is
always immediately followed by a drag move event.
In our \c dragEnterEvent() implementation, we first determine
whether we support the event's MIME type or not:
\snippet draganddrop/fridgemagnets/dragwidget.cpp 4
\snippet draganddrop/fridgemagnets/dragwidget.cpp 5
\snippet draganddrop/fridgemagnets/dragwidget.cpp 6
If the type is \c application/x-fridgemagnet and the event
origins from any of this application's fridge magnet widgets, we
first set the event's drop action using the
QDropEvent::setDropAction() method. An event's drop action is the
action to be performed on the data by the target. Qt::MoveAction
indicates that the data is moved from the source to the target.
Then we call the event's \l {QDragMoveEvent::}{accept()} method to
indicate that we have handled the event. In general, unaccepted
events might be propagated to the parent widget. If the event
origins from any other widget, we simply accept the proposed
action.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 7
We also accept the proposed action if the event's MIME type is \c
text/plain, i.e., if QMimeData::hasText() returns true. If the
event has any other type, on the other hand, we call the event's
\l {QDragMoveEvent::}{ignore()} method allowing the event to be
propagated further.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 8
Drag move events occur when the cursor enters a widget, when it
moves within the widget, and when a modifier key is pressed on the
keyboard while the widget has focus. Our widget will receive drag
move events repeatedly while a drag is within its boundaries. We
reimplement the \l {QWidget::}{dragMoveEvent()} method, and
examine the event in the exact same way as we did with drag enter
events.
Note that the \l{QWidget::}{dropEvent()} event handler behaves
slightly differently: We first get hold of the event's MIME
data.
\target drop
\snippet draganddrop/fridgemagnets/dragwidget.cpp 9
The QMimeData class provides a container for data that
records information about its MIME type. QMimeData objects
associate the data that they hold with the corresponding MIME
types to ensure that information can be safely transferred between
applications, and copied around within the same application.
We retrieve the data associated with the \c application/x-fridgemagnet
MIME type using a data stream in order to create a new \c DragLabel
object.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 10
The QDataStream class provides serialization of binary data to a
QIODevice (a data stream is a binary stream of encoded information
which is completely independent of the host computer's operating
system, CPU or byte order).
Finally, we create a label and move it to the event's position:
\snippet draganddrop/fridgemagnets/dragwidget.cpp 11
If the source of the event is also the widget receiving the
drop event, we set the event's drop action to Qt::MoveAction and
call the event's \l{QDragMoveEvent::}{accept()}
method. Otherwise, we simply accept the proposed action. This
means that labels are moved rather than copied in the same
window. However, if we drag a label to a second instance of the
Fridge Magnets example, the default action is to copy it, leaving
the original in the first instance.
If the event's MIME type is \c text/plain (i.e., if
QMimeData::hasText() returns true) we retrieve its text and split
it into words. For each word we create a new \c DragLabel action,
and show it at the event's position plus an offset depending on
the number of words in the text. In the end we accept the proposed
action. This lets the user drop selected text from a text editor or
Web browser onto the widget to add more fridge magnets.
\snippet draganddrop/fridgemagnets/dragwidget.cpp 12
If the event has any other type, we call the event's
\l{QDragMoveEvent::}{ignore()} method allowing the event to be
propagated further.
\section1 Summary
We set our main widget's \l{QWidget::}{acceptDrops} property
and reimplemented QWidget's \l{QWidget::}{dragEnterEvent()},
\l{QWidget::}{dragMoveEvent()} and \l{QWidget::}{dropEvent()} event
handlers to support content dropped on our widget.
In addition, we reimplemented the \l{QWidget::}{mousePressEvent()}
function to let the user pick up fridge magnets in the first place.
Because data is communicated using drag and drop operations and
encoded using MIME types, you can run more than one instance of this
example, and transfer magnets between them.
*/

View File

@ -4,6 +4,7 @@
/*!
\example itemviews/frozencolumn
\title Frozen Column Example
\examplecategory {User Interface Components}
\ingroup examples-itemviews
\brief This example demonstrates how to freeze a column within a QTableView.

View File

@ -5,6 +5,7 @@
\example gallery
\meta {tag} {gallery}
\title Widgets Gallery Example
\examplecategory {User Interface Components}
\ingroup examples-widgets
\brief The Widgets Gallery example shows widgets relevant for designing UIs.

View File

@ -4,6 +4,7 @@
/*!
\example painting/gradients
\title Gradients
\examplecategory {Graphics & Multimedia}
\ingroup examples-painting
\brief Shows how gradients can be used with QPainter.

View File

@ -1,28 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example graphicsview/flowlayout
\title Graphics View Flow Layout Example
\ingroup examples-graphicsview-layout
\brief Demonstrates flow layout on a graphics view scene.
The Graphics View Flow Layout example shows the use of a flow layout
in a Graphics View widget.
\image graphicsflowlayout-example.png
This example uses a Graphics View to display the widget, which is a more
customizable approach than displaying the flow layout in the application
window (See \l {Flow Layout Example}).
Graphics View Flow Layout snippet:
\snippet graphicsview/flowlayout/main.cpp 1
Flow Layout Example snippet:
\snippet layouts/flowlayout/main.cpp 1
*/

View File

@ -4,6 +4,7 @@
/*!
\example graphicsview/simpleanchorlayout
\title Simple Anchor Layout Example
\examplecategory {Graphics & Multimedia}
\ingroup examples-graphicsview-layout
\brief Demonstrates anchor layout on a graphics view scene.

View File

@ -4,6 +4,7 @@
/*!
\example widgets/groupbox
\title Group Box Example
\examplecategory {User Interface Components}
\ingroup examples-widgets
\brief The Group Box example shows how to use the different kinds of group
boxes in Qt.

View File

@ -1,805 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example widgets/icons
\title Icons Example
\ingroup examples-widgets
\brief The Icons example shows how QIcon can generate pixmaps reflecting
an icon's state, mode and size.
These pixmaps are generated from the set of pixmaps made available to the
icon, and are used by Qt widgets to show an icon representing a particular
action.
\image icons-example.png Screenshot of the Icons example
Contents:
\tableofcontents
\section1 QIcon Overview
The QIcon class provides scalable icons in different modes and
states. An icon's state and mode are depending on the intended use
of the icon. Qt currently defines four modes:
\table
\header \li Mode \li Description
\row
\li QIcon::Normal
\li Display the pixmap when the user is not interacting with the
icon, but the functionality represented by the icon is
available.
\row
\li QIcon::Active
\li Display the pixmap when the functionality represented by the
icon is available and the user is interacting with the icon,
for example, moving the mouse over it or clicking it.
\row
\li QIcon::Disabled
\li Display the pixmap when the functionality represented by
the icon is not available.
\row
\li QIcon::Selected
\li Display the pixmap when the icon is selected.
\endtable
QIcon's states are QIcon::On and QIcon::Off, which will display
the pixmap when the widget is in the respective state. The most
common usage of QIcon's states are when displaying checkable tool
buttons or menu entries (see QAbstractButton::setCheckable() and
QAction::setCheckable()). When a tool button or menu entry is
checked, the QIcon's state is \l{QIcon::}{On}, otherwise it's
\l{QIcon::}{Off}. You can, for example, use the QIcon's states to
display differing pixmaps depending on whether the tool button or
menu entry is checked or not.
A QIcon can generate smaller, larger, active, disabled, and
selected pixmaps from the set of pixmaps it is given. Such
pixmaps are used by Qt widgets to show an icon representing a
particular action.
\section1 Overview of the Icons Application
With the Icons application you get a preview of an icon's
generated pixmaps reflecting its different states, modes and size.
When an image is loaded into the application, it is converted into
a pixmap and becomes a part of the set of pixmaps available to the
icon. An image can be excluded from this set by checking off the
related checkbox. The application provides a sub directory
containing sets of images explicitly designed to illustrate how Qt
renders an icon in different modes and states.
The application allows you to manipulate the icon size with some
predefined sizes and a spin box. The predefined sizes are style
dependent, but most of the styles have the same values. Only the
\macos style differs by using 32 pixels instead of 16 pixels
for toolbar buttons. You can navigate between the available styles
using the \uicontrol View menu.
\image icons-view-menu.png Screenshot of the View menu
The \uicontrol View menu also provide the option to make the application
guess the icon state and mode from an image's file name. The \uicontrol
File menu provide the options of adding an image and removing all
images. These last options are also available through a context
menu that appears if you press the right mouse button within the
table of image files. In addition, the \uicontrol File menu provide an
\uicontrol Exit option, and the \uicontrol Help menu provide information about
the example and about Qt.
\image icons_find_normal.png Screenshot of the Find Files
The screenshot above shows the application with one image file
loaded. The \uicontrol {Guess Image Mode/State} is enabled and the
style is Plastique.
When QIcon is provided with only one available pixmap, that
pixmap is used for all the states and modes. In this case the
pixmap's icon mode is set to normal, and the generated pixmaps
for the normal and active modes will look the same. But in
disabled and selected mode, Qt will generate a slightly different
pixmap.
The next screenshot shows the application with an additional file
loaded, providing QIcon with two available pixmaps. Note that the
new image file's mode is set to disabled. When rendering the \uicontrol
Disabled mode pixmaps, Qt will now use the new image. We can see
the difference: The generated disabled pixmap in the first
screenshot is slightly darker than the pixmap with the originally
set disabled mode in the second screenshot.
\image icons_find_normal_disabled.png Screenshot of the Find Files
When Qt renders the icon's pixmaps it searches through the set of
available pixmaps following a particular algorithm. The algorithm
is documented in QIcon, but we will describe some particular cases
below.
\image icons_monkey_active.png Screenshot of the Find Files
In the screenshot above, we have set \c monkey_on_32x32 to be an
Active/On pixmap and \c monkey_off_64x64 to be Normal/Off. To
render the other six mode/state combinations, QIcon uses the
search algorithm described in the table below:
\table 100%
\header \li{2,1} Requested Pixmap \li {8,1} Preferred Alternatives (mode/state)
\header \li Mode \li State \li 1 \li 2 \li 3 \li 4 \li 5 \li 6 \li 7 \li 8
\row \li{1,2} Normal \li Off \li \b N0 \li A0 \li N1 \li A1 \li D0 \li S0 \li D1 \li S1
\row \li On \li N1 \li \b A1 \li N0 \li A0 \li D1 \li S1 \li D0 \li S0
\row \li{1,2} Active \li Off \li A0 \li \b N0 \li A1 \li N1 \li D0 \li S0 \li D1 \li S1
\row \li On \li \b A1 \li N1 \li A0 \li N0 \li D1 \li S1 \li D0 \li S0
\row \li{1,2} Disabled \li Off \li D0 \li \b {N0'} \li A0' \li D1 \li N1' \li A1' \li S0' \li S1'
\row \li On \li D1 \li N1' \li \b {A1'} \li D0 \li N0' \li A0' \li S1' \li S0'
\row \li{1,2} Selected \li Off \li S0 \li \b {N0''} \li A0'' \li S1 \li N1'' \li A1'' \li D0'' \li D1''
\row \li On \li S1 \li N1'' \li \b {A1''} \li S0 \li N0'' \li A0'' \li D1'' \li D0''
\endtable
In the table, "0" and "1" stand for "Off" and "On", respectively.
Single quotes indicates that QIcon generates a disabled ("grayed
out") version of the pixmap; similarly, double quuote indicate
that QIcon generates a selected ("blued out") version of the
pixmap.
The alternatives used in the screenshot above are shown in bold.
For example, the Disabled/Off pixmap is derived by graying out
the Normal/Off pixmap (\c monkey_off_64x64).
In the next screenshots, we loaded the whole set of monkey
images. By checking or unchecking file names from the image list,
we get different results:
\table
\row
\li \inlineimage icons_monkey.png Screenshot of the Monkey Files
\li \inlineimage icons_monkey_mess.png Screenshot of the Monkey Files
\endtable
For any given mode/state combination, it is possible to specify
several images at different resolutions. When rendering an
icon, QIcon will automatically pick the most suitable image
and scale it down if necessary. (QIcon never scales up images,
because this rarely looks good.)
The screenshots below shows what happens when we provide QIcon
with three images (\c qt_extended_16x16.png, \c qt_extended_32x32.png, \c
qt_extended_48x48.png) and try to render the QIcon at various
resolutions:
\table
\row
\li
\li \inlineimage icons_qt_extended_8x8.png Qt Extended icon at 8 x 8
\li \inlineimage icons_qt_extended_16x16.png Qt Extended icon at 16 x 16
\li \inlineimage icons_qt_extended_17x17.png Qt Extended icon at 17 x 17
\row
\li
\li 8 x 8
\li \b {16 x 16}
\li 17 x 17
\row
\li \inlineimage icons_qt_extended_32x32.png Qt Extended icon at 32 x 32
\li \inlineimage icons_qt_extended_33x33.png Qt Extended icon at 33 x 33
\li \inlineimage icons_qt_extended_48x48.png Qt Extended icon at 48 x 48
\li \inlineimage icons_qt_extended_64x64.png Qt Extended icon at 64 x 64
\row
\li \b {32 x 32}
\li 33 x 33
\li \b {48 x 48}
\li 64 x 64
\endtable
For sizes up to 16 x 16, QIcon uses \c qt_extended_16x16.png and
scales it down if necessary. For sizes between 17 x 17 and 32 x
32, it uses \c qt_extended_32x32.png. For sizes above 32 x 32, it uses
\c qt_extended_48x48.png.
\section1 Line-by-Line Walkthrough
The Icons example consists of four classes:
\list
\li \c MainWindow inherits QMainWindow and is the main application
window.
\li \c IconPreviewArea is a custom widget that displays all
combinations of states and modes for a given icon.
\li \c IconSizeSpinBox is a subclass of QSpinBox that lets the
user enter icon sizes (e.g., "48 x 48").
\li \c ImageDelegate is a subclass of QStyledItemDelegate that
provides comboboxes for letting the user set the mode and state
associated with an image.
\endlist
We will start by reviewing the \c IconPreviewArea class before we
take a look at the \c MainWindow class. Finally, we will review the
\c IconSizeSpinBox and \c ImageDelegate classes.
\section2 IconPreviewArea Class Definition
An \c IconPreviewArea widget consists of a group box containing a grid of
QLabel widgets displaying headers and pixmaps.
\image icons_preview_area.png Screenshot of IconPreviewArea.
\snippet widgets/icons/iconpreviewarea.h 0
The \c IconPreviewArea class inherits QWidget. It displays the
generated pixmaps corresponding to an icon's possible states and
modes at a given size.
\snippet widgets/icons/iconpreviewarea.cpp 42
We would like the table columns to be in the order QIcon::Normal,
QIcon::Active, QIcon::Disabled, QIcon::Selected and the rows in the order
QIcon::Off, QIcon::On, which does not match the enumeration. The above code
provides arrays allowing to map from enumeration value to row/column
(by using QList::indexOf()) and back by using the array index and lists
of the matching strings. Qt's containers can be easily populated by
using C++ 11 initializer lists.
We need two public functions to set the current icon and the
icon's size. In addition the class has three private functions: We
use the \c createHeaderLabel() and \c createPixmapLabel()
functions when constructing the preview area, and we need the \c
updatePixmapLabels() function to update the preview area when
the icon or the icon's size has changed.
The \c NumModes and \c NumStates constants reflect \l{QIcon}'s
number of currently defined modes and states.
\section2 IconPreviewArea Class Implementation
\snippet widgets/icons/iconpreviewarea.cpp 0
In the constructor we create the labels displaying the headers and
the icon's generated pixmaps, and add them to a grid layout.
When creating the header labels, we make sure the enums \c
NumModes and \c NumStates defined in the \c .h file, correspond
with the number of labels that we create. Then if the enums at
some point are changed, the \c Q_ASSERT() macro will alert that this
part of the \c .cpp file needs to be updated as well.
If the application is built in debug mode, the \c Q_ASSERT()
macro will expand to
\code
if (!condition)
qFatal("ASSERT: "condition" in file ...");
\endcode
In release mode, the macro simply disappear. The mode can be set
in the application's \c .pro file. One way to do so is to add an
option to \c qmake when building the application:
\code
qmake "CONFIG += debug" icons.pro
\endcode
or
\code
qmake "CONFIG += release" icons.pro
\endcode
Another approach is to add this line directly to the \c .pro
file.
\snippet widgets/icons/iconpreviewarea.cpp 1
\codeline
\snippet widgets/icons/iconpreviewarea.cpp 2
The public \c setIcon() and \c setSize() functions change the icon
or the icon size, and make sure that the generated pixmaps are
updated.
\snippet widgets/icons/iconpreviewarea.cpp 3
\codeline
\snippet widgets/icons/iconpreviewarea.cpp 4
We use the \c createHeaderLabel() and \c createPixmapLabel()
functions to create the preview area's labels displaying the
headers and the icon's generated pixmaps. Both functions return
the QLabel that is created.
\snippet widgets/icons/iconpreviewarea.cpp 5
We use the private \c updatePixmapLabel() function to update the
generated pixmaps displayed in the preview area.
For each mode, and for each state, we retrieve a pixmap using the
QIcon::pixmap() function, which generates a pixmap corresponding
to the given state, mode and size. We pass the QWindows instance
obtained by calling QWidget::windowHandle() on the top level
widget (QWidget::nativeParentWidget()) in order to retrieve
the pixmap that matches best.
We format a tooltip displaying size, actual size and device pixel
ratio.
\section2 MainWindow Class Definition
The \c MainWindow widget consists of three main elements: an
images group box, an icon size group box and a preview area.
\image icons-example.png Screenshot of the Icons example
\snippet widgets/icons/mainwindow.h 0
The MainWindow class inherits from QMainWindow. We reimplement the
constructor, and declare several private slots:
\list
\li The \c about() slot simply provides information about the example.
\li The \c changeStyle() slot changes the application's GUI style and
adjust the style dependent size options.
\li The \c changeSize() slot changes the size of the preview area's icon.
\li The \c changeIcon() slot updates the set of pixmaps available to the
icon displayed in the preview area.
\li The \c addSampleImages() slot allows the user to load a new image
from the samples provided into the application.
\li The \c addOtherImages() slot allows the user to load a new image from
the directory obtained by calling
QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).
\li The \c screenChanged() updates the display in the \uicontrol{High DPI}
group box to correctly display the parameters of the current screen
the window is located on.
\endlist
In addition we declare several private functions to simplify the
constructor.
\section2 MainWindow Class Implementation
\snippet widgets/icons/mainwindow.cpp 0
In the constructor we first create the main window's central
widget and its child widgets, and put them in a grid layout. Then
we create the menus with their associated entries and actions.
We set the window title and determine the current style for the
application. We also enable the icon size spin box by clicking the
associated radio button, making the current value of the spin box
the icon's initial size.
\snippet widgets/icons/mainwindow.cpp 1
The \c about() slot displays a message box using the static
QMessageBox::about() function. In this example it displays a
simple box with information about the example.
The \c about() function looks for a suitable icon in four
locations: It prefers its parent's icon if that exists. If it
doesn't, the function tries the top-level widget containing
parent, and if that fails, it tries the active window. As a last
resort it uses the QMessageBox's Information icon.
\snippet widgets/icons/mainwindow.cpp 2
In the \c changeStyle() slot we first check the slot's
parameter. If it is false we immediately return, otherwise we find
out which style to change to, i.e. which action that triggered the
slot, using the QObject::sender() function.
This function returns the sender as a QObject pointer. Since we
know that the sender is a QAction object, we can safely cast the
QObject. We could have used a C-style cast or a C++ \c
static_cast(), but as a defensive programming technique we use a
\l qobject_cast(). The advantage is that if the object has the
wrong type, a null pointer is returned. Crashes due to null
pointers are much easier to diagnose than crashes due to unsafe
casts.
\snippet widgets/icons/mainwindow.cpp 3
\snippet widgets/icons/mainwindow.cpp 4
Once we have the action, we extract the style name using
QAction::data(). Then we create a QStyle object using the static
QStyleFactory::create() function.
Although we can assume that the style is supported by the
QStyleFactory: To be on the safe side, we use the \c Q_ASSERT()
macro to check if the created style is valid before we use the
QApplication::setStyle() function to set the application's GUI
style to the new style. QApplication will automatically delete
the style object when a new style is set or when the application
exits.
The predefined icon size options provided in the application are
style dependent, so we need to update the labels in the icon size
group box and in the end call the \c changeSize() slot to update
the icon's size.
\snippet widgets/icons/mainwindow.cpp 5
The \c changeSize() slot sets the size for the preview area's
icon.
It is invoked by the QButtonGroup whose members are radio buttons for
controlling the icon size. In \c createIconSizeGroupBox(), each button is
assigned a QStyle::PixelMetric value as an id, which is passed as a
parameter to the slot.
The special value \c OtherSize indicates that the spin box is
enabled. If it is, we extract the extent of the new size from the
box. If it's not, we query the style for the metric. Then we create
a QSize object based on the extent, and use that object to set the
size of the preview area's icon.
\snippet widgets/icons/mainwindow.cpp 12
The function \c addImages() is called by the slot addSampleImages()
passing the samples directory, or by the slot addOtherImages()
passing the directory obtained by querying
QStandardPaths::standardLocations().
The first thing we do is to show a file dialog to the user.
We initialize it to show the filters returned by
QImageReader::supportedMimeTypes().
For each of the files the file dialog returns, we add a row to the
table widget. The table widget is listing the images the user has
loaded into the application.
\snippet widgets/icons/mainwindow.cpp 13
We retrieve the image name using the QFileInfo::baseName()
function that returns the base name of the file without the path,
and create the first table widget item in the row.
We check if a high resolution version of the image exists (identified by
the suffix \c @2x on the base name) and display that along with the size
in the tooltip.
We add the file's complete name to the item's data. Since an item can
hold several information pieces, we need to assign the file name a role
that will distinguish it from other data. This role can be Qt::UserRole
or any value above it.
We also make sure that the item is not editable by removing the
Qt::ItemIsEditable flag. Table items are editable by default.
\snippet widgets/icons/mainwindow.cpp 15
Then we create the second and third items in the row making the
default mode Normal and the default state Off. But if the \uicontrol
{Guess Image Mode/State} option is checked, and the file name
contains "_act", "_dis", or "_sel", the modes are changed to
Active, Disabled, or Selected. And if the file name contains
"_on", the state is changed to On. The sample files in the
example's \c images subdirectory respect this naming convention.
\snippet widgets/icons/mainwindow.cpp 18
In the end we add the items to the associated row, and use the
QTableWidget::openPersistentEditor() function to create
comboboxes for the mode and state columns of the items.
Due to the connection between the table widget's \l
{QTableWidget::itemChanged()}{itemChanged()} signal and the \c
changeIcon() slot, the new image is automatically converted into a
pixmap and made part of the set of pixmaps available to the icon
in the preview area. So, corresponding to this fact, we need to
make sure that the new image's check box is enabled.
\snippet widgets/icons/mainwindow.cpp 6
The \c changeIcon() slot is called when the user alters the set
of images listed in the QTableWidget, to update the QIcon object
rendered by the \c IconPreviewArea.
We first create a QIcon object, and then we run through the
QTableWidget, which lists the images the user has loaded into the
application.
\snippet widgets/icons/mainwindow.cpp 8
We also extract the image file's name using the
QTableWidgetItem::data() function. This function takes a
Qt::DataItemRole as an argument to retrieve the right data
(remember that an item can hold several pieces of information)
and returns it as a QVariant. Then we use the
QVariant::toString() function to get the file name as a QString.
To create a pixmap from the file, we need to first create an
image and then convert this image into a pixmap using
QPixmap::fromImage(). Once we have the final pixmap, we add it,
with its associated mode and state, to the QIcon's set of
available pixmaps.
\snippet widgets/icons/mainwindow.cpp 11
After running through the entire list of images, we change the
icon of the preview area to the one we just created.
\snippet widgets/icons/mainwindow.cpp 20
In the \c removeAllImages() slot, we simply set the table widget's
row count to zero, automatically removing all the images the user
has loaded into the application. Then we update the set of pixmaps
available to the preview area's icon using the \c changeIcon()
slot.
\image icons_images_groupbox.png Screenshot of the images group box
The \c createImagesGroupBox() function is implemented to simplify
the constructor. The main purpose of the function is to create a
QTableWidget that will keep track of the images the user has
loaded into the application.
\snippet widgets/icons/mainwindow.cpp 21
First we create a group box that will contain the table widget.
Then we create a QTableWidget and customize it to suit our
purposes.
We call QAbstractItemView::setSelectionMode() to prevent the user
from selecting items.
The QAbstractItemView::setItemDelegate() call sets the item
delegate for the table widget. We create a \c ImageDelegate that
we make the item delegate for our view.
The QStyledItemDelegate class can be used to provide an editor for an item view
class that is subclassed from QAbstractItemView. Using a delegate
for this purpose allows the editing mechanism to be customized and
developed independently from the model and view.
In this example we derive \c ImageDelegate from QStyledItemDelegate.
QStyledItemDelegate usually provides line editors, while our subclass
\c ImageDelegate, provides comboboxes for the mode and state
fields.
\snippet widgets/icons/mainwindow.cpp 22
Then we customize the QTableWidget's horizontal header, and hide
the vertical header.
\snippet widgets/icons/mainwindow.cpp 24
At the end, we connect the QTableWidget::itemChanged() signal to
the \c changeIcon() slot to ensure that the preview area is in
sync with the image table.
\image icons_size_groupbox.png Screenshot of the icon size group box
The \c createIconSizeGroupBox() function is called from the
constructor. It creates the widgets controlling the size of the
preview area's icon.
\snippet widgets/icons/mainwindow.cpp 26
First we create a group box that will contain all the widgets;
then we create the radio buttons and the spin box. We add the
radio buttons to an instance of QButtonGroup, using the value
of the QStyle::PixelMetric they represent as an integer id.
\snippet widgets/icons/mainwindow.cpp 40
We introduce an enumeration constant \c OtherSize to represent
a custom size.
The spin box is not a regular QSpinBox but an \c IconSizeSpinBox.
The \c IconSizeSpinBox class inherits QSpinBox and reimplements
two functions: QSpinBox::textFromValue() and
QSpinBox::valueFromText(). The \c IconSizeSpinBox is designed to
handle icon sizes, e.g., "32 x 32", instead of plain integer
values.
\snippet widgets/icons/mainwindow.cpp 27
Then we connect all of the radio buttons
\l{QRadioButton::toggled()}{toggled()} signals and the spin box's
\l {QSpinBox::valueChanged()}{valueChanged()} signal to the \c
changeSize() slot to make sure that the size of the preview
area's icon is updated whenever the user changes the icon size.
In the end we put the widgets in a layout that we install on the
group box.
\snippet widgets/icons/mainwindow.cpp 28
In the \c createActions() function we create and customize all the
actions needed to implement the functionality associated with the
menu entries in the application.
In particular we create the \c styleActionGroup based on the
currently available GUI styles using
QStyleFactory. QStyleFactory::keys() returns a list of valid keys,
typically including "windows" and "fusion". Depending on the platform,
"windowsvista" and "macos" may be available.
We create one action for each key, and adds the action to the
action group. Also, for each action, we call QAction::setData()
with the style name. We will retrieve it later using
QAction::data().
As we go along, we create the \uicontrol File, \uicontrol View and
\uicontrol Help menus and add the actions to them.
The QMenu class provides a menu widget for use in menu bars,
context menus, and other popup menus. We put each menu in the
application's menu bar, which we retrieve using
QMainWindow::menuBar().
\snippet widgets/icons/mainwindow.cpp 30
QWidgets have a \l{QWidget::contextMenuPolicy}{contextMenuPolicy}
property that controls how the widget should behave when the user
requests a context menu (e.g., by right-clicking). We set the
QTableWidget's context menu policy to Qt::ActionsContextMenu,
meaning that the \l{QAction}s associated with the widget should
appear in its context menu.
Then we add the \uicontrol{Add Image} and \uicontrol{Remove All Images}
actions to the table widget. They will then appear in the table
widget's context menu.
\snippet widgets/icons/mainwindow.cpp 31
In the \c checkCurrentStyle() function we go through the group of
style actions, looking for the current GUI style.
For each action, we first extract the style name using
QAction::data(). Since this is only a QStyleFactory key (e.g.,
"macos"), we cannot compare it directly to the current
style's class name. We need to create a QStyle object using the
static QStyleFactory::create() function and compare the class
name of the created QStyle object with that of the current style.
As soon as we are done with a QStyle candidate, we delete it.
For all QObject subclasses that use the \c Q_OBJECT macro, the
class name of an object is available through its
\l{QObject::metaObject()}{meta-object}.
We can assume that the style is supported by
QStyleFactory, but to be on the safe side we use the \c
Q_ASSERT() macro to make sure that QStyleFactory::create()
returned a valid pointer.
\snippet widgets/icons/mainwindow.cpp 44
We overload the show() function to set up the updating of the
current screen in \c screenChanged(). After calling QWidget::show(),
the QWindow associated with the QWidget is created and we can
connect to its QWindow::screenChanged() signal.
\section2 IconSizeSpinBox Class Definition
\snippet widgets/icons/iconsizespinbox.h 0
The \c IconSizeSpinBox class is a subclass of QSpinBox. A plain
QSpinBox can only handle integers. But since we want to display
the spin box's values in a more sophisticated way, we need to
subclass QSpinBox and reimplement the QSpinBox::textFromValue()
and QSpinBox::valueFromText() functions.
\image icons_size_spinbox.png Screenshot of the icon size spinbox
\section2 IconSizeSpinBox Class Implementation
\snippet widgets/icons/iconsizespinbox.cpp 0
The constructor is trivial.
\snippet widgets/icons/iconsizespinbox.cpp 2
QSpinBox::textFromValue() is used by the spin box whenever it
needs to display a value. The default implementation returns a
base 10 representation of the \c value parameter.
Our reimplementation returns a QString of the form "32 x 32".
\snippet widgets/icons/iconsizespinbox.cpp 1
The QSpinBox::valueFromText() function is used by the spin box
whenever it needs to interpret text typed in by the user. Since
we reimplement the \c textFromValue() function we also need to
reimplement the \c valueFromText() function to interpret the
parameter text and return the associated int value.
We parse the text using a regular expression (a QRegularExpression). We
define an expression that matches one or several digits,
optionally followed by whitespace, an "x" or the times symbol,
whitespace and one or several digits again.
The first digits of the regular expression are captured using
parentheses. This enables us to use the QRegularExpressionMatch::captured()
or QRegularExpressionMatch::capturedTexts() functions to extract the matched
characters. If the first and second numbers of the spin box value
differ (e.g., "16 x 24"), we use the first number.
When the user presses \uicontrol Enter, QSpinBox first calls
QSpinBox::valueFromText() to interpret the text typed by the
user, then QSpinBox::textFromValue() to present it in a canonical
format (e.g., "16 x 16").
\section2 ImageDelegate Class Definition
\snippet widgets/icons/imagedelegate.h 0
The \c ImageDelegate class is a subclass of QStyledItemDelegate. The
QStyledItemDelegate class provides display and editing facilities for
data items from a model. A single QStyledItemDelegate object is
responsible for all items displayed in a item view (in our case,
a QTableWidget).
A QStyledItemDelegate can be used to provide an editor for an item view
class that is subclassed from QAbstractItemView. Using a delegate
for this purpose allows the editing mechanism to be customized and
developed independently from the model and view.
\snippet widgets/icons/imagedelegate.h 1
The default implementation of QStyledItemDelegate creates a QLineEdit.
Since we want the editor to be a QComboBox, we need to subclass
QStyledItemDelegate and reimplement the QStyledItemDelegate::createEditor(),
QStyledItemDelegate::setEditorData() and QStyledItemDelegate::setModelData()
functions.
\snippet widgets/icons/imagedelegate.h 2
The \c emitCommitData() slot is used to emit the
QImageDelegate::commitData() signal with the appropriate
argument.
\section2 ImageDelegate Class Implementation
\snippet widgets/icons/imagedelegate.cpp 0
The constructor is trivial.
\snippet widgets/icons/imagedelegate.cpp 1
The default QStyledItemDelegate::createEditor() implementation returns
the widget used to edit the item specified by the model and item
index for editing. The parent widget and style option are used to
control the appearance of the editor widget.
Our reimplementation creates and populates a combobox instead of
the default line edit. The contents of the combobox depends on
the column in the table for which the editor is requested. Column
1 contains the QIcon modes, whereas column 2 contains the QIcon
states.
In addition, we connect the combobox's \l
{QComboBox::activated()}{activated()} signal to the \c
emitCommitData() slot to emit the
QAbstractItemDelegate::commitData() signal whenever the user
chooses an item using the combobox. This ensures that the rest of
the application notices the change and updates itself.
\snippet widgets/icons/imagedelegate.cpp 2
The QStyledItemDelegate::setEditorData() function is used by
QTableWidget to transfer data from a QTableWidgetItem to the
editor. The data is stored as a string; we use
QComboBox::findText() to locate it in the combobox.
Delegates work in terms of models, not items. This makes it
possible to use them with any item view class (e.g., QListView,
QListWidget, QTreeView, etc.). The transition between model and
items is done implicitly by QTableWidget; we don't need to worry
about it.
\snippet widgets/icons/imagedelegate.cpp 3
The QStyledItemDelegate::setEditorData() function is used by QTableWidget
to transfer data back from the editor to the \l{QTableWidgetItem}.
\snippet widgets/icons/imagedelegate.cpp 4
The \c emitCommitData() slot simply emit the
QAbstractItemDelegate::commitData() signal for the editor that
triggered the slot. This signal must be emitted when the editor
widget has completed editing the data, and wants to write it back
into the model.
\section2 The Implementation of the Function main()
\snippet widgets/icons/main.cpp 45
We use QCommandLineParser to handle any command line options or parameters
passed to the application. Then, we resize the main window according
to the available screen geometry and show it.
*/

View File

@ -4,6 +4,7 @@
/*!
\example painting/imagecomposition
\title Image Composition Example
\examplecategory {Graphics & Multimedia}
\ingroup examples-painting
\ingroup examples-layout
\brief Shows how composition modes work in QPainter.

View File

@ -1,320 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example widgets/imageviewer
\title Image Viewer Example
\ingroup examples-widgets
\brief The example shows how to combine QLabel and QScrollArea to
display an image.
QLabel is typically used for displaying 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.
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. In
addition the example shows how to use QPainter to print an image.
\borderedimage imageviewer-example.png
\caption Screenshot of the Image Viewer example
With the Image Viewer application, the users can view an image of
their choice. The \uicontrol File menu gives the user the possibility
to:
\list
\li \uicontrol{Open...} - Open an image file
\li \uicontrol{Print...} - Print an image
\li \uicontrol{Exit} - Exit the application
\endlist
Once an image is loaded, the \uicontrol View menu allows the users to:
\list
\li \uicontrol{Zoom In} - Scale the image up by 25%
\li \uicontrol{Zoom Out} - Scale the image down by 25%
\li \uicontrol{Normal Size} - Show the image at its original size
\li \uicontrol{Fit to Window} - Stretch the image to occupy the entire window
\endlist
In addition the \uicontrol Help menu provides the users with information
about the Image Viewer example in particular, and about Qt in
general.
\section1 ImageViewer Class Definition
\snippet widgets/imageviewer/imageviewer.h 0
The \c ImageViewer class inherits from QMainWindow. We reimplement
the constructor, and create several private slots to facilitate
the menu entries. In addition we create four private functions.
We use \c createActions() and \c createMenus() when constructing
the \c ImageViewer widget. We use the \c updateActions() function
to update the menu entries when a new image is loaded, or when
the \uicontrol {Fit to Window} option is toggled. The zoom slots use \c
scaleImage() to perform the zooming. In turn, \c
scaleImage() uses \c adjustScrollBar() to preserve the focal point after
scaling an image.
\section1 ImageViewer Class Implementation
\snippet widgets/imageviewer/imageviewer.cpp 0
In the constructor we first create the label and the scroll area.
We set \c {imageLabel}'s size policy to \l
{QSizePolicy::Ignored}{ignored}, making the users able to scale
the image to whatever size they want when the \uicontrol {Fit to Window}
option is turned on. Otherwise, the default size polizy (\l
{QSizePolicy::Preferred}{preferred}) will make scroll bars appear
when the scroll area becomes smaller than the label's minimum size
hint.
We ensure that the label will scale its contents to fill all
available space, to enable the image to scale properly when
zooming. If we omitted to set the \c {imageLabel}'s \l
{QLabel::scaledContents}{scaledContents} property, zooming in
would enlarge the QLabel, but leave the pixmap at
its original size, exposing the QLabel's background.
We make \c imageLabel the scroll area's child widget, and we make
\c scrollArea the central widget of the QMainWindow. At the end
we create the associated actions and menus, and customize the \c
{ImageViewer}'s appearance.
\snippet widgets/imageviewer/imageviewer.cpp 1
In the \c open() slot, we show a file dialog to the user. We compile
a list of mime types for use as a filter by querying QImageReader
for the available mime type names.
We show the file dialog until a valid file name is entered or
the user cancels.
The function \c loadFile() is used to load the image.
\snippet widgets/imageviewer/imageviewer.cpp 2
In the \c loadFile() function, we instantiate a QImageReader
and enable automatic transformations by calling
QImageReader::setAutoTransform(). For files in JPEG format,
this ensures that portrait mode images of digital cameras are shown
correctly by applying the appropriate orientation read from the
EXIF meta data stored in the image file.
We then load the image using QImageReader::read(). If this returns
a null image, indicating that the file is not an image file,
we use a QMessageBox to alert the user.
The QMessageBox class provides a modal dialog with a short
message, an icon, and some buttons. As with QFileDialog the
easiest way to create a QMessageBox is to use its static
convenience functions. QMessageBox provides a range of different
messages arranged along two axes: severity (question,
information, warning and critical) and complexity (the number of
necessary response buttons). In this particular example an
information message with an \uicontrol OK button (the default) is
sufficient, since the message is part of a normal operation.
\snippet widgets/imageviewer/imageviewer.cpp 4
If the format is supported, we display the image in \c imageLabel
by setting the label's \l {QLabel::pixmap}{pixmap}. Then we enable
the \uicontrol Print and \uicontrol {Fit to Window} menu entries and update
the rest of the view menu entries. The \uicontrol Open and \uicontrol Exit
entries are enabled by default.
If the \uicontrol {Fit to Window} option is turned off, the
QScrollArea::widgetResizable property is \c false and it is
our responsibility (not QScrollArea's) to give the QLabel a
reasonable size based on its contents. We call
\{QWidget::adjustSize()}{adjustSize()} to achieve this, which is
essentially the same as
\code
imageLabel->resize(imageLabel->pixmap()->size());
\endcode
In the \c print() slot, we first make sure that an image has been
loaded into the application:
\snippet widgets/imageviewer/imageviewer.cpp 5
\snippet widgets/imageviewer/imageviewer.cpp 6
If the application is built in debug mode, the \c Q_ASSERT() macro
will expand to
\code
if (imageLabel->pixmap().isNull())
qFatal("ASSERT: "imageLabel->pixmap().isNull()" in file ...");
\endcode
In release mode, the macro simply disappear. The mode can be set
in the application's \c .pro file. One way to do so is to add an
option to \uicontrol qmake when building the application:
\code
qmake "CONFIG += debug" foo.pro
\endcode
or
\code
qmake "CONFIG += release" foo.pro
\endcode
Another approach is to add this line directly to the \c .pro
file.
\snippet widgets/imageviewer/imageviewer.cpp 7
\snippet widgets/imageviewer/imageviewer.cpp 8
Then we present a print dialog allowing the user to choose a
printer and to set a few options. We construct a painter with a
QPrinter as the paint device. We set the painter's window
and viewport in such a way that the image is as large as possible
on the paper, but without altering its
\l{Qt::KeepAspectRatio}{aspect ratio}.
In the end we draw the pixmap at position (0, 0).
\snippet widgets/imageviewer/imageviewer.cpp 9
\snippet widgets/imageviewer/imageviewer.cpp 10
We implement the zooming slots using the private \c scaleImage()
function. We set the scaling factors to 1.25 and 0.8,
respectively. These factor values ensure that a \uicontrol {Zoom In}
action and a \uicontrol {Zoom Out} action will cancel each other (since
1.25 * 0.8 == 1), and in that way the normal image size can be
restored using the zooming features.
The screenshots below show an image in its normal size, and the
same image after zooming in:
\table
\row
\li \inlineimage imageviewer-original_size.png
\li \inlineimage imageviewer-zoom_in_1.png
\li \inlineimage imageviewer-zoom_in_2.png
\endtable
\snippet widgets/imageviewer/imageviewer.cpp 11
\snippet widgets/imageviewer/imageviewer.cpp 12
When zooming, we use the QLabel's ability to scale its contents.
Such scaling doesn't change the actual size hint of the contents.
And since the \l {QLabel::adjustSize()}{adjustSize()} function
use those size hint, the only thing we need to do to restore the
normal size of the currently displayed image is to call \c
adjustSize() and reset the scale factor to 1.0.
\snippet widgets/imageviewer/imageviewer.cpp 13
\snippet widgets/imageviewer/imageviewer.cpp 14
The \c fitToWindow() slot is called each time the user toggled
the \uicontrol {Fit to Window} option. If the slot is called to turn on
the option, we tell the scroll area to resize its child widget
with the QScrollArea::setWidgetResizable() function. Then we
disable the \uicontrol {Zoom In}, \uicontrol {Zoom Out} and \uicontrol {Normal
Size} menu entries using the private \c updateActions() function.
If the \l {QScrollArea::widgetResizable} property is set to \c
false (the default), the scroll area honors the size of its child
widget. If this property is set to \c true, the scroll area will
automatically resize the widget in order to avoid scroll bars
where they can be avoided, or to take advantage of extra space.
But the scroll area will honor the minimum size hint of its child
widget independent of the widget resizable property. So in this
example we set \c {imageLabel}'s size policy to \l
{QSizePolicy::Ignored}{ignored} in the constructor, to avoid that
scroll bars appear when the scroll area becomes smaller than the
label's minimum size hint.
The screenshots below shows an image in its normal size, and the
same image with the \uicontrol {Fit to window} option turned on.
Enlarging the window will stretch the image further, as shown in
the third screenshot.
\table
\row
\li \inlineimage imageviewer-original_size.png
\li \inlineimage imageviewer-fit_to_window_1.png
\li \inlineimage imageviewer-fit_to_window_2.png
\endtable
If the slot is called to turn off the option, the
{QScrollArea::setWidgetResizable} property is set to \c false. We
also restore the image pixmap to its normal size by adjusting the
label's size to its content. And in the end we update the view
menu entries.
\snippet widgets/imageviewer/imageviewer.cpp 15
\snippet widgets/imageviewer/imageviewer.cpp 16
We implement the \c about() slot to create a message box
describing what the example is designed to show.
\snippet widgets/imageviewer/imageviewer.cpp 17
\snippet widgets/imageviewer/imageviewer.cpp 18
In the private \c createAction() function, we create the
actions providing the application features and populate
a menu with them.
We assign a short-cut key to each action and connect them to the
appropriate slots. We only enable the \c openAct and \c exitAct at
the time of creation, the others are updated once an image has
been loaded into the application. In addition we make the \c
fitToWindowAct \l {QAction::checkable}{checkable}.
The QMenu class provides a menu widget for use in menu bars,
context menus, and other popup menus. The QMenuBar class provides
a horizontal menu bar that consists of a list of pull-down menu
items. So we put the menus in the \c {ImageViewer}'s
menu bar which we retrieve with the QMainWindow::menuBar()
function.
\snippet widgets/imageviewer/imageviewer.cpp 21
\snippet widgets/imageviewer/imageviewer.cpp 22
The private \c updateActions() function enables or disables the
\uicontrol {Zoom In}, \uicontrol {Zoom Out} and \uicontrol {Normal Size} menu
entries depending on whether the \uicontrol {Fit to Window} option is
turned on or off.
\snippet widgets/imageviewer/imageviewer.cpp 23
\snippet widgets/imageviewer/imageviewer.cpp 24
In \c scaleImage(), we use the \c factor parameter to calculate
the new scaling factor for the displayed image, and resize \c
imageLabel. Since we set the
\l{QLabel::scaledContents}{scaledContents} property to \c true in
the constructor, the call to QWidget::resize() will scale the
image displayed in the label. We also adjust the scroll bars to
preserve the focal point of the image.
At the end, if the scale factor is less than 33.3% or greater
than 300%, we disable the respective menu entry to prevent the
image pixmap from becoming too large, consuming too much
resources in the window system.
\snippet widgets/imageviewer/imageviewer.cpp 25
\snippet widgets/imageviewer/imageviewer.cpp 26
Whenever we zoom in or out, we need to adjust the scroll bars in
consequence. It would have been tempting to simply call
\code
scrollBar->setValue(int(factor * scrollBar->value()));
\endcode
but this would make the top-left corner the focal point, not the
center. Therefore we need to take into account the scroll bar
handle's size (the \l{QScrollBar::pageStep}{page step}).
*/

View File

@ -1,15 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example itemviews/interview
\title Interview
\ingroup examples-itemviews
\brief This example demonstrates the usage of the model/view framework.
\brief The Interview example explores the flexibility and scalability of the
model/view framework by presenting an infinitely deep data structure using a model
and three different types of view.
\image interview-demo.png
*/

Some files were not shown because too many files have changed in this diff Show More