Sophie

Sophie

distrib > Mageia > 6 > armv5tl > media > core-updates > by-pkgid > 768f7d9f703884aa2562bf0a651086df > files > 4317

qtbase5-doc-5.9.4-1.1.mga6.noarch.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- plugandpaint.qdoc -->
  <title>Plug &amp; Paint Example | Qt Widgets 5.9</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td >Qt 5.9</td><td ><a href="qtwidgets-index.html">Qt Widgets</a></td><td >Plug &amp; Paint Example</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right">Qt 5.9.4 Reference Documentation</td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#the-plugin-interfaces">The Plugin Interfaces</a></li>
<li class="level1"><a href="#the-mainwindow-class">The MainWindow Class</a></li>
<li class="level1"><a href="#the-paintarea-class">The PaintArea Class</a></li>
<li class="level1"><a href="#the-plugindialog-class">The PluginDialog Class</a></li>
<li class="level1"><a href="#importing-static-plugins">Importing Static Plugins</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Plug &amp; Paint Example</h1>
<span class="subtitle"></span>
<!-- $$$tools/plugandpaint/app-description -->
<div class="descr"> <a name="details"></a>
<p class="centerAlign"><img src="images/plugandpaint.png" alt="Screenshot of the Plug &amp; Paint example" /></p><p>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 <a href="../qtcore/qpluginloader.html">QPluginLoader</a>. To ensure that plugins don't get lost, it is also possible to link them statically to the executable. The Plug &amp; Paint example uses plugins to support custom brushes, shapes, and image filters. A single plugin can provide multiple brushes, shapes, and/or filters.</p>
<p>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 <a href="qtwidgets-tools-plugandpaint-plugins-basictools-example.html">Basic Tools</a> and <a href="qtwidgets-tools-plugandpaint-plugins-extrafilters-example.html">Extra Filters</a> overviews, which show how to implement static and dynamic plugins, respectively.</p>
<p>Plug &amp; Paint consists of the following classes:</p>
<ul>
<li><code>MainWindow</code> is a <a href="qmainwindow.html">QMainWindow</a> subclass that provides the menu system and that contains a <code>PaintArea</code> as the central widget.</li>
<li><code>PaintArea</code> is a <a href="qwidget.html">QWidget</a> that allows the user to draw using a brush and to insert shapes.</li>
<li><code>PluginDialog</code> is a dialog that shows information about the plugins detected by the application.</li>
<li><code>BrushInterface</code>, <code>ShapeInterface</code>, and <code>FilterInterface</code> are abstract base classes that can be implemented by plugins to provide custom brushes, shapes, and image filters.</li>
</ul>
<a name="the-plugin-interfaces"></a>
<h2 id="the-plugin-interfaces">The Plugin Interfaces</h2>
<p>We will start by reviewing the interfaces defined in <code>interfaces.h</code>. These interfaces are used by the Plug &amp; Paint application to access extra functionality. They are implemented in the plugins.</p>
<pre class="cpp">

  <span class="keyword">class</span> BrushInterface
  {
  <span class="keyword">public</span>:
      <span class="keyword">virtual</span> <span class="operator">~</span>BrushInterface() {}

      <span class="keyword">virtual</span> <span class="type"><a href="../qtcore/qstringlist.html">QStringList</a></span> brushes() <span class="keyword">const</span> <span class="operator">=</span> <span class="number">0</span>;
      <span class="keyword">virtual</span> <span class="type"><a href="../qtcore/qrect.html">QRect</a></span> mousePress(<span class="keyword">const</span> <span class="type"><a href="../qtcore/qstring.html">QString</a></span> <span class="operator">&amp;</span>brush<span class="operator">,</span> <span class="type"><a href="../qtgui/qpainter.html">QPainter</a></span> <span class="operator">&amp;</span>painter<span class="operator">,</span>
                               <span class="keyword">const</span> <span class="type"><a href="../qtcore/qpoint.html">QPoint</a></span> <span class="operator">&amp;</span>pos) <span class="operator">=</span> <span class="number">0</span>;
      <span class="keyword">virtual</span> <span class="type"><a href="../qtcore/qrect.html">QRect</a></span> mouseMove(<span class="keyword">const</span> <span class="type"><a href="../qtcore/qstring.html">QString</a></span> <span class="operator">&amp;</span>brush<span class="operator">,</span> <span class="type"><a href="../qtgui/qpainter.html">QPainter</a></span> <span class="operator">&amp;</span>painter<span class="operator">,</span>
                              <span class="keyword">const</span> <span class="type"><a href="../qtcore/qpoint.html">QPoint</a></span> <span class="operator">&amp;</span>oldPos<span class="operator">,</span> <span class="keyword">const</span> <span class="type"><a href="../qtcore/qpoint.html">QPoint</a></span> <span class="operator">&amp;</span>newPos) <span class="operator">=</span> <span class="number">0</span>;
      <span class="keyword">virtual</span> <span class="type"><a href="../qtcore/qrect.html">QRect</a></span> mouseRelease(<span class="keyword">const</span> <span class="type"><a href="../qtcore/qstring.html">QString</a></span> <span class="operator">&amp;</span>brush<span class="operator">,</span> <span class="type"><a href="../qtgui/qpainter.html">QPainter</a></span> <span class="operator">&amp;</span>painter<span class="operator">,</span>
                                 <span class="keyword">const</span> <span class="type"><a href="../qtcore/qpoint.html">QPoint</a></span> <span class="operator">&amp;</span>pos) <span class="operator">=</span> <span class="number">0</span>;
  };

