qt 6.5.1 original

This commit is contained in:
kleuter
2023-10-29 23:33:08 +01:00
parent 71d22ab6b0
commit 85d238dfda
21202 changed files with 5499099 additions and 0 deletions

View File

@ -0,0 +1,8 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_example(application)
qt_internal_add_example(dockwidgets)
qt_internal_add_example(mainwindow)
qt_internal_add_example(mdi)
qt_internal_add_example(menus)

View File

@ -0,0 +1,9 @@
All the standard features of application main windows are provided by Qt.
Main windows can have pull down menus, tool bars, and dock windows. These
separate forms of user input are unified in an integrated action system that
also supports keyboard shortcuts and accelerator keys in menu items.
Documentation for these examples can be found via the Examples
link in the main Qt documentation.

View File

@ -0,0 +1,54 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(application LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/mainwindows/application")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(application
main.cpp
mainwindow.cpp mainwindow.h
)
set_target_properties(application PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(application PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(application_resource_files
"images/copy.png"
"images/cut.png"
"images/new.png"
"images/open.png"
"images/paste.png"
"images/save.png"
)
qt_add_resources(application "application"
PREFIX
"/"
FILES
${application_resource_files}
)
install(TARGETS application
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,13 @@
QT += widgets
requires(qtConfig(filedialog))
HEADERS = mainwindow.h
SOURCES = main.cpp \
mainwindow.cpp
#! [0]
RESOURCES = application.qrc
#! [0]
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mainwindows/application
INSTALLS += target

View File

@ -0,0 +1,10 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/copy.png</file>
<file>images/cut.png</file>
<file>images/new.png</file>
<file>images/open.png</file>
<file>images/paste.png</file>
<file>images/save.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,32 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
#include <QApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(application);
QApplication app(argc, argv);
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationName("Application Example");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::applicationName());
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument("file", "The file to open.");
parser.process(app);
MainWindow mainWin;
if (!parser.positionalArguments().isEmpty())
mainWin.loadFile(parser.positionalArguments().first());
mainWin.show();
return app.exec();
}
//! [0]

View File

@ -0,0 +1,370 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
#include <QtWidgets>
#include "mainwindow.h"
//! [0]
//! [1]
MainWindow::MainWindow()
: textEdit(new QPlainTextEdit)
//! [1] //! [2]
{
setCentralWidget(textEdit);
createActions();
createStatusBar();
readSettings();
connect(textEdit->document(), &QTextDocument::contentsChanged,
this, &MainWindow::documentWasModified);
#ifndef QT_NO_SESSIONMANAGER
connect(qApp, &QGuiApplication::commitDataRequest,
this, &MainWindow::commitData);
#endif
setCurrentFile(QString());
setUnifiedTitleAndToolBarOnMac(true);
}
//! [2]
//! [3]
void MainWindow::closeEvent(QCloseEvent *event)
//! [3] //! [4]
{
if (maybeSave()) {
writeSettings();
event->accept();
} else {
event->ignore();
}
}
//! [4]
//! [5]
void MainWindow::newFile()
//! [5] //! [6]
{
if (maybeSave()) {
textEdit->clear();
setCurrentFile(QString());
}
}
//! [6]
//! [7]
void MainWindow::open()
//! [7] //! [8]
{
if (maybeSave()) {
QString fileName = QFileDialog::getOpenFileName(this);
if (!fileName.isEmpty())
loadFile(fileName);
}
}
//! [8]
//! [9]
bool MainWindow::save()
//! [9] //! [10]
{
if (curFile.isEmpty()) {
return saveAs();
} else {
return saveFile(curFile);
}
}
//! [10]
//! [11]
bool MainWindow::saveAs()
//! [11] //! [12]
{
QFileDialog dialog(this);
dialog.setWindowModality(Qt::WindowModal);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() != QDialog::Accepted)
return false;
return saveFile(dialog.selectedFiles().first());
}
//! [12]
//! [13]
void MainWindow::about()
//! [13] //! [14]
{
QMessageBox::about(this, tr("About Application"),
tr("The <b>Application</b> example demonstrates how to "
"write modern GUI applications using Qt, with a menu bar, "
"toolbars, and a status bar."));
}
//! [14]
//! [15]
void MainWindow::documentWasModified()
//! [15] //! [16]
{
setWindowModified(textEdit->document()->isModified());
}
//! [16]
//! [17]
void MainWindow::createActions()
//! [17] //! [18]
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QToolBar *fileToolBar = addToolBar(tr("File"));
const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(":/images/new.png"));
QAction *newAct = new QAction(newIcon, tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, &QAction::triggered, this, &MainWindow::newFile);
fileMenu->addAction(newAct);
fileToolBar->addAction(newAct);
//! [19]
const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(":/images/open.png"));
QAction *openAct = new QAction(openIcon, tr("&Open..."), this);
openAct->setShortcuts(QKeySequence::Open);
openAct->setStatusTip(tr("Open an existing file"));
connect(openAct, &QAction::triggered, this, &MainWindow::open);
fileMenu->addAction(openAct);
fileToolBar->addAction(openAct);
//! [18] //! [19]
const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(":/images/save.png"));
QAction *saveAct = new QAction(saveIcon, tr("&Save"), this);
saveAct->setShortcuts(QKeySequence::Save);
saveAct->setStatusTip(tr("Save the document to disk"));
connect(saveAct, &QAction::triggered, this, &MainWindow::save);
fileMenu->addAction(saveAct);
fileToolBar->addAction(saveAct);
const QIcon saveAsIcon = QIcon::fromTheme("document-save-as");
QAction *saveAsAct = fileMenu->addAction(saveAsIcon, tr("Save &As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
saveAsAct->setStatusTip(tr("Save the document under a new name"));
//! [20]
fileMenu->addSeparator();
const QIcon exitIcon = QIcon::fromTheme("application-exit");
QAction *exitAct = fileMenu->addAction(exitIcon, tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
//! [20]
exitAct->setStatusTip(tr("Exit the application"));
//! [21]
QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
QToolBar *editToolBar = addToolBar(tr("Edit"));
//!
#ifndef QT_NO_CLIPBOARD
const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(":/images/cut.png"));
QAction *cutAct = new QAction(cutIcon, tr("Cu&t"), this);
//! [21]
cutAct->setShortcuts(QKeySequence::Cut);
cutAct->setStatusTip(tr("Cut the current selection's contents to the "
"clipboard"));
connect(cutAct, &QAction::triggered, textEdit, &QPlainTextEdit::cut);
editMenu->addAction(cutAct);
editToolBar->addAction(cutAct);
const QIcon copyIcon = QIcon::fromTheme("edit-copy", QIcon(":/images/copy.png"));
QAction *copyAct = new QAction(copyIcon, tr("&Copy"), this);
copyAct->setShortcuts(QKeySequence::Copy);
copyAct->setStatusTip(tr("Copy the current selection's contents to the "
"clipboard"));
connect(copyAct, &QAction::triggered, textEdit, &QPlainTextEdit::copy);
editMenu->addAction(copyAct);
editToolBar->addAction(copyAct);
const QIcon pasteIcon = QIcon::fromTheme("edit-paste", QIcon(":/images/paste.png"));
QAction *pasteAct = new QAction(pasteIcon, tr("&Paste"), this);
pasteAct->setShortcuts(QKeySequence::Paste);
pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
"selection"));
connect(pasteAct, &QAction::triggered, textEdit, &QPlainTextEdit::paste);
editMenu->addAction(pasteAct);
editToolBar->addAction(pasteAct);
menuBar()->addSeparator();
#endif // !QT_NO_CLIPBOARD
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about);
aboutAct->setStatusTip(tr("Show the application's About box"));
//! [22]
QAction *aboutQtAct = helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
//! [22]
//! [23]
#ifndef QT_NO_CLIPBOARD
cutAct->setEnabled(false);
//! [23] //! [24]
copyAct->setEnabled(false);
connect(textEdit, &QPlainTextEdit::copyAvailable, cutAct, &QAction::setEnabled);
connect(textEdit, &QPlainTextEdit::copyAvailable, copyAct, &QAction::setEnabled);
#endif // !QT_NO_CLIPBOARD
}
//! [24]
//! [32]
void MainWindow::createStatusBar()
//! [32] //! [33]
{
statusBar()->showMessage(tr("Ready"));
}
//! [33]
//! [34] //! [35]
void MainWindow::readSettings()
//! [34] //! [36]
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
if (geometry.isEmpty()) {
const QRect availableGeometry = screen()->availableGeometry();
resize(availableGeometry.width() / 3, availableGeometry.height() / 2);
move((availableGeometry.width() - width()) / 2,
(availableGeometry.height() - height()) / 2);
} else {
restoreGeometry(geometry);
}
}
//! [35] //! [36]
//! [37] //! [38]
void MainWindow::writeSettings()
//! [37] //! [39]
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
settings.setValue("geometry", saveGeometry());
}
//! [38] //! [39]
//! [40]
bool MainWindow::maybeSave()
//! [40] //! [41]
{
if (!textEdit->document()->isModified())
return true;
const QMessageBox::StandardButton ret
= QMessageBox::warning(this, tr("Application"),
tr("The document has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
switch (ret) {
case QMessageBox::Save:
return save();
case QMessageBox::Cancel:
return false;
default:
break;
}
return true;
}
//! [41]
//! [42]
void MainWindow::loadFile(const QString &fileName)
//! [42] //! [43]
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("Application"),
tr("Cannot read file %1:\n%2.")
.arg(QDir::toNativeSeparators(fileName), file.errorString()));
return;
}
QTextStream in(&file);
#ifndef QT_NO_CURSOR
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
#endif
textEdit->setPlainText(in.readAll());
#ifndef QT_NO_CURSOR
QGuiApplication::restoreOverrideCursor();
#endif
setCurrentFile(fileName);
statusBar()->showMessage(tr("File loaded"), 2000);
}
//! [43]
//! [44]
bool MainWindow::saveFile(const QString &fileName)
//! [44] //! [45]
{
QString errorMessage;
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
QSaveFile file(fileName);
if (file.open(QFile::WriteOnly | QFile::Text)) {
QTextStream out(&file);
out << textEdit->toPlainText();
if (!file.commit()) {
errorMessage = tr("Cannot write file %1:\n%2.")
.arg(QDir::toNativeSeparators(fileName), file.errorString());
}
} else {
errorMessage = tr("Cannot open file %1 for writing:\n%2.")
.arg(QDir::toNativeSeparators(fileName), file.errorString());
}
QGuiApplication::restoreOverrideCursor();
if (!errorMessage.isEmpty()) {
QMessageBox::warning(this, tr("Application"), errorMessage);
return false;
}
setCurrentFile(fileName);
statusBar()->showMessage(tr("File saved"), 2000);
return true;
}
//! [45]
//! [46]
void MainWindow::setCurrentFile(const QString &fileName)
//! [46] //! [47]
{
curFile = fileName;
textEdit->document()->setModified(false);
setWindowModified(false);
QString shownName = curFile;
if (curFile.isEmpty())
shownName = "untitled.txt";
setWindowFilePath(shownName);
}
//! [47]
//! [48]
QString MainWindow::strippedName(const QString &fullFileName)
//! [48] //! [49]
{
return QFileInfo(fullFileName).fileName();
}
//! [49]
#ifndef QT_NO_SESSIONMANAGER
void MainWindow::commitData(QSessionManager &manager)
{
if (manager.allowsInteraction()) {
if (!maybeSave())
manager.cancel();
} else {
// Non-interactive: save without asking
if (textEdit->document()->isModified())
save();
}
}
#endif

View File

@ -0,0 +1,55 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
class QAction;
class QMenu;
class QPlainTextEdit;
class QSessionManager;
QT_END_NAMESPACE
//! [0]
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
void loadFile(const QString &fileName);
protected:
void closeEvent(QCloseEvent *event) override;
private slots:
void newFile();
void open();
bool save();
bool saveAs();
void about();
void documentWasModified();
#ifndef QT_NO_SESSIONMANAGER
void commitData(QSessionManager &);
#endif
private:
void createActions();
void createStatusBar();
void readSettings();
void writeSettings();
bool maybeSave();
bool saveFile(const QString &fileName);
void setCurrentFile(const QString &fileName);
QString strippedName(const QString &fullFileName);
QPlainTextEdit *textEdit;
QString curFile;
};
//! [0]
#endif

View File

