diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2023-06-26 15:06:29 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2023-06-30 08:50:59 +0200 |
commit | 9c71b924304c2d1bd3ac3e13263b47131478562c (patch) | |
tree | 5fcf6878f4143518c18e3cdb564c90323104935e /examples/widgets | |
parent | 921337f98c54d3c4a252569acd2152a1dea8c4bb (diff) |
Move plug and paint example to manual test
Pick-to: 6.5 6.6
Change-Id: Ibfd870f2f879d6ae68cd6806b0c1ab02da0a3441
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'examples/widgets')
31 files changed, 2 insertions, 1843 deletions
diff --git a/examples/widgets/doc/images/plugandpaint-plugindialog.png b/examples/widgets/doc/images/plugandpaint-plugindialog.png Binary files differdeleted file mode 100644 index 4b601bd58b..0000000000 --- a/examples/widgets/doc/images/plugandpaint-plugindialog.png +++ /dev/null diff --git a/examples/widgets/doc/images/plugandpaint.png b/examples/widgets/doc/images/plugandpaint.png Binary files differdeleted file mode 100644 index bd5d001f91..0000000000 --- a/examples/widgets/doc/images/plugandpaint.png +++ /dev/null diff --git a/examples/widgets/doc/src/echoplugin.qdoc b/examples/widgets/doc/src/echoplugin.qdoc index 4cdd700534..72fa3e5699 100644 --- a/examples/widgets/doc/src/echoplugin.qdoc +++ b/examples/widgets/doc/src/echoplugin.qdoc @@ -175,7 +175,5 @@ create plugins. We give an example of a plugin that extends Qt in the \l{Style - Plugin Example}{style plugin} example. The \l{Plug & Paint - Example}{plug and paint} example shows how to create static - plugins. + Plugin Example}{style plugin} example. */ diff --git a/examples/widgets/doc/src/plugandpaint.qdoc b/examples/widgets/doc/src/plugandpaint.qdoc deleted file mode 100644 index 09af21666a..0000000000 --- a/examples/widgets/doc/src/plugandpaint.qdoc +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example tools/plugandpaint/app - \title Plug & Paint Example - \ingroup examples-widgets-tools - - \brief Demonstrates how to extend Qt applications using plugins. - - \image plugandpaint.png Screenshot of the Plug & Paint example - - A plugin is a dynamic library that can be loaded at run-time to - extend an application. Qt makes it possible to create custom - plugins and to load them using QPluginLoader. To ensure that - plugins don't get lost, it is also possible to link them - statically to the executable. The Plug & Paint example uses - plugins to support custom brushes, shapes, and image filters. A - single plugin can provide multiple brushes, shapes, and/or - filters. - - If you want to learn how to make your own application extensible - through plugins, we recommend that you start by reading this - overview, which explains how to make an application use plugins. - Afterwards, you can read the - \l{tools/plugandpaint/plugins/basictools}{Basic Tools} and - \l{tools/plugandpaint/plugins/extrafilters}{Extra Filters} - overviews, which show how to implement static and dynamic - plugins, respectively. - - Plug & Paint consists of the following classes: - - \list - \li \c MainWindow is a QMainWindow subclass that provides the menu - system and that contains a \c PaintArea as the central widget. - \li \c PaintArea is a QWidget that allows the user to draw using a - brush and to insert shapes. - \li \c PluginDialog is a dialog that shows information about the - plugins detected by the application. - \li \c BrushInterface, \c ShapeInterface, and \c FilterInterface are - abstract base classes that can be implemented by plugins to - provide custom brushes, shapes, and image filters. - \endlist - - \section1 The Plugin Interfaces - - We will start by reviewing the interfaces defined in \c - interfaces.h. These interfaces are used by the Plug & Paint - application to access extra functionality. They are implemented - in the plugins. - - - \snippet tools/plugandpaint/app/interfaces.h 0 - - The \c BrushInterface class declares four pure virtual functions. - The first pure virtual function, \c brushes(), returns a list of - strings that identify the brushes provided by the plugin. By - returning a QStringList instead of a QString, we make it possible - for a single plugin to provide multiple brushes. The other - functions have a \c brush parameter to identify which brush - (among those returned by \c brushes()) is used. - - \c mousePress(), \c mouseMove(), and \c mouseRelease() take a - QPainter and one or two \l{QPoint}s, and return a QRect - identifying which portion of the image was altered by the brush. - - The class also has a virtual destructor. Interface classes - usually don't need such a destructor (because it would make - little sense to \c delete the object that implements the - interface through a pointer to the interface), but some compilers - emit a warning for classes that declare virtual functions but no - virtual destructor. We provide the destructor to keep these - compilers happy. - - \snippet tools/plugandpaint/app/interfaces.h 1 - - The \c ShapeInterface class declares a \c shapes() function that - works the same as \c{BrushInterface}'s \c brushes() function, and - a \c generateShape() function that has a \c shape parameter. - Shapes are represented by a QPainterPath, a data type that can - represent arbitrary 2D shapes or combinations of shapes. The \c - parent parameter can be used by the plugin to pop up a dialog - asking the user to specify more information. - - \snippet tools/plugandpaint/app/interfaces.h 2 - - The \c FilterInterface class declares a \c filters() function - that returns a list of filter names, and a \c filterImage() - function that applies a filter to an image. - - \snippet tools/plugandpaint/app/interfaces.h 4 - - To make it possible to query at run-time whether a plugin - implements a given interface, we must use the \c - Q_DECLARE_INTERFACE() macro. The first argument is the name of - the interface. The second argument is a string identifying the - interface in a unique way. By convention, we use a "Java package - name" syntax to identify interfaces. If we later change the - interfaces, we must use a different string to identify the new - interface; otherwise, the application might crash. It is therefore - a good idea to include a version number in the string, as we did - above. - - The \l{tools/plugandpaint/plugins/basictools}{Basic Tools} plugin - and the \l{tools/plugandpaint/plugins/extrafilters}{Extra Filters} - plugin shows how to derive from \c BrushInterface, \c - ShapeInterface, and \c FilterInterface. - - A note on naming: It might have been tempting to give the \c - brushes(), \c shapes(), and \c filters() functions a more generic - name, such as \c keys() or \c features(). However, that would - have made multiple inheritance impractical. When creating - interfaces, we should always try to give unique names to the pure - virtual functions. - - \section1 The MainWindow Class - - The \c MainWindow class is a standard QMainWindow subclass, as - found in many of the other examples. Here, we'll - concentrate on the parts of the code that are related to plugins. - - \snippet tools/plugandpaint/app/mainwindow.cpp 4 - - The \c loadPlugins() function is called from the \c MainWindow - constructor to detect plugins and update the \uicontrol{Brush}, - \uicontrol{Shapes}, and \uicontrol{Filters} menus. We start by handling static - plugins (available through QPluginLoader::staticInstances()) - - To the application that uses the plugin, a Qt plugin is simply a - QObject. That QObject implements plugin interfaces using multiple - inheritance. - - \snippet tools/plugandpaint/app/mainwindow.cpp 5 - - The next step is to load dynamic plugins. We initialize the \c - pluginsDir member variable to refer to the \c plugins - subdirectory of the Plug & Paint example. On Unix, this is just a - matter of initializing the QDir variable with - QApplication::applicationDirPath(), the path of the executable - file, and to do a \l{QDir::cd()}{cd()}. On Windows and \macos, - this file is usually located in a subdirectory, so we need to - take this into account. - - \snippet tools/plugandpaint/app/mainwindow.cpp 6 - \snippet tools/plugandpaint/app/mainwindow.cpp 7 - \snippet tools/plugandpaint/app/mainwindow.cpp 8 - - We use QDir::entryList() to get a list of all files in that - directory. Then we iterate over the result using a range-based for loop - and try to load the plugin using QPluginLoader. - - The QObject provided by the plugin is accessible through - QPluginLoader::instance(). If the dynamic library isn't a Qt - plugin, or if it was compiled against an incompatible version of - the Qt library, QPluginLoader::instance() returns a null pointer. - - If QPluginLoader::instance() is non-null, we add it to the menus. - - \snippet tools/plugandpaint/app/mainwindow.cpp 9 - - At the end, we enable or disable the \uicontrol{Brush}, \uicontrol{Shapes}, - and \uicontrol{Filters} menus based on whether they contain any items. - - \snippet tools/plugandpaint/app/mainwindow.cpp 10 - - For each plugin (static or dynamic), we check which interfaces it - implements using \l qobject_cast(). First, we try to cast the - plugin instance to a \c BrushInterface; if it works, we call the - private function \c addToMenu() with the list of brushes returned - by \c brushes(). Then we do the same with the \c ShapeInterface - and the \c FilterInterface. - - \snippet tools/plugandpaint/app/mainwindow.cpp 3 - - The \c aboutPlugins() slot is called on startup and can be - invoked at any time through the \uicontrol{About Plugins} action. It - pops up a \c PluginDialog, providing information about the loaded - plugins. - - \image plugandpaint-plugindialog.png Screenshot of the Plugin dialog - - - The \c addToMenu() function is called from \c loadPlugin() to - create \l{QAction}s for custom brushes, shapes, or filters and - add them to the relevant menu. The QAction is created with the - plugin from which it comes from as the parent; this makes it - convenient to get access to the plugin later. - - \snippet tools/plugandpaint/app/mainwindow.cpp 0 - - The \c changeBrush() slot is invoked when the user chooses one of - the brushes from the \uicontrol{Brush} menu. We start by finding out - which action invoked the slot using QObject::sender(). Then we - get the \c BrushInterface out of the plugin (which we - conveniently passed as the QAction's parent) and we call \c - PaintArea::setBrush() with the \c BrushInterface and the string - identifying the brush. Next time the user draws on the paint - area, \c PaintArea will use this brush. - - \snippet tools/plugandpaint/app/mainwindow.cpp 1 - - The \c insertShape() is invoked when the use chooses one of the - shapes from the \uicontrol{Shapes} menu. We retrieve the QAction that - invoked the slot, then the \c ShapeInterface associated with that - QAction, and finally we call \c ShapeInterface::generateShape() - to obtain a QPainterPath. - - \snippet tools/plugandpaint/app/mainwindow.cpp 2 - - The \c applyFilter() slot is similar: We retrieve the QAction - that invoked the slot, then the \c FilterInterface associated to - that QAction, and finally we call \c - FilterInterface::filterImage() to apply the filter onto the - current image. - - \section1 The PaintArea Class - - The \c PaintArea class contains some code that deals with \c - BrushInterface, so we'll review it briefly. - - \snippet tools/plugandpaint/app/paintarea.cpp 0 - - In \c setBrush(), we simply store the \c BrushInterface and the - brush that are given to us by \c MainWindow. - - \snippet tools/plugandpaint/app/paintarea.cpp 1 - - In the \l{QWidget::mouseMoveEvent()}{mouse move event handler}, - we call the \c BrushInterface::mouseMove() function on the - current \c BrushInterface, with the current brush. The mouse - press and mouse release handlers are very similar. - - \section1 The PluginDialog Class - - The \c PluginDialog class provides information about the loaded - plugins to the user. Its constructor takes a path to the plugins - and a list of plugin file names. It calls \c findPlugins() - to fill the QTreeWdiget with information about the plugins: - - \snippet tools/plugandpaint/app/plugindialog.cpp 0 - - The \c findPlugins() is very similar to \c - MainWindow::loadPlugins(). It uses QPluginLoader to access the - static and dynamic plugins. Its helper function \c - populateTreeWidget() uses \l qobject_cast() to find out which - interfaces are implemented by the plugins: - - \snippet tools/plugandpaint/app/plugindialog.cpp 1 - - \section1 Importing Static Plugins - - The \l{tools/plugandpaint/plugins/basictools}{Basic Tools} plugin - is built as a static plugin, to ensure that it is always - available to the application. This requires using the - Q_IMPORT_PLUGIN() macro somewhere in the application (in a \c - .cpp file) and specifying the plugin in the \c .pro file. - - For Plug & Paint, we have chosen to put Q_IMPORT_PLUGIN() in \c - main.cpp: - - \snippet tools/plugandpaint/app/main.cpp 0 - - The argument to Q_IMPORT_PLUGIN() is the plugin name, which corresponds - with the name of the class that declares metadata for the plugin with - Q_PLUGIN_METADATA(). - - In the \c .pro file, we need to specify the static library. - Here's the project file for building Plug & Paint: - - \snippet tools/plugandpaint/app/app.pro 0 - - The \c LIBS line variable specifies the library \c pnp_basictools - located in the \c ../plugandpaint/plugins/basictools directory. - (Although the \c LIBS syntax has a distinct Unix flavor, \c qmake - supports it on all platforms.) - - The \c CONFIG() code at the end is necessary for this example - because the example is part of the Qt distribution and Qt can be - configured to be built simultaneously in debug and in release - modes. You don't need to for your own plugin applications. - - This completes our review of the Plug & Paint application. At - this point, you might want to take a look at the - \l{tools/plugandpaint/plugins/basictools}{Basic Tools} example - plugin. -*/ - -/*! - \example tools/plugandpaint/plugins/basictools - \title Plug & Paint Basic Tools Example - \brief A plugin providing the basic tools for painting functionality. - - \image plugandpaint.png Screenshot of the Plug & Paint example - - The Basic Tools example is a static plugin for the - \l{tools/plugandpaint/app}{Plug & Paint} example. It provides a set - of basic brushes, shapes, and filters. Through the Basic Tools - example, we will review the four steps involved in writing a Qt - plugin: - - \list 1 - \li Declare a plugin class. - \li Implement the interfaces provided by the plugin. - \li Export the plugin using the Q_PLUGIN_METADATA() macro. - \li Build the plugin using an adequate \c .pro file. - \endlist - - \section1 Declaration of the Plugin Class - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.h 0 - - We start by including \c interfaces.h, which defines the plugin - interfaces for the \l{tools/plugandpaint/app}{Plug & Paint} - application. For the \c #include to work, we need to add an \c - INCLUDEPATH entry to the \c .pro file with the path to the - header file. - - The \c BasicToolsPlugin class is a QObject subclass that - implements the \c BrushInterface, the \c ShapeInterface, and the - \c FilterInterface. This is done through multiple inheritance. - The \c Q_INTERFACES() macro is necessary to tell \l{moc}, Qt's - meta-object compiler, that the base classes are plugin - interfaces. Without the \c Q_INTERFACES() macro, we couldn't use - \l qobject_cast() in the \l{tools/plugandpaint/app}{Plug & Paint} - application to detect interfaces. - For an explanation for the \c Q_PLUGIN_METADATA() macro see - \l {Exporting the Plugin}. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.h 2 - - In the \c public section of the class, we declare all the - functions from the three interfaces. - - \section1 Implementation of the Brush Interface - - Let's now review the implementation of the \c BasicToolsPlugin - member functions inherited from \c BrushInterface. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 0 - - The \c brushes() function returns a list of brushes provided by - this plugin. We provide three brushes: \uicontrol{Pencil}, \uicontrol{Air - Brush}, and \uicontrol{Random Letters}. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 1 - - On a mouse press event, we just call \c mouseMove() to draw the - spot where the event occurred. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 2 - - In \c mouseMove(), we start by saving the state of the QPainter - and we compute a few variables that we'll need later. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 3 - - Then comes the brush-dependent part of the code: - - \list - \li If the brush is \uicontrol{Pencil}, we just call - QPainter::drawLine() with the current QPen. - - \li If the brush is \uicontrol{Air Brush}, we start by setting the - painter's QBrush to Qt::Dense6Pattern to obtain a dotted - pattern. Then we draw a circle filled with that QBrush several - times, resulting in a thick line. - - \li If the brush is \uicontrol{Random Letters}, we draw a random letter - at the new cursor position. Most of the code is for setting - the font to be bold and larger than the default font and for - computing an appropriate bounding rect. - \endlist - - At the end, we restore the painter state to what it was upon - entering the function and we return the bounding rectangle. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 4 - - When the user releases the mouse, we do nothing and return an - empty QRect. - - \section1 Implementation of the Shape Interface - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 5 - - The plugin provides three shapes: \uicontrol{Circle}, \uicontrol{Star}, and - \uicontrol{Text...}. The three dots after \uicontrol{Text} are there because - the shape pops up a dialog asking for more information. We know - that the shape names will end up in a menu, so we include the - three dots in the shape name. - - A cleaner but more complicated design would have been to - distinguish between the internal shape name and the name used in - the user interface. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 6 - - The \c generateShape() creates a QPainterPath for the specified - shape. If the shape is \uicontrol{Text}, we pop up a QInputDialog to - let the user enter some text. - - \section1 Implementation of the Filter Interface - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 7 - - The plugin provides three filters: \uicontrol{Invert Pixels}, \uicontrol{Swap - RGB}, and \uicontrol{Grayscale}. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 8 - - The \c filterImage() function takes a filter name and a QImage as - parameters and returns an altered QImage. The first thing we do - is to convert the image to a 32-bit RGB format, to ensure that - the algorithms will work as expected. For example, - QImage::invertPixels(), which is used to implement the - \uicontrol{Invert Pixels} filter, gives counterintuitive results for - 8-bit images, because they invert the indices into the color - table instead of inverting the color table's entries. - - \section1 Exporting the Plugin - - To finally export your plugin you just have to add the - \c Q_PLUGIN_METADATA() macro right next to the \c Q_OBJECT() macro - into the header file of the plugin. - It must contain the plugins IID and optionally a filename pointing - to a json file containing the metadata for the plugin. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.h 4 - - Within this example the json file does not need to export any metadata, - so it just contains an empty json object. - - \code - {} - \endcode - - \section1 The .pro File - - Here's the project file for building the Basic Tools plugin: - - \snippet tools/plugandpaint/plugins/basictools/basictools.pro 0 - - The \c .pro file differs from typical \c .pro files in many - respects. First, it starts with a \c TEMPLATE entry specifying \c - lib. (The default template is \c app.) It also adds \c plugin to - the \c CONFIG variable. This is necessary on some platforms to - avoid generating symbolic links with version numbers in the file - name, which is appropriate for most dynamic libraries but not for - plugins. - - To make the plugin a static plugin, all that is required is to - specify \c static in addition to \c plugin. The - \l{tools/plugandpaint/plugins/extrafilters}{Extra Filters} plugin, - which is compiled as a dynamic plugin, doesn't specify \c static - in its \c .pro file. - - The \c INCLUDEPATH variable sets the search paths for global - headers (i.e., header files included using \c{#include <...>}). - We add \c ../../app to the list, so that we can include - \c <interfaces.h>. - - The \c TARGET variable specifies which name we want to give the - target library. We use \c pnp_ as the prefix to show that the - plugin is designed to work with Plug & Paint. On Unix, \c lib is - also prepended to that name. On all platforms, a - platform-specific suffix is appended (e.g., \c .dll on Windows, - \c .a on Linux). - - The \c CONFIG() code at the end is necessary for this example - because the example is part of the Qt distribution and Qt can be - configured to be built simultaneously in debug and in release - modes. You don't need to for your own plugins. -*/ - -/*! - \example tools/plugandpaint/plugins/extrafilters - \title Plug & Paint Extra Filters Example - \brief A plugin providing the extra filters. - - \image plugandpaint.png Screenshot of the Plug & Paint example - - The Extra Filters example is a plugin for the - \l{tools/plugandpaint/app}{Plug & Paint} example. It provides a set - of filters in addition to those provided by the - \l{tools/plugandpaint/plugins/basictools}{Basic Tools} plugin. - - Since the approach is identical to - \l{tools/plugandpaint/plugins/basictools}{Basic Tools}, we won't - review the code here. The only part of interest is the - \c .pro file, since Extra Filters is a dynamic plugin - (\l{tools/plugandpaint/plugins/basictools}{Basic Tools} is - linked statically into the Plug & Paint executable). - - Here's the project file for building the Extra Filters plugin: - - \snippet tools/plugandpaint/plugins/extrafilters/extrafilters.pro 0 - - The \c .pro file differs from typical \c .pro files in many - respects. First, it starts with a \c TEMPLATE entry specifying \c - lib. (The default template is \c app.) It also adds \c plugin to - the \c CONFIG variable. This is necessary on some platforms to - avoid generating symbolic links with version numbers in the file - name, which is appropriate for most dynamic libraries but not for - plugins. - - The \c INCLUDEPATH variable sets the search paths for global - headers (i.e., header files included using \c{#include <...>}). - We add \c ../../app to the list, so that we can include - \c <interfaces.h>. - - The \c TARGET variable specifies which name we want to give the - target library. We use \c pnp_ as the prefix to show that the - plugin is designed to work with Plug & Paint. On Unix, \c lib is - also prepended to that name. On all platforms, a - platform-specific suffix is appended (e.g., \c .dll on Windows, - \c .so on Linux). - - The \c DESTDIR variable specifies where we want to install the - plugin. We put it in Plug & Paint's \c plugins subdirectory, - since that's where the application looks for dynamic plugins. - - The \c CONFIG() code at the end is necessary for this example - because the example is part of the Qt distribution and Qt can be - configured to be built simultaneously in debug and in release - modes. You don't need to for your own plugins. -*/ diff --git a/examples/widgets/doc/src/styleplugin.qdoc b/examples/widgets/doc/src/styleplugin.qdoc index d7a1faf2ca..f08a8725c2 100644 --- a/examples/widgets/doc/src/styleplugin.qdoc +++ b/examples/widgets/doc/src/styleplugin.qdoc @@ -133,7 +133,4 @@ In the \l{Echo Plugin Example}{echo plugin example} we show how to implement plugins that extends Qt applications rather than Qt itself, which is the case with the style plugin of this example. - The \l{Plug & Paint Example}{plug & paint} example shows how to - implement a static plugin as well as being a more involved example - on plugins that extend applications. */ diff --git a/examples/widgets/tools/CMakeLists.txt b/examples/widgets/tools/CMakeLists.txt index edf951fe18..1d0f35e155 100644 --- a/examples/widgets/tools/CMakeLists.txt +++ b/examples/widgets/tools/CMakeLists.txt @@ -11,8 +11,4 @@ qt_internal_add_example(undoframework) if(QT_FEATURE_library) qt_internal_add_example(echoplugin) - - if(QT_FEATURE_inputdialog) - qt_internal_add_example(plugandpaint) - endif() endif() diff --git a/examples/widgets/tools/plugandpaint/CMakeLists.txt b/examples/widgets/tools/plugandpaint/CMakeLists.txt deleted file mode 100644 index 61b7ad728e..0000000000 --- a/examples/widgets/tools/plugandpaint/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(plugandpaint LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tools/plugandpaint") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -add_subdirectory(plugins) -add_subdirectory(app) diff --git a/examples/widgets/tools/plugandpaint/app/CMakeLists.txt b/examples/widgets/tools/plugandpaint/app/CMakeLists.txt deleted file mode 100644 index c0368e7ba2..0000000000 --- a/examples/widgets/tools/plugandpaint/app/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -qt_add_executable(plugandpaint - interfaces.h - main.cpp - mainwindow.cpp mainwindow.h - paintarea.cpp paintarea.h - plugindialog.cpp plugindialog.h -) - -set_target_properties(plugandpaint PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(plugandpaint PRIVATE - Qt6::Widgets - pnp_basictools -) - -if(QT6_IS_SHARED_LIBS_BUILD) - # Build the shared plugin too when building this example target. - add_dependencies(plugandpaint pnp_extrafilters) -else() - # Link the extrafilters plugin if Qt is built statically. - target_link_libraries(plugandpaint PRIVATE - pnp_extrafilters - ) -endif() - -install(TARGETS plugandpaint - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tools/plugandpaint/app/app.pro b/examples/widgets/tools/plugandpaint/app/app.pro deleted file mode 100644 index e5ff02ecf2..0000000000 --- a/examples/widgets/tools/plugandpaint/app/app.pro +++ /dev/null @@ -1,37 +0,0 @@ -#! [0] -TARGET = plugandpaint -DESTDIR = .. - -QT += widgets - -HEADERS = interfaces.h \ - mainwindow.h \ - paintarea.h \ - plugindialog.h -SOURCES = main.cpp \ - mainwindow.cpp \ - paintarea.cpp \ - plugindialog.cpp - -LIBS = -L../plugins - -macx-xcode { - LIBS += -lpnp_basictools$($${QMAKE_XCODE_LIBRARY_SUFFIX_SETTING}) -} else { - android { - LIBS += -lpnp_basictools_$${QT_ARCH} - } else { - LIBS += -lpnp_basictools - } - if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { - mac:LIBS = $$member(LIBS, 0) $$member(LIBS, 1)_debug - win32:LIBS = $$member(LIBS, 0) $$member(LIBS, 1)d - } -} -#! [0] - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint -INSTALLS += target - -CONFIG += install_ok # Do not cargo-cult this! diff --git a/examples/widgets/tools/plugandpaint/app/interfaces.h b/examples/widgets/tools/plugandpaint/app/interfaces.h deleted file mode 100644 index 9cd0e34fda..0000000000 --- a/examples/widgets/tools/plugandpaint/app/interfaces.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef INTERFACES_H -#define INTERFACES_H - -#include <QtPlugin> - -QT_BEGIN_NAMESPACE -class QImage; -class QPainter; -class QWidget; -class QPainterPath; -class QPoint; -class QRect; -class QString; -QT_END_NAMESPACE - -//! [0] -class BrushInterface -{ -public: - virtual ~BrushInterface() = default; - - virtual QStringList brushes() const = 0; - virtual QRect mousePress(const QString &brush, QPainter &painter, - const QPoint &pos) = 0; - virtual QRect mouseMove(const QString &brush, QPainter &painter, - const QPoint &oldPos, const QPoint &newPos) = 0; - virtual QRect mouseRelease(const QString &brush, QPainter &painter, - const QPoint &pos) = 0; -}; -//! [0] - -//! [1] -class ShapeInterface -{ -public: - virtual ~ShapeInterface() = default; - - virtual QStringList shapes() const = 0; - virtual QPainterPath generateShape(const QString &shape, - QWidget *parent) = 0; -}; -//! [1] - -//! [2] -class FilterInterface -{ -public: - virtual ~FilterInterface() = default; - - virtual QStringList filters() const = 0; - virtual QImage filterImage(const QString &filter, const QImage &image, - QWidget *parent) = 0; -}; -//! [2] - -QT_BEGIN_NAMESPACE -//! [3] //! [4] -#define BrushInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface/1.0" - -Q_DECLARE_INTERFACE(BrushInterface, BrushInterface_iid) -//! [3] - -#define ShapeInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.ShapeInterface/1.0" - -Q_DECLARE_INTERFACE(ShapeInterface, ShapeInterface_iid) -//! [5] -#define FilterInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface/1.0" - -Q_DECLARE_INTERFACE(FilterInterface, FilterInterface_iid) -//! [4] //! [5] -QT_END_NAMESPACE - -#endif diff --git a/examples/widgets/tools/plugandpaint/app/main.cpp b/examples/widgets/tools/plugandpaint/app/main.cpp deleted file mode 100644 index 3fc647dcca..0000000000 --- a/examples/widgets/tools/plugandpaint/app/main.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -//! [0] -#include "mainwindow.h" - -#include <QApplication> -#include <QtPlugin> - -Q_IMPORT_PLUGIN(BasicToolsPlugin) - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - MainWindow window; - window.show(); - return app.exec(); -} -//! [0] diff --git a/examples/widgets/tools/plugandpaint/app/mainwindow.cpp b/examples/widgets/tools/plugandpaint/app/mainwindow.cpp deleted file mode 100644 index 8e58ae4ba8..0000000000 --- a/examples/widgets/tools/plugandpaint/app/mainwindow.cpp +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - - -#include "mainwindow.h" -#include "interfaces.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); -} - -//! [0] -void MainWindow::changeBrush() -{ - auto action = qobject_cast<QAction *>(sender()); - if (!action) - return; - auto iBrush = qobject_cast<BrushInterface *>(action->parent()); - if (!iBrush) - return; - const QString brush = action->text(); - - paintArea->setBrush(iBrush, brush); -} -//! [0] - -//! [1] -void MainWindow::insertShape() -{ - auto action = qobject_cast<QAction *>(sender()); - if (!action) - return; - auto iShape = qobject_cast<ShapeInterface *>(action->parent()); - if (!iShape) - return; - - const QPainterPath path = iShape->generateShape(action->text(), this); - if (!path.isEmpty()) - paintArea->insertShape(path); -} -//! [1] - -//! [2] -void MainWindow::applyFilter() -{ - auto action = qobject_cast<QAction *>(sender()); - if (!action) - return; - auto iFilter = qobject_cast<FilterInterface *>(action->parent()); - if (!iFilter) - return; - - const QImage image = iFilter->filterImage(action->text(), paintArea->image(), - this); - paintArea->setImage(image); -} -//! [2] - -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.")); -} - -//! [3] -void MainWindow::aboutPlugins() -{ - PluginDialog dialog(pluginsDir.path(), pluginFileNames, this); - dialog.exec(); -} -//! [3] - -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); -} - -//! [4] -void MainWindow::loadPlugins() -{ - const auto staticInstances = QPluginLoader::staticInstances(); - for (QObject *plugin : staticInstances) - populateMenus(plugin); -//! [4] //! [5] - - pluginsDir = QDir(QCoreApplication::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"); -//! [5] - -//! [6] - 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; -//! [6] //! [7] - } -//! [7] //! [8] - } -//! [8] - -//! [9] - brushMenu->setEnabled(!brushActionGroup->actions().isEmpty()); - shapesMenu->setEnabled(!shapesMenu->actions().isEmpty()); - filterMenu->setEnabled(!filterMenu->actions().isEmpty()); -} -//! [9] - -//! [10] -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); -} -//! [10] - -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); - } - } -} diff --git a/examples/widgets/tools/plugandpaint/app/mainwindow.h b/examples/widgets/tools/plugandpaint/app/mainwindow.h deleted file mode 100644 index bc09471ba5..0000000000 --- a/examples/widgets/tools/plugandpaint/app/mainwindow.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include <QDir> -#include <QMainWindow> -#include <QStringList> - -QT_BEGIN_NAMESPACE -class QAction; -class QActionGroup; -class QMenu; -class QScrollArea; -QT_END_NAMESPACE -class PaintArea; - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(); - -private slots: - void open(); - bool saveAs(); - void brushColor(); - void brushWidth(); - void changeBrush(); - void insertShape(); - void applyFilter(); - void about(); - void aboutPlugins(); - -private: - typedef void (MainWindow::*Member)(); - - void createActions(); - void createMenus(); - void loadPlugins(); - void populateMenus(QObject *plugin); - void addToMenu(QObject *plugin, const QStringList &texts, QMenu *menu, - Member member, QActionGroup *actionGroup = nullptr); - - PaintArea *paintArea = nullptr; - QScrollArea *scrollArea = nullptr; - QDir pluginsDir; - QStringList pluginFileNames; - - QMenu *fileMenu = nullptr; - QMenu *brushMenu = nullptr; - QMenu *shapesMenu = nullptr; - QMenu *filterMenu = nullptr; - QMenu *helpMenu = nullptr; - QActionGroup *brushActionGroup = nullptr; - QAction *openAct = nullptr; - QAction *saveAsAct = nullptr; - QAction *exitAct = nullptr; - QAction *brushWidthAct = nullptr; - QAction *brushColorAct = nullptr; - QAction *aboutAct = nullptr; - QAction *aboutQtAct = nullptr; - QAction *aboutPluginsAct = nullptr; -}; - -#endif diff --git a/examples/widgets/tools/plugandpaint/app/paintarea.cpp b/examples/widgets/tools/plugandpaint/app/paintarea.cpp deleted file mode 100644 index 3596f7979c..0000000000 --- a/examples/widgets/tools/plugandpaint/app/paintarea.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - - -#include "paintarea.h" -#include "interfaces.h" - -#include <QMouseEvent> -#include <QPainter> - -PaintArea::PaintArea(QWidget *parent) : QWidget(parent) -{ - setAttribute(Qt::WA_StaticContents); - setAttribute(Qt::WA_OpaquePaintEvent); - - theImage.fill(qRgb(255, 255, 255)); -} - -bool PaintArea::openImage(const QString &fileName) -{ - QImage image; - if (!image.load(fileName)) - return false; - - setImage(image); - return true; -} - -bool PaintArea::saveImage(const QString &fileName, const char *fileFormat) -{ - return theImage.save(fileName, fileFormat); -} - -void PaintArea::setImage(const QImage &image) -{ - theImage = image.convertToFormat(QImage::Format_RGB32); - update(); - updateGeometry(); -} - -void PaintArea::insertShape(const QPainterPath &path) -{ - pendingPath = path; -#ifndef QT_NO_CURSOR - setCursor(Qt::CrossCursor); -#endif -} - -void PaintArea::setBrushColor(const QColor &color) -{ - this->color = color; -} - -void PaintArea::setBrushWidth(int width) -{ - thickness = width; -} - -//! [0] -void PaintArea::setBrush(BrushInterface *brushInterface, const QString &brush) -{ - this->brushInterface = brushInterface; - this->brush = brush; -} -//! [0] - -QSize PaintArea::sizeHint() const -{ - return theImage.size(); -} - -void PaintArea::paintEvent(QPaintEvent * /* event */) -{ - QPainter painter(this); - painter.drawImage(QPoint(0, 0), theImage); -} - -void PaintArea::mousePressEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) { - if (!pendingPath.isEmpty()) { - QPainter painter(&theImage); - setupPainter(painter); - - const QRectF boundingRect = pendingPath.boundingRect(); - QLinearGradient gradient(boundingRect.topRight(), - boundingRect.bottomLeft()); - gradient.setColorAt(0.0, QColor(color.red(), color.green(), - color.blue(), 63)); - gradient.setColorAt(1.0, QColor(color.red(), color.green(), - color.blue(), 191)); - painter.setBrush(gradient); - painter.translate(event->position().toPoint() - boundingRect.center()); - painter.drawPath(pendingPath); - - pendingPath = QPainterPath(); -#ifndef QT_NO_CURSOR - unsetCursor(); -#endif - update(); - } else { - if (brushInterface) { - QPainter painter(&theImage); - setupPainter(painter); - const QRect rect = brushInterface->mousePress(brush, painter, - event->position().toPoint()); - update(rect); - } - - lastPos = event->position().toPoint(); - } - } -} - -//! [1] -void PaintArea::mouseMoveEvent(QMouseEvent *event) -{ - if ((event->buttons() & Qt::LeftButton) && lastPos != QPoint(-1, -1)) { - if (brushInterface) { - QPainter painter(&theImage); - setupPainter(painter); - const QRect rect = brushInterface->mouseMove(brush, painter, lastPos, - event->position().toPoint()); - update(rect); - } - - lastPos = event->position().toPoint(); - } -} -//! [1] - -void PaintArea::mouseReleaseEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton && lastPos != QPoint(-1, -1)) { - if (brushInterface) { - QPainter painter(&theImage); - setupPainter(painter); - QRect rect = brushInterface->mouseRelease(brush, painter, - event->position().toPoint()); - update(rect); - } - - lastPos = QPoint(-1, -1); - } -} - -void PaintArea::setupPainter(QPainter &painter) -{ - painter.setRenderHint(QPainter::Antialiasing, true); - painter.setPen(QPen(color, thickness, Qt::SolidLine, Qt::RoundCap, - Qt::RoundJoin)); -} diff --git a/examples/widgets/tools/plugandpaint/app/paintarea.h b/examples/widgets/tools/plugandpaint/app/paintarea.h deleted file mode 100644 index f24db0ba89..0000000000 --- a/examples/widgets/tools/plugandpaint/app/paintarea.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef PAINTAREA_H -#define PAINTAREA_H - -#include <QColor> -#include <QImage> -#include <QPainterPath> -#include <QWidget> - -class BrushInterface; - -class PaintArea : public QWidget -{ - Q_OBJECT - -public: - PaintArea(QWidget *parent = nullptr); - - bool openImage(const QString &fileName); - bool saveImage(const QString &fileName, const char *fileFormat); - void setImage(const QImage &image); - void insertShape(const QPainterPath &path); - void setBrushColor(const QColor &color); - void setBrushWidth(int width); - void setBrush(BrushInterface *brushInterface, const QString &brush); - - QImage image() const { return theImage; } - QColor brushColor() const { return color; } - int brushWidth() const { return thickness; } - QSize sizeHint() const override; - -protected: - void paintEvent(QPaintEvent *event) override; - void mousePressEvent(QMouseEvent *event) override; - void mouseMoveEvent(QMouseEvent *event) override; - void mouseReleaseEvent(QMouseEvent *event) override; - -private: - void setupPainter(QPainter &painter); - - QImage theImage = {500, 400, QImage::Format_RGB32}; - QColor color = Qt::blue; - int thickness = 3; - - BrushInterface *brushInterface = nullptr; - QString brush; - QPoint lastPos = {-1, -1}; - - QPainterPath pendingPath; -}; - -#endif diff --git a/examples/widgets/tools/plugandpaint/app/plugindialog.cpp b/examples/widgets/tools/plugandpaint/app/plugindialog.cpp deleted file mode 100644 index 2ff5c4b1e3..0000000000 --- a/examples/widgets/tools/plugandpaint/app/plugindialog.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - - -#include "plugindialog.h" -#include "interfaces.h" - -#include <QDir> -#include <QGridLayout> -#include <QHeaderView> -#include <QLabel> -#include <QPluginLoader> -#include <QPushButton> -#include <QStringList> -#include <QTreeWidget> -#include <QTreeWidgetItem> - -PluginDialog::PluginDialog(const QString &path, const QStringList &fileNames, - QWidget *parent) : - QDialog(parent), - label(new QLabel), - treeWidget(new QTreeWidget), - okButton(new QPushButton(tr("OK"))) -{ - treeWidget->setAlternatingRowColors(false); - treeWidget->setSelectionMode(QAbstractItemView::NoSelection); - treeWidget->setColumnCount(1); - treeWidget->header()->hide(); - - okButton->setDefault(true); - - connect(okButton, &QAbstractButton::clicked, this, &QWidget::close); - - QGridLayout *mainLayout = new QGridLayout; - mainLayout->setColumnStretch(0, 1); - mainLayout->setColumnStretch(2, 1); - mainLayout->addWidget(label, 0, 0, 1, 3); - mainLayout->addWidget(treeWidget, 1, 0, 1, 3); - mainLayout->addWidget(okButton, 2, 1); - setLayout(mainLayout); - - interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon), - QIcon::Normal, QIcon::On); - interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon), - QIcon::Normal, QIcon::Off); - featureIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon)); - - setWindowTitle(tr("Plugin Information")); - findPlugins(path, fileNames); -} - -//! [0] -void PluginDialog::findPlugins(const QString &path, - const QStringList &fileNames) -{ - label->setText(tr("Plug & Paint found the following plugins\n" - "(looked in %1):") - .arg(QDir::toNativeSeparators(path))); - - const QDir dir(path); - - const auto staticInstances = QPluginLoader::staticInstances(); - for (QObject *plugin : staticInstances) - populateTreeWidget(plugin, tr("%1 (Static Plugin)") - .arg(plugin->metaObject()->className())); - - for (const QString &fileName : fileNames) { - QPluginLoader loader(dir.absoluteFilePath(fileName)); - QObject *plugin = loader.instance(); - if (plugin) - populateTreeWidget(plugin, fileName); - } -} -//! [0] - -//! [1] -void PluginDialog::populateTreeWidget(QObject *plugin, const QString &text) -{ - auto pluginItem = new QTreeWidgetItem(treeWidget); - pluginItem->setText(0, text); - pluginItem->setExpanded(true); - - QFont boldFont = pluginItem->font(0); - boldFont.setBold(true); - pluginItem->setFont(0, boldFont); - - if (plugin) { - auto iBrush = qobject_cast<BrushInterface *>(plugin); - if (iBrush) - addItems(pluginItem, "BrushInterface", iBrush->brushes()); - - auto iShape = qobject_cast<ShapeInterface *>(plugin); - if (iShape) - addItems(pluginItem, "ShapeInterface", iShape->shapes()); - - auto iFilter = qobject_cast<FilterInterface *>(plugin); - if (iFilter) - addItems(pluginItem, "FilterInterface", iFilter->filters()); - } -} -//! [1] - -void PluginDialog::addItems(QTreeWidgetItem *pluginItem, - const char *interfaceName, - const QStringList &features) -{ - auto interfaceItem = new QTreeWidgetItem(pluginItem); - interfaceItem->setText(0, interfaceName); - interfaceItem->setIcon(0, interfaceIcon); - - for (QString feature : features) { - if (feature.endsWith("...")) - feature.chop(3); - auto featureItem = new QTreeWidgetItem(interfaceItem); - featureItem->setText(0, feature); - featureItem->setIcon(0, featureIcon); - } -} diff --git a/examples/widgets/tools/plugandpaint/app/plugindialog.h b/examples/widgets/tools/plugandpaint/app/plugindialog.h deleted file mode 100644 index 32b8aa6fe0..0000000000 --- a/examples/widgets/tools/plugandpaint/app/plugindialog.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef PLUGINDIALOG_H -#define PLUGINDIALOG_H - -#include <QDialog> -#include <QIcon> - -QT_BEGIN_NAMESPACE -class QLabel; -class QPushButton; -class QTreeWidget; -class QTreeWidgetItem; -QT_END_NAMESPACE - -class PluginDialog : public QDialog -{ - Q_OBJECT - -public: - PluginDialog(const QString &path, const QStringList &fileNames, - QWidget *parent = nullptr); - -private: - void findPlugins(const QString &path, const QStringList &fileNames); - void populateTreeWidget(QObject *plugin, const QString &text); - void addItems(QTreeWidgetItem *pluginItem, const char *interfaceName, - const QStringList &features); - - QLabel *label = nullptr; - QTreeWidget *treeWidget = nullptr; - QPushButton *okButton = nullptr; - QIcon interfaceIcon; - QIcon featureIcon; -}; - -#endif diff --git a/examples/widgets/tools/plugandpaint/plugandpaint.pro b/examples/widgets/tools/plugandpaint/plugandpaint.pro deleted file mode 100644 index 58c4dbbb6e..0000000000 --- a/examples/widgets/tools/plugandpaint/plugandpaint.pro +++ /dev/null @@ -1,7 +0,0 @@ -QT_FOR_CONFIG += widgets -requires(qtConfig(inputdialog)) - -TEMPLATE = subdirs -SUBDIRS = plugins app - -app.depends = plugins diff --git a/examples/widgets/tools/plugandpaint/plugins/CMakeLists.txt b/examples/widgets/tools/plugandpaint/plugins/CMakeLists.txt deleted file mode 100644 index 9a2d66d99e..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(basictools) -add_subdirectory(extrafilters) diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/CMakeLists.txt b/examples/widgets/tools/plugandpaint/plugins/basictools/CMakeLists.txt deleted file mode 100644 index 86d58b9f08..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/basictools/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -qt_add_plugin(pnp_basictools - STATIC - CLASS_NAME BasicToolsPlugin - basictoolsplugin.cpp basictoolsplugin.h -) - -target_include_directories(pnp_basictools PRIVATE - ../../app -) - -target_link_libraries(pnp_basictools PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.json b/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro b/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro deleted file mode 100644 index f5ba95252c..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro +++ /dev/null @@ -1,17 +0,0 @@ -#! [0] -TEMPLATE = lib -CONFIG += plugin static -QT += widgets -INCLUDEPATH += ../../app -HEADERS = basictoolsplugin.h -SOURCES = basictoolsplugin.cpp -TARGET = $$qtLibraryTarget(pnp_basictools) -DESTDIR = ../../plugins -#! [0] - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint/plugins -INSTALLS += target - -CONFIG += install_ok # Do not cargo-cult this! -uikit: CONFIG += debug_and_release diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp deleted file mode 100644 index 6a350f38a4..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include "basictoolsplugin.h" - -#include <QInputDialog> -#include <QPainter> -#include <QRandomGenerator> -#include <QtMath> - -//! [0] -QStringList BasicToolsPlugin::brushes() const -{ - return {tr("Pencil"), tr("Air Brush"), tr("Random Letters")}; -} -//! [0] - -//! [1] -QRect BasicToolsPlugin::mousePress(const QString &brush, QPainter &painter, - const QPoint &pos) -{ - return mouseMove(brush, painter, pos, pos); -} -//! [1] - -//! [2] -QRect BasicToolsPlugin::mouseMove(const QString &brush, QPainter &painter, - const QPoint &oldPos, const QPoint &newPos) -{ - painter.save(); - - int rad = painter.pen().width() / 2; - QRect boundingRect = QRect(oldPos, newPos).normalized() - .adjusted(-rad, -rad, +rad, +rad); - QColor color = painter.pen().color(); - int thickness = painter.pen().width(); - QColor transparentColor(color.red(), color.green(), color.blue(), 0); -//! [2] //! [3] - - if (brush == tr("Pencil")) { - painter.drawLine(oldPos, newPos); - } else if (brush == tr("Air Brush")) { - int numSteps = 2 + (newPos - oldPos).manhattanLength() / 2; - - painter.setBrush(QBrush(color, Qt::Dense6Pattern)); - painter.setPen(Qt::NoPen); - - for (int i = 0; i < numSteps; ++i) { - int x = oldPos.x() + i * (newPos.x() - oldPos.x()) / (numSteps - 1); - int y = oldPos.y() + i * (newPos.y() - oldPos.y()) / (numSteps - 1); - - painter.drawEllipse(x - (thickness / 2), y - (thickness / 2), - thickness, thickness); - } - } else if (brush == tr("Random Letters")) { - QChar ch(QRandomGenerator::global()->bounded('A', 'Z' + 1)); - - QFont biggerFont = painter.font(); - biggerFont.setBold(true); - biggerFont.setPointSize(biggerFont.pointSize() + thickness); - painter.setFont(biggerFont); - - painter.drawText(newPos, QString(ch)); - - QFontMetrics metrics(painter.font()); - boundingRect = metrics.boundingRect(ch); - boundingRect.translate(newPos); - boundingRect.adjust(-10, -10, +10, +10); - } - painter.restore(); - return boundingRect; -} -//! [3] - -//! [4] -QRect BasicToolsPlugin::mouseRelease(const QString & /* brush */, - QPainter & /* painter */, - const QPoint & /* pos */) -{ - return QRect(0, 0, 0, 0); -} -//! [4] - -//! [5] -QStringList BasicToolsPlugin::shapes() const -{ - return {tr("Circle"), tr("Star"), tr("Text...")}; -} -//! [5] - -//! [6] -QPainterPath BasicToolsPlugin::generateShape(const QString &shape, - QWidget *parent) -{ - QPainterPath path; - - if (shape == tr("Circle")) { - path.addEllipse(0, 0, 50, 50); - } else if (shape == tr("Star")) { - path.moveTo(90, 50); - for (int i = 1; i < 5; ++i) { - path.lineTo(50 + 40 * std::cos(0.8 * i * M_PI), - 50 + 40 * std::sin(0.8 * i * M_PI)); - } - path.closeSubpath(); - } else if (shape == tr("Text...")) { - QString text = QInputDialog::getText(parent, tr("Text Shape"), - tr("Enter text:"), - QLineEdit::Normal, tr("Qt")); - if (!text.isEmpty()) { - QFont timesFont("Times", 50); - timesFont.setStyleStrategy(QFont::ForceOutline); - path.addText(0, 0, timesFont, text); - } - } - - return path; -} -//! [6] - -//! [7] -QStringList BasicToolsPlugin::filters() const -{ - return {tr("Invert Pixels"), tr("Swap RGB"), tr("Grayscale")}; -} -//! [7] - -//! [8] -QImage BasicToolsPlugin::filterImage(const QString &filter, const QImage &image, - QWidget * /* parent */) -{ - QImage result = image.convertToFormat(QImage::Format_RGB32); - - if (filter == tr("Invert Pixels")) { - result.invertPixels(); - } else if (filter == tr("Swap RGB")) { - result = result.rgbSwapped(); - } else if (filter == tr("Grayscale")) { - for (int y = 0; y < result.height(); ++y) { - for (int x = 0; x < result.width(); ++x) { - QRgb pixel = result.pixel(x, y); - int gray = qGray(pixel); - int alpha = qAlpha(pixel); - result.setPixel(x, y, qRgba(gray, gray, gray, alpha)); - } - } - } - return result; -} -//! [8] diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h deleted file mode 100644 index 9fb3295bf5..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef BASICTOOLSPLUGIN_H -#define BASICTOOLSPLUGIN_H - -//! [0] -#include <interfaces.h> - -#include <QImage> -#include <QObject> -#include <QPainterPath> -#include <QRect> -#include <QStringList> -#include <QtPlugin> - -//! [1] -class BasicToolsPlugin : public QObject, - public BrushInterface, - public ShapeInterface, - public FilterInterface -{ - Q_OBJECT -//! [4] - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" FILE "basictools.json") -//! [4] - Q_INTERFACES(BrushInterface ShapeInterface FilterInterface) -//! [0] - -//! [2] -public: -//! [1] - // BrushInterface - QStringList brushes() const override; - QRect mousePress(const QString &brush, QPainter &painter, - const QPoint &pos) override; - QRect mouseMove(const QString &brush, QPainter &painter, - const QPoint &oldPos, const QPoint &newPos) override; - QRect mouseRelease(const QString &brush, QPainter &painter, - const QPoint &pos) override; - - // ShapeInterface - QStringList shapes() const override; - QPainterPath generateShape(const QString &shape, QWidget *parent) override; - - // FilterInterface - QStringList filters() const override; - QImage filterImage(const QString &filter, const QImage &image, - QWidget *parent) override; -//! [3] -}; -//! [2] //! [3] - -#endif diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/CMakeLists.txt b/examples/widgets/tools/plugandpaint/plugins/extrafilters/CMakeLists.txt deleted file mode 100644 index cc883df049..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/extrafilters/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -qt_add_plugin(pnp_extrafilters - CLASS_NAME ExtraFiltersPlugin - extrafiltersplugin.cpp extrafiltersplugin.h -) - -set_target_properties(pnp_extrafilters PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/app" -) - -target_include_directories(pnp_extrafilters PRIVATE - ../../app -) - -target_link_libraries(pnp_extrafilters PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS pnp_extrafilters - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}/plugins" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}/plugins" -) diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.json b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro deleted file mode 100644 index e137b04823..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro +++ /dev/null @@ -1,17 +0,0 @@ -#! [0] -TEMPLATE = lib -CONFIG += plugin -QT += widgets -INCLUDEPATH += ../../app -HEADERS = extrafiltersplugin.h -SOURCES = extrafiltersplugin.cpp -TARGET = $$qtLibraryTarget(pnp_extrafilters) -DESTDIR = ../../plugins - -#! [0] -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint/plugins -INSTALLS += target - -CONFIG += install_ok # Do not cargo-cult this! -uikit: CONFIG += debug_and_release diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.cpp b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.cpp deleted file mode 100644 index 5356efc328..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include "extrafiltersplugin.h" - -#include <QInputDialog> - -QStringList ExtraFiltersPlugin::filters() const -{ - return {tr("Flip Horizontally"), tr("Flip Vertically"), - tr("Smudge..."), tr("Threshold...")}; -} - -QImage ExtraFiltersPlugin::filterImage(const QString &filter, - const QImage &image, QWidget *parent) -{ - QImage original = image.convertToFormat(QImage::Format_RGB32); - QImage result = original; - - if (filter == tr("Flip Horizontally")) { - for (int y = 0; y < original.height(); ++y) { - for (int x = 0; x < original.width(); ++x) { - QRgb pixel = original.pixel(original.width() - x - 1, y); - result.setPixel(x, y, pixel); - } - } - } else if (filter == tr("Flip Vertically")) { - for (int y = 0; y < original.height(); ++y) { - for (int x = 0; x < original.width(); ++x) { - QRgb pixel = original.pixel(x, original.height() - y - 1); - result.setPixel(x, y, pixel); - } - } - } else if (filter == tr("Smudge...")) { - bool ok; - int numIters = QInputDialog::getInt(parent, tr("Smudge Filter"), - tr("Enter number of iterations:"), - 5, 1, 20, 1, &ok); - if (ok) { - for (int i = 0; i < numIters; ++i) { - for (int y = 1; y < original.height() - 1; ++y) { - for (int x = 1; x < original.width() - 1; ++x) { - QRgb p1 = original.pixel(x, y); - QRgb p2 = original.pixel(x, y + 1); - QRgb p3 = original.pixel(x, y - 1); - QRgb p4 = original.pixel(x + 1, y); - QRgb p5 = original.pixel(x - 1, y); - - int red = (qRed(p1) + qRed(p2) + qRed(p3) + qRed(p4) - + qRed(p5)) / 5; - int green = (qGreen(p1) + qGreen(p2) + qGreen(p3) - + qGreen(p4) + qGreen(p5)) / 5; - int blue = (qBlue(p1) + qBlue(p2) + qBlue(p3) - + qBlue(p4) + qBlue(p5)) / 5; - int alpha = (qAlpha(p1) + qAlpha(p2) + qAlpha(p3) - + qAlpha(p4) + qAlpha(p5)) / 5; - - result.setPixel(x, y, qRgba(red, green, blue, alpha)); - } - } - } - } - } else if (filter == tr("Threshold...")) { - bool ok; - int threshold = QInputDialog::getInt(parent, tr("Threshold Filter"), - tr("Enter threshold:"), - 10, 1, 256, 1, &ok); - if (ok) { - int factor = 256 / threshold; - for (int y = 0; y < original.height(); ++y) { - for (int x = 0; x < original.width(); ++x) { - QRgb pixel = original.pixel(x, y); - result.setPixel(x, y, qRgba(qRed(pixel) / factor * factor, - qGreen(pixel) / factor * factor, - qBlue(pixel) / factor * factor, - qAlpha(pixel))); - } - } - } - } - return result; -} diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.h b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.h deleted file mode 100644 index 0fc50d2fd0..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#ifndef EXTRAFILTERSPLUGIN_H -#define EXTRAFILTERSPLUGIN_H - -//! [0] -#include <interfaces.h> - -#include <QObject> -#include <QtPlugin> -#include <QStringList> -#include <QImage> - -class ExtraFiltersPlugin : public QObject, public FilterInterface -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" FILE "extrafilters.json") - Q_INTERFACES(FilterInterface) - -public: - QStringList filters() const override; - QImage filterImage(const QString &filter, const QImage &image, - QWidget *parent) override; -}; -//! [0] - -#endif diff --git a/examples/widgets/tools/plugandpaint/plugins/plugins.pro b/examples/widgets/tools/plugandpaint/plugins/plugins.pro deleted file mode 100644 index e15220c621..0000000000 --- a/examples/widgets/tools/plugandpaint/plugins/plugins.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = basictools \ - extrafilters diff --git a/examples/widgets/tools/tools.pro b/examples/widgets/tools/tools.pro index 4a9dce3412..09b693dc15 100644 --- a/examples/widgets/tools/tools.pro +++ b/examples/widgets/tools/tools.pro @@ -3,7 +3,6 @@ SUBDIRS = \ completer \ customcompleter \ echoplugin \ - plugandpaint \ regularexpression \ settingseditor \ styleplugin \ @@ -12,6 +11,5 @@ SUBDIRS = \ !qtConfig(library) { SUBDIRS -= \ - echoplugin \ - plugandpaint + echoplugin } |