</pre>
<p>The <code>BrushInterface</code> class declares four pure virtual functions. The first pure virtual function, <code>brushes()</code>, returns a list of strings that identify the brushes provided by the plugin. By returning a <a href="../qtcore/qstringlist.html">QStringList</a> instead of a <a href="../qtcore/qstring.html">QString</a>, we make it possible for a single plugin to provide multiple brushes. The other functions have a <code>brush</code> parameter to identify which brush (among those returned by <code>brushes()</code>) is used.</p>
<p><code>mousePress()</code>, <code>mouseMove()</code>, and <code>mouseRelease()</code> take a <a href="../qtgui/qpainter.html">QPainter</a> and one or two <a href="../qtcore/qpoint.html">QPoint</a>s, and return a <a href="../qtcore/qrect.html">QRect</a> identifying which portion of the image was altered by the brush.</p>
<p>The class also has a virtual destructor. Interface classes usually don't need such a destructor (because it would make little sense to <code>delete</code> 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.</p>
<pre class="cpp">

  <span class="keyword">class</span> ShapeInterface
  {
  <span class="keyword">public</span>:
      <span class="keyword">virtual</span> <span class="operator">~</span>ShapeInterface() {}

      <span class="keyword">virtual</span> <span class="type"><a href="../qtcore/qstringlist.html">QStringList</a></span> shapes() <span class="keyword">const</span> <span class="operator">=</span> <span class="number">0</span>;
      <span class="keyword">virtual</span> <span class="type"><a href="../qtgui/qpainterpath.html">QPainterPath</a></span> generateShape(<span class="keyword">const</span> <span class="type"><a href="../qtcore/qstring.html">QString</a></span> <span class="operator">&amp;</span>shape<span class="operator">,</span>
                                         <span class="type"><a href="qwidget.html">QWidget</a></span> <span class="operator">*</span>parent) <span class="operator">=</span> <span class="number">0</span>;
  };

</pre>
<p>The <code>ShapeInterface</code> class declares a <code>shapes()</code> function that works the same as <code>BrushInterface</code>'s <code>brushes()</code> function, and a <code>generateShape()</code> function that has a <code>shape</code> parameter. Shapes are represented by a <a href="../qtgui/qpainterpath.html">QPainterPath</a>, a data type that can represent arbitrary 2D shapes or combinations of shapes. The <code>parent</code> parameter can be used by the plugin to pop up a dialog asking the user to specify more information.</p>
<pre class="cpp">

  <span class="keyword">class</span> FilterInterface
  {
  <span class="keyword">public</span>:
      <span class="keyword">virtual</span> <span class="operator">~</span>FilterInterface() {}

      <span class="keyword">virtual</span> <span class="type"><a href="../qtcore/qstringlist.html">QStringList</a></span> filters() <span class="keyword">const</span> <span class="operator">=</span> <span class="number">0</span>;
      <span class="keyword">virtual</span> <span class="type"><a href="../qtgui/qimage.html">QImage</a></span> filterImage(<span class="keyword">const</span> <span class="type"><a href="../qtcore/qstring.html">QString</a></span> <span class="operator">&amp;</span>filter<span class="operator">,</span> <span class="keyword">const</span> <span class="type"><a href="../qtgui/qimage.html">QImage</a></span> <span class="operator">&amp;</span>image<span class="operator">,</span>
                                 <span class="type"><a href="qwidget.html">QWidget</a></span> <span class="operator">*</span>parent) <span class="operator">=</span> <span class="number">0</span>;
  };