@ -0,0 +1,59 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(dockwidgets LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/mainwindows/dockwidgets")
find_package(Qt6
REQUIRED COMPONENTS Core Gui Widgets
OPTIONAL_COMPONENTS PrintSupport
)
qt_standard_project_setup()
qt_add_executable(dockwidgets
main.cpp
mainwindow.cpp mainwindow.h
)
set_target_properties(dockwidgets PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(dockwidgets PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
if (TARGET Qt6::PrintSupport)
target_link_libraries(dockwidgets PRIVATE Qt6::PrintSupport)
endif()
# Resources:
set(dockwidgets_resource_files
"images/new.png"
"images/print.png"
"images/save.png"
"images/undo.png"
)
qt_add_resources(dockwidgets "dockwidgets"
PREFIX
"/"
FILES
${dockwidgets_resource_files}
)
install(TARGETS dockwidgets
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,12 @@
QT += widgets
requires(qtConfig(listwidget))
qtHaveModule(printsupport): QT += printsupport
HEADERS = mainwindow.h
SOURCES = main.cpp \
mainwindow.cpp
RESOURCES = dockwidgets.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mainwindows/dockwidgets
INSTALLS += target

View File

@ -0,0 +1,8 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/new.png</file>
<file>images/print.png</file>
<file>images/save.png</file>
<file>images/undo.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 977 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

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

View File

@ -0,0 +1,298 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
#include <QtWidgets>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printdialog)
#include <QtPrintSupport>
#endif
#endif
#include "mainwindow.h"
//! [0]
//! [1]
MainWindow::MainWindow()
: textEdit(new QTextEdit)
{
setCentralWidget(textEdit);
createActions();
createStatusBar();
createDockWindows();
setWindowTitle(tr("Dock Widgets"));
newLetter();
setUnifiedTitleAndToolBarOnMac(true);
}
//! [1]
//! [2]
void MainWindow::newLetter()
{
textEdit->clear();
QTextCursor cursor(textEdit->textCursor());
cursor.movePosition(QTextCursor::Start);
QTextFrame *topFrame = cursor.currentFrame();
QTextFrameFormat topFrameFormat = topFrame->frameFormat();
topFrameFormat.setPadding(16);
topFrame->setFrameFormat(topFrameFormat);
QTextCharFormat textFormat;
QTextCharFormat boldFormat;
boldFormat.setFontWeight(QFont::Bold);
QTextCharFormat italicFormat;
italicFormat.setFontItalic(true);
QTextTableFormat tableFormat;
tableFormat.setBorder(1);
tableFormat.setCellPadding(16);
tableFormat.setAlignment(Qt::AlignRight);
cursor.insertTable(1, 1, tableFormat);
cursor.insertText("The Firm", boldFormat);
cursor.insertBlock();
cursor.insertText("321 City Street", textFormat);
cursor.insertBlock();
cursor.insertText("Industry Park");
cursor.insertBlock();
cursor.insertText("Some Country");
cursor.setPosition(topFrame->lastPosition());
cursor.insertText(QDate::currentDate().toString("d MMMM yyyy"), textFormat);
cursor.insertBlock();
cursor.insertBlock();
cursor.insertText("Dear ", textFormat);
cursor.insertText("NAME", italicFormat);
cursor.insertText(",", textFormat);
for (int i = 0; i < 3; ++i)
cursor.insertBlock();
cursor.insertText(tr("Yours sincerely,"), textFormat);
for (int i = 0; i < 3; ++i)
cursor.insertBlock();
cursor.insertText("The Boss", textFormat);
cursor.insertBlock();
cursor.insertText("ADDRESS", italicFormat);
}
//! [2]
//! [3]
void MainWindow::print()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
QTextDocument *document = textEdit->document();
QPrinter printer;
QPrintDialog dlg(&printer, this);
if (dlg.exec() != QDialog::Accepted) {
return;
}
document->print(&printer);
statusBar()->showMessage(tr("Ready"), 2000);
#endif
}
//! [3]
//! [4]
void MainWindow::save()
{
QMimeDatabase mimeDatabase;
QString fileName = QFileDialog::getSaveFileName(this,
tr("Choose a file name"), ".",
mimeDatabase.mimeTypeForName("text/html").filterString());
if (fileName.isEmpty())
return;
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("Dock Widgets"),
tr("Cannot write file %1:\n%2.")
.arg(QDir::toNativeSeparators(fileName), file.errorString()));
return;
}
QTextStream out(&file);
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
out << textEdit->toHtml();
QGuiApplication::restoreOverrideCursor();
statusBar()->showMessage(tr("Saved '%1'").arg(fileName), 2000);
}
//! [4]
//! [5]
void MainWindow::undo()
{
QTextDocument *document = textEdit->document();
document->undo();
}
//! [5]
//! [6]
void MainWindow::insertCustomer(const QString &customer)
{
if (customer.isEmpty())
return;
QStringList customerList = customer.split(", ");
QTextDocument *document = textEdit->document();
QTextCursor cursor = document->find("NAME");
if (!cursor.isNull()) {
cursor.beginEditBlock();
cursor.insertText(customerList.at(0));
QTextCursor oldcursor = cursor;
cursor = document->find("ADDRESS");
if (!cursor.isNull()) {
for (int i = 1; i < customerList.size(); ++i) {
cursor.insertBlock();
cursor.insertText(customerList.at(i));
}
cursor.endEditBlock();
}
else
oldcursor.endEditBlock();
}
}
//! [6]
//! [7]
void MainWindow::addParagraph(const QString &paragraph)
{
if (paragraph.isEmpty())
return;
QTextDocument *document = textEdit->document();
QTextCursor cursor = document->find(tr("Yours sincerely,"));
if (cursor.isNull())
return;
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::MoveAnchor, 2);
cursor.insertBlock();
cursor.insertText(paragraph);
cursor.insertBlock();
cursor.endEditBlock();
}
//! [7]
void MainWindow::about()
{
QMessageBox::about(this, tr("About Dock Widgets"),
tr("The <b>Dock Widgets</b> example demonstrates how to "
"use Qt's dock widgets. You can enter your own text, "
"click a customer to add a customer name and "
"address, and click standard paragraphs to add them."));
}
void MainWindow::createActions()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QToolBar *fileToolBar = addToolBar(tr("File"));
const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(":/images/new.png"));
QAction *newLetterAct = new QAction(newIcon, tr("&New Letter"), this);
newLetterAct->setShortcuts(QKeySequence::New);
newLetterAct->setStatusTip(tr("Create a new form letter"));
connect(newLetterAct, &QAction::triggered, this, &MainWindow::newLetter);
fileMenu->addAction(newLetterAct);
fileToolBar->addAction(newLetterAct);
const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(":/images/save.png"));
QAction *saveAct = new QAction(saveIcon, tr("&Save..."), this);
saveAct->setShortcuts(QKeySequence::Save);
saveAct->setStatusTip(tr("Save the current form letter"));
connect(saveAct, &QAction::triggered, this, &MainWindow::save);
fileMenu->addAction(saveAct);
fileToolBar->addAction(saveAct);
const QIcon printIcon = QIcon::fromTheme("document-print", QIcon(":/images/print.png"));
QAction *printAct = new QAction(printIcon, tr("&Print..."), this);
printAct->setShortcuts(QKeySequence::Print);
printAct->setStatusTip(tr("Print the current form letter"));
connect(printAct, &QAction::triggered, this, &MainWindow::print);
fileMenu->addAction(printAct);
fileToolBar->addAction(printAct);
fileMenu->addSeparator();
QAction *quitAct = fileMenu->addAction(tr("&Quit"), qApp, &QCoreApplication::quit);
quitAct->setShortcuts(QKeySequence::Quit);
quitAct->setStatusTip(tr("Quit the application"));
QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
QToolBar *editToolBar = addToolBar(tr("Edit"));
const QIcon undoIcon = QIcon::fromTheme("edit-undo", QIcon(":/images/undo.png"));
QAction *undoAct = new QAction(undoIcon, tr("&Undo"), this);
undoAct->setShortcuts(QKeySequence::Undo);
undoAct->setStatusTip(tr("Undo the last editing action"));
connect(undoAct, &QAction::triggered, this, &MainWindow::undo);
editMenu->addAction(undoAct);
editToolBar->addAction(undoAct);
viewMenu = menuBar()->addMenu(tr("&View"));
menuBar()->addSeparator();
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about);
aboutAct->setStatusTip(tr("Show the application's About box"));
QAction *aboutQtAct = helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
}
//! [8]
void MainWindow::createStatusBar()
{
statusBar()->showMessage(tr("Ready"));
}
//! [8]
//! [9]
void MainWindow::createDockWindows()
{
QDockWidget *dock = new QDockWidget(tr("Customers"), this);
dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
customerList = new QListWidget(dock);
customerList->addItems(QStringList()
<< "John Doe, Harmony Enterprises, 12 Lakeside, Ambleton"
<< "Jane Doe, Memorabilia, 23 Watersedge, Beaton"
<< "Tammy Shea, Tiblanka, 38 Sea Views, Carlton"
<< "Tim Sheen, Caraba Gifts, 48 Ocean Way, Deal"
<< "Sol Harvey, Chicos Coffee, 53 New Springs, Eccleston"
<< "Sally Hobart, Tiroli Tea, 67 Long River, Fedula");
dock->setWidget(customerList);
addDockWidget(Qt::RightDockWidgetArea, dock);
viewMenu->addAction(dock->toggleViewAction());
dock = new QDockWidget(tr("Paragraphs"), this);
paragraphsList = new QListWidget(dock);
paragraphsList->addItems(QStringList()
<< "Thank you for your payment which we have received today."
<< "Your order has been dispatched and should be with you "
"within 28 days."
<< "We have dispatched those items that were in stock. The "
"rest of your order will be dispatched once all the "
"remaining items have arrived at our warehouse. No "
"additional shipping charges will be made."
<< "You made a small overpayment (less than $5) which we "
"will keep on account for you, or return at your request."
<< "You made a small underpayment (less than $1), but we have "
"sent your order anyway. We'll add this underpayment to "
"your next bill."
<< "Unfortunately you did not send enough money. Please remit "
"an additional $. Your order will be dispatched as soon as "
"the complete amount has been received."
<< "You made an overpayment (more than $5). Do you wish to "
"buy more items, or should we return the excess to you?");
dock->setWidget(paragraphsList);
addDockWidget(Qt::RightDockWidgetArea, dock);
viewMenu->addAction(dock->toggleViewAction());
connect(customerList, &QListWidget::currentTextChanged,
this, &MainWindow::insertCustomer);
connect(paragraphsList, &QListWidget::currentTextChanged,
this, &MainWindow::addParagraph);
}
//! [9]

View File

@ -0,0 +1,46 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
class QAction;
class QListWidget;
class QMenu;
class QTextEdit;
QT_END_NAMESPACE
//! [0]
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
private slots:
void newLetter();
void save();
void print();
void undo();
void about();
void insertCustomer(const QString &customer);
void addParagraph(const QString &paragraph);
private:
void createActions();
void createStatusBar();
void createDockWindows();
QTextEdit *textEdit;
QListWidget *customerList;
QListWidget *paragraphsList;
QMenu *viewMenu;
};
//! [0]
#endif

View File

