#include "plugin-iface.h"
#define MenuPluginInterface_iid "org.ukui.peony-qt.plugin-iface.MenuPluginInterface"
namespace Peony {
/**
* @brief The MenuPluginInterface class
* @details MenuPluginInterface is a Qt Plugin Interface, the methods of this class must all be
* pure VIRTUAL and has ZERO as return value.
* Otherwise, the plugin will not be loaded correctly.
* For example, if we define a virtual QString method, we must do as this:
*
* virtual QString xxx() = 0;
*
* DO NOT FORGET to initial virtual method in class definition.
*/
class MenuPluginInterface : public PluginInterface
{
public:
/*!
* \brief The Type enum
* \details
* Type is a enum filter which could help you return different actions
* by different menu iface type.
* For example, if you write a desktop background wrapper plugin,
* you should only return your actions when the passing type is
* DesktopBackground.
*/
enum Type {
Invalid,
DirectoryView,
SideBar,
DesktopWindow,
Other
};
Q_DECLARE_FLAGS(Types, Type)
virtual ~MenuPluginInterface() {}
virtual QString testPlugin() = 0;
/*!
* \brief menuActions
* \param types
* \param uri
* \param selectionUris
* \return
* In peony-qt, user can install the menu extensions. This is because
* peony-qt's view/menu frameworks is desgined to be extensible.
* When a peony view context menu was request it will call the plugin's
* menuActions method get the extension actions.
* \note
* A menu can be more than one type, a desktop background menu is also
* could be a directory background menu. This is decied by peony-qt's
* view/menu framework itself.
* You can only implement one type of a menu, but you should never directly
* return the actions without a type check, this might cause actions in menu
* duplicated.
*/
virtual QList menuActions(Types types, const QString &uri, const QStringList &selectionUris) = 0;
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(Peony::MenuPluginInterface::Types)
Q_DECLARE_INTERFACE (Peony::MenuPluginInterface, MenuPluginInterface_iid)
#endif
peony-4.0.0.1/plugin-iface/emblem-plugin-iface.h 0000644 0001750 0001750 00000002453 14551627337 017763 0 ustar feng feng /*
* Peony-Qt
*
* Copyright (C) 2023, KylinSoft Information Technology Co., Ltd.
*
* 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 3 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, see .
*
* Authors: Yue Lan
*
*/
#ifndef EMBLEMPLUGINIFACE_H
#define EMBLEMPLUGINIFACE_H
#include "plugin-iface.h"
#include "peony-core_global.h"
#include "emblem-provider.h"
#define EmblemPluginInterface_iid "org.ukui.peony-qt.plugin-iface.EmblemPluginInterface"
namespace Peony {
class PEONYCORESHARED_EXPORT EmblemPluginInterface : public PluginInterface
{
public:
virtual ~EmblemPluginInterface() {}
virtual EmblemProvider *create() = 0;
};
}
Q_DECLARE_INTERFACE (Peony::EmblemPluginInterface, EmblemPluginInterface_iid)
#endif // EMBLEMPLUGINIFACE_H
peony-4.0.0.1/plugin-iface/vfs-plugin-iface.h 0000644 0001750 0001750 00000005261 14551627337 017320 0 ustar feng feng /*
* Peony-Qt
*
* Copyright (C) 2023, KylinSoft Information Technology Co., Ltd.
*
* 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 3 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, see .
*
* Authors: Yue Lan
*
*/
#ifndef VFSPLUGINIFACE_H
#define VFSPLUGINIFACE_H
#include "plugin-iface.h"
#include "peony-core_global.h"
#include "custom-error-handler.h"
#define VFSPluginInterface_iid "org.ukui.peony-qt.plugin-iface.VFSPluginInterface"
namespace Peony {
class PEONYCORESHARED_EXPORT VFSPluginIface : public PluginInterface {
public:
virtual ~VFSPluginIface() {}
/*!
* \brief uriScheme
* \return
* \details
* indicate the uri scheme you want to register.
*/
virtual QString uriScheme() = 0;
/*!
* \brief holdInSideBar
* \return
* \details
* indicate if it should display as an parent item in sidebar.
*/
virtual bool holdInSideBar() = 0;
/*!
* \brief initVFS
* \details
* peony will init your custom app vfs with this interface at early stage.
* you should call g_vfs_register_uri_scheme() in your own implement to register
* your vfs into peony.
* \note
* you should implement your vfs registion with your uri scheme.
*/
virtual void initVFS() = 0;
/*!
* \brief parseUriToVFSFile
* \param uri
* \return a GFile Handler represent crosponding uri.
* \details
* backup function for while register costom uri scheme is not supported.
* \note
* in old glib version, there is no g_vfs_register_uri_scheme(), and in new
* glib, register a vfs into system is asynchronous, those means it might not be
* registered and can not use GVfsFileLookupFunc to get file handler.
*/
virtual void* parseUriToVFSFile(const QString &uri) = 0;
/*!
* \brief customErrorHandler
* \return
* custom error handler for this vfs. normally it using with FileEnumerator::prepare(),
* and FileEnumerator::handleError().
*/
virtual CustomErrorHandler *customErrorHandler() = 0;
};
}
Q_DECLARE_INTERFACE(Peony::VFSPluginIface, VFSPluginInterface_iid)
#endif // VFSPLUGINIFACE_H
peony-4.0.0.1/plugin-iface/properties-window-tab-iface.h 0000644 0001750 0001750 00000003441 14551627337 021471 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Wenfei He
*
*/
#ifndef PROPERTIESWINDOWTABIFACE_H
#define PROPERTIESWINDOWTABIFACE_H
#include
#include "peony-core_global.h"
#define PropertiesWindowTabIface_iid "org.ukui.peony-qt.plugin-iface.PropertiesWindowTabInterface"
namespace Peony {
class PEONYCORESHARED_EXPORT PropertiesWindowTabIface : public QWidget
{
Q_OBJECT
public:
PropertiesWindowTabIface(QWidget *parent = nullptr) : QWidget(parent){}
virtual ~PropertiesWindowTabIface() {}
PropertiesWindowTabIface();
bool m_thisPageChanged = false;
/*!
* 作为当前页面是否改变的依据
* \brief
*/
virtual void thisPageChanged() {
this->m_thisPageChanged = true;
}
/*!
* \brief 响应确认按钮保存全部数据
*/
virtual void saveAllChange() {};
Q_SIGNALS:
/*!
* 当前tab页面请求关闭窗口
* \brief
*/
void requestCloseMainWindow();
};
}
Q_DECLARE_INTERFACE(Peony::PropertiesWindowTabIface, PropertiesWindowTabIface_iid)
#endif // PROPERTIESWINDOWTABIFACE_H
peony-4.0.0.1/plugin-iface/preview-page-plugin-iface.h 0000644 0001750 0001750 00000003402 14551627337 021110 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef PREVIEWPAGEPLUGINIFACE_H
#define PREVIEWPAGEPLUGINIFACE_H
#include
#include
#include
#include "plugin-iface.h"
#define PreviewPagePluginIface_iid "org.ukui.peony-qt.plugin-iface.PreviewPagePluginInterface"
namespace Peony {
class PreviewPageIface;
class PreviewPagePluginIface : public PluginInterface
{
public:
virtual ~PreviewPagePluginIface() {}
virtual PreviewPageIface *createPreviewPage() = 0;
};
class PreviewPageIface
{
public:
enum PreviewType {
Attribute,
Text,
Pictrue,
PDF,
OfficeDoc,
Other
};
virtual ~PreviewPageIface() {}
virtual void prepare(const QString &uri, PreviewType type) = 0;
virtual void prepare(const QString &uri) = 0;
virtual void startPreview() = 0;
virtual void cancel() = 0;
virtual void closePreviewPage() = 0;
};
}
Q_DECLARE_INTERFACE(Peony::PreviewPagePluginIface, PreviewPagePluginIface_iid)
#endif // PREVIEWPAGEPLUGINIFACE_H
peony-4.0.0.1/plugin-iface/tool-bar-action-plugin-iface.h 0000644 0001750 0001750 00000003031 14551627337 021505 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef TOOLBARACTIONPLUGINIFACE_H
#define TOOLBARACTIONPLUGINIFACE_H
#include "plugin-iface.h"
#include
#define ToolBarActionPluginIface_iid "org.ukui.peony-qt.plugin-iface.ToolBarActionPluginInterface"
namespace Peony {
class ToolBarExtensionActionIface : public QAction
{
Q_OBJECT
~ToolBarExtensionActionIface() {}
public Q_SLOTS:
virtual void excuteAction(const QString &directoryUri,
const QStringList &selectedUris) = 0;
};
class ToolBarActionPluginIface : public PluginInterface
{
public:
~ToolBarActionPluginIface() {}
virtual ToolBarExtensionActionIface *create() = 0;
};
}
Q_DECLARE_INTERFACE(Peony::ToolBarActionPluginIface, ToolBarActionPluginIface_iid)
#endif // TOOLBARACTIONPLUGINIFACE_H
peony-4.0.0.1/plugin-iface/directory-view-plugin-iface.h 0000644 0001750 0001750 00000021336 14551637202 021467 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef DIRECTORYVIEWPLUGINIFACE_H
#define DIRECTORYVIEWPLUGINIFACE_H
#include "plugin-iface.h"
#include
#define DirectoryViewPluginIface_iid "org.ukui.peony-qt.plugin-iface.DirectoryViewPluginInterface"
namespace Peony {
class DirectoryViewIface;
class DirectoryViewProxyIface;
class FileItemModel;
class FileItemProxyFilterSortModel;
/*!
* \brief The DirectoryViewPluginIface class
* \details
* It is a few complex to implement a peony-qt's directory view's plugin.
* There are 3 interface class must to be implemented.
* 1. DirectoryViewPluginIface:
* This is the entry of a plugin, peony-qt's application will dynamicly
* load external view modules when it started. After a plugin loaded
* it will be registered in peony-qt's application globally, then we can
* create such a view by create();
* \see DirectoryViewFactoryManager
*
* 2. DirectoryViewIface:
* This class define a set of methods a dervied class of directory view
* must implement. a dervied view could most be a dervied QAbstractItemView,
* such as QListView or QTreeView, but not certain.
* the directory view must implement these virtual method and make them
* seem worked in there own implement.
* \see DirectoryViewIface
*
* 3. DirectoryViewProxyIface
* \see DirectoryViewProxyIface
*
* \deprecated
* This interface is deprecated, and it should be removed from codes.
*
* To make a directory view extension,
* you have to implement DirectoryViewPluginIface2, not this.
*
* \see
* DirectoryViewPluginIface2
*/
class DirectoryViewPluginIface : public PluginInterface
{
public:
virtual ~DirectoryViewPluginIface() {}
virtual QString viewIdentity() = 0;
virtual QIcon viewIcon() = 0;
virtual bool supportUri(const QString &uri) = 0;
/*!
* \brief zoom_level_hint
* \return the description value of this type of view's zoom level.
* \details
* Peony-Qt doesn't deal the zoom level in a kind of view. Insteadly,
* there is a value for a view for describing its zoom level. Through
* this zoom level, Peony-Qt can realize "zoom in/out" by switch the view's
* type.
*
* We usually use the Peony-Qt's default icon view. Its zoom level hint is 100.
* If you want to implement a larger directory view extension you should set the
* zoom level hint bigger than the default one, vice versa.
*/
virtual int zoom_level_hint() = 0;
/*!
* \brief priority
* \return the priority of view that should be show when went to a location.
* \details
* In Peony-Qt, there are some special view should be shown when we went to some
* special directory, such as computer, it should be shown as a computer view.
* Peony-Qt first judge if it should switch the view if there is a higher-priority
* view than current view when the location change begin.
*
* The default icon view and details view's priority value is 0. If you want to
* implement an extension view replace the current view in some location, you should
* set the priority value larger than the default one.
*/
virtual int priority(const QString &directoryUri) = 0;
virtual DirectoryViewIface *create() = 0;
};
/*!
* \brief The DirectoryViewIface class
* \details
* This class define a set of interface for view operation.
* In peony-qt the directory view is desgin to be extensive,
* and every kind of view will have a global factory to create
* the view's instance. the factories will be managed by peony-qt
* in global, too.
* A peony-qt's file item view will implement this interface.
* \note
* Every DirectoryViewIface instance should have a DirectoryViewProxyIface
* instance, we usually use this proxy control the view.
* \see DirectoryViewProxyIface
*
* \note
* This interface is useless for implement of new directory view extensions, but
* it will be keeped for fitting translations about old view (IconView & ListView) and view's factory to
* new view (IconView2 & ListView2) and factory.
*
* To make a directory view extension,
* you have to implement DirectoryViewPluginIface2, not this.
*
* \see
* DirectoryViewPluginIface2
*/
class DirectoryViewIface
{
public:
virtual ~DirectoryViewIface() {}
virtual void bindModel(FileItemModel *sourceModel, FileItemProxyFilterSortModel *proxyModel) = 0;
virtual void setProxy(DirectoryViewProxyIface *proxy) = 0;
const virtual QString viewId() = 0;
//location
const virtual QString getDirectoryUri() = 0;
//selections
const virtual QStringList getSelections() = 0;
//children
const virtual QStringList getAllFileUris() = 0;
/*
//loaction
void openRequest(const QStringList &uri, bool newWindow);
void viewDirectoryChanged();
void viewSelectionChanged();
//menu
void menuRequest(const QPoint &pos);
//clipboard
void cutSelectionsRequest();
void copySelectionsRequest();
void pasteSelectionsRequest();
//zoom
void zoomedIn();
void zoomedOut();
*/
//location
virtual void open(const QStringList &uris, bool newWindow) = 0;
virtual void setDirectoryUri(const QString &uri) = 0;
virtual void beginLocationChange() = 0;
virtual void stopLocationChange() = 0;
virtual void closeView() = 0;
//selections
virtual void setSelections(const QStringList &uris) = 0;
virtual void invertSelections() = 0;
virtual void scrollToSelection(const QString &uri) = 0;
//clipboard
virtual void setCutFiles(const QStringList &uris) = 0;
virtual DirectoryViewProxyIface *getProxy() = 0;
virtual int getSortType() = 0;
virtual void setSortType(int sortType) = 0;
virtual int getSortOrder() = 0;
virtual void setSortOrder(int sortOrder) = 0;
//edit
virtual void editUri(const QString &uri) = 0;
/*!
* \brief editUris
* \param uris
* \todo
* implement batch rename
*/
virtual void editUris(const QStringList uris) = 0;
};
/*!
* \brief The DirectoryViewProxyIface class
* \deprecated
* This interface is deprecated, and it should be removed from codes.
* To make a directory view extension,
* you have to implement DirectoryViewPluginIface2, not this.
*
* \see
* DirectoryViewPluginIface2
*/
class DirectoryViewProxyIface: public QObject
{
Q_OBJECT
public:
explicit DirectoryViewProxyIface(QObject *parent = nullptr) : QObject(parent) {}
~DirectoryViewProxyIface() {}
virtual void switchView(DirectoryViewIface *view) = 0;
virtual DirectoryViewIface *getView() = 0;
//location
const virtual QString getDirectoryUri() = 0;
//selections
const virtual QStringList getSelections() = 0;
//children
const virtual QStringList getAllFileUris() = 0;
Q_SIGNALS:
//loaction
//FIXME: support open in new TAB?
void openRequest(const QStringList &uri, bool newWindow);
void viewDoubleClicked(const QString &uri);
void viewDirectoryChanged();
void viewSelectionChanged();
//menu
void menuRequest(const QPoint &pos);
//window
void updateWindowLocationRequest(const QString &uri);
virtual int getSortType() = 0;
virtual int getSortOrder() = 0;
public Q_SLOTS:
//location
virtual void open(const QStringList &uris, bool newWindow) = 0;
virtual void setDirectoryUri(const QString &uri) = 0;
virtual void beginLocationChange() = 0;
virtual void stopLocationChange() = 0;
virtual void closeProxy() = 0;
//selections
virtual void setSelections(const QStringList &uris) = 0;
virtual void invertSelections() = 0;
virtual void scrollToSelection(const QString &uri) = 0;
//clipboard
//cut items should be drawn differently.
virtual void setCutFiles(const QStringList &uris) = 0;
virtual void setSortType(int sortType) = 0;
virtual void setSortOrder(int sortOrder) = 0;
virtual void editUri(const QString &uri) = 0;
virtual void editUris(const QStringList uris) = 0;
};
}
Q_DECLARE_INTERFACE(Peony::DirectoryViewPluginIface, DirectoryViewPluginIface_iid)
#endif // DIRECTORYVIEWPLUGINIFACE_H
peony-4.0.0.1/plugin-iface/style-plugin-iface.h 0000644 0001750 0001750 00000002457 14551627337 017666 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef STYLEPLUGINIFACE_H
#define STYLEPLUGINIFACE_H
#include
#include
#include
#include "plugin-iface.h"
#define StylePluginIface_iid "org.ukui.peony-qt.plugin-iface.StylePluginInterface"
class QProxyStyle;
namespace Peony {
class StylePluginIface : public PluginInterface
{
public:
~StylePluginIface() {}
virtual int defaultPriority() = 0;
virtual QProxyStyle *getStyle() = 0;
};
}
Q_DECLARE_INTERFACE(Peony::StylePluginIface, StylePluginIface_iid)
#endif // STYLEPLUGINIFACE_H
peony-4.0.0.1/plugin-iface/directory-view-plugin-iface2.h 0000644 0001750 0001750 00000005630 14551627337 021560 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef DIRECTORYVIEWPLUGINIFACE2_H
#define DIRECTORYVIEWPLUGINIFACE2_H
#include "plugin-iface.h"
#include
#define DirectoryViewPluginIface2_iid "org.ukui.peony-qt.plugin-iface.DirectoryViewPluginInterface2"
namespace Peony {
class DirectoryViewWidget;
/*!
* \brief The DirectoryViewPluginIface2 class
* \details
* This class is a pure virtual interface class. It defines an extensionalbe
* interface for making newly type item view for peony.
*
* There are 2 kinds of internal implement at peony, icon view and list view.
*
* \verbatim
*
* Directory View's Zoom In/Out:
*
* It is not cool that every view zoom in/out in itself at all.
* The zoom of the view should be linked with the view type,
* and the transition should be as smooth as possible.
*
* I defined some rules to indicate how peony zoom its view.
* there are 3 mainly parts:
*
* 1. the default zoom level hint of a view.
* 2. the range for a view can be zoomed.
* 3. wether a view supports zoomed.
*
* Zoom level has a range at 0 to 100. The hint should both contained
* in the range and between view's min zoom level and max zoom level.
*
* Due to all view rebase the rules, there could be a common interface controling
* the zoom of a window.
*
* For some special view, it might could not zoom, it better to indicate
* with a clearly state for that case.
*
* \endverbatim
*
* \see IconView2, ListView2
*/
class DirectoryViewPluginIface2 : public PluginInterface
{
public:
virtual ~DirectoryViewPluginIface2() {}
virtual QString viewIdentity() = 0;
virtual QString viewName() = 0;
virtual QIcon viewIcon() = 0;
virtual bool supportUri(const QString &uri) = 0;
virtual int zoom_level_hint() = 0;
virtual int minimumSupportedZoomLevel() = 0;
virtual int maximumSupportedZoomLevel() = 0;
virtual int priority(const QString &directoryUri) = 0;
virtual bool supportZoom() = 0;
//virtual void fillDirectoryView(DirectoryViewWidget *view) = 0;
virtual DirectoryViewWidget *create() = 0;
};
}
Q_DECLARE_INTERFACE (Peony::DirectoryViewPluginIface2, DirectoryViewPluginIface2_iid)
#endif // DIRECTORYVIEWPLUGINIFACE2_H
peony-4.0.0.1/plugin-iface/plugin-iface.h 0000644 0001750 0001750 00000003140 14551637202 016506 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef PLUGINIFACE_H
#define PLUGINIFACE_H
#include
#include
//#define PluginInterface_iid "org.ukui.peony-qt.PluginInterface"
namespace Peony {
class PluginInterface
{
public:
enum PluginType
{
Invalid,
MenuPlugin,
PreviewPagePlugin,
DirectoryViewPlugin,
DirectoryViewPlugin2,
ToolBarPlugin,
PropertiesWindowPlugin,
ColumnProviderPlugin,
StylePlugin,
VFSPlugin,
EmblemPlugin,
SideBarPlugin,
Other
};
virtual ~PluginInterface() {}
virtual PluginType pluginType() = 0;
virtual const QString name() = 0;
virtual const QString description() = 0;
virtual const QIcon icon() = 0;
virtual void setEnable(bool enable) = 0;
virtual bool isEnable() = 0;
};
}
#endif // PLUGINIFACE_H
peony-4.0.0.1/plugin-iface/properties-window-tab-page-plugin-iface.h 0000644 0001750 0001750 00000003307 14551627337 023700 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef PROPERTIESWINDOWTABPAGEPLUGINIFACE_H
#define PROPERTIESWINDOWTABPAGEPLUGINIFACE_H
#include
#include
#include
#include "plugin-iface.h"
#include "properties-window-tab-iface.h"
class QWidget;
#define PropertiesWindowTabPagePluginIface_iid "org.ukui.peony-qt.plugin-iface.PropertiesWindowTabPagePluginInterface"
namespace Peony {
class PropertiesWindowTabPagePluginIface : public PluginInterface
{
public:
virtual ~PropertiesWindowTabPagePluginIface() {}
virtual int tabOrder() = 0;
virtual bool supportUris(const QStringList &uris) = 0;
// virtual QWidget *createTabPage(const QStringList &uris) = 0;
virtual PropertiesWindowTabIface *createTabPage(const QStringList &uris) = 0;
virtual void closeFactory() = 0;
};
}
Q_DECLARE_INTERFACE(Peony::PropertiesWindowTabPagePluginIface, PropertiesWindowTabPagePluginIface_iid)
#endif // PROPERTIESWINDOWTABPAGEPLUGINIFACE_H
peony-4.0.0.1/3rd-parties/ 0000755 0001750 0001750 00000000000 14551627337 013576 5 ustar feng feng peony-4.0.0.1/3rd-parties/qtsingleapplication/ 0000755 0001750 0001750 00000000000 14551627337 017650 5 ustar feng feng peony-4.0.0.1/3rd-parties/qtsingleapplication/qtlocalpeer.h 0000644 0001750 0001750 00000005205 14551627337 022336 0 ustar feng feng /****************************************************************************
**
** 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
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtsingleapplication.pri 0000644 0001750 0001750 00000001061 14551627337 024434 0 ustar feng feng 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
}
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtlockedfile_win.cpp 0000644 0001750 0001750 00000014661 14551627337 023707 0 ustar feng feng /****************************************************************************
**
** 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);
}
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtlockedfile_unix.cpp 0000644 0001750 0001750 00000006614 14551627337 024074 0 ustar feng feng /****************************************************************************
**
** 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();
}
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtlockedfile.h 0000644 0001750 0001750 00000006307 14551627337 022475 0 ustar feng feng /****************************************************************************
**
** 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
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtsinglecoreapplication.pri 0000644 0001750 0001750 00000000504 14551627337 025306 0 ustar feng feng INCLUDEPATH += $$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)
}
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtsingleapplication.cpp 0000644 0001750 0001750 00000027012 14551627337 024430 0 ustar feng feng /****************************************************************************
**
** 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
*/
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtlockedfile.cpp 0000644 0001750 0001750 00000013742 14551627337 023031 0 ustar feng feng /****************************************************************************
**
** 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.
*/
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtsingleapplication.h 0000644 0001750 0001750 00000007617 14551627337 024106 0 ustar feng feng /****************************************************************************
**
** 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
peony-4.0.0.1/3rd-parties/qtsingleapplication/QtLockedFile 0000644 0001750 0001750 00000000032 14551627337 022074 0 ustar feng feng #include "qtlockedfile.h"
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtlocalpeer.cpp 0000644 0001750 0001750 00000015554 14551627337 022701 0 ustar feng feng /****************************************************************************
**
** 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
#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 (true) {
if (socket->state() == QLocalSocket::UnconnectedState) {
qWarning("QtLocalPeer: Peer disconnected");
delete socket;
socket = nullptr;
return;
}
if (socket->bytesAvailable() >= qint64(sizeof(quint32)))
break;
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;
socket = nullptr;
return;
}
QString message(QString::fromUtf8(uMsg));
socket->write(ack, qstrlen(ack));
socket->waitForBytesWritten(1000);
socket->waitForDisconnected(1000); // make sure client reads ack
delete socket;
socket = nullptr;
Q_EMIT messageReceived(message); //### (might take a long time to return)
}
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtsinglecoreapplication.h 0000644 0001750 0001750 00000005025 14551627337 024746 0 ustar feng feng /****************************************************************************
**
** 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
peony-4.0.0.1/3rd-parties/qtsingleapplication/qtsinglecoreapplication.cpp 0000644 0001750 0001750 00000012355 14551627337 025305 0 ustar feng feng /****************************************************************************
**
** 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()
*/
peony-4.0.0.1/3rd-parties/qtsingleapplication/QtSingleApplication 0000644 0001750 0001750 00000000041 14551627337 023500 0 ustar feng feng #include "qtsingleapplication.h"
peony-4.0.0.1/3rd-parties/SingleApplication/ 0000755 0001750 0001750 00000000000 14551637202 017173 5 ustar feng feng peony-4.0.0.1/3rd-parties/SingleApplication/CMakeLists.txt 0000644 0001750 0001750 00000002531 14551627337 021744 0 ustar feng feng cmake_minimum_required(VERSION 3.1.0)
project(SingleApplication)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
# SingleApplication base class
set(QAPPLICATION_CLASS QCoreApplication CACHE STRING "Inheritance class for SingleApplication")
set_property(CACHE QAPPLICATION_CLASS PROPERTY STRINGS QApplication QGuiApplication QCoreApplication)
# Libary target
add_library(${PROJECT_NAME} STATIC
singleapplication.cpp
singleapplication_p.cpp
)
# Find dependencies
find_package(Qt5Network)
if(QAPPLICATION_CLASS STREQUAL QApplication)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
find_package(Qt5 COMPONENTS Gui REQUIRED)
else()
find_package(Qt5 COMPONENTS Core REQUIRED)
endif()
add_compile_definitions(QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
# Link dependencies
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Network)
if(QAPPLICATION_CLASS STREQUAL QApplication)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets)
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Gui)
else()
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core)
endif()
if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE advapi32)
endif()
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
peony-4.0.0.1/3rd-parties/SingleApplication/singleapplication_p.h 0000644 0001750 0001750 00000006156 14551627337 023410 0 ustar feng feng // The MIT License (MIT)
//
// Copyright (c) Itay Grudev 2015 - 2016
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// W A R N I N G !!!
// -----------------
//
// This file is not part of the SingleApplication API. It is used purely as an
// implementation detail. This header file may change from version to
// version without notice, or may even be removed.
//
#ifndef SINGLEAPPLICATION_P_H
#define SINGLEAPPLICATION_P_H
#include
#include
#include
#include "singleapplication.h"
struct InstancesInfo {
bool primary;
quint32 secondary;
qint64 primaryPid;
quint16 checksum;
};
struct ConnectionInfo {
explicit ConnectionInfo() :
msgLen(0), instanceId(0), stage(0) {}
qint64 msgLen;
quint32 instanceId;
quint8 stage;
};
class SingleApplicationPrivate : public QObject {
Q_OBJECT
public:
enum ConnectionType : quint8 {
InvalidConnection = 0,
NewInstance = 1,
SecondaryInstance = 2,
Reconnect = 3
};
enum ConnectionStage : quint8 {
StageHeader = 0,
StageBody = 1,
StageConnected = 2,
};
Q_DECLARE_PUBLIC(SingleApplication)
SingleApplicationPrivate( SingleApplication *q_ptr );
~SingleApplicationPrivate();
void genBlockServerName(const char *appName);
void initializeMemoryBlock();
void startPrimary();
void startSecondary();
void connectToPrimary(int msecs, ConnectionType connectionType );
quint16 blockChecksum();
qint64 primaryPid();
void readInitMessageHeader(QLocalSocket *socket);
void readInitMessageBody(QLocalSocket *socket);
SingleApplication *q_ptr;
QSharedMemory *memory;
QLocalSocket *socket;
QLocalServer *server;
quint32 instanceNumber;
QString blockServerName;
SingleApplication::Options options;
QMap connectionMap;
public Q_SLOTS:
void slotConnectionEstablished();
void slotDataAvailable( QLocalSocket*, quint32 );
void slotClientConnectionClosed( QLocalSocket*, quint32 );
};
#endif // SINGLEAPPLICATION_P_H
peony-4.0.0.1/3rd-parties/SingleApplication/singleapplication.h 0000644 0001750 0001750 00000011342 14551637202 023052 0 ustar feng feng // The MIT License (MIT)
//
// Copyright (c) Itay Grudev 2015 - 2018
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef SINGLE_APPLICATION_H
#define SINGLE_APPLICATION_H
#include
#include
#ifndef QAPPLICATION_CLASS
#define QAPPLICATION_CLASS QCoreApplication
#endif
#include QT_STRINGIFY(QAPPLICATION_CLASS)
class SingleApplicationPrivate;
/**
* @brief The SingleApplication class handles multiple instances of the same
* Application
* @see QCoreApplication
*/
class SingleApplication : public QAPPLICATION_CLASS
{
Q_OBJECT
typedef QAPPLICATION_CLASS app_t;
public:
/**
* @brief Mode of operation of SingleApplication.
* Whether the block should be user-wide or system-wide and whether the
* primary instance should be notified when a secondary instance had been
* started.
* @note Operating system can restrict the shared memory blocks to the same
* user, in which case the User/System modes will have no effect and the
* block will be user wide.
* @enum
*/
enum Mode {
User = 1 << 0,
System = 1 << 1,
SecondaryNotification = 1 << 2,
ExcludeAppVersion = 1 << 3,
ExcludeAppPath = 1 << 4
};
Q_DECLARE_FLAGS(Options, Mode)
/**
* @brief Intitializes a SingleApplication instance with argc command line
* arguments in argv
* @arg {int &} argc - Number of arguments in argv
* @arg {const char *[]} argv - Supplied command line arguments
* @arg {bool} allowSecondary - Whether to start the instance as secondary
* if there is already a primary instance.
* @arg {Mode} mode - Whether for the SingleApplication block to be applied
* User wide or System wide.
* @arg {int} timeout - Timeout to wait in milliseconds.
* @note argc and argv may be changed as Qt removes arguments that it
* recognizes
* @note Mode::SecondaryNotification only works if set on both the primary
* instance and the secondary instance.
* @note The timeout is just a hint for the maximum time of blocking
* operations. It does not guarantee that the SingleApplication
* initialisation will be completed in given time, though is a good hint.
* Usually 4*timeout would be the worst case (fail) scenario.
* @see See the corresponding QAPPLICATION_CLASS constructor for reference
*/
explicit SingleApplication(int &argc, char *argv[], const char *appName = "SingleApplication", bool allowSecondary = false, Options options = Mode::User, int timeout = 1000 );
~SingleApplication();
/**
* @brief Returns if the instance is the primary instance
* @returns {bool}
*/
bool isPrimary();
/**
* @brief Returns if the instance is a secondary instance
* @returns {bool}
*/
bool isSecondary();
/**
* @brief Returns a unique identifier for the current instance
* @returns {qint32}
*/
quint32 instanceId();
/**
* @brief Returns the process ID (PID) of the primary instance
* @returns {qint64}
*/
qint64 primaryPid();
/**
* @brief Sends a message to the primary instance. Returns true on success.
* @param {int} timeout - Timeout for connecting
* @returns {bool}
* @note sendMessage() will return false if invoked from the primary
* instance.
*/
bool sendMessage( QByteArray message, int timeout = 100 );
Q_SIGNALS:
void instanceStarted();
void receivedMessage( quint32 instanceId, QByteArray message );
private:
SingleApplicationPrivate *d_ptr;
Q_DECLARE_PRIVATE(SingleApplication)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options)
#endif // SINGLE_APPLICATION_H
peony-4.0.0.1/3rd-parties/SingleApplication/Windows.md 0000644 0001750 0001750 00000002636 14551627337 021166 0 ustar feng feng Windows Specific Implementations
================================
Setting the foreground window
-----------------------------
In the `instanceStarted()` example in the `README` we demonstrated how an
application can bring it's primary instance window whenever a second copy
of the application is started.
On Windows the ability to bring the application windows to the foreground is
restricted, see [`AllowSetForegroundWindow()`][AllowSetForegroundWindow] for more
details.
The background process (the primary instance) can bring its windows to the
foreground if it is allowed by the current foreground process (the secondary
instance). To bypass this `SingleApplication` must be initialized with the
`allowSecondary` parameter set to `true` and the `options` parameter must
include `Mode::SecondaryNotification`, See `SingleApplication::Mode` for more
details.
Here is an example:
```cpp
if( app.isSecondary() ) {
// This API requires LIBS += User32.lib to be added to the project
AllowSetForegroundWindow( DWORD( app.primaryPid() ) );
}
if( app.isPrimary() ) {
QObject::connect(
&app,
&SingleApplication::instanceStarted,
this,
&App::instanceStarted
);
}
```
```cpp
void App::instanceStarted() {
QApplication::setActiveWindow( [window/widget to set to the foreground] );
}
```
[AllowSetForegroundWindow]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms632668.aspx
peony-4.0.0.1/3rd-parties/SingleApplication/README.md 0000644 0001750 0001750 00000020242 14551627337 020462 0 ustar feng feng SingleApplication
=================
This is a replacement of the QtSingleApplication for `Qt5`.
Keeps the Primary Instance of your Application and kills each subsequent
instances. It can (if enabled) spawn secondary (non-related to the primary)
instances and can send data to the primary instance from secondary instances.
Usage
-----
The `SingleApplication` class inherits from whatever `Q[Core|Gui]Application`
class you specify via the `QAPPLICATION_CLASS` macro (`QCoreApplication` is the
default). Further usage is similar to the use of the `Q[Core|Gui]Application`
classes.
The library sets up a `QLocalServer` and a `QSharedMemory` block. The first
instance of your Application is your Primary Instance. It would check if the
shared memory block exists and if not it will start a `QLocalServer` and listen
for connections. Each subsequent instance of your application would check if the
shared memory block exists and if it does, it will connect to the QLocalServer
to notify the primary instance that a new instance had been started, after which
it would terminate with status code `0`. In the Primary Instance
`SingleApplication` would emit the `instanceStarted()` signal upon detecting
that a new instance had been started.
The library uses `stdlib` to terminate the program with the `exit()` function.
You can use the library as if you use any other `QCoreApplication` derived
class:
```cpp
#include
#include
int main( int argc, char* argv[] )
{
SingleApplication app( argc, argv );
return app.exec();
}
```
To include the library files I would recommend that you add it as a git
submodule to your project and include it's contents with a `.pri` file. Here is
how:
```bash
git submodule add git@github.com:itay-grudev/SingleApplication.git singleapplication
```
**Qmake:**
Then include the `singleapplication.pri` file in your `.pro` project file.
```qmake
include(singleapplication/singleapplication.pri)
DEFINES += QAPPLICATION_CLASS=QApplication
```
**CMake:**
Then include the subdirectory in your `CMakeLists.txt` project file.
```cmake
set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication")
add_subdirectory(src/third-party/singleapplication)
```
Also don't forget to specify which `QCoreApplication` class your app is using if it
is not `QCoreApplication` as in examples above.
The `Instance Started` signal
------------------------
The SingleApplication class implements a `instanceStarted()` signal. You can
bind to that signal to raise your application's window when a new instance had
been started, for example.
```cpp
// window is a QWindow instance
QObject::connect(
&app,
&SingleApplication::instanceStarted,
&window,
&QWindow::raise
);
```
Using `SingleApplication::instance()` is a neat way to get the
`SingleApplication` instance for binding to it's signals anywhere in your
program.
__Note:__ On Windows the ability to bring the application windows to the
foreground is restricted. See [Windows specific implementations](Windows.md)
for a workaround and an example implementation.
Secondary Instances
-------------------
If you want to be able to launch additional Secondary Instances (not related to
your Primary Instance) you have to enable that with the third parameter of the
`SingleApplication` constructor. The default is `false` meaning no Secondary
Instances. Here is an example of how you would start a Secondary Instance send
a message with the command line arguments to the primary instance and then shut
down.
```cpp
int main(int argc, char *argv[])
{
SingleApplication app( argc, argv, true );
if( app.isSecondary() ) {
app.sendMessage( app.arguments().join(' ')).toUtf8() );
app.exit( 0 );
}
return app.exec();
}
```
*__Note:__ A secondary instance won't cause the emission of the
`instanceStarted()` signal by default. See `SingleApplication::Mode` for more
details.*
You can check whether your instance is a primary or secondary with the following
methods:
```cpp
app.isPrimary();
// or
app.isSecondary();
```
*__Note:__ If your Primary Instance is terminated a newly launched instance
will replace the Primary one even if the Secondary flag has been set.*
API
---
### Members
```cpp
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100 )
```
Depending on whether `allowSecondary` is set, this constructor may terminate
your app if there is already a primary instance running. Additional `Options`
can be specified to set whether the SingleApplication block should work
user-wide or system-wide. Additionally the `Mode::SecondaryNotification` may be
used to notify the primary instance whenever a secondary instance had been
started (disabled by default). `timeout` specifies the maximum time in
milliseconds to wait for blocking operations.
*__Note:__ `argc` and `argv` may be changed as Qt removes arguments that it
recognizes.*
*__Note:__ `Mode::SecondaryNotification` only works if set on both the primary
and the secondary instance.*
*__Note:__ Operating system can restrict the shared memory blocks to the same
user, in which case the User/System modes will have no effect and the block will
be user wide.*
---
```cpp
bool SingleApplication::sendMessage( QByteArray message, int timeout = 100 )
```
Sends `message` to the Primary Instance. Uses `timeout` as a the maximum timeout
in milliseconds for blocking functions
---
```cpp
bool SingleApplication::isPrimary()
```
Returns if the instance is the primary instance.
---
```cpp
bool SingleApplication::isSecondary()
```
Returns if the instance is a secondary instance.
---
```cpp
quint32 SingleApplication::instanceId()
```
Returns a unique identifier for the current instance.
---
```cpp
qint64 SingleApplication::primaryPid()
```
Returns the process ID (PID) of the primary instance.
### Signals
```cpp
void SingleApplication::instanceStarted()
```
Triggered whenever a new instance had been started, except for secondary
instances if the `Mode::SecondaryNotification` flag is not specified.
---
```cpp
void SingleApplication::receivedMessage( quint32 instanceId, QByteArray message )
```
Triggered whenever there is a message received from a secondary instance.
---
### Flags
```cpp
enum SingleApplication::Mode
```
* `Mode::User` - The SingleApplication block should apply user wide. This adds
user specific data to the key used for the shared memory and server name.
This is the default functionality.
* `Mode::System` – The SingleApplication block applies system-wide.
* `Mode::SecondaryNotification` – Whether to trigger `instanceStarted()` even
whenever secondary instances are started.
* `Mode::ExcludeAppPath` – Excludes the application path from the server name
(and memory block) hash.
* `Mode::ExcludeAppVersion` – Excludes the application version from the server
name (and memory block) hash.
*__Note:__ `Mode::SecondaryNotification` only works if set on both the primary
and the secondary instance.*
*__Note:__ Operating system can restrict the shared memory blocks to the same
user, in which case the User/System modes will have no effect and the block will
be user wide.*
---
Versioning
----------
Each major version introduces either very significant changes or is not
backwards compatible with the previous version. Minor versions only add
additional features, bug fixes or performance improvements and are backwards
compatible with the previous release. See [`CHANGELOG.md`](CHANGELOG.md) for
more details.
Implementation
--------------
The library is implemented with a QSharedMemory block which is thread safe and
guarantees a race condition will not occur. It also uses a QLocalSocket to
notify the main process that a new instance had been spawned and thus invoke the
`instanceStarted()` signal and for messaging the primary instance.
Additionally the library can recover from being forcefully killed on *nix
systems and will reset the memory block given that there are no other
instances running.
License
-------
This library and it's supporting documentation are released under
`The MIT License (MIT)` with the exception of the Qt calculator examples which
is distributed under the BSD license.
peony-4.0.0.1/3rd-parties/SingleApplication/singleapplication.pri 0000644 0001750 0001750 00000000544 14551627337 023427 0 ustar feng feng QT += core network
CONFIG += c++11
HEADERS += $$PWD/singleapplication.h \
$$PWD/singleapplication_p.h
SOURCES += $$PWD/singleapplication.cpp \
$$PWD/singleapplication_p.cpp
INCLUDEPATH += $$PWD
win32 {
msvc:LIBS += Advapi32.lib
gcc:LIBS += -ladvapi32
}
DISTFILES += \
$$PWD/README.md \
$$PWD/CHANGELOG.md \
$$PWD/Windows.md
peony-4.0.0.1/3rd-parties/SingleApplication/singleapplication_p.cpp 0000644 0001750 0001750 00000027712 14551627337 023744 0 ustar feng feng // The MIT License (MIT)
//
// Copyright (c) Itay Grudev 2015 - 2018
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// W A R N I N G !!!
// -----------------
//
// This file is not part of the SingleApplication API. It is used purely as an
// implementation detail. This header file may change from version to
// version without notice, or may even be removed.
//
#include
#include
#include
#include
#include
#include
#include
#include
#include "singleapplication.h"
#include "singleapplication_p.h"
#ifdef Q_OS_UNIX
#include
#include
#include
#endif
#ifdef Q_OS_WIN
#include
#include
#endif
SingleApplicationPrivate::SingleApplicationPrivate( SingleApplication *q_ptr )
: q_ptr( q_ptr )
{
server = nullptr;
socket = nullptr;
memory = nullptr;
instanceNumber = -1;
}
SingleApplicationPrivate::~SingleApplicationPrivate()
{
if( socket != nullptr ) {
socket->close();
delete socket;
}
memory->lock();
InstancesInfo* inst = static_cast(memory->data());
if( server != nullptr ) {
server->close();
delete server;
inst->primary = false;
inst->primaryPid = -1;
inst->checksum = blockChecksum();
}
memory->unlock();
delete memory;
}
void SingleApplicationPrivate::genBlockServerName(const char* appName)
{
QCryptographicHash appData( QCryptographicHash::Sha256 );
appData.addData( appName, 17 );
appData.addData( SingleApplication::app_t::applicationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() );
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ) {
appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() );
}
if( ! (options & SingleApplication::Mode::ExcludeAppPath) ) {
#ifdef Q_OS_WIN
appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() );
#else
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
#endif
}
// User level block requires a user specific data in the hash
if( options & SingleApplication::Mode::User ) {
#ifdef Q_OS_WIN
wchar_t username [ UNLEN + 1 ];
// Specifies size of the buffer on input
DWORD usernameLength = UNLEN + 1;
if( GetUserNameW( username, &usernameLength ) ) {
appData.addData( QString::fromWCharArray(username).toUtf8() );
} else {
appData.addData( qgetenv("USERNAME") );
}
#endif
#ifdef Q_OS_UNIX
QByteArray username;
uid_t uid = geteuid();
struct passwd *pw = getpwuid(uid);
if( pw ) {
username = pw->pw_name;
}
if( username.isEmpty() ) {
username = qgetenv("USER");
}
appData.addData(username);
#endif
}
appData.addData(qgetenv("DISPLAY"));
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
// server naming requirements.
blockServerName = appData.result().toBase64().replace("/", "_");
}
void SingleApplicationPrivate::initializeMemoryBlock()
{
InstancesInfo* inst = static_cast( memory->data() );
inst->primary = false;
inst->secondary = 0;
inst->primaryPid = -1;
inst->checksum = blockChecksum();
}
void SingleApplicationPrivate::startPrimary()
{
Q_Q(SingleApplication);
// Successful creation means that no main process exists
// So we start a QLocalServer to listen for connections
QLocalServer::removeServer( blockServerName );
server = new QLocalServer();
// Restrict access to the socket according to the
// SingleApplication::Mode::User flag on User level or no restrictions
if( options & SingleApplication::Mode::User ) {
server->setSocketOptions( QLocalServer::UserAccessOption );
} else {
server->setSocketOptions( QLocalServer::WorldAccessOption );
}
server->listen( blockServerName );
QObject::connect(
server,
&QLocalServer::newConnection,
this,
&SingleApplicationPrivate::slotConnectionEstablished
);
// Reset the number of connections
InstancesInfo* inst = static_cast ( memory->data() );
inst->primary = true;
inst->primaryPid = q->applicationPid();
inst->checksum = blockChecksum();
instanceNumber = 0;
}
void SingleApplicationPrivate::startSecondary()
{
}
void SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType )
{
// Connect to the Local Server of the Primary Instance if not already
// connected.
if( socket == nullptr ) {
socket = new QLocalSocket();
}
// If already connected - we are done;
if( socket->state() == QLocalSocket::ConnectedState )
return;
// If not connect
if( socket->state() == QLocalSocket::UnconnectedState ||
socket->state() == QLocalSocket::ClosingState ) {
socket->connectToServer( blockServerName );
}
// Wait for being connected
if( socket->state() == QLocalSocket::ConnectingState ) {
socket->waitForConnected( msecs );
}
// Initialisation message according to the SingleApplication protocol
if( socket->state() == QLocalSocket::ConnectedState ) {
// Notify the parent that a new instance had been started;
QByteArray initMsg;
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
writeStream.setVersion(QDataStream::Qt_5_6);
#endif
writeStream << blockServerName.toLatin1();
writeStream << static_cast(connectionType);
writeStream << instanceNumber;
quint16 checksum = qChecksum(initMsg.constData(), static_cast(initMsg.length()));
writeStream << checksum;
// The header indicates the message length that follows
QByteArray header;
QDataStream headerStream(&header, QIODevice::WriteOnly);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
headerStream.setVersion(QDataStream::Qt_5_6);
#endif
headerStream << static_cast ( initMsg.length() );
socket->write( header );
socket->write( initMsg );
socket->flush();
socket->waitForBytesWritten( msecs );
}
}
quint16 SingleApplicationPrivate::blockChecksum()
{
return qChecksum(
static_cast ( memory->data() ),
offsetof( InstancesInfo, checksum )
);
}
qint64 SingleApplicationPrivate::primaryPid()
{
qint64 pid;
memory->lock();
InstancesInfo* inst = static_cast( memory->data() );
pid = inst->primaryPid;
memory->unlock();
return pid;
}
/**
* @brief Executed when a connection has been made to the LocalServer
*/
void SingleApplicationPrivate::slotConnectionEstablished()
{
QLocalSocket *nextConnSocket = server->nextPendingConnection();
connectionMap.insert(nextConnSocket, ConnectionInfo());
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose,
[nextConnSocket, this]() {
auto &info = connectionMap[nextConnSocket];
Q_EMIT this->slotClientConnectionClosed( nextConnSocket, info.instanceId );
}
);
QObject::connect(nextConnSocket, &QLocalSocket::disconnected,
[nextConnSocket, this]() {
connectionMap.remove(nextConnSocket);
nextConnSocket->deleteLater();
}
);
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
[nextConnSocket, this]() {
auto &info = connectionMap[nextConnSocket];
switch(info.stage) {
case StageHeader:
readInitMessageHeader(nextConnSocket);
break;
case StageBody:
readInitMessageBody(nextConnSocket);
break;
case StageConnected:
Q_EMIT this->slotDataAvailable( nextConnSocket, info.instanceId );
break;
default:
break;
};
}
);
}
void SingleApplicationPrivate::readInitMessageHeader( QLocalSocket *sock )
{
if (!connectionMap.contains( sock )) {
return;
}
if( sock->bytesAvailable() < ( qint64 )sizeof( quint64 ) ) {
return;
}
QDataStream headerStream( sock );
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
headerStream.setVersion( QDataStream::Qt_5_6 );
#endif
// Read the header to know the message length
quint64 msgLen = 0;
headerStream >> msgLen;
ConnectionInfo &info = connectionMap[sock];
info.stage = StageBody;
info.msgLen = msgLen;
if ( sock->bytesAvailable() >= (qint64) msgLen ) {
readInitMessageBody( sock );
}
}
void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock )
{
Q_Q(SingleApplication);
if (!connectionMap.contains( sock )) {
return;
}
ConnectionInfo &info = connectionMap[sock];
if( sock->bytesAvailable() < ( qint64 )info.msgLen ) {
return;
}
// Read the message body
QByteArray msgBytes = sock->read(info.msgLen);
QDataStream readStream(msgBytes);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
readStream.setVersion( QDataStream::Qt_5_6 );
#endif
// server name
QByteArray latin1Name;
readStream >> latin1Name;
// connection type
ConnectionType connectionType = InvalidConnection;
quint8 connTypeVal = InvalidConnection;
readStream >> connTypeVal;
connectionType = static_cast ( connTypeVal );
// instance id
quint32 instanceId = 0;
readStream >> instanceId;
// checksum
quint16 msgChecksum = 0;
readStream >> msgChecksum;
const quint16 actualChecksum = qChecksum( msgBytes.constData(), static_cast( msgBytes.length() - sizeof( quint16 ) ) );
bool isValid = readStream.status() == QDataStream::Ok &&
QLatin1String(latin1Name) == blockServerName &&
msgChecksum == actualChecksum;
if( !isValid ) {
sock->close();
return;
}
info.instanceId = instanceId;
info.stage = StageConnected;
if( connectionType == NewInstance ||
( connectionType == SecondaryInstance &&
options & SingleApplication::Mode::SecondaryNotification ) )
{
Q_EMIT q->instanceStarted();
}
if (sock->bytesAvailable() > 0) {
Q_EMIT this->slotDataAvailable( sock, instanceId );
}
}
void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId )
{
Q_Q(SingleApplication);
Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() );
}
void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId )
{
if( closedSocket->bytesAvailable() > 0 )
Q_EMIT slotDataAvailable( closedSocket, instanceId );
}
peony-4.0.0.1/3rd-parties/SingleApplication/LICENSE 0000644 0001750 0001750 00000002232 14551627337 020207 0 ustar feng feng The MIT License (MIT)
Copyright (c) Itay Grudev 2015 - 2016
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Note: Some of the examples include code not distributed under the terms of the
MIT License.
peony-4.0.0.1/3rd-parties/SingleApplication/CHANGELOG.md 0000644 0001750 0001750 00000014230 14551627337 021014 0 ustar feng feng Changelog
=========
__3.0.18__
----------
* Fallback to standard QApplication class on iOS and Android systems where
the library is not supported.
__3.0.17__
----------
* Fixed compilation warning/error caused by `geteuid()` on unix based systems.
_Iakov Kirilenko_
* Added CMake support
_Hennadii Chernyshchyk_
__3.0.16__
----------
* Use geteuid and getpwuid to get username on Unix, fallback to environment variable.
_Jonas Kvinge_
__3.0.15__
----------
* Bug Fix: sendMessage() might return false even though data was actually written.
_Jonas Kvinge_
__3.0.14__
----------
* Fixed uninitialised variables in the `SingleApplicationPrivate` constructor.
__3.0.13a__
----------
* Process socket events asynchronously
* Fix undefined variable error on Windows
_Francis Giraldeau_
__3.0.12a__
----------
* Removed signal handling.
__3.0.11a__
----------
* Fixed bug where the message sent by the second process was not received
correctly when the message is sent immediately following a connection.
_Francis Giraldeau_
* Refactored code and implemented shared memory block consistency checks
via `qChecksum()` (CRC-16).
* Explicit `qWarning` and `qCritical` when the library is unable to initialise
correctly.
__3.0.10__
----------
* Removed C style casts and eliminated all clang warnings. Fixed `instanceId`
reading from only one byte in the message deserialization. Cleaned up
serialization code using `QDataStream`. Changed connection type to use
`quint8 enum` rather than `char`.
* Renamed `SingleAppConnectionType` to `ConnectionType`. Added initialization
values to all `ConnectionType` enum cases.
_Jedidiah Buck McCready_
__3.0.9__
---------
* Added SingleApplicationPrivate::primaryPid() as a solution to allow
bringing the primary window of an application to the foreground on
Windows.
_Eelco van Dam from Peacs BV_
__3.0.8__
---------
* Bug fix - changed QApplication::instance() to QCoreApplication::instance()
_Evgeniy Bazhenov_
__3.0.7a__
----------
* Fixed compilation error with Mingw32 in MXE thanks to Vitaly Tonkacheyev.
* Removed QMutex used for thread safe behaviour. The implementation now uses
QCoreApplication::instance() to get an instance to SingleApplication for
memory deallocation.
__3.0.6a__
----------
* Reverted GetUserName API usage on Windows. Fixed bug with missing library.
* Fixed bug in the Calculator example, preventing it's window to be raised
on Windows.
Special thanks to Charles Gunawan.
__3.0.5a__
----------
* Fixed a memory leak in the SingleApplicationPrivate destructor.
_Sergei Moiseev_
__3.0.4a__
----------
* Fixed shadow and uninitialised variable warnings.
_Paul Walmsley_
__3.0.3a__
----------
* Removed Microsoft Windows specific code for getting username due to
multiple problems and compiler differences on Windows platforms. On
Windows the shared memory block in User mode now includes the user's
home path (which contains the user's username).
* Explicitly getting absolute path of the user's home directory as on Unix
a relative path (`~`) may be returned.
__3.0.2a__
----------
* Fixed bug on Windows when username containing wide characters causes the
library to crash.
_Le Liu_
__3.0.1a__
----------
* Allows the application path and version to be excluded from the server name
hash. The following flags were added for this purpose:
* `SingleApplication::Mode::ExcludeAppVersion`
* `SingleApplication::Mode::ExcludeAppPath`
* Allow a non elevated process to connect to a local server created by an
elevated process run by the same user on Windows
* Fixes a problem with upper case letters in paths on Windows
_Le Liu_
__v3.0a__
---------
* Deprecated secondary instances count.
* Added a sendMessage() method to send a message to the primary instance.
* Added a receivedMessage() signal, emitted when a message is received from a
secondary instance.
* The SingleApplication constructor's third parameter is now a bool
specifying if the current instance should be allowed to run as a secondary
instance if there is already a primary instance.
* The SingleApplication constructor accept a fourth parameter specifying if
the SingleApplication block should be User-wide or System-wide.
* SingleApplication no longer relies on `applicationName` and
`organizationName` to be set. It instead concatenates all of the following
data and computes a `SHA256` hash which is used as the key of the
`QSharedMemory` block and the `QLocalServer`. Since at least
`applicationFilePath` is always present there is no need to explicitly set
any of the following prior to initialising `SingleApplication`.
* `QCoreApplication::applicationName`
* `QCoreApplication::applicationVersion`
* `QCoreApplication::applicationFilePath`
* `QCoreApplication::organizationName`
* `QCoreApplication::organizationDomain`
* User name or home directory path if in User mode
* The primary instance is no longer notified when a secondary instance had
been started by default. A `Mode` flag for this feature exists.
* Added `instanceNumber()` which represents a unique identifier for each
secondary instance started. When called from the primary instance will
return `0`.
__v2.4__
--------
* Stability improvements
* Support for secondary instances.
* The library now recovers safely after the primary process has crashed
and the shared memory had not been deleted.
__v2.3__
--------
* Improved pimpl design and inheritance safety.
_Vladislav Pyatnichenko_
__v2.2__
--------
* The `QAPPLICATION_CLASS` macro can now be defined in the file including the
Single Application header or with a `DEFINES+=` statement in the project file.
__v2.1__
--------
* A race condition can no longer occur when starting two processes nearly
simultaneously.
Fix issue [#3](https://github.com/itay-grudev/SingleApplication/issues/3)
__v2.0__
--------
* SingleApplication is now being passed a reference to `argc` instead of a
copy.
Fix issue [#1](https://github.com/itay-grudev/SingleApplication/issues/1)
* Improved documentation.
peony-4.0.0.1/3rd-parties/SingleApplication/singleapplication.cpp 0000644 0001750 0001750 00000013205 14551637202 023405 0 ustar feng feng // The MIT License (MIT)
//
// Copyright (c) Itay Grudev 2015 - 2018
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include
#include
#include
#include
#include
#include "singleapplication.h"
#include "singleapplication_p.h"
/**
* @brief Constructor. Checks and fires up LocalServer or closes the program
* if another instance already exists
* @param argc
* @param argv
* @param {bool} allowSecondaryInstances
*/
SingleApplication::SingleApplication(int &argc, char *argv[], const char* appName, bool allowSecondary, Options options, int timeout )
: app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) )
{
Q_D(SingleApplication);
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
// On Android and iOS since the library is not supported fallback to
// standard QApplication behaviour by simply returning at this point.
qWarning() << "SingleApplication is not supported on Android and iOS systems.";
return;
#endif
// Store the current mode of the program
d->options = options;
// Generating an application ID used for identifying the shared memory
// block and QLocalServer
d->genBlockServerName(appName);
#ifdef Q_OS_UNIX
// By explicitly attaching it and then deleting it we make sure that the
// memory is deleted even after the process has crashed on Unix.
d->memory = new QSharedMemory( d->blockServerName );
d->memory->attach();
delete d->memory;
#endif
// Guarantee thread safe behaviour with a shared memory block.
d->memory = new QSharedMemory( d->blockServerName );
// Create a shared memory block
if( d->memory->create( sizeof( InstancesInfo ) ) ) {
// Initialize the shared memory block
d->memory->lock();
d->initializeMemoryBlock();
d->memory->unlock();
} else {
// Attempt to attach to the memory segment
if( ! d->memory->attach() ) {
qCritical() << "SingleApplication: Unable to attach to shared memory block.";
qCritical() << d->memory->errorString();
delete d;
::exit( EXIT_FAILURE );
}
}
InstancesInfo* inst = static_cast( d->memory->data() );
QTime time;
time.start();
// Make sure the shared memory block is initialised and in consistent state
while( true ) {
d->memory->lock();
if( d->blockChecksum() == inst->checksum ) break;
if( time.elapsed() > 5000 ) {
qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
d->initializeMemoryBlock();
}
d->memory->unlock();
// Random sleep here limits the probability of a collision between two racing apps
qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits::max() );
QThread::sleep( 8 + static_cast ( static_cast ( qrand() ) / RAND_MAX * 10 ) );
}
if( inst->primary == false) {
d->startPrimary();
d->memory->unlock();
return;
}
// Check if another instance can be started
if( allowSecondary ) {
inst->secondary += 1;
inst->checksum = d->blockChecksum();
d->instanceNumber = inst->secondary;
d->startSecondary();
if( d->options & Mode::SecondaryNotification ) {
d->connectToPrimary( timeout, SingleApplicationPrivate::SecondaryInstance );
}
d->memory->unlock();
return;
}
d->memory->unlock();
d->connectToPrimary( timeout, SingleApplicationPrivate::NewInstance );
delete d;
::exit( EXIT_SUCCESS );
}
/**
* @brief Destructor
*/
SingleApplication::~SingleApplication()
{
Q_D(SingleApplication);
delete d;
}
bool SingleApplication::isPrimary()
{
Q_D(SingleApplication);
return d->server != nullptr;
}
bool SingleApplication::isSecondary()
{
Q_D(SingleApplication);
return d->server == nullptr;
}
quint32 SingleApplication::instanceId()
{
Q_D(SingleApplication);
return d->instanceNumber;
}
qint64 SingleApplication::primaryPid()
{
Q_D(SingleApplication);
return d->primaryPid();
}
bool SingleApplication::sendMessage( QByteArray message, int timeout )
{
Q_D(SingleApplication);
// Nobody to connect to
if( isPrimary() ) return false;
// Make sure the socket is connected
d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect );
d->socket->write( message );
bool dataWritten = d->socket->waitForBytesWritten( timeout );
d->socket->flush();
return dataWritten;
}
peony-4.0.0.1/peony-qt-plugin-test/ 0000755 0001750 0001750 00000000000 14551627337 015466 5 ustar feng feng peony-4.0.0.1/peony-qt-plugin-test/directory-view-extensions-plugin-test/ 0000755 0001750 0001750 00000000000 14551627337 025110 5 ustar feng feng ././@LongLink 0000644 0000000 0000000 00000000163 00000000000 011603 L ustar root root peony-4.0.0.1/peony-qt-plugin-test/directory-view-extensions-plugin-test/directory-view-extensions-test-plugin.cpp peony-4.0.0.1/peony-qt-plugin-test/directory-view-extensions-plugin-test/directory-view-extensions-t0000644 0001750 0001750 00000003120 14551627337 032441 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2019, Tianjin KYLIN Information Technology Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#include "directory-view-extensions-test-plugin.h"
#include "directory-view-widget.h"
#include
#include
#include
using namespace Peony;
DirectoryViewExtensionsTestPlugin::DirectoryViewExtensionsTestPlugin(QObject *parent) : QObject(parent)
{
}
//void DirectoryViewExtensionsTestPlugin::fillDirectoryView(DirectoryViewWidget *view)
//{
// auto layout = new QVBoxLayout(view);
// layout->addWidget(new QLabel("test icon view", nullptr));
// view->setLayout(layout);
//}
DirectoryViewWidget *DirectoryViewExtensionsTestPlugin::create()
{
qDebug()<<"create directory view";
auto w = new DirectoryViewWidget;
auto layout = new QVBoxLayout(w);
layout->addWidget(new QLabel("test directory view", w));
w->setLayout(layout);
return w;
}
././@LongLink 0000644 0000000 0000000 00000000161 00000000000 011601 L ustar root root peony-4.0.0.1/peony-qt-plugin-test/directory-view-extensions-plugin-test/directory-view-extensions-test-plugin.h peony-4.0.0.1/peony-qt-plugin-test/directory-view-extensions-plugin-test/directory-view-extensions-t0000644 0001750 0001750 00000004717 14551627337 032456 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2019, Tianjin KYLIN Information Technology Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef DIRECTORYVIEWEXTENSIONSTESTPLUGIN_H
#define DIRECTORYVIEWEXTENSIONSTESTPLUGIN_H
#include "directory-view-extensions-plugin-test_global.h"
#include "directory-view-plugin-iface2.h"
namespace Peony {
class DIRECTORYVIEWEXTENSIONSPLUGINTESTSHARED_EXPORT DirectoryViewExtensionsTestPlugin : public QObject, public DirectoryViewPluginIface2
{
Q_OBJECT
Q_PLUGIN_METADATA(IID DirectoryViewPluginIface2_iid)
Q_INTERFACES(Peony::DirectoryViewPluginIface2)
public:
explicit DirectoryViewExtensionsTestPlugin(QObject *parent = nullptr);
//plugin implement
const QString name() override {
return QObject::tr("Directory View Plugin");
}
PluginType pluginType() override {
return PluginType::DirectoryViewPlugin2;
}
const QString description() override {
return QObject::tr("Show the folder children as icons.");
}
const QIcon icon() override {
return QIcon::fromTheme("folder");
}
void setEnable(bool enable) override {
Q_UNUSED(enable)
}
bool isEnable() override {
return true;
}
//directory view plugin implemeny
QString viewIdentity() override {
return QObject::tr("Directory View Plugin");
}
QIcon viewIcon() override {
return QIcon::fromTheme("folder");
}
bool supportUri(const QString &uri) override {
return !uri.isEmpty();
}
//void fillDirectoryView(DirectoryViewWidget *view) override;
DirectoryViewWidget *create() override;
int zoom_level_hint() override {
return 0;
}
int priority(const QString &) override {
return -1;
}
};
}
#endif // DIRECTORYVIEWEXTENSIONSTESTPLUGIN_H
././@LongLink 0000644 0000000 0000000 00000000170 00000000000 011601 L ustar root root peony-4.0.0.1/peony-qt-plugin-test/directory-view-extensions-plugin-test/directory-view-extensions-plugin-test_global.h peony-4.0.0.1/peony-qt-plugin-test/directory-view-extensions-plugin-test/directory-view-extensions-p0000644 0001750 0001750 00000002271 14551627337 032443 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2019, Tianjin KYLIN Information Technology Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef DIRECTORYVIEWEXTENSIONSPLUGINTEST_GLOBAL_H
#define DIRECTORYVIEWEXTENSIONSPLUGINTEST_GLOBAL_H
#include
#if defined(DIRECTORYVIEWEXTENSIONSPLUGINTEST_LIBRARY)
# define DIRECTORYVIEWEXTENSIONSPLUGINTESTSHARED_EXPORT Q_DECL_EXPORT
#else
# define DIRECTORYVIEWEXTENSIONSPLUGINTESTSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // DIRECTORYVIEWEXTENSIONSPLUGINTEST_GLOBAL_H
././@LongLink 0000644 0000000 0000000 00000000163 00000000000 011603 L ustar root root peony-4.0.0.1/peony-qt-plugin-test/directory-view-extensions-plugin-test/directory-view-extensions-plugin-test.pro peony-4.0.0.1/peony-qt-plugin-test/directory-view-extensions-plugin-test/directory-view-extensions-p0000644 0001750 0001750 00000002622 14551627337 032443 0 ustar feng feng #-------------------------------------------------
#
# Project created by QtCreator 2019-11-18T09:07:42
#
#-------------------------------------------------
QT += widgets
TARGET = directory-view-extensions-plugin-test
TEMPLATE = lib
DEFINES += DIRECTORYVIEWEXTENSIONSPLUGINTEST_LIBRARY
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
include(../../plugin-iface/plugin-iface.pri)
include(../../libpeony-qt/libpeony-qt-header.pri)
PKGCONFIG +=gio-2.0 glib-2.0 gio-unix-2.0
CONFIG += c++11 link_pkgconfig no_keywords
LIBS += -L$$PWD/../../libpeony-qt/ -lpeony-qt
SOURCES += \
directory-view-extensions-test-plugin.cpp
HEADERS += \
directory-view-extensions-test-plugin.h \
directory-view-extensions-plugin-test_global.h
unix {
target.path = $$[QT_INSTALL_LIBS]/peony-extensions
INSTALLS += target
}
peony-4.0.0.1/peony-qt-plugin-test/gtk2-style-enhanced-plugin/ 0000755 0001750 0001750 00000000000 14551627337 022532 5 ustar feng feng peony-4.0.0.1/peony-qt-plugin-test/gtk2-style-enhanced-plugin/gtk2-style-enhanced-plugin_global.h 0000644 0001750 0001750 00000002175 14551627337 031274 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2019, Tianjin KYLIN Information Technology Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef GTK2STYLEENHANCEDPLUGIN_GLOBAL_H
#define GTK2STYLEENHANCEDPLUGIN_GLOBAL_H
#include
#if defined(GTK2STYLEENHANCEDPLUGIN_LIBRARY)
# define GTK2STYLEENHANCEDPLUGINSHARED_EXPORT Q_DECL_EXPORT
#else
# define GTK2STYLEENHANCEDPLUGINSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // GTK2STYLEENHANCEDPLUGIN_GLOBAL_H
peony-4.0.0.1/peony-qt-plugin-test/gtk2-style-enhanced-plugin/gtk2-style-enhanced-plugin.pro 0000644 0001750 0001750 00000002565 14551627337 030330 0 ustar feng feng #-------------------------------------------------
#
# Project created by QtCreator 2019-11-13T10:58:32
#
#-------------------------------------------------
QT += widgets
TARGET = gtk2-style-enhanced-plugin
TEMPLATE = lib
DEFINES += GTK2STYLEENHANCEDPLUGIN_LIBRARY
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
include(../../plugin-iface/plugin-iface.pri)
include(../../libpeony-qt/libpeony-qt-header.pri)
PKGCONFIG +=gio-2.0 glib-2.0 gio-unix-2.0
CONFIG += c++11 link_pkgconfig no_keywords
LIBS += -L$$PWD/../../libpeony-qt/ -lpeony-qt
SOURCES += \
gtk2-style-enhanced-plugin.cpp
HEADERS += \
gtk2-style-enhanced-plugin.h \
gtk2-style-enhanced-plugin_global.h
DESTDIR += ../../testdir
unix {
target.path = $$[QT_INSTALL_LIBS]/peony-extensions
INSTALLS += target
}
peony-4.0.0.1/peony-qt-plugin-test/gtk2-style-enhanced-plugin/gtk2-style-enhanced-plugin.cpp 0000644 0001750 0001750 00000002110 14551627337 030274 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2019, Tianjin KYLIN Information Technology Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#include "gtk2-style-enhanced-plugin.h"
#include "complementary-style.h"
using namespace Peony;
Gtk2StyleEnhancedPlugin::Gtk2StyleEnhancedPlugin(QObject *parent) : QObject(parent)
{
}
QProxyStyle *Gtk2StyleEnhancedPlugin::getStyle()
{
return ComplementaryStyle::getStyle();
}
peony-4.0.0.1/peony-qt-plugin-test/gtk2-style-enhanced-plugin/gtk2-style-enhanced-plugin.h 0000644 0001750 0001750 00000003670 14551627337 027755 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2019, Tianjin KYLIN Information Technology Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef GTK2STYLEENHANCEDPLUGIN_H
#define GTK2STYLEENHANCEDPLUGIN_H
#include "gtk2-style-enhanced-plugin_global.h"
#include
#include
#include "style-plugin-iface.h"
namespace Peony {
class GTK2STYLEENHANCEDPLUGINSHARED_EXPORT Gtk2StyleEnhancedPlugin : public QObject, public StylePluginIface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID StylePluginIface_iid)
Q_INTERFACES(Peony::StylePluginIface)
public:
explicit Gtk2StyleEnhancedPlugin(QObject *parent = nullptr);
PluginInterface::PluginType pluginType() {
return PluginInterface::StylePlugin;
}
const QString name() {
return tr("Gtk theme enhanced extension");
}
const QString description() {
return tr("Improve the gtk-themed controls' style and painting");
}
const QIcon icon() {
return QIcon::fromTheme("utilities-terminal-symbolic");
}
void setEnable(bool enable) {
m_enable = enable;
}
bool isEnable() {
return m_enable;
}
int defaultPriority() {
return 0;
}
QProxyStyle *getStyle();
private:
bool m_enable;
};
}
#endif // GTK2STYLEENHANCEDPLUGIN_H
peony-4.0.0.1/peony-qt-plugin-test/peony-qt-menu-plugin-example/ 0000755 0001750 0001750 00000000000 14551627337 023131 5 ustar feng feng peony-4.0.0.1/peony-qt-plugin-test/peony-qt-menu-plugin-example/menu-plugin-example.h 0000644 0001750 0001750 00000003732 14551627337 027200 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2019, Tianjin KYLIN Information Technology Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#ifndef MENUPLUGINEXAMPLE_H
#define MENUPLUGINEXAMPLE_H
#include "peony-qt-menu-plugin-example_global.h"
#include
#include
#include "menu-plugin-iface.h"
namespace Peony {
class PEONYQTMENUPLUGINEXAMPLESHARED_EXPORT MenuPluginExample : public QObject, public MenuPluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID MenuPluginInterface_iid)
Q_INTERFACES(Peony::MenuPluginInterface)
public:
explicit MenuPluginExample(QObject *parent = nullptr);
PluginInterface::PluginType pluginType() override {
return PluginInterface::MenuPlugin;
}
const QString name() override {
return "testMenuPlugin1";
}
const QString description() override {
return "This is a menu type test plugin";
}
const QIcon icon() override {
return QIcon::fromTheme("search");
}
void setEnable(bool enable) override {
m_enable = enable;
}
bool isEnable() override {
return m_enable;
}
QString testPlugin() override;
QList menuActions(Types types, const QString &uri, const QStringList &selectionUris) override;
private:
bool m_enable;
};
}
#endif // MENUPLUGINEXAMPLE_H
peony-4.0.0.1/peony-qt-plugin-test/peony-qt-menu-plugin-example/peony-qt-menu-plugin-example.pro 0000644 0001750 0001750 00000002270 14551627337 031317 0 ustar feng feng #-------------------------------------------------
#
# Project created by QtCreator 2019-10-29T09:29:17
#
#-------------------------------------------------
QT += widgets
TARGET = peony-qt-menu-plugin-example
TEMPLATE = lib
DEFINES += PEONYQTMENUPLUGINEXAMPLE_LIBRARY
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
include(../../plugin-iface/plugin-iface.pri)
SOURCES += \
menu-plugin-example.cpp
HEADERS += \
menu-plugin-example.h \
peony-qt-menu-plugin-example_global.h
DESTDIR += ../../testdir
unix {
target.path = $$[QT_INSTALL_LIBS]/peony-extensions
INSTALLS += target
}
peony-4.0.0.1/peony-qt-plugin-test/peony-qt-menu-plugin-example/menu-plugin-example.cpp 0000644 0001750 0001750 00000003744 14551627337 027536 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2019, Tianjin KYLIN Information Technology Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see .
*
* Authors: Yue Lan
*
*/
#include "menu-plugin-example.h"
#include
#include
#include
using namespace Peony;
MenuPluginExample::MenuPluginExample(QObject *parent) : QObject(parent)
{
}
QString MenuPluginExample::testPlugin()
{
qDebug()<<"menu test plugin1";
return QString("MenuPluginExample");
}
QList MenuPluginExample::menuActions(Types types, const QString &uri, const QStringList &selectionUris)
{
//return QList();
Q_UNUSED(types);
Q_UNUSED(uri);
Q_UNUSED(selectionUris);
QList actions;
QAction *action = new QAction(QIcon::fromTheme("search"), tr("plugin-sub-menu test"));
actions<parentWidget());
connect(action, &QAction::destroyed, [=]() {
qDebug()<<"delete sub menu";
menu->deleteLater();
});
menu->addAction("sub test1");
menu->addSeparator();
menu->addAction("sub test2");
action->setMenu(menu);
QAction *action2 = new QAction(QIcon::fromTheme("media-eject"), tr("plugin-action test"));
connect(action2, &QAction::triggered, [=]() {
qDebug()<<"action triggered";
});
actions<