</pre>
<p>The <code>FilterInterface</code> class declares a <code>filters()</code> function that returns a list of filter names, and a <code>filterImage()</code> function that applies a filter to an image.</p>
<pre class="cpp">

  <span class="preprocessor">#define BrushInterface_iid &quot;org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface&quot;</span>

  Q_DECLARE_INTERFACE(BrushInterface<span class="operator">,</span> BrushInterface_iid)

  <span class="preprocessor">#define ShapeInterface_iid  &quot;org.qt-project.Qt.Examples.PlugAndPaint.ShapeInterface&quot;</span>

  Q_DECLARE_INTERFACE(ShapeInterface<span class="operator">,</span> ShapeInterface_iid)
  <span class="preprocessor">#define FilterInterface_iid &quot;org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface&quot;</span>

  Q_DECLARE_INTERFACE(FilterInterface<span class="operator">,</span> FilterInterface_iid)

</pre>
<p>To make it possible to query at run-time whether a plugin implements a given interface, we must use the <code>Q_DECLARE_INTERFACE()</code> 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 &quot;Java package name&quot; 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.</p>
<p>The <a href="qtwidgets-tools-plugandpaint-plugins-basictools-example.html">Basic Tools</a> plugin and the <a href="qtwidgets-tools-plugandpaint-plugins-extrafilters-example.html">Extra Filters</a> plugin shows how to derive from <code>BrushInterface</code>, <code>ShapeInterface</code>, and <code>FilterInterface</code>.</p>
<p>A note on naming: It might have been tempting to give the <code>brushes()</code>, <code>shapes()</code>, and <code>filters()</code> functions a more generic name, such as <code>keys()</code> or <code>features()</code>. However, that would have made multiple inheritance impractical. When creating interfaces, we should always try to give unique names to the pure virtual functions.</p>
<a name="the-mainwindow-class"></a>
<h2 id="the-mainwindow-class">The MainWindow Class</h2>
<p>The <code>MainWindow</code> class is a standard <a href="qmainwindow.html">QMainWindow</a> subclass, as found in many of the other examples (e.g&#x2e;, <a href="qtwidgets-mainwindows-application-example.html">Application</a>). Here, we'll concentrate on the parts of the code that are related to plugins.</p>
<pre class="cpp">

  <span class="type">void</span> MainWindow<span class="operator">::</span>loadPlugins()
  {
      foreach (<span class="type"><a href="../qtcore/qobject.html">QObject</a></span> <span class="operator">*</span>plugin<span class="operator">,</span> <span class="type"><a href="../qtcore/qpluginloader.html">QPluginLoader</a></span><span class="operator">::</span>staticInstances())
          populateMenus(plugin);

</pre>
<p>The <code>loadPlugins()</code> function is called from the <code>MainWindow</code> constructor to detect plugins and update the <b>Brush</b>, <b>Shapes</b>, and <b>Filters</b> menus. We start by handling static plugins (available through <a href="../qtcore/qpluginloader.html#staticInstances">QPluginLoader::staticInstances</a>())</p>
<p>To the application that uses the plugin, a Qt plugin is simply a <a href="../qtcore/qobject.html">QObject</a>. That <a href="../qtcore/qobject.html">QObject</a> implements plugin interfaces using multiple inheritance.</p>
<pre class="cpp">

      pluginsDir <span class="operator">=</span> <span class="type"><a href="../qtcore/qdir.html">QDir</a></span>(qApp<span class="operator">-</span><span class="operator">&gt;</span>applicationDirPath());

  <span class="preprocessor">#if defined(Q_OS_WIN)</span>
      <span class="keyword">if</span> (pluginsDir<span class="operator">.</span>dirName()<span class="operator">.</span>toLower() <span class="operator">=</span><span class="operator">=</span> <span class="string">&quot;debug&quot;</span> <span class="operator">|</span><span class="operator">|</span> pluginsDir<span class="operator">.</span>dirName()<span class="operator">.</span>toLower() <span class="operator">=</span><span class="operator">=</span> <span class="string">&quot;release&quot;</span>)
          pluginsDir<span class="operator">.</span>cdUp();
  <span class="preprocessor">#elif defined(Q_OS_MAC)</span>
      <span class="keyword">if</span> (pluginsDir<span class="operator">.</span>dirName() <span class="operator">=</span><span class="operator">=</span> <span class="string">&quot;MacOS&quot;</span>) {
          pluginsDir<span class="operator">.</span>cdUp();
          pluginsDir<span class="operator">.</span>cdUp();
          pluginsDir<span class="operator">.</span>cdUp();
      }
  <span class="preprocessor">#endif</span>
      pluginsDir<span class="operator">.</span>cd(<span class="string">&quot;plugins&quot;</span>);

</pre>
<p>The next step is to load dynamic plugins. We initialize the <code>pluginsDir</code> member variable to refer to the <code>plugins</code> subdirectory of the Plug &amp; Paint example. On Unix, this is just a matter of initializing the <a href="../qtcore/qdir.html">QDir</a> variable with QApplication::applicationDirPath(), the path of the executable file, and to do a <a href="../qtcore/qdir.html#cd">cd()</a>. On Windows and macOS, this file is usually located in a subdirectory, so we need to take this into account.</p>
<pre class="cpp">

      foreach (<span class="type"><a href="../qtcore/qstring.html">QString</a></span> fileName<span class="operator">,</span> pluginsDir<span class="operator">.</span>entryList(<span class="type"><a href="../qtcore/qdir.html">QDir</a></span><span class="operator">::</span>Files)) {
          <span class="type"><a href="../qtcore/qpluginloader.html">QPluginLoader</a></span> loader(pluginsDir<span class="operator">.</span>absoluteFilePath(fileName));
          <span class="type"><a href="../qtcore/qobject.html">QObject</a></span> <span class="operator">*</span>plugin <span class="operator">=</span> loader<span class="operator">.</span>instance();
          <span class="keyword">if</span> (plugin) {
              populateMenus(plugin);
              pluginFileNames <span class="operator">+</span><span class="operator">=</span> fileName;
          }
      }

</pre>
<p>We use <a href="../qtcore/qdir.html#entryList-1">QDir::entryList</a>() to get a list of all files in that directory. Then we iterate over the result using <a href="../qtcore/containers.html#foreach">foreach</a> and try to load the plugin using <a href="../qtcore/qpluginloader.html">QPluginLoader</a>.</p>
<p>The <a href="../qtcore/qobject.html">QObject</a> provided by the plugin is accessible through <a href="../qtcore/qpluginloader.html#instance">QPluginLoader::instance</a>(). If the dynamic library isn't a Qt plugin, or if it was compiled against an incompatible version of the Qt library, <a href="../qtcore/qpluginloader.html#instance">QPluginLoader::instance</a>() returns a null pointer.</p>
<p>If <a href="../qtcore/qpluginloader.html#instance">QPluginLoader::instance</a>() is non-null, we add it to the menus.</p>
<pre class="cpp">

      brushMenu<span class="operator">-</span><span class="operator">&gt;</span>setEnabled(<span class="operator">!</span>brushActionGroup<span class="operator">-</span><span class="operator">&gt;</span>actions()<span class="operator">.</span>isEmpty());
      shapesMenu<span class="operator">-</span><span class="operator">&gt;</span>setEnabled(<span class="operator">!</span>shapesMenu<span class="operator">-</span><span class="operator">&gt;</span>actions()<span class="operator">.</span>isEmpty());
      filterMenu<span class="operator">-</span><span class="operator">&gt;</span>setEnabled(<span class="operator">!</span>filterMenu<span class="operator">-</span><span class="operator">&gt;</span>actions()<span class="operator">.</span>isEmpty());
  }

</pre>
<p>At the end, we enable or disable the <b>Brush</b>, <b>Shapes</b>, and <b>Filters</b> menus based on whether they contain any items.</p>
<pre class="cpp">

  <span class="type">void</span> MainWindow<span class="operator">::</span>populateMenus(<span class="type"><a href="../qtcore/qobject.html">QObject</a></span> <span class="operator">*</span>plugin)
  {
      BrushInterface <span class="operator">*</span>iBrush <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span>BrushInterface <span class="operator">*</span><span class="operator">&gt;</span>(plugin);
      <span class="keyword">if</span> (iBrush)
          addToMenu(plugin<span class="operator">,</span> iBrush<span class="operator">-</span><span class="operator">&gt;</span>brushes()<span class="operator">,</span> brushMenu<span class="operator">,</span> SLOT(changeBrush())<span class="operator">,</span>
                    brushActionGroup);

      ShapeInterface <span class="operator">*</span>iShape <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span>ShapeInterface <span class="operator">*</span><span class="operator">&gt;</span>(plugin);
      <span class="keyword">if</span> (iShape)
          addToMenu(plugin<span class="operator">,</span> iShape<span class="operator">-</span><span class="operator">&gt;</span>shapes()<span class="operator">,</span> shapesMenu<span class="operator">,</span> SLOT(insertShape()));

      FilterInterface <span class="operator">*</span>iFilter <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span>FilterInterface <span class="operator">*</span><span class="operator">&gt;</span>(plugin);
      <span class="keyword">if</span> (iFilter)
          addToMenu(plugin<span class="operator">,</span> iFilter<span class="operator">-</span><span class="operator">&gt;</span>filters()<span class="operator">,</span> filterMenu<span class="operator">,</span> SLOT(applyFilter()));
  }

</pre>
<p>For each plugin (static or dynamic), we check which interfaces it implements using <a href="../qtcore/qobject.html#qobject_cast">qobject_cast</a>(). First, we try to cast the plugin instance to a <code>BrushInterface</code>; if it works, we call the private function <code>addToMenu()</code> with the list of brushes returned by <code>brushes()</code>. Then we do the same with the <code>ShapeInterface</code> and the <code>FilterInterface</code>.</p>
<pre class="cpp">

  <span class="type">void</span> MainWindow<span class="operator">::</span>aboutPlugins()
  {
      PluginDialog dialog(pluginsDir<span class="operator">.</span>path()<span class="operator">,</span> pluginFileNames<span class="operator">,</span> <span class="keyword">this</span>);
      dialog<span class="operator">.</span>exec();
  }

</pre>
<p>The <code>aboutPlugins()</code> slot is called on startup and can be invoked at any time through the <b>About Plugins</b> action. It pops up a <code>PluginDialog</code>, providing information about the loaded plugins.</p>
<p class="centerAlign"><img src="images/plugandpaint-plugindialog.png" alt="Screenshot of the Plugin dialog" /></p><p>The <code>addToMenu()</code> function is called from <code>loadPlugin()</code> to create <a href="qaction.html">QAction</a>s for custom brushes, shapes, or filters and add them to the relevant menu. The <a href="qaction.html">QAction</a> is created with the plugin from which it comes from as the parent; this makes it convenient to get access to the plugin later.</p>
<pre class="cpp">

  <span class="type">void</span> MainWindow<span class="operator">::</span>changeBrush()
  {
      <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>action <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span><span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span><span class="operator">&gt;</span>(sender());
      BrushInterface <span class="operator">*</span>iBrush <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span>BrushInterface <span class="operator">*</span><span class="operator">&gt;</span>(action<span class="operator">-</span><span class="operator">&gt;</span>parent());
      <span class="keyword">const</span> <span class="type"><a href="../qtcore/qstring.html">QString</a></span> brush <span class="operator">=</span> action<span class="operator">-</span><span class="operator">&gt;</span>text();

      paintArea<span class="operator">-</span><span class="operator">&gt;</span>setBrush(iBrush<span class="operator">,</span> brush);
  }

</pre>
<p>The <code>changeBrush()</code> slot is invoked when the user chooses one of the brushes from the <b>Brush</b> menu. We start by finding out which action invoked the slot using <a href="../qtcore/qobject.html#sender">QObject::sender</a>(). Then we get the <code>BrushInterface</code> out of the plugin (which we conveniently passed as the <a href="qaction.html">QAction</a>'s parent) and we call <code>PaintArea::setBrush()</code> with the <code>BrushInterface</code> and the string identifying the brush. Next time the user draws on the paint area, <code>PaintArea</code> will use this brush.</p>
<pre class="cpp">

  <span class="type">void</span> MainWindow<span class="operator">::</span>insertShape()
  {
      <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>action <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span><span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span><span class="operator">&gt;</span>(sender());
      ShapeInterface <span class="operator">*</span>iShape <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span>ShapeInterface <span class="operator">*</span><span class="operator">&gt;</span>(action<span class="operator">-</span><span class="operator">&gt;</span>parent());

      <span class="keyword">const</span> <span class="type"><a href="../qtgui/qpainterpath.html">QPainterPath</a></span> path <span class="operator">=</span> iShape<span class="operator">-</span><span class="operator">&gt;</span>generateShape(action<span class="operator">-</span><span class="operator">&gt;</span>text()<span class="operator">,</span> <span class="keyword">this</span>);
      <span class="keyword">if</span> (<span class="operator">!</span>path<span class="operator">.</span>isEmpty())
          paintArea<span class="operator">-</span><span class="operator">&gt;</span>insertShape(path);
  }

</pre>
<p>The <code>insertShape()</code> is invoked when the use chooses one of the shapes from the <b>Shapes</b> menu. We retrieve the <a href="qaction.html">QAction</a> that invoked the slot, then the <code>ShapeInterface</code> associated with that <a href="qaction.html">QAction</a>, and finally we call <code>ShapeInterface::generateShape()</code> to obtain a <a href="../qtgui/qpainterpath.html">QPainterPath</a>.</p>
<pre class="cpp">

  <span class="type">void</span> MainWindow<span class="operator">::</span>applyFilter()
  {
      <span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span>action <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span><span class="type"><a href="qaction.html">QAction</a></span> <span class="operator">*</span><span class="operator">&gt;</span>(sender());
      FilterInterface <span class="operator">*</span>iFilter <span class="operator">=</span>
              qobject_cast<span class="operator">&lt;</span>FilterInterface <span class="operator">*</span><span class="operator">&gt;</span>(action<span class="operator">-</span><span class="operator">&gt;</span>parent());

      <span class="keyword">const</span> <span class="type"><a href="../qtgui/qimage.html">QImage</a></span> image <span class="operator">=</span> iFilter<span class="operator">-</span><span class="operator">&gt;</span>filterImage(action<span class="operator">-</span><span class="operator">&gt;</span>text()<span class="operator">,</span> paintArea<span class="operator">-</span><span class="operator">&gt;</span>image()<span class="operator">,</span>
                                                <span class="keyword">this</span>);
      paintArea<span class="operator">-</span><span class="operator">&gt;</span>setImage(image);
  }

</pre>
<p>The <code>applyFilter()</code> slot is similar: We retrieve the <a href="qaction.html">QAction</a> that invoked the slot, then the <code>FilterInterface</code> associated to that <a href="qaction.html">QAction</a>, and finally we call <code>FilterInterface::filterImage()</code> to apply the filter onto the current image.</p>
<a name="the-paintarea-class"></a>
<h2 id="the-paintarea-class">The PaintArea Class</h2>
<p>The <code>PaintArea</code> class contains some code that deals with <code>BrushInterface</code>, so we'll review it briefly.</p>
<pre class="cpp">

  <span class="type">void</span> PaintArea<span class="operator">::</span>setBrush(BrushInterface <span class="operator">*</span>brushInterface<span class="operator">,</span> <span class="keyword">const</span> <span class="type"><a href="../qtcore/qstring.html">QString</a></span> <span class="operator">&amp;</span>brush)
  {
      <span class="keyword">this</span><span class="operator">-</span><span class="operator">&gt;</span>brushInterface <span class="operator">=</span> brushInterface;
      <span class="keyword">this</span><span class="operator">-</span><span class="operator">&gt;</span>brush <span class="operator">=</span> brush;
  }

</pre>
<p>In <code>setBrush()</code>, we simply store the <code>BrushInterface</code> and the brush that are given to us by <code>MainWindow</code>.</p>
<pre class="cpp">

  <span class="type">void</span> PaintArea<span class="operator">::</span>mouseMoveEvent(<span class="type"><a href="../qtgui/qmouseevent.html">QMouseEvent</a></span> <span class="operator">*</span>event)
  {
      <span class="keyword">if</span> ((event<span class="operator">-</span><span class="operator">&gt;</span>buttons() <span class="operator">&amp;</span> <span class="type"><a href="../qtcore/qt.html">Qt</a></span><span class="operator">::</span>LeftButton) <span class="operator">&amp;</span><span class="operator">&amp;</span> lastPos <span class="operator">!</span><span class="operator">=</span> <span class="type"><a href="../qtcore/qpoint.html">QPoint</a></span>(<span class="operator">-</span><span class="number">1</span><span class="operator">,</span> <span class="operator">-</span><span class="number">1</span>)) {
          <span class="keyword">if</span> (brushInterface) {
              <span class="type"><a href="../qtgui/qpainter.html">QPainter</a></span> painter(<span class="operator">&amp;</span>theImage);
              setupPainter(painter);
              <span class="keyword">const</span> <span class="type"><a href="../qtcore/qrect.html">QRect</a></span> rect <span class="operator">=</span> brushInterface<span class="operator">-</span><span class="operator">&gt;</span>mouseMove(brush<span class="operator">,</span> painter<span class="operator">,</span> lastPos<span class="operator">,</span>
                                                           event<span class="operator">-</span><span class="operator">&gt;</span>pos());
              update(rect);
          }

          lastPos <span class="operator">=</span> event<span class="operator">-</span><span class="operator">&gt;</span>pos();
      }
  }

</pre>
<p>In the <a href="qwidget.html#mouseMoveEvent">mouse move event handler</a>, we call the <code>BrushInterface::mouseMove()</code> function on the current <code>BrushInterface</code>, with the current brush. The mouse press and mouse release handlers are very similar.</p>
<a name="the-plugindialog-class"></a>
<h2 id="the-plugindialog-class">The PluginDialog Class</h2>
<p>The <code>PluginDialog</code> 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 <code>findPlugins()</code> to fill the QTreeWdiget with information about the plugins:</p>
<pre class="cpp">

  <span class="type">void</span> PluginDialog<span class="operator">::</span>findPlugins(<span class="keyword">const</span> <span class="type"><a href="../qtcore/qstring.html">QString</a></span> <span class="operator">&amp;</span>path<span class="operator">,</span>
                                 <span class="keyword">const</span> <span class="type"><a href="../qtcore/qstringlist.html">QStringList</a></span> <span class="operator">&amp;</span>fileNames)
  {
      label<span class="operator">-</span><span class="operator">&gt;</span>setText(tr(<span class="string">&quot;Plug &amp; Paint found the following plugins\n&quot;</span>
                        <span class="string">&quot;(looked in %1):&quot;</span>)
                     <span class="operator">.</span>arg(<span class="type"><a href="../qtcore/qdir.html">QDir</a></span><span class="operator">::</span>toNativeSeparators(path)));

      <span class="keyword">const</span> <span class="type"><a href="../qtcore/qdir.html">QDir</a></span> dir(path);

      foreach (<span class="type"><a href="../qtcore/qobject.html">QObject</a></span> <span class="operator">*</span>plugin<span class="operator">,</span> <span class="type"><a href="../qtcore/qpluginloader.html">QPluginLoader</a></span><span class="operator">::</span>staticInstances())
          populateTreeWidget(plugin<span class="operator">,</span> tr(<span class="string">&quot;%1 (Static Plugin)&quot;</span>)
                                     <span class="operator">.</span>arg(plugin<span class="operator">-</span><span class="operator">&gt;</span>metaObject()<span class="operator">-</span><span class="operator">&gt;</span>className()));

      foreach (<span class="type"><a href="../qtcore/qstring.html">QString</a></span> fileName<span class="operator">,</span> fileNames) {
          <span class="type"><a href="../qtcore/qpluginloader.html">QPluginLoader</a></span> loader(dir<span class="operator">.</span>absoluteFilePath(fileName));
          <span class="type"><a href="../qtcore/qobject.html">QObject</a></span> <span class="operator">*</span>plugin <span class="operator">=</span> loader<span class="operator">.</span>instance();
          <span class="keyword">if</span> (plugin)
              populateTreeWidget(plugin<span class="operator">,</span> fileName);
      }
  }

</pre>
<p>The <code>findPlugins()</code> is very similar to <code>MainWindow::loadPlugins()</code>. It uses <a href="../qtcore/qpluginloader.html">QPluginLoader</a> to access the static and dynamic plugins. Its helper function <code>populateTreeWidget()</code> uses <a href="../qtcore/qobject.html#qobject_cast">qobject_cast</a>() to find out which interfaces are implemented by the plugins:</p>
<pre class="cpp">

  <span class="type">void</span> PluginDialog<span class="operator">::</span>populateTreeWidget(<span class="type"><a href="../qtcore/qobject.html">QObject</a></span> <span class="operator">*</span>plugin<span class="operator">,</span> <span class="keyword">const</span> <span class="type"><a href="../qtcore/qstring.html">QString</a></span> <span class="operator">&amp;</span>text)
  {
      <span class="type"><a href="qtreewidgetitem.html">QTreeWidgetItem</a></span> <span class="operator">*</span>pluginItem <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qtreewidgetitem.html">QTreeWidgetItem</a></span>(treeWidget);
      pluginItem<span class="operator">-</span><span class="operator">&gt;</span>setText(<span class="number">0</span><span class="operator">,</span> text);
      treeWidget<span class="operator">-</span><span class="operator">&gt;</span>setItemExpanded(pluginItem<span class="operator">,</span> <span class="keyword">true</span>);

      <span class="type"><a href="../qtgui/qfont.html">QFont</a></span> boldFont <span class="operator">=</span> pluginItem<span class="operator">-</span><span class="operator">&gt;</span>font(<span class="number">0</span>);
      boldFont<span class="operator">.</span>setBold(<span class="keyword">true</span>);
      pluginItem<span class="operator">-</span><span class="operator">&gt;</span>setFont(<span class="number">0</span><span class="operator">,</span> boldFont);

      <span class="keyword">if</span> (plugin) {
          BrushInterface <span class="operator">*</span>iBrush <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span>BrushInterface <span class="operator">*</span><span class="operator">&gt;</span>(plugin);
          <span class="keyword">if</span> (iBrush)
              addItems(pluginItem<span class="operator">,</span> <span class="string">&quot;BrushInterface&quot;</span><span class="operator">,</span> iBrush<span class="operator">-</span><span class="operator">&gt;</span>brushes());

          ShapeInterface <span class="operator">*</span>iShape <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span>ShapeInterface <span class="operator">*</span><span class="operator">&gt;</span>(plugin);
          <span class="keyword">if</span> (iShape)
              addItems(pluginItem<span class="operator">,</span> <span class="string">&quot;ShapeInterface&quot;</span><span class="operator">,</span> iShape<span class="operator">-</span><span class="operator">&gt;</span>shapes());

          FilterInterface <span class="operator">*</span>iFilter <span class="operator">=</span>
                  qobject_cast<span class="operator">&lt;</span>FilterInterface <span class="operator">*</span><span class="operator">&gt;</span>(plugin);
          <span class="keyword">if</span> (iFilter)
              addItems(pluginItem<span class="operator">,</span> <span class="string">&quot;FilterInterface&quot;</span><span class="operator">,</span> iFilter<span class="operator">-</span><span class="operator">&gt;</span>filters());
      }
  }

</pre>
<a name="importing-static-plugins"></a>
<h2 id="importing-static-plugins">Importing Static Plugins</h2>
<p>The <a href="qtwidgets-tools-plugandpaint-plugins-basictools-example.html">Basic Tools</a> plugin is built as a static plugin, to ensure that it is always available to the application. This requires using the <a href="../qtcore/qtplugin.html#Q_IMPORT_PLUGIN">Q_IMPORT_PLUGIN</a>() macro somewhere in the application (in a <code>.cpp</code> file) and specifying the plugin in the <code>.pro</code> file.</p>
<p>For Plug &amp; Paint, we have chosen to put <a href="../qtcore/qtplugin.html#Q_IMPORT_PLUGIN">Q_IMPORT_PLUGIN</a>() in <code>main.cpp</code>:</p>
<pre class="cpp">

  <span class="preprocessor">#include &quot;mainwindow.h&quot;</span>
  <span class="preprocessor">#include &lt;QtPlugin&gt;</span>
  <span class="preprocessor">#include &lt;QApplication&gt;</span>

  Q_IMPORT_PLUGIN(BasicToolsPlugin)

  <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>argv<span class="operator">[</span><span class="operator">]</span>)
  {
      <span class="type"><a href="qapplication.html">QApplication</a></span> app(argc<span class="operator">,</span> argv);
      MainWindow window;
      window<span class="operator">.</span>show();
      <span class="keyword">return</span> app<span class="operator">.</span>exec();
  }

</pre>
<p>The argument to <a href="../qtcore/qtplugin.html#Q_IMPORT_PLUGIN">Q_IMPORT_PLUGIN</a>() is the plugin name, which corresponds with the name of the class that declares metadata for the plugin with <a href="../qtcore/qtplugin.html#Q_PLUGIN_METADATA">Q_PLUGIN_METADATA</a>().</p>
<p>In the <code>.pro</code> file, we need to specify the static library. Here's the project file for building Plug &amp; Paint:</p>
<pre class="cpp">

  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 {
      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
      }
  }