@ -0,0 +1,54 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(mainwindow LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/mainwindows/mainwindow")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(mainwindow
colorswatch.cpp colorswatch.h
main.cpp
mainwindow.cpp mainwindow.h
toolbar.cpp toolbar.h
)
set_target_properties(mainwindow PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(mainwindow PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(mainwindow_resource_files
"qt.png"
"titlebarCenter.png"
"titlebarLeft.png"
"titlebarRight.png"
)
qt_add_resources(mainwindow "mainwindow"
PREFIX
"/res"
FILES
${mainwindow_resource_files}
)
install(TARGETS mainwindow
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,685 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "colorswatch.h"
#include <QActionGroup>
#include <QtEvents>
#include <QFrame>
#include <QMainWindow>
#include <QMenu>
#include <QPainter>
#include <QImage>
#include <QColor>
#include <QDialog>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QSignalBlocker>
#include <QSpinBox>
#include <QLabel>
#include <QPainterPath>
#include <QPushButton>
#include <QHBoxLayout>
#include <QBitmap>
#include <QtDebug>
#undef DEBUG_SIZEHINTS
QColor bgColorForName(const QString &name)
{
if (name == "Black")
return QColor("#D8D8D8");
if (name == "White")
return QColor("#F1F1F1");
if (name == "Red")
return QColor("#F1D8D8");
if (name == "Green")
return QColor("#D8E4D8");
if (name == "Blue")
return QColor("#D8D8F1");
if (name == "Yellow")
return QColor("#F1F0D8");
return QColor(name).lighter(110);
}
QColor fgColorForName(const QString &name)
{
if (name == "Black")
return QColor("#6C6C6C");
if (name == "White")
return QColor("#F8F8F8");
if (name == "Red")
return QColor("#F86C6C");
if (name == "Green")
return QColor("#6CB26C");
if (name == "Blue")
return QColor("#6C6CF8");
if (name == "Yellow")
return QColor("#F8F76C");
return QColor(name);
}
class ColorDock : public QFrame
{
Q_OBJECT
public:
explicit ColorDock(const QString &c, QWidget *parent);
QSize sizeHint() const override { return szHint; }
QSize minimumSizeHint() const override { return minSzHint; }
void setCustomSizeHint(const QSize &size);
public slots:
void changeSizeHints();
protected:
void paintEvent(QPaintEvent *) override;
private:
const QString color;
QSize szHint;
QSize minSzHint;
};
ColorDock::ColorDock(const QString &c, QWidget *parent)
: QFrame(parent)
, color(c)
, szHint(-1, -1)
, minSzHint(125, 75)
{
QFont font = this->font();
font.setPointSize(8);
setFont(font);
}
void ColorDock::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
p.fillRect(rect(), bgColorForName(color));
p.save();
extern void render_qt_text(QPainter *, int, int, const QColor &);
render_qt_text(&p, width(), height(), fgColorForName(color));
p.restore();
#ifdef DEBUG_SIZEHINTS
p.setRenderHint(QPainter::Antialiasing, false);
QSize sz = size();
QSize szHint = sizeHint();
QSize minSzHint = minimumSizeHint();
QSize maxSz = maximumSize();
QString text = QString::fromLatin1("sz: %1x%2\nszHint: %3x%4\nminSzHint: %5x%6\n"
"maxSz: %8x%9")
.arg(sz.width()).arg(sz.height())
.arg(szHint.width()).arg(szHint.height())
.arg(minSzHint.width()).arg(minSzHint.height())
.arg(maxSz.width()).arg(maxSz.height());
QRect r = fontMetrics().boundingRect(rect(), Qt::AlignLeft|Qt::AlignTop, text);
r.adjust(-2, -2, 1, 1);
p.translate(4, 4);
QColor bg = Qt::yellow;
bg.setAlpha(120);
p.setBrush(bg);
p.setPen(Qt::black);
p.drawRect(r);
p.drawText(rect(), Qt::AlignLeft|Qt::AlignTop, text);
#endif // DEBUG_SIZEHINTS
}
static QSpinBox *createSpinBox(int value, QWidget *parent, int max = 1000)
{
QSpinBox *result = new QSpinBox(parent);
result->setMinimum(-1);
result->setMaximum(max);
result->setValue(value);
return result;
}
void ColorDock::changeSizeHints()
{
QDialog dialog(this);
dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
dialog.setWindowTitle(color);
QVBoxLayout *topLayout = new QVBoxLayout(&dialog);
QGridLayout *inputLayout = new QGridLayout();
topLayout->addLayout(inputLayout);
inputLayout->addWidget(new QLabel(tr("Size Hint:"), &dialog), 0, 0);
inputLayout->addWidget(new QLabel(tr("Min Size Hint:"), &dialog), 1, 0);
inputLayout->addWidget(new QLabel(tr("Max Size:"), &dialog), 2, 0);
inputLayout->addWidget(new QLabel(tr("Dock Widget Max Size:"), &dialog), 3, 0);
QSpinBox *szHintW = createSpinBox(szHint.width(), &dialog);
inputLayout->addWidget(szHintW, 0, 1);
QSpinBox *szHintH = createSpinBox(szHint.height(), &dialog);
inputLayout->addWidget(szHintH, 0, 2);
QSpinBox *minSzHintW = createSpinBox(minSzHint.width(), &dialog);
inputLayout->addWidget(minSzHintW, 1, 1);
QSpinBox *minSzHintH = createSpinBox(minSzHint.height(), &dialog);
inputLayout->addWidget(minSzHintH, 1, 2);
QSize maxSz = maximumSize();
QSpinBox *maxSzW = createSpinBox(maxSz.width(), &dialog, QWIDGETSIZE_MAX);
inputLayout->addWidget(maxSzW, 2, 1);
QSpinBox *maxSzH = createSpinBox(maxSz.height(), &dialog, QWIDGETSIZE_MAX);
inputLayout->addWidget(maxSzH, 2, 2);
QSize dwMaxSz = parentWidget()->maximumSize();
QSpinBox *dwMaxSzW = createSpinBox(dwMaxSz.width(), &dialog, QWIDGETSIZE_MAX);
inputLayout->addWidget(dwMaxSzW, 3, 1);
QSpinBox *dwMaxSzH = createSpinBox(dwMaxSz.height(), &dialog, QWIDGETSIZE_MAX);
inputLayout->addWidget(dwMaxSzH, 3, 2);
inputLayout->setColumnStretch(1, 1);
inputLayout->setColumnStretch(2, 1);
topLayout->addStretch();
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
topLayout->addWidget(buttonBox);
if (dialog.exec() != QDialog::Accepted)
return;
szHint = QSize(szHintW->value(), szHintH->value());
minSzHint = QSize(minSzHintW->value(), minSzHintH->value());
maxSz = QSize(maxSzW->value(), maxSzH->value());
setMaximumSize(maxSz);
dwMaxSz = QSize(dwMaxSzW->value(), dwMaxSzH->value());
parentWidget()->setMaximumSize(dwMaxSz);
updateGeometry();
update();
}
void ColorDock::setCustomSizeHint(const QSize &size)
{
if (szHint != size) {
szHint = size;
updateGeometry();
}
}
ColorSwatch::ColorSwatch(const QString &colorName, QMainWindow *parent, Qt::WindowFlags flags)
: QDockWidget(parent, flags), mainWindow(parent)
{
setObjectName(colorName + QLatin1String(" Dock Widget"));
setWindowTitle(objectName() + QLatin1String(" [*]"));
ColorDock *swatch = new ColorDock(colorName, this);
swatch->setFrameStyle(QFrame::Box | QFrame::Sunken);
setWidget(swatch);
closableAction = new QAction(tr("Closable"), this);
closableAction->setCheckable(true);
connect(closableAction, &QAction::triggered, this, &ColorSwatch::changeClosable);
movableAction = new QAction(tr("Movable"), this);
movableAction->setCheckable(true);
connect(movableAction, &QAction::triggered, this, &ColorSwatch::changeMovable);
floatableAction = new QAction(tr("Floatable"), this);
floatableAction->setCheckable(true);
connect(floatableAction, &QAction::triggered, this, &ColorSwatch::changeFloatable);
verticalTitleBarAction = new QAction(tr("Vertical title bar"), this);
verticalTitleBarAction->setCheckable(true);
connect(verticalTitleBarAction, &QAction::triggered,
this, &ColorSwatch::changeVerticalTitleBar);
floatingAction = new QAction(tr("Floating"), this);
floatingAction->setCheckable(true);
connect(floatingAction, &QAction::triggered, this, &ColorSwatch::changeFloating);
allowedAreasActions = new QActionGroup(this);
allowedAreasActions->setExclusive(false);
allowLeftAction = new QAction(tr("Allow on Left"), this);
allowLeftAction->setCheckable(true);
connect(allowLeftAction, &QAction::triggered, this, &ColorSwatch::allowLeft);
allowRightAction = new QAction(tr("Allow on Right"), this);
allowRightAction->setCheckable(true);
connect(allowRightAction, &QAction::triggered, this, &ColorSwatch::allowRight);
allowTopAction = new QAction(tr("Allow on Top"), this);
allowTopAction->setCheckable(true);
connect(allowTopAction, &QAction::triggered, this, &ColorSwatch::allowTop);
allowBottomAction = new QAction(tr("Allow on Bottom"), this);
allowBottomAction->setCheckable(true);
connect(allowBottomAction, &QAction::triggered, this, &ColorSwatch::allowBottom);
allowedAreasActions->addAction(allowLeftAction);
allowedAreasActions->addAction(allowRightAction);
allowedAreasActions->addAction(allowTopAction);
allowedAreasActions->addAction(allowBottomAction);
areaActions = new QActionGroup(this);
areaActions->setExclusive(true);
leftAction = new QAction(tr("Place on Left") , this);
leftAction->setCheckable(true);
connect(leftAction, &QAction::triggered, this, &ColorSwatch::placeLeft);
rightAction = new QAction(tr("Place on Right") , this);
rightAction->setCheckable(true);
connect(rightAction, &QAction::triggered, this, &ColorSwatch::placeRight);
topAction = new QAction(tr("Place on Top") , this);
topAction->setCheckable(true);
connect(topAction, &QAction::triggered, this, &ColorSwatch::placeTop);
bottomAction = new QAction(tr("Place on Bottom") , this);
bottomAction->setCheckable(true);
connect(bottomAction, &QAction::triggered, this, &ColorSwatch::placeBottom);
areaActions->addAction(leftAction);
areaActions->addAction(rightAction);
areaActions->addAction(topAction);
areaActions->addAction(bottomAction);
connect(movableAction, &QAction::triggered, areaActions, &QActionGroup::setEnabled);
connect(movableAction, &QAction::triggered, allowedAreasActions, &QActionGroup::setEnabled);
connect(floatableAction, &QAction::triggered, floatingAction, &QAction::setEnabled);
connect(floatingAction, &QAction::triggered, floatableAction, &QAction::setDisabled);
connect(movableAction, &QAction::triggered, floatableAction, &QAction::setEnabled);
tabMenu = new QMenu(this);
tabMenu->setTitle(tr("Tab into"));
connect(tabMenu, &QMenu::triggered, this, &ColorSwatch::tabInto);
splitHMenu = new QMenu(this);
splitHMenu->setTitle(tr("Split horizontally into"));
connect(splitHMenu, &QMenu::triggered, this, &ColorSwatch::splitInto);
splitVMenu = new QMenu(this);
splitVMenu->setTitle(tr("Split vertically into"));
connect(splitVMenu, &QMenu::triggered, this, &ColorSwatch::splitInto);
QAction *windowModifiedAction = new QAction(tr("Modified"), this);
windowModifiedAction->setCheckable(true);
windowModifiedAction->setChecked(false);
connect(windowModifiedAction, &QAction::toggled, this, &QWidget::setWindowModified);
menu = new QMenu(colorName, this);
menu->addAction(toggleViewAction());
menu->addAction(tr("Raise"), this, &QWidget::raise);
menu->addAction(tr("Change Size Hints..."), swatch, &ColorDock::changeSizeHints);
menu->addSeparator();
menu->addAction(closableAction);
menu->addAction(movableAction);
menu->addAction(floatableAction);
menu->addAction(floatingAction);
menu->addAction(verticalTitleBarAction);
menu->addSeparator();
menu->addActions(allowedAreasActions->actions());
menu->addSeparator();
menu->addActions(areaActions->actions());
menu->addSeparator();
menu->addMenu(splitHMenu);
menu->addMenu(splitVMenu);
menu->addMenu(tabMenu);
menu->addSeparator();
menu->addAction(windowModifiedAction);
connect(menu, &QMenu::aboutToShow, this, &ColorSwatch::updateContextMenu);
if (colorName == QLatin1String("Black")) {
leftAction->setShortcut(Qt::CTRL | Qt::Key_W);
rightAction->setShortcut(Qt::CTRL | Qt::Key_E);
toggleViewAction()->setShortcut(Qt::CTRL | Qt::Key_R);
}
}
void ColorSwatch::updateContextMenu()
{
const Qt::DockWidgetArea area = mainWindow->dockWidgetArea(this);
const Qt::DockWidgetAreas areas = allowedAreas();
closableAction->setChecked(features() & QDockWidget::DockWidgetClosable);
if (windowType() == Qt::Drawer) {
floatableAction->setEnabled(false);
floatingAction->setEnabled(false);
movableAction->setEnabled(false);
verticalTitleBarAction->setChecked(false);
} else {
floatableAction->setChecked(features() & QDockWidget::DockWidgetFloatable);
floatingAction->setChecked(isWindow());
// done after floating, to get 'floatable' correctly initialized
movableAction->setChecked(features() & QDockWidget::DockWidgetMovable);
verticalTitleBarAction
->setChecked(features() & QDockWidget::DockWidgetVerticalTitleBar);
}
allowLeftAction->setChecked(isAreaAllowed(Qt::LeftDockWidgetArea));
allowRightAction->setChecked(isAreaAllowed(Qt::RightDockWidgetArea));
allowTopAction->setChecked(isAreaAllowed(Qt::TopDockWidgetArea));
allowBottomAction->setChecked(isAreaAllowed(Qt::BottomDockWidgetArea));
if (allowedAreasActions->isEnabled()) {
allowLeftAction->setEnabled(area != Qt::LeftDockWidgetArea);
allowRightAction->setEnabled(area != Qt::RightDockWidgetArea);
allowTopAction->setEnabled(area != Qt::TopDockWidgetArea);
allowBottomAction->setEnabled(area != Qt::BottomDockWidgetArea);
}
{
const QSignalBlocker blocker(leftAction);
leftAction->setChecked(area == Qt::LeftDockWidgetArea);
}
{
const QSignalBlocker blocker(rightAction);
rightAction->setChecked(area == Qt::RightDockWidgetArea);
}
{
const QSignalBlocker blocker(topAction);
topAction->setChecked(area == Qt::TopDockWidgetArea);
}
{
const QSignalBlocker blocker(bottomAction);
bottomAction->setChecked(area == Qt::BottomDockWidgetArea);
}
if (areaActions->isEnabled()) {
leftAction->setEnabled(areas & Qt::LeftDockWidgetArea);
rightAction->setEnabled(areas & Qt::RightDockWidgetArea);
topAction->setEnabled(areas & Qt::TopDockWidgetArea);
bottomAction->setEnabled(areas & Qt::BottomDockWidgetArea);
}
tabMenu->clear();
splitHMenu->clear();
splitVMenu->clear();
const QList<ColorSwatch *> dockList = mainWindow->findChildren<ColorSwatch*>();
for (const ColorSwatch *dock : dockList) {
tabMenu->addAction(dock->objectName());
splitHMenu->addAction(dock->objectName());
splitVMenu->addAction(dock->objectName());
}
}
static ColorSwatch *findByName(const QMainWindow *mainWindow, const QString &name)
{
const QList<ColorSwatch *> dockList = mainWindow->findChildren<ColorSwatch*>();
for (ColorSwatch *dock : dockList) {
if (name == dock->objectName())
return dock;
}
return nullptr;
}
void ColorSwatch::splitInto(QAction *action)
{
ColorSwatch *target = findByName(mainWindow, action->text());
if (!target)
return;
const Qt::Orientation o = action->parent() == splitHMenu
? Qt::Horizontal : Qt::Vertical;
mainWindow->splitDockWidget(target, this, o);
}
void ColorSwatch::tabInto(QAction *action)
{
if (ColorSwatch *target = findByName(mainWindow, action->text()))
mainWindow->tabifyDockWidget(target, this);
}
#ifndef QT_NO_CONTEXTMENU
void ColorSwatch::contextMenuEvent(QContextMenuEvent *event)
{
event->accept();
menu->popup(event->globalPos());
}
#endif // QT_NO_CONTEXTMENU
void ColorSwatch::resizeEvent(QResizeEvent *e)
{
if (BlueTitleBar *btb = qobject_cast<BlueTitleBar*>(titleBarWidget()))
btb->updateMask();
QDockWidget::resizeEvent(e);
}
void ColorSwatch::allow(Qt::DockWidgetArea area, bool a)
{
Qt::DockWidgetAreas areas = allowedAreas();
areas = a ? areas | area : areas & ~area;
setAllowedAreas(areas);
if (areaActions->isEnabled()) {
leftAction->setEnabled(areas & Qt::LeftDockWidgetArea);
rightAction->setEnabled(areas & Qt::RightDockWidgetArea);
topAction->setEnabled(areas & Qt::TopDockWidgetArea);
bottomAction->setEnabled(areas & Qt::BottomDockWidgetArea);
}
}
void ColorSwatch::place(Qt::DockWidgetArea area, bool p)
{
if (!p)
return;
mainWindow->addDockWidget(area, this);
if (allowedAreasActions->isEnabled()) {
allowLeftAction->setEnabled(area != Qt::LeftDockWidgetArea);
allowRightAction->setEnabled(area != Qt::RightDockWidgetArea);
allowTopAction->setEnabled(area != Qt::TopDockWidgetArea);
allowBottomAction->setEnabled(area != Qt::BottomDockWidgetArea);
}
}
void ColorSwatch::setCustomSizeHint(const QSize &size)
{
if (ColorDock *dock = qobject_cast<ColorDock*>(widget()))
dock->setCustomSizeHint(size);
}
void ColorSwatch::changeClosable(bool on)
{ setFeatures(on ? features() | DockWidgetClosable : features() & ~DockWidgetClosable); }
void ColorSwatch::changeMovable(bool on)
{ setFeatures(on ? features() | DockWidgetMovable : features() & ~DockWidgetMovable); }
void ColorSwatch::changeFloatable(bool on)
{ setFeatures(on ? features() | DockWidgetFloatable : features() & ~DockWidgetFloatable); }
void ColorSwatch::changeFloating(bool floating)
{ setFloating(floating); }
void ColorSwatch::allowLeft(bool a)
{ allow(Qt::LeftDockWidgetArea, a); }
void ColorSwatch::allowRight(bool a)
{ allow(Qt::RightDockWidgetArea, a); }
void ColorSwatch::allowTop(bool a)
{ allow(Qt::TopDockWidgetArea, a); }
void ColorSwatch::allowBottom(bool a)
{ allow(Qt::BottomDockWidgetArea, a); }
void ColorSwatch::placeLeft(bool p)
{ place(Qt::LeftDockWidgetArea, p); }
void ColorSwatch::placeRight(bool p)
{ place(Qt::RightDockWidgetArea, p); }
void ColorSwatch::placeTop(bool p)
{ place(Qt::TopDockWidgetArea, p); }
void ColorSwatch::placeBottom(bool p)
{ place(Qt::BottomDockWidgetArea, p); }
void ColorSwatch::changeVerticalTitleBar(bool on)
{
setFeatures(on ? features() | DockWidgetVerticalTitleBar
: features() & ~DockWidgetVerticalTitleBar);
}
QSize BlueTitleBar::minimumSizeHint() const
{
QDockWidget *dw = qobject_cast<QDockWidget*>(parentWidget());
Q_ASSERT(dw);
QSize result(leftPm.width() + rightPm.width(), centerPm.height());
if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar)
result.transpose();
return result;
}
BlueTitleBar::BlueTitleBar(QWidget *parent)
: QWidget(parent)
, leftPm(QPixmap(":/res/titlebarLeft.png"))
, centerPm(QPixmap(":/res/titlebarCenter.png"))
, rightPm(QPixmap(":/res/titlebarRight.png"))
{
}
void BlueTitleBar::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QRect rect = this->rect();
QDockWidget *dw = qobject_cast<QDockWidget*>(parentWidget());
Q_ASSERT(dw);
if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) {
QSize s = rect.size();
s.transpose();
rect.setSize(s);
painter.translate(rect.left(), rect.top() + rect.width());
painter.rotate(-90);
painter.translate(-rect.left(), -rect.top());
}
painter.drawPixmap(rect.topLeft(), leftPm);
painter.drawPixmap(rect.topRight() - QPoint(rightPm.width() - 1, 0), rightPm);
QBrush brush(centerPm);
painter.fillRect(rect.left() + leftPm.width(), rect.top(),
rect.width() - leftPm.width() - rightPm.width(),
centerPm.height(), centerPm);
}
void BlueTitleBar::mouseReleaseEvent(QMouseEvent *event)
{
QPoint pos = event->position().toPoint();
QRect rect = this->rect();
QDockWidget *dw = qobject_cast<QDockWidget*>(parentWidget());
Q_ASSERT(dw);
if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) {
QPoint p = pos;
pos.setX(rect.left() + rect.bottom() - p.y());
pos.setY(rect.top() + p.x() - rect.left());
QSize s = rect.size();
s.transpose();
rect.setSize(s);
}
const int buttonRight = 7;
const int buttonWidth = 20;
int right = rect.right() - pos.x();
int button = (right - buttonRight)/buttonWidth;
switch (button) {
case 0:
event->accept();
dw->close();
break;
case 1:
event->accept();
dw->setFloating(!dw->isFloating());
break;
case 2: {
event->accept();
QDockWidget::DockWidgetFeatures features = dw->features();
if (features & QDockWidget::DockWidgetVerticalTitleBar)
features &= ~QDockWidget::DockWidgetVerticalTitleBar;
else
features |= QDockWidget::DockWidgetVerticalTitleBar;
dw->setFeatures(features);
break;
}
default:
event->ignore();
break;
}
}
void BlueTitleBar::updateMask()
{
QDockWidget *dw = qobject_cast<QDockWidget*>(parent());
Q_ASSERT(dw);
QRect rect = dw->rect();
QBitmap bitmap(dw->size());
{
QPainter painter(&bitmap);
// initialize to transparent
painter.fillRect(rect, Qt::color0);
QRect contents = rect;
contents.setTopLeft(geometry().bottomLeft());
contents.setRight(geometry().right());
contents.setBottom(contents.bottom()-y());
painter.fillRect(contents, Qt::color1);
// let's paint the titlebar
QRect titleRect = this->geometry();
if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) {
QSize s = rect.size();
s.transpose();
rect.setSize(s);
QSize s2 = size();
s2.transpose();
titleRect.setSize(s2);
painter.translate(rect.left(), rect.top() + rect.width());
painter.rotate(-90);
painter.translate(-rect.left(), -rect.top());
}
contents.setTopLeft(titleRect.bottomLeft());
contents.setRight(titleRect.right());
contents.setBottom(rect.bottom()-y());
QRect rect = titleRect;
painter.drawPixmap(rect.topLeft(), leftPm.mask());
painter.fillRect(rect.left() + leftPm.width(), rect.top(),
rect.width() - leftPm.width() - rightPm.width(),
centerPm.height(), Qt::color1);
painter.drawPixmap(rect.topRight() - QPoint(rightPm.width() - 1, 0), rightPm.mask());
painter.fillRect(contents, Qt::color1);
}
dw->setMask(bitmap);
}
#include "colorswatch.moc"

