pax_global_header00006660000000000000000000000064125215325730014517gustar00rootroot0000000000000052 comment=65a5dd004f11c1bf9c2a4fc929319acfe91e9b27 KDocker-5.0/000077500000000000000000000000001252153257300127055ustar00rootroot00000000000000KDocker-5.0/3rdparty/000077500000000000000000000000001252153257300144555ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/000077500000000000000000000000001252153257300205275ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/INSTALL.TXT000066400000000000000000000223741252153257300222460ustar00rootroot00000000000000INSTALLATION INSTRUCTIONS These instructions refer to the package you are installing as some-package.tar.gz or some-package.zip. The .zip file is intended for use on Windows. The directory you choose for the installation will be referred to as your-install-dir. Note to Qt Visual Studio Integration users: In the instructions below, instead of building from command line with nmake, you can use the menu command 'Qt->Open Solution from .pro file' on the .pro files in the example and plugin directories, and then build from within Visual Studio. Unpacking and installation -------------------------- 1. Unpacking the archive (if you have not done so already). On Unix and Mac OS X (in a terminal window): cd your-install-dir gunzip some-package.tar.gz tar xvf some-package.tar This creates the subdirectory some-package containing the files. On Windows: Unpack the .zip archive by right-clicking it in explorer and choosing "Extract All...". If your version of Windows does not have zip support, you can use the infozip tools available from www.info-zip.org. If you are using the infozip tools (in a command prompt window): cd your-install-dir unzip some-package.zip 2. Configuring the package. The configure script is called "configure" on unix/mac and "configure.bat" on Windows. It should be run from a command line after cd'ing to the package directory. You can choose whether you want to use the component by including its source code directly into your project, or build the component as a dynamic shared library (DLL) that is loaded into the application at run-time. The latter may be preferable for technical or licensing (LGPL) reasons. If you want to build a DLL, run the configure script with the argument "-library". Also see the note about usage below. (Components that are Qt plugins, e.g. styles and image formats, are by default built as a plugin DLL.) The configure script will prompt you in some cases for further information. Answer these questions and carefully read the license text before accepting the license conditions. The package cannot be used if you do not accept the license conditions. 3. Building the component and examples (when required). If a DLL is to be built, or if you would like to build the examples, next give the commands qmake make [or nmake if your are using Microsoft Visual C++] The example program(s) can be found in the directory called "examples" or "example". Components that are Qt plugins, e.g. styles and image formats, are ready to be used as soon as they are built, so the rest of this installation instruction can be skipped. 4. Building the Qt Designer plugin (optional). Some of the widget components are provided with plugins for Qt Designer. To build and install the plugin, cd into the some-package/plugin directory and give the commands qmake make [or nmake if your are using Microsoft Visual C++] Restart Qt Designer to make it load the new widget plugin. Note: If you are using the built-in Qt Designer from the Qt Visual Studio Integration, you will need to manually copy the plugin DLL file, i.e. copy %QTDIR%\plugins\designer\some-component.dll to the Qt Visual Studio Integration plugin path, typically: C:\Program Files\Trolltech\Qt VS Integration\plugins Note: If you for some reason are using a Qt Designer that is built in debug mode, you will need to build the plugin in debug mode also. Edit the file plugin.pro in the plugin directory, changing 'release' to 'debug' in the CONFIG line, before running qmake. Solutions components are intended to be used directly from the package directory during development, so there is no 'make install' procedure. Using a component in your project --------------------------------- To use this component in your project, add the following line to the project's .pro file (or do the equivalent in your IDE): include(your-install-dir/some-package/src/some-package.pri) This adds the package's sources and headers to the SOURCES and HEADERS project variables respectively (or, if the component has been configured as a DLL, it adds that library to the LIBS variable), and updates INCLUDEPATH to contain the package's src directory. Additionally, the .pri file may include some dependencies needed by the package. To include a header file from the package in your sources, you can now simply use: #include or alternatively, in pre-Qt 4 style: #include Refer to the documentation to see the classes and headers this components provides. Install documentation (optional) -------------------------------- The HTML documentation for the package's classes is located in the your-install-dir/some-package/doc/html/index.html. You can open this file and read the documentation with any web browser. To install the documentation into Qt Assistant (for Qt version 4.4 and later): 1. In Assistant, open the Edit->Preferences dialog and choose the Documentation tab. Click the Add... button and select the file your-install-dir/some-package/doc/html/some-package.qch For Qt versions prior to 4.4, do instead the following: 1. The directory your-install-dir/some-package/doc/html contains a file called some-package.dcf. Execute the following commands in a shell, command prompt or terminal window: cd your-install-dir/some-package/doc/html/ assistant -addContentFile some-package.dcf The next time you start Qt Assistant, you can access the package's documentation. Removing the documentation from assistant ----------------------------------------- If you have installed the documentation into Qt Assistant, and want to uninstall it, do as follows, for Qt version 4.4 and later: 1. In Assistant, open the Edit->Preferences dialog and choose the Documentation tab. In the list of Registered Documentation, select the item com.nokia.qtsolutions.some-package_version, and click the Remove button. For Qt versions prior to 4.4, do instead the following: 1. The directory your-install-dir/some-package/doc/html contains a file called some-package.dcf. Execute the following commands in a shell, command prompt or terminal window: cd your-install-dir/some-package/doc/html/ assistant -removeContentFile some-package.dcf Using the component as a DLL ---------------------------- 1. Normal components The shared library (DLL) is built and placed in the some-package/lib directory. It is intended to be used directly from there during development. When appropriate, both debug and release versions are built, since the run-time linker will in some cases refuse to load a debug-built DLL into a release-built application or vice versa. The following steps are taken by default to help the dynamic linker to locate the DLL at run-time (during development): Unix: The some-package.pri file will add linker instructions to add the some-package/lib directory to the rpath of the executable. (When distributing, or if your system does not support rpath, you can copy the shared library to another place that is searched by the dynamic linker, e.g. the "lib" directory of your Qt installation.) Mac: The full path to the library is hardcoded into the library itself, from where it is copied into the executable at link time, and ready by the dynamic linker at run-time. (When distributing, you will want to edit these hardcoded paths in the same way as for the Qt DLLs. Refer to the document "Deploying an Application on Mac OS X" in the Qt Reference Documentation.) Windows: the .dll file(s) are copied into the "bin" directory of your Qt installation. The Qt installation will already have set up that directory to be searched by the dynamic linker. 2. Plugins For Qt Solutions plugins (e.g. image formats), both debug and release versions of the plugin are built by default when appropriate, since in some cases the release Qt library will not load a debug plugin, and vice versa. The plugins are automatically copied into the plugins directory of your Qt installation when built, so no further setup is required. Plugins may also be built statically, i.e. as a library that will be linked into your application executable, and so will not need to be redistributed as a separate plugin DLL to end users. Static building is required if Qt itself is built statically. To do it, just add "static" to the CONFIG variable in the plugin/plugin.pro file before building. Refer to the "Static Plugins" section in the chapter "How to Create Qt Plugins" for explanation of how to use a static plugin in your application. The source code of the example program(s) will also typically contain the relevant instructions as comments. Uninstalling ------------ The following command will remove any fils that have been automatically placed outside the package directory itself during installation and building make distclean [or nmake if your are using Microsoft Visual C++] If Qt Assistant documentation or Qt Designer plugins have been installed, they can be uninstalled manually, ref. above. Enjoy! :) - The Qt Solutions Team. KDocker-5.0/3rdparty/qtsingleapplication/README.TXT000066400000000000000000000016411252153257300220670ustar00rootroot00000000000000Qt Solutions Component: Single Application The QtSingleApplication component provides support for applications that can be only started once per user. Version history: 2.0: - Version 1.3 ported to Qt 4. 2.1: - Fix compilation problem on Mac. 2.2: - Really fix the Mac compilation problem. - Mac: fix crash due to wrong object releasing. - Mac: Fix memory leak. 2.3: - Windows: Force creation of internal widget to make it work with Qt 4.2. 2.4: - Fix the system for automatic window raising on message reception. NOTE: minor API change. 2.5: - Mac: Fix isRunning() to work and report correctly. 2.6: - - initialize() is now obsolete, no longer necessary to call it - - Fixed race condition where multiple instances migth be started - - QtSingleCoreApplication variant provided for non-GUI (console) usage - Complete reimplementation. Visible changes: - LGPL release. KDocker-5.0/3rdparty/qtsingleapplication/buildlib/000077500000000000000000000000001252153257300223155ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/buildlib/buildlib.pro000066400000000000000000000007211252153257300246250ustar00rootroot00000000000000TEMPLATE=lib CONFIG += qt dll qtsingleapplication-buildlib mac:CONFIG += absolute_library_soname win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release build_all include(../src/qtsingleapplication.pri) TARGET = $$QTSINGLEAPPLICATION_LIBNAME DESTDIR = $$QTSINGLEAPPLICATION_LIBDIR win32 { DLLDESTDIR = $$[QT_INSTALL_BINS] QMAKE_DISTCLEAN += $$[QT_INSTALL_BINS]\\$${QTSINGLEAPPLICATION_LIBNAME}.dll } target.path = $$DESTDIR INSTALLS += target KDocker-5.0/3rdparty/qtsingleapplication/common.pri000066400000000000000000000005641252153257300225400ustar00rootroot00000000000000exists(config.pri):infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtsingleapplication-uselib TEMPLATE += fakelib QTSINGLEAPPLICATION_LIBNAME = $$qtLibraryTarget(QtSolutions_SingleApplication-head) TEMPLATE -= fakelib QTSINGLEAPPLICATION_LIBDIR = $$PWD/lib unix:qtsingleapplication-uselib:!qtsingleapplication-buildlib:QMAKE_RPATHDIR += $$QTSINGLEAPPLICATION_LIBDIR KDocker-5.0/3rdparty/qtsingleapplication/configure000066400000000000000000000012611252153257300224330ustar00rootroot00000000000000#!/bin/sh if [ "x$1" != "x" -a "x$1" != "x-library" ]; then echo "Usage: $0 [-library]" echo echo "-library: Build the component as a dynamic library (DLL). Default is to" echo " include the component source code directly in the application." echo exit 0 fi rm -f config.pri if [ "x$1" = "x-library" ]; then echo "Configuring to build this component as a dynamic library." echo "SOLUTIONS_LIBRARY = yes" > config.pri fi echo echo "This component is now configured." echo echo "To build the component library (if requested) and example(s)," echo "run qmake and your make command." echo echo "To remove or reconfigure, run make distclean." echo KDocker-5.0/3rdparty/qtsingleapplication/configure.bat000066400000000000000000000054501252153257300232040ustar00rootroot00000000000000::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). :: Contact: http://www.qt-project.org/legal :: :: This file is part of the Qt Solutions component. :: :: $QT_BEGIN_LICENSE:BSD$ :: You may use this file under the terms of the BSD license as follows: :: :: "Redistribution and use in source and binary forms, with or without :: modification, are permitted provided that the following conditions are :: met: :: * Redistributions of source code must retain the above copyright :: notice, this list of conditions and the following disclaimer. :: * Redistributions in binary form must reproduce the above copyright :: notice, this list of conditions and the following disclaimer in :: the documentation and/or other materials provided with the :: distribution. :: * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names :: of its contributors may be used to endorse or promote products derived :: from this software without specific prior written permission. :: :: :: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS :: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT :: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR :: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT :: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, :: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT :: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, :: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY :: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT :: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE :: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." :: :: $QT_END_LICENSE$ :: ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: @echo off rem rem "Main" rem if not "%1"=="" ( if not "%1"=="-library" ( call :PrintUsage goto EOF ) ) if exist config.pri. del config.pri if "%1"=="-library" ( echo Configuring to build this component as a dynamic library. echo SOLUTIONS_LIBRARY = yes > config.pri ) echo . echo This component is now configured. echo . echo To build the component library (if requested) and example(s), echo run qmake and your make or nmake command. echo . echo To remove or reconfigure, run make (nmake) distclean. echo . goto EOF :PrintUsage echo Usage: configure.bat [-library] echo . echo -library: Build the component as a dynamic library (DLL). Default is to echo include the component source directly in the application. echo A DLL may be preferable for technical or licensing (LGPL) reasons. echo . goto EOF :EOF KDocker-5.0/3rdparty/qtsingleapplication/doc/000077500000000000000000000000001252153257300212745ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/doc/html/000077500000000000000000000000001252153257300222405ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/doc/html/classic.css000066400000000000000000000074531252153257300244040ustar00rootroot00000000000000BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { font-family: Arial, Geneva, Helvetica, sans-serif; } H1 { text-align: center; font-size: 160%; } H2 { font-size: 120%; } H3 { font-size: 100%; } h3.fn,span.fn { background-color: #eee; border-width: 1px; border-style: solid; border-color: #ddd; font-weight: bold; padding: 6px 0px 6px 10px; margin: 42px 0px 0px 0px; } hr { border: 0; color: #a0a0a0; background-color: #ccc; height: 1px; width: 100%; text-align: left; margin: 34px 0px 34px 0px; } table.valuelist { border-width: 1px 1px 1px 1px; border-style: solid; border-color: #dddddd; border-collapse: collapse; background-color: #f0f0f0; } table.indextable { border-width: 1px 1px 1px 1px; border-style: solid; border-collapse: collapse; background-color: #f0f0f0; border-color:#555; font-size: 100%; } table td.largeindex { border-width: 1px 1px 1px 1px; border-collapse: collapse; background-color: #f0f0f0; border-color:#555; font-size: 120%; } table.valuelist th { border-width: 1px 1px 1px 2px; padding: 4px; border-style: solid; border-color: #666; color:white; background-color:#666; } th.titleheader { border-width: 1px 0px 1px 0px; padding: 2px; border-style: solid; border-color: #666; color:white; background-color:#555; background-image:url('images/gradient.png')}; background-repeat: repeat-x; font-size: 100%; } th.largeheader { border-width: 1px 0px 1px 0px; padding: 4px; border-style: solid; border-color: #444; color:white; background-color:#555555; font-size: 120%; } p { margin-left: 4px; margin-top: 8px; margin-bottom: 8px; } a:link { color: #0046ad; text-decoration: none } a:visited { color: #672967; text-decoration: none } a.obsolete { color: #661100; text-decoration: none } a.compat { color: #661100; text-decoration: none } a.obsolete:visited { color: #995500; text-decoration: none } a.compat:visited { color: #995500; text-decoration: none } body { background: #ffffff; color: black } table.generic, table.annotated { border-width: 1px; border-color:#bbb; border-style:solid; border-collapse:collapse; } table td.memItemLeft { width: 180px; padding: 2px 0px 0px 8px; margin: 4px; border-width: 1px; border-color: #E0E0E0; border-style: none; font-size: 100%; white-space: nowrap } table td.memItemRight { padding: 2px 8px 0px 8px; margin: 4px; border-width: 1px; border-color: #E0E0E0; border-style: none; font-size: 100%; } table tr.odd { background: #f0f0f0; color: black; } table tr.even { background: #e4e4e4; color: black; } table.annotated th { padding: 3px; text-align: left } table.annotated td { padding: 3px; } table tr pre { padding-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; border: none; background: none } tr.qt-style { background: #96E066; color: black } body pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } table tr.qt-code pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } span.preprocessor, span.preprocessor a { color: darkblue; } span.comment { color: darkred; font-style: italic } span.string,span.char { color: darkgreen; } .title { text-align: center } .subtitle { font-size: 0.8em } .small-subtitle { font-size: 0.65em } .qmlitem { padding: 0; } .qmlname { white-space: nowrap; } .qmltype { text-align: center; font-size: 160%; } .qmlproto { background-color: #eee; border-width: 1px; border-style: solid; border-color: #ddd; font-weight: bold; padding: 6px 10px 6px 10px; margin: 42px 0px 0px 0px; } .qmlreadonly { float: right; color: red } .qmldoc { } *.qmlitem p { } KDocker-5.0/3rdparty/qtsingleapplication/doc/html/index.html000066400000000000000000000052751252153257300242460ustar00rootroot00000000000000 Single Application
  Home

Single Application

Description

The QtSingleApplication component provides support for applications that can be only started once per user.

For some applications it is useful or even critical that they are started only once by any user. Future attempts to start the application should activate any already running instance, and possibly perform requested actions, e.g. loading a file, in that instance.

The QtSingleApplication class provides an interface to detect a running instance, and to send command strings to that instance. For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui.

Classes

Examples

Tested platforms


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt Solutions
KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-loader.html000066400000000000000000000167001252153257300321010ustar00rootroot00000000000000 Loading Documents
  Home

Loading Documents

The application in this example loads or prints the documents passed as commandline parameters to further instances of this application.

 /****************************************************************************
 **
 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 ** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the Qt Solutions component.
 **
 ** You may use this file under the terms of the BSD license as follows:
 **
 ** "Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions are
 ** met:
 **   * Redistributions of source code must retain the above copyright
 **     notice, this list of conditions and the following disclaimer.
 **   * Redistributions in binary form must reproduce the above copyright
 **     notice, this list of conditions and the following disclaimer in
 **     the documentation and/or other materials provided with the
 **     distribution.
 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
 **     the names of its contributors may be used to endorse or promote
 **     products derived from this software without specific prior written
 **     permission.
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 **
 ****************************************************************************/

 #include <qtsingleapplication.h>
 #include <QtCore/QFile>
 #include <QtGui/QMainWindow>
 #include <QtGui/QPrinter>
 #include <QtGui/QPainter>
 #include <QtGui/QTextEdit>
 #include <QtGui/QMdiArea>
 #include <QtCore/QTextStream>

 class MainWindow : public QMainWindow
 {
     Q_OBJECT
 public:
     MainWindow();

 public slots:
     void handleMessage(const QString& message);

 signals:
     void needToShow();

 private:
     QMdiArea *workspace;
 };

The user interface in this application is a QMainWindow subclass with a QMdiArea as the central widget. It implements a slot handleMessage() that will be connected to the messageReceived() signal of the QtSingleApplication class.

 MainWindow::MainWindow()
 {
     workspace = new QMdiArea(this);

     setCentralWidget(workspace);
 }

The MainWindow constructor creates a minimal user interface.

 void MainWindow::handleMessage(const QString& message)
 {
     enum Action {
         Nothing,
         Open,
         Print
     } action;

     action = Nothing;
     QString filename = message;
     if (message.toLower().startsWith("/print ")) {
         filename = filename.mid(7);
         action = Print;
     } else if (!message.isEmpty()) {
         action = Open;
     }
     if (action == Nothing) {
         emit needToShow();
         return;
     }

     QFile file(filename);
     QString contents;
     if (file.open(QIODevice::ReadOnly))
         contents = file.readAll();
     else
         contents = "[[Error: Could not load file " + filename + "]]";

     QTextEdit *view = new QTextEdit;
     view->setPlainText(contents);

     switch(action) {

The handleMessage() slot interprets the message passed in as a filename that can be prepended with /print to indicate that the file should just be printed rather than loaded.

     case Print:
         {
             QPrinter printer;
             view->print(&printer);
             delete view;
         }
         break;

     case Open:
         {
             workspace->addSubWindow(view);
             view->setWindowTitle(message);
             view->show();
             emit needToShow();
         }
         break;
     default:
         break;
     };
 }

Loading the file will also activate the window.

 #include "main.moc"

 int main(int argc, char **argv)
 {
     QtSingleApplication instance("File loader QtSingleApplication example", argc, argv);
     QString message;
     for (int a = 1; a < argc; ++a) {
         message += argv[a];
         if (a < argc-1)
             message += " ";
     }

     if (instance.sendMessage(message))
         return 0;

The main entry point function creates a QtSingleApplication object, and creates a message to send to a running instance of the application. If the message was sent successfully the process exits immediately.

     MainWindow mw;
     mw.handleMessage(message);
     mw.show();

     QObject::connect(&instance, SIGNAL(messageReceived(const QString&)),
                      &mw, SLOT(handleMessage(const QString&)));

     instance.setActivationWindow(&mw, false);
     QObject::connect(&mw, SIGNAL(needToShow()), &instance, SLOT(activateWindow()));

     return instance.exec();
 }

If the message could not be sent the application starts up. Note that false is passed to the call to setActivationWindow() to prevent automatic activation for every message received, e.g. when the application should just print a file. Instead, the message handling function determines whether activation is requested, and signals that by emitting the needToShow() signal. This is then simply connected directly to QtSingleApplication's activateWindow() slot.


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt Solutions
KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-trivial.html000066400000000000000000000124341252153257300323050ustar00rootroot00000000000000 A Trivial Example
  Home

A Trivial Example

The application in this example has a log-view that displays messages sent by further instances of the same application.

The example demonstrates the use of the QtSingleApplication class to detect and communicate with a running instance of the application using the sendMessage() API. The messageReceived() signal is used to display received messages in a QTextEdit log.

 /****************************************************************************
 **
 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 ** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the Qt Solutions component.
 **
 ** You may use this file under the terms of the BSD license as follows:
 **
 ** "Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions are
 ** met:
 **   * Redistributions of source code must retain the above copyright
 **     notice, this list of conditions and the following disclaimer.
 **   * Redistributions in binary form must reproduce the above copyright
 **     notice, this list of conditions and the following disclaimer in
 **     the documentation and/or other materials provided with the
 **     distribution.
 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
 **     the names of its contributors may be used to endorse or promote
 **     products derived from this software without specific prior written
 **     permission.
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 **
 ****************************************************************************/

 #include <qtsingleapplication.h>
 #include <QtGui/QTextEdit>

 class TextEdit : public QTextEdit
 {
     Q_OBJECT
 public:
     TextEdit(QWidget *parent = 0)
         : QTextEdit(parent)
     {}
 public slots:
     void append(const QString &str)
     {
         QTextEdit::append(str);
     }
 };

 #include "main.moc"

 int main(int argc, char **argv)
 {
     QtSingleApplication instance(argc, argv);

The example has only the main entry point function. A QtSingleApplication object is created immediately.

     if (instance.sendMessage("Wake up!"))
         return 0;

If another instance of this application is already running, sendMessage() will succeed, and this instance just exits immediately.

     TextEdit logview;
     logview.setReadOnly(true);
     logview.show();

Otherwise the instance continues as normal and creates the user interface.

     instance.setActivationWindow(&logview);

     QObject::connect(&instance, SIGNAL(messageReceived(const QString&)),
                      &logview, SLOT(append(const QString&)));

     return instance.exec();

The logview object is also set as the application's activation window. Every time a message is received, the window will be raised and activated automatically.

The messageReceived() signal is also connected to the QTextEdit's append() slot. Every message received from further instances of this application will be displayed in the log.

Finally the event loop is entered.


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt Solutions
KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-members.html000066400000000000000000000737021252153257300306410ustar00rootroot00000000000000 List of All Members for QtSingleApplication
  Home

List of All Members for QtSingleApplication

This is the complete list of members for QtSingleApplication, including inherited members.


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt Solutions
KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-obsolete.html000066400000000000000000000037211252153257300310150ustar00rootroot00000000000000 Obsolete Members for QtSingleApplication
  Home

Obsolete Members for QtSingleApplication

The following class members are obsolete. They are provided to keep old source code working. We strongly advise against using them in new code.

Public Functions

void initialize ( bool dummy = true )   (obsolete)

Member Function Documentation

void QtSingleApplication::initialize ( bool dummy = true )


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt Solutions
KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.dcf000066400000000000000000000050711252153257300267730ustar00rootroot00000000000000
QtSingleApplication activateWindow activationWindow id isRunning messageReceived sendMessage setActivationWindow
QtSingleCoreApplication id isRunning messageReceived sendMessage
A non-GUI example
A Trivial Example
Loading Documents
Single Application
KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.html000066400000000000000000000520001252153257300271750ustar00rootroot00000000000000 QtSingleApplication Class Reference
  Home

QtSingleApplication Class Reference

The QtSingleApplication class provides an API to detect and communicate with running instances of an application. More...

 #include <QtSingleApplication>

Inherits QApplication.


Public Functions

QtSingleApplication ( int & argc, char ** argv, bool GUIenabled = true )
QtSingleApplication ( const QString & appId, int & argc, char ** argv )
QtSingleApplication ( int & argc, char ** argv, Type type )
QtSingleApplication ( Display * dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )
QtSingleApplication ( Display * dpy, int & argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )
QtSingleApplication ( Display * dpy, const QString & appId, int argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )
QWidget * activationWindow () const
QString id () const
bool isRunning ()
void setActivationWindow ( QWidget * aw, bool activateOnMessage = true )

Public Slots

void activateWindow ()
bool sendMessage ( const QString & message, int timeout = 5000 )

Signals

void messageReceived ( const QString & message )

Additional Inherited Members


Detailed Description

The QtSingleApplication class provides an API to detect and communicate with running instances of an application.

This class allows you to create applications where only one instance should be running at a time. I.e., if the user tries to launch another instance, the already running instance will be activated instead. Another usecase is a client-server system, where the first started instance will assume the role of server, and the later instances will act as clients of that server.

By default, the full path of the executable file is used to determine whether two processes are instances of the same application. You can also provide an explicit identifier string that will be compared instead.

The application should create the QtSingleApplication object early in the startup phase, and call isRunning() to find out if another instance of this application is already running. If isRunning() returns false, it means that no other instance is running, and this instance has assumed the role as the running instance. In this case, the application should continue with the initialization of the application user interface before entering the event loop with exec(), as normal.

The messageReceived() signal will be emitted when the running application receives messages from another instance of the same application. When a message is received it might be helpful to the user to raise the application so that it becomes visible. To facilitate this, QtSingleApplication provides the setActivationWindow() function and the activateWindow() slot.

If isRunning() returns true, another instance is already running. It may be alerted to the fact that another instance has started by using the sendMessage() function. Also data such as startup parameters (e.g. the name of the file the user wanted this new instance to open) can be passed to the running instance with this function. Then, the application should terminate (or enter client mode).

If isRunning() returns true, but sendMessage() fails, that is an indication that the running instance is frozen.

Here's an example that shows how to convert an existing application to use QtSingleApplication. It is very simple and does not make use of all QtSingleApplication's functionality (see the examples for that).

 // Original
 int main(int argc, char **argv)
 {
     QApplication app(argc, argv);

     MyMainWidget mmw;
     mmw.show();
     return app.exec();
 }

 // Single instance
 int main(int argc, char **argv)
 {
     QtSingleApplication app(argc, argv);

     if (app.isRunning())
         return !app.sendMessage(someDataString);

     MyMainWidget mmw;
     app.setActivationWindow(&mmw);
     mmw.show();
     return app.exec();
 }

Once this QtSingleApplication instance is destroyed (normally when the process exits or crashes), when the user next attempts to run the application this instance will not, of course, be encountered. The next instance to call isRunning() or sendMessage() will assume the role as the new running instance.

For console (non-GUI) applications, QtSingleCoreApplication may be used instead of this class, to avoid the dependency on the QtGui library.

See also QtSingleCoreApplication.


Member Function Documentation

QtSingleApplication::QtSingleApplication ( int & argc, char ** argv, bool GUIenabled = true )

Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). argc, argv, and GUIenabled are passed on to the QAppliation constructor.

If you are creating a console application (i.e. setting GUIenabled to false), you may consider using QtSingleCoreApplication instead.

QtSingleApplication::QtSingleApplication ( const QString & appId, int & argc, char ** argv )

Creates a QtSingleApplication object with the application identifier appId. argc and argv are passed on to the QAppliation constructor.

QtSingleApplication::QtSingleApplication ( int & argc, char ** argv, Type type )

Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). argc, argv, and type are passed on to the QAppliation constructor.

QtSingleApplication::QtSingleApplication ( Display * dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )

Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). dpy, visual, and cmap are passed on to the QApplication constructor.

QtSingleApplication::QtSingleApplication ( Display * dpy, int & argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )

Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). dpy, argc, argv, visual, and cmap are passed on to the QApplication constructor.

QtSingleApplication::QtSingleApplication ( Display * dpy, const QString & appId, int argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )

Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be appId. dpy, argc, argv, visual, and cmap are passed on to the QApplication constructor.

void QtSingleApplication::activateWindow ()   [slot]

De-minimizes, raises, and activates this application's activation window. This function does nothing if no activation window has been set.

This is a convenience function to show the user that this application instance has been activated when he has tried to start another instance.

This function should typically be called in response to the messageReceived() signal. By default, that will happen automatically, if an activation window has been set.

See also setActivationWindow(), messageReceived(), and initialize().

QWidget * QtSingleApplication::activationWindow () const

Returns the applications activation window if one has been set by calling setActivationWindow(), otherwise returns 0.

See also setActivationWindow().

QString QtSingleApplication::id () const

Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application.

bool QtSingleApplication::isRunning ()

Returns true if another instance of this application is running; otherwise false.

This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session).

See also sendMessage().

void QtSingleApplication::messageReceived ( const QString & message )   [signal]

This signal is emitted when the current instance receives a message from another instance of this application.

See also sendMessage(), setActivationWindow(), and activateWindow().

bool QtSingleApplication::sendMessage ( const QString & message, int timeout = 5000 )   [slot]

Tries to send the text message to the currently running instance. The QtSingleApplication object in the running instance will emit the messageReceived() signal when it receives the message.

This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within timeout milliseconds, this function return false.

See also isRunning() and messageReceived().

void QtSingleApplication::setActivationWindow ( QWidget * aw, bool activateOnMessage = true )

Sets the activation window of this application to aw. The activation window is the widget that will be activated by activateWindow(). This is typically the application's main window.

If activateOnMessage is true (the default), the window will be activated automatically every time a message is received, just prior to the messageReceived() signal being emitted.

See also activationWindow(), activateWindow(), and messageReceived().


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt Solutions
KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.index000066400000000000000000000317141252153257300273510ustar00rootroot00000000000000 KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.qhp000066400000000000000000000074111252153257300270270ustar00rootroot00000000000000 com.nokia.qtsolutions.qtsingleapplication_head qdoc qt solutions qtsingleapplication qt solutions qtsingleapplication
qtsingleapplication.html index.html qtsingleapplication-example-trivial.html qtsinglecoreapplication.html qtsingleapplication-example-loader.html qtsinglecoreapplication-example-console.html classic.css images/qt-logo.png KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-example-console.html000066400000000000000000000124151252153257300331450ustar00rootroot00000000000000 A non-GUI example
  Home

A non-GUI example

This example shows how to use the single-application functionality in a console application. It does not require the QtGui library at all.

The only differences from the GUI application usage demonstrated in the other examples are:

1) The .pro file should include qtsinglecoreapplication.pri instead of qtsingleapplication.pri

2) The class name is QtSingleCoreApplication instead of QtSingleApplication.

3) No calls are made regarding window activation, for obvious reasons.

console.pro:

 TEMPLATE   = app
 CONFIG    += console
 SOURCES   += main.cpp
 include(../../src/qtsinglecoreapplication.pri)
 QT -= gui

main.cpp:

 /****************************************************************************
 **
 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 ** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the Qt Solutions component.
 **
 ** You may use this file under the terms of the BSD license as follows:
 **
 ** "Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions are
 ** met:
 **   * Redistributions of source code must retain the above copyright
 **     notice, this list of conditions and the following disclaimer.
 **   * Redistributions in binary form must reproduce the above copyright
 **     notice, this list of conditions and the following disclaimer in
 **     the documentation and/or other materials provided with the
 **     distribution.
 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
 **     the names of its contributors may be used to endorse or promote
 **     products derived from this software without specific prior written
 **     permission.
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 **
 ****************************************************************************/

 #include "qtsinglecoreapplication.h"
 #include <QtCore/QDebug>

 void report(const QString& msg)
 {
     qDebug("[%i] %s", (int)QCoreApplication::applicationPid(), qPrintable(msg));
 }

 class MainClass : public QObject
 {
     Q_OBJECT
 public:
     MainClass()
         : QObject()
         {}

 public slots:
     void handleMessage(const QString& message)
         {
             report( "Message received: \"" + message + "\"");
         }
 };

 int main(int argc, char **argv)
 {
     report("Starting up");

     QtSingleCoreApplication app(argc, argv);

     if (app.isRunning()) {
         QString msg(QString("Hi master, I am %1.").arg(QCoreApplication::applicationPid()));
         bool sentok = app.sendMessage(msg, 2000);
         QString rep("Another instance is running, so I will exit.");
         rep += sentok ? " Message sent ok." : " Message sending failed; the other instance may be frozen.";
         report(rep);
         return 0;
     } else {
         report("No other instance is running; so I will.");
         MainClass mainObj;
         QObject::connect(&app, SIGNAL(messageReceived(const QString&)),
                          &mainObj, SLOT(handleMessage(const QString&)));
         return app.exec();
     }
 }

 #include "main.moc"


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt Solutions
KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-members.html000066400000000000000000000357771252153257300315240ustar00rootroot00000000000000 List of All Members for QtSingleCoreApplication
  Home

List of All Members for QtSingleCoreApplication

This is the complete list of members for QtSingleCoreApplication, including inherited members.


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt Solutions
KDocker-5.0/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication.html000066400000000000000000000235661252153257300300650ustar00rootroot00000000000000 QtSingleCoreApplication Class Reference
  Home

QtSingleCoreApplication Class Reference

A variant of the QtSingleApplication class for non-GUI applications. More...

 #include <QtSingleCoreApplication>

Inherits QCoreApplication.


Public Functions

QtSingleCoreApplication ( int & argc, char ** argv )
QtSingleCoreApplication ( const QString & appId, int & argc, char ** argv )
QString id () const
bool isRunning ()

Public Slots

bool sendMessage ( const QString & message, int timeout = 5000 )

Signals

void messageReceived ( const QString & message )

Additional Inherited Members


Detailed Description

A variant of the QtSingleApplication class for non-GUI applications.

This class is a variant of QtSingleApplication suited for use in console (non-GUI) applications. It is an extension of QCoreApplication (instead of QApplication). It does not require the QtGui library.

The API and usage is identical to QtSingleApplication, except that functions relating to the "activation window" are not present, for obvious reasons. Please refer to the QtSingleApplication documentation for explanation of the usage.

A QtSingleCoreApplication instance can communicate to a QtSingleApplication instance if they share the same application id. Hence, this class can be used to create a light-weight command-line tool that sends commands to a GUI application.

See also QtSingleApplication.


Member Function Documentation

QtSingleCoreApplication::QtSingleCoreApplication ( int & argc, char ** argv )

Creates a QtSingleCoreApplication object. The application identifier will be QCoreApplication::applicationFilePath(). argc and argv are passed on to the QCoreAppliation constructor.

QtSingleCoreApplication::QtSingleCoreApplication ( const QString & appId, int & argc, char ** argv )

Creates a QtSingleCoreApplication object with the application identifier appId. argc and argv are passed on to the QCoreAppliation constructor.

QString QtSingleCoreApplication::id () const

Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application.

bool QtSingleCoreApplication::isRunning ()

Returns true if another instance of this application is running; otherwise false.

This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session).

See also sendMessage().

void QtSingleCoreApplication::messageReceived ( const QString & message )   [signal]

This signal is emitted when the current instance receives a message from another instance of this application.

See also sendMessage().

bool QtSingleCoreApplication::sendMessage ( const QString & message, int timeout = 5000 )   [slot]

Tries to send the text message to the currently running instance. The QtSingleCoreApplication object in the running instance will emit the messageReceived() signal when it receives the message.

This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within timeout milliseconds, this function return false.

See also isRunning() and messageReceived().


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt Solutions
KDocker-5.0/3rdparty/qtsingleapplication/doc/index.qdoc000066400000000000000000000064061252153257300232610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page index.html \title Single Application \section1 Description The QtSingleApplication component provides support for applications that can be only started once per user. For some applications it is useful or even critical that they are started only once by any user. Future attempts to start the application should activate any already running instance, and possibly perform requested actions, e.g. loading a file, in that instance. The QtSingleApplication class provides an interface to detect a running instance, and to send command strings to that instance. For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui. \section1 Classes \list \i QtSingleApplication \i QtSingleCoreApplication\endlist \section1 Examples \list \i \link qtsingleapplication-example-trivial.html A Trivial Example \endlink \i \link qtsingleapplication-example-loader.html Loading Documents \endlink \i \link qtsinglecoreapplication-example-console.html A Non-GUI Example \endlink \endlist \section1 Tested platforms \list \i Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005 \i Qt 4.4, 4.5 / Linux / gcc \i Qt 4.4, 4.5 / MacOS X 10.5 / gcc \endlist */ KDocker-5.0/3rdparty/qtsingleapplication/examples/000077500000000000000000000000001252153257300223455ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/examples/console/000077500000000000000000000000001252153257300240075ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/examples/console/console.pro000066400000000000000000000001651252153257300261750ustar00rootroot00000000000000TEMPLATE = app CONFIG += console SOURCES += main.cpp include(../../src/qtsinglecoreapplication.pri) QT -= gui KDocker-5.0/3rdparty/qtsingleapplication/examples/console/console.qdoc000066400000000000000000000052411252153257300263230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qtsinglecoreapplication-example-console.html \title A non-GUI example This example shows how to use the single-application functionality in a console application. It does not require the \c QtGui library at all. The only differences from the GUI application usage demonstrated in the other examples are: 1) The \c.pro file should include \c qtsinglecoreapplication.pri instead of \c qtsingleapplication.pri 2) The class name is \c QtSingleCoreApplication instead of \c QtSingleApplication. 3) No calls are made regarding window activation, for obvious reasons. console.pro: \quotefile console/console.pro main.cpp: \quotefile console/main.cpp */ KDocker-5.0/3rdparty/qtsingleapplication/examples/console/main.cpp000066400000000000000000000062161252153257300254440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtsinglecoreapplication.h" #include void report(const QString& msg) { qDebug("[%i] %s", (int)QCoreApplication::applicationPid(), qPrintable(msg)); } class MainClass : public QObject { Q_OBJECT public: MainClass() : QObject() {} public slots: void handleMessage(const QString& message) { report( "Message received: \"" + message + "\""); } }; int main(int argc, char **argv) { report("Starting up"); QtSingleCoreApplication app(argc, argv); if (app.isRunning()) { QString msg(QString("Hi master, I am %1.").arg(QCoreApplication::applicationPid())); bool sentok = app.sendMessage(msg, 2000); QString rep("Another instance is running, so I will exit."); rep += sentok ? " Message sent ok." : " Message sending failed; the other instance may be frozen."; report(rep); return 0; } else { report("No other instance is running; so I will."); MainClass mainObj; QObject::connect(&app, SIGNAL(messageReceived(const QString&)), &mainObj, SLOT(handleMessage(const QString&))); return app.exec(); } } #include "main.moc" KDocker-5.0/3rdparty/qtsingleapplication/examples/examples.pro000066400000000000000000000001111252153257300246760ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = trivial \ loader \ console KDocker-5.0/3rdparty/qtsingleapplication/examples/loader/000077500000000000000000000000001252153257300236135ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/examples/loader/file1.qsl000066400000000000000000000000071252153257300253310ustar00rootroot00000000000000File 1 KDocker-5.0/3rdparty/qtsingleapplication/examples/loader/file2.qsl000066400000000000000000000000071252153257300253320ustar00rootroot00000000000000File 2 KDocker-5.0/3rdparty/qtsingleapplication/examples/loader/loader.pro000066400000000000000000000002061252153257300256010ustar00rootroot00000000000000greaterThan(QT_MAJOR_VERSION, 4): QT += printsupport TEMPLATE = app include(../../src/qtsingleapplication.pri) SOURCES += main.cpp KDocker-5.0/3rdparty/qtsingleapplication/examples/loader/loader.qdoc000066400000000000000000000071151252153257300257350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qtsingleapplication-example-loader.html \title Loading Documents The application in this example loads or prints the documents passed as commandline parameters to further instances of this application. \quotefromfile loader/main.cpp \printuntil }; The user interface in this application is a QMainWindow subclass with a QMdiArea as the central widget. It implements a slot \c handleMessage() that will be connected to the messageReceived() signal of the QtSingleApplication class. \printuntil } The MainWindow constructor creates a minimal user interface. \printto case Print: The handleMessage() slot interprets the message passed in as a filename that can be prepended with \e /print to indicate that the file should just be printed rather than loaded. \printto #include Loading the file will also activate the window. \printto mw The \c main entry point function creates a QtSingleApplication object, and creates a message to send to a running instance of the application. If the message was sent successfully the process exits immediately. \printuntil } If the message could not be sent the application starts up. Note that \c false is passed to the call to setActivationWindow() to prevent automatic activation for every message received, e.g. when the application should just print a file. Instead, the message handling function determines whether activation is requested, and signals that by emitting the needToShow() signal. This is then simply connected directly to QtSingleApplication's activateWindow() slot. */ KDocker-5.0/3rdparty/qtsingleapplication/examples/loader/main.cpp000066400000000000000000000100641252153257300252440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); public slots: void handleMessage(const QString& message); signals: void needToShow(); private: QMdiArea *workspace; }; MainWindow::MainWindow() { workspace = new QMdiArea(this); setCentralWidget(workspace); } void MainWindow::handleMessage(const QString& message) { enum Action { Nothing, Open, Print } action; action = Nothing; QString filename = message; if (message.toLower().startsWith("/print ")) { filename = filename.mid(7); action = Print; } else if (!message.isEmpty()) { action = Open; } if (action == Nothing) { emit needToShow(); return; } QFile file(filename); QString contents; if (file.open(QIODevice::ReadOnly)) contents = file.readAll(); else contents = "[[Error: Could not load file " + filename + "]]"; QTextEdit *view = new QTextEdit; view->setPlainText(contents); switch(action) { case Print: { QPrinter printer; view->print(&printer); delete view; } break; case Open: { workspace->addSubWindow(view); view->setWindowTitle(message); view->show(); emit needToShow(); } break; default: break; }; } #include "main.moc" int main(int argc, char **argv) { QtSingleApplication instance("File loader QtSingleApplication example", argc, argv); QString message; for (int a = 1; a < argc; ++a) { message += argv[a]; if (a < argc-1) message += " "; } if (instance.sendMessage(message)) return 0; MainWindow mw; mw.handleMessage(message); mw.show(); QObject::connect(&instance, SIGNAL(messageReceived(const QString&)), &mw, SLOT(handleMessage(const QString&))); instance.setActivationWindow(&mw, false); QObject::connect(&mw, SIGNAL(needToShow()), &instance, SLOT(activateWindow())); return instance.exec(); } KDocker-5.0/3rdparty/qtsingleapplication/examples/trivial/000077500000000000000000000000001252153257300240175ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/examples/trivial/main.cpp000066400000000000000000000052121252153257300254470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include class TextEdit : public QTextEdit { Q_OBJECT public: TextEdit(QWidget *parent = 0) : QTextEdit(parent) {} public slots: void append(const QString &str) { QTextEdit::append(str); } }; #include "main.moc" int main(int argc, char **argv) { QtSingleApplication instance(argc, argv); if (instance.sendMessage("Wake up!")) return 0; TextEdit logview; logview.setReadOnly(true); logview.show(); instance.setActivationWindow(&logview); QObject::connect(&instance, SIGNAL(messageReceived(const QString&)), &logview, SLOT(append(const QString&))); return instance.exec(); } KDocker-5.0/3rdparty/qtsingleapplication/examples/trivial/trivial.pro000066400000000000000000000001211252153257300262050ustar00rootroot00000000000000TEMPLATE = app include(../../src/qtsingleapplication.pri) SOURCES += main.cpp KDocker-5.0/3rdparty/qtsingleapplication/examples/trivial/trivial.qdoc000066400000000000000000000064511252153257300263470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qtsingleapplication-example-trivial.html \title A Trivial Example The application in this example has a log-view that displays messages sent by further instances of the same application. The example demonstrates the use of the QtSingleApplication class to detect and communicate with a running instance of the application using the sendMessage() API. The messageReceived() signal is used to display received messages in a QTextEdit log. \quotefromfile trivial/main.cpp \printuntil instance The example has only the \c main entry point function. A QtSingleApplication object is created immediately. \printuntil return If another instance of this application is already running, sendMessage() will succeed, and this instance just exits immediately. \printuntil show() Otherwise the instance continues as normal and creates the user interface. \printuntil return instance.exec(); The \c logview object is also set as the application's activation window. Every time a message is received, the window will be raised and activated automatically. The messageReceived() signal is also connected to the QTextEdit's append() slot. Every message received from further instances of this application will be displayed in the log. Finally the event loop is entered. */ KDocker-5.0/3rdparty/qtsingleapplication/qtsingleapplication.pro000066400000000000000000000001651252153257300253250ustar00rootroot00000000000000TEMPLATE=subdirs CONFIG += ordered include(common.pri) qtsingleapplication-uselib:SUBDIRS=buildlib SUBDIRS+=examples KDocker-5.0/3rdparty/qtsingleapplication/src/000077500000000000000000000000001252153257300213165ustar00rootroot00000000000000KDocker-5.0/3rdparty/qtsingleapplication/src/QtLockedFile000066400000000000000000000000321252153257300235420ustar00rootroot00000000000000#include "qtlockedfile.h" KDocker-5.0/3rdparty/qtsingleapplication/src/QtSingleApplication000066400000000000000000000000411252153257300251460ustar00rootroot00000000000000#include "qtsingleapplication.h" KDocker-5.0/3rdparty/qtsingleapplication/src/qtlocalpeer.cpp000066400000000000000000000150411252153257300243360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlocalpeer.h" #include #include #if defined(Q_OS_WIN) #include #include typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); static PProcessIdToSessionId pProcessIdToSessionId = 0; #endif #if defined(Q_OS_UNIX) #include #include #include #endif namespace QtLP_Private { #include "qtlockedfile.cpp" #if defined(Q_OS_WIN) #include "qtlockedfile_win.cpp" #else #include "qtlockedfile_unix.cpp" #endif } const char* QtLocalPeer::ack = "ack"; QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) : QObject(parent), id(appId) { QString prefix = id; if (id.isEmpty()) { id = QCoreApplication::applicationFilePath(); #if defined(Q_OS_WIN) id = id.toLower(); #endif prefix = id.section(QLatin1Char('/'), -1); } prefix.remove(QRegExp("[^a-zA-Z]")); prefix.truncate(6); QByteArray idc = id.toUtf8(); quint16 idNum = qChecksum(idc.constData(), idc.size()); socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16); #if defined(Q_OS_WIN) if (!pProcessIdToSessionId) { QLibrary lib("kernel32"); pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); } if (pProcessIdToSessionId) { DWORD sessionId = 0; pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); socketName += QLatin1Char('-') + QString::number(sessionId, 16); } #else socketName += QLatin1Char('-') + QString::number(::getuid(), 16); #endif server = new QLocalServer(this); QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile"); lockFile.setFileName(lockName); lockFile.open(QIODevice::ReadWrite); } bool QtLocalPeer::isClient() { if (lockFile.isLocked()) return false; if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) return true; bool res = server->listen(socketName); #if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) // ### Workaround if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); res = server->listen(socketName); } #endif if (!res) qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); return false; } bool QtLocalPeer::sendMessage(const QString &message, int timeout) { if (!isClient()) return false; QLocalSocket socket; bool connOk = false; for(int i = 0; i < 2; i++) { // Try twice, in case the other instance is just starting up socket.connectToServer(socketName); connOk = socket.waitForConnected(timeout/2); if (connOk || i) break; int ms = 250; #if defined(Q_OS_WIN) Sleep(DWORD(ms)); #else struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; nanosleep(&ts, NULL); #endif } if (!connOk) return false; QByteArray uMsg(message.toUtf8()); QDataStream ds(&socket); ds.writeBytes(uMsg.constData(), uMsg.size()); bool res = socket.waitForBytesWritten(timeout); if (res) { res &= socket.waitForReadyRead(timeout); // wait for ack if (res) res &= (socket.read(qstrlen(ack)) == ack); } return res; } void QtLocalPeer::receiveConnection() { QLocalSocket* socket = server->nextPendingConnection(); if (!socket) return; while (socket->bytesAvailable() < (int)sizeof(quint32)) socket->waitForReadyRead(); QDataStream ds(socket); QByteArray uMsg; quint32 remaining; ds >> remaining; uMsg.resize(remaining); int got = 0; char* uMsgBuf = uMsg.data(); do { got = ds.readRawData(uMsgBuf, remaining); remaining -= got; uMsgBuf += got; } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); if (got < 0) { qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); delete socket; return; } QString message(QString::fromUtf8(uMsg)); socket->write(ack, qstrlen(ack)); socket->waitForBytesWritten(1000); socket->waitForDisconnected(1000); // make sure client reads ack delete socket; emit messageReceived(message); //### (might take a long time to return) } KDocker-5.0/3rdparty/qtsingleapplication/src/qtlocalpeer.h000066400000000000000000000052051252153257300240040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTLOCALPEER_H #define QTLOCALPEER_H #include #include #include #include "qtlockedfile.h" class QtLocalPeer : public QObject { Q_OBJECT public: QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); bool isClient(); bool sendMessage(const QString &message, int timeout); QString applicationId() const { return id; } Q_SIGNALS: void messageReceived(const QString &message); protected Q_SLOTS: void receiveConnection(); protected: QString id; QString socketName; QLocalServer* server; QtLP_Private::QtLockedFile lockFile; private: static const char* ack; }; #endif // QTLOCALPEER_H KDocker-5.0/3rdparty/qtsingleapplication/src/qtlockedfile.cpp000066400000000000000000000137421252153257300244770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlockedfile.h" /*! \class QtLockedFile \brief The QtLockedFile class extends QFile with advisory locking functions. A file may be locked in read or write mode. Multiple instances of \e QtLockedFile, created in multiple processes running on the same machine, may have a file locked in read mode. Exactly one instance may have it locked in write mode. A read and a write lock cannot exist simultaneously on the same file. The file locks are advisory. This means that nothing prevents another process from manipulating a locked file using QFile or file system functions offered by the OS. Serialization is only guaranteed if all processes that access the file use QLockedFile. Also, while holding a lock on a file, a process must not open the same file again (through any API), or locks can be unexpectedly lost. The lock provided by an instance of \e QtLockedFile is released whenever the program terminates. This is true even when the program crashes and no destructors are called. */ /*! \enum QtLockedFile::LockMode This enum describes the available lock modes. \value ReadLock A read lock. \value WriteLock A write lock. \value NoLock Neither a read lock nor a write lock. */ /*! Constructs an unlocked \e QtLockedFile object. This constructor behaves in the same way as \e QFile::QFile(). \sa QFile::QFile() */ QtLockedFile::QtLockedFile() : QFile() { #ifdef Q_OS_WIN wmutex = 0; rmutex = 0; #endif m_lock_mode = NoLock; } /*! Constructs an unlocked QtLockedFile object with file \a name. This constructor behaves in the same way as \e QFile::QFile(const QString&). \sa QFile::QFile() */ QtLockedFile::QtLockedFile(const QString &name) : QFile(name) { #ifdef Q_OS_WIN wmutex = 0; rmutex = 0; #endif m_lock_mode = NoLock; } /*! Opens the file in OpenMode \a mode. This is identical to QFile::open(), with the one exception that the Truncate mode flag is disallowed. Truncation would conflict with the advisory file locking, since the file would be modified before the write lock is obtained. If truncation is required, use resize(0) after obtaining the write lock. Returns true if successful; otherwise false. \sa QFile::open(), QFile::resize() */ bool QtLockedFile::open(OpenMode mode) { if (mode & QIODevice::Truncate) { qWarning("QtLockedFile::open(): Truncate mode not allowed."); return false; } return QFile::open(mode); } /*! Returns \e true if this object has a in read or write lock; otherwise returns \e false. \sa lockMode() */ bool QtLockedFile::isLocked() const { return m_lock_mode != NoLock; } /*! Returns the type of lock currently held by this object, or \e QtLockedFile::NoLock. \sa isLocked() */ QtLockedFile::LockMode QtLockedFile::lockMode() const { return m_lock_mode; } /*! \fn bool QtLockedFile::lock(LockMode mode, bool block = true) Obtains a lock of type \a mode. The file must be opened before it can be locked. If \a block is true, this function will block until the lock is aquired. If \a block is false, this function returns \e false immediately if the lock cannot be aquired. If this object already has a lock of type \a mode, this function returns \e true immediately. If this object has a lock of a different type than \a mode, the lock is first released and then a new lock is obtained. This function returns \e true if, after it executes, the file is locked by this object, and \e false otherwise. \sa unlock(), isLocked(), lockMode() */ /*! \fn bool QtLockedFile::unlock() Releases a lock. If the object has no lock, this function returns immediately. This function returns \e true if, after it executes, the file is not locked by this object, and \e false otherwise. \sa lock(), isLocked(), lockMode() */ /*! \fn QtLockedFile::~QtLockedFile() Destroys the \e QtLockedFile object. If any locks were held, they are released. */ KDocker-5.0/3rdparty/qtsingleapplication/src/qtlockedfile.h000066400000000000000000000063071252153257300241430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTLOCKEDFILE_H #define QTLOCKEDFILE_H #include #ifdef Q_OS_WIN #include #endif #if defined(Q_OS_WIN) # if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) # define QT_QTLOCKEDFILE_EXPORT # elif defined(QT_QTLOCKEDFILE_IMPORT) # if defined(QT_QTLOCKEDFILE_EXPORT) # undef QT_QTLOCKEDFILE_EXPORT # endif # define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) # elif defined(QT_QTLOCKEDFILE_EXPORT) # undef QT_QTLOCKEDFILE_EXPORT # define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) # endif #else # define QT_QTLOCKEDFILE_EXPORT #endif namespace QtLP_Private { class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile { public: enum LockMode { NoLock = 0, ReadLock, WriteLock }; QtLockedFile(); QtLockedFile(const QString &name); ~QtLockedFile(); bool open(OpenMode mode); bool lock(LockMode mode, bool block = true); bool unlock(); bool isLocked() const; LockMode lockMode() const; private: #ifdef Q_OS_WIN Qt::HANDLE wmutex; Qt::HANDLE rmutex; QVector rmutexes; QString mutexname; Qt::HANDLE getMutexHandle(int idx, bool doCreate); bool waitMutex(Qt::HANDLE mutex, bool doBlock); #endif LockMode m_lock_mode; }; } #endif KDocker-5.0/3rdparty/qtsingleapplication/src/qtlockedfile_unix.cpp000066400000000000000000000066141252153257300255420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include "qtlockedfile.h" bool QtLockedFile::lock(LockMode mode, bool block) { if (!isOpen()) { qWarning("QtLockedFile::lock(): file is not opened"); return false; } if (mode == NoLock) return unlock(); if (mode == m_lock_mode) return true; if (m_lock_mode != NoLock) unlock(); struct flock fl; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; int cmd = block ? F_SETLKW : F_SETLK; int ret = fcntl(handle(), cmd, &fl); if (ret == -1) { if (errno != EINTR && errno != EAGAIN) qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); return false; } m_lock_mode = mode; return true; } bool QtLockedFile::unlock() { if (!isOpen()) { qWarning("QtLockedFile::unlock(): file is not opened"); return false; } if (!isLocked()) return true; struct flock fl; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_type = F_UNLCK; int ret = fcntl(handle(), F_SETLKW, &fl); if (ret == -1) { qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); return false; } m_lock_mode = NoLock; return true; } QtLockedFile::~QtLockedFile() { if (isOpen()) unlock(); } KDocker-5.0/3rdparty/qtsingleapplication/src/qtlockedfile_win.cpp000066400000000000000000000146611252153257300253550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlockedfile.h" #include #include #define MUTEX_PREFIX "QtLockedFile mutex " // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS #define MAX_READERS MAXIMUM_WAIT_OBJECTS #if QT_VERSION >= 0x050000 #define QT_WA(unicode, ansi) unicode #endif Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) { if (mutexname.isEmpty()) { QFileInfo fi(*this); mutexname = QString::fromLatin1(MUTEX_PREFIX) + fi.absoluteFilePath().toLower(); } QString mname(mutexname); if (idx >= 0) mname += QString::number(idx); Qt::HANDLE mutex; if (doCreate) { QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); if (!mutex) { qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); return 0; } } else { QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); if (!mutex) { if (GetLastError() != ERROR_FILE_NOT_FOUND) qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); return 0; } } return mutex; } bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) { Q_ASSERT(mutex); DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); switch (res) { case WAIT_OBJECT_0: case WAIT_ABANDONED: return true; break; case WAIT_TIMEOUT: break; default: qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); } return false; } bool QtLockedFile::lock(LockMode mode, bool block) { if (!isOpen()) { qWarning("QtLockedFile::lock(): file is not opened"); return false; } if (mode == NoLock) return unlock(); if (mode == m_lock_mode) return true; if (m_lock_mode != NoLock) unlock(); if (!wmutex && !(wmutex = getMutexHandle(-1, true))) return false; if (!waitMutex(wmutex, block)) return false; if (mode == ReadLock) { int idx = 0; for (; idx < MAX_READERS; idx++) { rmutex = getMutexHandle(idx, false); if (!rmutex || waitMutex(rmutex, false)) break; CloseHandle(rmutex); } bool ok = true; if (idx >= MAX_READERS) { qWarning("QtLockedFile::lock(): too many readers"); rmutex = 0; ok = false; } else if (!rmutex) { rmutex = getMutexHandle(idx, true); if (!rmutex || !waitMutex(rmutex, false)) ok = false; } if (!ok && rmutex) { CloseHandle(rmutex); rmutex = 0; } ReleaseMutex(wmutex); if (!ok) return false; } else { Q_ASSERT(rmutexes.isEmpty()); for (int i = 0; i < MAX_READERS; i++) { Qt::HANDLE mutex = getMutexHandle(i, false); if (mutex) rmutexes.append(mutex); } if (rmutexes.size()) { DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), TRUE, block ? INFINITE : 0); if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { if (res != WAIT_TIMEOUT) qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky unlock(); return false; } } } m_lock_mode = mode; return true; } bool QtLockedFile::unlock() { if (!isOpen()) { qWarning("QtLockedFile::unlock(): file is not opened"); return false; } if (!isLocked()) return true; if (m_lock_mode == ReadLock) { ReleaseMutex(rmutex); CloseHandle(rmutex); rmutex = 0; } else { foreach(Qt::HANDLE mutex, rmutexes) { ReleaseMutex(mutex); CloseHandle(mutex); } rmutexes.clear(); ReleaseMutex(wmutex); } m_lock_mode = QtLockedFile::NoLock; return true; } QtLockedFile::~QtLockedFile() { if (isOpen()) unlock(); if (wmutex) CloseHandle(wmutex); } KDocker-5.0/3rdparty/qtsingleapplication/src/qtsingleapplication.cpp000066400000000000000000000270101252153257300260740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtsingleapplication.h" #include "qtlocalpeer.h" #include /*! \class QtSingleApplication qtsingleapplication.h \brief The QtSingleApplication class provides an API to detect and communicate with running instances of an application. This class allows you to create applications where only one instance should be running at a time. I.e., if the user tries to launch another instance, the already running instance will be activated instead. Another usecase is a client-server system, where the first started instance will assume the role of server, and the later instances will act as clients of that server. By default, the full path of the executable file is used to determine whether two processes are instances of the same application. You can also provide an explicit identifier string that will be compared instead. The application should create the QtSingleApplication object early in the startup phase, and call isRunning() to find out if another instance of this application is already running. If isRunning() returns false, it means that no other instance is running, and this instance has assumed the role as the running instance. In this case, the application should continue with the initialization of the application user interface before entering the event loop with exec(), as normal. The messageReceived() signal will be emitted when the running application receives messages from another instance of the same application. When a message is received it might be helpful to the user to raise the application so that it becomes visible. To facilitate this, QtSingleApplication provides the setActivationWindow() function and the activateWindow() slot. If isRunning() returns true, another instance is already running. It may be alerted to the fact that another instance has started by using the sendMessage() function. Also data such as startup parameters (e.g. the name of the file the user wanted this new instance to open) can be passed to the running instance with this function. Then, the application should terminate (or enter client mode). If isRunning() returns true, but sendMessage() fails, that is an indication that the running instance is frozen. Here's an example that shows how to convert an existing application to use QtSingleApplication. It is very simple and does not make use of all QtSingleApplication's functionality (see the examples for that). \code // Original int main(int argc, char **argv) { QApplication app(argc, argv); MyMainWidget mmw; mmw.show(); return app.exec(); } // Single instance int main(int argc, char **argv) { QtSingleApplication app(argc, argv); if (app.isRunning()) return !app.sendMessage(someDataString); MyMainWidget mmw; app.setActivationWindow(&mmw); mmw.show(); return app.exec(); } \endcode Once this QtSingleApplication instance is destroyed (normally when the process exits or crashes), when the user next attempts to run the application this instance will not, of course, be encountered. The next instance to call isRunning() or sendMessage() will assume the role as the new running instance. For console (non-GUI) applications, QtSingleCoreApplication may be used instead of this class, to avoid the dependency on the QtGui library. \sa QtSingleCoreApplication */ void QtSingleApplication::sysInit(const QString &appId) { actWin = 0; peer = new QtLocalPeer(this, appId); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a argv, and \a GUIenabled are passed on to the QAppliation constructor. If you are creating a console application (i.e. setting \a GUIenabled to false), you may consider using QtSingleCoreApplication instead. */ QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) : QApplication(argc, argv, GUIenabled) { sysInit(); } /*! Creates a QtSingleApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QAppliation constructor. */ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) : QApplication(argc, argv) { sysInit(appId); } #if QT_VERSION < 0x050000 /*! Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a argv, and \a type are passed on to the QAppliation constructor. */ QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) : QApplication(argc, argv, type) { sysInit(); } # if defined(Q_WS_X11) /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, visual, cmap) { sysInit(); } /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a argv, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, argc, argv, visual, cmap) { sysInit(); } /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be \a appId. \a dpy, \a argc, \a argv, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, argc, argv, visual, cmap) { sysInit(appId); } # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 /*! Returns true if another instance of this application is running; otherwise false. This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session). \sa sendMessage() */ bool QtSingleApplication::isRunning() { return peer->isClient(); } /*! Tries to send the text \a message to the currently running instance. The QtSingleApplication object in the running instance will emit the messageReceived() signal when it receives the message. This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() */ bool QtSingleApplication::sendMessage(const QString &message, int timeout) { return peer->sendMessage(message, timeout); } /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. */ QString QtSingleApplication::id() const { return peer->applicationId(); } /*! Sets the activation window of this application to \a aw. The activation window is the widget that will be activated by activateWindow(). This is typically the application's main window. If \a activateOnMessage is true (the default), the window will be activated automatically every time a message is received, just prior to the messageReceived() signal being emitted. \sa activateWindow(), messageReceived() */ void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) { actWin = aw; if (activateOnMessage) connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); else disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); } /*! Returns the applications activation window if one has been set by calling setActivationWindow(), otherwise returns 0. \sa setActivationWindow() */ QWidget* QtSingleApplication::activationWindow() const { return actWin; } /*! De-minimizes, raises, and activates this application's activation window. This function does nothing if no activation window has been set. This is a convenience function to show the user that this application instance has been activated when he has tried to start another instance. This function should typically be called in response to the messageReceived() signal. By default, that will happen automatically, if an activation window has been set. \sa setActivationWindow(), messageReceived(), initialize() */ void QtSingleApplication::activateWindow() { if (actWin) { actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); actWin->raise(); actWin->activateWindow(); } } /*! \fn void QtSingleApplication::messageReceived(const QString& message) This signal is emitted when the current instance receives a \a message from another instance of this application. \sa sendMessage(), setActivationWindow(), activateWindow() */ /*! \fn void QtSingleApplication::initialize(bool dummy = true) \obsolete */ KDocker-5.0/3rdparty/qtsingleapplication/src/qtsingleapplication.h000066400000000000000000000076171252153257300255540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTSINGLEAPPLICATION_H #define QTSINGLEAPPLICATION_H #include class QtLocalPeer; #if defined(Q_OS_WIN) # if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) # define QT_QTSINGLEAPPLICATION_EXPORT # elif defined(QT_QTSINGLEAPPLICATION_IMPORT) # if defined(QT_QTSINGLEAPPLICATION_EXPORT) # undef QT_QTSINGLEAPPLICATION_EXPORT # endif # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) # elif defined(QT_QTSINGLEAPPLICATION_EXPORT) # undef QT_QTSINGLEAPPLICATION_EXPORT # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) # endif #else # define QT_QTSINGLEAPPLICATION_EXPORT #endif class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication { Q_OBJECT public: QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); QtSingleApplication(const QString &id, int &argc, char **argv); #if QT_VERSION < 0x050000 QtSingleApplication(int &argc, char **argv, Type type); # if defined(Q_WS_X11) QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 bool isRunning(); QString id() const; void setActivationWindow(QWidget* aw, bool activateOnMessage = true); QWidget* activationWindow() const; // Obsolete: void initialize(bool dummy = true) { isRunning(); Q_UNUSED(dummy) } public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000); void activateWindow(); Q_SIGNALS: void messageReceived(const QString &message); private: void sysInit(const QString &appId = QString()); QtLocalPeer *peer; QWidget *actWin; }; #endif // QTSINGLEAPPLICATION_H KDocker-5.0/3rdparty/qtsingleapplication/src/qtsingleapplication.pri000066400000000000000000000011101252153257300260750ustar00rootroot00000000000000include(../common.pri) INCLUDEPATH += $$PWD DEPENDPATH += $$PWD QT *= network greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets qtsingleapplication-uselib:!qtsingleapplication-buildlib { LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME } else { SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h } win32 { contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT } KDocker-5.0/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.cpp000066400000000000000000000123551252153257300267530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtsinglecoreapplication.h" #include "qtlocalpeer.h" /*! \class QtSingleCoreApplication qtsinglecoreapplication.h \brief A variant of the QtSingleApplication class for non-GUI applications. This class is a variant of QtSingleApplication suited for use in console (non-GUI) applications. It is an extension of QCoreApplication (instead of QApplication). It does not require the QtGui library. The API and usage is identical to QtSingleApplication, except that functions relating to the "activation window" are not present, for obvious reasons. Please refer to the QtSingleApplication documentation for explanation of the usage. A QtSingleCoreApplication instance can communicate to a QtSingleApplication instance if they share the same application id. Hence, this class can be used to create a light-weight command-line tool that sends commands to a GUI application. \sa QtSingleApplication */ /*! Creates a QtSingleCoreApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc and \a argv are passed on to the QCoreAppliation constructor. */ QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) : QCoreApplication(argc, argv) { peer = new QtLocalPeer(this); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Creates a QtSingleCoreApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QCoreAppliation constructor. */ QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) : QCoreApplication(argc, argv) { peer = new QtLocalPeer(this, appId); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Returns true if another instance of this application is running; otherwise false. This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session). \sa sendMessage() */ bool QtSingleCoreApplication::isRunning() { return peer->isClient(); } /*! Tries to send the text \a message to the currently running instance. The QtSingleCoreApplication object in the running instance will emit the messageReceived() signal when it receives the message. This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() */ bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) { return peer->sendMessage(message, timeout); } /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. */ QString QtSingleCoreApplication::id() const { return peer->applicationId(); } /*! \fn void QtSingleCoreApplication::messageReceived(const QString& message) This signal is emitted when the current instance receives a \a message from another instance of this application. \sa sendMessage() */ KDocker-5.0/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.h000066400000000000000000000050251252153257300264140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTSINGLECOREAPPLICATION_H #define QTSINGLECOREAPPLICATION_H #include class QtLocalPeer; class QtSingleCoreApplication : public QCoreApplication { Q_OBJECT public: QtSingleCoreApplication(int &argc, char **argv); QtSingleCoreApplication(const QString &id, int &argc, char **argv); bool isRunning(); QString id() const; public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000); Q_SIGNALS: void messageReceived(const QString &message); private: QtLocalPeer* peer; }; #endif // QTSINGLECOREAPPLICATION_H KDocker-5.0/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.pri000066400000000000000000000005041252153257300267540ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp QT *= network win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) } KDocker-5.0/AUTHORS000066400000000000000000000002401252153257300137510ustar00rootroot00000000000000John Schember (john@nachtimwald.com) - Maintainer Dave Butcher - Contributor Girish Ramakrishnan - Original creator. He is not an active member of the project. KDocker-5.0/BUGS000066400000000000000000000001001252153257300133570ustar00rootroot00000000000000Bugs and wishes to https://github.com/user-none/KDocker/issues KDocker-5.0/COPYING000066400000000000000000000432541252153257300137500ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. KDocker-5.0/CREDITS000066400000000000000000000016451252153257300137330ustar00rootroot00000000000000Code ---- Maintained by John Schember (john@nachtimwald.com) Originally created by Girish Ramakrishnan. He is not an active member of the project. Artwork ------- KDocker Icon by Marcel Dierkes (marcel dot dierkes at gmx dot de) 4.x Translations ------------ Italian - Alessio Cassibba (x-drum@zerodev.it) 1.3 Translations ------------ Spanish translations by Edulix (edulix at tumundoweb dot com) French translations by Al (altrash at altern &dot& org) Czech translations by Jiri Hofman (jiri dot hofman # a.t # tut*fi) Russian translations by Aleksey Kirpichnikov (coder *at* paco dot net) Brazilian Portugese by Paulo Ruthes (paulo.ruthes $at$ $uol$ com dot br) German translations by Thomas Runge (thomas dot r3 at gmx dot de) Polish translation by KonMan (dedalus !at o2 dot pl) Indonesian translation by Eko Prasetiyo (e hiphen prast at spymac dot com) Italian translations by Alessio Cassibba (swapon at gmail dot com) KDocker-5.0/ChangeLog000066400000000000000000000144521252153257300144650ustar00rootroot00000000000000for version 5.0 - Support Qt 5. for version 4.9 - Assorted bug fixed (mostly minimal). for version 4.8 - Format help argument output so that it wraps at a 79 characters. - Scrolling (mouse scroll wheel event) on icon can raise and iconify window. - Add option -e option to specify pattern matching type. Accepts n = normal, r = regex, u = unix wildcard, w = wildcard, x = xml schema 1.1. - Add option -j to enable case senstive matching. - Add option -k to set regex minimal matching. for version 4.7 - Fix install location of icon referenced by .desktop file so that it shows properly. - Fix bug where build fails with GCC-4.7. for version 4.6 - Fix bug with windows not showing after being restored when KWin is the WM. - Fix bug with restored windows not gaining focus when KWin is the WM. for version 4.5 - Change -n option behavior: - -n now acts as -n -y. - Name matching now matches any running application. Previously it would only match when launching an application. - Remove -y option. - Change a number of casts from C style to C++ style. for version 4.4 - Remove window manager decoration close button can optionally iconify. It ended up causing many issues. Fixes: - Drag and drop. - Moving borderless windows (chrome). - Windows moving slightly when undocking. - Focus bug (#600045). - Remove -c option. - Add help text for -i option. - Update INSTALL. - Default install path is now /usr instead of /usr/local. for version 4.3 - Use QtSingleApplication. - Window manager decoration close button can optionally iconify. - Changed command line option -c: Disables WM close button iconify. - Restructure large parts of the appplication. for version 4.2.2 - Fix installing translation files. for version 4.2.1 - Fix type in .pro file that prevents all files from installing. for version 4.2 - Fix disabling balloon title changes menu option. - Ignore docked windows and continue looking when matching command by name and when matching by specified pid. - Bash completion - Italian Translation thanks to Alessio Cassibba - Change behavior of tray activation. Raise window when not active, and iconify when active. - Change to the desktop the window was last on when restoring. Only works with WMs that support _NET_CURRENT_DESKTOP. - Iconify when focus lost. for version 4.1 - Fix bug 431297: Fall back to window title and class name when launching if pid becomes invalid. Allows commands that detach and get a new pid (rox) to dock correctly. - New command line option -n: Specify the string to use for fall back when launching a command and a pid match cannot be determined. - New command line option -y: Force matching command by title and class name. - New command line option -x: Specify PID of application to dock. - Fix a bug that prevented the time out for trying to dock and launched command from increasing. - Menu item for setting the tray icon. - Fix bug: Do not quit when closing docked application from tray menu. for version 4.0 - 4.0 rewrite complete. for version 4.0-preview-1 - Preview release of Qt 4 port. for version 1.3 - Fix bug when reading back balloon timeout on session restoration - AutoLaunch enhancement (Request user to provide program name when autodetection failed) - Indonesian translations from Eko Prasetiyo - Italian translations from Alessio Cassibba - Updated Brazilian Portuguese and polish translations for version 1.2 - Polish translations from KonMan - Check WM_NAME to support programs like LimeWire (for lavacube) - Store entire application path as part of session - Move around command line handling code - Configure balloon timeout using "-p" (for roopesh) for version 1.1 - German translations from Thomas Runge - Dialog detection bug. I replaced all LOG with TRACE (Thanks to Novoselic who raised a question which helped me notice it) - -v Displays the version - -b Suppress the warning when docking non-normal dialogs (For John Pettigrew) - Fix issue when passing large command line to previous instance (Reported by Arseniy Akopyan) for version 1.0 CR1 - Russian translations by Aleksey Kirpichnikov - Brazilian Portugese translations by Paulo Ruthes for version 1.0 - Spanish translations are back in (Thanks Edulix) - Yet another fix for xmms for version 1.0 rc2 - "make install" support (with QMake) - Multiple desktop awareness (for Sharon) - Icons from Marcel Dierkes - Use XDND type mechanism to pass arguments to previous instance - Spanish translations are out. - Czech translations by Jiri Hofman - Drag and drop support for Antonio C. Censi - Xmms+PlayList fix (for KDE) for version 1.0 rc1 - Session Management support (XSMP) for KDE and GNOME - AutoLaunch application support that do not support Session Management - Wait until system tray comes up on session restoration (Requested by Normen) - Fix GNOME docked icon resize issue - Track tray label appearance and disappearance handling - Major code refactoring. QTrayLabel is now a very reusable class for version 0.9 - Support to dock the active window (useful with keyboard shortcuts) -f Was requested by Daniel - Small security fix - ToolTip positioning issue (reported by Alex) - CLI Support to disabling ballooning of title changes. -q (requested by Marcel Dierkes) - French Translations (Thanks to Al) for version 0.8 - Custom Icons. Accessible through menu or CLI - Fixes for KDE (ObscureEvent, BringToFront, SkippingTaskbar) - Code refactoring - Changes to have only a single instance of KDocker running all the time! for version 0.7 - Use WM_COMMAND to identify windows - Warn when attemping to dock non-normal windows - Issue with tool tips fixed for version 0.6 - Start up applications - CLI support - Spanish Translation and i18n support for version 0.5 - Support to remember the position - Support to close application - Support to remove application from the task bar for version 0.4 - Add dock on obscure - Add dock on minimise KDocker-5.0/INSTALL000066400000000000000000000010101252153257300137260ustar00rootroot00000000000000Prerequisites 1. Make sure you have Qt 5 installed and working. If you dont know what Qt is, go to http://qt.nokia.com/products/. You will need qmake to compile. Building 1. edit kdocker.pro if necessary. It should be ready to go with no change. 2. qmake 3. make 4. run "make install" (optional) 5. While making shortcuts, use the icons in /usr/share/kdocker/icons. Please see README for tips and general information IMPORTANT: Kill all previous instances of KDocker that are running before trying out this version KDocker-5.0/README.md000066400000000000000000000015751252153257300141740ustar00rootroot00000000000000KDocker ------- KDocker will help you dock any application in the system tray. This means you can dock openoffice, firefox, thunderbolt, eclipse, anything! Just point and click. Works for both KDE and GNOME (In fact it should work for most modern window managers that support NET WM Specification. I believe it works for XFCE, for instance) All you need to do is start KDocker and select an application using the mouse and lo! the application gets docked into the system tray. The application can also be made to dissappear from the task bar. System Tray Support ------------------- KDocker supports the System Tray Protocol from freedesktop.org Website ------- http://kdocker.com is the official website. It currently redirects to the development page on GitHub, https://github.com/user-none/KDocker Reporting Bugs -------------- Bug tracker is at https://github.com/user-none/KDocker KDocker-5.0/TODO000066400000000000000000000000221252153257300133670ustar00rootroot000000000000001. Translations. KDocker-5.0/VERSION000066400000000000000000000000051252153257300137500ustar00rootroot000000000000005.0 KDocker-5.0/helpers/000077500000000000000000000000001252153257300143475ustar00rootroot00000000000000KDocker-5.0/helpers/appdata/000077500000000000000000000000001252153257300157615ustar00rootroot00000000000000KDocker-5.0/helpers/appdata/context.png000066400000000000000000000753761252153257300201750ustar00rootroot00000000000000‰PNG  IHDRˆÃÉjsBITÛáOà pHYs a Äî–@µ IDATxœìw@GÀߛٻ£‰TŒ{AM¬¨¨(**ر÷c7¶Dc‰±Æ[ô³·Ø»ÖhÔhìÑ4QcEÁF»Û™ï=Îó8°dòÇÞîìì›ñÍÛ™7³ópêW“ÇŽÉL›ò•ž* ”$É"0®%‰ JNe0Å)@)å,=™ .äÄÁJgQ)8J¢}‘ˆƒ … NN”È"‹Äx}r*I)¼å¿‰::Rª¼‘r .äDfûdDE|ɽÌÄ™‰÷í7R–‰§ñ.ƒ€‚1:&X²¢ !8ÁÍgHŸUÊN u„ ‚s!Ë€’„”‚*ð['ïËAIBéÅkÓÐ ª§¨í¥l„™¸j•ˆÁ€„ƸÉB(&Ô m[)€Ô “†}¢àÂl†pþ\Ÿç@‘3æ¦(&Î Ñ!ÕszJLAªË¦ƒTBÀÁdµD”è`«*““ÁR”  ‚S¼Ô@¨ŽX:,’#%ôµvBˆ„/öL¹)Nj \H€H„™“è›’„Ú FDI"¨ Ft€"€!(B32θB‘(sW€1òÆÄ×x»±4BÁ &Á˜bîCQªÇä$Æe€H©à‚¹j@Id‚‰¨ÈÈaƒûר]×Ïoİ¡÷ïßOãéÓ§~qùrÊó}Êݺu+Ý… ­^ÑY·mn2©FJ0¡ÀsÓ#@'àyûæB'à ·À­ÿÔóÌ$¨E`kɳ_J!Xb3Ê\a” BEAr‚ÂRÀÕô¿`ô5äaŸç†‰1®:—QûGªaâL˜O¢`2Wíut$ÔAÌÄ„ ‚ µåþ|l‰òö9ràçŸËùøôëÝ›±TT/^Œ‹Ky~æÍùòåËÄb¢$Q''0—‹s¡ËÄÌ3a2ÉqI¦8ŧ¨}:«k)µè½!,=eà‚Ë\Ib¦xգǀ«o8DêèHˆ^gN :³NýJÓe˜„€ûOŒ÷ŸÅÛë"ÔÈl ÎyrçÈl­„L¨¤ 9—e!' ¦¨ÉCžl|®\¿ظÁ@$Iêѳ×ÐáÃE€ˆˆˆ.:¶lܶMë çÏ@Û6—/5ê«É“l„êÞ­k\\?v¬yPPÀú#G OHH€Ç1"¨IãÀ† ·lÞ¬¦nÚdÿ¾}­[¶¨å[}ö¬Y)KI$ §ÉÝ ot°– Ãó_„"!dÙdBú!JŽ:¤/tÙ¸Ìå$¡^Õ9験#.”$àÉVµWÉò¿ÄÄÞ{œ4u{ÄÙëOôeQ¥hžÏƒ?ôÌ©Ïüi¼e˜ÝLŒ©ã$i²2ÉSrs²üÂËKË@ªAƒ£G íÕ«WùÒóåÏ_×ߟJ\QLC 0pPPpðµkW?ýdÀÎÝ»7nÚܱ}»ÏFúøãJv»5zägËV¬,Q²äÌÓýøã°#Æ}>¶DÉ’³fÏŽ¼{·sÇeÊ”)]¦ lݲyåêÕœ‹N]:7,ïSæÅB"…¡•íu«-«@IBýRŠ ÈüíŸPŽT=gB(ŠP ã Œ —MêèÍþ› ­Ó©kƒ¾9­ÓéšU)Я~áþõ 7¯œ_’hМK§o¿@À&Mvlߦ&iÛÖÅ%‡«««Oùò7oÜÈh%¼ ]…BR¦þ©+6Ì ¾ù¾ÌÄå$œ”%‰I“Gf(3q.s z=ur6åRjéþS¿Õ*éΑ(Bªå€™a·8¡Õ‹åî»özØÀR^©÷›ÂÃÂüj×  }ú4&æåo¯‡¢ózzªÇyÜÜêÔ­û÷_9¹¸8'kHÞ¼yÕQ!x{T¨$Æ—fn™gœ®¼iÓ„Ö‡"µ•_oËT3q§zJç\ÆÌ*dVDÔé*Œ+v2á<ÕӴЛùò8ßãwŸ²ËL±qòãåŸhÓݧü~‚È—Ûqúiˆ·oßÞé3fDEFZÏ¡;úKãF «W©léãòËú¿ýfÖŸüa7ï§Nëбc^½v‡†ÙMpñâÅI'øÕ©­×ÛïÄù׫'„¸øûï/^œwþ|JéæM:¸;4lÿ¡C‰‰ «V®TÓœ9sšüóÏÎ_ø¸r¥*U«>züèØÑ£Ù<(HmåÉ“ç^TTjRÕ«Wïä‰ÿüý7ç|Ñ ®^¹âîî^¥jÕ¥K–pÎïܹÚºMHj·Ÿ?wnî?¤q,ˆZ:@$‡W®½ÿ&TÔA‡4y‘'"JutDBª'(Q@Œ ê.$™©Î<î³o˜¢ŸÉW±«±ìî3q÷Œ¬ï¹¡wñïZ¼ó”߃»qpõ‘¸òHDÇÙŸîÝ»woÓ `nÖ<<ì¹)éÛ¯¿$IyòäiÛ¶Ý®;=ztðÀŸ€ÞÞÁÍ›oÞ´ñ*âñãGCúbüø•+VįĤ–ÌËË+66v˦M-Z¶Ê_ |2`Àþ}{?~^³V­R¥KÀ€ŸV©ZU½åÚÕ«ýûö™8y²‹KX¿n]ž=]\±[ž7¬W“=}òä‹ñ_º»{¼‚ðo9’H.ÔÙ)U•ô.:êìLÑÊg :JÎÉÙ™::DP! pÉå´rÓÆ;ÑÑ-Z4÷oXgéšÕÓ¿ù¦lY½^¿àÇ…ÿ[´0À¿îÀŸ :´PáÂЩs—ïfÏnôôéÓ”Rå/P`êô#?Q¿n¤¤¤^}úÀ´3ÿúë¯zuêôïÛwäèÑÅŠS u.³Ã ~ÿýÂ’¥‹Ô“¿_üý‹Rѹþ¸zå‹ RÔ9I’³ut$”è\ôÉ5ð@‚ªÄžç[ï"Y_"’91ò‡wT’#•œ$ÕÛhÐ#MêkL瀒³ur"¤Ô\½„@DÐ9RÉÅ1U'ú‰ˆF Ú®Ž¼:®¤W.CT‚ ˆBR+øÞð°ˆË—çÍ#„ˆ¾ÿÞ½{^^^3W.5Aþù/^ü=òî]g+¿€§§çÙ3gl²éX¡°fõêé3g¶ iûëñãsçü0aÒd»É¢££ó¸å‰¼{·šouõŒ‹K''§{QQÑÑ÷½’WǸ¹»×PE1lÈà.ݺmݼ¹jÕjy÷Y½8c‡Eñ%¤·c IV@@´qŠv5Â^bó¥|ž¹g3åÅ“ Š+¶jÍZ›ÔÕ}}÷ú9e.'~;¥Ô©[·Nݺ֗<<<ýo±Mú]{BÕQdÓ§MTOvïѳ{žêÉ^=;õêÙ ,ÇÔ¥˜h²ä“Jy³ ž†6—ÒNœm˜×¦b"ÈÖ—^Xí7§¼9tys;EÇ1Aˆ‚’_Œ ê€H€H<\¤¼ÎvÞ!OŸ>Bœ8uZý9xàÀð°°î=zÀ“Çóäɪ©Êë陘÷LíDß.àí ŽŽŽŠlžqˆŠŒL.hªæ?(8¸MH[9jtpÓ&½ûôUó±æè/G…U¨P1¯—ç½(³{".îYbbbþ<<òž9mÖø¨¨¨óçÎ5lÔˆs>jÌØê¾¾þuoÞ¼Y¨P!¯|ù\? À&ó÷Ø*ih¼ìå¡]¥< Óƒ”ü‡€É? éÛWp±k+ìß_µZ5ËÏúáa¡`0–,YÌ9‰Ù²iSó-=<<ªûú.˜?Ÿs~ûö­];w´ïÐJ•.}úôiøõøñ«×®©ù¸¹¹=7R/R¸põ XñâÁÍšûíl뫊¢œøõ×Ñ£F9Ò`04oÑbÇömwîÜBÌŸ;7(¸™««k£FŽ;öןrÎç|ÿú1¥´–ŸŸ$I}úöûá»o u›6Ë—-MHHPïýløð Õµ††F:IuÂâózy4ä¡¡ñÖ¡& ·[Ó±cÇÞˆo–Zµj½i44žck˜4ÕÐÐxãH&Æ'M²Ýò]ã?ŽÝýN:óð¥÷º¹¹×©W/óeÒø/!@áÂ…ß´o7RÙ;&æa@£@»—c4y»¢{óH0ÿšó[#¸¦ÂÆ ëûõí“””äêêšÚ½Q‘‘Æ ð¯kðRQ”Š>ålR.Zøã˜Q#Ó#Ï_þ9sÆôŒ–¢kçNçε>óÓÚ5_O™’ZzìG3L¯‹,ËkV¯~íææ–F²Q#?+Z¬xøþ/ xÙ&$dÈÐaéytll안ˆWZãíF3L¯Kèž=ÑtëÞ¦¹ùlÄ•+%I² xiaÛÖ-ú÷cŒ…í ]¶l,]¼xÞܹŸ~Ò¿–oõ¾½{Ùx¸¶oÛ:i—¿_¸Ü´ÉÕ«Wc?|ÿ]ë–-Z5oÖ¥SG5 FlLÌ€þý5hÔ¤ñâE‹lEº|¹e³`5[¦È£GŽlب]HÈë×ÕþùGÏîÝBZ· jÒø‹@|||“F wïÞ]­j•?RÙ¢^ãõÑ “Æk!„X±by—–­Z§2 `Ôˆá»wíR7ü«ëïo0<%ûÛÉ“?­];ó›ol¬Û¶-›ûõÿäȱãùóçŸôåëK-Z¶š0ir…Šwí -V¬Ø¶­[¯]½¶aÓæ­;vÖ©SwÑÂàÇ Ê”-·wÿþM[¶^ºtéÊ•+–Û£££?1|úÌYnnîBÀþ½û»vï¶'|o£ÀFÆÎù°!C†ølÓ–­?­ß°þ§Ÿîܹ ‰‰‰á¡{6mÞR¶ì[Gï]$Í0id Î!4tß­ÛѲ¢“Ýñ_Ïÿ~1¢uHGgçiß8qÒäv:ؼT¹þï¿Ã† óùçê&ËÖÔ©[·|… ”Ò^}ú=úKáNúê+u›ãZ~~ÿ^»”’óçΞ?wŽR:gÞ¼âÅ‹€`˜˜8ðÓMš6-Yª#¯VÅ·lÙrбSç?þ¸tÿþ}déò>>>àêêZΧüõë7àáÇC‡øàƒÒŽ1•EfûPaäB¶µL‚¿]ß: ŒY¡ªÚÈŠNV$Ʃīñ¾R½zõ4¼Ôi +ô÷‹— 6÷‡y”J’¤[µr¥NÒwêÜCV$YIk(§ÓéÚwèøã¢ÿ?qrè°¡ßΞýÛÉ“ „;ftûŽvíØ‘ò.''s¬ wwwEQžìß·oó  mÛž?w61!$I*Z´è+Ô^æ 0.?¬ ¸Ulv.ÈöýwoY¡²" !¢SÕ†R‰IššÚd‰aBÄ *„„„tèСaÆiïâææV¥Jõ8oÞ¼!!©†ÓÈ,\\\*Uªäࡈih’%Z¡BÅÀÀÆ;wíüçï¿o\¿~øðáÆMš(àˆB“lß6EDDÌ›;W=¶x œó!C‡ øtàéS§nß¾msc||œzðàÁI’r%Ú1ËdÕg™>mꕈˆEÿ[¼eÛö‰“¿RO †/Æßµ'tßÁƒ9sæ\ò¿ÿ €Ð¸Iã^]{+Zj÷Ž=‚Húgñ‰„P@6²‡‘òyzܻշWïŽ:mÛ¹sÝÆå+TPó$„¼‘¾¨Â# 0q¡€`¨ O$½*¼`(Œœ|KÆwfµ‘$‰RÉRuh†¤¦6Yb˜*V¬X¨P¡°°°õë×ß¼y³Q£F...©%vppÈ;·z»ÿþ¬IÃI’|}}mÚy˜dŠH$IBÄÏ>I ™1cúÊ•+„]»uçœ'Ú"&Y’IQ$…!Ìû§*T(<,tþ¼ybc­^¥Ô·F I’ºuïñãüy6ÏÝ¿o_DDclÍêÕuýýmšæÎûþýûœsxøàaš5ó¸¹1Æ6¬[§ŠÓ·W¯5«×2&r¸æupt“t®Œu¬æW_!½ú}ºpþ\Žž=súê›ì§5+>ªZÙ³€÷ÓgOtŽ5jÖ$„\þ石gÏñlߢJ&™d¬èUá:(ÄA’àŒèô@Q§G`Œè%Ôé‘€x1¸¹xÙX«Í ÂÁ9OCm2?&NWºtéÐÐи¸8¸|ù²——W¹råNž<éããC)ussóððˆ=zôh>úè#½^ߢE‹Ã‡BüüüvìØ… ._¾¼^¯üøññãÇ‹)R @“ÉT¸pa£ÑxäÈ‘Ç#b•*U ,(„ˆŽŽþí·ßääÐOi#IR¥J•Ο?›vJ…!"±¸¥ )Ò±SçU«Vþúë¯+VôññB$¿Q’t„H‚s"+B!Qn0–._1û›ošM¦¢E‹N›1£lÙrÖs-ZµZ²dñõÿµ~t@ƒß;ûK—J•.=}ÆLÁJ—)S¸PáÀF Û´i3hÈ)“&?vŒÒ4(øø±£0mÆŒ‰¦.]²ZÒé«T©<àÓ’$QJ)¥’$/Qªx™Öo؆ÓgÍúþ»o¯^¹Z° ÷ôY³D©²eCÚ´éÚ¹KžÜî^y½ù7xò0Õd¡(Bt:s_Ãi‘sÎ8Qd¡×¹"Y&RŠŒqŽ 9g ÚSe¿¨6T«$„°VDB$«MDsww7?¶œ¹}û¶êA€âÅ‹>|øáǾ¾¾¾¾¾‡JLL,[¶ì¾}ûÀ2èsss«Zµêž={âãã?þøc5%,Xðĉ§N*UªT¥J•}ÒŸØ@g£÷ª`"›†a]4ιQæ:*’¯óä4¯,ÑExó#“ÕÆF<ëckµ±!ó ÓÇœœråÊeÍ}ðÁwïÞUu:ów뎎Žj,»b%$$8;;[n‘$)>>>W®\)#âßÿýÇH’TºtéjÕªíܹ3Ó õþÁ;uê”ÅЧ†‚qªê·_ݺ/ÍÖît•ÚŠ€sP“hv´¦˜ ¢Ý«fK™JŒõ"ÈŒSÁ%ÊÌ … ¤€ÂìÔÑ„Okµ±œ±R1[æ"dºLF£ñòåË~~~ÎÎΈX¼xñ¼yóþóÏ?êUÕ%„ˆeÊ”¹}û6cÌh4:99ÙHvýúõ"EЍsyåË—¿~ýºÉd²û¸Š+Ö¬YS’$EQRûüJÚøøøsçνÔ*q&Y¢T’$óDoj­%KðÜw€ˆÈYZk2 ÎS’ûÖ‘ÒŽ<–Üö ã” €D'ˆ$19™`Y5.z§…‡LR›,‰’röìÙ *4iÒD§ÓÅÄÄìݻײ`÷Ö­[ü±:+÷Ë/¿@LLÌÓ§O[µjuåÊ•;wî¨Éîß¿áÂ…ÀÀ@D|ðà=﬙‹/V©R¥E‹Bˆ¸¸¸ãÇgE‰Þ3Ò¨O3@–Õù+ /z[Ó6C©f©ÞB¨¬"§4«FB…Q"ÑÔ¥|?§–•Úþe…tAÂà(‘€‘ÑJx¿…!2Gmpâĉٶ“Á`8sæLö !/LýØ,¢ÁäÕquWWú©ýs“Éd3=lwQˆ ""`€×¶ IDATJâõ¿Cé]@h3ÉõR0„Aõ6£½ï´ðª`™j£& ;ˆÔ_Zªn™¿5HñÎU/B¬•ÌÚí27ók<•}y2"³€—P,ÎëŸ)Ezé³Ì2§ip3Ä;-üs3Om4äa!P}ÏÁ‹¯h‹INf¿m¨oEuéY:µ?SÚHòBbûyYÞÛÂo“,=ÏRÇD¯%ÓÂ'?=ÓÔF‚ÔÃõhüg!DR¿ MyÉædÊ4–»‚1fÓ±Oý•.2e52c À ^ °×e³i$6 ÞV²ÔÄF‘¹ßľÓÂË2ÉDµ‘ô”Œ7>åÓx×™6å+uÍ®ÍùÃZ¤1dpss¯íï¯*™a{ã‘dïÃëš&DˆŠ¢Ju–­lF”6C ë)±Ü’²c"„ 4“¬é;.<˜L‘Ú] dפ¦D•Ó¢6Ú¬œ†ì*PllLƒÀÆ/½÷ÀÞpLÞW,;.©N|ñ#)0¯»3QúÚ­S„H’µËÃÒªSv"¬)OÚ¤W6c&J3¯Ëñ. /ËšU‚4‘Ý”ê€N3L GŽ‘E4ª1RÃÛ·gÍœñÇ¥KŒñJ•+3ÖÓÓS–åÊ—ûýóÖy.Zøãõÿ>sVFÅCDBrsëc š;*JU*".]¼ørDĬo¾V3ÙlI-Øxp¬{yŠlD䈙9J§ðlkÞá…Bè$éå˯2¤6šaÒÈ0iºŠžcI£Œ3ºJÕj3¿ùW¯ZÕ§gÏÍÛ¶1fm&jÚ„„˜Œö¿Ù~)„ ,ë 1"7Oa2…G¢SûþùÇ7ß~Ç9ÉËk„¥\*êIÎYuA³ºACˆ@Òj‰¯Hz„·ˆ÷–Ϲ­S,5Ò¯6ˆY°µ®ÆûŠux…Û¯^»öåÄI’¤ãÜØµ[§>Èo2ÅK%ˆ„nÛºeÿ¾}sç/ÛzóÖ­/Æ[ºxqbRÒßýùû… eÊ–6c†››»už)äÌéÉ€ÌùvίÇqÆœœ]¦LþwÁ?þ¼4}ê”gÏâhºõT7sDÄåÉ¿Œ{öT¯×þŸ }—жMëƒOž4aÙ²%åÊ•ˆL]Ò@ áH€Ì<E¡@u‚)e„¨ë¸ €'q@ŠHÕG !8€yÑ<·ÇÔm6²\xuÀK»KUm¹€F†±&¤¾H@@ÀèÏF„îÙs/* üëù;:ABû-Ã/í&à‚nß±õÚµ+›¶mÙ±gw½ÿ%‹R„)“&têÔiûÎsæý°cÛ&ENPä„¡û·oßnÇ®]ÓgÍ;v´"›yb³ð=;6oÞX®\Šœ¢ b :'I’³¢ÇÄE €œHH%BuH)ªF €A˜@˜@(œ $jDB¡ 0D‘ Âgh‘G†Ô&c=¦5ÿ¬9sè‰0‰znõ:—꜡Û5Þ]RzX3úœ4ù«Í›6†îÙ=qÂnn9{öêÙ®}õ}{ãú¿Ã† ™»`~j/ WŸ¾Íš616»žÚ$MÏÖ«Õ¨~u5ò¥_íÚÂ÷#@žœ¹ FähL0ñL‘Ï_8À›·B%‹-YüÃÇT­^ýQ샡ÃG~X¤  …]PoÒì¼MÌdÔéÔç u¹É‘#JAý€ ~Y‚B0N%ªd—ðéZ Wû†éĉ)ƒŽ…E‡p>ð‘óGm¼Ú„'†/‹\–p6¡o¥¾/}†Æ»ŽeR_ýiñ¼¦­d6WÕ€—mÛµ7ã>6qÂÄ¢E?¬T¹2Àó€—•*U¶É$eÀ˼yó¦‘ >þIîܹÌŸwìèQÎ9"ʉ&N1¤Cû1£F­\µ2§{Áï˜ïâìðà^dÜÓG]Ú‡ |úôéãG)pBõ÷!ð™AÌ+²'%"̲­î$ $ɶ>9E5Bpâ‚<ŽR n™ªðêeÁ…,$Aœ<É6áA.„7“Eg0ùsâtª ¤þ/æÉã:Ýó€/K¯,sŒsØ»{hÛ¡ÛmgNlöÃÙv SMßêÑ÷ï#¢N§ó)_~ÌØÏ+~ôQú‹zìèÑÌ_»n}i"ïÞ­Q½ÚðÏ>mêý{÷ýoq7·K—þ7f ˜1sú–íÛò* „S< î鞯`ÂkVo$€ºï ÇgOâAçŒrQDhþ ô:†2ûã×T€"0¡Ê ƒ "AÁU§X ÏäzG@ÈFá@pnR—mËËA^Gmìû˜dYŽŒŒŒŠŠŠ³âºñßÁyïm³7ŸK¾;|UI5$ÉO6D\û÷üÅKmÛµïÚ¹Ó_þùÊE·KxX˜_í:áaa¯poLLÌ?ÿ¹ò¼gðd„ÊÁz¶HñÁ„‡…Λ;76&†1Sf¼´›À&ò%Š„@ä½;\I䊌À¹W­óäñ/Çq¢nG5o|ýê NPxR‚` ¡ˆªþA6ö®Î ©27Z„g€‘ä C`ÈÈ~áQ$¢P”$ÆX&ª}IEqpp4­(˜»`¿ÇýŠì,r'îN‘_Šô‹èW,W±´£×ë[µnÝ¡c§Ó§cì›™3Ô«W½Jå ãÇ«{Ü%%%>¬ZåJõêÖÙ¿ŸM#† ]0ÏVY`ß¾½ÓgÌˆŠŒ¼uë–z¦^Ý:a¡¡ Tô)7uŠ9YÊ'nÚ¸ą‘çΞ­W·NDDÄ'Ä÷éÙÓ·ZÕݺªÑ\„³gÍò¯íàï?îóÏU9¿þꫵ«W·mÓºwÏé­æwEIR™1¦j[)íêŸM‡ Ã’eËoܸÔ¤a­¾ÿ[´P xi}W‹V­Îœ9c7à¥m¿×ÿoÏù2Á !CÂC÷èßèàAµüj=‹{ŠkÔ¬9v̘Z¾Õ¬R®Q@ÀOÖ ú-\¼xaýúþ}ú 8xØA$t”A.̪!"DjŽÜ–ñêÌœ›Êˆ`ý\½^èˆ 9ALöy ‚FæÈ9ªc©ìÔÝèKÊDµ±?”Óé¤9lƒz+ˆp‚eF¤Gô-[6 Z¢(ÊòeKÏŸ?·+4zõè¾rùòž½{O2„8qêtdäÝV­*W®b¹qÎß ! h“aÌÇ’$ðölÜ8,tO¿þŸ¨ç7¬_·yëVÎE³¦MšW¨PaÙÒ%)Ÿ˜7¯çÿ-´ 7oܸxÙò%JôïÛgÃúõ={õÚ¼iã¡Cw‡†99;6|ت•+{ôì +W,ïÛ¿ã&MÓSêwD!„œÜÑ&·ºþõJ”(5kÕR‡œë×­ëѳ§³‹ tëÑsôÈÏTÃT¬xñ6!mÓSäwBRLÖYÕË"ckõ²[VÙ©yÆLÜìç0ß³pJË‚Âu‚€u %K–*]:¨q;×\(¥_NšHˆyé3=‘p ‘¨S\ÀqaJ&l_÷šÂ«ƒÁÉ& ñ-^í1qŽªI²QË*§´ÕFµJªÚ(Š1˱‹G—Îî-?m"î¦Ftt´$I9rä¸{7Ò2¥âééi2™žõdý€øçßk×Ö®YS×ß?<,¬EË–6î ‹¸|yÞÜ9Bˆèû÷ïÝ»çåå|PHM@%IË’ò‰)Åó.è­ètz“,@äÝ»‹~\¸fõjàŒYB¼”*]:=å} TÝ……΀¹’'O®ëÖZ>à‚$Ç,L¶AÂÝݱ$Ë…B¨;¨ªH2²ÛôK^ÚM@ÀÄL ¥ÏÛ¶³³ó¤)³9t$^mÖ2PLäF ’•cC¬'JvGK)<ÈŠTâܨvOÞBáѲ´S€Ú¨ëÎíªȹYm„à\-b*=¦´%Èè-;wl÷õ­A)õôò¼wï^9ˆ¾¿€··^¯wuuŒŒ*Q"ìÞµ³jµê`’å9óæÇ={Ö§w¯àfͬÝ=}úTqâÔiõçàÃú÷è˜âƒø”OLYJlgP½òå8hp²•|ŽNzùޱïˆæÑ–¢gµýkÛ¸2­+ÒrÉbƒRä I–ûh(U/œ¨ƒç&ét:’I"aŒ“,“ñÙÅ»+¼Õ´Û j£¾œ¬5çÅoŠ™j<•çjCHÏ1ÄÇÇoܰ~ÕŠ•ŸÍ[´XºdqRRRBBÂÒ%‹;wîAÍš-\0Ÿ1võÊ•)“';::@©R¥<==‹+V¦LÙ-›7Yçy`ÿþªÕªY~Ö MM»OÌ“'Ͻ{÷ÒpεnÓfù²¥ Bˆùsç~6|øk×Ä»Šj¡Õ1D êŸù Eëõ˜¤Ì(Q»`˜ VI%e8Hä‰ Ç§öZMùQ" ¨Óe«URy§…·ˆôšj“Ußʵ I’|Ê—_¾je…Š`À§>xXË×WoзhÙ²}ÇŽ0nü—cFª^¥rW×Y³g«ß¯[4dHï=Z¶jmÙ¨<<,¬ÿ'ŸXÔõ÷ÿlø°Ø˜»bØ}bÙrå>,ò¡_Í:v´{WÇND?hX¿>ã¬zõ꓾š’ 5ò΢¾Ç¬·${á’ú*7ÿ³:iIõÆZÇ ètêW]æŸB€Ñää OxKÄK›wQø×QDÄ©_MN¹QÜï¿ÿ^¡B…—>;11Qíàh¼OL›ò•^¯ 9êM ’…eGDOâÓ µý–òN ŸR xéèè˜ÇvFWOih¼%D‘]K¸3™wZøtbß0©Óçï+¸ '÷;-|:ÑöcÒø/òïÏ;-|:yO©ï2šaÒÐÐxëÐ “††Æ[‡f˜444Þ:4ç·Fz9rè%àe¸¹¹×©W/äÑxÑ “Fz‰‰yÐ(ð¥Éì Ïa4Þo4ä‘\]]_ùÞ¨ÈÈ™3¦_ºxQQ˜%à%LŸúu«ÖmJ”, }ÊíÜúÁ¤¼}î?è zË7ï7šI#›5ò³¢ÅЇï?pàçŸËùøôëÝ[ÝôâÅ‹qÉûvoشٲŽÆÍ0idW®4 ”$I’¤={ >\Q”¶!m"._3jÔW“'@÷n]ãââàöíÛ=ºumPÏ¿sÇ7®_·Î'.îYÛ6gNŸîÔ¡ýÑ£GÕ“ æÏÛ¹cGöJ#‹Ð “F60jÄðÝ»v©ÛõÕõ÷7 7m.Q²äô™3­÷óB 40¸Y³ý‡~îÕ§ÏØ1£-—E>lxûöí+W©Ò4((t÷.õüÁRñî¢&lbâ¤Éí:tس{W‹æÍ5h°aýºÔR^‰ˆˆ‰‰mÙª5øû×k×¾½åsñ©_OáLiÕº 4nÜäÈá#‰‰‰Ο/Z¬¸³³söD#Мßi!˜ã™Þõåz"„P8Ò?ã 9W8 !íÚuhß¡£¢({÷„3¾€û¾µ}SfõàÁƒ¼žy-›ŸµhÙJ=ع}{M¿Ú÷îÝ»{÷NÞ¹óä)_¡Âχž={6((È&Sœ"Ñ%ïèš¾‚p&X\‘:˜w¤fFÎe’±-c&ñjƒUÍKVýŒj%¢îÒÇeÁŒˆ©>Kú%¯_óJ"ËÉ|Ê”¶$×µs§óçÎ¥çÆÓ¦ÎóCúôÍÌ™/M¿u˖½OúÍr¦O¯^¡{öXhØ`p1Cj)U¸"”®ÞháBIb‚ ÉÉáß;wæ/X(Çs!P’¤õWó«~íÖ-f!l·6vww¿w—´fÍõØÓËkô˜1ݺ÷X¸àGõRPpðömÛNýö[š5íH%t*ˆàBI`DO$gGêä$€* œ ÉÉ@ r¢"«¾¡Í¨ÀŽš—œœêÔšÅÈ%'utd&à<«L¯_óïÿP.,4ô•CcjX£$2Ó3%åyÁKâÔA‚wO\pYPƒ‹ÉwàÐî æ=¼÷H–å#?ÿ|îì¥JU}DîÜyïEEYßX¼D‰Ü¹roÞ´ víÜypÿ>µÛR­zuJi‹–-OŸ>}óæMð¯WïÂùóÕ}kHRúþ\榧JÊH$\D"@¥&ΙBÔÍ‘  Q‘Ý[¿¿NÍb’  0‚gœS$&L=z[Ö‘þšÏVÃd7&elLL·.üý»uéüð¡y‡ÜG 0À¿Nm¿5Ö¯3;#nÞ¼Ù.¤oÕ*­Z4ÿ÷Ú5ëœãâž5iüÛÉ“6OLHHˆŒ¼;zÌÍ0½>D"D'¥|õ!ÉYÔ!òä )‚ !*ƒaéò·ïÞjÖ¤qMßZKWþoÊäÉ%‹”¦Ò¹K—ïfÏnôôéSóƒ™3oÞ®;êúùmÞ¸qò”¯­§Óéºuï6Þ<pvvö)_>888CA‚DO¹0¤ìûˆñù~ð‚BtDI0*FNlûwÙÀëÔ|r(‚RÂŒF%QÉþ­æÒ_óÙm2SƤ=j”Où•«×DEF5m¢Æ;ùlø°R¥KÏ[°àî;-›7óññ)S¶l¿Þ½zôêÕ®}‡ýû÷ :dÇ®ÝjžŠ¢|Ò¯—®]«U¯nó¸Ã?ÿܰQ£r>>ƒ!ûk€'§|ERHñêFDˆ&›èê˜Q ðôôœùÍ,f’“!²D}cûÖ¨²ÿÐÏê-'~;¥*\xÕšµÖ¹ 2ÄrÜ¡c§;ÀÍ›7Ÿ={V>•ÿVn4q#X·X³¼)A!8¾x‰HÈLŒ+Œè@€`IABõ‚è$!(€@´ E™Y¤&0Ñ!J¯^ó‚s!‘PG©Zó³•é¼fÍ+I,» “MLÊR¥Jý|èà´Ó _þüàÑ£G˜3o>ðönÞ|ó¦íh‡‡cÚ¶k 4|üè‘ÅñåøqŒ)íÚwHù¸ð°°a#F@pp³ð°PÍ0¥êèH@pΓ’,ç­»/ Ún¾,ÔðMj ŽøZqb}:àÊ•«_MI5TÑëš5çüöí[»vîhß¡cÉR¥òäγ`ë–-áa¡ª…ªY«¥4¤mÛ“'N\ñÛ…ð°°š5kY~Ö«_?И/…+œ™xÊÙ}&sS3Å1.s¡p%ÁhŠc\ R”ãÓ3…ÉBrÒ’¬½ÕèNm:Hˆœ(LÏ9!Ab0 ²7¾í¿XóYñøaÃG*\¸m›6uýjýåÈÚuëI갦Θq`ßþömC&Nø²iSó2¹ïçÌýãÒ¥ª•*uíÜyü„ %J” „,^ºtë–Í•?úhÝÚµ³fk‰N§ëÓ¯ïwV=&ÆØ¯ÇWüè#Ë™zᡚaÊHQ—Ã<;.9RÉÙ§+OuD笓œ%g'êäD$'G !$œ ’³58JYíݰ w‘ˆô¼%[„èˆ.‡^ N¤09T‡:gIrv¢ŽÎDï ɦîRÿkÞ~ÀKÿ2ÿ…€—o3ßΚùþ/°ÔÐÐxçÐ “††Æ[‡f˜444Þ:4ä¡¡ñÖ¡& ·Í0ihh¼uhÅi¤‰B@Hé^1Ì1/Ÿ#BPn^°ÂrA9ìú0"£Â«@™€Ð'/G|'„·ªyA¼s5/ (Ô»l Ó±cÇ2Q& ઒+GŽ\9\rxäÈ‘S=±qÃú~}û$“rætAbB  "„ € ˆªßà̉³‚¾Ö{ÑÂÇŒ©¯_÷S€Ý6­Zf, "\¦|õõšU«^¸$áX&AQ2úÊÂWô)wëÖ­Ô®öéÕsËæÍéʧBÙ›wnÚÙh A‘Åü™®¡î-  üð¯½ûöx5á3äš·K\€Vßk>&Œƒ (ÁÔn…,ËkV¯6 nnn€€ ÑDPpBÔ½/€r¡ŒRôu6Zkb2šßùK—,Y¼tY‘?|á_¸¢P! Aù…w6å‚ ]âÒäùåÄIé q¼aóf/oO@{Â[>Ðê°N=kþõk>H­æÕN*š€k=&×Q¢¨îÕÐ={¢<èÖ½;¥@âLBF BA’ "#ÄDˆ|çÎ-›`–Œ±¹?üÐ"88À¿îÔ¯¿V#ôNž4qåŠåýúö©]³Fÿ¾}ããâ lOè²eËbb¶l}ÿþÁƒÆŒÕ¡][õ ­[¶°ùôéSßjUeY€Å‹}ÿ­ùï®;ÄÅÅB|BüàO?mP¿Þ€þýâŸ$ &èü¹ß5l4eòd‹$«V.ù¤·º~U>é×G•Ěɓ&þ´vMßÞ½ýkû-˜?ïöíÛÝ»t©ãWkÑBsÐK Ïà¦MöïÛ׺e‹Z¾ÕgÏš¥^5c†º+tpÓ&‡hà_÷Èáÿ9Òºe‹ÿº–¸žÝ»uvô—-›·lÜ4°‘O™ÒBˆysæ5lÞ$øëñ_+ p¤¦i_Ô8°c»Ö\:Mˆœm¦Ô°V›´Ñ “Æk!„X±by—–­ZCòÆÓ„(„šP’@0õ Òn0Ë5«W]¼øûúM›v‡…_ÿ÷ÚºµæMu7®_?zô˜ÃGåÈá²qãK&nnîÛvîrrv^¹zÍ×Ó¦EEFݾ}<è_¯¾%™««k‰â%Ô=§OŸ:~ü8<~üX½;¶mwîlúþ?ß4ä‘1„ó—ôˆ IDAT{ãnßWÍÍ©S§þú믶íÚ¹¸¸'¨PP=€£ºÇ¼°R3»Á,wlÛÖ¥k7‡Ž;oÛ¶UM\»N‹%„T÷­qãú »òPJîÞµvîÜi˜ ¦_­_3‰‰‰œó?z¬Z嚪ðµj×)V¬T«^ýê­J7nßÚ¾{7GלˆÒµÛÖm;Õ]^*IíÚuræÌéêêZ¡bÅÊ•*åÈ‘#wž¬LÄ¢6êO¡STá9!/ŽæZÏÇQÐDí¦¿ÿþ;­Ý,äÌ™ÓËËë5„×xë‘8ãDí5(”*”–*]©A£€­¡[;õêåìLþùç¦M›æÏŸ?9½"t‚ITyAà„˜¬µÐÌRµMkÖ¬éÔ©SÞ¼ÑÑÑeÊ–€‡ä/`Þ5œ¤oëHŸòå9c³fLoÒôÅx¼/Q¾LTLÌÎðð†½~ÃúuÿœŸ4u*TRb»'d^OϾýúש[W âBˆ)C’¤LGËR…g(ôyÍ3n"¸ŽsAçΙûa‘7QÓzx{ôî3¨vz–»€\y Ä>|¤þ|üäI¦ Â'«N)1rÂ9×ç=œ˜ƒÜ©jäT^*Šâîîáîî‘;wë?õdÞ¼žyò¸yzz9::fié4ÞQ(5Zÿ}6r¤Dá›o&­Zµº÷èi^ur«)S:\í³lÒ´éêU+“’’V¯ZÙ69ÒDúiÜlÿ¾}›4¶9O)ó«]yßÞ­Uª”­RµÜ©ßX¬¨NG(5Úõ7kÞ|íšÕ léâ¹ã>ÿ<£’d")kù_Ù¾mó¸ ¬Å^÷Ó2£ñ!IË–Ì™0~¥ÆÀÀ:¡¡»Àd2mݼé-ÞnÍ#rBLVjc²ßcJJ2>xðÉ‹¯ÆDäœQ*)Šl‰nbCäÝ»“'M¼pþ¼¢°ªÕª~9q’——WlllZ5/ýõw¦V®X>aü {o®^ûÓÈÃOž>“žÛÏ=;tð ‡ÙßïãS>³¤ú/P¸H‘Ž:¯Zµòĉüqùò¨=5˜åøq_ÌŸ;·P¡BS¦M€Þ}úÆÄÄ6h 7蛵 ɨHÕ«W¿xñw77÷”—jùùݺuK ºS¹J•ª)‚ZÒ¶ÝÇ1-›7çœU®\yìãÒHü¦XÿÓZ…ñ~½{©?§NŸaWìŽ;_¿q½K§ŽµüüNüúë•:cØßZ÷äÉß@ ¨g…%X" !òæõÈ—ÏÎP®uË5kÖ/WG½ý îÿüóOÓà`I’$Iê×ÿ“ÑcÇZ\€¡{öøûûV­²g·9Žî?ÿÒªUíš56Pgvƒ›49sú4œ=s¦E3ó$ËŒiSìߟvyn\¿þiÿþpðÀÑ#GN?¾B¹²ª<­[¶hX¿^ÓÆgÏœ€î]»ìÝ»wÞ¼¹Ý»v€Ý»þßÞYGGquüŽ­%#‡ A‚V$xp×BѶTâw m©à-îî(ÖB‘â!@Üe7Y™™÷¾?^²,Éî&¡h¿ùœœÝ™g3»{çÞ÷î»÷@Ûð°¦ 8 55¾üâóóæÀßwîtía™&O\]]7mÞ¼dé²V­[¿Ý‘\¾t)¬UËÜÜÜòQâ_uSN¡Pxзw¯víÛ †Aú/^º,8$äü¹s£F ?wáb‹ÐÐÈóç4lxñâ…;·ogdd¸ºº^ˆ¼ðñØO­vg•?þ¸|êìYAF~8ì³/¾ìÚ­Û£G‡rêìÙõ¿þ6|ذ®ÝºµïÐáÖ­[3gLß»ÿ€¯ï¢… &NøzÕš5'M oÕª{žÓ§M5{Nq–þóXMx¹o÷®ÂÅJkD›49qêtiö(Q XLË:7k–ûð¡).®°`2ÅÇóiiÎÍšQ¬õêó,ܺeó¾½{¦Lšèêê6jÌh²œÌóü˜?¦iºZ` EÓ)))×ÿüÓËË+8$‚CBÜ5šsgφ´h1{ÖÌÏ¿üòÒï¿wŠˆˆ<®Qã&J•Òœ›×Ì…ÈÈù š¾]±Â-?­&dgeMž:eÙÈÈ󢈺vë•+W©\¥òÙ3§ÃÉfTصcG—®ÝÈJÐè1cjfffº»k>úø“>½zuŠèdÎÜùNó-Þö$þ_°éÇTõ—_„ÌÌÌÈHuƒNéîÜ©µw/ëâb˼á8nà Á áÈáC__±b¥j®®®¤ŒŒãxÞgvµOOÏøøøÖaaÏŸ=KHH0™L»<°ß`0¼ß¼yáŽÞoÞÜrŽéîß›_W®R…eYˆ‹ËÌÌ4›„YYY©©i–ÄÇÅ5j’7!êè¨V©T‰ ...»v™3{V•ªRæ^ ‰ÒƦ`âÜÜ877¥µ’Þƒ“…ÝÃàþýû‡ü⫯€eÙNwïÚuïîÝj… "O/ÏÄÄDóÛääd??_†aš4mºlÉ’† ƒš4m:eò¤ÜÜÜ#G•ìÂòµ9ooŸ *ìÝÀVI/ÏÄ„¼1ètZ½^O´§Å ö0péâE;uR«Õ%ê]BBâŸ`;½VkŒO¶!yçNc|¼ ÕZ­X¡B…ö/[²$=-çù“'NüùÇAY-Ò"4.6öì™3púԩ̡̌Ð"4t×ÎM›5S(+Vºrùò{µk¿Êõ4nÒ$=#ýÜÙ³×:44úÉË»tÙ·wOll Æø‡ï¾ëØ)ÂÉÉéÆõë?ž9{v‹Ð–Ë–,~µ®%$$^ ›‚éáèÑ·:v”i¬x*É<5gŽ(ŠÓ§N™9k6EQ_Oœ¸g÷î¼Z﯀u?¦÷h!÷÷¯µoŸÕU¹Û;Ÿ=«­P©Jk¨¥„”"\âí²tÑBësLrŽ{ïÊ™·7XHrs«iJHÀ¢h¥²„„„Ä?ú`*PdMùËÛ¸%$$$^’ß „„Ä;‡I X@XváH¼°€$Á$a,b,¾åøÐÿ·`K‚I˜\06ZÑ / L÷–-‹,&!aLI‚I ˜Sb®`ÀÔìœÖ­'qËKx '-\WB¢ø`N)M~K”'ä%¼4ìäGkß&üÚÕ«ÿp¯!áe>sfÏ.˜ðòµòÅgŸ?vì͵oŸ ‘‘Ç -ºÜ»Š¤1IüS^Jxù†y /%þ H“Ä?¥`ÂË¢ˆ‰‰y» /öï— ðrÂËœx‘9òå„—…Gb‰Õñ@bbÂÃ[·úâ³Oõz=¤§¥5²MXXÇöíVýü³­B2h’³›7mœùÍ X¼páö­[‡ øÉGc¬Ž!D2\öíÕëÖÍ›%ù ß9$Á$ñx)áeñÊ¿› /÷ìÞ y™#wìÜ{à€^Ÿ»eËû#!Øÿ‘C‡—­XqäØq“É´fÕ*øqåÊê5j;qbǮݷoß~ôè‘Õb‹-›7uíÖmþÂEVǹyãÆo†ËH‚I¢d`Œ=šŸúí¥„—Åàí'¼¼p¡Qã&ä¬eÂ˨Ç`×Îý ppt¤(ªoÿ{óãsÚ‰­ñwëÑÃÕÕ•a˜Aƒ‡9|†¾qýÏׯ3 ³âûï+W®lõ†Øº{+UêÜ¥«ƒƒƒÕq¾s.ÿÒ“Dɸ{÷ï±c?éÚ¥ëü… ॄ—Å ”^¾ÿ~óÓ§5jܤNºE]¼yõÊs_ß—^@bBº5k·mÝ !óFQû#±5~söJoŸ””óñ'+¾ývÚÔ)ñqquêÖ¿p‘Õb‰¥˜ª\%/цÕq¦¥¾Í —¯I0I”Œ5j†……íÝ·wð!J¥²`ÂË¢(Õ„—Õ«§$'>tÈœðòÞÝ»3gÏ!gí$¼,pÜþHl?+?ÍdrR’‡‡ÈåòÉS§R•––:gÖ¬Õ¿üÒ­{÷Â7D¡PˆBÞDU’E$EŽå쌳Œ»{zZ:y]Ú._7’)'Qb¾újCÓ Ìß°a=JxiŸRNxIQTÓfÍŽ>T¯^½zõë_úýRÅJ•X±êÁ"á%ÆxÕÏ?3ᥭñ:x ;;[„ß~Ý@„æˆaÃ6m܈ruusrrR*VoHÕªUÉ$QrròéS'‹9ΰ°ðÇÂ[Êpùzy#S­êÛvì$4 ÿç_|Y·^½"+.˜7WåàðI±³¡,^¸P®¿¼ÄkAJxY«ãW«FóáÐ2³²š5m:bÔ(˜·`ÁœÙ³6¬[K3lýúõ†iõ†´m×>òüù^=º»¹•éÓ·ß“è'züïe¸,€õ@qÿI0ý«™7{Ã0RÂK‰·…Í„—oˆ–-BŽ>Ü6<¬N­šsgÏ&ÓÓÒÐ:4tðÀæü%ܼiÓ­ùK¶Ïž=ëݳG“ †Ýºt~eÙ²N§íؾݕ˗KórþŸ‘^J¼QJ{ò{ÛÖ-;wïFGthß¡S§ÚµkO?¾V­÷6ü¶1!>¾c‡öC>ø¾úâój߯\ÛµsD­Zµª×¨1òÃa Ö»Oß'ŽþÙ§ûäåòaôÈQ jdWK—ø‡H /%JÒLýú÷wtT@ºuŸDEU«VíÌéSóÌoŸ6mÛ@FFÆ©“'W|ÿøúùuêÜyçŽí½™¾©©i½z÷€°°ðÌŒ ³»Ç´©SDQèݧo)_ËÿRÂK‰Rã˜r à ô"ÌFØœQ®\9ÿ¼2,k43220Æîîy¹Xœœ >.ÎÁÑÑœw—dÁLNNöôò4»{ôìÕ›¼ÞµcÇr ±±1oâZ$$$JŸ7"˜4¤¤$óÛ¸ø8×üäÝÔË9/]]])Š"» ##<<=õ¹¹:]^Þºä¤d_??F“`Ö’Ö­]K^{y{O›1cøˆ‘Ë—}û&®EBB¢ôy#‚©yHðO+W>‰ŠJOO_·v-E???«%åryhhË}{÷@B|ü‰'@£Ñ4nÒdå? „bbžØ¿¯Oß~U«UssuÛ²y3ìÞµëè‘ÃDcjöþû ÃôìÕëò¥KÑÑÑoâr$$$J™7"˜>ÿâKÿòå{õèÑ¢ùû‘çÏmÚ²µprp3s,8yüDŸ^=gLŸÖ!ßs÷Ûßݹ};¨~ýAL>½J•*4M¯Z³f÷® êÖݲiÓ¢%K-á8nøÈË–,y—#!!Qʼ?&‰5¶ü˜$$J‡Òöc’(’`’xç“„„Ä;‡$˜$$$Þ9$Á$!!ñÎ!Š“(.RÂK‰RCLÅ%--µu›¶E;yìh) Fâ¿dÊI”[ /-±U÷¿ðrâ„ñáa­gL{³.c?þ¸¤I4çÏóðÁƒ74ž7‡¤1Iü›x7^ÆÄÄ\»zõØÉSÅ̬WšÜºu+¼mÑz¤1I”6ÿ±„—çΞùá°ŒŒŒ]»œ;{633sÜ—_vlß®mxø®;m]²Õ”–VÓaZÅj/7ÿú«wÏžÚ¶éÑ­ë™3§ WÏ<øzüøY3¿yåÏë­ & +à7BèÓ?êØ©ÓñS§‡~øáׯcŒûuÃÍ›mÙ¾ýÀá#O¢oÞ¸‘Þ¶eËøñΜtttضm«¹7·2»÷íWªTëýmöܹñqñÏŸ?ÇŸ:y²EhKs1µZ]9 òõ?ÿÄ_½zåÂ… ciG­VcŒ÷îÞýÉgŸ?yJ&“íÞµ c¼wÏîsçÎnݾcÏþý¹¹9›7o¶?ŒqpHÈ’eß–-[v÷¾ýÁ!!“'~íWÖïÀ¡ÃkÖ®ý~Åò»ÿmõ’­²ò‡«×8züøö»nݺõðáC[% ÷‚1ž6eÊç_|qðÈÑeË—oX·ŽçùmÛwT®ReÞ‚S¦N+Ùçô¶‘“D©òŸLxi&33óÜÙ³Ã>>¾¾mÛ·ß·wOñSZN‡Yü^€a™“'OFE=öññ]·áW;É`Þ}$Á$a…7÷$LNNÖxhÌ]tîÒââÊ”)Cޏ»kâãÉk¿²äÃЃÞV›í;t,<<%%ÅÝÝš5n\¸ºùõ ÁCrrrûõéCINÿæ;šQäË–¯˜2yRû6mÕŽS§O¯Y³&ü²zõÔ)“׬Zåïï¿pñ…BÑ¥k·kW¯Ðßͭ̆>‰~¢P(–-_>gö¬m[6“t˜ŸŒý”´Y¸#«½|÷ÃÊeK—¤§§s,Ñ¥Kë°0öáð©“'mX·þ·Í›íx™½S( ›â®­_ÿdøðšýú)êÕ3¥¤pz=P”!U` þ¯¿žnÜ(6¬õÒ¥…+À„qãnݺ¹fí:wfýºµ¿®ßpüÔ)•J% ¦ófÏû /í %¼”ø‡Ø g4ÿš;×W£IÉÈ(;t¨ï°aqÑÑq·o»téR~ذ4ŒËøú>ýñÇœ””Âuãbc·oÛºlù __™L6bä(ÿòþ—/]²,sÿÞ½žÝº7kÚ6<ìÆõëäàöm[[4?4$¸wÏæ|–‡ kÙ2¼UËýû§XëNâÿ)áåë¦\â½{ÌãÇ"Ãàk×NþyØ?VŸ7/3:Ú§yó+ß}—³w/ÎÌt5?^§ÿuÿøã/oïjÕª™lÚ²Õ²@nnî ý/]rþܹQ#†Ÿ»p1G§›=sæù‹¿»¸¸?vtíš5³çÎ~òäëñãöìÛ_) `û¶­S&MüyÕê×~ $ CVF tw×ìÚ¾­ÈºGáºoŽF?yм.Í~_ 4MÑ4Eæ§1Æa„ ^EQ ó¢Œ(Zùh¬BQËÒµZ½jÍÚ)“'ÿêK_ß_V¯–ÉdÍÞÀ }{÷âM¼ÚIý튎ŽUªT™6㛡ƒ‡ètZÿòå¿[ùã¿zûÏ¿Œ± ¹Üáê9,Kx&#„,õ YQ‰ô!Ž<¢˜'Ú(ŠbF¡PF„Dªï8äV˜êοÆG C1 %Š ÏÚ*Ú´)û£uºlG/†);gŽßøñï”î'ñº˜7{Ƹ°Ï‹f©d4æ§)K)f4æpÜK[@xž—Ëåä[$1(È)"•d2EQ…Õd–eišÖëõ…Å™UÌö UÙGÓ%f)@nEá%3™ŒÁóü }eiš¦ÂE!„Él”2öÂZLÆ`l¥‹b6ûYºh¡M„a˜ÊýûÇW©¢œ3Çxê”A¯Ç –ulÚT3mZ™–-%©ôH1åQ1ËSEì2`Æd2‰¢HÄƘ¦irÐ\ž¦iš¦É–™LÆqÙ§jÿ«HÚ'J–ea"­”J¥Éd*²‘RƒèLŽ`l6ý¬ [†˜}­Èfß.ö,#†aÊ6nì¹kWVjª1*ŠFH öô”ì©ÿ[ìÛqFcŽV…Bˆrã8N.—“à$D¯a¦ÀDÃ0D¥2™LD½"uíƒ1–Ëå4Msg4-•2Žã(Š’Édz½þ >IQÀ² ˆ"2O?1 MÓŒ-=èõ6ËqyGH•ÒiI)ZÄÈd2øø”Âh$Þ¬:XÚ‚e1Bч­6B&“‰ã8¥Ri0ˆ<¢iº€`"£"B,Ëݪ˜ã$ûZEQ$j™®*rlo L4#Ë~Í3âä ‚€Ì÷!Jˆ¶ã9Y°›B×UÌf‰7©Îq¬Õ¦ÞÅ {"!aIÅG.w@HÔëJ¥B.WX-`¿AŽãˆ1ÅóNÓ‚^oÌMûúú6 ¥¨¢§lhšEQ¯×«T*Š¢ÈÌ‘Éd’Éd …!dÖ›(ŠfYÖìàCB> ‚h¹gÒ8ñ<`Fs-“Éôj’…LQaŒ‰ VÒê!²`Pž8 (Ц)lö{EÌ0ËÒ‚ æ—ÉóŸ,°mlÚYV§Ù·¾7……ü0öIKKíѽ°¥f)˜àä±£4(ŠB¨èç-Ã0¢( ¹\.“ɈMGæ›,|—ò6X „ÂäLQÏ£bJb»yd^ $šÔ«9CaŒY–%«@!Kë²Ø-€ –e8ޱð«¤áÅÌ‘("Šš¦9޵pq¢BfážÅ”&Åi–L*€LÆšLoÁ«™s×CÔiÁÚ´ì£A,ºd÷¥ßNzت°]w!¨]±¼óÙ³?~9.¢òØgYw&éwýFF½º®›úÜšy¾ûƒøG›úÜšu¾çýø€öÕ(rÍ›7ŠŠzøð!y+g¡¼+îãtIFñ ”G6íäFëš+¢dúCÖxí÷¸L0?3BBB ÅÅ‹m5žúàAFZšÉdªX¾JõêŸL›ž™{ãïçNjGÊ”„€Ž¼vâÜÕG©Tª¶Eåá*WƱ¿GY}JŠy?8«V«Ê——»»›²²øœ^«eT*¥§gòµk¹ ŒJu”æôVüD¶nÍ ½P½zuHKKÕ†ú¬]ES4CQ E1TB–bç“Aë6’Ëå Æú…U½ ÌZk˜¹Æ`n§OŸ>V‡z³ÒPÃÕK]º é·Þ«øá˜cJÅcg®ô\pùÃA­¯G§zz9ßy®­ûd-©U£ZU«ßr'''€‚ÁÆhZà8£åƒÁIJŒ\.ÅÛµš4 ÂH š—·÷¸ñšñ ³Kæù¦õê>zÌÕÕµI£ c'NyxhDQ$M Ê"fš¦i"ûŠóƒ$J“R©Ä/˜7·s—®Õyžñá°¶íÚwïÑcïžÝ4EGtéýõÙóç“§L±Ó‘nÄ1Ýr­àø±cXñý÷E‰lègšh‚aQ-U¡Ë—.ÍžùÍácdž²UˆZdm½â¥­<–ð¼HÓØN³F#r9k4š¥Ò«‡àå<`”¿ÿ6ÿ£8«å1Æìûþ‘âbJÏv£³ÅÄõ´26ÀQ±¦8ýmûsuDå± V ÙYyuFmán,ß-Ú¬¥TJ¥îåt] C—/ë_F{ï=!*ß;Xžì\ëtŒg¶A´lR«Õº¹¹Ù¹kœ—Å0`0Ô mÚ¬Y³Ô”ø¬l=FüÇECJ¥ ¾ÏâµiÇÄt‘’iL´²ÈcŒh•J®ÑÈÊ”a”J iÑh4¤§‹&ÅqršeÆêÊ•y£Q4-½œ­’››ëàà ŠâóNäÍPS4¢@¤Îƶ>}áÎóçÏ?ìZî}ßß#Eð)è+hµY‘’ž%´ŸØÆË­Ñõ+cž<ÎÉÕGG=~õðÎíÛÜŠ×êÒ2œÔ2Š.Á W‘‚(Šz¥R!Š/ÆùÛ¦ÍÕ1ƧNžüâ³OÏ_ü„‚$ ÿD6‘™&œM3D£A“e8„ ˆÅm˪µb ¢‹Ýºu«ux8ùN›ñ ‰ëø4:Z©R³s`I2H"O‹? 3a„l.®=rxó¶í!ûÛo,dG±Žçw]ô®Ëì·f^Á—ä#ʃý Ÿ_éXýb¬|pçç8홑É5D9g#R¹òôõÐ<üUryrô®ÿ!<Ž®”ËàYÚÓôÌ\7•ek èTª””ÙËÛY\ÝÜHB‚ Bb6^U¶–O€¯£Ñ6ñ˜Ž5ªþŠ2>KsŒ/]iVV–«‹‹1»¸¸dgg ‚œž™ždÈá¦RâŸ&Ä'Wð÷EñÇ}¹§ÞžÁC*;ЯC†E\<Æœ››²bEQ¯'Ï>;;ûñ㜄Ñd†¡9ŽutTW¬(/S¦L:Ú§O!á©ý»ª×ëÉó<> H.£(‘ u3ÙïÆs×ÈÈ}-úŽë”ÄE].P4àMÓÔ µÑVãÚkrh\åÕ*(d̶0Æ.®®uêÖ­×,lÛ7u険L“ 7£’Šó¹sÑM&ã l”7CQTë°°É“˜Ä„„ +þý÷Å jµZ„P×n݆|0Ô²$Ëæé#ii©³¾ùæÞ½»&?bä¨~ýûQ•™™9gÖÌ{÷î ‚8|Ĉî=z@§íÇ~úÙO?®LJLìÚ­û—ãÆ…àîճdzèè‰&4mÖlÒä) çÏïqåÊåcGŽÐ4}êÔ©í;vZŽöø±c+¿ÿž¢@ãé5wÞ-** !äãëG„fvvöÌÓ°ºëµýVlûsµù;¡T*}}}cbb «DÓ6¿1dàAŠÉÐ+X`!Ðó†\x_V«U(í©9Ç999åää\¿ù JEŸr¾îzããíééáFSÀrÆ *ÿëÝFÎtIøYÑ“ ×ç$&rNN oo^¯O¹qØ‘ÈnqžG¹¹83Ó´›£cNR’>3£"4a½^OfU’³PN.f) 0šè뙡[·m¯UY3§w¦¬lŠa)–x¸R‰éEÌV6+ssÏcçè˜ôʽ|||FúMÓ€‘`4˜ŒúýŸVxöý²Îª¨k9ú\„‹þÜ‹³WŽãX–•‰"Xt¡û÷ùùú–ó÷G}6vìâ¥Ë6l˜››Û.<¬Eh¨Ÿ_YózœÙ…rÒ×_TX¸xq|\ÜÀþýëÖ­S½FÉ¿®Z­ê¢%Kâãâôë[½zõÀêÕ`÷®~û !Ü·Wϰ6mÞ{ï=²»…¦émÛwôíÝëËqã4hˆ1&ǧL¦vtTªT#G¶ê³§OgL›¶iË– +îÙ½köÌo¾]ñBÈhÌ3]çÏ›'ðüácÇâ?4¨nÝzpãúŸmÚ¶=züó7®øvùòï¾{öôéŠåßnß±ÓÅÅåæ_÷Õñ'åröÒï‘S§Ï˜6cÚ–Í›¾]ºø‡þåçŸ\ÝÜö/_¡×ëôísçΚ5k.˜7×ÑÑqÿÁC99ºAýû¿W»vÕjÕ¦O:qòä&M›$&ÆO›2¹U«PÚÒ“ËY“I(ü½ËY„°¥Ë2 CY-ü¶ ;x¦Œ«w¶O¬g"¥½¢zø§ÛŲrp+¶Ù˜1?ßø|T½oŒzœ”ólñ…Q>^j'Õxžÿ/7¾8ñp;ΖcŒiš.[¶l÷îÝk×®››k6ËÍ(Š^¼"‚\¤é > ž§Cl&¤ê ÇTP*€V«5g%³JNNŽ‹‹ ˲IÉé_zð8VŸ›ÍR"M9Ú¬çI¹‹~}—œ•ƒihÊþ ÀcŒ°>=Q«¾¾ú´´Ä‹õ))¢É$ ‚(Ï“ÿ™ÑÑ9 ¬JeÈÌÄYmÉ|&“‰Ì¡$gº\@<yt;¹ìž“÷ÊyÈæõÉVÒ¹¹¹HàˆHA#Êy¼ÐGì –1‰£¾\ÿÛú_#ÏŸ'~@‚(òbn\"ïœcLM5 ÍœÎXý”‹\ž§ó¼`E&52<¬u³&Ο?iêTbÔ¯Y·>((ˆ„¬^ãéÓg,ËÊd2–eXÑŸ™ž|ù÷³}4R!£*V(Û¹sûûvdg¦\ºpfÄðáå¼Ð³W/GGµ““SÍZµâbc•J%˲¤;Ëer²ëE©TšwÆ`ß¾½¡­Z’T]ºv»|ùJVVeÁ‘C‡ Î0ŒŸ_Ù)Ó¦‹¢¦CǎФI^MoŸ_ýÄ8¬]§Ž6;Û`0‚[¶íÚ™LBƒ†M¢ŸD@·2&£IEžç&SŽNg4<8|äHŠ¢Õ]ºìݳòÓ[>{íééýÓ/k)Š!ž“û+ý؉gð¶`ÇUÉdä@iA—Lé²°³ŽGªâîåóñR÷êÏØé½¸BDå±Wâ÷LF¨ègoœîºâçÞnn®AAAÕ«W×h4{öì1r¹ÜÒj iÚÉÉÉÅÅE¯·²]$®®®$zKÄÑÑÑËË+''çæí‡÷<)_ÎÛÕÕÅhB1)8*;ñííÅÉÞ”‘®¥D£¢(‹c$×hºçÏ3=âµZ„&Ë38/B*Âó|ÚýûÞM›*ÜÝqF¢}C‰x€Î ¦j)ogŒDºŒ_÷<î´k¡s“ëy#Åq”Œ£d4G…Q€}õþ‹:¶ZîÐ4kïeõÖíÇ+ø9ܳÓÃÓ§\ùòUªUuquÝ:ZáæLi“ ¹< (ÖçnË”S©”ƒù·a2™d2Åˉ°ò§Ÿ«ÀíÛ·Ç~4fíú å+TÐiµcFzöô©\.‰yÞ¡cG2—IJ,ËP K1 NLˆurqtqq$íøøzüuãFRRœ“«£“ZE"|xxxüuã)`N—°y Oƒì>üÈ…cAˆ£9Ñ› _lB|ü×®õëÓ›¼urvJJJrvv6_cvv¶g~ÔCs6:s^<Ž“™d2ÙåË—víÜ©Ój•*•A¯'_u??¿¼q24±:FDôîÙ5¢C{µ“Sß~ýƒCÞü8Ož8Â9ºœÀê5`Á¢Å?|·âƒAC´:]»ví¦L›îàð"¥Šý¨L$ð“y5ç{±’È–fw*s8M¹œåy‘ã˜RÓªXCE3`ñ£T¸§‹®Ý¸¤Î[5êPV/ŠX06¢òØ› ‘y+q‰*ÃEO%çP±JÅ-ZT©R%==]¯×GGGC!»ƒeYFÃó|VV–Á`°Þ H.¢™줤¤¸¹¹eggçää$%§>‰~¬ 8V§Œk=gFŽù\]F|ùìiéÎEÝ“qKÔ=úùc“6[4AS `Î[ !ÿ°Ayÿ–`Ðg5µl6x^ˆM§jùÁ¹þ³gÚ^µbåœIä)޵ ”Ð!ž¢è÷’Æd§ñβŠqÑTÏ0ò·îž÷ñºwéÂy™Œ‹|€uY9É1­š'óc/lÊÑ4£R9ˆ"9*U^^#Ae2d+àW­ZµjÖªéääôÑèQ³çÎkÒ´)MÓcF$xž7™L+)@HãánÈÕétYù)“¼}¼4w£N§ÓfËT.`‘÷(:oµŽøWr2‰Nìeó¾óm7‹0K<½¼Ú´m÷Õø‚2™L­vJLL PÀÑ#‡ë7hHnH’GþùÇŸ¾[¹2 cÜ8¨aþ­+xV,ÿö˯ÆuŠèj>âååɲÌÊŸ~Q©8Ž!ò ¥·Œ<¶Åj²Ñ(Èå6½‰ó$™w'¾”dÌLj""VÃP,˘}†.M[~ô\¼üØpìAîæG)Qµ‚PQn¢F ‹‹+ÝxžÿÏ×?OÖ&XýWu™ˆˆˆ^½z$'';99=}ú4--lδ„ã8–eãââ’’’RJHRRRrr2Ù¢iä™™™F£Ñ¨T*V¦™+pe€UQ ŸÌn—Ëœ‚ ~*ú&p,ï¬2ª¸ ‚‚›7gü}Ýk׬Ü"¸\ã ¶‚[¡lÕÐU[†V m!8)ÁÃRÈíßOŒ1ùý‚ð,L´ú~vÊ*§MÎr\F‰eÆF<ŒxèûB09æ¶íª‘.žes±bó‰èmg亸XcöÓÐf¬­QA ÌšBq¡( cëí „nߺuóæÍŠ•*jµZ†aƒ5¢(êáƒwïÞS*•Ä¥Àd2åE¡Æà^ƽaà5«V#ÅÆÄ=|¸{·înn 4\µj5B(66æè‘ÃÝ{ô´Ú#‘8fuÉÍÍ-.68îÅrµ››[R¡ÀÍ;E;z$66®^¹Ò5¢S,mÛ·[»z•(ŠO¢¢/\X œ™ÔÔ´Àê°kçN£Á`ùøé׎qRR’å|«ƒƒ²e«°Õ«VaŒ³³uŸ»oï­VÛ¦u+¢!zyy«ÕŽŽ–>PVZ~ù†˜5DšÎ›™ÂL&ÁÒ½ÓR‰ôjRÉ™V9ÑJ'F¡fejŽsäXGí £¬Äå~»Ê·zÑ×QË;Àù‡§0O£ ¥)ÊFlƒ ȤczzºZ­6 >Ôétl¡G“³³3Ïó‹/¾ÿ>¹eØb‡TÞDIþ^sbÛãüÝ¡5j˜L&—¬¬,k£{ÉdòññÑjµ4+׋rc±i޲'õÕ{A(Áš&ˆ|uºuê~íúÕ zAs–Ì®]³Ž«³kFf˲Ÿ<&§àþÃ{¤J‘s7dï;BèyÄäz§Åž)«ÎÔ8’ša0…9GÔ9&…Àºyê´YsfÍš9³Sûp–å:wíѹ EQ‹–,?o®9½e£ÆM-û` !:>Õòq^-lؾòÌ#χ/â¯Ob`‘ß5pœM ªC‡%êæ6ãÓ,“H"ÌÓbºLÌà°Ž38”!G¦¼ëQ©T={ö¬U«ù±1 sÿþýýû÷'&&ÞCààà0qâD™L†Âý–Rç»±™“Jî Ã0z½~Á‚99%‹ôÊ8{¨U*X0sQ\Bœ¯·ï„iãÚ…µüäƸr¥*GN&§vïÛ ¹9¹YÉ=¼àСCæ×d‚V„VuÔÓ”e°sÎëŽ^"W2µ#wá”Îjg7§n_óñ׋o“º%ýíÓ¨AýÂâvnÛÞwÀ/žl-ÏÙJxi4æ0\0ÆJ¥’|šäOž³E±4Èe@Y>2Ì?œ÷Î$R¶9ŸB¾9DWâyÞrû9E"ŸPPo%$“BÁùn ‚ЬIã§N89¹@ZZÚ°-_ñ]…ЕР/IQñ‡4KË– ÷HÓd×!Æ‹""Il9Q$¿/ËYƒ·ÓTqÉl &–µ>÷²tÑB+vµ}jb?ˆôËŒ´u>¯5QÉ®`YöÙ³gW¯^‹‹³ºü¡ÓéæÎ«P(^-¤7™]*àŸùFA øýòÅ{¶Æ8)9)¼eÛØ¸˜í»·šO™/å` þþþÕªUóòòòóñzâZÎÛ¯‚›³ÂMň|Ž.;53=96ú¯ø¸˜˜Ø˜˜ç1ñI9¢_½|ùòÍ›7 qft:]iJ–‚ #ž`Ó¶æãç/œ;áœù­å)ÈwɱcÏ×××ßß_§Ó¥¥>£ù¨ §7Å%dÄŧ¦¤gër½7ñ6íüRøöh4{wm/rJ£ñ(,¶lmG+°ÖQ؈À˜ÊO/MÄXž-[Bç]F9jô˜>Ê™$rc4òE‘¨#ãa˜xqMQLפ"!Ö\¹#"Ë2$Ò.EÑd%î5]\ xS‚IÅK—.ùûû'%%EGGgdd¼ƒ_‚W€È—Ô„ŒW¨+ò¢ýðÒçÏŸ?þü+ìÕ*Ÿ×žðÒØÄL›ƒ0ÅóvÔ" c@v5¦wb+Y"ŠÈb€ ˆ…'¶ !£Ñú³¢pËŽ[ 2rP±åö`³2e«©7[Ò%˜âó÷ßÿý÷ßæ·oE!|Èlä†)FÆV¶ÃÃÃ_Ç ìù1½ËØ\aSö5‰ÿ$oJc’xeX)…¤„„Ä»ô¶Ç ñÎÑ¡m›·=‰ …caorD¥bm¹ 0ŒÍmÿrËšl? ¤yIEND®B`‚KDocker-5.0/helpers/appdata/kdocker.appdata.xml000066400000000000000000000033311252153257300215360ustar00rootroot00000000000000 kdocker.desktop CC0-1.0 GPL-2.0 KDocker Run command and dock window Esegui comando e aggancia la finestra

KDocker will help you dock any application in the system tray. This means you can dock openoffice, firefox, thunderbolt, eclipse, anything! Just point and click. Works for both KDE and GNOME (In fact it should work for most modern window managers that support NET WM Specification. I believe it works for XFCE, for instance)

Example para 1

All you need to do is start KDocker and select an application using the mouse and lo! the application gets docked into the system tray. The application can also be made to disappear from the task bar.

Example para 2

https://raw.githubusercontent.com/user-none/KDocker/master/helpers/appdata/context.png Context menu showing available actions and option settings http://kdocker.com https://github.com/user-none/KDocker/issues https://github.com/user-none/KDocker/blob/master/README.md kdocker Requires Qt Version 5
KDocker-5.0/helpers/kdocker000066400000000000000000000003201252153257300157070ustar00rootroot00000000000000have kdocker && _kdocker() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=($( compgen -A command $cur ) ) } [ "${have:-}" ] && complete -F _kdocker kdocker KDocker-5.0/helpers/kdocker.1000066400000000000000000000152731252153257300160630ustar00rootroot00000000000000.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "KDOCKER 1" .TH KDOCKER 1 "10 March, 2015" "Version 4.9" "General Commands Manual" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" .Vb 1 \& kdocker \- dock any application in the system tray .Ve .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBkdocker\fR [\fIoptions\fR]\fI\fR .SH "DESCRIPTION" .IX Header "DESCRIPTION" .Vb 1 \& KDocker is a program that will dock any application to the system tray .Ve .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-a\fR" 4 .IX Item "-a" .Vb 1 \& Show author information .Ve .IP "\fB\-b\fR" 4 .IX Item "-b" .Vb 1 \& Suppress the warning dialog when docking non\-normal windows (blind mode) .Ve .IP "\fB\-d\fR \fIsecs\fR" 4 .IX Item "-d secs" .Vb 2 \& Maximum time in seconds to allow for a command to start and open a window \& [default: 5 seconds] .Ve .IP "\fB\-e\fR \fItype\fR" 4 .IX Item "-e type" .Vb 6 \& Name matching syntax. Choices are: \& n = normal, substring matching [default] \& r = regex (regular expression) \& u = unix wildcard \& w = wildcard \& x = W3C XML Schema 1.1 .Ve .IP "\fB\-f\fR" 4 .IX Item "-f" .Vb 1 \& Dock window that has focus (active window) .Ve .IP "\fB\-h\fR" 4 .IX Item "-h" .Vb 1 \& Display this help, then exit .Ve .IP "\fB\-i\fR \fIfile\fR" 4 .IX Item "-i file" .Vb 1 \& Custom icon path .Ve .IP "\fB\-j\fR" 4 .IX Item "-j" .Vb 1 \& Case sensitive name (title) matching .Ve .IP "\fB\-k\fR" 4 .IX Item "-k" .Vb 1 \& Regex minimal matching .Ve .IP "\fB\-l\fR" 4 .IX Item "-l" .Vb 1 \& Iconify when focus lost .Ve .IP "\fB\-m\fR" 4 .IX Item "-m" .Vb 1 \& Keep application window showing (don\*(Aqt hide on dock) .Ve .IP "\fB\-n\fR \fIname\fR" 4 .IX Item "-n name" .Vb 1 \& Match window based on its title .Ve .IP "\fB\-o\fR" 4 .IX Item "-o" .Vb 1 \& Iconify when obscured by other windows .Ve .IP "\fB\-p\fR \fIsecs\fR" 4 .IX Item "-p secs" .Vb 3 \& By default, when the title of the application changes, \& a popup is displayed from the system tray for 4 seconds \& Works well with music players .Ve .IP "\fB\-q\fR" 4 .IX Item "-q" .Vb 1 \& Disable ballooning title changes (quiet) .Ve .IP "\fB\-r\fR" 4 .IX Item "-r" .Vb 1 \& Remove this application from the pager .Ve .IP "\fB\-s\fR" 4 .IX Item "-s" .Vb 1 \& Make the window sticky (appears on all desktops) .Ve .IP "\fB\-t\fR" 4 .IX Item "-t" .Vb 1 \& Remove this application from the taskbar .Ve .IP "\fB\-v, \-\-version\fR" 4 .IX Item "-v, --version" .Vb 1 \& Show the KDocker version string, then exit .Ve .IP "\fB\-w\fR \fIwid\fR" 4 .IX Item "-w wid" .Vb 2 \& Window id of the application to dock \& Assumes hex number of the form 0x###... .Ve .IP "\fB\-x\fR \fIpid\fR" 4 .IX Item "-x pid" .Vb 2 \& Process id of the application to dock \& Assumes decimal number of the form ###... .Ve .SH "AUTHOR" .IX Header "AUTHOR" .Vb 2 \& KDocker was written by Girish Ramakrishnan \& Revised and maintained by John Schember .Ve .SH "REPORTING BUGS" .IX Header "REPORTING BUGS" Bugs and wishes to the KDocker Home Page KDocker-5.0/helpers/kdocker.desktop000066400000000000000000000003061252153257300173630ustar00rootroot00000000000000[Desktop Entry] Name=KDocker GenericName=Docking utility Comment=Docks any application into system tray Exec=kdocker TryExec=kdocker Icon=kdocker Terminal=false Type=Application Categories=Utility; KDocker-5.0/helpers/kdocker.pod000066400000000000000000000037131252153257300165010ustar00rootroot00000000000000 =head1 NAME kdocker - dock any application in the system tray =head1 SYNOPSIS B [I]I<> =head1 DESCRIPTION KDocker is a program that will dock any application to the system tray =head1 OPTIONS =over =item B<-a> Show author information =item B<-b> Suppress the warning dialog when docking non-normal windows (blind mode) =item B<-d> I Maximum time in seconds to allow for a command to start and open a window [default: 5 seconds] =item B<-e> I Name matching syntax. Choices are: n = normal, substring matching [default] r = regex (regular expression) u = unix wildcard w = wildcard x = W3C XML Schema 1.1 =item B<-f> Dock window that has focus (active window) =item B<-h> Display this help, then exit =item B<-i> I Custom icon path =item B<-j> Case sensitive name (title) matching =item B<-k> Regex minimal matching =item B<-l> Iconify when focus lost =item B<-m> Keep application window showing (don't hide on dock) =item B<-n> I Match window based on its title =item B<-o> Iconify when obscured by other windows =item B<-p> I By default, when the title of the application changes, a popup is displayed from the system tray for 4 seconds Works well with music players =item B<-q> Disable ballooning title changes (quiet) =item B<-r> Remove this application from the pager =item B<-s> Make the window sticky (appears on all desktops) =item B<-t> Remove this application from the taskbar =item B<-v, --version> Show the KDocker version string, then exit =item B<-w> I Window id of the application to dock Assumes hex number of the form 0x###... =item B<-x> I Process id of the application to dock Assumes decimal number of the form ###... =back =head1 AUTHOR KDocker was written by Girish Ramakrishnan Revised and maintained by John Schember =head1 REPORTING BUGS Bugs and wishes to the L KDocker-5.0/helpers/kdocker_man.sh000077500000000000000000000003451252153257300171650ustar00rootroot00000000000000#!/bin/sh # Create man page (kdocker.1) from pod template pod2man --center 'General Commands Manual' \ --release 'Version 5.0' \ --date "$(date +'%e %B, %Y')" \ kdocker.pod kdocker.1 KDocker-5.0/kdocker.pro000066400000000000000000000036661252153257300150640ustar00rootroot00000000000000TEMPLATE = app CONFIG += qt QT += x11extras TARGET = kdocker isEmpty(SYSTEMQTSA) { include(3rdparty/qtsingleapplication/src/qtsingleapplication.pri) } else { CONFIG += qtsingleapplication } DEPENDPATH += src INCLUDEPATH += . src /usr/include/X11 QMAKE_LIBDIR += /usr/X11/lib LIBS = -lX11 -lXpm -lXmu INSTALL_PATH = /usr/share/kdocker #TRANSLATIONS += i18n/ isEmpty(QMAKE_LRELEASE) { QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease !exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt4 } } #updateqm.input = TRANSLATIONS #updateqm.output = build/i18n/${QMAKE_FILE_BASE}.qm #updateqm.commands = $$QMAKE_LRELEASE -silent ${QMAKE_FILE_IN} -qm build/i18n/${QMAKE_FILE_BASE}.qm #updateqm.CONFIG += no_link target_predeps #QMAKE_EXTRA_COMPILERS += updateqm TRANSLATIONS_PATH = $$INSTALL_PATH DEFINES += TRANSLATIONS_PATH=\\\"$${TRANSLATIONS_PATH}/i18n\\\" #translations.path = $$TRANSLATIONS_PATH #translations.files = build/i18n icons.path = /usr/share/pixmaps icons.files = resources/images/kdocker.png desktop.path = /usr/share/applications desktop.files = helpers/kdocker.desktop appdata.path = /usr/share/appdata appdata.files = helpers/appdata/kdocker.appdata.xml completion.path = /etc/bash_completion.d completion.files = helpers/kdocker target.path = /usr/bin #INSTALLS += target icons desktop completion translations INSTALLS += target icons appdata desktop completion # Input HEADERS += src/application.h \ src/constants.h \ src/kdocker.h \ src/scanner.h \ src/trayitem.h \ src/trayitemmanager.h \ src/xlibutil.h SOURCES += src/application.cpp \ src/constants.cpp \ src/kdocker.cpp \ src/main.cpp \ src/scanner.cpp \ src/trayitem.cpp \ src/trayitemmanager.cpp \ src/xlibutil.cpp RESOURCES += resources/resources.qrc # Output MOC_DIR = build OBJECTS_DIR = build RCC_DIR = build DESTDIR = . KDocker-5.0/resources/000077500000000000000000000000001252153257300147175ustar00rootroot00000000000000KDocker-5.0/resources/images/000077500000000000000000000000001252153257300161645ustar00rootroot00000000000000KDocker-5.0/resources/images/about.png000066400000000000000000000164721252153257300200160ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsBIT|dˆñIDATxœíy°$Uï?'³¶»÷]{ošÍnèn  Vy2öŽ£=ó18Oob4ºï(†3L (3ódT#AÀÔ熂¶8Ç fùÝØ<Ų ®l%~ö‡¸óò_„3°x8:`Çý˘ç“q-à—Z€YïÈšl=®‡3Oèá´5]dRF@ñU¾X¶yfß4O½8ÍÓ/M3[°¢iÔ­D ä͈ÌMÜñ¦|8c­ÇÒ+ÀÕ÷_âËÀºZZˆ7„`ëún.ØØÏ¦5]ÊĸFØöŒÌðÐsãüâål)äBÝÂó ÞÏ—.i ¸t °ýî Föù„˜ºõÀ«»-Åùû9C?½éøíŜ徲ÅÇgKüøù v¿0Á”+nt Ámtoä¶+ 1J K£×<°ì¯[ÙY8íÌ¥ù£Íƒ\°±´dâƒë7=5T²$ïç{Ïf¦`—­Y ù3,ñî¼ä•†Øm‹¯ï|à-öÝ@OØíY[Æä’S¸hS?Ù”ÂiÜ.æ ù’E¾laÛK›dӂ޶"’^H¾'«P’üð¹#ühï8óE;Â-pÄ;ùÒÅkw%,®\óÀû@þ »½;c}oý º•Q||LÍ—xåð<‡&óÌ-eÉtÊ`°'ÇÊe9{rº¤#y›œ/sߣü×Ë3j"õje$æK.ºñd°H ×|óòưfûº2\µm§¬ît¤Æ`Q1Ãò%‹F¦Ù?>O5>ëíH³º7G_W–´)8<]äàT‘ýãõ ¼·3ÆÕ]ô´gêÄ›­=#sÜ÷ä(ãsQë òS|áâ¿k®5=´^¶ßm’i¿ )¯ñ·^o~Ûñ•YîçU>4cS~ùÒ$¥²M6mpå˹hÓVv*o4FÆóì~þßx|?cÓ%pâŠNÖ/ïD-8…›u e›ûžå©—fÃéH>Ç/¼DЂC"h±HÁ»¾õE;*­ù›K›‚?9kgߣǞf,ðûÑ9~½ )áͧòþ‹×Ñ×™ ¨ëF¡lsߣû¹ó'û(Y6+–µqÊÚLÃisEU<úâ<}„²­’ïB;RÜÎÔë¸çÏÔ>+´P¤àÏ¿yˆ¿j¶¿3ûÎ]ÅòîŒ/OCuæËc³¼02MÊ|ð²xë™Ëcq^ųû¦ÙõõçŸ-1Ø“ã´ã–XaT(Îþ‰_}ôGfÃ’äüÛ;Ze ÌVàݯÿ'7T.Dýí^ÓŸcÇkèiK#%õÏáÌ“Âsí?ÏÙóreŸÆÇ®ÚÀ[66Ü…¡î,ç¾®ï=3Æ‘™"èiÏhñQïƒPô£rtdMN_ÓÉ‹‡ Lç-÷8Õ†ÍØÂ™/eyòK-yŽÐøóov ¼Þ/Á†•\ý†UdÒ†Ö@ù”¢ZÖsØH~ñ⥲dÇ…kùoÛV4Ý•î¶VvòýgÆŸ-2¸,‡i¡|¨û¡.›2§¯éààd‰#så…ñZ8êŠpg½ï÷<ùŧ›îÉ+À»¾ù& îD`¸Í^娲®‹?Ù¶C„Ì"¼ƒ©1ã$Œ™ãÀxõƒíìüÓ×n1±²7Çèt½#³K’þîœ? ”Bpʪv¦ò6§Jî1«)WpÆ„'¿˜èÞĨ¥µx¸ú»k1Ä×@˜n³Á¦5]\¶eÛË–õCzÏ!C°då9’GJÉ.9#!áWñ—®%›2849O¡l+x¬óQ9üE)—ŸÖÇÆ•ín«YÇ ÷qí#“ìWr °ýî )ë^ƒužë¦ì¤åí\¾y "|é92hžž+XLÏ—èÎòÆ“{ëVýÎÛЇeKÆ&ó~¥ ¸”þþ*‰-%WœÖljƒm¸'Om<{|…íÏêÝÎh 9Èv|!^_÷]Õ(X×߯•[‡Ç@yå@)9ÀJŒM°¥äü }Á{DšÄùúƦ !Šé鋎sWnîem_÷XÖ:uÓÃIõ)xï·.@×Õ꾫§=Åå[*‘x¨Àug~À@O̱%lY×H—TØr\7¶„É™b€Ù÷Z±€2J^I.?­—î\u£³pRÞȵ?;/‰>5¯;~”Ã6oGáXAÊ4¸bË iÓ¨ kX OÙ|ÉFJèJÌ:úÐבÆ4…²MÙ¶¬™B¸Zq€£ß2)ƒ+Nï%åZ­†&&wñÁŸ5­íÍ+€U܉àu• ·¹ºxSË:ÒŠÒôù¡JãìRÙÆ–’eìЄÐÝ–Æ–•'}ÁÁ_µ :¼ý¬ô¯·=Í›6ôྮñzÊâ¦fûÔœ¼û;[|Äí#Wu²~ =8pÓñùAþRi‹…ÛÊ™¼÷AK²˜œ+W* ‡US)´³º3ß7V’ã²lXá «¨Œóu\ÿxSwA»&õ`·‚L»:s&gŸÐƒ%¥»¼ôFgÕüˆ¨­–-Õt„Ä46phªÈ©zÜÇÆä|™|É"µ°T ÚÜ<ºY­hE¦Žñp ÝÙë;Ù7Qb¶h{+¤°åÍÀëð¯Bãà½ß»¸ÈíWMÕ¹'÷bBßÔ+}}Ⱥ€"ÒÎeSH Ϩž¹'ƒ=¯Ì ©´i­ÌzÜXÀ’`‚sOìrsÝ-¼>vi£}jÆÜäY©'/ï`¨;£ÜB"ßÈuв¡³-‹-áÁg7Ñ¥p<ôÜl í9µà¢^뻢ÏÊq¨×_ޕ椡œsM€Ú…-naX6$ËÆ\ÀŽï¾ Ä*uÓ–6§¯íÄrZ~YûÀ[ÞQÀŸ®,æ(+Ü™étŠLÚä…sìye†M®M%Íc¾hñ½gÆ@g{fÁ½y˜ôx¼J¶Ê¬7æ6¯nç÷GJ”œ\¡±™Ñ§ßü‡Vgh@k¤óãþ§V‚SVwVnùBgG# *ÒöšSIWGÉg¾ó»øÝŠÀ—w0:S¢=—Á¨ÝÖ†X1Ÿ%kÞ-¤ ÁÆmžF ò†Fú_þòû Øê}jÕž19q°Mß7°Ü«Žêåz»Ú0 ƒG^˜àÛÿ5ÚÈx(ñâØ<_xxRBÿ²¶€¾Dõ!Ê-蹆“³´gªbs=o¹ˆ>}Fܾ5`ÌkýöY°qe¡ïÇ#-‚j0U±@}P¥ ,kÇ–ðÑ{~ÅžWš§óe®»c3‹®Ž,Ùl&€ç {z°lQ?¤éc”T„½a(ç~`T‹â[x«æïùA?¦xÈ:ýp.mpé¦^ ïï;B©«2#âU¦¯ŒàÀá&§çéïLsÛ{6qæúÆÌN¹þÎ=<³o†l&źU}þ§Œ5º°ó¦+Ö#âïçwìá·£ód2)V-ïÁÆBžCy Ú0âIì§»PùIÚá9Û ˜ØæAý×GtûÏüÕƒ{À8Å™dš‚‹6ô’6ýnA¿… BÞh?ªªãBJƧæ9<9À Cíüõ%k¹ôÔ~Ú³j½·lÉÏ3Éííc÷¯&èìÈ24ЭPõìTóV 1KQ´$ÿzÅbÔÏùì–7DpÕ’;~´ƒçê3¿‚Õ½YN]Õ^'§0ÉúxÙ¦=Ÿ/16>K±TY"Φ Î9©‡†ÚYÞ!mœ*òÊxžG^˜`baϾiô-ë »³-‚ŒK'âe¿Ü—¿=\\°.å·1Ò˹eÃX;zÀʽ!ëÚÚêëÌ`jvõDeÖ¥ã2 ¾r–ë^*“L„•âÁY?j†0ÈG@}¯[ðÒðô£¯=ÅÈ”÷‡CÂÀ²Î"_N¥§Â>ϵOʪ\Zå#Ý Ö/£üx_p Lú³k$ãùOe[:·‰±¢ÚÖÊ󃇶Œ!¶wx y6‰)æVo Ö™3=³?bð xZè?ýiDÌrBøð\{Eñe­¼ððЙ3˜ÊÛîò’7ª+»¡¡R ~ºÕËdG6üA°2ĘôV*MˆÿŒ àuŸRFòá¡‘D´ïµxʸ©’Ö™1™Ê{Ê Î)ˆøMa´\·ûx,ÑíeBJê/DªæE ”Ò”©êW“‚ýg±XbjjË­… ÄÐåMÓ »·›LƱ×01kÓøvOyóë„$B1Ö¢Ÿ7ó|™h°ÅV•fïŸ*aIì Ù„é¨$üçÂéäÔår”ðíyùˆ*¿N[6“Óô ô)ù¨]D.„¹üо;+/$Δ94c©ËJy4«ˆMA·y‡¦KÌ—%+ºÓÁëì3#ŽY÷+Mueoì¶ ¢»Ðþf7Å’EÙ»–iÖ©—u|ùó4]ÖÔ_Ù–p`Úbºàðý^9IÖt«pÿÄÖÓÑé¼E¾TQÿËœtg†##ÊJ,´ï[”lä‚BúâдVÒQ%Ø;ÉÖ2}sª’P(Û˜¶(ÙÒOÃUßX£Èp!Z„øu]`%[²o²HO.Eo{Ê1.3Ãuªï?IþÿJå雺/1ü¸Ò 8Gx2=õ%’ñy‹É¼\Ð7g¾ÒÒ$ È¡ ÕUKI˜˜·˜-Úôv¤iK‹z†—³†¢}w›Ë £ÚŽ%‰°VDûqï w|ÕóÕVb¾d3>o»÷†X‰$a ÇûU‚ü|=½dWbƒ\Ú¤;gT^úêÿÂn‹TmVò[ʶb°ñãNëJãϲd*o‘//¤‡=–v] €•þ¹¡øß±¢ñNý|Ù&?c“K›tf RÞ—ú.â„DÚ¨6å¶UÖ¬ê.fýx [p+MÙ–Ì$yKe#x¨#R¾:+F¤À]§î²ù’M¾TyM[{ƨoQÍò¨êA ³h QßãÁ*³Ž§û~?e%Š–d¾,ÝÛ½ô^/PÉî )èjFBf§¿Ê’BÙ"e²)ƒLJTnã€P+³h.`á»ö¸%ôöŒ†¬„¤h±ð«ã*ÝèÉå+à"7ýê¸ñh+ie å’Íl ÒfÅ"¤ *S‡:ˆ0LlË"÷‡ò‘ÿ×óCøŠF-°|xý¸OàåPDûrfÑ’¸×³„†À½åÊk¸H B)–kðÓ)Y’’ BHR†À4À¬Å9ª»†zšh뀹¤íY }úÕXÃr TÏ{ùÔ·~—m•LJàú}×±õ‡Í:³<ÊR(èH %«r€Ä0¨(ƒAe«¹ÏÏ He0»ûÔm (Gî…ÐBuòÚvÈì ‰ömÇOÄ}lc§"!TqD) £ 0 ¢O•á?c)‚­„-Á®)„aˆ…­nÕq‹¾O*F¨­x}¾"Ú¯Þ(زòÖ/¿À!DX®/_ºë2„†;+‰Aâp|3 ¯lL+a/,Â8Íp%¼‘Î× ¤¤ÅDÕÁTütE¢RÖz!¥’æà¥þÕJ³Y?ò": °¯i»N“°Ôܵ²ìBÔãTMT—\-ïBN´ïƒ†ÀCéĵ" `ˆ}Z·g^FµŠ„¨™‘Bf³ŽÀ•Eš2ëúõeÀ/#˵^Fµ ÍÎŒ¦ "”NU. |"¢áŠ‹óYA´˜rþ-Œb›õdJ•ߪ<„)pb‹¢³¾a>«¨à‚F `Ôÿå2a?žpÀãHJHøÊ6‚h'l­’°)ùvñè÷|vó¯Lø_ ¾7XºZ¯¦;« ÷Q;­ÖwÒwÒðš_G9g}ÏÖõD]@("šÏ»”ôÆBU_¨ë»’ Æ^ùbT·4^!$ˆÇ܃ p¯Ð}¥êd#¥1ÐI ß×–˜ò;è8ódôìÝ߯ÿCÊ7»ÃªLÊBõL­úA4D@V’Â÷¶Ñ‰Eá’ËS ¹ §¶|¬F¼Y)û¯;P1xÐù•û£+° ú)@J­ÿ$ÖS€TægØ%›šËhÀZf%’BÖJ[ùƒh,p÷i3õ57ô^uˆ1?qû¯ ëñ]ÚþOU_¨ë£ªß*á;xv^GòQ­ç쇢/®KE_bÚ 'R<ÌðÖ²ôß`ˆû‘\èÏH`f(³âX M>š‚“Ïšõ$–ÕMþoô_'­û¨ígŠÒìêiÐ ÕµAVÆQ>Šfʇ†µ œá³ÜÛ¿ Yj%RßÑíž¾|úô—<Ö˜Àâ TÀ½t¢ø  ¡hßži¼&t‹ú5¿dx`¯nïb¾+ظ8»Ö–ûÄ͈rð…â2LJ*:*!|$ß@]*ÚŒ2ëQõiÿ©àó)ïM¡–}B› x‚¬Q3ÌICÁG’ÂkÖc-˜%j%æ‘é»âô,žܺi?ðï5fšŠöå›Rœ >’‚SéИ·¡f]Q_7Ú÷*âk ÷NÄé]üwÛÆ­ñü¸Bè‹y›Ø,|wÚÌP/ oý¦¬2ܯýŠØ*ûǃiάC°Àñ×Tš ')|ífh¢VBÉçÎFzטüö¤{g&5d%Âêã)Ó,š™¡š÷ÒІü)»ú¿ÛH¯S€{„Ƈ“õã^ªúžY¤<6‹†f¨j–k¼Ñ˜Eò±Æ*6ó§Q7Ÿð}¤ñíĦe%ªYAJç©Útf¨JàÄ´ ãA†j´r“ÿ*>‚0ÊÍ L×J„ ¼%Òw°ã˜ŽÀ£¬D"(!Œ5C 9¸yýsûÿT.â¬Q+‘ ,›…¦À<$/p7$ÿÈξgš!ÑÜ?‡Øò£Æ[ã* žN Eš3Ó—¥ª¯¸(`f¼ò²–bDZ—ÔÙF z k1>µˆm¼›ÊÏÉiȬ7³€òÚÀ$ư(&E09øÔª½q‚bc‘²j–¿¦îDilgxp$I¢É*ÀMk~ÆõM™õÅY@yµá# ÷íNšhò pÓªÛâš2ëºË¬¯ ÈO°kà¶VPn|båßwÆ2ë±–Y[ÆùQùv 6ô¤O­S„dïÊ¿BÈ/$í+•æ\ ¤ø<;>ÜÊ&a¥`×ÁÏ!¹>Ød ח⑼~dÊ‘/ÁZ¤Òз*iª_Bö¿a¡ó¯ cñ¦Ð®Ÿñ·¾f…ïÄ ¥)åaj ¬V/GÀ4¡;Ñ¥` ò&vìB„ÿßOX\: ÷QÃGÎCØÿlXjVâ·ñvöýt)¹X àÄpßnäôVà“ÀQr_×RA܂䌥> À‰á#›ö§K–š•á~¤}#ÃC¿^jFª8º Š¿}ð ç.5+ á)¤üŸÍìÞmŽN¨âï\öÇmKÍJC<„Íg¡ÿ?[½¢×(Žn¨¢(^ ¼h[jv"Pþa–CZ¯j[J¼: ŠáÉ>Dù/@¾8u©Ùq@?GÈ{±åW:°Ô éâÕ¥N mDˆËò­HÎ2‹ÌìîEŠûîß·Èí'‚¥RÕçyÔ³_÷så‹þW'Ûv\J¶ë¤Ò›1R§ƒèI”c)'°ËOPÎ?Naêq~óÈã|ã:ç2HÜ‹ZÎkIýÏG¼éÞ:‹ŠfÀ+8µ«ë †£¼á©$tÕµªm7Oôñµ¬;ûT:WœD:;€‘ •ÄHõaý¨þS϶¦°K)—P.ì§8s€ù‰Fžzžw½H>%dUZе7Ïöœ;Ó¼‡ºí؈R€j¾[¸:çAiAJ÷ àZõ­ê«÷Ú;ˆª™&dðÏò8‡Ž°UiaçN~”ðBU8*¡)AXZ#J¥PºJ„ç;Lª›Ý:3YGˆÞ2ª¼(ë” +S»%uÎð0†}7Z·QúqizÓ«ýõBå³U‚ŠXaÄýŽ*Ó0}Ó1Qf4î·7­Ñzºe½çN‚ß<‡ ®…Z€º35Ê"x¾ÃÚÓ©ù­2…qfVØLŒë t®uç(ÎUðºêw”ù×u øôFòÃÒ´Ã[VW°Q‹#XPß1]«¾ãöW\‡ÍRÕuÜ °Ù@Ð[.q@^x•ÄY&®°UôUßaçq ²Îó …P¥é*EµŒW¸^ú‰  âĺçªk/‚f¿ÎyзŠîQÿ"à¨÷»äIEND®B`‚KDocker-5.0/resources/images/another.png000066400000000000000000000115071252153257300203360ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsBIT|dˆþIDATxœí{Œ\Õ}Ç?÷1sgf×»ë}øµÆcHc³˜F@ME ˆÓ„ÐH¸¥UKi( 44©Q[¢¢µyT‰•DQ5jhJÚn¨‰(*<Š©È,&€×6^¯w½»3÷1÷Þþqî™{gvgöή¯÷žïêhöÎÜǹç÷=¿ßïüÎïž«¡prñ=Vp:²X…ÆjJh˜h”‡€£èAã0ÿ‡Æ äy–ðöɬžv2OžYüWò»„\ œ‰hi Ð0ûÑg˜ØjßïGç)r|—øá‰®ª"À‰Â× Ï_áq+0 ®èÄ€˜aâ’>1ªÑ¶hÄâ_Éó·ÜÄ‘QmE€…â›ôãñ Ê\‹†… µ¢#„o"Z:© ’$B‰….I ‹øÎ¡À÷(ðgÜÂèBª¯0_ÜÉ÷2Á-@ ÈEEÀÛº¡sv×ÙlY¾…³:ÎbMq }V9-€zuŽ2RaÿÔ~öŽïexb˜ÀÀCÀCßKƒ %¾Î*þ’ëñçsŠóÁ7¹ˆIþ ›3j‚Ï ?𩱭W ^Åö¾ítåºÄ±­ZŸ§£ØA¡X˜©  .Nðvåm¾ºï«ŒÚ ‚ @±]àut.ä/˜nu{Š­p7&/có> ÁwP#À=gpû†ÛéÊÏîàù¾ÏÔä“““54ƒ$À²eËè\Ö‰aM÷•¾Á„7Áîáݼ3þŽú4‚’ ìe=ÛZƒrÄá €Nþ‰Hø„ðK@Öt­áÖ ·b™NèˆýCêZÏó=¦Ýi&+“xž‡¦i膎®ëhh„„A@à„aHÎÏ¡[:†oÓs³×)Á¡‚Yà“>Éî7wspò`}lÁ&ÙÊ~ž>N<˜”JˆvïV}˦£ŸåO°ø, XF­÷wwtsÛ†Ûè2»êœ½Fx®ÇøØ8ãÇÆqÃ0¸Çý-/»ëç»èéí!—oB‰„o0Q`÷›»9^>.4À4p<út€€æïøpx˜"rIM`Ø "x®p)gQàLDz=%0 &;×î$oä±±g8iIx¾G¥Z¡ì”qwn¡•j…‚_ÀRÄu"c;wòÀ;àãÇÑÃQü}.åÏòlt”LDÏ_ƒ ‚ Zf&—ñÇhèXÄv¿°àÒþKé·ú±{ΖòŠÀuÉ“Ÿóò¯B1(¦#ÔüÂÛû·óô‘§ã²Túet>ȧøÞÂãB Ô Ý%|€›ù˰=¿3ú´`Eit_ ¿¹O€ë»Tª*^×qñµ¹…Z©V¨ø•ôa[÷6^~•#ᑸ÷»Ø,ãnàë¼JBËK¡×ÿùÏ~ëwÞùÑ|>ß ]š8\>̺{×áú®èRõ[@.Y~ Nà¤>€¸ØžíÙ8ŽC`4HØžØÁÜûΆK–_£S¹~z·¾=Øôðz,ï$4€Ï|泿EáÜüÄ͸¶Û}9äËÃ`i¾\vh§> `û6§‚ëºéàÛØþü Пëguq5Ãâ iím¦ƒßcwó´ÜßlÈã/=.ÅÒî—ƒcÎ)Ó–ð!ÒUÇup‡Ð˜û`»º0 pnǹt évÇlÀåbn`€af!€DQðbÞõ8­pçSwRu«3U¿ %³ÄòÜraûÛ€x8UÇsp\Gi8U'pD€³‡’Y¢–©ù2Èa¡Áþ¸š Þ{ï¾?¯)æÓßéû⟵!Ÿ ­¶V·-|·ê º®çÊY»–pª•ê<œÀ¬¶V3 ×ßOi®£Êå ÕjªÉ¤%=#199)|cñ“!1Mô¨ù@j·êâ¹)F'Dt›ÝâqÝâÞ¦ ]ü=ã¾ßT¤QýÕj•±±1l[4N¡P ··ÓljY%Ú÷øG'vü"áëšN^Ë/ˆžë ¤Ôv`/XXš…®ébÒ$ÖÇ¢O@-'.ªÕ*o¼ñ##f0U×uײqãÆÓ†/þòEñOŽXUFUª¿ÿëŒuhhm9ÕJ»lã9žð/¼¹±Ë6椉Ym£í41™¤åÄ\C ¼e¿%„¯'­tD÷X*\ ML@†M 0==ÍË/¿ŒmÛœwÞ¹lܸåË—pìØ1†‡ßäÕW_ctt”¡¡!J¥Rú9.3y|RlÈé^Ù*P‰ñ ^›zî°›¼–BËÃÝ÷˜‹[v ¼€4)S‡§p]=ßFD^=§“ëÊáwûÎÆÁ©ßG†µs➘¦›{ÙØ–p]—_|Ã0¸öÚÐÛÛ[÷ûÀÀlÚ´‰'Ÿ|’^xž‹.º˜\nñŽ,Ÿy"Þ1Qñ*ómðÆÖ–Æó<®¹æº»»›Žzzº¹êª+yì±= ¿ÁæÍ禿™_1~~(Ê£Ô¨¥vÕdë#k”ší¬Fº¦£·1o¦>·cWnßù´HÃt!fwfT€xD áó›© M:tˆ7R(XT*­³ …7n`xx?›6ƒ®/ÎIÆ·Æ÷ÇÔE1lª 8šèº¦·Ô𦉯_ž¢B)-fH(òª¡¨[d®p iú‡ rIØlJmÆÆÆ¨V«¬\¹’r¹œª’+W®äõ×÷166F_ßl´<õ/ÇðõlA}.~ÂNndÌû‡žb h_la:äh Öp}M0ÓLOO!¹œ9gï—¶?dzzj†¿°XPv*ñ#[vSfÖÈ'rN‡¹RŸÖ#‹ø>B–5ñfjùmÛ©Õ¹ïû‘?ÑzXy*áúNüÈV£ƒŸœ'mH÷Z´¨›Ûyb-’OmŠÅ"a(LAGGGªºLMM†P*•-=ˆ3!Õ¿¬òé–)Ùª©åƒªZq€žž CçàÁà ®NUC‡a:ÝÝÝ‹–¾á7}X=*&mNæ"k’èF‹ÙÀFišÆÊ•«9@©TÀ² f=ÇåèÑ£ ®EÓ´EKòÄö}¶QZ2gzaáù_ æÊ䈥ތÍâëׯçÈ‘÷8p`„¾¾^òùÙ£bžç1:z˲X¿~ýâ>+åð+þìY>ÔòEvíâ‡Ek$ Ãi+hš&CC°wïË>|„BÁ²òµ‡ªU×u±m‡R©ÄÖ­[1MsQ T(a{QŽŸGý8Ù@Vúªõt˜ í¢94„¶“R·˜j{. P(pᅿΛo¾ÉÈÈHm&°v Mgpp 6`Æ¢>@w©›±Ê˜ØC(iCeðFz*h_kÃô€ñ¨¸@'„_nÝÚç4è!UòH|B¨Ë¢ú6;V¦‹Ç›×l ®ëœ}öÙ¬_¿žcÇŽá8r:¸HOOOmp± `]ç™ìŸˆ¢òyûd² ‡úÕ<ÒÀFhŽ ¢ñÓdZö?¡‘rè'Ÿó‚ÙÍU#L^o[$aýýý³ºà® ùïCO‰x-ž²aç3³­!”§¾á[AúŹvlf¾Š jI’xf^`)áòeä+æ—ÅF’'bÜ/Ï•\,j.H;}¢Î8¢)sÁu]X X—_Gg±“)oJ|ᓌ”È8B;óa'’rˆ[%i*Žq=od^œß5ÄOÆŸJöÜ…†Câ@’,sA®#x¢ ïAžSj¤×“Î^òÚp”Ÿð“»/ÎD½S„»º>GÎÈÕ¯óÛh‚6J2vŒ̧$û­¼f´^qÞÈ×ù »(Dè5zùëãñÏÉ5¡}4zÞiÑ.Ñ’%Ùûå}DÏ8ÞzÆ­ð ÉK)4àŽÎ?g@ˆ…/s’+}C½Ь@¬‚Û ͇ÉQ‹¼^‚ÀkÌ5|éÜ/͸”"@ î-~QLqË5€eO’$H ¹•ºnÔi|€v4'Õ½\¼:š‡0 ƒo®þ†63­0 ÞonáÃ?Š{’\Xj‚¤JoÕ[åÐK’'M ( lÇÄ$Ÿ”P‘¸IûC¥ f½Ü¬UZµj«V­JQÛ¥‹¸Ÿƒ{Gø¡ýC!¼¤s%'V’ 36óÚ¥`"ÂhßšE $U·$@«A˜6K‘¦J ?"ëŽÂ¾µõ¾¦§R ölÝÃsK¬V¯ 6I„¤z–NY£h,Fùšõöä°2y^Ùë“uÌÁPnˆG¶<ÒòZÀÀ๭ϱYß7r´dœ\ùžYŸhõr,xŸù>~6ô3L­µÝQ˜f/ ½ÄùÆùõ$II•+{s£VHãØ5îŸìíRS4 >YŸ C¼°õ,­uæ6(¤BQ/òü–çù°õáØÈ—/{ßlÎbÃ2ò@s¡'O œBo$¢ µ>Êó[Ÿ§ §Ë)SH S3ÙsÞî齇œ™‹W“+‰&V¯BöTOh´ùÉíäPS:tIÛž$œ¼^gôYÏa~¡û ¥i$EÒD¿ŸåŸÅÃg>̶eÛÚ¾¥æt}€}¿¶]¥]bÜC“½3Y’êZjŽBCIþÖxžÎÄyä"V”Œ»J»Ø·eß¼„ÂÒü0„H|& ÿ™×™2ŠQo”O¿ýi¶ëò$'_ô'œJ Ð8*H:{Éç“&#Ò –fqy»7ì¦?73+»4M»ø_ÄÓ J,ý¹~¾½ñÛ¼³én/ÞÎ }Eì(&{~£VèL”Ù´EòØÈ¹ìû¹£t6à;›¿Ó¶ðgƒÒ'?ýŽ>È3Þ3ÒÕÛþV¹†Ñ=V+¹¬p7 ÜÄÕ½W/¸n@9';úw°£ûËûy|ìqž+?Çk•×e”ãÚñ8ÿ0B1(²\_΀1À9æ9lïÚ·z?Ä™…3Oj]•È” PE€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãPÈ82E€ŒC ãH¾©v®w[*, ÔÉ9Í«Š–êä­6PA¼ãJaé£BâÍ…&pA¼>&ÝûFNgŒ!^m ¡w+€>Ä Ê”c¸ô¢³¿LEß¡QÿbRùÞk…¥ùÒ:/*þ©­Ž‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚¯ÿþ·.GÜq£øIEND®B`‚KDocker-5.0/resources/images/close.png000066400000000000000000000256371252153257300200140ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsBIT|dˆ IDATxœíyœe™ï¿Uçôé%ÝYÈBÈÂ"„-‘ Ì•&Ä Í0zY®rg¸iÇåŽãë0êè訣£NœA/jÂŽÜ$"BX$ÝÉét’^ÎRÛý£ê=ç©÷¼uº;}º“8÷ù|êSuêÔ©zêýýžå}Þ·êÀÿ—ÿÔbhFI»/ýû`ãûþ•?è÷`ö÷>öN‚? RŠ0+×IÛúoM¢ƒTÙ–k}û‘ôV`ˆ¢ƒ.ÁµÅºô݇¡e,NÁÂfÛ0Ý‚i>fÁ$/áÞ}È¥aŸ {-ØeÁN^€çÖÁÓ¿¾ò¡@œˆ}‡„Ì tµØbmÞ׫l8#€£]8,ˆÎaG‹BÅ&Yš!ÂjM¸öR°Ë†7êá…¸÷xNüL.ò”­ŒÐݵ´l…¥}´,…«Rp‰ ]/BûÚ¾@|–7mµ–‹ ô¤áyø-üô>0üDžî ’ƒ‰zì–Vž쉾® à¿:°ÈȃLÛò³~¡$‘À¾i¡[¬‡\øÎð/€ÇAN„ƒIÀÛ„À§> ÓÁç|¸Ì‰)âàÚÚt@%ÔÚ„F’ù*Àè^ô'>«u ²øù>ørt&œò€Ë$@ð ßôgáä©ðÛ‘µ§¢Ó”]ƒü!ÄÁNQ ü`7-­Z÷’r­ÀwÅ~7ÔÅm€Ç¸ýØÄAF„ESBg⚺Ž;îé‡E€•"rÄ"·-m[÷ᢜ¾ëk“Ë÷(Bß–„ˆ<…WOà“wÃkĉpÀH0Ö†(qKé‹aêÙð×,· ¦l}‘ÀCÙ3È R ÓÜLÃÌ™ÔM™B]S©¦&¬L&¶XÄÀ ˜Í2°m^,áƒ8øÒ#HàÕ¶kþÎm†·ÃÍ;)s Æ’I1>Ý™»áv>4•¾ ìtàe.¿~Ö,&žtãO:‰æN éˆ#HO˜0,…={ÈoÛFïË/³÷¥—Ø·iùíÛ+€×½²zµ¸T†þ:øËÛà¯0'‹c"cAÝê¥1×}Nž?€¹¥â€´X§ '(oÛL<妜{.“Ï=—úéÓJ GLHäwì ûÉ'é~â ön܈ïû±˜/-^ÁMØ—?WÜ®ÇÜŒ6ô¾¼Ä¸î/àn n² N‚¬¶ëˆ“À”4ΘÁô‹/fê™4)Q‘Š bOÙ_ÿš¿ø¹;*òøjÛ!–'Â=Ÿ‚Ïc.EŒšŒ&LÙ}¨»fžk‹p’¾N[K2èÀO\¸™—_ÎÄÓOËŠ]t¬¤„N°ç¹çØqß}ôlØP‘J8” à'F¼¸– v1F!a´ÚK‚³ú?ƒŽƒ¸Ð¬@NÊ`Ëmü–NàÈk®aüÂ…Cº‘Þ ê= u¼x߆ ¼ó£ÑûÊ+¸”óé $øP$æ v§àò?ƒÇŒL]»:ÂDï¦4ÜmCZ1B}YGÜòõ˜ß4e G~âLzÿû½¹¯V-W­pdÚßóÌ3¼ý½ï‘ïîN ŽX\ÊD 8îü4|ƒŠbcm¥Ö0º| þ‹ðu®´Á’€g([½¾”ñÛ6Ó>ô!f^}5©ÆÆDÅMVZë›3¿Ú0 70Àöþgºz?*H /ŠmE‚IðÃ[àF‘µl#ü: ® Ûà§ý°¤´“ð$(wß8e sn¹…æ÷¼gTM‘Hõ½ò oßs¹Ý»+¼$ jÛšá?‚Ë~_rµ%A­ÚS‚_ ë!øôÃéʽg¢¥ˆ÷ùSÀÄSOåÈo$ÝÜ\SEÇZZî¾}lý»¿cïK/ź‰Êê% ÄCC<úy¸€x½ &R‹v5‚4~þ-gH‹¯§LI YÛŸ~ñÅL[µ +ÊîUð•”:öAÀÎûï§óÁK}=´´|È‹ýÐO¬…ÖjL‚‘¶­Éíg€†/À½.œ-­¼ž8 slÛfÖ5×0éœsj¦àÁ"­Ý?ÎöŸþß÷cž@ -EâùÁ$Xÿ™ÐÔ,'Iû&‚ÿø^?,Wñ¾A}AÜý˘_WWÇ×_OóÉ'ÿÑ€ž$лq#Û¾û]\×5&…’ʸÀxøñðqjD‚Ôà‡Å”íg€Æ/Á]ð‘qKo¤ ~E·/•âˆë®£ùı|þ,™©Si˜5‹þ °‚ Ö¨²w¡ÏGÈÁ)Óû‰]ûû ~=ÐðiXÙ ß´ÀVñ¾|Ýõ—ým›×\ÃøSOÙ¢²ïw¿cÇO~‚)(O BA>ZçÄ~¼ÃàßaÙx  ê3%/¿æŸYÐXbD´nŒ¶õŒ?L[µŠ g5"…E‘hí}úiv>ð@l8Yæ9B"(28@äÆÁi·…s |ö“ÃnÊøë`Ü©ð“4Ê~½Šûz¶¯.:á}ïcÂg¸î •6³è’"ÖÁE¥›©XTMט°hùwßeïóÏc’ #¾—“QÔR€Æø“aùm°ŽýCõƬ2´L¿öÀR nýÊýËÉ“Î;»±‘ÀqŒÚ*àý À÷ýÒ¶EܺJB×ZüH'Ï÷ |?œÄïÆ •,é–N¥J„5‰ÝÔĤóΣû¡‡ð æ Ô°r=屄TøƒŸ~æFÏ$¨Ÿ I†Ò Ôã~Éú? ëÂ)6eЕõ«P&}6ÐtôÑL<÷ÜÄî‘ïyø®ö×uñÏó€ñ Ò¿u+¾çá¹.A@ày¡õù~Ø­Å.œÒÑS::Žëâ».¾ç1ñ´Óèß¶-Ô;Úçû>x^9T$蘙6bg'^Oå™4 ÙùWƒh:Žn‡û‡ üp  ÷÷®†Ó&ÀŸV) ìö•ë—3yìtš©«VaÕÕUÜxàûx¨ x'j@×u ,‹£®¿žé\€ïûìyùå°a£ß¨sX‘Ç è::bQ¤¹bs®¼’¦#Ž`׳Ïâ9FÖÒ9t¬Ÿ5‹¾Ã{Ñ€àËœ ó—Áëɦ5ó&ëo¯€ÊÃäå.Ÿ_}dÜ·€ñï}/ óæV5 lT/²28dÒ‚Œ?î8|ßg÷¦MekTž@5l+Û_ð¥ŽEÇ¡X,ÆH:{åJŽ\¹€†Ã§éÈ#éüíoÃÇY:Z $°êêÀu)lß^1µâ¤ˆ9†vÎZß*øC%@¬Ë4ü7X¬¶ÅN•ô©¢²~~º©‰IçŸNßJhX×qpŠEŠ‘[UàÏÿô§9L+M8þxÏ£{ãÆ’'ð=¢FÌÊö|×q( 8ønDÒ9—^ÊÜK/éØ8}:ͳg³ã©§ð'¦g‰ DÍLÊÀ+¯ÄºÈRd^ ÂB¦] /®ƒÍ Ñ T#€>¥«äå—Ã÷=hQ‰_#0ޏõËq} h9ýt2Ó¦UºTeQÅ"ÅB!l\Ç ]'pÒí·3å´ÓŒ N<áü  {ÆРDÞ »6l(%\^D€@¿Ÿ9"h1òL…B¼ßs]޾újŽ½êªª:Ž›9“–yóx÷ñÇñŠÅ¸ÇRàGž@Ꙟ0Ü«¯â{žñ‘vÓ ã"L¸ Þþ5t0$@Z¿Ìñ/‚o…õ7P¶~Õõ“OêX@ÓñÇ“™>Ýhù…B!lØBb±&|ÀiwßÍ´3ÎL&Ÿ|2ï³ó…B SnV6°?¼ÞJ.Ç¡P,’‹t,ðßsÍ5·zõt7k-GÅ»ëׇ¿—$l¡_ÉãàìÚ+€)‘N‹Äfžò(|“@æmüï° ¸‚èK•ø) †yå™–m3~Ñ"¬T*æR‹QÃæ#«*FñÔ·,ÎøÂ˜~æ™CjX%“,ÀW$ˆÂ§åÖ»‰Ê‹#‚*ðóQwÏó<ŽÿØÇ˜ÿÑKÇæ#Ž`ü1ǰõ‘GÊ]\™«)-'H·´0°ys¬+¨Dõä,㨀4q<û(¼Á $0À4»h\_+Â4ˆ»ÿf≟"@æðÃi˜3'Ö¸®ë†V•Ï—à8¾eqÖ—¾Ä 184™ºp!~ÐùÜs%O ºˆÒÍVÄ[øŽãÀÏ ]×åÄk¯åÄk¯Ý/[Ž<’‰ÇÖ‡ÆÃÀóBØA€­rßDzmÜÝ»ñúûKÀHQ$ùÀ88zü#ûI9Ú—΄ÙGÂmA¤C&¼ã(Ç~5»G é=ï!ÕÜ\n`ß×qPÖYþâ¯~•™‹­%dÚ©§Ûÿã?J`ú~¹‹hE®Õ|ÏÃõ<ŠÅ"¹b‘|>Ô1êöyžÇÉ×_ÏÉ×]7"[fÏfâ±Ç²¥½=Lv£ bH[VD‚’n@qÇŽÒï%T2(Ÿ/ ü<ãBøÁ:è¥ LÐçó7ƒ5.¯~¤b !ä@OÉ]¥RŒ;ùäHSA×¥à8䣆v]—÷¯YÜóÏJû *‡¿÷½øAÀ¶gŸ CA´(WkGÖ&ÃAÉíG:õ+ðUxò<Þx# n¸¡&:ŽŸ3‡¦ÃçÍuë Bðm›´e…•SA»¡ü[o•Æ”¨˜/çˆ ƒöD˜ôø…8¼BôäRNöˆ=ÔaÃyêÿë¥^é¢ê&O† p]ã¢J§®ëÒñÃ’ïér& o¸Sn¸¡ÔÃèÏçéÍåè ?Ÿ'ŸÏ‡µ†hq‡|>70@o.G.&~ŽÃ‚odá7ÖL¿|O~øÃ°Ø¥’AÕ=ô¼X;¤;¬ô[=ASe÷:âíßöÖt§Ý»~×AkV©Ò„qó ^tM™y«¤Ôõ< Å"Qú "Ëw<Óo¾™Ó?ùÉšèëéá?ýS²/¿ŒÔÙ6 ¶M}*EƲJ9€l· PÀݽ»tÙ+É`žrà@ãrxz=l!ÁèO^—º~+àsÌU5ºþÂì_Oü”4΋•NÇûÖÑÍ©7Æõ}zwîä­'žà˜åË©« fžqAðö3Ïàù~©wˆ¸ï¸.¹b‘¾B¾Bþb‘Bäöϸåθùæšè!øÿzõÕìzùå°mÛ4¤R4¥Ó4ÚvH¨HR-Û6æ²<¬†ˆ]q½ñÐÜ?'a©$€ÌþKÉÐt.Üå…Û@hõ  †|uð-Û&3kVøAÞˆÖí |/"‚çûôvuñÖãóž’`Ö¢EøAÀÛO?§’½ˆ Žç‘wú‹Eú¢ø_p]\ßçÌ[oåÌ[n©‰¹Ý»¹÷ª«Øùû߇lÛ4¥RŒK¥hJ¥h°í°†bê¦Ngg,s#|B¨¹JR0y=|=:¤BtTLñ^ÇÏgœ@t@3!ÆEé±?Ô.Àíé!ÝÒRQÿ—D°üpÝàF$ØòØc·bEÍHpä™gâo=õT83²ü‚ë’sŠErŽ‚ïyœõ™ÏpÖ­·ÖäÚ‚ÿ³Ë/§kӦнÚ6M¶MK:͸ü:Ìàû¹\8.à8±sÊYÄ>å§lêŒ[ kÛ¡›A<€1û¿2|8ñyÐ`"¡ûW  I×ÅéîÆ®¯¯!ª^/=Á¾;yãÑG9þ¢‹jF‚Ùï?~°å©§Â$Z ®KÞu)F=³o»ÅŸýlM® 0°{7?½ôRº6m"mYdl›q©Íé4Í©|Ýõ{{ö{ã ‚b±ê5To`€pæ4÷f(´‡3†Ô¡%1y€Xé÷|¸ÍR ZG™ªòWU|·§‡Àq°*f,ßo<šý㎠¼¾~='\|1uMMƒ]iH2笳ð7žxß÷)F$PÞçÜÏ}Žso¿½&×èîæÇ«Vѹi©üæTŠñ©ͶÍ8Û«§Q÷´”+¹.Å;(lß^ I"Ã@ްã/Q À?`ÈRâ“>€ÆÅp«â®NÆÊñßT2‰ŸËáîÝ‹•J•CKx‚R TyßÇ övvòÚ#pâ%—ÔŒsÏ>›xí‰'ð‚ ´ü—;ïdÉwÔä‚ÿƒK.aÇK/‘¶,ê#ð'¤R4§R‰à{{÷Rxç¼þþ!]G¡ªò€^≠Ðò8|*!@Oë†÷¼¹+x× sòWU|¯·?ŸÇ®« ‡< ,ü À \ßgog'›×¯ç¤•+ÉÔˆó/&Þxüq‚ à¼ÏžÞygMÎ ÐßÝÍ÷.º(¨·mZ"ËoI¥h²¬0à…ÅÎNœÝ»µz)rJ}ØCyž8€™eðë UA“( þü ¬ÈÀ9òã ÐDBò7 wß>‚b1ô–U"Mþ$ näz:;yuÝ:NYµªf$8jñbËbÞ9çÐz×]59'„àç ٱqchù–U²ü–TŠq–ÖN"ðƒBg÷nœl¶"Ñ®¸„(hû'Á«¿ß¡@…p}Î HM„S5WRrCuý‰x}}x}}Ø ¤ZZ°ëêȈÁòE n°­£ƒo/_ÎM=ĸɓGrõ’œ_Cà!ÿ[Ë—Ó¹q#u–E&GX4k š|ŸŒ*ô8ÅÈ#ŽTxj¶.œ |Ÿxù bÒil$0óôÉ·vÕJü|g×.Ü]»ðûú¨sš‚ Tld‚ØÖÑÁ7—-£?›­¡µ‘¾l–¿]¶Œw£>ëfËb¼e…E³  ÎqðûúpwíÂÙµ«&à+±(?«§KæÇˆWp+¼€ S,íK5ác4æßŽCÐÛ‹ßÝMjß> Ʋ> ïvtpϲeôD$èËfù› .àŽ¬  r½dBÐX(Þ· »› ·wÄ®Þ$2‰Óqsàp ŽÛÖ~/ `{a¨‰õ-±»X$ÝßO}o/ãr9Z‡qAP"ÁÖ øúÒ¥ ú²Yþ÷Ò¥¼ÓÑAJïûLp]šs9z{©ëïÇ.G½Ý”‡ÖÅ £PÅåõ1œ˜p¡^gR­Ý’”Fƒ€fÏc¼ã0¡X¤ÙqhðõžG³ã0ÞqBÒzõÑpïh‚¯Dyi7¿l̃z °O€Ã|°õÕ16P ©ag5ú8h£ÚÁÖ_ä«­­ôôf³üÏÖV¶¾øbèöƒ€– `’Ò“°˜2VàC9ƒ×qó ½*Þ¥›N†yúI”‹KQ׬'L'ÞE aãÚÀÖŽ¾2Æ$èÍfùJk+[;:Jó#'DºIýF;\ꢌƄ݉åD0–Æ&ñ¨å0˜a:ÉþöýG"ª>­†¡e#7Fß¿ÝÑÁ—ƈ½Ù,_lmå­üF*Álœd4E‚*`ªéX%±ãë ]ÊÅ2Ö@‰"A#a(PnvånÏ–Žþb”IЛÍò…ÖV¶tt@tíf¡ÏxÊs$øÊcš°³CUcbšV"Œé$Ãzø¼Æ¢¨f#ËùˆjHôŽÖ´¶²oH°/›å´¶òfGGéÉ]õ@¬ªY(· ÀWëʉ¥ÎP½OÒÓ²Ÿù×—X鈼9ý5(²¥£ƒgæ×~æ¾ûx;_ê#ÿÓà@„H)J·!xï’‘'J’8P7¨F¼ÔhõÒ$õ€¤"ÂUmm,»é¦š_ÙM7qe[[¬!ÕT,ù§è9½"ÊLØ™DŽÈs <€.~´Œµ‹Ó§=íöý”§@YÀ•mm\¾fͨéqùš5ØÀ½mm]»?ÒEÎŽJœ)5ÊR »rŒ(öävú’0Ö"ÁWÝC8êÕGyèóж6.Eð•\¶f p[.!!÷Rù\Ä"òºäÃ&‹‰|uOl.àLhž —èn¤…r*97&Ý~Ž2ø» ½@ô¢$.mkãÒ1_É K–`Yxì±’ž*<ÊüDïg¦(z EÇ._{´üWu@2ê³à|þTïK6`,ºƒ|ee=ÑÒKùMÚÒÖÆª1_Éü%K°-‹W4@|~ýX‘ ªøÑGØ^Z/ø.|®'þN‰ŠqƒÒÆÝPLãk£‹ ”ÑÎtËßGè¿öÞ`1ú~U[—ð•\å¶µ•ˆ*ûá2Àè’@>*¦c“çÍò{¥J" h‹Ÿ “Û xÑÎÑê(tð÷º6óW¶µqÑ_ÉEQNð $ä8Êh@¡šdœ™°é*:'i*WÆЗ Ã~IÔ’Zˆ?Ohí{£e€2ø·µqáA¾’ ~‘ ‡Ùý«Ü Ö¢ aêáPýiC¨ô‘Rð-è²a†éõüY­­¦€å ãüB0@Ù­hkcùA¾’ £pðë¶¶RwUöÁÂJ¡  ‘ŠÂÅ¥œÔI±ÊÏƦ†Ë$°"<æ7 ú|ùDp-E‚¯,_¯ ,ª1øýÙ,ÎÀ@Í&š%†o<öXÌ-CeEµ–Æ#ÏQÏbïþá´:•$§tÿ>àoß™ªIò¯QMñc ~?!ð}ÑgeùjkãC5ÿÛ­­|»µµ¦s /X³†eQ¡H…2yO9*žåñ¢Põ0ì…G#õ*¦…ëÃý¥w¼û–ÂG‚pl tb5ñ°VcÝÊu©†RýXõ £,kkciÁÿûÖV:;:èïêâÕövN¹ì²šy‚££:ÁÑE„øº6T»_"½Œüß!élð¾ ÿ}W¹9c!@ê¥ju@¦Ò+a¥¶v@­>”âBÀûÁWVKÛÚ8¿ÆàÿCk+]¥ûèêâµövN¼©‘@‰þTÎþˆJþÔ¢<‹×w}/|BX9ïDTPzíÿRX”™òõÚБ²W¾ß¦Ÿ²Õç(»ýÖ¶6Zk þZ[Ù/‹5ý]]¼‘ V¡‘à­ˆP9b'gã WdP9€BX¸õ§ï‡µþr®Úãáu@fLœ‹¤²Š#™# ÎQŽ*æûÀÛÚ8¯†àd³ü£_½âF†3E‚kH‚y Þ6xiXêópDÊĵð=¿ Ÿ ÔÈ< d^…Ëà*[ä¦çpæ ¨dEý)’rù9ÊÝË%mm|°Æàÿ¸µ•]å‡)¿ßPNâèëêâövN¼¥‘@ÕSö'PÇÊÐßE‹ó ¸¶3lnåJb"@Ì €½.HÃx™ÀèݙုFöä¿`Hí–´µ±¤ÆàÿS~éÿígò请U¢PcðÖÚJ6²ü eàå_ÚHK(ý¶«‹7ÛÛ9¾†$˜Õ ¶j9n\j¿i‘¢÷ÝÕ=¨¥?{ |9„x§tYª½%L n7ìX —ZZwÐÄÚÁæ (7%ÿOYþÚÚ8gÀW–¯Þl.ßj.ã¿)!ëH0¿†$˜‘@å2¯2•.²“ÈýÞ>öÛ°¦VÿÁì*H°Ü•p^L¨“,4)¥,ä!©Äeñš5,ŽŠ'µ\6ËÚÈòå+ÏäK­U"«÷ÉuººØRcO0{É,àÝÇ5¶Z›`8¶-§ÅEûþðø´!`)z5Wze¬P|~¡ƒ¯+eRØÄP¥°ô"=¯¾¾$±’Ëf¹·µ•ÝÂí7ˆE=B­7¢|9’$J°»£ƒ{[[ÉÕ¨bx{^}µ¢+ÉÆ£#×PYÕë…ïQÞ•N4ÚU¢ÜDôk&þ ü{ õFW\WRŠT·Ïæ_y%Ëò“ðÍâû)¹l–ŸGn_Y–þoåÒò¥ÈdJþ‹·,ÛNY°€ËÖ­£qÊ”ýÖ1ð<~µz5›×®Å‚ ’&M+× +‘æ­÷}æî-ÿ÷´LJbºŽl‡’p¡Ð Ošž;3ÅNI;Åò5ä¥?6¯]ËC«Wï·'Èe³ü[äöåܨE/_'y'[üVÿ¬îŽþmž ð<~½z5¯¯]«© JIDATK´ôaâj  4<Ý›ªöÍÁƒ{ã®ßèLI ¼F,Ø[>«R`« ÊìÙt…jûô.¤ìÞ´‰žÍ›9fÕ*,{èã¹l–û[[éŽb¾üCõNƒá–¯õ†VK®«‹­íí{Ùe¤‡‘žG{¾rýÊ+UóLúõõ\êæ¼upåóáhº1ùSbÊôêb)g뀮nØ 'Jj­?¤!¿ÓY,‹ ª"§z}íZÚ‡á òÙ,D1?Ö¥ò¯ët]’¬L‘ ¥s‚om%?DOx¯^Íø’¤zN¢'Õ&1yaEˆ"<úmèÄâb ¶¦s—ªƒ½ðöÙ°"Eù¹½$¬çÕ4H²²Ý›6±gófŽÄä³YŒÀ×û¯* Ȥu8"-Q–j¥'x§½£ñç±nõjÞŒb¾ÔQ¾rGZ¿ªJ]¤×•kâ¿wŸ„+ž,U²ý¾*t¦œ4Èÿ#(<oî„çe¼±µmÝI`Še¦X˜ÞX»–uU< |ùõ¦ÇƆ»HëR„’£ƒ_Vñç±~õj¶Ë×ïU^uçÔõu¯Î#ÛOmÀÃ_ƒ7I(üèR-ÝÖÉU<{ þp¬L¾@BÿÑ`ù€þ©W¡¶{6mbïæÍÌӛ嗭­ôttÄ7Ù¨µš¯ »D=ô建ØÖÞÎ<ÍžÇcÂíËF”V¯[¡É#ê…"}p.òÀÅŸÁÅ/…sOM1\[ŠÞ+Rµ›Âï¡s ¬“ñAO²’®$OPÁ2ñù͵kY/›å¡üX|¢²Q÷×ò“²o©—ÔswG¿ž@‚/#×z!-É@$™M×Vçéµ?ƒ]†}“d°·îJ8= —ÃÊ däAêGºÛ××&/äM,`Oä ¦Ÿs¿^º´äö•eè ÖÂò«‰î lœ`{{;sV­âéë¯/¹}Ùõ­¦£©k—dª­1\Ø}3üÉÞøˆú $¨ÖNÒû”ÞJùÑüñŸ‹.ÛäIÔUå¿X©®D@y¸Wg=b¿œá"Ï in¦Ø×WRPïø2K—ÛŠôuÍ͸}}¹N’ަ(Ém šÁ›áºëà_)Ï †RrÓs’Çþ-¼s,˜Ó¥R•l6%‚2ÑJê!è¢W­™,ÞäEFK’ò[è¨>ëI[R‚,¿—ùŒ$€)ÜöÀ£WÁ—(ÿqØÀ‡¡‡]¿RÛ?Ï_v 3ºk3!3Û¤¡_Pn'?Æ øjb"„)y$áÙ~tÙe”à@öý |èõp^r¼ƒ¯d¸E÷ ìtçÚ„µ¤ŒYzÝúõÚ~Q}ÛD†%I`xÙ t¹È\G€æo„ÿ6Rþ á¤èj”á†}¿ XÏBç"˜1ŽÖ1Y…É èD,$˜:ľžä™,_/hY@'üø£ð-â®X¯pª0ó¿‚ß]ç4ÃÄÁYå’É“îäþCl¨$¸ÞpÊÝKk—egYt’yÄ>Øx9|Ô‰XÊ)C’ý úÚ,¬gàépA4˜¬_±ÏôYo¼CQª¹{iùÒÒMUQéúsý"œ¿9|†F‚?dׯd80…âØ½íw'lX ­uÖo6v°vyRi-Õ*Š«$eÎÊÚe’§‰g0'~ê÷EÈ?+oQ~Gư?)û?ó"!,¼½xûø@šò°qµ¼ ‰IŸ•lD0å&2šÊÁºÛ—®_æàAñqøHü帯?b8,  Ò{[ÏC×dØ=ÎLN$5õÙ•WÞÃöPr€E†$õûTý:èÊêu/ [¾îóð©[ øtÊýrýJFJ“XOÁÛ‡A÷‰áSE¶Þ I=ÝK¨œa¸‰àh¢šwÒCž\Y½²j ¸½”ÝÊGïºç@îøÄ-ðKâ–/“¾9»Z‡£RÏÁŽnxé½°¸!=4‘À”#ÈÌñÌ9Ä`aþ¤žÉ` Kk×»sºug¨Œ÷¦)kj€žŸÃwÃÓ„à›êü#Žt£‘Ç|^†î§áÑ%°¨&˜<€ÜÖ'u˜È!ÃFµ’D„$˜t²µmxùP‡´|ãåPYàÑ«|;áͯÀE߇׈ƒ?â¤O—Ñ $Ì«ÈBþ^h_ s¦Á‘å±} Ä4ÚWí³‰IŸ«-I$Ó»ptiõ hù‚ÜÖ]¾Z¢F ^‡ß\Wn ÿí[wû5Ƙ€ï€/<3ö §¦!e².Ó }@$É›“'-úÌÓ°¬)©3¹x=Ö›f)Gñ~àIøó«á/ å·ãÈBOÍÁW×®õùdûêÏg¨ç2›€ÆEpä—àî9p¬RDŸd¡¿øÀ3,ò…Uò=†z‹ 5pšÂ„É3ÈdUؘƒ$3”»¶;`ã7টÃVÊ._võF|u£qNÊU¨ç3ë IPZ¾—·ÂGÂÏ@% ô%ôcLÐÁJ70 x=Ð !‹>¦p¤$ùçážká»”––ñ~DU¾¡Èh@WÞ³Ì䃺¥§µO€©_†;çé©H/‹Jú›€W­¤{$ ¥%erY­ Õj¹‹jŒèúÞÛðÔ_ÀO†pèV¯»üQ+tŽä¹¥—T¹’ òñ»F áJ8ñpóìpnfM ËV“ó£ëÕ¯Ö×O[CtŒ¬d쀗îƒ5ß 'q(à•ÕË>þ°‡v÷GF“òzè”Þ@¡Dˆ[áÌKàã3a®T²t×/'•š~›¤¬TÚ¾)T«'DÀ¿Ñ_ûrøÂF ¼nõ£ïM2P×IJu"Ä–Ãé«àš£áøTTI”-£›Š. t½uM”˜’B Ûawü®¾õUø¿$?f._—±"€¼–î ’ºÐõr}*~+¬> 7‡ÿÓS‚§Àtì`Š‚lµß${`ß›ððßÃ7 c|‘¸«Wõ|Ýê¥úc"cIyMSX¡A>8[OÜKdn‡sγá¸gº Skš¶õßÚ>tÓwÐ;¡ãøùŸÃÔ‹8ÊÚM@¬^Ê €¼î`D0"¶Ü ?­³à”É0=•l˜Ã’$‚(ñÁë†ÎmðâÓðËoÀ³”–.~0àååÆ\ôëë¹VÒY1JÏPL…¦ká}ÇÂpô˜ÕÕô´¡ˆ œ^Ø»¶eaófxþ‡ðÔöò\|iáj­?¥ç¨I—S9ÐP"C¬Þå6•ßõQVù\ì4¤N‡i§Á3aæT˜Ö “3Т’J+Â7}}н¶oƒw^‚·ž‚¬ST®å"¿3Y{RJr@å`!T†WSýE¯²V[’ÆŠô^Æ,´Eªƒ¬W¤«U£á .H1uÇ«b°ñ jÝt0—Lf½ò\ ðƒ"Æ&+”˜’ðj5ÓÀ_ø2‰WëjDHª5Uü ^ÉÁN)IdÛƒ-ò÷º F„$ 9Ð¥J2”®º ôÁî×fÀm\ŽªÐE¿A’>+ÑA¬ð! ¸.,H’‘Þß ÐIòÿ†?£T%÷8~IEND®B`‚KDocker-5.0/resources/images/iconify.png000066400000000000000000000055631252153257300203430ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsBIT|dˆ *IDATxœí]lUÇÓqí$v>hš8QBZÒ¦­´¼Ð]Aªù+"µ«ŠEÊ (b[‘ö $€òHHEZ‰•EÛVåkAÕ´¨I*‘ЇòÂJmCÓ4›(u€mš;±Ï>8S×v<žkÏØ¾?iâ™{æLÎßçž™{}$‰DR (ÀÀ±´­±ÖI‰á¥-¢èŠu@9à$* I~¡A` ¸X¸ØT.¤ò X~Zú;DT8€2`=Q!8¬ðN’ÂD…ð¿¥-Ñ>ßµ´©–¹&É*¿ÆúV­çà×BPxûí·›8ð”Ó锂È#B¡Pø½÷Þ÷àÁ®¡åŸ+Ào-@)€ßøkqq‘Ó%f~~~¡¸¸ø÷À%`âÜöÉàç/EEE®ØÏ}‘H„`0ˆ¦eÖ)IfQp:¬YÿO\D"&'bqq1£ÎI²ƒªªTWWÅA\øýÂápÆ“d‡p8ŒßÀãqß¶/a©?¿H”ÍÖšT@^‘(žq iÚªPǃÛ]‚Ó¹€`0ÄÜœŸÙÙÙ¼Ùë·º½NZ@UU¼Þ*œÎ•wŒ.——ˉÇS‚Ï—¿E¤Ùë·¢½°  ( UUëQU5©ƒUU•\¿>™w™Àìõ[Ý>Ã?EE.Âááp(¥cy£§°5f¯ßêö±¤ÑhøýþUO®›oÀüõ[ÓÞP,póó (f ä›Ì^¿Uí…!A 8póóóD‡•SÃáȯ¡³×o]{C ±‚Á…”«{UUQÕµ)›+˜½~«Ú » Ð4)9àv{ò® 0{ýV·Åpp¹Š˜šºA(”¼ u:¸\Ey'³×oU{¡O++«#\ˆ»ßå*bݺõIOœË˜½~«Û/'í'wÞÙÀ/¿üÌÔÔ¥ÂŠŠŠ¨¨XGee%Š¢äeðÁüõ[Ñ^øX@eåz*+×ÇÝ—¯Á_ŽÙë·º=ÈÑÀ‚!#@’ûÈ P È ‰‹Ì‚Ì’¸È P È ‰‹Ì‚° !’Ü$Q8åš@NÜ PSSCMMM¶}‘X€ÌŽ@#PàH8RŽ@#PàH8¶€†F÷ÐQB‘ Õ®dœP$H÷ÐQ4?ïÊ$– @CãÐùƒ¼rþ ûûÎk„"Aö÷?Ì+çrèüA[ˆÀRèÁï:À7ãgòVzð¿?@÷Ð1[ˆÀ2Ä_']©þfÞébR>ùã¤tl¢àëX-KðÁл ƒ¯“ªú&z8|áE}}"]LÊ ¯Ã^¤o¢'éq«_§{è ½+ÒÅ”±D{6=Ãu»V=n5 O_æÀ¹ÇXԜ̢&ûXÔ9pî1†§/Ç=&Õàä1B& A³6û'¾fwO3W¦/‰qH¶@ßD»{š®AtnÿËðôev÷4¯:Š˜Ml!€ã°÷ì.¦ƒSÂlŠìDÚšN±÷ì.S]œH,@ ìÇã(e÷†=Ô”Ô ³+²i«¦¤ŽÝöàq”fuS" ¿3H4ÅŽß¼Ç7ï¢Ã­¾^¾›ìç[ßÙ¤^“!²0c«¶¤žû½ÜWÝJ‹·¥›…ù%ËËÆÒÍl,ݼBßMö3àë5$ˆñ¹QÆæF¨wo4åÏØÜˆ¡þ_x‹·ûª[mðXl'€XtA<¶4cftv˜_/ƒ“} øz“gÀ×Ë#O›:ÿjßþ:w-Þvš«Ûhñ¶Óài4u¾lc{ÄÒài¤ÁÓ¸Bzw+ˆL@¸žÖs-à±äœbÑ¡zln„_/¾^Ææ®™¶?6wG÷Òâm§ÅÛnºK±¶˜"ɶœ"±)€G  À‘(p¤ )€G  ÀÉùA±Ä>úøæFòýwõî yû (çìQð#{MÛ¯woà“á|2|‚-ÇÈ`P‹·ÝôùZ¼í·‚ÑQÆO‡OòéðI@eœt‡ƒAœ’+ˆ\¶ÝX€¨ !uî2?Ðüņ´çÚmBHìX€å öóÅÈ?¢…Ûd/×ýãBìŠøö/·¥Ã2á㳫Ý|vµˆN k©Ž”mü3ÅŽa~¦ƒå·ÅŽfÃ3œ¾vJXðî÷vØÒÖuÿ8§¯b6d¦ÿeÛŽ"°…Œ.™ˆÚ’úŒŽÆ5x©-©O¸?™o:vå0º¼êW;/°oÛsq÷g2ý¯vŽ}Ûžã«„¬‚žM,@ºk뾺ý­¸‹š«Û2áæªçh­}W·¿%dôlc™Ì,¬¬**Çv|Ì]¥M+޳"ÜUÚıߺÏÏ5X"«j—®-çïíÿ¢tm9íÿ³1Ö¾±tó­: Ö\%8uå}!Kª7–máèŽP5+é_§¹º UQ9ºã£„ƒWFEpêÊû¢ÝL KðDÓ³<ÙÔ•ô˜T—Wm«íäÐö7iöfQÞ6msÕQ½TEðdSO4=+ÒÅ”±lJX²7‡¥³¶n ìÏÚ £çJÖå=ÙÔÅá{ßAAébBlóóp…Ã÷¾s[&Hwaålή1z®D™ ÛÁ‡¥·±"°óªÚf‰‚6™¬¡ñÁÐ1ölúK^9¡HSWþÆM]–?¶ °…$Ù#^ `ý+¬%ÙdE¼uDbwHò–Û°°´ÙóÑ,ýÂÑ_M?­\9%ÉÓ@XÿCÜÀ: p.}&É/4 L7€KY@!Ú 8–6ËçH2F„è7?̲.@"‘H$‰D"‘H$‰D"‘ÿãš»p3°IEND®B`‚KDocker-5.0/resources/images/kdocker.png000066400000000000000000000363511252153257300203240ustar00rootroot00000000000000‰PNG  IHDR€€´9Q]bKGDÿÿÿ ½§“ pHYs  šœtIMEÔ JÔÂõ IDATx^íw€EöÇ?=q#»ld ’s*bÀ„s@=õç)‡Ù3§˜½3œéŒ(r˜sÂ, –œwÉ›`Ù8;©»ê÷GÏôôÌôì.ñ¼;¿Ð;Õ•ºê½WU¯2$&KÙ„?˜¬\ |k­!¢"¸gʽŒ9úZfeÓ¡cg4!(ÈN·ŒÀká hŒjc§‰u²ÅZBH!„ôúƒ²ªÎ+K+ëå¶²jùùw³%kô_lŒLA ¨ÊšzŸ,ß§Þ°£R®ØR.®Û%™€ÜÐ0OF˜ÃÉR5‰*AMTU#Ôðìóö¨ÅlymL`®eBJ„ÐMH4M †";säù§+¨óØ„¿€)qD4³C›Ö­¢¶Þ@…Z̘cú멘ŽÐ6›M‰È„L`î¤[Q,ÆŽS·€Êtr³&‚y²e)ÁbÊÕ"îÿ¿k –½M„5`cò¦míåã»O s#RJ™‘‘ùyjjÚÇÀ…,½x#áÀÎ(·‡~N“RJ¯×ßx™˜€¤—™­”íÅ…²U›^x½~vþr5Ë÷â‡ÊílwÌ;gæF…oסeU‚5[x÷–J.~¦¥.;w–óùç¿ðàt'£GGn«TŠJ,J*ëY]¼€´õ ØR´5ÎÏ~Ca²¼˜Þ”G&+–²â÷Gh·ióæ­ù•6éG1dØ1¨š@’6“­‚Lj²ª Ú´kÏ¿¦ÿ‘9ÛgéšvÖVaSaÒ„ÄÔðTÞ¹é ¶ø5êKª&(.­à›Oç´s¿ „õ‹æÕ)ÍA=$ 12×IfhBòËœ9œ4õK÷Áø{ă 2 Pè8ÙÒ[B$”cU†Â0hÈpö l@‚ÒÒRf.ÿ‰Û¸A÷—RËû^çü;OÕNà}¦³›PƒÚ ˆûåtЕ U¨ªž€`HÉ?šÐí5MPUÎ{~ÅÕ›èÔú(¾~àmÒìÙ´»¶—ûûŒ&È/ ¿NL„”¨ª0>4"âbPHlÞ¸Ž«>?€e/Eº=›t[×vÕ¿2Àk•€¨ºÈP­ +Tµ†?¨†ëkA (Œ uû.¼tê7 ™xÁ­T¨Å½¶Dx €;öã`J€¤ ÿJãRêö2¤†õÀP½/„@Óm;v¡ ¥=BJ*‚zÅY¡³ú•ŸôœÏOV  ¡Ç~Ÿg•=TÚ;Ó£Õt=Ò+jh5xíµºe2#¢ªÂét¶7Ýž4—°ínx°éölÒì9ú¯-›t{i!óèIÐýë­Á<{#Ñ6køû(\º­þ’ª†jò:Q¥Ÿ ~Té#(ýœ{Ë}ºßé´¶4Ò¼Qèdž€¼¦¨…¼y[Gyì”Vz6šÉ†”RÊþý‡î‘RÊÏ?ÿA !ä¿þõaC£¬Ñ9œããyvl/.”~5 !$…^˜£ª37Q^>ˆ®]{&ŸròéòõW ´´œ‚‚üDqP[Wú<­7ú…·ÌBÜ$çI!B ¤þ+…dö/¿êú9@I¹Ö•7pÔ©ÓÀ7‘-¥S¸ï/7ñ÷'@JÉ竟¦Âך•UCX´°Že L˜ˆvúQ]ï§²ÖKÇO®³ €7.]@ë-k¨ï6Œïs9ïÂî‘„±lE5íÛjäädGEºo_>úÁ*¦?ÿCyEt‰ÎÏ‹+©|ûÝÏ–öÿ[hþ€Gs‘ #”ZÞ÷Œ<7¾¢C³fÏfñ®ÅôÎë‡ÛîFÝzô$--!õVTJIëÓ¬#ijöBêMòIS¤xó¬h›w]»õHè§1$L€®éšÏ¢› )«(ãì÷N‹ówõ—PÖŹ7K<¬ˆtîÒáÇOÉ?êøä‚ïQL²e/@iý.Çso¢x­ Üó“a¢Õ.ҊƒPšÌŸ?‡+¿:€Â—¿!ÝžMç놅ã•L§ PÿÉhÄ¥T"ôHýÃf•L‹(ªËÔ3¾`À §ãU½¾”¡(L ÈŠ?Ñ:¡4 ¹…-¤ria%TDÓ»ÿ^9å3ú]*­ŠîzÛÇݤGx›ã¾ƒx¥4fì/ZQ5'FzõÌ]¯ ¼~­ŠϺšÌÔ °‘…‹Q–_!¢”JVʧ1”‰½³‡è ÐôDÌ~D/!d3ØòëÄP ü+Ñ¿®'Š˜Ç” u.ëz+;«¶Th•ÛRôt¾‹ûrQ2`4IFÿÀx ý•¡¿f?zBÝIÉ<õö;!*TãU¸Æèf/,•£Sô "º]S,L°våRÖ®X†ß§«Šv,ðˆ*~xÂèõ·\1Áõªøñ9Ú®Çgú,ºN ºæž@{ß>ωíÂL³•ÃiÇ#ª°)vl¤'‡äÏ<侃¿ò @¸-xÈÙŽE¨·sÍm T¥Ð³S=è °)6l6BˆH˜l÷KyH€ã˜ ÷rn~øhS(ÔC²EzJÇL¼ôjÚ`ý¡èí¤5¹¤2´]/ä;Š¢ (6”Yáä'ê¾§3 ( > €-,¢w®[ì§ïèÐG±¿þ¾—Uø˜1¨D Ÿ5»Ùl•ááÇý½2ªÔ÷áið¤/³b6g¬³¹˜¨>s)˜|_h¨èm†6 ;;çËðx©”RjšØ_myx¸?xÅ·T®0ú†QÓff8¾ývŽhß¾­âñx$À/¿Ì×4MàpØ÷—B ÙÆ½tà±M+üzMªRLsFÌüþ€ x=R!ƒAUžxâÙÕM…I€´˜žñQyV.ºèRùÊ+¯ùY £žE¶™HyÙ$ >R“j Ïee´j•—0²½•U¸\N–/_Å•3ÿÄÔÑ/Я_/¤ÐÇ’"½c½ekÛ¶5Ê—Ÿ½-_|ù ¾»ï#‚ݲ©f3y{³XP³Š;Ë>$‡¯güÀš I‰·«6'3{bÇ„ )¹ ìÑ‹Ê}ÕàpóØUÜ2Hï¬þóOÅd&çñKÕ÷¼öÆy8úõëÅuרîý-“&“ç˜ÃŽ_û³[«`øæW,ch;'~ÍMV›¦…ÙÔðKUû<Ô5Ð4v[Ö¢¨+9tœá×ðÞ?2uÚwMãÜñ¼Œ~ó"ˆÍ¦°cÙ^r»Om0¯–lýU|/HÇÇÀn·£¦e¢h*µj- g.j|`ûölج1ö¤q‘^uólUÚòåC“Ñ"=Îtäd·lt|  âtFÏ€þO#ÒÊ9‹C‰ÉJ:Pß”·Å¡j 'ÎhÊÃÁ ª¥TÃÚîoë¦j쫪Âápàv'ár9Q[H‡—*¿¡ë˰Âo¸…~ L]uøËjNé”xœ(Â]·¹sç2æÍÑúuÚœŒh?ŠS;ŸIœ^H$éé-èбî¤$ÂÓ¶áÞ×'Àþ@ïFú­…«\Í[…o& Afmý‰Y[-'n8þ¨ùÓàÛ±ÛíôìÓhaéïPb¿ ÝŽ`ða <”§å‹ƒ*6l ¦¦š•e…<0û¤4õ‰BèÛ©k¶n6úKsvüÌœ¡¡ë¥;@w °1.‚C€¨Vàžrz¢" $Qá‘ gñ' {(//c[q¯ÖG76)IÉüúqÙ’ùvñîxcr|T¶ó—«€Úx†f@‹Í¤yÌÈ”ÉXIs‰A¬ÚÚ6®_Çí?_Ëž†rã;n§‹E/|KIÁ­$£']'FZt‚>f ^6»9H4Ú J0Æ Œ1)ÍzZYÓLC‰"z/<Úž÷NJI£Ï€!|wÛ ¦œú9­RÛàèýi|ðë'xD¥žM¯.f×”uÜ0öÚHÂÎg&؉ÞÑ:¨š2¡Hˆâ´f2I$Vn¡_s±KPƒÇÃúµ«˜ôóùFrZeå2ãÑ7p))¸lÉ!©Háÿ^º™ËMCmûxƒ¼,çPâDZôè{¾ƒyjddÕOeM5¯Ì˜ŽGTGÁ#ªØ1e v›=œ‹t.g@k ¡QX‰> +#£µÒDãÁŠHa%)òDµ1&Jç}¹èëFRÞšñ%QECŒ$x´*6¿º(’fñ*$ ·‚%BÚ(2l#£a5Uʈ_ƒPæ°aÿQ„Š1L Ý‘&»ÝA’=5j*샟¿¡Þ”q36¾fçsÑ“®tRi&â 1!êepÀ‘@Vvƒó"‹Õ>Ÿ97.ã &óŸÆ]‰`ïâ"N€(M°Ò ›*A×ð@%ô BÚâku³YÈ_iø•ú•”î(biÑg|°ñ™Dé ¦ÞƒGTé+ql>‚Š?Ê|Åigñϯ¦EÃ|t§žZêðP‡@šãŽO¦‘ ­Ã€®œÎudsQcžNÕ™sÏŒ[IÁ¥$ã²¥D™]J c&™ô„DÐØÅ»œ©É<Ó‹VteTHt:&cNÈÊ Û0'‡tƒ…Ù¥$³iû.}âÆÈW¼Ìácî¢ øwÁ>¬nÌb¥gÚ˜p[~ º”Ü!)š@)\1ù~J+Mã‚ßr{YTÆ~øÐLÏ<°ƒUüL?®”€O²dV=}F+©!Ph†Y¢!dÈÝN“gÝ|õ^c¹›ÊtFÑÀL,ý­H€Çr1oà¤{ØâªRpÛR »”dýÝT,X°÷>]‰e//ó-¯+,¾aà·H€œÈ´æî°Å©×ØiÝ.º_.ÿõWTÕ4Þð.£ÐXB®›Ñho0=½ÅgK–,÷WUÕÈK/½ÂXú2aÂÕ¥/¼ðJm×®= ë‰â@±žŸy‚o1V(}÷†Æ¬Oë¢ô*o%Ü37’y½Lg$shFæ­0ìÁÿî}Ix¾PJ)Ç¿°8ÝïH!„Ô4Mž|òéÛî ¡`Zˤãä¥[ÿn‹^Ÿ:”I@ç¦"l™™YŸz½~¹qãv)„[¾¾1œùËO³¤¦i2TåîÝåèÝT|‡#¸oÜ¢ÜÈäpˆßžšòxøô³!ÈÛú(JúŽêaH£8\Éø|‚A’’½Ê…œ³úÒ‹ÇÓ¿o”ý[*y@X±b O,|ž¥K »>9=yðØ;ô`¿¨}—ûe{q¡¼ëžgxçÝ·TŽïœ£hu1ZþT‚A•íËï§§ãM¶·^ƒ×ë§¡ÁGr²›[nžÄ›S7"üà£ÏywÉz²ŒÂL¥tÉn?©=眿à°)„çúöx þ¨7ԕ¾"ËA¹= %›L[=+/_“^\¼'ÿöA2{¤r矯!¼ôÛï~æ´SOÔû{ü6vm_…×ë¥ÖÓ‚,å::u™‚´iTW×ãóù º¶boWmé}lÐ4AII9ÞH›Ëe·Þ‰—õ㜎­¨ V°Ç—OFÞ©¼ékÍÓÿ÷s_¿9.‘Í…¾Ó§¾@ÞÀ |}G0¸çæÅÏœÝ~Þ4ŽIîÏÉÞw Á­ù×c)”ÚŸçž{þÏðÕúrÆ2n¼ñ:ÊÊ&³¦ôNòs[à[; ¤ uÏ™SôWȆAGµâÉ'_æ®;Æ3þìçŒðy]òpÛüzÄJ»¢aC`CPŸ;ˆƒ’ŸJƒ/ˆÇ¤ÁÄëWñTê½8ÿZ Ü%›qWl#Õ-5ƒmUû¢üEU?‚çŸ}›,§EjÏ<óJçKuÏ¿ðw:´SèÐNáןâö[Î">çj>û¬†ÕÕƒØR×ÝÞöìñ·b÷ÌÏøñ¶[ØÆÔŸ†ð/Tx$åõ’z‹}½w|~.³{ldU^”uéËB¹•œðêkwEù‹[¿ ù8],<ž/_e¼kš†TQUý †~Ív–慠¦ÅNÌH&ß'¿ãwüÃ<1rày‡ [gõbÚ˜ èÝåÂRæ?=†ýá=ü¶ pð?O€(Mp⃫ª«ªÑ4Óå")ÉÝîM”ÈÈLŒžl Ya6H$¬wr û8÷Qxqÿû+€>»3gî\ k–S¨¦%Y8ÚÐ29+ä.‘’“SÈÍË#77ÅfG"C³J¦Y£…f9Ž<BJ6lØÈ‹ _à“µÖçÔ„Ñ>£'w:S:N’à ŠBÛ¶GѪ µ‘y£-:8al6˜ŒÙŸ††V—ETÖDØ^³)Ë_fÊò—Hr$qÍ€‰Œé08ºSgZfå Ç~d(p@• 4¦Àôi®Î]ºò¯âLi*h|ª.y†ó>ËeŸžÃŒ_²hÁ¯lÛºµ© ‡ û-Æl®iÎÏårÓ§o_>ãk4!X²{1Íy¿æo*:>ÕË}³õX×ö¿‘@ñа'j[Ðá@”&˜èx‘0¬2¯ƒhûòòrŠ‹¶  ÇæLfIIÔl”>»²zë&K7–g¿ÇÚÊ·€Ù@|§ÿ ÙH”y!%RCݬª«W­¢ÁÛÀ£sli\¼ß<þ^¯Ê5Oÿ™jÅê7Á>Þål$¥@Q¼‡ƒC³®ðb§¸õéoâ¢E" ¢ —/ÃãópÍWТ™ùü¤Ýû8áä쇮¢¸Ìb´}W±šõÀâxÇG³`d.Š1ó+Í¥Ô‰U_ïaíêU¼·öM¾ÞòIÔ7½úÆ ‹[I&€·Œ&¨ÅšVɾá-ˆÞþu0ˆLŽŽž<ùQñôŒD¯õi*óVÅBH‰Ãá¤Uë6ä‰åÃÏÛ¾1¾3³p>ƒºõ¢ +—ÓÅ­ã&‚´±p“©Ø¤0.Åz¶;âS»ÿhT Ñ·Èh¢u€"T,¬V‡èuƒN˜-›6R²g'“~¸4ê›sÿñ-“³Œy¿êÚzúß³øËÃ|ÊCIh|¥¨Œ]ù-ÒRêe]†8.%¡ßøÌ i^?(éЩ mò;ðÌÓÒ`ä­>‚ÒKPúhÙ¢»_Y'Ê)ŒåB`‰„„2$cÌ1OT‘°z¢¤#º>isTò³Úrëà‡¢¾ý§ï# |¤— ô¢ lJÌÄG7Ñ‘vÀïþ¥1Äp_ÆŒ7Hp\Fcˆ—#&.GœgœˆE8“ȱd ¢Ì2ÚÞ®DÔ)_~fèf J/Ý9Õð‡t`ÑW‚æC3½F\M/Ñ·"JŒYC “D ÉÊÉã¸‚ÓøçêÅ@øB÷:zwìJÎàÀÑì,Š€9«Q ÞuCQÌf6G¨OÝÜ2'Ÿaù'EÂK’¯I/Љ”^NYUNW­Ùì·¹ÄÒ£_e¬Eôk˜(N§‹LwôqxáŠ0¢xCv>œp‡Ùë~çg¿(âÖÄ–V%qŽRˆŒ:@'DRr̨^OÚ£ Ý,XŒ *ij'Ú5lPdøMêgI“ŸÐ»9SŠÉR‘àó6°iý“^ ×±„ðëQ\ŠƒPPlŠ—PÀ¦à°ÛQµÐÞÂΜÁ:;Ñ÷ˆÐc‰(l¬ÔË£ŠIQ‰ýULZ\ø×dgÒõ£•žØ0’ +6òøâK2fcd t p¢ ЃT ³"Žï;”™…¡uÂéœÌ~¥Zꨣ/54 !ÑOàŽKB4¶õø‡çgbö»Ò‚ »j]Ø´&wH %@@x!Äy³(Ba`·ØÈ¡;/ZD#™ÎñÄ*!Àd¥#Ж#‹¡L zlÌÂæ'(í(2$(Qæî:4€C±uÀ.+O‡Éá£Â§\EÛvéh>'ªÏA÷.¤Be^±‚mòÖ³‹Ö­Nü%A•õ~ÊíaÁ.çG’“jk,‹Ý½\ÞÊþ;ôƳª¦AÕw8Áb j¶æ·°cdÅÌ¡W„-ÊK|tî“Jx÷ b˜”Ðiw¡7%ܺ(¡ÿ Ï~<••EƱm°¿°å@1Øï©±Ã€zê©£Y¤pÀöü^”¤¸£×öFFe´=¦¡Áëã½™_Gb×(gs€õVÿ-HÀnÖSD?®[¬šß@¿Qî( ÐM!B(ay ¤déîgÝv{tÌïpúN1K]à·BI“£ï‘Ò³-óíaa7i“JèÜ<Ý.OMý]å¦Ýb븞RVa±[,ŒßBc‹)¤ u¡®-³?ñÒ©Ŧ‹y¤°ÅéU5õ,\iºN#È&–±†&æK°‡Ì¡7W…-vé2Àf} Æ pÓ}Ó¢cz—s€4¦×s;CÍ„—êø2lQ±CPçñE†ÆLc„aóSÿü6:–E\ l£‘>@¿5,åsž4[|ø”?f< bÞ±{[·™Š¸lbÍTêš[Ž,°†Vœ €gŠFvCøCŸÂ3/3‡“¼Ç¥Àü¸ Q øüó¯¶mÛ¡y<^AäpÈq‹/^rÉe.—ëuOÿa«ØŒ†Q¥/ýFƼòLÌB?2ŽCyàR}}ƒ”RJ!¤DÏhò‚Kº?ü0ÛöÃ…½g0óväe[lòE©òô2¢·ÎÃÐŒÃSc%ÝØ®]‡™„D>2Œ%Ä¥—^Y<|ø §’ÚZ§œ2údÀÇáAI=Õ‘3«+ÀS+HßLêÖk¡zãÀW¤¦¦}.„ªªÊ»ï~ÂûÐCßWSS/Ãܾýöûá£Á *].׫MÅyˆ0‚ ƒÓW Ý$šûiœd4QSp¿ûîתªjÒëõÉ›WÊêê:ƒ^¯_ªªžù†ºrÖ4ZÑ…‹î=ƒ)@âPš€¹ø/¿üì—½^?;—}@»,§Q¤§Ó®ß¼°h……Kn°Žî° ŒÍìBegœ‹ÄÏ ÞâO‘‚ÐÖY)aã¦Í¼ÿáø|^º”MNG#\mßš¦Ñ³ggN9弟O<¡§œ|YYû=·ßÐ4åËWqþ×WcƇgNq÷½§×Üä䯇%%eØ]íèÛÿÚµŒgÑ­ä8ŠÀ»ÍÞ[¿i, âÛ2ÙæRü~?Ï?ÿ4ÉÉIlذ•¤¤RR¢G¡ý¥%e´nS€ë ް=oûéÓ}6»ËºÏ;õÙìu%6›¯×Gƒ×kÌ.E Î.¢®X͸3ÇâRнËQdd¤Q]]R·òK ð&ªz@@@%;é#–¯mIZÁ±x½~Š‹wÇõ‚A®½í´îqäu¥ü“"ZnÇÛÏÝ‹ÝÞ\+·ËE‹ô4:Lï”#`ûÑ`¿'¯nÊáUßq°ÞíüÇß¾òÊ;,]XŽÍ©òÇëÇ2hPdú½p…>|æhÛ¦5Ï<õ ¯çºënbPÞ¹½2Öð«øýA¼^?-“f10i‹ªÖà÷û‘RòôSòæ”GH¯¸õn\|Aé¢.À•Ö‘½†súõOòýëÆaûO/”œÝ à8< ^‚ª›ƒ€êAÓÞ3/ŽÿwÉSŒ.¸–1-%Zr:K¾K£°ð-®½6êBO½¼öšË™òê£|ôáÚŒ¸ ‘¤vÆïN¼yjIDATÐÐࣺºZ¸Iвe:UUuìÝ[C÷øêëïøæ›9þ²´JÞMŽ»œ giÎ:’ ÇÜÍÌ™¼ÃÝ€ª „b'(mÔ{Ô5¨mˆ_Büé§38)m^J¢¡´ô,fÏ^Æžä"TO];̧mk½:½‰êK£,m_}5‡?|—.G+ÜyûùŒ;s,?ÍG w=yIe¤;jqÛ}8”%ˆÃeç›_¸¢ô‰_@ÃçWñúƒx|Aê}AKÌüf)ΪR’J¶T² ç¾ìõû8:§Û¶E¯¯4ðÏ—Þäá‡aäÈÌúu õI?³cu[šÎö•ƒ)˜úþ.¸à$nºé&ÞÿÀ´BHMNÁ¯%QÈÄ/’P…!í¡ÇFFªå„ÍFø²Z¿ª_Vë è;É­vŽ·iŸƒ¢±ù=ؼõ(jESihØK^Ì=dƈP«VyìÙSÅçŸÏdé’/™ñõ›7âìö^TVVS¸üz ZåðÅIôïß3n”á‚sÇñɶdå´! \Ô©4h©øD »¹èÜè•û !"3ªZø&H ¯?f=10é–+yíòèœ×„@MÏF$§³b׋¤¤DpÞø3Y²hcFÅäûÿÌ£ßÇSÅ™gŽ ¢¢„'ÿöWn»õNÝžï¿ýwÜ61*¢¾}zRóëv×åQá+`Ÿ?‡Ú`Kê<†îžN×.8PÔùõƒÞöyaŸO¡Ê§PíW¨öÛ¨ ÄwhÓÓÓ8ùán̲obOn>;“sj^åµ7o‹óÛèöù›o}‚&ÞÊãMfÚÔÈ1aê´÷ùxáF¼-Úc¯*ãÊÑ]¸üRÓ²¶ýÀ‚Å…3tÁ`}U‰¯|p:dµ´VÈTUÅn·Ç5Ù_}ý=ãÎÛ¼óþgÌš³ÐŠ‘RÆ LpV€•ŒÉåùãϤwïƒ;ÔáwüŽßñŸŽøºm² ü!Þëï°À}LVNºý'Àjb°+‡ç|¼ÿ>¼sæZ`ð X/?ù­ã·8-ö;Ž ~€ÿqü.ÿãH¸8¨±kÉ'¤”ìܵ‹;w¡ªª>¨vCýY›ÍŽÃîÀétât»p»Ü¸ÝnÜII$%%ávë ‘¡pz¡_Sœ23Æ*š°“•VÞL¡Üóï8ÔøM¬“!&UUU³fÍ<þzþòÓ½¬,[™0ŒËî"Å™BVr6¹©¹ä¦æÓ*­i­iÞ†‚ôÖ8í.ÓA±)$§¤žÞ‚-2HOOÇž¨ û³†ˆ½”†lüWàß&F‰”aÂJŠ‹‹RrÃW7°³&zØ>-@@ Pí«¦¸ªy'Џín:¶ìDï¼¾ôÎëG÷œž¸í‘ùÔ””T²²sÈÊÎÆåÒGïeLMðßÄ|ø7@¸´GJRØ,IoÑ‚ººzÎí1žç>ÛTTû ¿ægÃÞulØ»Ž×½v›ƒ^¹}8®Ýh†µ9ŽTg*R‚Óå"//ŸÜ¼|‡QKùår‡GL¢o®NC$•’öí;’’’Æ8ÎæŒ®gáWý,/]ƼísYR²_Ôj¨C M¨¬*/dUy!//ý‡aß©eWÆu=ŸÁÇ`WôI…àÞÎànßHlÿ98ìÍpWŠ]ÈOVvC³²‘è#w¯êÅØÊÓ©®®AÓ4¤”xænŸÍŒÍ_²­º¸ñ$Šª6ñì"cù©x×ÕÛ:¡ßšÉè@ÕPðåÀôƒíÄ•øŒ †ŸÄþÃ:ƒÏ磼¼œŠŠr‚Á H(®.â“õï³pׯMî½}cÉù£NåÒ1ãøuõr¾_:—5Û65R3!)g9…<Æ*€ °ˆ>´ý7ŒC.Q Œ©ê­/e˜±Ön±B… )¨Ü[IÉî]x½ H +Ê–1mի쮋_P‹¼Ìlžºþz·ïŽ]qâ÷«|±à¦ýô!»ö–ÒLHêøŠY¼H ^ôa1ó~k8¤`Å<*QÂ`t s›Éø(Ið-rPUÝ»wR^V†’]µÛyyÙÓl­Ž¿wà §ÃÁƒWÞÊiƒGcWœúƒ¡Á'¿Îàù¯_gOÍÞFã@ÒÀc¿ ovØ4#à‘Ç!€8FE1ÕŠéM¼7êª ,Ç, º‚’]»(-+A É’Òù¼^ø,^5ñ)Å»ƒÇ¯ù3'„0Ø'ëvlâÞé³rÛš„q¨åSfð*}ßR³¶î)´4ÆP‘P(@Hbü’È-, v¿Ÿ¢-›ðxê©òíãÙű½6±™‘šÎ[~’Ž­:`Ç#F슓%› ™4åÏ”ìk¢©h`&_ó0~Tô­‹Ín['Jö‹ÙM1Ø*œùVqZ096^°¿}[1•{öà Öó%“ÙZcºº9cÏcWÿ‡Í€xaPUÁ]ÿºŸæš0jùˆ/y‰†~€Gü•HGñ ÖGOî ŒyœØ1>@Rš˜ÞfKBgîí§P4úž˜ñÁ´pZdd’_Ð-¨18ç8†·>¥¥óðkñ¾ŠJ¶óÎÏŸ3fÐpÒ“Sôo"Cñ $›ÍÆiOæÎ³oÁns2ƒõÉѸéE_®$…uìBéüõƒ¹Ìœ!Ø´ßÈ{Lbé§©w+ƇýDÌ-2Z’›O .À mÏÀmObý¾ø9ˆ ªòþ¬¯i›ŸÏÑ­Û‚!æ›ÿ ¤”Óm(>ûVê¼õ,+.Œ‹ °‘Í©ô`(›™F ŠÃtTxcØošfhs™/ÌöÍ’XfZùiì=Ê,A±‘“›b·“«´â˜Ö'²°tªÆåVáB;ôëÜÍÄt]ˆ†zϤSoàçU³©¨5ᆔÑ2›†cڞŪ½‹© ÄócÙÆ5`“ôëÜ5ŠåÒ¨D˜8v®<áRz¶íÁWK"‡†P°“ÇYPO»4ÀBZš½ ÄŠ‘úŸÄ †0ñÍOæ5ÂÔ8æ7ñ«ŸÒj:­-ü+3Æioš”8\nºõì‡ÃáâŽAOrt†õÚù׿ú¯þlum>ã7r¼eè>Æ< /,¥ e¾e|äqgs ôçÍ65[BbŠé1,L%‹!1Û‡­Bõ~2ßBà mÌ_Ô¯!sè ½+6]zôÁn·3±ï´J±>¦ü±½Jqù¶˜C½Q=†x J/ÉI.–ü}6Ç÷<Î2>Zpçr7z-}˜òaB³@gœ •êX†GÃÙÌ€Pب02b/MX»Y‡‰eþ~Õ æ_aýŽ¢Ð¡sÀÆ }&ã²Åïî“Ào¼¨3<†éfas”>T|¼sÛ«œÌÙqñÆœÅ$t!èiíéСy:€‰Ã2ú5ÂX" 7fjT˜pDB‚áy¢â‹aj8TûXæG OŒ`…Þͽ›ÝÝîÀ[ß@VR>k*‹ªº:23RéÜ®m(þˆB(ŒœEEúwꀓ(.ÛÎÆ‹áé$z“Ç^Š“›bج >‡8fK˜ya1þæp`±7¼†^Ì‚¿™I‘è#Q†Ë0¦°ñö¦´X0?ì73;wR2ý²á¨ô.XáÝï¾#|åE¤0릣¯¥×8ùùÙë¡o‡gžp'Ýi‡~FQ“‡«(š%aDŽbVœç†D9ÅÔ_ÃñJó'¢c0˜a(¦_3Sc‚ 6‡1ÛG„(ìßì&ÉÉ/@"9¾`VØ[]͵+#§\ÇC˜áa…0rö™—·nyžw²e¼ôçáÐáX]9LJa“`ÉäF¤…C3 {ëH¤¥µLhŒd¸Æˆ‰ÈRHBDHHLÇžž‰Íf§[ËQkÍX´fM”`îD•~“p¤¤dLHp€†“NœÌxô¹öë\øæ¢I8`$”œsî‡ûûmE!5=›b§S†õe%¶îŒÔ"¦0ìÃ¥?|1ˆþœ2xƒ»$Pús¹;6ô“y-Ðä’0…ôJèïnåU?n^±¬ÅJ@¬#Œ‹[Ñÿ(Òº~ m0I)©©®Âã©GÓ„~«bÓ=*á³9mF‚ò’Û°Žø‹+*«ñëq;“h4ì¨Ø¥Š]Qqà4ì*B:І=äïg\ÂÒg-–ÁÛhÁñœÈ,~r8ăDM €B˜Q!r+ ÄU¥&¿ŠÍã-,ÃQ ŒçhB¡A—sÚè@Šá'”¦PXülÞ°UUÙQ[Ä’ò_ðª 8m.6'NÅ…#l¶¹p(º¹Æo½Ú+ âÓPì2ÄpafzHìăTŠ“ÝzÐ6·€]{,f‰s9øèz¦_‰¾ø$ˆ>¯PB3V#%€Çç)<uÐþ!¯}þ}v-‘깊%|v» ?A©Dj€F˜¶·ãÄŽ†•úeú_ÄGîf0HtД@ŸZÖ/ÊÐ(¥”éÌæ'ta(¤‘I¦x˜¬¼ ¼ÞæçþßèŠ'r'6\Mh -’‘ö)C 7ÕRE„.UŠ-Ät~¤“;6õ+ØPLºœƒ£iÇ\Äx>`"ÐHxéwcMÀNàƒFÜÿÓ‘N¾Ì`§3 ;‰~i­ˆ6s?ñP®ð5½5*„ß `/Õ¤³‰÷éÆñØhë©l‡JéŽG÷µÏ0kf†ÄÄts³a² Tu]×=ü8«‹lWÙÁW\@;€5Ànk‰ñ»Ä#” ’þ¢3­qÑ9ÖS]•`Ã2?ÚP!¦'(ý:C£…¤©`îÒÕÜûÜxý ºðULãSîÃO°ðZ{l¿ €5$ºr˜Îz–ЊÒ8&ÖS0khÓU’”fqLûmfz‚Å£fÁBðôë_0cV-_âg×2ŸÑ»êëiDËo ¿ @ãÐÇÝ‹(ÁÁ"ò8ƒåPJظT%¹…FË‚h–7Ítña…²|O ÷=ö1¥ =?+ù˜Ë(c°‚C0/ð»4 ŽR*øŒŽœ†BÜþÎOFë.a†ÇÔ¦öž “ýϳ6óæ´hšˆZGOòÿ@Pƒ®å’=ÿëAû70NÎã\ôµò”ÕN½ÆÓnRœ8ˆè ›¥jçÍ—×PV걊µÌãJ¶³Ø‚ÅU¨ƒƒ€¡À` ÈIKKËÏÍÍ˯®®vTUí;}* ˜ˆ¾¼©0ô¡ßöýŸú’íÎæ&Zp•'W2œ9Q!5ÍÏôðh¡â¤lG€÷¦lCˆMx?ó)"I&g÷ö,99¹_nÛ¶}\jjtmxÉ%ÊÞÿí¡`,hìØ§Oÿ/úé§^yyÙ €”ÇÇöí»Ä=÷ܻ端>~x™ÿtrÍI´ãK œt%ä··a‹ÛLê`î×u¬^œp_¨¤˜»ù•ùèûM·"Z4µ`0 x˜•©á•µÑvú èC¬Øl¶ž{îåÛ'Mº.=6\yy…8ë¬3Wo:›ßØžùf`#PÇl~¢'[È(13Š~z œ,èql@Ÿ’*ª/ȯxñÔ$hë5vóW³`‡b®º$Z6lÀ€!—,Y½Ìãñ¾üÃó÷vÚø]v»ý =pº¢(Ýâ¦$~¿?¸¸gÏ>«KJʘ4éºt)¥q[0¨rç­êܹÃMÅÅ›ñŸÇü0J€•¬c_q&šuÛ\ø#ÌûHWûŠ×ùy÷ožÄ̯á=Þåbö±ýàÃÊ|HÜ\1iÒ]ÏÝÿ]™¹¹ú@˜¦ V¯ÞBvvmÚä¡i^¯Ÿ-R@RJÖ¯/"55•víZ…m ¯°-,\£žqÆ©s÷ì);}èõ¿ÍšQl’ «¹•lDÍkrçP!Q7påâÅ¿þ<þòÓúô”áñxÉÌL#;;ƒÊÕSIÿuåvS¬DÏ?bpl/.|ÞÊAÁ•¸±BQ´¶]º´S¶¬[Eçõ×ÓuØ#0p>AU DD—r‡C¿gTßp©Wûõõ Œyzê–ÍëîyïÝ—F$¹îµß*V®Z›½mÛךúõ«^ßøv_}'1Îiúö19#Ögž–1qäˆáå6›í¢F(Û‹ ¥¦iL}ë=6n,FÕlddäЪ #GŽdìØìXõ5 ¯„üÁÐóZ°AP(Ô¦%33½šUÕØ´èRòú’ß¶#š&B†ªª,]ºO}[Š6³uë*÷–’–f瑇î: Û5ÿð4xYZHTMu ååìóWñZÙ[¨=]‡tpYÆ…d»[’‘Ñ‚ÌÌL„–L`yd#a­ðœsN£g}m© ´¬œ­Ûö1uÚ»$'ë¥3TÙ¶­)%¶õBj5ˆŸ`Ÿ€Ì~HœhÚI¡Ò®?ªªa“Etv.aÓê?×°×4.]Ž¢ªª–ƒz“‘‘Niéî¼óVü~Ü´fmã—¹ Xºv3U A‚슬T7Çô먑Çоýá¸Í=1¼^.§ƒc†ô±¤"• Õëñi÷t8éëßf[Í÷è-…ƒ^9ã9¿Ë¹(vºöÄíÖ›P—M28/Á`P#ðùüTîۇЙ™¤§§5êÿÛï~¦¨h[´¸].JJvòÒKÓèܹ+ùùÙäçgÓÐà´¤}wZàœ r&8ZÜN ŒÒð…ø‚?ÑÕ•ëž`kÆ'¸“[ Cî‚Ý»+˜1cß}÷)n—ÄåŠ_“©ªoL}‡ŸV®&wP²:t £ýѤáÆ§%ãÑ’ùRMaêÇ›plx›Ë?š —Ívøö»$BµßÎ3k:‘—Ò«[ôo%G·éNAÖ½ õ!%%…ÎàÎ`þŽH#±£´’Q[æ/÷Æßîh†”’￟Ågï/¦¥2”v9ýHM.‡ ¯ðSR³™’š™ ?6ƒ+&Œ7,¹¹9L}ãIò¦¦šÏ>ùŒ]%>î¿ÿ\ýžÂ³y©™^ýH£”Tñû¨ª†ªj:ƒ“$d.ÈvlEÙ4œEÉ3HNoI ÄïiÕ*—ÓO?/>ƒêêZrr²ŒïïÙ[ÉOF/ñ©™HgÒî@$¥"]IH‡ép"m6íšE¿uTb9N’““yëgøäÓ¯yìч)(è@ié:&\>ž›'Ž¢(H)¹ýŽû¸ðâ5j6›Â¬YKøá»i¼ðü£\z‘®/]º‚Ûo{œ¼üžTVî¡ÃQI¼ûö38‰§!&\v{žßÇœÏVÓëÔ‘8 RÚP¥ƒ€pIxµä.Jƒ–JƒÏNÝ//se?;çŸg½ÿH@JiœS{ôŒê¶iB÷ «¡šBK4#hÂØ±'PÐ:ŸWžø€Nî´ÏèŒ"4PlH§-)-¥•xYµãÆ]ܳÆ5Þ6y{v"Ìœ5—EKvpÓMiÑ"’’=<úè߸è‚ã8îØ¡Mo¶m啩ﱡN¥eïA¤¶é„°¹ 7Í7à zÇVæql~€›þï"ÚµkÓT´‡{+«Ø\´Íèú5o- òÙGÁ5váçØŒMö¨­­cÞ¼E,_´ž²ÝUhB’Û‚ÞŽfäÈ¡´ic½ÑéÛï~FUUÆ98PU•É>IYyúˆ  k×öÜ}ç‡åºõŠ={Ù°a3eex}~R’“((ȧG÷®dgÇ-Ü=ìØ[YÅÚ ›Ôßú¼Àèú!õE_Ä™Mc…&¿†«p1î–æF0kÖaËsRGB®ÎébKGDÿÿÿ ½§“ pHYs ô ô}¹›tIMEÙ 6¨³í ¸IDATxÚímhÅÇ¿;ût»—»k.¹ë¥©¡¶[¥>!E¡ZET|D¥­ø¢å¯ ˆR}©­/}¥í+­†‚Eð¡Š}¥"õ¥RPÛ`sIÚ&—¤¹§Ý»ù¿X“Þån÷öÒ$vg8¹aóßüfvf ‚ ‚ ‚ ",H5Ÿï ÎùžÀ0àØÌ—JM†xÿú×^{ýét*C"«ñGGÏ¿ð®ý'Ü<@6›}=“Éô½Ädxx8ÛÓÓ³ ÀÀÌw¬&¥R© ™I\þmßÚ6¯À›õ•JÕj•¬pce¹¡}› `†óçÇP,Éz‚‰DÐÕ•lšÖ €R©„B_$ …"J¥4Mó#€28çd5Á(•Êþ€"”æë­ ª*LÓ€ªª$ å²…R©ªØ!BÓT¨ª Û®À²,LOOûžMÓ€¦iPU Õj–e#ŸÏömŸc»]סi8ç°, ù|–e¡y»Â¯ð®8‘ˆ#A’¤º@ˆaz:ññœÐ3UUÐÕ•¬s©ºî¼ÇbÏ!Ÿ/¸–—eÉd' #ÒÇËM`jê‚gd¿lYѺï Ã@,Ãää&&&çç8÷‰8‰¸G¯0!Ë2FFF…l|YfH§S³S«fÛÝÝ…ÑѳMƒiI’NwCUÕ¦å%IBgç2pLMM5ÍÓÕ•l*ž™ò3í“ËM´ìÔmÅŠ¢@Ó4 …–†2Œˆg/²Û/—Ë>ò™(Š ¶ìèˆÂ¶í–n>Ñ0=ÍP©Tì ð–m i*Eq<=w€,3‹þU’Ä &%IçU_Àé02Êe«a,ö[^–YƒP“Ú*_.sïNÝŽ¨Tl •6LÆ!’$É¿ñ{Uël)Ih+Hž[€/ïã§3ÏË8cšÿeLÊض Ë*µ%I’ël›ÏçÛ‘«5Ú)_[ÿ‚x€r¹ŒJÅö]¹aD…@;îß™-hPÕº{/(‹¾‡FEQ¡i—R^¦EÎpîüRU ‘ˆh JJ¥’ï)®¦éM\¸Û¶|•ïèPÊÛvå²?/dšÑÙò â4MÇÄD®ed)IâñeB®(꺱±s¾ŒÏ˜Ü`ƒHÄÀÙ³“>êÑ¡ªjÓòSS“-Eèx}acg¡"l6ëªbÆR©4c‚ @‡¦éÈåÆ=¦ÀâñDÓëW¦Źsg=¼§ŠT*Ý´ ccÎk|ÈåÛ:;dòâ»Ë¹?@9søòKàÛoo¾½óG£À-··Þ Üv›óAlã"ñÜoÙ¹¢8w¸çûZµŠó·ÞâüÂ!Ì`›Ø1Àè(ðÀÀÍ7‡;.þR8u xöY ¯x÷] /k¾ú ¸öZàèÑʼnž~xôQ`b‚pÙñþûÀ½÷##‹[Ï‘#À7:ž‚ÀË„?vì€ï³èñ8pÍ5@: ˜&pþ<04üþ»¿ßøë/àž{€ï¾R) ÿS¾ÿžsMkÌ©*ç;v8ù-«ùoŽr~àçëÖù oº)pÁáÜ 0ذmί»®uCmÚÄùß·÷»ï¼Ã¹a´þí]»Hÿûöµn ;Ý{|+~þ™ó+®híYþøƒ°ääóœ'“ÞsÿýNo¾Nœà¼³Ó»ž‡¢u€%ç“Oœ©™é400pé«xëÖ}äç‹/œ@’¦KÈÁƒÞé{ö8ÑþBpçÀÖ­îé¶í’°DŒŒÇ޹§÷ö;w.l¯¼âþÙg$€%ãøq âñ¸º­[þÎÚµÀ 7x¯ –ˆ_õNïï_œzo¿Ý=-›%,¿üâž–H×_¿8õ®\éžvîÀdSË—68=—Gr.^»¥c1€ÏœÁ¼°ÿÅÏ““ÀéÓÎFÁAàÊ+¯ÞÓ§ÝÓúúiÊàß ŠÇo°aÃâ×õÛo €6…úehÈÙoàÆÕW“„æÍ7½w=ù$ @XŽÞxÃ=}Ó&g @@Ç÷žâ=õT`/àÅ©SÀw8s|76nô¾O@('O:g¼–xMxï½@ÎÿI­¦{›7ÿüãïÀÀŽý$7ŽwN {çÛ³xì±À_.  –£G»îrÎ zñüóÀK/ qÉ$€~hõ§LÏ<ã=%$Ç…œVÇÈvïöîêÒéiPŸ~ lßî=Ïg xûmçh˜`„[þ lÛæÝóUÕÙ¸e‹&¯lÛÙ9äòÍœûÿGŽ÷Ý'¬Â+€½{Ÿ~rODœKlÞ,´Â À«¯zù~(|ã‡Wz/ôìÞ <òH(LN|þ¹{ÚÚµÀ‹/†Æá€e_ížþÜs€®“„åÇ š§iZ oí’üpò¤{ÚUW9Ï $Œ×‰âõëCg@-«W“B-€…:NN¸ŒñZ÷ÅH£($€jOQn㜠…póšè ž¾\’¶ø`¶?„Ò(´ "¼CA H €_hYÀƒzçÙ·X³&œàœ7ý{Qa¨V½òxï 8Íþœ†ŠA H € u¡¯V^~Ù;O&CYv}4$‚@H € $€*N&þo;ÏR»dÛ¶]VE';‰‰mÛe¶›&5M{€Šú#„8½ß0I¦ ‚ ‚ ‚ ‚!ÿuç#ÐÌïtÓIEND®B`‚KDocker-5.0/resources/images/restore.png000066400000000000000000000054551252153257300203660ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsBIT|dˆ äIDATxœíÍkSYÇ?·É䥭Ock>š©k…áa|ó µ…A¢ÌFP7ÎBŸ ºRðtUx\XFPñÜ Š eÀ*òÌB†¤‚µ–*µÔÎhÓQ“4MrŸE^lÓ¼ÜsošLïý} ”ÞœsrÎý~ó;'÷œ{.‚ EêwæUWÛêËH Hd^©ìA7àš&ÀCÚ‚½Ð8f€(¸ÕÀ ð"°#:0üžùž´!pÖ6‚»µªB‚´Þe^qH÷ùÞÌËU³ª ÕÀÅ'­sc=7Ÿ‚ÀÀÀÀWßÿý!Ç#†°óóó‰üið‡þý|áq Øt«"‘èü~Ÿ§u–™X,6ç÷û·Ï€PàgŸˆo_|>Ÿ7ÿXÑA_*•"£ëË[)ayÑ4ðx<ÔÕ¾ÄSЩTŠééßI&“ËZ9¡:¸\.Ö®m-h‚‚ˆD¢$‰e¯˜P‰‘H”ÆÆ†%ïúíE±h^t  ‹lE1= @×õ²Ð4ÆÆFêñx> ŸçãÇ>|°½¬¶¿Öù³˜Š.—‹Ï?oÅãYü‹Ñëõàõzhl¬çÍû"­¶¿ù+4M£µu .—«d[[[˜šš¶]$°ÚþZçÏGyòÇçó’HÌ“HÌJÆT?â/Õö×:>&ºH$Röóií¬·¿6ù•º€RÂÅbsh +ìf«í¯Uþb2.‹‘žV6†Ûm¯©«í¯]~¥PÜñøœáѽËåÂåúÌPÚ•‚Õö×*Å~è:D£QChhh´]`µýµÎŸrðz}„Ã3ÌÏ—…z<¼^Ÿí `µýµÊ_Ñ+--­¼~=A<>Wð}¯×Gsóš’¼’±ÚþZç_ˆé+_|ÑÎÛ·Ïd&àóùšiiiAÓ4[ŠÖÛ_‹üŸ hiYCKËš‚ïÙUü…Xm­óƒÌ:†e‰ÂÊG"€C D"€C D"€C D"€C¨Ø‚aeRLNÙÈáŒmmm´µµU».B àpÄG àpÊÞò¿¯¿Æ·aÞ^½½ø6n¬Bµ³ÄÆÇ  "öò%ÿøå—’éËÀ·aS—.1uéRúÿöö´úúhêéÁ U¦æ‚)¢ccÌ>|Høþý´è¯^åÞk;t¨lþ²ôöæÄˆ½zÅÔåËL]¾ |2DÓŽz{ÅËLtlŒðг,<Ÿ@ooÙò–ì¦ëúà±ñq~íè0\Ao0H ¯/%zzð+ä–%üða:¬ß¿ÏÜÄ„á¼_Ž.é²5Mû' v +k€_C¡’N+EÎ==é!†(Itt4-v&¬«¾_{;_-9žoCwz{s!_•¹‰ Þ\¹Â›+Wð®_ŸP®=xW}½©ríB2aúÚµÜÀmîõ는k$üƒÁŸ¾>+uYÄÜë×L߸Aòý{Ç‹ય'ùþ=Ó7nTL|0®™!4õôX©Ë"Ü[oÝ"xüxÅÊ\égë­[¸Š•iT3Cð‡BøÚÛ-U ¾³“/=¢y×.ËeÙæ]»øòÑ#ê;;-—åko7ükÌð•@£}J1šwîL7pËK娙ú-[Ò_;-•£¢•aXé‚dzõömÜ«W›.Ã)¸W¯fëíÛ–ºH­ŒG“Á†înB§O£¹d÷y£h.¡Ó§ièî6•_E+Ã0;ø8<Ìð¾}¤âqå¼N%3¼o‡‡•óªôÿ 8h¶x{玘À YñßÞ¹c*¿ªFJ°2”Ǫø ®‘š,^§⃺FJð‡BxƒÁ¢ï7tu•-CL°ñKco0¨<«¼"¨Xˆ ;ƶÇiÙ½»lb‚O¨ˆß²{7Û?&xìXÁ÷ÍtÑêرcɱæ;Ùtö,uÝ7oŠ ¢*~÷Í›Ôy¨k’¥jwå›ÀÑâgÉ3Yñ-U]€Rñ8S?ý”n´“Å_ˆ®398HÛwß-»ø¦–… ö¡"cÁ>ˆŽÀሎÀሎÀሎÀሎÀሎÀáTÝ©xœÉóç‹ï_îDtÉóçk²0¶ªÈ. éïg¤¿_L¹¥a#ýý5Y]5ä¯ œä­ ¬ÅySHF"Jé‹- u´ Š, 5kUM²˜2ÀôÕ«L J[î&Gš ÄŠ`P7ÁÄÀÓW¯šªŠ)„<àÅÉ“¼»{·d:£wÀL2yá‚™ª¬H&/\(*~£&xw÷./Nž$ü੺˜6€žLòôàA"##Ó¨ÞþÔvø°™ª¬HÚ®Èms‘‘ž<ˆžLVÏÑÑÑÜþµ‰ÙYž|ó ‰ÙÙEi*qĽ“ùç~nb‚èè¨z]T3„‡†ý}þœ§ '“€ˆo+&ГIž8@ôùóEéòµ1TÕ …BÍ»{÷xq℈¯ˆY¼8q‚w÷î-Ic¦P¾/à¿7ݼ¡«‹OŸ–ýP1ª[Ä;ÇÞ`—Ìoé¾€èØXÉýëE|s¨D‚Rçxnb‚hg”ül•Äáû÷• ÏGÄ/ŽŠ J¡ª‘šL 2²ˆøå©„ T5R2ÀìÇJ…gñcÕª6@tlÌÔsƒº»E|E²&0³YtìÕ+¥q€a˜íÿ?3vêTî:P=™dìÔ)S›EƒšV† `6üCz²âÉž=$ffL—á33<Ù³Çðd[!T´2, !}±è·íÛ‰<{f©;yöŒß¶o/x‘G­ ÀlÿŸOdd$ÝÀ2³ˆNäÝÝ»é/H‘É5TƆ `%ü瓇y²w¯¥g7&x²w/‰p¸beÕ̬^ZˆwýzÖîßkÕ*Ó«XìD2Áµjk÷ïÇ»~}ÅÊ5ª™<:ö/Fµ+þ‹³Ü.ûìàr#Jy|üòâïèÀßÑÁß3+¦T¢-Ïù( +x ¯¦ž¼ÊøC!ü¡Ð"CÌfº‹|C„‡†hûöÛ’å•5@ìåKÚÊ=ñ;?¤µ%kˆ¬Ð±ññÜ“Èc/_–ͯ_["¦iÛ€,ÑTæ¯`é\Ìe^2[ã æHáôàOàÒÝ·F•ªÇŸ@"û4Í@àÉì…Ä00DÉDt7àμdÃû’"ýÍO°  AAAAÁ üšsÁVxKIEND®B`‚KDocker-5.0/resources/resources.qrc000066400000000000000000000004731252153257300174440ustar00rootroot00000000000000 images/about.png images/another.png images/close.png images/iconify.png images/kdocker.png images/question.png images/restore.png KDocker-5.0/src/000077500000000000000000000000001252153257300134745ustar00rootroot00000000000000KDocker-5.0/src/application.cpp000066400000000000000000000021541252153257300165050ustar00rootroot00000000000000/* * Copyright (C) 2009 John Schember * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include "application.h" Application::Application(const QString &appId, int &argc, char **argv) : QtSingleApplication(appId, argc, argv) { m_kdocker = 0; } void Application::setKDockerInstance(KDocker *kdocker) { m_kdocker = kdocker; } void Application::close() { if (m_kdocker) { m_kdocker->undockAll(); } quit(); } KDocker-5.0/src/application.h000066400000000000000000000021771252153257300161570ustar00rootroot00000000000000/* * Copyright (C) 2009 John Schember * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #ifndef _APPLICATION_H #define _APPLICATION_H #include #include "kdocker.h" class Application : public QtSingleApplication { Q_OBJECT public: Application(const QString &appId, int &argc, char **argv); void setKDockerInstance(KDocker *kdocker); void close(); private: KDocker *m_kdocker; }; #endif /* _APPLICATION_H */ KDocker-5.0/src/constants.cpp000066400000000000000000000024251252153257300162170ustar00rootroot00000000000000/* * Copyright (C) 2009, 2012, 2015 John Schember * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include "constants.h" const QString Constants::APP_NAME = "KDocker"; const QString Constants::ORG_NAME = "com.kdocker"; const QString Constants::DOM_NAME = "kdocker.com"; const QString Constants::WEBSITE = "http://kdocker.com"; const QString Constants::APP_VERSION = "5.0"; const char *Constants::OPTIONSTRING = "+abd:e:fhi:jklmn:op:qrstvuw:x:"; const QString Constants::ABOUT_MESSAGE = QString("%1 %2\n\n%3").arg(Constants::APP_NAME).arg(Constants::APP_VERSION).arg(Constants::WEBSITE); KDocker-5.0/src/constants.h000066400000000000000000000022631252153257300156640ustar00rootroot00000000000000/* * Copyright (C) 2009 John Schember * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #ifndef _CONSTANTS_H #define _CONSTANTS_H #include #include class Constants : QObject { Q_OBJECT public: static const QString APP_NAME; static const QString ORG_NAME; static const QString DOM_NAME; static const QString WEBSITE; static const QString APP_VERSION; static const char *OPTIONSTRING; static const QString ABOUT_MESSAGE; }; #endif /* _CONSTANTS_H */ KDocker-5.0/src/kdocker.cpp000066400000000000000000000211211252153257300156170ustar00rootroot00000000000000/* * Copyright (C) 2009, 2012 John Schember * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include "constants.h" #include "kdocker.h" #include "trayitemmanager.h" #include #include #define ARG_MAX_LEN 30 #define ARG_PRE_PAD 2 #define ARG_POST_PAD 2 #define MAX_HELP_LINE_LEN 79 KDocker::KDocker() { m_trayItemManager = new TrayItemManager(); } KDocker::~KDocker() { if (m_trayItemManager) { delete m_trayItemManager; m_trayItemManager = 0; } } void KDocker::undockAll() { if (m_trayItemManager) { m_trayItemManager->undockAll(); } } void KDocker::run() { if (m_trayItemManager) { m_trayItemManager->processCommand(QCoreApplication::arguments()); } } void KDocker::handleMessage(const QString &args) { if (m_trayItemManager) { m_trayItemManager->processCommand(args.split("\n")); } } /* * handle arguments that output information to the user. We want to handle * them here so they are printed on the tty that the application is run from. * If we left it up to TrayItemManager with the rest of the arguments these * would be printed on the tty the instance was started on not the instance the * user is calling from. */ void KDocker::preProcessCommand(int argc, char **argv) { int option; optind = 0; // initialise the getopt static while ((option = getopt(argc, argv, Constants::OPTIONSTRING)) != -1) { switch (option) { case '?': printUsage(); ::exit(1); break; case 'a': printAbout(); ::exit(0); break; case 'h': printHelp(); ::exit(0); break; case 'u': printUsage(); ::exit(0); break; case 'v': printVersion(); ::exit(0); break; } } } // It would be much faster to just format help args appropriately but that would // require that translators put new lines in the translation. We just run the args // through this function to format the text properly so they don't have to worry // about it. QString KDocker::formatHelpArgs(QList > commands) { int padding = 0; QString out; // Find the longest arg below max length. for (int i = 0; i < commands.count(); ++i) { int length = commands.at(i).first.length(); if (length > padding && length < ARG_MAX_LEN) { padding = length; } } // Pad spaces before and after the longest arg. padding += ARG_PRE_PAD + ARG_POST_PAD; // Build a formatted string from the arg and its description. for (int i = 0; i < commands.count(); ++i) { QString arg = commands.at(i).first; QString desc = commands.at(i).second; // Add the arg to the output. If it's over our max arg length // start the description on a new line. out += QString(' ').repeated(ARG_PRE_PAD); if (arg.length() < ARG_MAX_LEN) { out += arg.leftJustified(padding - ARG_PRE_PAD, ' '); } else { out += arg + "\n"; out += QString(' ').repeated(padding); } int desc_len = desc.length(); int last_offset = 0; int offset = 0; // Move forward in the string then back until we hit a space to break at. // If we don't find a space in the segment force a split. while (offset < desc_len) { if (offset != 0) { out += QString(' ').repeated(padding); } offset += MAX_HELP_LINE_LEN - padding; if (offset < desc_len) { while (offset > last_offset && desc.at(offset) != ' ') { offset--; } if (offset == last_offset) { offset += MAX_HELP_LINE_LEN - padding; } } else { offset = desc_len; } out += desc.mid(last_offset, offset - last_offset) + '\n'; // Skip any spaces because we're going to start on a new line. while (offset < desc_len && desc.at(offset) == ' ') { offset++; } last_offset = offset; } } return out; } void KDocker::printAbout() { QTextStream out(stdout); out << Constants::ABOUT_MESSAGE << endl; } void KDocker::printHelp() { QTextStream out(stdout); QList > commands; out << tr("Usage: %1 [options] [command] -- [command options]").arg(qApp->applicationName().toLower()) << endl; out << tr("Docks any application into the system tray") << endl; out << endl; out << tr("Command") << endl; out << tr("Run command and dock window") << endl; out << tr("Use -- after command to specify options for command") << endl; out << endl; out << tr("Options") << endl; commands.append(qMakePair(QString("-a"), tr("Show author information"))); commands.append(qMakePair(QString("-b"), tr("Don't warn about non-normal windows (blind mode)"))); commands.append(qMakePair(QString("-d secs"), tr("Maximum time in seconds to allow for command to start and open a window (defaults to 5 sec)"))); commands.append(qMakePair(QString("-e type"), tr("Name matting syntax. Choices are 'n', 'r', 'u', 'w', 'x'. n = normal, substring matching (default). r = regex. u = unix wildcard. w = wildcard. x = W3C XML Schema 1.1."))); commands.append(qMakePair(QString("-f"), tr("Dock window that has focus (active window)"))); commands.append(qMakePair(QString("-h"), tr("Display this help"))); commands.append(qMakePair(QString("-i file"), tr("Set the tray icon to file"))); commands.append(qMakePair(QString("-j"), tr("Case senstive name (title) matching"))); commands.append(qMakePair(QString("-k"), tr("Regex minimal matching"))); commands.append(qMakePair(QString("-l"), tr("Iconify when focus lost"))); commands.append(qMakePair(QString("-m"), tr("Keep application window showing (don't hide on dock)"))); commands.append(qMakePair(QString("-n name"), tr("Match window based on window title"))); commands.append(qMakePair(QString("-o"), tr("Iconify when obscured"))); commands.append(qMakePair(QString("-p secs"), tr("Set ballooning timeout (popup time)"))); commands.append(qMakePair(QString("-q"), tr("Disable ballooning title changes (quiet)"))); commands.append(qMakePair(QString("-r"), tr("Remove this application from the pager"))); commands.append(qMakePair(QString("-s"), tr("Make the window sticky (appears on all desktops)"))); commands.append(qMakePair(QString("-t"), tr("Remove this application from the taskbar"))); commands.append(qMakePair(QString("-v"), tr("Display version"))); commands.append(qMakePair(QString("-w wid"), tr("Window id of the application to dock. Assumes hex number of the form 0x###..."))); commands.append(qMakePair(QString("-x pid"), tr("Process id of the application to dock. Assumes decimal number of the form ###..."))); out << formatHelpArgs(commands); out << endl; out << tr("Bugs and wishes to https://github.com/user-none/KDocker") << endl; out << tr("Project information at https://github.com/user-none/KDocker") << endl; } void KDocker::printUsage() { QTextStream out(stdout); out << tr("Usage: %1 [options] command").arg(qApp->applicationName().toLower()) << endl; out << tr("Try `%1 -h' for more information").arg(qApp->applicationName().toLower()) << endl; } void KDocker::printVersion() { QTextStream out(stdout); out << tr("%1 version: %2").arg(qApp->applicationName()).arg(qApp->applicationVersion()) << endl; out << tr("Using Qt version: %1").arg(qVersion()) << endl; } KDocker-5.0/src/kdocker.h000066400000000000000000000027211252153257300152710ustar00rootroot00000000000000/* * Copyright (C) 2009 John Schember * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #ifndef _KDOCKER_H #define _KDOCKER_H #include #include #include #include #include "trayitemmanager.h" class KDocker : public QObject { Q_OBJECT public: KDocker(); ~KDocker(); void undockAll(); void preProcessCommand(int argc, char **argv); public slots: void run(); private slots: void handleMessage(const QString &args); private: QString formatHelpArgs(QList > commands); void printAbout(); void printHelp(); void printUsage(); void printVersion(); TrayItemManager *m_trayItemManager; }; #endif /* _KDOCKER_H */ KDocker-5.0/src/main.cpp000066400000000000000000000056201252153257300151270ustar00rootroot00000000000000/* * Copyright (C) 2009 John Schember * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include #include #include #include "application.h" #include "constants.h" #include "kdocker.h" static void sighandler(int sig) { Q_UNUSED(sig); dynamic_cast (qApp)->close(); } int main(int argc, char *argv[]) { Application app(Constants::APP_NAME, argc, argv); // setup signal handlers that undock and quit signal(SIGHUP, sighandler); signal(SIGSEGV, sighandler); signal(SIGTERM, sighandler); signal(SIGINT, sighandler); signal(SIGUSR1, sighandler); // Setup the translator QTranslator translator; QString locale = QString("kdocker_%1").arg(QLocale::system().name()); if (!translator.load(locale, TRANSLATIONS_PATH)) { if (!translator.load(locale, "./build/i18n/")) { translator.load(locale, "./i18n/"); } } app.installTranslator(&translator); app.setOrganizationName(Constants::ORG_NAME); app.setOrganizationDomain(Constants::DOM_NAME); app.setApplicationName(Constants::APP_NAME); app.setApplicationVersion(Constants::APP_VERSION); // Quitting will be handled by the TrayItemManager in the KDocker instance. // It will determine when there is nothing left running. app.setQuitOnLastWindowClosed(false); KDocker kdocker; // This can exit the application. We want the output of any help text output // on the tty the instance has started from so we call this here. kdocker.preProcessCommand(argc, argv); // Send the arguments in a message to another instance if there is one. if (app.sendMessage(QCoreApplication::arguments().join("\n"))) { return 0; } // Handle messages from another instance so this can be a single instance app. QObject::connect(&app, SIGNAL(messageReceived(const QString&)), &kdocker, SLOT(handleMessage(const QString&))); // Wait for the Qt event loop to be started before running. QMetaObject::invokeMethod(&kdocker, "run", Qt::QueuedConnection); app.setKDockerInstance(&kdocker); return app.exec(); } KDocker-5.0/src/scanner.cpp000066400000000000000000000074321252153257300156370ustar00rootroot00000000000000/* * Copyright (C) 2009, 2012 John Schember * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include #include #include #include #include #include "scanner.h" #include "xlibutil.h" #include Scanner::Scanner(TrayItemManager *manager) { m_manager = manager; m_timer = new QTimer(); // Check every second if a window has been created. m_timer->setInterval(1000); connect(m_timer, SIGNAL(timeout()), this, SLOT(check())); } Scanner::~Scanner() { delete m_timer; } void Scanner::enqueue(const QString &command, const QStringList &arguments, TrayItemSettings settings, int maxTime, bool checkNormality, const QRegExp &windowName) { qint64 pid = 0; bool started = true; if (maxTime <= 0) { maxTime = 1; } ProcessId processId = {command, 0, settings, 0, maxTime, checkNormality, windowName}; if (!command.isEmpty()) { // Launch the requested application. started = QProcess::startDetached(command, arguments, "", &pid); } if (started) { // Either the application started properly or we are matching by name. processId.pid = static_cast(pid); m_processes.append(processId); m_timer->start(); } else { QMessageBox::information(0, qApp->applicationName(), tr("%1 did not start properly.").arg(command)); } } bool Scanner::isRunning() { return !m_processes.isEmpty(); } void Scanner::check() { QMutableListIterator pi(m_processes); while (pi.hasNext()) { ProcessId id = pi.next(); id.count++; pi.setValue(id); Window w = None; if (id.windowName.isEmpty()) { if (kill(id.pid, 0) == -1) { // PID does not exist; fall back to name matching. id.windowName.setPattern(id.command.split("/").last()); id.windowName.setPatternSyntax(QRegExp::FixedString); pi.setValue(id); } else { // Check based on PID. w = XLibUtil::pidToWid(QX11Info::display(), QX11Info::appRootWindow(), id.checkNormality, id.pid); } } // Use an if instead of else because the windowName could be set previously if the PID does not exist. if (!id.windowName.isEmpty()) { // Check based on window name if the user specified a window name to match with. w = XLibUtil::findWindow(QX11Info::display(), QX11Info::appRootWindow(), id.checkNormality, id.windowName, m_manager->dockedWindows()); } if (w != None) { emit windowFound(w, id.settings); pi.remove(); } else { if (id.count >= id.maxCount) { QMessageBox::information(0, tr("KDocker"), tr("Could not find a matching window for %1 in the specified time: %2 seconds.").arg(id.command).arg(QString::number(id.maxCount))); pi.remove(); } } } if (m_processes.isEmpty()) { m_timer->stop(); emit stopping(); } } KDocker-5.0/src/scanner.h000066400000000000000000000034041252153257300152770ustar00rootroot00000000000000/* * Copyright (C) 2009, 2012, 2015 John Schember * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #ifndef _SCANNER_H #define _SCANNER_H #include #include #include #include #include #include #include "trayitemmanager.h" class TrayItemManager; struct ProcessId { QString command; pid_t pid; TrayItemSettings settings; int count; int maxCount; bool checkNormality; QRegExp windowName; }; // Launches commands and looks for the window ids they create. class Scanner : public QObject { Q_OBJECT public: Scanner(TrayItemManager *manager); ~Scanner(); void enqueue(const QString &command, const QStringList &arguments, TrayItemSettings settings, int maxTime = 30, bool checkNormality = true, const QRegExp &windowName = QRegExp()); bool isRunning(); private slots: void check(); signals: void windowFound(Window, TrayItemSettings); void stopping(); private: TrayItemManager *m_manager; QTimer *m_timer; QList m_processes; }; #endif /* _SCANNER_H */ KDocker-5.0/src/trayitem.cpp000066400000000000000000000450361252153257300160460ustar00rootroot00000000000000/* * Copyright (C) 2009, 2015 John Schember * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include #include #include #include #include #include #include #include #include "trayitem.h" #include "xlibutil.h" TrayItem::TrayItem(Window window) { m_iconified = false; m_customIcon = false; m_skipTaskbar = false; m_skipPager = false; m_sticky = false; m_iconifyMinimized = true; m_iconifyObscure = false; m_iconifyFocusLost = false; m_balloonTimeout = 4000; m_dockedAppName = ""; m_window = window; m_is_restoring = false; Display *display = QX11Info::display(); // Allows events from m_window to be forwarded to the x11EventFilter. XLibUtil::subscribe(display, m_window, StructureNotifyMask | PropertyChangeMask | VisibilityChangeMask | FocusChangeMask); // Store the desktop on which the window is being shown. XLibUtil::getCardinalProperty(display, m_window, XInternAtom(display, "_NET_WM_DESKTOP", True), &m_desktop); readDockedAppName(); updateTitle(); updateIcon(); createContextMenu(); updateToggleAction(); connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason))); } TrayItem::~TrayItem() { // No further interest in events from undocked window. XLibUtil::unSubscribe(QX11Info::display(), m_window); // Only the main menu needs to be deleted. The rest of the menus and actions // are children of this menu and Qt will delete all children. delete m_contextMenu; } bool TrayItem::xcbEventFilter(xcb_generic_event_t *event, xcb_window_t dockedWindow) { if (!isBadWindow() && static_cast(dockedWindow) == m_window) { switch (event-> response_type & ~0x80) { case XCB_FOCUS_OUT: focusLostEvent(); break; case XCB_DESTROY_NOTIFY: destroyEvent(); // return true; break; case XCB_UNMAP_NOTIFY: m_iconified = true; updateToggleAction(); break; case XCB_MAP_NOTIFY: m_iconified = false; updateToggleAction(); break; case XCB_VISIBILITY_NOTIFY: if (reinterpret_cast(event)-> state == XCB_VISIBILITY_FULLY_OBSCURED) { obscureEvent(); } break; case XCB_PROPERTY_NOTIFY: propertyChangeEvent(static_cast(reinterpret_cast(event)-> atom)); break; } } return false; } Window TrayItem::dockedWindow() { return m_window; } void TrayItem::restoreWindow() { if (isBadWindow()) { return; } m_is_restoring = true; Display *display = QX11Info::display(); Window root = QX11Info::appRootWindow(); if (m_iconified) { m_iconified = false; /* * A simple XMapWindow would not do. Some applications that use multiple * windows like xmms (and it's successors) won't redisplay its other * windows (like the playlist, equalizer) since the Withdrawn->Normal * state change code does not map them. So we make the * window go through Withdrawn->Map->Iconify->Normal state. */ XMapWindow(display, m_window); XIconifyWindow(display, m_window, DefaultScreen(display)); XSync(display, False); m_sizeHint.flags = USPosition; XSetWMNormalHints(display, m_window, &m_sizeHint); updateToggleAction(); } XMapRaised(display, m_window); XFlush(display); // Change to the desktop that the window was last on. long l_currDesk[2] = {m_desktop, CurrentTime}; XLibUtil::sendMessage(display, root, root, "_NET_CURRENT_DESKTOP", 32, SubstructureNotifyMask | SubstructureRedirectMask, l_currDesk, sizeof (l_currDesk)); // Set the desktop the window wants to be on. long l_wmDesk[2] = {m_desktop, 1}; // 1 == request sent from application. 2 == from pager XLibUtil::sendMessage(display, root, m_window, "_NET_WM_DESKTOP", 32, SubstructureNotifyMask | SubstructureRedirectMask, l_wmDesk, sizeof (l_wmDesk)); // Make it the active window // 1 == request sent from application. 2 == from pager. // We use 2 because KWin doesn't always give the window focus with 1. long l_active[2] = {2, CurrentTime}; XLibUtil::sendMessage(display, root, m_window, "_NET_ACTIVE_WINDOW", 32, SubstructureNotifyMask | SubstructureRedirectMask, l_active, sizeof (l_active)); XSetInputFocus(display, m_window, RevertToParent, CurrentTime); updateToggleAction(); doSkipTaskbar(); /* * Wait half a second to ensure the window is fully restored. * This and m_is_restoring are a work around for KWin. * KWin is the only WM that will send a PropertyNotify * event with the Iconic state set because of the above * XIconifyWindow call. */ QTime t; t.start(); while (t.elapsed() < 500) { qApp->processEvents(); } m_is_restoring = false; } void TrayItem::iconifyWindow() { if (isBadWindow() || m_is_restoring) { return; } m_iconified = true; /* Get screen number */ Display *display = QX11Info::display(); int screen = DefaultScreen(display); long dummy; XGetWMNormalHints(display, m_window, &m_sizeHint, &dummy); /* * A simple call to XWithdrawWindow wont do. Here is what we do: * 1. Iconify. This will make the application hide all its other windows. For * example, xmms would take off the playlist and equalizer window. * 2. Withdraw the window to remove it from the taskbar. */ XIconifyWindow(display, m_window, screen); // good for effects too XSync(display, False); XWithdrawWindow(display, m_window, screen); updateToggleAction(); } void TrayItem::closeWindow() { if (isBadWindow()) { return; } Display *display = QX11Info::display(); long l[5] = {0, 0, 0, 0, 0}; restoreWindow(); XLibUtil::sendMessage(display, QX11Info::appRootWindow(), m_window, "_NET_CLOSE_WINDOW", 32, SubstructureNotifyMask | SubstructureRedirectMask, l, sizeof (l)); } void TrayItem::doSkipTaskbar() { set_NET_WM_STATE("_NET_WM_STATE_SKIP_TASKBAR", m_skipTaskbar); } void TrayItem::doSkipPager() { set_NET_WM_STATE("_NET_WM_STATE_SKIP_PAGER", m_skipPager); } void TrayItem::doSticky() { set_NET_WM_STATE("_NET_WM_STATE_STICKY", m_sticky); } void TrayItem::setCustomIcon(QString path) { m_customIcon = true; QPixmap customIcon; if (!customIcon.load(path)) { customIcon.load(":/images/question.png"); } setIcon(QIcon(customIcon)); } void TrayItem::selectCustomIcon(bool value) { Q_UNUSED(value); QStringList types; QString supportedTypes; QString path; Q_FOREACH(QByteArray type, QImageReader::supportedImageFormats()) { types << QString(type); } if (types.isEmpty()) { supportedTypes = "All Files (*.*)"; } else { supportedTypes = QString("Images (*.%1);;All Files (*.*)").arg(types.join(" *.")); } path = QFileDialog::getOpenFileName(0, tr("Select Icon"), QDir::homePath(), supportedTypes); if (!path.isEmpty()) { setCustomIcon(path); } } void TrayItem::setSkipTaskbar(bool value) { m_skipTaskbar = value; m_actionSkipTaskbar->setChecked(value); doSkipTaskbar(); } void TrayItem::setSkipPager(bool value) { m_skipPager = value; m_actionSkipPager->setChecked(value); doSkipPager(); } void TrayItem::setSticky(bool value) { m_sticky = value; m_actionSticky->setChecked(value); doSticky(); } void TrayItem::setIconifyMinimized(bool value) { m_iconifyMinimized = value; m_actionIconifyMinimized->setChecked(value); } void TrayItem::setIconifyObscure(bool value) { m_iconifyObscure = value; m_actionIconifyObscure->setChecked(value); } void TrayItem::setIconifyFocusLost(bool value) { m_iconifyFocusLost = value; m_actionIconifyFocusLost->setChecked(value); focusLostEvent(); } void TrayItem::setBalloonTimeout(int value) { if (value < 0) { value = 0; } m_balloonTimeout = value; m_actionBalloonTitleChanges->setChecked(value ? true : false); } void TrayItem::setBalloonTimeout(bool value) { if (!value) { setBalloonTimeout(-1); } else { setBalloonTimeout(4000); } } void TrayItem::toggleWindow() { if (m_iconified || m_window != XLibUtil::activeWindow(QX11Info::display())) { restoreWindow(); } else { iconifyWindow(); } } void TrayItem::trayActivated(QSystemTrayIcon::ActivationReason reason) { if (reason == QSystemTrayIcon::Trigger) { toggleWindow(); } } bool TrayItem::event(QEvent *e) { if (e->type() == QEvent::Wheel) { QWheelEvent *we = static_cast(e); QPoint delta = we->angleDelta(); if (!delta.isNull() && delta.y() != 0) { if (delta.y() > 0) { restoreWindow(); } else { iconifyWindow(); } return true; } } return QSystemTrayIcon::event(e); } void TrayItem::doUndock() { emit undock(this); } void TrayItem::minimizeEvent() { if (m_iconifyMinimized) { iconifyWindow(); } } void TrayItem::destroyEvent() { m_window = 0; emit dead(this); } void TrayItem::propertyChangeEvent(Atom property) { if (isBadWindow()) { return; } Display *display = QX11Info::display(); static Atom WM_NAME = XInternAtom(display, "WM_NAME", True); static Atom WM_ICON = XInternAtom(display, "WM_ICON", True); static Atom WM_STATE = XInternAtom(display, "WM_STATE", True); static Atom _NET_WM_DESKTOP = XInternAtom(display, "_NET_WM_DESKTOP", True); if (property == WM_NAME) { updateTitle(); } else if (property == WM_ICON) { updateIcon(); } else if (property == _NET_WM_DESKTOP) { XLibUtil::getCardinalProperty(display, m_window, _NET_WM_DESKTOP, &m_desktop); } else if (property == WM_STATE) { Atom type = None; int format; unsigned long nitems, after; unsigned char *data = 0; int r = XGetWindowProperty(display, m_window, WM_STATE, 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, &data); if ((r == Success) && data && (*reinterpret_cast (data) == IconicState)) { minimizeEvent(); XFree(data); } } } void TrayItem::obscureEvent() { if (m_iconifyObscure) { iconifyWindow(); } } void TrayItem::focusLostEvent() { // Wait half a second before checking to ensure the window is properly // focused when being restored. QTime t; t.start(); while (t.elapsed() < 500) { qApp->processEvents(); } if (m_iconifyFocusLost && m_window != XLibUtil::activeWindow(QX11Info::display())) { iconifyWindow(); } } void TrayItem::set_NET_WM_STATE(const char *type, bool set) { if (isBadWindow()) { return; } // set, true = add the state to the window. False, remove the state from // the window. Display *display = QX11Info::display(); Atom atom = XInternAtom(display, type, False); qint64 l[2] = {set ? 1 : 0, static_cast(atom)}; XLibUtil::sendMessage(display, QX11Info::appRootWindow(), m_window, "_NET_WM_STATE", 32, SubstructureNotifyMask, l, sizeof (l)); } void TrayItem::readDockedAppName() { if (isBadWindow()) { return; } Display *display = QX11Info::display(); XClassHint ch; if (XGetClassHint(display, m_window, &ch)) { if (ch.res_class) { m_dockedAppName = QString(ch.res_class); } else if (ch.res_name) { m_dockedAppName = QString(ch.res_name); } if (ch.res_class) { XFree(ch.res_class); } if (ch.res_name) { XFree(ch.res_name); } } } /* * Update the title in the tooltip. */ void TrayItem::updateTitle() { if (isBadWindow()) { return; } Display *display = QX11Info::display(); char *windowName = 0; QString title; XFetchName(display, m_window, &windowName); title = windowName; if (windowName) { XFree(windowName); } setToolTip(QString("%1 [%2]").arg(title).arg(m_dockedAppName)); if (m_balloonTimeout > 0) { showMessage(m_dockedAppName, title, QSystemTrayIcon::Information, m_balloonTimeout); } } void TrayItem::updateIcon() { if (isBadWindow() || m_customIcon) { return; } setIcon(createIcon(m_window)); } void TrayItem::updateToggleAction() { QString text; QIcon icon; if (m_iconified) { text = tr("Show %1").arg(m_dockedAppName); icon = QIcon(":/images/restore.png"); } else { text = tr("Hide %1").arg(m_dockedAppName); icon = QIcon(":/images/iconify.png"); } m_actionToggle->setIcon(icon); m_actionToggle->setText(text); } void TrayItem::createContextMenu() { m_contextMenu = new QMenu(); m_contextMenu->addAction(QIcon(":/images/about.png"), tr("About %1").arg(qApp->applicationName()), this, SIGNAL(about())); m_contextMenu->addSeparator(); // Options menu m_optionsMenu = new QMenu(tr("Options"), m_contextMenu); m_actionSetIcon = new QAction(tr("Set icon..."), m_optionsMenu); connect(m_actionSetIcon, SIGNAL(triggered(bool)), this, SLOT(selectCustomIcon(bool))); m_optionsMenu->addAction(m_actionSetIcon); m_actionSkipTaskbar = new QAction(tr("Skip taskbar"), m_optionsMenu); m_actionSkipTaskbar->setCheckable(true); m_actionSkipTaskbar->setChecked(m_skipTaskbar); connect(m_actionSkipTaskbar, SIGNAL(triggered(bool)), this, SLOT(setSkipTaskbar(bool))); m_optionsMenu->addAction(m_actionSkipTaskbar); m_actionSkipPager = new QAction(tr("Skip pager"), m_optionsMenu); m_actionSkipPager->setCheckable(true); m_actionSkipPager->setChecked(m_skipPager); connect(m_actionSkipPager, SIGNAL(triggered(bool)), this, SLOT(setSkipPager(bool))); m_optionsMenu->addAction(m_actionSkipPager); m_actionSticky = new QAction(tr("Sticky"), m_optionsMenu); m_actionSticky->setCheckable(true); m_actionSticky->setChecked(m_sticky); connect(m_actionSticky, SIGNAL(triggered(bool)), this, SLOT(setSticky(bool))); m_optionsMenu->addAction(m_actionSticky); m_actionIconifyMinimized = new QAction(tr("Iconify when minimized"), m_optionsMenu); m_actionIconifyMinimized->setCheckable(true); m_actionIconifyMinimized->setChecked(m_iconifyMinimized); connect(m_actionIconifyMinimized, SIGNAL(triggered(bool)), this, SLOT(setIconifyMinimized(bool))); m_optionsMenu->addAction(m_actionIconifyMinimized); m_actionIconifyObscure = new QAction(tr("Iconify when obscured"), m_optionsMenu); m_actionIconifyObscure->setCheckable(true); m_actionIconifyObscure->setChecked(m_iconifyObscure); connect(m_actionIconifyObscure, SIGNAL(triggered(bool)), this, SLOT(setIconifyObscure(bool))); m_optionsMenu->addAction(m_actionIconifyObscure); m_actionIconifyFocusLost = new QAction(tr("Iconify when focus lost"), m_optionsMenu); m_actionIconifyFocusLost->setCheckable(true); m_actionIconifyFocusLost->setChecked(m_iconifyFocusLost); connect(m_actionIconifyFocusLost, SIGNAL(toggled(bool)), this, SLOT(setIconifyFocusLost(bool))); m_optionsMenu->addAction(m_actionIconifyFocusLost); m_actionBalloonTitleChanges = new QAction(tr("Balloon title changes"), m_optionsMenu); m_actionBalloonTitleChanges->setCheckable(true); m_actionBalloonTitleChanges->setChecked(m_balloonTimeout ? true : false); connect(m_actionBalloonTitleChanges, SIGNAL(triggered(bool)), this, SLOT(setBalloonTimeout(bool))); m_optionsMenu->addAction(m_actionBalloonTitleChanges); m_contextMenu->addMenu(m_optionsMenu); m_contextMenu->addAction(QIcon(":/images/another.png"), tr("Dock Another"), this, SIGNAL(selectAnother())); m_contextMenu->addAction(tr("Undock All"), this, SIGNAL(undockAll())); m_contextMenu->addSeparator(); m_actionToggle = new QAction(tr("Toggle"), m_contextMenu); connect(m_actionToggle, SIGNAL(triggered()), this, SLOT(toggleWindow())); m_contextMenu->addAction(m_actionToggle); m_contextMenu->addAction(tr("Undock"), this, SLOT(doUndock())); m_contextMenu->addAction(QIcon(":/images/close.png"), tr("Close"), this, SLOT(closeWindow())); setContextMenu(m_contextMenu); } QIcon TrayItem::createIcon(Window window) { char **window_icon = 0; if (!window) { return QIcon(); } QPixmap appIcon; Display *display = QX11Info::display(); XWMHints *wm_hints = XGetWMHints(display, window); if (wm_hints != 0) { if (!(wm_hints->flags & IconMaskHint)) wm_hints->icon_mask = None; /* * We act paranoid here. Progams like KSnake has a bug where * IconPixmapHint is set but no pixmap (Actually this happens with * quite a few KDE 3.x programs) X-( */ if ((wm_hints->flags & IconPixmapHint) && (wm_hints->icon_pixmap)) { XpmCreateDataFromPixmap(display, &window_icon, wm_hints->icon_pixmap, wm_hints->icon_mask, 0); } XFree(wm_hints); } if (!window_icon) { appIcon.load(":/images/question.png"); } else { appIcon = QPixmap(const_cast (window_icon)); } if (window_icon) { XpmFree(window_icon); } return QIcon(appIcon); } bool TrayItem::isBadWindow() { Display *display = QX11Info::display(); if (!XLibUtil::isValidWindowId(display, m_window)) { destroyEvent(); return true; } return false; } KDocker-5.0/src/trayitem.h000066400000000000000000000070661252153257300155140ustar00rootroot00000000000000/* * Copyright (C) 2009 John Schember * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #ifndef _TRAYITEM_H #define _TRAYITEM_H #include #include #include #include #include #include #include #include "xlibutil.h" struct TrayItemSettings { QString customIcon; int balloonTimeout; bool iconify; bool skipTaskbar; bool skipPager; bool sticky; bool iconifyObscure; bool iconifyFocusLost; }; class TrayItem : public QSystemTrayIcon { Q_OBJECT public: TrayItem(Window window); ~TrayItem(); Window dockedWindow(); // Pass on all events through this interface bool xcbEventFilter(xcb_generic_event_t *event, xcb_window_t dockedWindow); void restoreWindow(); void iconifyWindow(); void doSkipTaskbar(); void doSkipPager(); void doSticky(); public slots: void closeWindow(); void setCustomIcon(QString path); void selectCustomIcon(bool value); void setSkipTaskbar(bool value); void setSkipPager(bool value); void setSticky(bool value); void setIconifyMinimized(bool value); void setIconifyObscure(bool value); void setIconifyFocusLost(bool value); void setBalloonTimeout(int value); void setBalloonTimeout(bool value); private slots: void toggleWindow(); void trayActivated(QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Trigger); void doUndock(); signals: void selectAnother(); void dead(TrayItem*); void undockAll(); void undock(TrayItem*); void about(); protected: bool event(QEvent *e); private: void minimizeEvent(); void destroyEvent(); void propertyChangeEvent(Atom property); void obscureEvent(); void focusLostEvent(); void set_NET_WM_STATE(const char *type, bool set); void readDockedAppName(); void updateTitle(); void updateIcon(); void updateToggleAction(); void createContextMenu(); QIcon createIcon(Window window); bool isBadWindow(); bool m_iconified; bool m_customIcon; bool m_skipTaskbar; bool m_skipPager; bool m_sticky; bool m_iconifyMinimized; bool m_iconifyObscure; bool m_iconifyFocusLost; int m_balloonTimeout; bool m_is_restoring; // SizeHint of m_window XSizeHints m_sizeHint; // The window that is associated with the tray icon. Window m_window; long m_desktop; QString m_dockedAppName; QMenu *m_contextMenu; QMenu *m_optionsMenu; QAction *m_actionSetIcon; QAction *m_actionSkipTaskbar; QAction *m_actionSkipPager; QAction *m_actionSticky; QAction *m_actionIconifyMinimized; QAction *m_actionIconifyObscure; QAction *m_actionIconifyFocusLost; QAction *m_actionBalloonTitleChanges; QAction *m_actionToggle; }; #endif /* _TRAYITEM_H */ KDocker-5.0/src/trayitemmanager.cpp000066400000000000000000000360541252153257300174010ustar00rootroot00000000000000/* * Copyright (C) 2009, 2012, 2015 John Schember * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include #include #include #include "constants.h" #include "trayitemmanager.h" #include #include #include #include #include #define ESC_key 9 int ignoreXErrors(Display *, XErrorEvent *) { return 0; } TrayItemManager::TrayItemManager() { m_scanner = new Scanner(this); connect(m_scanner, SIGNAL(windowFound(Window, TrayItemSettings)), this, SLOT(dockWindow(Window, TrayItemSettings))); connect(m_scanner, SIGNAL(stopping()), this, SLOT(checkCount())); m_grabInfo.qtimer = new QTimer; m_grabInfo.qloop = new QEventLoop; m_grabInfo.isGrabbing = false; connect(m_grabInfo.qtimer, SIGNAL(timeout()), m_grabInfo.qloop, SLOT(quit())); connect(this, SIGNAL(quitMouseGrab()), m_grabInfo.qloop, SLOT(quit())); // This will prevent x errors from being written to the console. // The isValidWindowId function in util.cpp will generate errors if the // window is not valid while it is checking. XSetErrorHandler(ignoreXErrors); qApp-> installNativeEventFilter(this); } TrayItemManager::~TrayItemManager() { while (!m_trayItems.isEmpty()) { TrayItem *t = m_trayItems.takeFirst(); delete t; } delete m_grabInfo.qtimer; delete m_grabInfo.qloop; delete m_scanner; qApp-> removeNativeEventFilter(this); } /* The X11 Event Filter. Pass on events to the TrayItems that we created. */ bool TrayItemManager::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { Q_UNUSED(eventType); // Platform string; not used Q_UNUSED(result); // Win* OS only static xcb_window_t dockedWindow = 0; // zero: event ignored (default) ... // non-zero: pass to TrayItem::xcbEventFilter switch (static_cast(message)-> response_type & ~0x80) { case XCB_FOCUS_OUT: // -> TrayItem::xcbEventFilter dockedWindow = static_cast(message)-> event; break; case XCB_DESTROY_NOTIFY: // -> TrayItem::xcbEventFilter dockedWindow = static_cast(message)-> window; break; case XCB_UNMAP_NOTIFY: // -> TrayItem::xcbEventFilter dockedWindow = static_cast(message)-> window; break; case XCB_MAP_NOTIFY: // -> TrayItem::xcbEventFilter dockedWindow = static_cast(message)-> window; break; case XCB_VISIBILITY_NOTIFY: // -> TrayItem::xcbEventFilter dockedWindow = static_cast(message)-> window; break; case XCB_PROPERTY_NOTIFY: // -> TrayItem::xcbEventFilter dockedWindow = static_cast(message)-> window; break; case XCB_BUTTON_PRESS: if (m_grabInfo.isGrabbing) { m_grabInfo.isGrabbing = false; // Cancel immediately m_grabInfo.button = static_cast(message)-> detail; m_grabInfo.window = static_cast(message)-> child; emit quitMouseGrab(); // Interrupt QTimer waiting for grab return true; // Event has been handled - don't propagate } break; case XCB_KEY_RELEASE: if (m_grabInfo.isGrabbing) { if (static_cast(message)-> detail == ESC_key) { m_grabInfo.isGrabbing = false; emit quitMouseGrab(); // Interrupt QTimer waiting for grab return true; // Event has been handled - don't propagate } } break; } if (dockedWindow) { // Pass on the event to the tray item with the associated window. QListIterator ti(m_trayItems); static TrayItem *t; while (ti.hasNext()) { t = ti.next(); if (t-> dockedWindow() == static_cast(dockedWindow)) { return t-> xcbEventFilter(static_cast(message), dockedWindow); } } } return false; } void TrayItemManager::processCommand(const QStringList &args) { int option; pid_t pid = 0; Window window = 0; bool checkNormality = true; int maxTime = 5; QRegExp windowName; windowName.setPatternSyntax(QRegExp::FixedString); TrayItemSettings settings; settings.balloonTimeout = 4000; settings.iconify = true; settings.skipTaskbar = false; settings.skipPager = false; settings.sticky = false; settings.iconifyObscure = false; settings.iconifyFocusLost = false; // Turn the QStringList of arguments into something getopt can use. QList bargs; Q_FOREACH(QString s, args) { bargs.append(s.toLocal8Bit()); } int argc = bargs.count(); // Use a const char * here and a const_cast later because it is faster. // Using char * will cause a deep copy. const char *argv[argc + 1]; for (int i = 0; i < argc; i++) { argv[i] = bargs[i].data(); } /* Options: a, h, u, v are all handled by the KDocker class because we * want them to print on the tty the instance was called from. */ optind = 0; // initialise the getopt static while ((option = getopt(argc, const_cast (argv), Constants::OPTIONSTRING)) != -1) { switch (option) { case '?': checkCount(); return; case 'b': checkNormality = false; break; case 'd': maxTime = atoi(optarg); break; case 'e': if (QString::fromLocal8Bit(optarg).compare("n") == 0) { windowName.setPatternSyntax(QRegExp::FixedString); } else if (QString::fromLocal8Bit(optarg).compare("r") == 0) { windowName.setPatternSyntax(QRegExp::RegExp2); } else if (QString::fromLocal8Bit(optarg).compare("u") == 0) { windowName.setPatternSyntax(QRegExp::WildcardUnix); } else if (QString::fromLocal8Bit(optarg).compare("w") == 0) { windowName.setPatternSyntax(QRegExp::Wildcard); } else if (QString::fromLocal8Bit(optarg).compare("x") == 0) { windowName.setPatternSyntax(QRegExp::W3CXmlSchema11); } else { QMessageBox::critical(0, qApp->applicationName(), tr("Invalid name matting option: %1.\n\nChoices are: %2.").arg(optarg).arg("n, r, u, w, x")); checkCount(); return; } case 'f': window = XLibUtil::activeWindow(QX11Info::display()); if (!window) { QMessageBox::critical(0, qApp->applicationName(), tr("Cannot dock the active window because no window has focus.")); checkCount(); return; } break; case 'i': settings.customIcon = QString::fromLocal8Bit(optarg); break; case 'j': windowName.setCaseSensitivity(Qt::CaseSensitive); break; case 'k': windowName.setMinimal(true); break; case 'l': settings.iconifyFocusLost = true; break; case 'm': settings.iconify = false; break; case 'n': windowName.setPattern(QString::fromLocal8Bit(optarg)); break; case 'o': settings.iconifyObscure = true; break; case 'p': settings.balloonTimeout = atoi(optarg) * 1000; // convert to ms break; case 'q': settings.balloonTimeout = 0; // same as '-p 0' break; case 'r': settings.skipPager = true; break; case 's': settings.sticky = true; break; case 't': settings.skipTaskbar = true; break; case 'w': if (((sizeof(optarg) / sizeof(*optarg)) > 2) && ((optarg[1] == 'x') || (optarg[1] == 'X'))) { sscanf(optarg, "%x", reinterpret_cast(&window)); } else { window = static_cast(atoi(optarg)); } if (!XLibUtil::isValidWindowId(QX11Info::display(), window)) { QMessageBox::critical(0, qApp->applicationName(), tr("Invalid window id.")); checkCount(); return; } break; case 'x': pid = atol(optarg); break; } // switch (option) } // while (getopt) if (optind < argc || !windowName.isEmpty()) { // We are either launching an application and or matching by name. QString command; QStringList arguments; // Store the command and it's arguments if the user specified them. if (optind < argc) { command = argv[optind]; for (int i = optind + 1; i < argc; i++) { arguments << QString::fromLocal8Bit(argv[i]); } } // Add the parameters the scanner should use to match. If a command was specified it will be started by the scanner. m_scanner->enqueue(command, arguments, settings, maxTime, checkNormality, windowName); checkCount(); } else { if (!window) { if (pid != 0) { window = XLibUtil::pidToWid(QX11Info::display(), QX11Info::appRootWindow(), checkNormality, pid, dockedWindows()); } else { window = userSelectWindow(checkNormality); } } if (window) { dockWindow(window, settings); } else { // No window was selected or set. checkCount(); } } } void TrayItemManager::dockWindow(Window window, TrayItemSettings settings) { if (isWindowDocked(window)) { QMessageBox::information(0, qApp->applicationName(), tr("This window is already docked.\nClick on system tray icon to toggle docking.")); checkCount(); return; } TrayItem *ti = new TrayItem(window); if (!settings.customIcon.isEmpty()) { ti->setCustomIcon(settings.customIcon); } ti->setBalloonTimeout(settings.balloonTimeout); ti->setSticky(settings.sticky); ti->setSkipPager(settings.skipPager); ti->setSkipTaskbar(settings.skipTaskbar); ti->setIconifyObscure(settings.iconifyObscure); ti->setIconifyFocusLost(settings.iconifyFocusLost); connect(ti, SIGNAL(selectAnother()), this, SLOT(selectAndIconify())); connect(ti, SIGNAL(dead(TrayItem*)), this, SLOT(remove(TrayItem*))); connect(ti, SIGNAL(undock(TrayItem*)), this, SLOT(undock(TrayItem*))); connect(ti, SIGNAL(undockAll()), this, SLOT(undockAll())); connect(ti, SIGNAL(about()), this, SLOT(about())); ti->show(); if (settings.iconify) { ti->iconifyWindow(); } else { if (settings.skipTaskbar) { ti->doSkipTaskbar(); } } m_trayItems.append(ti); } Window TrayItemManager::userSelectWindow(bool checkNormality) { QTextStream out(stdout); out << tr("Select the application/window to dock with the left mouse button.") << endl; out << tr("Click any other mouse button to abort.") << endl; QString error; Window window = XLibUtil::selectWindow(QX11Info::display(), m_grabInfo, error); if (!window) { if (error != QString()) { QMessageBox::critical(0, qApp->applicationName(), error); } checkCount(); return 0; } if (checkNormality) { if (!XLibUtil::isNormalWindow(QX11Info::display(), window)) { if (QMessageBox::warning(0, qApp->applicationName(), tr("The window you are attempting to dock does not seem to be a normal window."), QMessageBox::Abort | QMessageBox::Ignore) == QMessageBox::Abort) { checkCount(); return 0; } } } return window; } void TrayItemManager::remove(TrayItem *trayItem) { m_trayItems.removeAll(trayItem); trayItem->deleteLater(); checkCount(); } void TrayItemManager::undock(TrayItem *trayItem) { trayItem->restoreWindow(); trayItem->setSkipTaskbar(false); trayItem->doSkipTaskbar(); remove(trayItem); } void TrayItemManager::undockAll() { Q_FOREACH(TrayItem *ti, m_trayItems) { undock(ti); } } void TrayItemManager::about() { QMessageBox aboutBox; aboutBox.setIconPixmap(QPixmap(":/images/kdocker.png")); aboutBox.setWindowTitle(tr("About %1 - %2").arg(qApp->applicationName()).arg(qApp->applicationVersion())); aboutBox.setText(Constants::ABOUT_MESSAGE); aboutBox.setInformativeText(tr("See %1 for more information.").arg("https://github.com/user-none/KDocker")); aboutBox.setStandardButtons(QMessageBox::Ok); aboutBox.exec(); } void TrayItemManager::selectAndIconify() { Window window = userSelectWindow(true); if (window) { TrayItemSettings settings; settings.balloonTimeout = 4000; settings.iconify = true; settings.skipTaskbar = false; settings.skipPager = false; settings.sticky = false; settings.iconifyObscure = false; settings.iconifyFocusLost = false; dockWindow(window, settings); } } void TrayItemManager::checkCount() { if (m_trayItems.isEmpty() && !m_scanner->isRunning()) { qApp->quit(); } } QList TrayItemManager::dockedWindows() { QList windows; QListIterator ti(m_trayItems); while (ti.hasNext()) { windows.append(ti.next()->dockedWindow()); } return windows; } bool TrayItemManager::isWindowDocked(Window window) { return dockedWindows().contains(window); } KDocker-5.0/src/trayitemmanager.h000066400000000000000000000037721252153257300170470ustar00rootroot00000000000000/* * Copyright (C) 2009 John Schember * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #ifndef _TRAYITEMMANAGER_H #define _TRAYITEMMANAGER_H #include #include #include #include #include #include "trayitem.h" #include "scanner.h" class Scanner; class TrayItemManager : public QObject, public QAbstractNativeEventFilter { Q_OBJECT // The Scanner needs to know which windows are docked. friend class Scanner; public: TrayItemManager(); ~TrayItemManager(); virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; void processCommand(const QStringList &args); public slots: void dockWindow(Window window, TrayItemSettings settings); Window userSelectWindow(bool checkNormality = true); void remove(TrayItem *trayItem); void undock(TrayItem *trayItem); void undockAll(); void about(); private slots: void selectAndIconify(); void checkCount(); signals: void quitMouseGrab(); private: QList dockedWindows(); bool isWindowDocked(Window window); Scanner *m_scanner; QList m_trayItems; GrabInfo m_grabInfo; }; #endif /* _TRAYITEMMANAGER_H */ KDocker-5.0/src/xlibutil.cpp000066400000000000000000000275621252153257300160500ustar00rootroot00000000000000/* * Copyright (C) 2009, 2012, 2015 John Schember * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include #include #include #include "xlibutil.h" #define BIT0 (1 << 0) #define BIT1 (1 << 1) #define BIT2 (1 << 2) #define BIT3 (1 << 3) /* * Assert validity of the window id. Get window attributes for the heck of it * and see if the request went through. */ bool XLibUtil::isValidWindowId(Display *display, Window w) { XWindowAttributes attrib; return (XGetWindowAttributes(display, w, &attrib) != 0); } /* * Checks if this window is a normal window (i.e) * - Has a WM_STATE * - Not modal window * - Not a purely transient window (with no window type set) * - Not a special window (desktop/menu/util) as indicated in the window type */ bool XLibUtil::isNormalWindow(Display *display, Window w) { Atom type; int format; unsigned long left; Atom *data = NULL; unsigned long nitems; Window transient_for = None; static Atom wmState = XInternAtom(display, "WM_STATE", false); static Atom windowState = XInternAtom(display, "_NET_WM_STATE", false); static Atom modalWindow = XInternAtom(display, "_NET_WM_STATE_MODAL", false); static Atom windowType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", false); static Atom normalWindow = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", false); static Atom dialogWindow = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", false); int ret = XGetWindowProperty(display, w, wmState, 0, 10, false, AnyPropertyType, &type, &format, &nitems, &left, (unsigned char **) & data); if (ret != Success || data == NULL) { if (data != NULL) XFree(data); return false; } if (data) { XFree(data); } ret = XGetWindowProperty(display, w, windowState, 0, 10, false, AnyPropertyType, &type, &format, &nitems, &left, (unsigned char **) & data); if (ret == Success) { unsigned int i; for (i = 0; i < nitems; i++) { if (data[i] == modalWindow) { break; } } XFree(data); if (i < nitems) { return false; } } XGetTransientForHint(display, w, &transient_for); ret = XGetWindowProperty(display, w, windowType, 0, 10, false, AnyPropertyType, &type, &format, &nitems, &left, (unsigned char **) & data); if ((ret == Success) && data) { unsigned int i; for (i = 0; i < nitems; i++) { if (data[i] != normalWindow && data[i] != dialogWindow) { break; } } XFree(data); return (i == nitems); } else { return (transient_for == None); } } /* * Returns the contents of the _NET_WM_PID (which is supposed to contain the * process id of the application that created the window) */ pid_t XLibUtil::pid(Display *display, Window w) { Atom actual_type; int actual_format; unsigned long nitems, leftover; unsigned char *pid; pid_t pid_return = -1; if (XGetWindowProperty(display, w, XInternAtom(display, "_NET_WM_PID", false), 0, 1, false, XA_CARDINAL, &actual_type, &actual_format, &nitems, &leftover, &pid) == Success) { if (pid) { pid_return = *(pid_t *) pid; } XFree(pid); } return pid_return; } Window XLibUtil::pidToWid(Display *display, Window window, bool checkNormality, pid_t epid, QList dockedWindows) { Window w = None; Window root; Window parent; Window *child; unsigned int num_child; if (XQueryTree(display, window, &root, &parent, &child, &num_child) != 0) { for (unsigned int i = 0; i < num_child; i++) { if (epid == pid(display, child[i])) { if (!dockedWindows.contains(child[i])) { if (checkNormality) { if (isNormalWindow(display, child[i])) { return child[i]; } } else { return child[i]; } } } w = pidToWid(display, child[i], checkNormality, epid); if (w != None) { break; } } } return w; } /* * The Grand Window Analyzer. Checks if window w has a expected pid of epid * or a expected name of ename. */ bool XLibUtil::analyzeWindow(Display *display, Window w, const QRegExp &ename) { XClassHint ch; // no plans to analyze windows without a name char *window_name = NULL; if (!XFetchName(display, w, &window_name)) { return false; } if (window_name) { XFree(window_name); } else { return false; } bool this_is_our_man = false; // lets try the program name if (XGetClassHint(display, w, &ch)) { if (QString(ch.res_name).contains(ename)) { this_is_our_man = true; } else if (QString(ch.res_class).contains(ename)) { this_is_our_man = true; } else { // sheer desperation char *wm_name = NULL; XFetchName(display, w, &wm_name); if (wm_name && QString(wm_name).contains(ename)) { this_is_our_man = true; } } if (ch.res_class) { XFree(ch.res_class); } if (ch.res_name) { XFree(ch.res_name); } } // it's probably a good idea to check (obsolete) WM_COMMAND here return this_is_our_man; } /* * Given a starting window look though all children and try to find a window * that matches the ename. */ Window XLibUtil::findWindow(Display *display, Window window, bool checkNormality, const QRegExp &ename, QList dockedWindows) { Window w = None; Window root; Window parent; Window *child; unsigned int num_child; if (XQueryTree(display, window, &root, &parent, &child, &num_child) != 0) { for (unsigned int i = 0; i < num_child; i++) { if (analyzeWindow(display, child[i], ename)) { if (!dockedWindows.contains(child[i])) { if (checkNormality) { if (isNormalWindow(display, child[i])) { return child[i]; } } else { return child[i]; } } } w = findWindow(display, child[i], checkNormality, ename); if (w != None) { break; } } } return w; } /* * Sends ClientMessage to a window. */ void XLibUtil::sendMessage(Display* display, Window to, Window w, const char *type, int format, long mask, void* data, int size) { XEvent ev; memset(&ev, 0, sizeof (ev)); ev.xclient.type = ClientMessage; ev.xclient.window = w; ev.xclient.message_type = XInternAtom(display, type, true); ev.xclient.format = format; memcpy((char *) & ev.xclient.data, (const char *) data, size); XSendEvent(display, to, false, mask, &ev); XSync(display, false); } /* * Returns the id of the currently active window. */ Window XLibUtil::activeWindow(Display * display) { Atom active_window_atom = XInternAtom(display, "_NET_ACTIVE_WINDOW", true); Atom type = None; int format; unsigned long nitems, after; unsigned char *data = NULL; int screen = DefaultScreen(display); Window root = RootWindow(display, screen); int r = XGetWindowProperty(display, root, active_window_atom, 0, 1, false, AnyPropertyType, &type, &format, &nitems, &after, &data); Window w = None; if ((r == Success) && data && (*reinterpret_cast (data) != None)) { w = *(Window *) data; } else { int revert; XGetInputFocus(display, &w, &revert); } return w; } /* * Requests user to select a window by grabbing the mouse. * A left click will select the application. * Clicking any other mouse button or the Escape key will abort the selection. */ Window XLibUtil::selectWindow(Display *display, GrabInfo &grabInfo, QString &error) { int screen = DefaultScreen(display); Window root = RootWindow(display, screen); Cursor cursor = XCreateFontCursor(display, XC_draped_box); if (cursor == None) { error = tr("Failed to create XC_draped_box"); return None; } if (XGrabPointer(display, root, false, ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, cursor, CurrentTime) != GrabSuccess) { error = tr("Failed to grab mouse"); return None; } // // X11 treats Scroll_Lock & Num_Lock as 'modifiers'; each exact combination has to be grabbed // from [ESC + No Modifier] (raw) through to [ESC + CAPS_lock + NUM_lock + SCROLL_lock] // Cannot use 'AnyModifier' here in case, say, CTRL+ESC is in use (results in failure to grab at all) // KeyCode keyEsc = XKeysymToKeycode(display, XK_Escape); for (int b = 0; b < BIT3; b++) { // 000..111 (grab eight Escape key combinations) int modifiers = ((b & BIT0) ? LockMask : 0) | // CAPS_lock ((b & BIT1) ? Mod2Mask : 0) | // NUM_lock ((b & BIT2) ? Mod5Mask : 0); // SCROLL_lock XGrabKey(display, keyEsc, modifiers, root, False, GrabModeAsync, GrabModeAsync); } XSelectInput(display, root, KeyPressMask); XAllowEvents(display, SyncPointer, CurrentTime); grabInfo.window = 0; grabInfo.button = 0; grabInfo.qtimer-> setSingleShot(true); grabInfo.qtimer-> start(20000); // 20 second timeout XSync(display, false); grabInfo.isGrabbing = true; // Enable XCB_BUTTON_PRESS code in event filter grabInfo.qloop-> exec(); // block until button pressed or timeout XUngrabPointer(display, CurrentTime); XUngrabKey(display, keyEsc, AnyModifier, root); XSelectInput(display, root, NoEventMask); XFreeCursor(display, cursor); if (grabInfo.button != Button1 || !grabInfo.window || !grabInfo.qtimer-> isActive()) { return None; } return XmuClientWindow(display, grabInfo.window); } /* * Have events associated with mask for the window set in the X11 Event loop * to the application. */ void XLibUtil::subscribe(Display *display, Window w, long mask) { Window root = RootWindow(display, DefaultScreen(display)); XWindowAttributes attr; XGetWindowAttributes(display, w == None ? root : w, &attr); XSelectInput(display, w == None ? root : w, attr.your_event_mask | mask); XSync(display, false); } void XLibUtil::unSubscribe(Display *display, Window w) { XSelectInput(display, w, NoEventMask); XSync(display, false); } /* * Sets data to the value of the requested window property. */ bool XLibUtil::getCardinalProperty(Display *display, Window w, Atom prop, long *data) { Atom type; int format; unsigned long nitems, bytes; unsigned char *d = NULL; if (XGetWindowProperty(display, w, prop, 0, 1, false, XA_CARDINAL, &type, &format, &nitems, &bytes, &d) == Success && d) { if (data) { *data = *reinterpret_cast (d); } XFree(d); return true; } return false; } KDocker-5.0/src/xlibutil.h000066400000000000000000000045411252153257300155050ustar00rootroot00000000000000/* * Copyright (C) 2009, 2012, 2015 John Schember * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #ifndef _XLIBUTIL_H #define _XLIBUTIL_H #include #include #include #include #include #include #include #include #include #include #undef Bool typedef struct GrabInfo { QTimer *qtimer; QEventLoop *qloop; Window window; unsigned int button; bool isGrabbing; } GrabInfo; class XLibUtil : public QObject { Q_OBJECT public: static bool isNormalWindow(Display *display, Window w); static bool isValidWindowId(Display *display, Window w); static pid_t pid(Display *display, Window w); static Window pidToWid(Display *display, Window window, bool checkNormality, pid_t epid, QList dockedWindows = QList()); static bool analyzeWindow(Display *display, Window w, const QRegExp &ename); static Window findWindow(Display *display, Window w, bool checkNormality, const QRegExp &ename, QList dockedWindows = QList()); static void sendMessage(Display *display, Window to, Window w, const char *type, int format, long mask, void *data, int size); static Window activeWindow(Display *display); static Window selectWindow(Display *display, GrabInfo &grabInfo, QString &error); static void subscribe(Display *display, Window w, long mask); static void unSubscribe(Display *display, Window w); static bool getCardinalProperty(Display *display, Window w, Atom prop, long *data); }; #endif /* _XLIBUTIL_H */