mainwindow.cpp Example File

tools/plugandpaint/app/mainwindow.cpp
/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/
#include "interfaces.h" #include "mainwindow.h" #include "paintarea.h" #include "plugindialog.h" #include <QAction> #include <QActionGroup> #include <QApplication> #include <QColorDialog> #include <QFileDialog> #include <QInputDialog> #include <QMenu> #include <QMenuBar> #include <QMessageBox> #include <QPluginLoader> #include <QScrollArea> #include <QTimer> MainWindow::MainWindow() : paintArea(new PaintArea), scrollArea(new QScrollArea) { scrollArea->setBackgroundRole(QPalette::Dark); scrollArea->setWidget(paintArea); setCentralWidget(scrollArea); createActions(); createMenus(); loadPlugins(); setWindowTitle(tr("Plug & Paint")); if (!brushActionGroup->actions().isEmpty()) brushActionGroup->actions().first()->trigger(); QTimer::singleShot(500, this, &MainWindow::aboutPlugins); } void MainWindow::open() { const QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::currentPath()); if (!fileName.isEmpty()) { if (!paintArea->openImage(fileName)) { QMessageBox::information(this, tr("Plug & Paint"), tr("Cannot load %1.").arg(fileName)); return; } paintArea->adjustSize(); } } bool MainWindow::saveAs() { const QString initialPath = QDir::currentPath() + "/untitled.png"; const QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), initialPath); if (fileName.isEmpty()) return false; return paintArea->saveImage(fileName, "png"); } void MainWindow::brushColor() { const QColor newColor = QColorDialog::getColor(paintArea->brushColor()); if (newColor.isValid()) paintArea->setBrushColor(newColor); } void MainWindow::brushWidth() { bool ok; const int newWidth = QInputDialog::getInt(this, tr("Plug & Paint"), tr("Select brush width:"), paintArea->brushWidth(), 1, 50, 1, &ok); if (ok) paintArea->setBrushWidth(newWidth); } void MainWindow::changeBrush() { auto action = qobject_cast<QAction *>(sender()); auto iBrush = qobject_cast<BrushInterface *>(action->parent()); const QString brush = action->text(); paintArea->setBrush(iBrush, brush); } void MainWindow::insertShape() { auto action = qobject_cast<QAction *>(sender()); auto iShape = qobject_cast<ShapeInterface *>(action->parent()); const QPainterPath path = iShape->generateShape(action->text(), this); if (!path.isEmpty()) paintArea->insertShape(path); } void MainWindow::applyFilter() { auto action = qobject_cast<QAction *>(sender()); auto iFilter = qobject_cast<FilterInterface *>(action->parent()); const QImage image = iFilter->filterImage(action->text(), paintArea->image(), this); paintArea->setImage(image); } void MainWindow::about() { QMessageBox::about(this, tr("About Plug & Paint"), tr("The <b>Plug & Paint</b> example demonstrates how to write Qt " "applications that can be extended through plugins.")); } void MainWindow::aboutPlugins() { PluginDialog dialog(pluginsDir.path(), pluginFileNames, this); dialog.exec(); } void MainWindow::createActions() { openAct = new QAction(tr("&Open..."), this); openAct->setShortcuts(QKeySequence::Open); connect(openAct, &QAction::triggered, this, &MainWindow::open); saveAsAct = new QAction(tr("&Save As..."), this); saveAsAct->setShortcuts(QKeySequence::SaveAs); connect(saveAsAct, &QAction::triggered, this, &MainWindow::saveAs); exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, &QAction::triggered, this, &MainWindow::close); brushColorAct = new QAction(tr("&Brush Color..."), this); connect(brushColorAct, &QAction::triggered, this, &MainWindow::brushColor); brushWidthAct = new QAction(tr("&Brush Width..."), this); connect(brushWidthAct, &QAction::triggered, this, &MainWindow::brushWidth); brushActionGroup = new QActionGroup(this); aboutAct = new QAction(tr("&About"), this); connect(aboutAct, &QAction::triggered, this, &MainWindow::about); aboutQtAct = new QAction(tr("About &Qt"), this); connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt); aboutPluginsAct = new QAction(tr("About &Plugins"), this); connect(aboutPluginsAct, &QAction::triggered, this, &MainWindow::aboutPlugins); } void MainWindow::createMenus() { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(openAct); fileMenu->addAction(saveAsAct); fileMenu->addSeparator(); fileMenu->addAction(exitAct); brushMenu = menuBar()->addMenu(tr("&Brush")); brushMenu->addAction(brushColorAct); brushMenu->addAction(brushWidthAct); brushMenu->addSeparator(); shapesMenu = menuBar()->addMenu(tr("&Shapes")); filterMenu = menuBar()->addMenu(tr("&Filter")); menuBar()->addSeparator(); helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(aboutAct); helpMenu->addAction(aboutQtAct); helpMenu->addAction(aboutPluginsAct); } void MainWindow::loadPlugins() { const auto staticInstances = QPluginLoader::staticInstances(); for (QObject *plugin : staticInstances) populateMenus(plugin); pluginsDir = QDir(qApp->applicationDirPath()); #if defined(Q_OS_WIN) if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release") pluginsDir.cdUp(); #elif defined(Q_OS_MAC) if (pluginsDir.dirName() == "MacOS") { pluginsDir.cdUp(); pluginsDir.cdUp(); pluginsDir.cdUp(); } #endif pluginsDir.cd("plugins"); const auto entryList = pluginsDir.entryList(QDir::Files); for (const QString &fileName : entryList) { QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); QObject *plugin = loader.instance(); if (plugin) { populateMenus(plugin); pluginFileNames += fileName; } } brushMenu->setEnabled(!brushActionGroup->actions().isEmpty()); shapesMenu->setEnabled(!shapesMenu->actions().isEmpty()); filterMenu->setEnabled(!filterMenu->actions().isEmpty()); } void MainWindow::populateMenus(QObject *plugin) { auto iBrush = qobject_cast<BrushInterface *>(plugin); if (iBrush) addToMenu(plugin, iBrush->brushes(), brushMenu, &MainWindow::changeBrush, brushActionGroup); auto iShape = qobject_cast<ShapeInterface *>(plugin); if (iShape) addToMenu(plugin, iShape->shapes(), shapesMenu, &MainWindow::insertShape); auto iFilter = qobject_cast<FilterInterface *>(plugin); if (iFilter) addToMenu(plugin, iFilter->filters(), filterMenu, &MainWindow::applyFilter); } void MainWindow::addToMenu(QObject *plugin, const QStringList &texts, QMenu *menu, Member member, QActionGroup *actionGroup) { for (const QString &text : texts) { auto action = new QAction(text, plugin); connect(action, &QAction::triggered, this, member); menu->addAction(action); if (actionGroup) { action->setCheckable(true); actionGroup->addAction(action); } } }