View File

@ -0,0 +1,102 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef COLORSWATCH_H
#define COLORSWATCH_H
#include <QDockWidget>
QT_FORWARD_DECLARE_CLASS(QAction)
QT_FORWARD_DECLARE_CLASS(QActionGroup)
QT_FORWARD_DECLARE_CLASS(QMenu)
class ColorSwatch : public QDockWidget
{
Q_OBJECT
public:
explicit ColorSwatch(const QString &colorName, QMainWindow *parent = nullptr, Qt::WindowFlags flags = { });
void setCustomSizeHint(const QSize &size);
QMenu *colorSwatchMenu() const { return menu; }
protected:
#ifndef QT_NO_CONTEXTMENU
void contextMenuEvent(QContextMenuEvent *event) override;
#endif // QT_NO_CONTEXTMENU
void resizeEvent(QResizeEvent *e) override;
private slots:
void changeClosable(bool on);
void changeMovable(bool on);
void changeFloatable(bool on);
void changeFloating(bool on);
void changeVerticalTitleBar(bool on);
void updateContextMenu();
void allowLeft(bool a);
void allowRight(bool a);
void allowTop(bool a);
void allowBottom(bool a);
void placeLeft(bool p);
void placeRight(bool p);
void placeTop(bool p);
void placeBottom(bool p);
void splitInto(QAction *action);
void tabInto(QAction *action);
private:
void allow(Qt::DockWidgetArea area, bool allow);
void place(Qt::DockWidgetArea area, bool place);
QAction *closableAction;
QAction *movableAction;
QAction *floatableAction;
QAction *floatingAction;
QAction *verticalTitleBarAction;
QActionGroup *allowedAreasActions;
QAction *allowLeftAction;
QAction *allowRightAction;
QAction *allowTopAction;
QAction *allowBottomAction;
QActionGroup *areaActions;
QAction *leftAction;
QAction *rightAction;
QAction *topAction;
QAction *bottomAction;
QMenu *tabMenu;
QMenu *splitHMenu;
QMenu *splitVMenu;
QMenu *menu;
QMainWindow *mainWindow;
};
class BlueTitleBar : public QWidget
{
Q_OBJECT
public:
explicit BlueTitleBar(QWidget *parent = nullptr);
QSize sizeHint() const override { return minimumSizeHint(); }
QSize minimumSizeHint() const override;
protected:
void paintEvent(QPaintEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
public slots:
void updateMask();
private:
const QPixmap leftPm;
const QPixmap centerPm;
const QPixmap rightPm;
};
#endif // COLORSWATCH_H

View File

@ -0,0 +1,147 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
#include <QPainterPath>
#include <QPainter>
#include <QMap>
#include <QDebug>
void render_qt_text(QPainter *painter, int w, int h, const QColor &color)
{
QPainterPath path;
path.moveTo(-0.083695, 0.283849);
path.cubicTo(-0.049581, 0.349613, -0.012720, 0.397969, 0.026886, 0.428917);
path.cubicTo(0.066493, 0.459865, 0.111593, 0.477595, 0.162186, 0.482108);
path.lineTo(0.162186, 0.500000);
path.cubicTo(0.115929, 0.498066, 0.066565, 0.487669, 0.014094, 0.468810);
path.cubicTo(-0.038378, 0.449952, -0.088103, 0.423839, -0.135082, 0.390474);
path.cubicTo(-0.182061, 0.357108, -0.222608, 0.321567, -0.256722, 0.283849);
path.cubicTo(-0.304712, 0.262250, -0.342874, 0.239362, -0.371206, 0.215184);
path.cubicTo(-0.411969, 0.179078, -0.443625, 0.134671, -0.466175, 0.081963);
path.cubicTo(-0.488725, 0.029255, -0.500000, -0.033043, -0.500000, -0.104932);
path.cubicTo(-0.500000, -0.218407, -0.467042, -0.312621, -0.401127, -0.387573);
path.cubicTo(-0.335212, -0.462524, -0.255421, -0.500000, -0.161752, -0.500000);
path.cubicTo(-0.072998, -0.500000, 0.003903, -0.462444, 0.068951, -0.387331);
path.cubicTo(0.133998, -0.312218, 0.166522, -0.217440, 0.166522, -0.102998);
path.cubicTo(0.166522, -0.010155, 0.143394, 0.071325, 0.097138, 0.141441);
path.cubicTo(0.050882, 0.211557, -0.009396, 0.259026, -0.083695, 0.283849);
path.moveTo(-0.167823, -0.456963);
path.cubicTo(-0.228823, -0.456963, -0.277826, -0.432624, -0.314831, -0.383946);
path.cubicTo(-0.361665, -0.323340, -0.385082, -0.230335, -0.385082, -0.104932);
path.cubicTo(-0.385082, 0.017569, -0.361376, 0.112025, -0.313964, 0.178433);
path.cubicTo(-0.277248, 0.229368, -0.228534, 0.254836, -0.167823, 0.254836);
path.cubicTo(-0.105088, 0.254836, -0.054496, 0.229368, -0.016045, 0.178433);
path.cubicTo(0.029055, 0.117827, 0.051605, 0.028691, 0.051605, -0.088975);
path.cubicTo(0.051605, -0.179562, 0.039318, -0.255803, 0.014744, -0.317698);
path.cubicTo(-0.004337, -0.365409, -0.029705, -0.400548, -0.061362, -0.423114);
path.cubicTo(-0.093018, -0.445680, -0.128505, -0.456963, -0.167823, -0.456963);
path.moveTo(0.379011, -0.404739);
path.lineTo(0.379011, -0.236460);
path.lineTo(0.486123, -0.236460);
path.lineTo(0.486123, -0.197292);
path.lineTo(0.379011, -0.197292);
path.lineTo(0.379011, 0.134913);
path.cubicTo(0.379011, 0.168117, 0.383276, 0.190442, 0.391804, 0.201886);
path.cubicTo(0.400332, 0.213330, 0.411246, 0.219052, 0.424545, 0.219052);
path.cubicTo(0.435531, 0.219052, 0.446227, 0.215264, 0.456635, 0.207689);
path.cubicTo(0.467042, 0.200113, 0.474993, 0.188910, 0.480486, 0.174081);
path.lineTo(0.500000, 0.174081);
path.cubicTo(0.488436, 0.210509, 0.471957, 0.237911, 0.450564, 0.256286);
path.cubicTo(0.429170, 0.274662, 0.407054, 0.283849, 0.384215, 0.283849);
path.cubicTo(0.368893, 0.283849, 0.353859, 0.279094, 0.339115, 0.269584);
path.cubicTo(0.324371, 0.260074, 0.313530, 0.246534, 0.306592, 0.228965);
path.cubicTo(0.299653, 0.211396, 0.296184, 0.184075, 0.296184, 0.147002);
path.lineTo(0.296184, -0.197292);
path.lineTo(0.223330, -0.197292);
path.lineTo(0.223330, -0.215667);
path.cubicTo(0.241833, -0.224049, 0.260697, -0.237992, 0.279922, -0.257495);
path.cubicTo(0.299147, -0.276999, 0.316276, -0.300129, 0.331310, -0.326886);
path.cubicTo(0.338826, -0.341070, 0.349523, -0.367021, 0.363400, -0.404739);
path.lineTo(0.379011, -0.404739);
path.moveTo(-0.535993, 0.275629);
painter->translate(w / 2, h / 2);
double scale = qMin(w, h) * 8 / 10.0;
painter->scale(scale, scale);
painter->setRenderHint(QPainter::Antialiasing);
painter->save();
painter->translate(.1, .1);
painter->fillPath(path, QColor(0, 0, 0, 63));
painter->restore();
painter->setBrush(color);
painter->setPen(QPen(Qt::black, 0.02, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin));
painter->drawPath(path);
}
static void usage()
{
qWarning() << "Usage: mainwindow [-SizeHint<color> <width>x<height>] ...";
exit(1);
}
enum ParseCommandLineArgumentsResult {
CommandLineArgumentsOk,
CommandLineArgumentsError,
HelpRequested
};
static ParseCommandLineArgumentsResult
parseCustomSizeHints(const QStringList &arguments, MainWindow::CustomSizeHintMap *result)
{
result->clear();
const auto argumentCount = arguments.size();
for (int i = 1; i < argumentCount; ++i) {
const QString &arg = arguments.at(i);
if (arg.startsWith(QLatin1String("-SizeHint"))) {
const QString name = arg.mid(9);
if (name.isEmpty())
return CommandLineArgumentsError;
if (++i == argumentCount)
return CommandLineArgumentsError;
const QStringView sizeStr{ arguments.at(i) };
const auto idx = sizeStr.indexOf(QLatin1Char('x'));
if (idx == -1)
return CommandLineArgumentsError;
bool ok;
const int w = sizeStr.left(idx).toInt(&ok);
if (!ok)
return CommandLineArgumentsError;
const int h = sizeStr.mid(idx + 1).toInt(&ok);
if (!ok)
return CommandLineArgumentsError;
result->insert(name, QSize(w, h));
} else if (arg == QLatin1String("-h") || arg == QLatin1String("--help")) {
return HelpRequested;
} else {
return CommandLineArgumentsError;
}
}
return CommandLineArgumentsOk;
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MainWindow::CustomSizeHintMap customSizeHints;
switch (parseCustomSizeHints(QCoreApplication::arguments(), &customSizeHints)) {
case CommandLineArgumentsOk:
break;
case CommandLineArgumentsError:
usage();
return -1;
case HelpRequested:
usage();
return 0;
}
MainWindow mainWin(customSizeHints);
mainWin.resize(800, 600);
mainWin.show();
return app.exec();
}

View File

@ -0,0 +1,444 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include "colorswatch.h"
#include "toolbar.h"
#include <QActionGroup>
#include <QLayout>
#include <QMenu>
#include <QMenuBar>
#include <QStatusBar>
#include <QTextEdit>
#include <QFile>
#include <QDataStream>
#include <QFileDialog>
#include <QDialogButtonBox>
#include <QMessageBox>
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
#include <QLineEdit>
#include <QComboBox>
#include <QLabel>
#include <QPushButton>
#include <QTextEdit>
#include <QDebug>
static const char message[] =
"<p><b>Qt Main Window Example</b></p>"
"<p>This is a demonstration of the QMainWindow, QToolBar and "
"QDockWidget classes.</p>"
"<p>The tool bar and dock widgets can be dragged around and rearranged "
"using the mouse or via the menu.</p>"
"<p>Each dock widget contains a colored frame and a context "
"(right-click) menu.</p>"
#ifdef Q_OS_MAC
"<p>On OS X, the \"Black\" dock widget has been created as a "
"<em>Drawer</em>, which is a special kind of QDockWidget.</p>"
#endif
;
Q_DECLARE_METATYPE(QDockWidget::DockWidgetFeatures)
MainWindow::MainWindow(const CustomSizeHintMap &customSizeHints,
QWidget *parent, Qt::WindowFlags flags)
: QMainWindow(parent, flags)
{
Q_UNUSED(message);
setObjectName("MainWindow");
setWindowTitle("Qt Main Window Example");
QTextEdit *center = new QTextEdit(this);
center->setReadOnly(true);
center->setMinimumSize(400, 205);
setCentralWidget(center);
setupToolBar();
setupMenuBar();
setupDockWidgets(customSizeHints);
statusBar()->showMessage(tr("Status Bar"));
}
void MainWindow::actionTriggered(QAction *action)
{
qDebug("action '%s' triggered", action->text().toLocal8Bit().data());
}
void MainWindow::setupToolBar()
{
#ifdef Q_OS_MACOS
setUnifiedTitleAndToolBarOnMac(true);
#endif
for (int i = 0; i < 3; ++i) {
ToolBar *tb = new ToolBar(QString::fromLatin1("Tool Bar %1").arg(i + 1), this);
toolBars.append(tb);
addToolBar(tb);
}
}
void MainWindow::setupMenuBar()
{
QMenu *menu = menuBar()->addMenu(tr("&File"));
menu->addAction(tr("Save layout..."), this, &MainWindow::saveLayout);
menu->addAction(tr("Load layout..."), this, &MainWindow::loadLayout);
menu->addAction(tr("Switch layout direction"),this, &MainWindow::switchLayoutDirection);
menu->addSeparator();
menu->addAction(tr("&Quit"), qApp, &QCoreApplication::quit);
mainWindowMenu = menuBar()->addMenu(tr("Main window"));
QAction *action = mainWindowMenu->addAction(tr("Animated docks"));
action->setCheckable(true);
action->setChecked(dockOptions() & AnimatedDocks);
connect(action, &QAction::toggled, this, &MainWindow::setDockOptions);
action = mainWindowMenu->addAction(tr("Allow nested docks"));
action->setCheckable(true);
action->setChecked(dockOptions() & AllowNestedDocks);
connect(action, &QAction::toggled, this, &MainWindow::setDockOptions);
action = mainWindowMenu->addAction(tr("Allow tabbed docks"));
action->setCheckable(true);
action->setChecked(dockOptions() & AllowTabbedDocks);
connect(action, &QAction::toggled, this, &MainWindow::setDockOptions);
action = mainWindowMenu->addAction(tr("Force tabbed docks"));
action->setCheckable(true);
action->setChecked(dockOptions() & ForceTabbedDocks);
connect(action, &QAction::toggled, this, &MainWindow::setDockOptions);
action = mainWindowMenu->addAction(tr("Vertical tabs"));
action->setCheckable(true);
action->setChecked(dockOptions() & VerticalTabs);
connect(action, &QAction::toggled, this, &MainWindow::setDockOptions);
action = mainWindowMenu->addAction(tr("Grouped dragging"));
action->setCheckable(true);
action->setChecked(dockOptions() & GroupedDragging);
connect(action, &QAction::toggled, this, &MainWindow::setDockOptions);
QMenu *toolBarMenu = menuBar()->addMenu(tr("Tool bars"));
for (int i = 0; i < toolBars.count(); ++i)
toolBarMenu->addMenu(toolBars.at(i)->toolbarMenu());
#ifdef Q_OS_MACOS
toolBarMenu->addSeparator();
action = toolBarMenu->addAction(tr("Unified"));
action->setCheckable(true);
action->setChecked(unifiedTitleAndToolBarOnMac());
connect(action, &QAction::toggled, this, &QMainWindow::setUnifiedTitleAndToolBarOnMac);
#endif
dockWidgetMenu = menuBar()->addMenu(tr("&Dock Widgets"));
QMenu *aboutMenu = menuBar()->addMenu(tr("About"));
QAction *aboutAct = aboutMenu->addAction(tr("&About"), this, &MainWindow::about);
aboutAct->setStatusTip(tr("Show the application's About box"));
QAction *aboutQtAct = aboutMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
}
void MainWindow::setDockOptions()
{
DockOptions opts;
QList<QAction*> actions = mainWindowMenu->actions();
if (actions.at(0)->isChecked())
opts |= AnimatedDocks;
if (actions.at(1)->isChecked())
opts |= AllowNestedDocks;
if (actions.at(2)->isChecked())
opts |= AllowTabbedDocks;
if (actions.at(3)->isChecked())
opts |= ForceTabbedDocks;
if (actions.at(4)->isChecked())
opts |= VerticalTabs;
if (actions.at(5)->isChecked())
opts |= GroupedDragging;
QMainWindow::setDockOptions(opts);
}
void MainWindow::saveLayout()
{
QString fileName
= QFileDialog::getSaveFileName(this, tr("Save layout"));
if (fileName.isEmpty())
return;
QFile file(fileName);
if (!file.open(QFile::WriteOnly)) {
QString msg = tr("Failed to open %1\n%2")
.arg(QDir::toNativeSeparators(fileName), file.errorString());
QMessageBox::warning(this, tr("Error"), msg);
return;
}
QByteArray geo_data = saveGeometry();
QByteArray layout_data = saveState();
bool ok = file.putChar((uchar)geo_data.size());
if (ok)
ok = file.write(geo_data) == geo_data.size();
if (ok)
ok = file.write(layout_data) == layout_data.size();
if (!ok) {
QString msg = tr("Error writing to %1\n%2")
.arg(QDir::toNativeSeparators(fileName), file.errorString());
QMessageBox::warning(this, tr("Error"), msg);
return;
}
}
void MainWindow::loadLayout()
{
QString fileName
= QFileDialog::getOpenFileName(this, tr("Load layout"));
if (fileName.isEmpty())
return;
QFile file(fileName);
if (!file.open(QFile::ReadOnly)) {
QString msg = tr("Failed to open %1\n%2")
.arg(QDir::toNativeSeparators(fileName), file.errorString());
QMessageBox::warning(this, tr("Error"), msg);
return;
}
uchar geo_size;
QByteArray geo_data;
QByteArray layout_data;
bool ok = file.getChar((char*)&geo_size);
if (ok) {
geo_data = file.read(geo_size);
ok = geo_data.size() == geo_size;
}
if (ok) {
layout_data = file.readAll();
ok = layout_data.size() > 0;
}
if (ok)
ok = restoreGeometry(geo_data);
if (ok)
ok = restoreState(layout_data);
if (!ok) {
QString msg = tr("Error reading %1").arg(QDir::toNativeSeparators(fileName));
QMessageBox::warning(this, tr("Error"), msg);
return;
}
}
static QAction *addCornerAction(const QString &text, QMainWindow *mw, QMenu *menu, QActionGroup *group,
Qt::Corner c, Qt::DockWidgetArea a)
{
QAction *result = menu->addAction(text, mw, [=]() { mw->setCorner(c, a); });
result->setCheckable(true);
group->addAction(result);
return result;
}
void MainWindow::setupDockWidgets(const CustomSizeHintMap &customSizeHints)
{
qRegisterMetaType<QDockWidget::DockWidgetFeatures>();
QMenu *cornerMenu = dockWidgetMenu->addMenu(tr("Top left corner"));
QActionGroup *group = new QActionGroup(this);
group->setExclusive(true);
QAction *cornerAction = addCornerAction(tr("Top dock area"), this, cornerMenu, group, Qt::TopLeftCorner, Qt::TopDockWidgetArea);
cornerAction->setChecked(true);
addCornerAction(tr("Left dock area"), this, cornerMenu, group, Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
cornerMenu = dockWidgetMenu->addMenu(tr("Top right corner"));
group = new QActionGroup(this);
group->setExclusive(true);
cornerAction = addCornerAction(tr("Top dock area"), this, cornerMenu, group, Qt::TopRightCorner, Qt::TopDockWidgetArea);
cornerAction->setChecked(true);
addCornerAction(tr("Right dock area"), this, cornerMenu, group, Qt::TopRightCorner, Qt::RightDockWidgetArea);
cornerMenu = dockWidgetMenu->addMenu(tr("Bottom left corner"));
group = new QActionGroup(this);
group->setExclusive(true);
cornerAction = addCornerAction(tr("Bottom dock area"), this, cornerMenu, group, Qt::BottomLeftCorner, Qt::BottomDockWidgetArea);
cornerAction->setChecked(true);
addCornerAction(tr("Left dock area"), this, cornerMenu, group, Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
cornerMenu = dockWidgetMenu->addMenu(tr("Bottom right corner"));
group = new QActionGroup(this);
group->setExclusive(true);
cornerAction = addCornerAction(tr("Bottom dock area"), this, cornerMenu, group, Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
cornerAction->setChecked(true);
addCornerAction(tr("Right dock area"), this, cornerMenu, group, Qt::BottomRightCorner, Qt::RightDockWidgetArea);
dockWidgetMenu->addSeparator();
static const struct Set {
const char * name;
uint flags;
Qt::DockWidgetArea area;
} sets [] = {
#ifndef Q_OS_MAC
{ "Black", 0, Qt::LeftDockWidgetArea },
#else
{ "Black", Qt::Drawer, Qt::LeftDockWidgetArea },
#endif
{ "White", 0, Qt::RightDockWidgetArea },
{ "Red", 0, Qt::TopDockWidgetArea },
{ "Green", 0, Qt::TopDockWidgetArea },
{ "Blue", 0, Qt::BottomDockWidgetArea },
{ "Yellow", 0, Qt::BottomDockWidgetArea }
};
const int setCount = sizeof(sets) / sizeof(Set);
const QIcon qtIcon(QPixmap(":/res/qt.png"));
for (int i = 0; i < setCount; ++i) {
ColorSwatch *swatch = new ColorSwatch(tr(sets[i].name), this, Qt::WindowFlags(sets[i].flags));
if (i % 2)
swatch->setWindowIcon(qtIcon);
if (qstrcmp(sets[i].name, "Blue") == 0) {
BlueTitleBar *titlebar = new BlueTitleBar(swatch);
swatch->setTitleBarWidget(titlebar);
connect(swatch, &QDockWidget::topLevelChanged, titlebar, &BlueTitleBar::updateMask);
connect(swatch, &QDockWidget::featuresChanged, titlebar, &BlueTitleBar::updateMask, Qt::QueuedConnection);
}
QString name = QString::fromLatin1(sets[i].name);
if (customSizeHints.contains(name))
swatch->setCustomSizeHint(customSizeHints.value(name));
addDockWidget(sets[i].area, swatch);
dockWidgetMenu->addMenu(swatch->colorSwatchMenu());
}
destroyDockWidgetMenu = new QMenu(tr("Destroy dock widget"), this);
destroyDockWidgetMenu->setEnabled(false);
connect(destroyDockWidgetMenu, &QMenu::triggered, this, &MainWindow::destroyDockWidget);
dockWidgetMenu->addSeparator();
dockWidgetMenu->addAction(tr("Add dock widget..."), this, &MainWindow::createDockWidget);
dockWidgetMenu->addMenu(destroyDockWidgetMenu);
}
void MainWindow::switchLayoutDirection()
{
if (layoutDirection() == Qt::LeftToRight)
QApplication::setLayoutDirection(Qt::RightToLeft);
else
QApplication::setLayoutDirection(Qt::LeftToRight);
}
class CreateDockWidgetDialog : public QDialog
{
public:
explicit CreateDockWidgetDialog(QWidget *parent = nullptr);
QString enteredObjectName() const { return m_objectName->text(); }
Qt::DockWidgetArea location() const;
private:
QLineEdit *m_objectName;
QComboBox *m_location;
};
CreateDockWidgetDialog::CreateDockWidgetDialog(QWidget *parent)
: QDialog(parent)
, m_objectName(new QLineEdit(this))
, m_location(new QComboBox(this))
{
setWindowTitle(tr("Add Dock Widget"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QGridLayout *layout = new QGridLayout(this);
layout->addWidget(new QLabel(tr("Object name:")), 0, 0);
layout->addWidget(m_objectName, 0, 1);
layout->addWidget(new QLabel(tr("Location:")), 1, 0);
m_location->setEditable(false);
m_location->addItem(tr("Top"));
m_location->addItem(tr("Left"));
m_location->addItem(tr("Right"));
m_location->addItem(tr("Bottom"));
m_location->addItem(tr("Restore"));
layout->addWidget(m_location, 1, 1);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
layout->addWidget(buttonBox, 2, 0, 1, 2);
}
Qt::DockWidgetArea CreateDockWidgetDialog::location() const
{
switch (m_location->currentIndex()) {
case 0: return Qt::TopDockWidgetArea;
case 1: return Qt::LeftDockWidgetArea;
case 2: return Qt::RightDockWidgetArea;
case 3: return Qt::BottomDockWidgetArea;
default:
break;
}
return Qt::NoDockWidgetArea;
}
void MainWindow::createDockWidget()
{
CreateDockWidgetDialog dialog(this);
if (dialog.exec() == QDialog::Rejected)
return;
QDockWidget *dw = new QDockWidget;
const QString name = dialog.enteredObjectName();
dw->setObjectName(name);
dw->setWindowTitle(name);
dw->setWidget(new QTextEdit);
Qt::DockWidgetArea area = dialog.location();
switch (area) {
case Qt::LeftDockWidgetArea:
case Qt::RightDockWidgetArea:
case Qt::TopDockWidgetArea:
case Qt::BottomDockWidgetArea:
addDockWidget(area, dw);
break;
default:
if (!restoreDockWidget(dw)) {
QMessageBox::warning(this, QString(), tr("Failed to restore dock widget"));
delete dw;
return;
}
break;
}
extraDockWidgets.append(dw);
destroyDockWidgetMenu->setEnabled(true);
destroyDockWidgetMenu->addAction(new QAction(name, this));
}
void MainWindow::destroyDockWidget(QAction *action)
{
auto index = destroyDockWidgetMenu->actions().indexOf(action);
delete extraDockWidgets.takeAt(index);
destroyDockWidgetMenu->removeAction(action);
action->deleteLater();
if (destroyDockWidgetMenu->isEmpty())
destroyDockWidgetMenu->setEnabled(false);
}
void MainWindow::about()
{
QMessageBox::about(this, tr("About MainWindows"), message);
}

View File

@ -0,0 +1,50 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMap>
#include <QString>
#include <QSize>
class ToolBar;
QT_FORWARD_DECLARE_CLASS(QMenu)
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
typedef QMap<QString, QSize> CustomSizeHintMap;
explicit MainWindow(const CustomSizeHintMap &customSizeHints,
QWidget *parent = nullptr,
Qt::WindowFlags flags = { });
public slots:
void actionTriggered(QAction *action);
void saveLayout();
void loadLayout();
void switchLayoutDirection();
void setDockOptions();
void createDockWidget();
void destroyDockWidget(QAction *action);
void about();
private:
void setupToolBar();
void setupMenuBar();
void setupDockWidgets(const CustomSizeHintMap &customSizeHints);
QList<ToolBar*> toolBars;
QMenu *dockWidgetMenu;
QMenu *mainWindowMenu;
QList<QDockWidget *> extraDockWidgets;
QMenu *destroyDockWidgetMenu;
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,16 @@
TEMPLATE = app
QT += widgets
requires(qtConfig(combobox))
HEADERS += colorswatch.h mainwindow.h toolbar.h
SOURCES += colorswatch.cpp mainwindow.cpp toolbar.cpp main.cpp
build_all:!build_pass {
CONFIG -= build_all
CONFIG += release
}
RESOURCES += mainwindow.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mainwindows/mainwindow
INSTALLS += target

View File

@ -0,0 +1,8 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/res">
<file>qt.png</file>
<file>titlebarLeft.png</file>
<file>titlebarCenter.png</file>
<file>titlebarRight.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,308 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "toolbar.h"
#include <QRandomGenerator>
#include <QActionGroup>
#include <QMainWindow>
#include <QMenu>
#include <QPainter>
#include <QPainterPath>
#include <QSpinBox>
#include <QLabel>
#include <QToolTip>
#include <stdlib.h>
static QPixmap genIcon(const QSize &iconSize, const QString &, const QColor &color, qreal pixelRatio)
{
int w = qRound(iconSize.width() * pixelRatio);
int h = qRound(iconSize.height() * pixelRatio);
QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
image.fill(0);
QPainter p(&image);
extern void render_qt_text(QPainter *, int, int, const QColor &);
render_qt_text(&p, w, h, color);
QPixmap pm = QPixmap::fromImage(image, Qt::DiffuseDither | Qt::DiffuseAlphaDither);
pm.setDevicePixelRatio(pixelRatio);
return pm;
}
static QPixmap genIcon(const QSize &iconSize, int number, const QColor &color, qreal pixelRatio)
{ return genIcon(iconSize, QString::number(number), color, pixelRatio); }
ToolBar::ToolBar(const QString &title, QMainWindow *mainWindow)
: QToolBar(mainWindow)
, mainWindow(mainWindow)
, spinbox(nullptr)
, spinboxAction(nullptr)
{
setWindowTitle(title);
setObjectName(title);
setIconSize(QSize(32, 32));
qreal dpr = devicePixelRatio();
menu = new QMenu("One", this);
menu->setIcon(genIcon(iconSize(), 1, Qt::black, dpr));
menu->addAction(genIcon(iconSize(), "A", Qt::blue, dpr), "A");
menu->addAction(genIcon(iconSize(), "B", Qt::blue, dpr), "B");
menu->addAction(genIcon(iconSize(), "C", Qt::blue, dpr), "C");
addAction(menu->menuAction());
QAction *two = addAction(genIcon(iconSize(), 2, Qt::white, dpr), "Two");
QFont boldFont;
boldFont.setBold(true);
two->setFont(boldFont);
addAction(genIcon(iconSize(), 3, Qt::red, dpr), "Three");
addAction(genIcon(iconSize(), 4, Qt::green, dpr), "Four");
addAction(genIcon(iconSize(), 5, Qt::blue, dpr), "Five");
addAction(genIcon(iconSize(), 6, Qt::yellow, dpr), "Six");
orderAction = new QAction(this);
orderAction->setText(tr("Order Items in Tool Bar"));
connect(orderAction, &QAction::triggered, this, &ToolBar::order);
randomizeAction = new QAction(this);
randomizeAction->setText(tr("Randomize Items in Tool Bar"));
connect(randomizeAction, &QAction::triggered, this, &ToolBar::randomize);
addSpinBoxAction = new QAction(this);
addSpinBoxAction->setText(tr("Add Spin Box"));
connect(addSpinBoxAction, &QAction::triggered, this, &ToolBar::addSpinBox);
removeSpinBoxAction = new QAction(this);
removeSpinBoxAction->setText(tr("Remove Spin Box"));
removeSpinBoxAction->setEnabled(false);
connect(removeSpinBoxAction, &QAction::triggered, this, &ToolBar::removeSpinBox);
movableAction = new QAction(tr("Movable"), this);
movableAction->setCheckable(true);
connect(movableAction, &QAction::triggered, this, &ToolBar::changeMovable);
allowedAreasActions = new QActionGroup(this);
allowedAreasActions->setExclusive(false);
allowLeftAction = new QAction(tr("Allow on Left"), this);
allowLeftAction->setCheckable(true);
connect(allowLeftAction, &QAction::triggered, this, &ToolBar::allowLeft);
allowRightAction = new QAction(tr("Allow on Right"), this);
allowRightAction->setCheckable(true);
connect(allowRightAction, &QAction::triggered, this, &ToolBar::allowRight);
allowTopAction = new QAction(tr("Allow on Top"), this);
allowTopAction->setCheckable(true);
connect(allowTopAction, &QAction::triggered, this, &ToolBar::allowTop);
allowBottomAction = new QAction(tr("Allow on Bottom"), this);
allowBottomAction->setCheckable(true);
connect(allowBottomAction, &QAction::triggered, this, &ToolBar::allowBottom);
allowedAreasActions->addAction(allowLeftAction);
allowedAreasActions->addAction(allowRightAction);
allowedAreasActions->addAction(allowTopAction);
allowedAreasActions->addAction(allowBottomAction);
areaActions = new QActionGroup(this);
areaActions->setExclusive(true);
leftAction = new QAction(tr("Place on Left") , this);
leftAction->setCheckable(true);
connect(leftAction, &QAction::triggered, this, &ToolBar::placeLeft);
rightAction = new QAction(tr("Place on Right") , this);
rightAction->setCheckable(true);
connect(rightAction, &QAction::triggered, this, &ToolBar::placeRight);
topAction = new QAction(tr("Place on Top") , this);
topAction->setCheckable(true);
connect(topAction, &QAction::triggered, this, &ToolBar::placeTop);
bottomAction = new QAction(tr("Place on Bottom") , this);
bottomAction->setCheckable(true);
connect(bottomAction, &QAction::triggered, this, &ToolBar::placeBottom);
areaActions->addAction(leftAction);
areaActions->addAction(rightAction);
areaActions->addAction(topAction);
areaActions->addAction(bottomAction);
connect(movableAction, &QAction::triggered, areaActions, &QActionGroup::setEnabled);
connect(movableAction, &QAction::triggered, allowedAreasActions, &QActionGroup::setEnabled);
menu = new QMenu(title, this);
menu->addAction(toggleViewAction());
menu->addSeparator();
menu->addAction(orderAction);
menu->addAction(randomizeAction);
menu->addSeparator();
menu->addAction(addSpinBoxAction);
menu->addAction(removeSpinBoxAction);
menu->addSeparator();
menu->addAction(movableAction);
menu->addSeparator();
menu->addActions(allowedAreasActions->actions());
menu->addSeparator();
menu->addActions(areaActions->actions());
menu->addSeparator();
menu->addAction(tr("Insert break"), this, &ToolBar::insertToolBarBreak);
connect(menu, &QMenu::aboutToShow, this, &ToolBar::updateMenu);
randomize();
}
void ToolBar::updateMenu()
{
const Qt::ToolBarArea area = mainWindow->toolBarArea(this);
const Qt::ToolBarAreas areas = allowedAreas();
movableAction->setChecked(isMovable());
allowLeftAction->setChecked(isAreaAllowed(Qt::LeftToolBarArea));
allowRightAction->setChecked(isAreaAllowed(Qt::RightToolBarArea));
allowTopAction->setChecked(isAreaAllowed(Qt::TopToolBarArea));
allowBottomAction->setChecked(isAreaAllowed(Qt::BottomToolBarArea));
if (allowedAreasActions->isEnabled()) {
allowLeftAction->setEnabled(area != Qt::LeftToolBarArea);
allowRightAction->setEnabled(area != Qt::RightToolBarArea);
allowTopAction->setEnabled(area != Qt::TopToolBarArea);
allowBottomAction->setEnabled(area != Qt::BottomToolBarArea);
}
leftAction->setChecked(area == Qt::LeftToolBarArea);
rightAction->setChecked(area == Qt::RightToolBarArea);
topAction->setChecked(area == Qt::TopToolBarArea);
bottomAction->setChecked(area == Qt::BottomToolBarArea);
if (areaActions->isEnabled()) {
leftAction->setEnabled(areas & Qt::LeftToolBarArea);
rightAction->setEnabled(areas & Qt::RightToolBarArea);
topAction->setEnabled(areas & Qt::TopToolBarArea);
bottomAction->setEnabled(areas & Qt::BottomToolBarArea);
}
}
void ToolBar::order()
{
QList<QAction *> ordered;
QList<QAction *> actions1 = actions();
const QList<QAction *> childActions = findChildren<QAction *>();
for (QAction *action : childActions) {
if (!actions1.contains(action))
continue;
actions1.removeAll(action);
ordered.append(action);
}
clear();
addActions(ordered);
orderAction->setEnabled(false);
}
void ToolBar::randomize()
{
QList<QAction *> randomized;
QList<QAction *> actions = this->actions();
while (!actions.isEmpty()) {
QAction *action = actions.takeAt(QRandomGenerator::global()->bounded(actions.size()));
randomized.append(action);
}
clear();
addActions(randomized);
orderAction->setEnabled(true);
}
void ToolBar::addSpinBox()
{
if (!spinbox)
spinbox = new QSpinBox(this);
if (!spinboxAction)
spinboxAction = addWidget(spinbox);
else
addAction(spinboxAction);
addSpinBoxAction->setEnabled(false);
removeSpinBoxAction->setEnabled(true);
}
void ToolBar::removeSpinBox()
{
if (spinboxAction)
removeAction(spinboxAction);
addSpinBoxAction->setEnabled(true);
removeSpinBoxAction->setEnabled(false);
}
void ToolBar::allow(Qt::ToolBarArea area, bool a)
{
Qt::ToolBarAreas areas = allowedAreas();
areas = a ? areas | area : areas & ~area;
setAllowedAreas(areas);
if (areaActions->isEnabled()) {
leftAction->setEnabled(areas & Qt::LeftToolBarArea);
rightAction->setEnabled(areas & Qt::RightToolBarArea);
topAction->setEnabled(areas & Qt::TopToolBarArea);
bottomAction->setEnabled(areas & Qt::BottomToolBarArea);
}
}
void ToolBar::place(Qt::ToolBarArea area, bool p)
{
if (!p)
return;
mainWindow->addToolBar(area, this);
if (allowedAreasActions->isEnabled()) {
allowLeftAction->setEnabled(area != Qt::LeftToolBarArea);
allowRightAction->setEnabled(area != Qt::RightToolBarArea);
allowTopAction->setEnabled(area != Qt::TopToolBarArea);
allowBottomAction->setEnabled(area != Qt::BottomToolBarArea);
}
}
void ToolBar::changeMovable(bool movable)
{ setMovable(movable); }
void ToolBar::allowLeft(bool a)
{ allow(Qt::LeftToolBarArea, a); }
void ToolBar::allowRight(bool a)
{ allow(Qt::RightToolBarArea, a); }
void ToolBar::allowTop(bool a)
{ allow(Qt::TopToolBarArea, a); }
void ToolBar::allowBottom(bool a)
{ allow(Qt::BottomToolBarArea, a); }
void ToolBar::placeLeft(bool p)
{ place(Qt::LeftToolBarArea, p); }
void ToolBar::placeRight(bool p)
{ place(Qt::RightToolBarArea, p); }
void ToolBar::placeTop(bool p)
{ place(Qt::TopToolBarArea, p); }
void ToolBar::placeBottom(bool p)
{ place(Qt::BottomToolBarArea, p); }
void ToolBar::insertToolBarBreak()
{
mainWindow->insertToolBarBreak(this);
}

View File

@ -0,0 +1,74 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef TOOLBAR_H
#define TOOLBAR_H
#include <QToolBar>
QT_FORWARD_DECLARE_CLASS(QAction)
QT_FORWARD_DECLARE_CLASS(QActionGroup)
QT_FORWARD_DECLARE_CLASS(QMenu)
QT_FORWARD_DECLARE_CLASS(QSpinBox)
class ToolBar : public QToolBar
{
Q_OBJECT
public:
explicit ToolBar(const QString &title, QMainWindow *mainWindow);
QMenu *toolbarMenu() const { return menu; }
private slots:
void order();
void randomize();
void addSpinBox();
void removeSpinBox();
void changeMovable(bool movable);
void allowLeft(bool a);
void allowRight(bool a);
void allowTop(bool a);
void allowBottom(bool a);
void placeLeft(bool p);
void placeRight(bool p);
void placeTop(bool p);
void placeBottom(bool p);
void updateMenu();
void insertToolBarBreak();
private:
void allow(Qt::ToolBarArea area, bool allow);
void place(Qt::ToolBarArea area, bool place);
QMainWindow *mainWindow;
QSpinBox *spinbox;
QAction *spinboxAction;
QMenu *menu;
QAction *orderAction;
QAction *randomizeAction;
QAction *addSpinBoxAction;
QAction *removeSpinBoxAction;
QAction *movableAction;
QActionGroup *allowedAreasActions;
QAction *allowLeftAction;
QAction *allowRightAction;
QAction *allowTopAction;
QAction *allowBottomAction;
QActionGroup *areaActions;
QAction *leftAction;
QAction *rightAction;
QAction *topAction;
QAction *bottomAction;
};
#endif // TOOLBAR_H

View File

@ -0,0 +1,6 @@
TEMPLATE = subdirs
SUBDIRS = application \
dockwidgets \
mainwindow \
mdi \
menus

View File

@ -0,0 +1,55 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(mdi LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/mainwindows/mdi")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(mdi
main.cpp
mainwindow.cpp mainwindow.h
mdichild.cpp mdichild.h
)
set_target_properties(mdi PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(mdi PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(mdi_resource_files
"images/copy.png"
"images/cut.png"
"images/new.png"
"images/open.png"
"images/paste.png"
"images/save.png"
)
qt_add_resources(mdi "mdi"
PREFIX
"/"
FILES
${mdi_resource_files}
)
install(TARGETS mdi
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,31 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(mdi);
QApplication app(argc, argv);
QCoreApplication::setApplicationName("MDI Example");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription("Qt MDI Example");
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument("file", "The file to open.");
parser.process(app);
MainWindow mainWin;
const QStringList posArgs = parser.positionalArguments();
for (const QString &fileName : posArgs)
mainWin.openFile(fileName);
mainWin.show();
return app.exec();
}

View File

@ -0,0 +1,461 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "mainwindow.h"
#include "mdichild.h"
MainWindow::MainWindow()
: mdiArea(new QMdiArea)
{
mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setCentralWidget(mdiArea);
connect(mdiArea, &QMdiArea::subWindowActivated,
this, &MainWindow::updateMenus);
createActions();
createStatusBar();
updateMenus();
readSettings();
setWindowTitle(tr("MDI"));
setUnifiedTitleAndToolBarOnMac(true);
}
void MainWindow::closeEvent(QCloseEvent *event)
{
mdiArea->closeAllSubWindows();
if (mdiArea->currentSubWindow()) {
event->ignore();
} else {
writeSettings();
event->accept();
}
}
void MainWindow::newFile()
{
MdiChild *child = createMdiChild();
child->newFile();
child->show();
}
void MainWindow::open()
{
const QString fileName = QFileDialog::getOpenFileName(this);
if (!fileName.isEmpty())
openFile(fileName);
}
bool MainWindow::openFile(const QString &fileName)
{
if (QMdiSubWindow *existing = findMdiChild(fileName)) {
mdiArea->setActiveSubWindow(existing);
return true;
}
const bool succeeded = loadFile(fileName);
if (succeeded)
statusBar()->showMessage(tr("File loaded"), 2000);
return succeeded;
}
bool MainWindow::loadFile(const QString &fileName)
{
MdiChild *child = createMdiChild();
const bool succeeded = child->loadFile(fileName);
if (succeeded)
child->show();
else
child->close();
MainWindow::prependToRecentFiles(fileName);
return succeeded;
}
static inline QString recentFilesKey() { return QStringLiteral("recentFileList"); }
static inline QString fileKey() { return QStringLiteral("file"); }
static QStringList readRecentFiles(QSettings &settings)
{
QStringList result;
const int count = settings.beginReadArray(recentFilesKey());
for (int i = 0; i < count; ++i) {
settings.setArrayIndex(i);
result.append(settings.value(fileKey()).toString());
}
settings.endArray();
return result;
}
static void writeRecentFiles(const QStringList &files, QSettings &settings)
{
const int count = files.size();
settings.beginWriteArray(recentFilesKey());
for (int i = 0; i < count; ++i) {
settings.setArrayIndex(i);
settings.setValue(fileKey(), files.at(i));
}
settings.endArray();
}
bool MainWindow::hasRecentFiles()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const int count = settings.beginReadArray(recentFilesKey());
settings.endArray();
return count > 0;
}
void MainWindow::prependToRecentFiles(const QString &fileName)
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const QStringList oldRecentFiles = readRecentFiles(settings);
QStringList recentFiles = oldRecentFiles;
recentFiles.removeAll(fileName);
recentFiles.prepend(fileName);
if (oldRecentFiles != recentFiles)
writeRecentFiles(recentFiles, settings);
setRecentFilesVisible(!recentFiles.isEmpty());
}
void MainWindow::setRecentFilesVisible(bool visible)
{
recentFileSubMenuAct->setVisible(visible);
recentFileSeparator->setVisible(visible);
}
void MainWindow::updateRecentFileActions()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const QStringList recentFiles = readRecentFiles(settings);
const int count = qMin(int(MaxRecentFiles), recentFiles.size());
int i = 0;
for ( ; i < count; ++i) {
const QString fileName = QFileInfo(recentFiles.at(i)).fileName();
recentFileActs[i]->setText(tr("&%1 %2").arg(i + 1).arg(fileName));
recentFileActs[i]->setData(recentFiles.at(i));
recentFileActs[i]->setVisible(true);
}
for ( ; i < MaxRecentFiles; ++i)
recentFileActs[i]->setVisible(false);
}
void MainWindow::openRecentFile()
{
if (const QAction *action = qobject_cast<const QAction *>(sender()))
openFile(action->data().toString());
}
void MainWindow::save()
{
if (activeMdiChild() && activeMdiChild()->save())
statusBar()->showMessage(tr("File saved"), 2000);
}
void MainWindow::saveAs()
{
MdiChild *child = activeMdiChild();
if (child && child->saveAs()) {
statusBar()->showMessage(tr("File saved"), 2000);
MainWindow::prependToRecentFiles(child->currentFile());
}
}
#ifndef QT_NO_CLIPBOARD
void MainWindow::cut()
{
if (activeMdiChild())
activeMdiChild()->cut();
}
void MainWindow::copy()
{
if (activeMdiChild())
activeMdiChild()->copy();
}
void MainWindow::paste()
{
if (activeMdiChild())
activeMdiChild()->paste();
}
#endif
void MainWindow::about()
{
QMessageBox::about(this, tr("About MDI"),
tr("The <b>MDI</b> example demonstrates how to write multiple "
"document interface applications using Qt."));
}
void MainWindow::updateMenus()
{
bool hasMdiChild = (activeMdiChild() != nullptr);
saveAct->setEnabled(hasMdiChild);
saveAsAct->setEnabled(hasMdiChild);
#ifndef QT_NO_CLIPBOARD
pasteAct->setEnabled(hasMdiChild);
#endif
closeAct->setEnabled(hasMdiChild);
closeAllAct->setEnabled(hasMdiChild);
tileAct->setEnabled(hasMdiChild);
cascadeAct->setEnabled(hasMdiChild);
nextAct->setEnabled(hasMdiChild);
previousAct->setEnabled(hasMdiChild);
windowMenuSeparatorAct->setVisible(hasMdiChild);
#ifndef QT_NO_CLIPBOARD
bool hasSelection = (activeMdiChild() &&
activeMdiChild()->textCursor().hasSelection());
cutAct->setEnabled(hasSelection);
copyAct->setEnabled(hasSelection);
#endif
}
void MainWindow::updateWindowMenu()
{
windowMenu->clear();
windowMenu->addAction(closeAct);
windowMenu->addAction(closeAllAct);
windowMenu->addSeparator();
windowMenu->addAction(tileAct);
windowMenu->addAction(cascadeAct);
windowMenu->addSeparator();
windowMenu->addAction(nextAct);
windowMenu->addAction(previousAct);
windowMenu->addAction(windowMenuSeparatorAct);
QList<QMdiSubWindow *> windows = mdiArea->subWindowList();
windowMenuSeparatorAct->setVisible(!windows.isEmpty());
for (int i = 0; i < windows.size(); ++i) {
QMdiSubWindow *mdiSubWindow = windows.at(i);
MdiChild *child = qobject_cast<MdiChild *>(mdiSubWindow->widget());
QString text;
if (i < 9) {
text = tr("&%1 %2").arg(i + 1)
.arg(child->userFriendlyCurrentFile());
} else {
text = tr("%1 %2").arg(i + 1)
.arg(child->userFriendlyCurrentFile());
}
QAction *action = windowMenu->addAction(text, mdiSubWindow, [this, mdiSubWindow]() {
mdiArea->setActiveSubWindow(mdiSubWindow);
});
action->setCheckable(true);
action ->setChecked(child == activeMdiChild());
}
}
MdiChild *MainWindow::createMdiChild()
{
MdiChild *child = new MdiChild;
mdiArea->addSubWindow(child);
#ifndef QT_NO_CLIPBOARD
connect(child, &QTextEdit::copyAvailable, cutAct, &QAction::setEnabled);
connect(child, &QTextEdit::copyAvailable, copyAct, &QAction::setEnabled);
#endif
return child;
}
void MainWindow::createActions()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QToolBar *fileToolBar = addToolBar(tr("File"));
const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(":/images/new.png"));
newAct = new QAction(newIcon, tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, &QAction::triggered, this, &MainWindow::newFile);
fileMenu->addAction(newAct);
fileToolBar->addAction(newAct);
const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(":/images/open.png"));
QAction *openAct = new QAction(openIcon, tr("&Open..."), this);
openAct->setShortcuts(QKeySequence::Open);
openAct->setStatusTip(tr("Open an existing file"));
connect(openAct, &QAction::triggered, this, &MainWindow::open);
fileMenu->addAction(openAct);
fileToolBar->addAction(openAct);
const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(":/images/save.png"));
saveAct = new QAction(saveIcon, tr("&Save"), this);
saveAct->setShortcuts(QKeySequence::Save);
saveAct->setStatusTip(tr("Save the document to disk"));
connect(saveAct, &QAction::triggered, this, &MainWindow::save);
fileToolBar->addAction(saveAct);
const QIcon saveAsIcon = QIcon::fromTheme("document-save-as");
saveAsAct = new QAction(saveAsIcon, tr("Save &As..."), this);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
saveAsAct->setStatusTip(tr("Save the document under a new name"));
connect(saveAsAct, &QAction::triggered, this, &MainWindow::saveAs);
fileMenu->addAction(saveAsAct);
fileMenu->addSeparator();
QMenu *recentMenu = fileMenu->addMenu(tr("Recent..."));
connect(recentMenu, &QMenu::aboutToShow, this, &MainWindow::updateRecentFileActions);
recentFileSubMenuAct = recentMenu->menuAction();
for (int i = 0; i < MaxRecentFiles; ++i) {
recentFileActs[i] = recentMenu->addAction(QString(), this, &MainWindow::openRecentFile);
recentFileActs[i]->setVisible(false);
}
recentFileSeparator = fileMenu->addSeparator();
setRecentFilesVisible(MainWindow::hasRecentFiles());
fileMenu->addAction(tr("Switch layout direction"), this, &MainWindow::switchLayoutDirection);
fileMenu->addSeparator();
//! [0]
const QIcon exitIcon = QIcon::fromTheme("application-exit");
QAction *exitAct = fileMenu->addAction(exitIcon, tr("E&xit"), qApp, &QApplication::quit);
exitAct->setShortcuts(QKeySequence::Quit);
exitAct->setStatusTip(tr("Exit the application"));
fileMenu->addAction(exitAct);
//! [0]
#ifndef QT_NO_CLIPBOARD
QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
QToolBar *editToolBar = addToolBar(tr("Edit"));
const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(":/images/cut.png"));
cutAct = new QAction(cutIcon, tr("Cu&t"), this);
cutAct->setShortcuts(QKeySequence::Cut);
cutAct->setStatusTip(tr("Cut the current selection's contents to the "
"clipboard"));
connect(cutAct, &QAction::triggered, this, &MainWindow::cut);
editMenu->addAction(cutAct);
editToolBar->addAction(cutAct);
const QIcon copyIcon = QIcon::fromTheme("edit-copy", QIcon(":/images/copy.png"));
copyAct = new QAction(copyIcon, tr("&Copy"), this);
copyAct->setShortcuts(QKeySequence::Copy);
copyAct->setStatusTip(tr("Copy the current selection's contents to the "
"clipboard"));
connect(copyAct, &QAction::triggered, this, &MainWindow::copy);
editMenu->addAction(copyAct);
editToolBar->addAction(copyAct);
const QIcon pasteIcon = QIcon::fromTheme("edit-paste", QIcon(":/images/paste.png"));
pasteAct = new QAction(pasteIcon, tr("&Paste"), this);
pasteAct->setShortcuts(QKeySequence::Paste);
pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
"selection"));
connect(pasteAct, &QAction::triggered, this, &MainWindow::paste);
editMenu->addAction(pasteAct);
editToolBar->addAction(pasteAct);
#endif
windowMenu = menuBar()->addMenu(tr("&Window"));
connect(windowMenu, &QMenu::aboutToShow, this, &MainWindow::updateWindowMenu);
closeAct = new QAction(tr("Cl&ose"), this);
closeAct->setStatusTip(tr("Close the active window"));
connect(closeAct, &QAction::triggered,
mdiArea, &QMdiArea::closeActiveSubWindow);
closeAllAct = new QAction(tr("Close &All"), this);
closeAllAct->setStatusTip(tr("Close all the windows"));
connect(closeAllAct, &QAction::triggered, mdiArea, &QMdiArea::closeAllSubWindows);
tileAct = new QAction(tr("&Tile"), this);
tileAct->setStatusTip(tr("Tile the windows"));
connect(tileAct, &QAction::triggered, mdiArea, &QMdiArea::tileSubWindows);
cascadeAct = new QAction(tr("&Cascade"), this);
cascadeAct->setStatusTip(tr("Cascade the windows"));
connect(cascadeAct, &QAction::triggered, mdiArea, &QMdiArea::cascadeSubWindows);
nextAct = new QAction(tr("Ne&xt"), this);
nextAct->setShortcuts(QKeySequence::NextChild);
nextAct->setStatusTip(tr("Move the focus to the next window"));
connect(nextAct, &QAction::triggered, mdiArea, &QMdiArea::activateNextSubWindow);
previousAct = new QAction(tr("Pre&vious"), this);
previousAct->setShortcuts(QKeySequence::PreviousChild);
previousAct->setStatusTip(tr("Move the focus to the previous "
"window"));
connect(previousAct, &QAction::triggered, mdiArea, &QMdiArea::activatePreviousSubWindow);
windowMenuSeparatorAct = new QAction(this);
windowMenuSeparatorAct->setSeparator(true);
updateWindowMenu();
menuBar()->addSeparator();
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about);
aboutAct->setStatusTip(tr("Show the application's About box"));
QAction *aboutQtAct = helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
}
void MainWindow::createStatusBar()
{
statusBar()->showMessage(tr("Ready"));
}
void MainWindow::readSettings()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
if (geometry.isEmpty()) {
const QRect availableGeometry = screen()->availableGeometry();
resize(availableGeometry.width() / 3, availableGeometry.height() / 2);
move((availableGeometry.width() - width()) / 2,
(availableGeometry.height() - height()) / 2);
} else {
restoreGeometry(geometry);
}
}
void MainWindow::writeSettings()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
settings.setValue("geometry", saveGeometry());
}
MdiChild *MainWindow::activeMdiChild() const
{
if (QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow())
return qobject_cast<MdiChild *>(activeSubWindow->widget());
return nullptr;
}
QMdiSubWindow *MainWindow::findMdiChild(const QString &fileName) const
{
QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();
const QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
for (QMdiSubWindow *window : subWindows) {
MdiChild *mdiChild = qobject_cast<MdiChild *>(window->widget());
if (mdiChild->currentFile() == canonicalFilePath)
return window;
}
return nullptr;
}
void MainWindow::switchLayoutDirection()
{
if (layoutDirection() == Qt::LeftToRight)
QGuiApplication::setLayoutDirection(Qt::RightToLeft);
else
QGuiApplication::setLayoutDirection(Qt::LeftToRight);
}