</pre>
<p>The <code>LIBS</code> line variable specifies the library <code>pnp_basictools</code> located in the <code>../plugandpaint/plugins/basictools</code> directory. (Although the <code>LIBS</code> syntax has a distinct Unix flavor, <code>qmake</code> supports it on all platforms.)</p>
<p>The <code>CONFIG()</code> 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.</p>
<p>This completes our review of the Plug &amp; Paint application. At this point, you might want to take a look at the <a href="qtwidgets-tools-plugandpaint-plugins-basictools-example.html">Basic Tools</a> example plugin.</p>
<p>Files:</p>
<ul>
<li><a href="qtwidgets-tools-plugandpaint-app-interfaces-h.html">tools/plugandpaint/app/interfaces.h</a></li>
<li><a href="qtwidgets-tools-plugandpaint-app-mainwindow-cpp.html">tools/plugandpaint/app/mainwindow.cpp</a></li>
<li><a href="qtwidgets-tools-plugandpaint-app-mainwindow-h.html">tools/plugandpaint/app/mainwindow.h</a></li>
<li><a href="qtwidgets-tools-plugandpaint-app-paintarea-cpp.html">tools/plugandpaint/app/paintarea.cpp</a></li>
<li><a href="qtwidgets-tools-plugandpaint-app-paintarea-h.html">tools/plugandpaint/app/paintarea.h</a></li>
<li><a href="qtwidgets-tools-plugandpaint-app-plugindialog-cpp.html">tools/plugandpaint/app/plugindialog.cpp</a></li>
<li><a href="qtwidgets-tools-plugandpaint-app-plugindialog-h.html">tools/plugandpaint/app/plugindialog.h</a></li>
<li><a href="qtwidgets-tools-plugandpaint-app-main-cpp.html">tools/plugandpaint/app/main.cpp</a></li>
<li><a href="qtwidgets-tools-plugandpaint-app-app-pro.html">tools/plugandpaint/app/app.pro</a></li>
</ul>
</div>
<!-- @@@tools/plugandpaint/app -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2017 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>