View File

@ -0,0 +1,84 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MdiChild;
QT_BEGIN_NAMESPACE
class QAction;
class QMenu;
class QMdiArea;
class QMdiSubWindow;
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
bool openFile(const QString &fileName);
protected:
void closeEvent(QCloseEvent *event) override;
private slots:
void newFile();
void open();
void save();
void saveAs();
void updateRecentFileActions();
void openRecentFile();
#ifndef QT_NO_CLIPBOARD
void cut();
void copy();
void paste();
#endif
void about();
void updateMenus();
void updateWindowMenu();
MdiChild *createMdiChild();
void switchLayoutDirection();
private:
enum { MaxRecentFiles = 5 };
void createActions();
void createStatusBar();
void readSettings();
void writeSettings();
bool loadFile(const QString &fileName);
static bool hasRecentFiles();
void prependToRecentFiles(const QString &fileName);
void setRecentFilesVisible(bool visible);
MdiChild *activeMdiChild() const;
QMdiSubWindow *findMdiChild(const QString &fileName) const;
QMdiArea *mdiArea;
QMenu *windowMenu;
QAction *newAct;
QAction *saveAct;
QAction *saveAsAct;
QAction *recentFileActs[MaxRecentFiles];
QAction *recentFileSeparator;
QAction *recentFileSubMenuAct;
#ifndef QT_NO_CLIPBOARD
QAction *cutAct;
QAction *copyAct;
QAction *pasteAct;
#endif
QAction *closeAct;
QAction *closeAllAct;
QAction *tileAct;
QAction *cascadeAct;
QAction *nextAct;
QAction *previousAct;
QAction *windowMenuSeparatorAct;
};
#endif

View File

@ -0,0 +1,13 @@
QT += widgets
requires(qtConfig(filedialog))
HEADERS = mainwindow.h \
mdichild.h
SOURCES = main.cpp \
mainwindow.cpp \
mdichild.cpp
RESOURCES = mdi.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mainwindows/mdi
INSTALLS += target

View File

@ -0,0 +1,10 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/copy.png</file>
<file>images/cut.png</file>
<file>images/new.png</file>
<file>images/open.png</file>
<file>images/paste.png</file>
<file>images/save.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,150 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "mdichild.h"
MdiChild::MdiChild()
{
setAttribute(Qt::WA_DeleteOnClose);
isUntitled = true;
}
void MdiChild::newFile()
{
static int sequenceNumber = 1;
isUntitled = true;
curFile = tr("document%1.txt").arg(sequenceNumber++);
setWindowTitle(curFile + "[*]");
connect(document(), &QTextDocument::contentsChanged,
this, &MdiChild::documentWasModified);
}
bool MdiChild::loadFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("MDI"),
tr("Cannot read file %1:\n%2.")
.arg(fileName)
.arg(file.errorString()));
return false;
}
QTextStream in(&file);
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
setPlainText(in.readAll());
QGuiApplication::restoreOverrideCursor();
setCurrentFile(fileName);
connect(document(), &QTextDocument::contentsChanged,
this, &MdiChild::documentWasModified);
return true;
}
bool MdiChild::save()
{
if (isUntitled) {
return saveAs();
} else {
return saveFile(curFile);
}
}
bool MdiChild::saveAs()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),
curFile);
if (fileName.isEmpty())
return false;
return saveFile(fileName);
}
bool MdiChild::saveFile(const QString &fileName)
{
QString errorMessage;
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
QSaveFile file(fileName);
if (file.open(QFile::WriteOnly | QFile::Text)) {
QTextStream out(&file);
out << toPlainText();
if (!file.commit()) {
errorMessage = tr("Cannot write file %1:\n%2.")
.arg(QDir::toNativeSeparators(fileName), file.errorString());
}
} else {
errorMessage = tr("Cannot open file %1 for writing:\n%2.")
.arg(QDir::toNativeSeparators(fileName), file.errorString());
}
QGuiApplication::restoreOverrideCursor();
if (!errorMessage.isEmpty()) {
QMessageBox::warning(this, tr("MDI"), errorMessage);
return false;
}
setCurrentFile(fileName);
return true;
}
QString MdiChild::userFriendlyCurrentFile()
{
return strippedName(curFile);
}
void MdiChild::closeEvent(QCloseEvent *event)
{
if (maybeSave()) {
event->accept();
} else {
event->ignore();
}
}
void MdiChild::documentWasModified()
{
setWindowModified(document()->isModified());
}
bool MdiChild::maybeSave()
{
if (!document()->isModified())
return true;
const QMessageBox::StandardButton ret
= QMessageBox::warning(this, tr("MDI"),
tr("'%1' has been modified.\n"
"Do you want to save your changes?")
.arg(userFriendlyCurrentFile()),
QMessageBox::Save | QMessageBox::Discard
| QMessageBox::Cancel);
switch (ret) {
case QMessageBox::Save:
return save();
case QMessageBox::Cancel:
return false;
default:
break;
}
return true;
}
void MdiChild::setCurrentFile(const QString &fileName)
{
curFile = QFileInfo(fileName).canonicalFilePath();
isUntitled = false;
document()->setModified(false);
setWindowModified(false);
setWindowTitle(userFriendlyCurrentFile() + "[*]");
}
QString MdiChild::strippedName(const QString &fullFileName)
{
return QFileInfo(fullFileName).fileName();
}

View File

@ -0,0 +1,39 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MDICHILD_H
#define MDICHILD_H
#include <QTextEdit>
class MdiChild : public QTextEdit
{
Q_OBJECT
public:
MdiChild();
void newFile();
bool loadFile(const QString &fileName);
bool save();
bool saveAs();
bool saveFile(const QString &fileName);
QString userFriendlyCurrentFile();
QString currentFile() { return curFile; }
protected:
void closeEvent(QCloseEvent *event) override;
private slots:
void documentWasModified();
private:
bool maybeSave();
void setCurrentFile(const QString &fileName);
QString strippedName(const QString &fullFileName);
QString curFile;
bool isUntitled;
};
#endif

View File

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

View File

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

View File

@ -0,0 +1,335 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "mainwindow.h"
//! [0]
MainWindow::MainWindow()
{
QWidget *widget = new QWidget;
setCentralWidget(widget);
//! [0]
//! [1]
QWidget *topFiller = new QWidget;
topFiller->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
infoLabel = new QLabel(tr("<i>Choose a menu option, or right-click to "
"invoke a context menu</i>"));
infoLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
infoLabel->setAlignment(Qt::AlignCenter);
QWidget *bottomFiller = new QWidget;
bottomFiller->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QVBoxLayout *layout = new QVBoxLayout;
layout->setContentsMargins(5, 5, 5, 5);
layout->addWidget(topFiller);
layout->addWidget(infoLabel);
layout->addWidget(bottomFiller);
widget->setLayout(layout);
//! [1]
//! [2]
createActions();
createMenus();
QString message = tr("A context menu is available by right-clicking");
statusBar()->showMessage(message);
setWindowTitle(tr("Menus"));
setMinimumSize(160, 160);
resize(480, 320);
}
//! [2]
//! [3]
#ifndef QT_NO_CONTEXTMENU
void MainWindow::contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu(this);
menu.addAction(cutAct);
menu.addAction(copyAct);
menu.addAction(pasteAct);
menu.exec(event->globalPos());
}
#endif // QT_NO_CONTEXTMENU
//! [3]
void MainWindow::newFile()
{
infoLabel->setText(tr("Invoked <b>File|New</b>"));
}
void MainWindow::open()
{
infoLabel->setText(tr("Invoked <b>File|Open</b>"));
}
void MainWindow::save()
{
infoLabel->setText(tr("Invoked <b>File|Save</b>"));
}
void MainWindow::print()
{
infoLabel->setText(tr("Invoked <b>File|Print</b>"));
}
void MainWindow::undo()
{
infoLabel->setText(tr("Invoked <b>Edit|Undo</b>"));
}
void MainWindow::redo()
{
infoLabel->setText(tr("Invoked <b>Edit|Redo</b>"));
}
void MainWindow::cut()
{
infoLabel->setText(tr("Invoked <b>Edit|Cut</b>"));
}
void MainWindow::copy()
{
infoLabel->setText(tr("Invoked <b>Edit|Copy</b>"));
}
void MainWindow::paste()
{
infoLabel->setText(tr("Invoked <b>Edit|Paste</b>"));
}
void MainWindow::bold()
{
infoLabel->setText(tr("Invoked <b>Edit|Format|Bold</b>"));
}
void MainWindow::italic()
{
infoLabel->setText(tr("Invoked <b>Edit|Format|Italic</b>"));
}
void MainWindow::leftAlign()
{
infoLabel->setText(tr("Invoked <b>Edit|Format|Left Align</b>"));
}
void MainWindow::rightAlign()
{
infoLabel->setText(tr("Invoked <b>Edit|Format|Right Align</b>"));
}
void MainWindow::justify()
{
infoLabel->setText(tr("Invoked <b>Edit|Format|Justify</b>"));
}
void MainWindow::center()
{
infoLabel->setText(tr("Invoked <b>Edit|Format|Center</b>"));
}
void MainWindow::setLineSpacing()
{
infoLabel->setText(tr("Invoked <b>Edit|Format|Set Line Spacing</b>"));
}
void MainWindow::setParagraphSpacing()
{
infoLabel->setText(tr("Invoked <b>Edit|Format|Set Paragraph Spacing</b>"));
}
void MainWindow::about()
{
infoLabel->setText(tr("Invoked <b>Help|About</b>"));
QMessageBox::about(this, tr("About Menu"),
tr("The <b>Menu</b> example shows how to create "
"menu-bar menus and context menus."));
}
void MainWindow::aboutQt()
{
infoLabel->setText(tr("Invoked <b>Help|About Qt</b>"));
}
//! [4]
void MainWindow::createActions()
{
//! [5]
newAct = new QAction(tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, &QAction::triggered, this, &MainWindow::newFile);
//! [4]
openAct = new QAction(tr("&Open..."), this);
openAct->setShortcuts(QKeySequence::Open);
openAct->setStatusTip(tr("Open an existing file"));
connect(openAct, &QAction::triggered, this, &MainWindow::open);
//! [5]
saveAct = new QAction(tr("&Save"), this);
saveAct->setShortcuts(QKeySequence::Save);
saveAct->setStatusTip(tr("Save the document to disk"));
connect(saveAct, &QAction::triggered, this, &MainWindow::save);
printAct = new QAction(tr("&Print..."), this);
printAct->setShortcuts(QKeySequence::Print);
printAct->setStatusTip(tr("Print the document"));
connect(printAct, &QAction::triggered, this, &MainWindow::print);
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcuts(QKeySequence::Quit);
exitAct->setStatusTip(tr("Exit the application"));
connect(exitAct, &QAction::triggered, this, &QWidget::close);
undoAct = new QAction(tr("&Undo"), this);
undoAct->setShortcuts(QKeySequence::Undo);
undoAct->setStatusTip(tr("Undo the last operation"));
connect(undoAct, &QAction::triggered, this, &MainWindow::undo);
redoAct = new QAction(tr("&Redo"), this);
redoAct->setShortcuts(QKeySequence::Redo);
redoAct->setStatusTip(tr("Redo the last operation"));
connect(redoAct, &QAction::triggered, this, &MainWindow::redo);
cutAct = new QAction(tr("Cu&t"), this);
cutAct->setShortcuts(QKeySequence::Cut);
cutAct->setStatusTip(tr("Cut the current selection's contents to the "
"clipboard"));
connect(cutAct, &QAction::triggered, this, &MainWindow::cut);
copyAct = new QAction(tr("&Copy"), this);
copyAct->setShortcuts(QKeySequence::Copy);
copyAct->setStatusTip(tr("Copy the current selection's contents to the "
"clipboard"));
connect(copyAct, &QAction::triggered, this, &MainWindow::copy);
pasteAct = new QAction(tr("&Paste"), this);
pasteAct->setShortcuts(QKeySequence::Paste);
pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
"selection"));
connect(pasteAct, &QAction::triggered, this, &MainWindow::paste);
boldAct = new QAction(tr("&Bold"), this);
boldAct->setCheckable(true);
boldAct->setShortcut(QKeySequence::Bold);
boldAct->setStatusTip(tr("Make the text bold"));
connect(boldAct, &QAction::triggered, this, &MainWindow::bold);
QFont boldFont = boldAct->font();
boldFont.setBold(true);
boldAct->setFont(boldFont);
italicAct = new QAction(tr("&Italic"), this);
italicAct->setCheckable(true);
italicAct->setShortcut(QKeySequence::Italic);
italicAct->setStatusTip(tr("Make the text italic"));
connect(italicAct, &QAction::triggered, this, &MainWindow::italic);
QFont italicFont = italicAct->font();
italicFont.setItalic(true);
italicAct->setFont(italicFont);
setLineSpacingAct = new QAction(tr("Set &Line Spacing..."), this);
setLineSpacingAct->setStatusTip(tr("Change the gap between the lines of a "
"paragraph"));
connect(setLineSpacingAct, &QAction::triggered, this, &MainWindow::setLineSpacing);
setParagraphSpacingAct = new QAction(tr("Set &Paragraph Spacing..."), this);
setParagraphSpacingAct->setStatusTip(tr("Change the gap between paragraphs"));
connect(setParagraphSpacingAct, &QAction::triggered,
this, &MainWindow::setParagraphSpacing);
aboutAct = new QAction(tr("&About"), this);
aboutAct->setStatusTip(tr("Show the application's About box"));
connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
aboutQtAct = new QAction(tr("About &Qt"), this);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
connect(aboutQtAct, &QAction::triggered, this, &MainWindow::aboutQt);
leftAlignAct = new QAction(tr("&Left Align"), this);
leftAlignAct->setCheckable(true);
leftAlignAct->setShortcut(tr("Ctrl+L"));
leftAlignAct->setStatusTip(tr("Left align the selected text"));
connect(leftAlignAct, &QAction::triggered, this, &MainWindow::leftAlign);
rightAlignAct = new QAction(tr("&Right Align"), this);
rightAlignAct->setCheckable(true);
rightAlignAct->setShortcut(tr("Ctrl+R"));
rightAlignAct->setStatusTip(tr("Right align the selected text"));
connect(rightAlignAct, &QAction::triggered, this, &MainWindow::rightAlign);
justifyAct = new QAction(tr("&Justify"), this);
justifyAct->setCheckable(true);
justifyAct->setShortcut(tr("Ctrl+J"));
justifyAct->setStatusTip(tr("Justify the selected text"));
connect(justifyAct, &QAction::triggered, this, &MainWindow::justify);
centerAct = new QAction(tr("&Center"), this);
centerAct->setCheckable(true);
centerAct->setShortcut(tr("Ctrl+E"));
centerAct->setStatusTip(tr("Center the selected text"));
connect(centerAct, &QAction::triggered, this, &MainWindow::center);
//! [6] //! [7]
alignmentGroup = new QActionGroup(this);
alignmentGroup->addAction(leftAlignAct);
alignmentGroup->addAction(rightAlignAct);
alignmentGroup->addAction(justifyAct);
alignmentGroup->addAction(centerAct);
leftAlignAct->setChecked(true);
//! [6]
}
//! [7]
//! [8]
void MainWindow::createMenus()
{
//! [9] //! [10]
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(newAct);
//! [9]
fileMenu->addAction(openAct);
//! [10]
fileMenu->addAction(saveAct);
fileMenu->addAction(printAct);
//! [11]
fileMenu->addSeparator();
//! [11]
fileMenu->addAction(exitAct);
editMenu = menuBar()->addMenu(tr("&Edit"));
editMenu->addAction(undoAct);
editMenu->addAction(redoAct);
editMenu->addSeparator();
editMenu->addAction(cutAct);
editMenu->addAction(copyAct);
editMenu->addAction(pasteAct);
editMenu->addSeparator();
helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(aboutAct);
helpMenu->addAction(aboutQtAct);
//! [8]
//! [12]
formatMenu = editMenu->addMenu(tr("&Format"));
formatMenu->addAction(boldAct);
formatMenu->addAction(italicAct);
formatMenu->addSeparator()->setText(tr("Alignment"));
formatMenu->addAction(leftAlignAct);
formatMenu->addAction(rightAlignAct);
formatMenu->addAction(justifyAct);
formatMenu->addAction(centerAct);
formatMenu->addSeparator();
formatMenu->addAction(setLineSpacingAct);
formatMenu->addAction(setParagraphSpacingAct);
}
//! [12]

View File

@ -0,0 +1,89 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
class QAction;
class QActionGroup;
class QLabel;
class QMenu;
QT_END_NAMESPACE
//! [0]
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
protected:
#ifndef QT_NO_CONTEXTMENU
void contextMenuEvent(QContextMenuEvent *event) override;
#endif // QT_NO_CONTEXTMENU
//! [0]
//! [1]
private slots:
void newFile();
void open();
void save();
void print();
void undo();
void redo();
void cut();
void copy();
void paste();
void bold();
void italic();
void leftAlign();
void rightAlign();
void justify();
void center();
void setLineSpacing();
void setParagraphSpacing();
void about();
void aboutQt();
//! [1]
//! [2]
private:
void createActions();
void createMenus();
//! [2]
//! [3]
QMenu *fileMenu;
QMenu *editMenu;
QMenu *formatMenu;
QMenu *helpMenu;
QActionGroup *alignmentGroup;
QAction *newAct;
QAction *openAct;
QAction *saveAct;
QAction *printAct;
QAction *exitAct;
QAction *undoAct;
QAction *redoAct;
QAction *cutAct;
QAction *copyAct;
QAction *pasteAct;
QAction *boldAct;
QAction *italicAct;
QAction *leftAlignAct;
QAction *rightAlignAct;
QAction *justifyAct;
QAction *centerAct;
QAction *setLineSpacingAct;
QAction *setParagraphSpacingAct;
QAction *aboutAct;
QAction *aboutQtAct;
QLabel *infoLabel;
};
//! [3]
#endif

View File

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