Внешние библиотеки вынесены в 3rdparty

This commit is contained in:
Andrey Rodionov 2017-08-04 23:16:38 +03:00
commit a4d78b3009
81 changed files with 2287 additions and 0 deletions

1
include/plugin/iplugin.h Normal file
View File

@ -0,0 +1 @@
#include "../../src/iplugin.h"

View File

@ -0,0 +1 @@
#include "../../src/pluginmanager.h"

124
main.qbs Normal file
View File

@ -0,0 +1,124 @@
import qbs
import qbs.File
import qbs.FileInfo
import qbs.Process
Product {
type: "dynamiclibrary"
property string productname: ""
property string version: "1"
property string description: ""
property string company: ""
property string copyright: ""
property string applicationPath: "bin/"
property string includePath: "include/" + name + "/"
property string docPath: "share/doc/" + name + "/"
Properties {
condition: qbs.targetOS.contains("linux")
property string rLibraryPath: "../lib/" + name + "/"
property string rLibraryTestPath: "../../../lib/" + name + "/"
}
Properties {
condition: qbs.targetOS.contains("windows")
property string rLibraryPath: ""
property string rLibraryTestPath: ""
}
property string pubIncludePath: sourceDirectory + "/../include"
cpp.defines: [
"APP_VERSION=" + "\"" + product.version + "\"",
"APP_COMPANY=" + "\"" + product.company + "\"",
"APP_PRODUCT=" + "\"" + product.productname + "\"",
"APP_DESCRIPTION=" + "\"" + product.description + "\"",
"APP_COPYRIGHT=" + "\"" + product.copyright + "\"",
"APP_NAME=" + "\"" + product.name + "\""
]
Depends { name: "cpp" }
Export {
Depends { name: "cpp" }
cpp.includePaths: product.pubIncludePath
cpp.rpaths: [product.rLibraryPath, product.rLibraryTestPath]
}
Group {
fileTagsFilter: [
"dynamiclibrary",
"dynamiclibrary_symlink",
"dynamiclibrary_import"
]
qbs.install: true
qbs.installDir: product.applicationPath + "/" + product.rLibraryPath
}
FileTagger {
condition: publicInclude.value.length > 0
patterns: publicInclude.value
fileTags: ["publicInclude"]
}
Group {
fileTagsFilter: ["publicInclude"]
qbs.install: true
qbs.installDir: product.includePath
}
Probe {
id: publicInclude
property stringList value
property string prjDir: project.sourceDirectory
property string incDir: product.pubIncludePath + "/" + product.name
property int hack: {
//A bit of a hack to make qbs re-resolve (see QBS-996)
return File.lastModified(prjDir + "/.git/logs/HEAD");
}
configure: {
var list = File.directoryEntries(incDir, File.Files);
for(var dir in list) {
list[dir] = FileInfo.fileName(list[dir]);
}
value = list;
}
}
Probe {
id: version
property string prjDir: project.sourceDirectory
property string prdDir: product.sourceDirectory
property int hack: {
//A bit of a hack to make qbs re-resolve (see QBS-996)
return File.lastModified(prjDir + "/.git/logs/HEAD");
}
configure: {
var cmd;
var args;
if (qbs.targetOS.contains("windows")) {
cmd = "cmd";
args = ["/c", prjDir+"/scripts/version.bat"];
}
if (qbs.targetOS.contains("linux")) {
cmd = "/usr/bin/sh";
args = ["-c", prjDir+"/scripts/version.sh"];
}
var p = new Process();
p.setWorkingDirectory(prdDir)
if (0 === p.exec(cmd, args)) {
found = true;
} else {
found = false;
}
p.close();
}
}
}

6
plugin.qbs Normal file
View File

@ -0,0 +1,6 @@
Project {
references: [
"src/plugin.qbs",
"tests/tests.qbs"
]
}

24
scripts/version.bat Normal file
View File

@ -0,0 +1,24 @@
@echo off
for /f "tokens=*" %%m in ('git rev-list -1 HEAD -- .') do (
set commit=%%m
)
for /f "tokens=*" %%i in ('git describe --tags --always %commit%') do (
set ver=%%i
)
set test=-
if exist src\version.h (
for /F "TOKENS=2,3*" %%j in (version.h) do (
set test=%%j
)
)
for /f "tokens=*" %%k in ('git show -s --format^=format:%%ci %ver%') do (
set datever=%%k
)
if not %test%=="%ver%" (
echo #ifndef VERSION_H > src\version.h
echo #define VERSION_H >> src\version.h
echo #define VER_REV "%datever% (%ver%)" >> src\version.h
echo #endif >> src\version.h
)

15
scripts/version.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/sh
TVER=`cat src/version.h | grep '#define VER_REV'`
COMMIT=`git rev-list -1 HEAD -- .`
VER=`git describe --tags --always $COMMIT`
if [ "$TVER" != "#define VER_REV \"$VER\"" ]; then
DATE_REV=`git show -s --format=format:"%ci" $VER`
echo "#ifndef VERSION_H" > src/version.h
echo "#define VERSION_H" >> src/version.h
echo "#define VER_REV \"$DATE_REV ($VER)\"" >> src/version.h
echo "#endif" >> src/version.h
fi

8
src/clogging.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "clogging.h"
namespace RTPTechGroup {
namespace Plugin {
Q_LOGGING_CATEGORY(lcPlugin,"RTPTechGroup.Plugin")
}}

13
src/clogging.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef CLOGGING_H
#define CLOGGING_H
#include <QtCore/QLoggingCategory>
namespace RTPTechGroup {
namespace Plugin {
Q_DECLARE_LOGGING_CATEGORY(lcPlugin)
}}
#endif // CLOGGING_H

39
src/iplugin.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "iplugin.h"
using namespace RTPTechGroup::Plugin;
IPlugin::IPlugin(const QString& depInterfaces)
{
PluginManager *pluginManager = PluginManager::instance();
m_depModulList = depInterfaces.split(" ");
foreach (const QString &depPlugin, depModulList()) {
if (!depPlugin.isEmpty())
pluginManager->nextLoadPlugins(depPlugin);
}
if (pluginManager->settings())
setSettings(pluginManager->settings());
}
IPlugin::~IPlugin()
{
// NOTE: Возможно надо сделать на цикле for
foreach (IPlugin *plug,PluginManager::instance()->dependentPlugins(this)) {
if (!PluginManager::instance()->dependentPlugins(this).isEmpty())
if (plug)
delete plug;
}
}
void IPlugin::setSettings(QSettings *s){
m_settings = s;
}
QSettings *IPlugin::settings()
{
return m_settings;
}
const QStringList &IPlugin::depModulList() const
{
return m_depModulList;
}

192
src/iplugin.h Normal file
View File

@ -0,0 +1,192 @@
#ifndef IPLUGIN_H
#define IPLUGIN_H
#include <QtPlugin>
#include <QStringList>
#include <QIcon>
#include <QSettings>
#include <QMessageBox>
#include <QDebug>
#include <QDir>
#include <QPluginLoader>
#include <QApplication>
#include "pluginmanager.h"
QT_BEGIN_NAMESPACE
class QWidget;
class QString;
class QStringList;
class QObject;
QT_END_NAMESPACE
#define PLUG_INTERFACES(x) QStringList interfaces(){return QString(#x).split(" ");}
#undef Q_INTERFACES
#define Q_INTERFACES(x) PLUG_INTERFACES(x)
//! Класс плагина
/*! Этот класс предназначен для создания пользовательского
плагина путем наследования данного класса. Работа с
плагинами производится при помощи класса PluginManager
\n
Пример: \n
\b exampleplug.h
\code
#ifndef PLUG_EXAMPLE_H
#define PLUG_EXAMPLE_H
#include <plugin/iplugin.h>
#include <itreedockwidget.h>
class ExamplePlug:
public QObject,
public IPlugin
{
Q_OBJECT
Q_INTERFACES(IPlugin)
Q_PLUGIN_METADATA(
IID "com.RTPTechGroup.Raindrop.Example" FILE "example.json")
#endif
public:
ExamplePlug(QObject *parent = 0);
// IPlugin
//! Получение имени плагина
QString name() {return tr("Пример плагина");}
//! Получение иконки плагина
QIcon icon() {return QIcon(":/example");}
//! Описание продукта
QString product() {return tr("");}
//! Авторские права
QString copyright() {return tr("");}
//! Описание плагина
QString descript() {return tr("");}
//! Категория в которой состоит плагин
QString category() {return tr("");}
//! Версия плагина
QString version() {return tr("");}
//! Производитель плагина
QString vendor() {return tr("");}
MainWindow *window;
};
#endif
\endcode
\b exampleplug.cpp
\code
#include "exampleplug.h"
ExamplePlug::ExamplePlug(QObject *parent):
QObject(parent), IPlugin("IMainWindow ITreeDockWidget")
{
// Получение интерфейса ITreeDockWidget
PluginManager *pluginManager = PluginManager::instance();
ITreeDockWidget *dockWidget
= pluginManager->interfaceObject<ITreeDockWidget*>(
"ITreeDockWidget");
}
void ExamplePlug::readSettings()
{
window->resize(settings->value("size", QSize(687, 582)).toSize());
}
void ExamplePlug::writeSettings()
{
settings->setValue("size", window->size());
}
Q_EXPORT_PLUGIN2(example, ExamplePlug)
\endcode
*/
class PLUGINLIB IPlugin
{
public:
//! Конструктор плагина
explicit IPlugin(const QString &depInterfaces);
//! Деструктор плагина
virtual ~IPlugin();
//! Получение экземпляра
virtual QObject *instance() {return dynamic_cast<QObject *>(this);}
//! Получение экземпляра с приведением типа
template<typename T> T instance() {return dynamic_cast<T>(this);}
//! Получение определенных интерфейсов
virtual QStringList interfaces() = 0;
//! Список зависимостей плагина
/*! Список плагинов от которых зависит текущий плагин
*/
const QStringList& depModulList() const;
//! Устанавливает ссылку на объект для сохранения настроек
virtual void setSettings(QSettings *settings);
//! Получает ссылку на объект для сохранения настроек
virtual QSettings *settings();
//! Получение имени плагина
/*! Получение наименования плагина для
отображения
*/
virtual QString name() = 0;
//! Получение иконки плагина
/*! Получение иконки плагина для
отображения
*/
virtual QIcon icon() = 0;
//! Описание плагина
/*! Получение описания плагина для
отображения
*/
virtual QString descript() = 0;
//! Категория в которой состоит плагин
/*! Категория плагинов предназначена для группировки плагинов
* по смыслу в одну группу.
*/
virtual QString category() = 0;
//! Версия плагина
virtual QString version() = 0;
//! Производитель плагина
virtual QString vendor() = 0;
//! Описание продукта
virtual QString product() = 0;
//! Авторские права
virtual QString copyright() = 0;
private:
//! Настройки
QSettings *m_settings;
//! Список зависимостей плагина
QStringList m_depModulList;
};
QT_BEGIN_NAMESPACE
#define IPlugin_iid "com.RTPTechGroup.Raindrop.IPlugin"
Q_DECLARE_INTERFACE(IPlugin, IPlugin_iid)
QT_END_NAMESPACE
#endif

15
src/plugin.pro Normal file
View File

@ -0,0 +1,15 @@
VERSION = 1.0.0
QMAKE_TARGET_COMPANY = "RTPTechGroup"
QMAKE_TARGET_PRODUCT = "Plugin Library"
QMAKE_TARGET_DESCRIPTION = "Plugin Library"
QMAKE_TARGET_COPYRIGHT = "Copyright (C) RTPTechGroup"
include(../libs.pri)
DEFINES += PLUGIN_LIBRARY
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
}
HEADERS = *.h
SOURCES = *.cpp

23
src/plugin.qbs Normal file
View File

@ -0,0 +1,23 @@
import "../main.qbs" as LibProduct
LibProduct {
name: "plugin"
productname: "Plugin Library"
version: "1.0.0"
description: "Plugin Library"
company: "RTPTechGroup"
copyright: "Copyright (C) RTPTechGroup"
cpp.defines: base.concat([
"PLUGIN_LIBRARY"
])
Depends { name: "Qt"; submodules: ["widgets"] }
files: [
"*.h",
"*.cpp",
"*.ui",
"*.qrc"
]
}

7
src/pluginglobal.h Normal file
View File

@ -0,0 +1,7 @@
#include <QtCore/QtGlobal>
#if defined(PLUGIN_LIBRARY)
# define PLUGINLIB Q_DECL_EXPORT
#else
# define PLUGINLIB Q_DECL_IMPORT
#endif

181
src/pluginmanager.cpp Normal file
View File

@ -0,0 +1,181 @@
#include "pluginmanager.h"
#include <QRegExp>
#include "clogging.h"
namespace RTPTechGroup {
namespace Plugin {
PluginManager::PluginManager(QObject *parent) :
QObject(parent)
{
m_instance = this;
m_settings = NULL;
m_lockFiles = NULL;
m_pluginsDir = QDir(qApp->applicationDirPath() + "/plugins/");
}
PluginManager *PluginManager::m_instance = 0;
PluginManager *PluginManager::instance()
{
return m_instance;
}
QObject *PluginManager::interfaceObject(QString interfaceName)
{
return m_interfaces.value(interfaceName, NULL);
}
QList<QObject *> PluginManager::interfaceObjects(QString interfaceName)
{
return m_interfaces.values(interfaceName);
}
PluginManager::~PluginManager()
{
QObject *plug = interfaceObject("IPlugin");
while (plug) {
delete plug;
plug = interfaceObject("IPlugin");
}
delete [] m_lockFiles;
}
QSettings *PluginManager::settings() const
{
return m_settings;
}
QList<IPlugin *> PluginManager::dependPlugins(IPlugin *plugin)
{
QHash<QString, IPlugin *> pluginList;
if (plugin)
foreach (const QString &depInterfaceName, plugin->depModulList())
foreach (QObject *objInterfacePlugin, interfaceObjects(depInterfaceName)) {
IPlugin *interfacePlugin = qobject_cast<IPlugin *>(objInterfacePlugin);
if (interfacePlugin)
pluginList[objInterfacePlugin->objectName()] = interfacePlugin;
}
return pluginList.values();
}
QList<IPlugin *> PluginManager::dependentPlugins(IPlugin *plugin)
{
QHash<QString, IPlugin *> pluginList;
foreach (QObject *objPlug, m_interfaces.values("IPlugin")) {
IPlugin *plug = qobject_cast<IPlugin *>(objPlug);
if (plug && plug!=plugin)
foreach (IPlugin *interfacePlugin,dependPlugins(plug))
if (plugin == interfacePlugin)
pluginList[objPlug->objectName()] = plug;
}
return pluginList.values();
}
bool PluginManager::loadPlugins()
{
if (!m_pluginsDir.exists())
{
qCWarning(lcPlugin) << tr("Не найден каталог с модулями ")
+ m_pluginsDir.absolutePath();
return false;
}
m_fileList = m_pluginsDir.entryList(QDir::Files);
qint32 count = m_fileList.count();
m_lockFiles = new bool[count];
for (qint32 i = 0; i < count; ++i) m_lockFiles[i] = false;
nextLoadPlugins();
emit endLoadingPlugins();
return true;
}
bool PluginManager::nextLoadPlugins(QString iid)
{
bool result = false;
for (qint32 fileNum = m_fileList.count()-1; fileNum >= 0 ; --fileNum)
{
if (!m_lockFiles[fileNum]) {
m_lockFiles[fileNum] = true;
bool isLoad = loadPlugin(m_fileList.at(fileNum), iid);
if (!isLoad)
m_lockFiles[fileNum] = false;
result = result || isLoad;
}
}
return result;
}
bool PluginManager::loadPlugin(QString fileName, QString iid)
{
fileName = m_pluginsDir.absoluteFilePath(fileName);
if (!QLibrary::isLibrary(fileName)) {
qCWarning(lcPlugin) << tr("Файл не является модулем ") + fileName;
return false;
}
QPluginLoader loader(fileName);
QString plugIid = loader.metaData().value("IID").toString();
QRegExp checkIid("\\."+iid+"([\\.\\][0-9]+.?[0-9]*)?");
if (!plugIid.isEmpty() && !plugIid.contains(checkIid)) {
return false;
}
QObject *plugin = loader.instance();
if (plugin)
{
IPlugin *corePlugin = qobject_cast<IPlugin*>(plugin);
if (corePlugin){
connect(plugin, &QObject::destroyed,
this, &PluginManager::removePlugin);
plugin->setObjectName(plugin->metaObject()->className());
foreach (const QString &interface, corePlugin->interfaces())
m_interfaces.insert(interface, plugin);
emit loadedPlugin(plugin);
qCDebug(lcPlugin) << tr("Загружен модуль ") + plugin->objectName();
return true;
} else
delete plugin;
}
qCWarning(lcPlugin) << loader.errorString();
return false;
}
void PluginManager::setSettings(QSettings *s)
{
m_settings = s;
}
void PluginManager::removePlugin(QObject *obj)
{
foreach (const QString &interface, m_interfaces.keys())
foreach (QObject *plug,m_interfaces.values(interface))
if (plug == obj) {
m_interfaces.remove(interface, plug);
qCDebug(lcPlugin) << tr("Очищен модуль ") + plug->objectName();
}
qCDebug(lcPlugin) << tr("Выгружен модуль ") + obj->objectName();
emit removedPlugin(obj);
}
QDir PluginManager::pluginsDir() const
{
return m_pluginsDir;
}
void PluginManager::setPluginsDir(const QDir &pluginsDir)
{
m_pluginsDir = pluginsDir;
}
}}

134
src/pluginmanager.h Normal file
View File

@ -0,0 +1,134 @@
#ifndef PLUGINMANAGER_H
#define PLUGINMANAGER_H
#include <QObject>
#include "pluginglobal.h"
#include "iplugin.h"
class IPlugin;
namespace RTPTechGroup {
namespace Plugin {
//! Класс для управления плагинами
/*! Данный класс предназначен для загрузки плагинов,
получения объектов плагина, сохранение настроек плагина.\n
Пример:\n
\code
QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
QLatin1String("RTPTechGroup"), QLatin1String("UniversalPlatform"));
PluginManager pluginManager;
pluginManager.setSettings(settings);
pluginManager.loadPlugins();
\endcode
*/
class PLUGINLIB PluginManager : public QObject
{
Q_OBJECT
friend class IPlugin;
public:
//! Получение экземпляра менеджера плагинов
static PluginManager *instance();
//! Конструктор плагина
/*! Производит инициализацию плагина при его создании
*/
explicit PluginManager(QObject *parent = 0);
//! Деструктор плагина
/*! Производит завершающие действия при удалении плагина
*/
~PluginManager();
//! Получение объекта для указанного интерфейса
QObject *interfaceObject(QString interfaceName);
//! Получение объекта для указанного интерфейса с приведением типа
template<typename T> T interfaceObject(QString interfaceName)
{
return qobject_cast<T>(m_interfaces.value(interfaceName, NULL));
}
//! Получение объектов для указанного интерфейса
QList<QObject *> interfaceObjects(QString interfaceName);
//! Получить зависимые плагины
/*! Позволяет получить список зависимых плагинов от указанного
*/
QList<IPlugin*> dependentPlugins(IPlugin *plugin);
//! Получить от каких плагинов зависит
/*! Позволяет получить список плагинов от которых зависит указанный плвгин
*/
QList<IPlugin *> dependPlugins(IPlugin *plugin);
//! Загрузка плагинов
/*! Производит поиск плагина на диске в каталоге
plugins запущенного приложения и его загрузку
*/
bool loadPlugins();
//! Загрузка указанного плагина
bool loadPlugin(QString fileName, QString iid = "");
//! Загрузка следующего плагина
bool nextLoadPlugins(QString iid = "");
//! Устанавливает ссылку на объект для сохранения настроек
void setSettings(QSettings *s);
//! Получает ссылку на объект для сохранения настроек
QSettings *settings() const;
//! Получение каталога для плагина
QDir pluginsDir() const;
//! Установка каталога для плагина
void setPluginsDir(const QDir &pluginsDir);
signals:
//! Сигнал о загрузке плагина
void loadedPlugin(QObject *plugin);
//! Сигнал об удалении плагина
void removedPlugin(QObject *plugin);
//! Сигнал об окончании загрузки плагинов
void endLoadingPlugins();
private slots:
//! Удаляет указанный плагин
void removePlugin(QObject *obj);
private:
//! Экземпляр менеджера плагинов
static PluginManager *m_instance;
//! Настройки
QSettings *m_settings;
//! Список плагинов
/*! В списке плагинов хранятся загруженные плагины, которые можно получить
* по интерфейсам
*/
QMultiHash<QString, QObject *> m_interfaces;
//! Каталог нахождения плагинов
QDir m_pluginsDir;
//! Список файлов в каталоге плагина
QStringList m_fileList;
//! Множество заблокированных файлов
bool *m_lockFiles;
};
}}
#endif // PLUGINMANAGER_H

1
tests/README Normal file
View File

@ -0,0 +1 @@
Каталог для Unit тестов

6
tests/auto/auto.pri Normal file
View File

@ -0,0 +1,6 @@
include(../tests.pri)
INCLUDEPATH += $$PWD
QT += testlib
CONFIG += qt warn_on console depend_includepath testcase
CONFIG -= app_bundle
DEFINES -= QT_NO_CAST_FROM_ASCII

3
tests/auto/auto.pro Normal file
View File

@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS += plugin
SUBDIRS += treexmlmodel

9
tests/auto/auto.qbs Normal file
View File

@ -0,0 +1,9 @@
Project {
references: [
"tst_plugin1/tst_plugin1.qbs",
"tst_plugin2/tst_plugin2.qbs",
"tst_plugin3/tst_plugin3.qbs",
"tst_plugin4/tst_plugin4.qbs",
"tst_pluginmanager/tst_pluginmanager.qbs"
]
}

10
tests/auto/main.qbs Normal file
View File

@ -0,0 +1,10 @@
import "../main.qbs" as TestProduct
TestProduct {
name: "auto"
type: "application"
Group {
fileTagsFilter: ["application"]
qbs.install: true
qbs.installDir: "tests/auto/plugin/"
}
}

7
tests/auto/plugin.pro Normal file
View File

@ -0,0 +1,7 @@
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += tst_plugin1
SUBDIRS += tst_plugin2
SUBDIRS += tst_plugin3
SUBDIRS += tst_plugin4
SUBDIRS += tst_pluginmanager

View File

@ -0,0 +1,8 @@
LIBS += -lplugin
include(../auto.pri)
DEPENDPATH += .
INCLUDEPATH += .
QT += widgets
DESTDIR = $$DESTDIR/../plugins

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg version="1.1" width="64" height="64" color-interpolation="linearRGB"
xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
<g>
<path style="fill:#010101; fill-opacity:0.4549"
d="M18 62H25L33 54L46 62H53L64 50L56 46L30 49L18 62z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M2 34V52L18 60L30 49V32L14 26L2 34z"
/>
<path style="fill:#ec6666"
d="M2 34V52L18 60V41L2 34z"
/>
<linearGradient id="gradient0" gradientUnits="userSpaceOnUse" x1="46.61" y1="-4.85" x2="79.29" y2="20.92">
<stop offset="0" stop-color="#a3043c"/>
<stop offset="1" stop-color="#ff90af"/>
</linearGradient>
<path style="fill:url(#gradient0)"
d="M18 41V60L30 49V32L18 41z"
/>
<path style="fill:#0d2964"
d="M24 34L28 45V36L24 34z"
transform="matrix(1,0,0,1,0,1)"
/>
<path style="fill:#ffacac"
d="M2 34L18 41L30 32L14 26L2 34z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M30 34V52L46 60L58 48V31L42 25L30 34z"
/>
<linearGradient id="gradient1" gradientUnits="userSpaceOnUse" x1="-19.87" y1="-1.53" x2="5.48" y2="-26.29">
<stop offset="0" stop-color="#ffec4b"/>
<stop offset="1" stop-color="#f0a506"/>
</linearGradient>
<path style="fill:url(#gradient1)"
d="M33 49L33.99 53.99L46 60V41L41.07 38.84L33 49z"
/>
<linearGradient id="gradient2" gradientUnits="userSpaceOnUse" x1="46.61" y1="-4.85" x2="79.29" y2="20.92">
<stop offset="0" stop-color="#ed9306"/>
<stop offset="1" stop-color="#fcb23d"/>
</linearGradient>
<path style="fill:url(#gradient2)"
d="M30 34V52L33.99 53.99L33 49L41.07 38.84L30 34z"
/>
<linearGradient id="gradient3" gradientUnits="userSpaceOnUse" x1="118.72" y1="7.64" x2="121.66" y2="49.17">
<stop offset="0" stop-color="#edbf06"/>
<stop offset="1" stop-color="#fcec3d"/>
</linearGradient>
<path style="fill:url(#gradient3)"
d="M30 34L40.98 38.8L51.5 30.75L41.58 26.18L30 34z"
/>
<linearGradient id="gradient4" gradientUnits="userSpaceOnUse" x1="66.26" y1="9.32" x2="83.19" y2="22.3">
<stop offset="0" stop-color="#f99b05"/>
<stop offset="1" stop-color="#fcb23d"/>
</linearGradient>
<path style="fill:url(#gradient4)"
d="M32 18V37L44 28V10L32 18z
M46 41V60L58 48V30L46 41z"
/>
<linearGradient id="gradient5" gradientUnits="userSpaceOnUse" x1="45.5" y1="-4.56" x2="71.01" y2="9.11">
<stop offset="0" stop-color="#ffffff"/>
<stop offset="1" stop-color="#fff289"/>
</linearGradient>
<path style="fill:url(#gradient5)"
d="M51.5 30.75L40.98 38.8L46 41L58 31L42 25L41.58 26.18L51.5 30.75z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M16 12V30L32 37L44 28V10L28 5L16 12z"
/>
<linearGradient id="gradient6" gradientUnits="userSpaceOnUse" x1="10.36" y1="-26.67" x2="32.29" y2="-26.91">
<stop offset="0" stop-color="#d5dcff"/>
<stop offset="1" stop-color="#9d9bd5"/>
</linearGradient>
<path style="fill:url(#gradient6)"
d="M16 12V30L32 37V18L16 12z"
/>
<linearGradient id="gradient7" gradientUnits="userSpaceOnUse" x1="38.85" y1="-28.7" x2="61.14" y2="-16.76">
<stop offset="0" stop-color="#d7e6ff"/>
<stop offset="1" stop-color="#a4a3d7"/>
</linearGradient>
<path style="fill:url(#gradient7)"
d="M16 12L32 18L44 10L28 5L16 12z"
/>
<linearGradient id="gradient8" gradientUnits="userSpaceOnUse" x1="62.71" y1="-4.87" x2="77.45" y2="10.54">
<stop offset="0" stop-color="#343483"/>
<stop offset="1" stop-color="#6967c0"/>
</linearGradient>
<path style="fill:url(#gradient8)"
d="M32 18V37L44 28V10L32 18z"
/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,77 @@
#ifndef IMAINWINDOW_H
#define IMAINWINDOW_H
#include <QMdiSubWindow>
#include <QMainWindow>
#include <mdiextarea/mdiextarea.h>
//! Класс главного окна
class IMainWindow
{
public:
//! Получение подокна
/*! Предназначено для получения подокна
*/
virtual QMdiSubWindow *subWindow(QString objName) = 0;
//! Получение списка подокон
/*! Предназначено для получения списка подокон
*/
virtual QList<QMdiSubWindow *> subWindowList() const = 0;
public slots:
//! Добавления QAction для использования в главном окне
virtual void addAction(QString category, QAction *action) = 0;
//! Удаление QAction из главного окна
virtual void removeAction(QAction *action) = 0;
//! Запись настроек меню
virtual void writeBarSettings() = 0;
//! Чтение настроек меню
virtual void readBarSettings() = 0;
//! Чтение и применение настроек главного окна
virtual void readSettings() = 0;
//! Запись настроек главного окна
virtual void writeSettings() = 0;
//! Слот обработки события закрытия главного окна
virtual void closeEvent(QCloseEvent *event) = 0;
//! Слот обновления меню управления окнами
/*! Слот предназаначен для изменения состояния
пунктов меню при изменении состояния приложения
*/
virtual void updateMenus() = 0;
//! Слот установки оконного режима
/*! Слот предназначен переключение приложения в закладочный
или оконный режим
*/
virtual void setWindowModeEnable(bool mode) = 0;
//! Слот добавления подчиненного окна
/*! Слот предназаначен для добавления подчиненного окна(закладки)
в главное окно. Возращает добавленное подокно QMdiSubWindow
*/
virtual QMdiSubWindow *addSubWindow(QWidget *widget) = 0;
//! Слот установки активного окна по имени
/*! Слот предназначен для установки активного подокна в главном окне
по его имени
*/
virtual QMdiSubWindow *setActiveSubWindow(QString objName) = 0;
//! Получение области подокон
virtual MdiExtArea *getMdiArea() = 0;
};
Q_DECLARE_INTERFACE(IMainWindow,"com.RTPTechGroup.Raindrop.IMainWindow/1.0")
#endif // IMAINWINDOW_H

View File

@ -0,0 +1,12 @@
#ifndef ITST_PLUGIN1_H
#define ITST_PLUGIN1_H
class Itst_plugin1
{
};
#define Itst_plugin1_iid "com.RTPTechGroup.Raindrop.Itst_plugin1/1.0"
Q_DECLARE_INTERFACE(Itst_plugin1, Itst_plugin1_iid)
#endif // IMAINWINDOW_H

View File

@ -0,0 +1,7 @@
#include "tst_plugin1.h"
tst_plugin1::tst_plugin1(QObject *parent):
QObject(parent), IPlugin("Itst_plugin4")
{
}

View File

@ -0,0 +1,55 @@
#ifndef TST_PLUGIN1_H
#define TST_PLUGIN1_H
#include <QObject>
#include <plugin/iplugin.h>
#include "tst_plugin1global.h"
#include "itst_plugin1.h"
class TST_PLUGIN1LIB tst_plugin1:
public QObject,
public IPlugin,
public Itst_plugin1
{
Q_OBJECT
Q_INTERFACES(IPlugin Itst_plugin1)
Q_PLUGIN_METADATA(IID Itst_plugin1_iid FILE "tst_plugin1.json")
public:
//! Конструктор плагина
explicit tst_plugin1(QObject *parent = 0);
// IPlugin
//! Получение экземпляра
QObject *instance() { return this; }
//! Получение имени плагина
QString name() {return APP_NAME;};
//! Получение иконки плагина
QIcon icon() {return QIcon(":/tst_plugin1");};
//! Описание продукта
QString product() {return tr(APP_PRODUCT);};
//! Авторские права
QString copyright() {return tr(APP_COPYRIGHT);};
//! Описание плагина
QString descript() {return tr(APP_DESCRIPTION);};
//! Категория в которой состоит плагин
QString category() {return tr("");};
//! Версия плагина
QString version() {return APP_VERSION;};
//! Производитель плагина
QString vendor() {return tr(APP_COMPANY);};
};
#endif

View File

@ -0,0 +1,2 @@
{}

View File

@ -0,0 +1,16 @@
include(../tst_plugin.pri)
CONFIG += plugin
TEMPLATE = lib
DEFINES += TST_PLUGIN1_LIBRARY
VERSION = 1.0.0
QMAKE_TARGET_COMPANY = "RTPTechGroup"
QMAKE_TARGET_PRODUCT = "TST_PLUGIN1"
QMAKE_TARGET_DESCRIPTION = "TST_PLUGIN1"
QMAKE_TARGET_COPYRIGHT = "Copyright (C) RTPTechGroup"
# Input
HEADERS = *.h
SOURCES = *.cpp
RESOURCES = *.qrc

View File

@ -0,0 +1,30 @@
import "../main.qbs" as PluginProduct
PluginProduct {
name: "tst_plugin1"
type: "dynamiclibrary"
productname: "TST_PLUGIN1"
version: "1.0.0"
description: "TST_PLUGIN1"
company: "RTPTechGroup"
copyright: "Copyright (C) RTPTechGroup"
cpp.defines: base.concat(["TST_PLUGIN1_LIBRARY"])
cpp.includePaths: base.concat(['.'])
Depends { name: "Qt"; submodules: ["widgets"] }
Depends { name: "plugin" }
files: [
"*.h",
"*.cpp",
"*.ui",
"*.qrc"
]
Group {
fileTagsFilter: ["dynamiclibrary"]
qbs.install: true
qbs.installDir: "tests/auto/plugin/plugins"
}
}

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file alias="tst_plugin1">icons/tst_plugin1.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,9 @@
#ifndef TST_PLUGIN1GLOBAL_H
#define TST_PLUGIN1GLOBAL_H
#if defined(TST_PLUGIN1_LIBRARY)
# define TST_PLUGIN1LIB Q_DECL_EXPORT
#else
# define TST_PLUGIN1LIB Q_DECL_IMPORT
#endif
#endif // TST_PLUGIN1GLOBAL_H

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg version="1.1" width="64" height="64" color-interpolation="linearRGB"
xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
<g>
<path style="fill:#010101; fill-opacity:0.4549"
d="M18 62H25L33 54L46 62H53L64 50L56 46L30 49L18 62z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M2 34V52L18 60L30 49V32L14 26L2 34z"
/>
<path style="fill:#ec6666"
d="M2 34V52L18 60V41L2 34z"
/>
<linearGradient id="gradient0" gradientUnits="userSpaceOnUse" x1="46.61" y1="-4.85" x2="79.29" y2="20.92">
<stop offset="0" stop-color="#a3043c"/>
<stop offset="1" stop-color="#ff90af"/>
</linearGradient>
<path style="fill:url(#gradient0)"
d="M18 41V60L30 49V32L18 41z"
/>
<path style="fill:#0d2964"
d="M24 34L28 45V36L24 34z"
transform="matrix(1,0,0,1,0,1)"
/>
<path style="fill:#ffacac"
d="M2 34L18 41L30 32L14 26L2 34z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M30 34V52L46 60L58 48V31L42 25L30 34z"
/>
<linearGradient id="gradient1" gradientUnits="userSpaceOnUse" x1="-19.87" y1="-1.53" x2="5.48" y2="-26.29">
<stop offset="0" stop-color="#ffec4b"/>
<stop offset="1" stop-color="#f0a506"/>
</linearGradient>
<path style="fill:url(#gradient1)"
d="M33 49L33.99 53.99L46 60V41L41.07 38.84L33 49z"
/>
<linearGradient id="gradient2" gradientUnits="userSpaceOnUse" x1="46.61" y1="-4.85" x2="79.29" y2="20.92">
<stop offset="0" stop-color="#ed9306"/>
<stop offset="1" stop-color="#fcb23d"/>
</linearGradient>
<path style="fill:url(#gradient2)"
d="M30 34V52L33.99 53.99L33 49L41.07 38.84L30 34z"
/>
<linearGradient id="gradient3" gradientUnits="userSpaceOnUse" x1="118.72" y1="7.64" x2="121.66" y2="49.17">
<stop offset="0" stop-color="#edbf06"/>
<stop offset="1" stop-color="#fcec3d"/>
</linearGradient>
<path style="fill:url(#gradient3)"
d="M30 34L40.98 38.8L51.5 30.75L41.58 26.18L30 34z"
/>
<linearGradient id="gradient4" gradientUnits="userSpaceOnUse" x1="66.26" y1="9.32" x2="83.19" y2="22.3">
<stop offset="0" stop-color="#f99b05"/>
<stop offset="1" stop-color="#fcb23d"/>
</linearGradient>
<path style="fill:url(#gradient4)"
d="M32 18V37L44 28V10L32 18z
M46 41V60L58 48V30L46 41z"
/>
<linearGradient id="gradient5" gradientUnits="userSpaceOnUse" x1="45.5" y1="-4.56" x2="71.01" y2="9.11">
<stop offset="0" stop-color="#ffffff"/>
<stop offset="1" stop-color="#fff289"/>
</linearGradient>
<path style="fill:url(#gradient5)"
d="M51.5 30.75L40.98 38.8L46 41L58 31L42 25L41.58 26.18L51.5 30.75z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M16 12V30L32 37L44 28V10L28 5L16 12z"
/>
<linearGradient id="gradient6" gradientUnits="userSpaceOnUse" x1="10.36" y1="-26.67" x2="32.29" y2="-26.91">
<stop offset="0" stop-color="#d5dcff"/>
<stop offset="1" stop-color="#9d9bd5"/>
</linearGradient>
<path style="fill:url(#gradient6)"
d="M16 12V30L32 37V18L16 12z"
/>
<linearGradient id="gradient7" gradientUnits="userSpaceOnUse" x1="38.85" y1="-28.7" x2="61.14" y2="-16.76">
<stop offset="0" stop-color="#d7e6ff"/>
<stop offset="1" stop-color="#a4a3d7"/>
</linearGradient>
<path style="fill:url(#gradient7)"
d="M16 12L32 18L44 10L28 5L16 12z"
/>
<linearGradient id="gradient8" gradientUnits="userSpaceOnUse" x1="62.71" y1="-4.87" x2="77.45" y2="10.54">
<stop offset="0" stop-color="#343483"/>
<stop offset="1" stop-color="#6967c0"/>
</linearGradient>
<path style="fill:url(#gradient8)"
d="M32 18V37L44 28V10L32 18z"
/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,12 @@
#ifndef ITST_PLUGIN2_H
#define ITST_PLUGIN2_H
class Itst_plugin2
{
};
#define Itst_plugin2_iid "com.RTPTechGroup.Raindrop.Itst_plugin2/1.0"
Q_DECLARE_INTERFACE(Itst_plugin2, Itst_plugin2_iid)
#endif // IMAINWINDOW_H

View File

@ -0,0 +1,7 @@
#include "tst_plugin2.h"
tst_plugin2::tst_plugin2(QObject *parent):
QObject(parent), IPlugin("Itst_plugin3")
{
}

View File

@ -0,0 +1,55 @@
#ifndef TST_PLUGIN2_H
#define TST_PLUGIN2_H
#include <QObject>
#include <plugin/iplugin.h>
#include "tst_plugin2global.h"
#include "itst_plugin2.h"
class TST_PLUGIN2LIB tst_plugin2:
public QObject,
public IPlugin,
public Itst_plugin2
{
Q_OBJECT
Q_INTERFACES(IPlugin Itst_plugin2)
Q_PLUGIN_METADATA(IID Itst_plugin2_iid FILE "tst_plugin2.json")
public:
//! Конструктор плагина
explicit tst_plugin2(QObject *parent = 0);
// IPlugin
//! Получение экземпляра
QObject *instance() { return this; }
//! Получение имени плагина
QString name() {return APP_NAME;};
//! Получение иконки плагина
QIcon icon() {return QIcon(":/tst_plugin2");};
//! Описание продукта
QString product() {return tr(APP_PRODUCT);};
//! Авторские права
QString copyright() {return tr(APP_COPYRIGHT);};
//! Описание плагина
QString descript() {return tr(APP_DESCRIPTION);};
//! Категория в которой состоит плагин
QString category() {return tr("");};
//! Версия плагина
QString version() {return APP_VERSION;};
//! Производитель плагина
QString vendor() {return tr(APP_COMPANY);};
};
#endif

View File

@ -0,0 +1,2 @@
{}

View File

@ -0,0 +1,16 @@
include(../tst_plugin.pri)
CONFIG += plugin
TEMPLATE = lib
DEFINES += TST_PLUGIN2_LIBRARY
VERSION = 1.0.0
QMAKE_TARGET_COMPANY = "RTPTechGroup"
QMAKE_TARGET_PRODUCT = "TST_PLUGIN2"
QMAKE_TARGET_DESCRIPTION = "TST_PLUGIN2"
QMAKE_TARGET_COPYRIGHT = "Copyright (C) RTPTechGroup"
# Input
HEADERS = *.h
SOURCES = *.cpp
RESOURCES = *.qrc

View File

@ -0,0 +1,32 @@
import "../main.qbs" as PluginProduct
PluginProduct {
name: "tst_plugin2"
type: "dynamiclibrary"
productname: "TST_PLUGIN2"
version: "1.0.0"
description: "TST_PLUGIN2"
company: "RTPTechGroup"
copyright: "Copyright (C) RTPTechGroup"
cpp.defines: base.concat(["TST_PLUGIN2_LIBRARY"])
cpp.includePaths: base.concat(['.'])
Depends { name: "Qt"; submodules: ["widgets"] }
Depends { name: "plugin" }
files: [
"*.h",
"*.cpp",
"*.ui",
"*.qrc"
]
Group {
fileTagsFilter: [
"dynamiclibrary",
"dynamiclibrary_import"]
qbs.install: true
qbs.installDir: "tests/auto/plugin/plugins"
}
}

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file alias="tst_plugin2">icons/tst_plugin2.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,9 @@
#ifndef TST_PLUGIN2GLOBAL_H
#define TST_PLUGIN2GLOBAL_H
#if defined(TST_PLUGIN2_LIBRARY)
# define TST_PLUGIN2LIB Q_DECL_EXPORT
#else
# define TST_PLUGIN2LIB Q_DECL_IMPORT
#endif
#endif // TST_PLUGIN2GLOBAL_H

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg version="1.1" width="64" height="64" color-interpolation="linearRGB"
xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
<g>
<path style="fill:#010101; fill-opacity:0.4549"
d="M18 62H25L33 54L46 62H53L64 50L56 46L30 49L18 62z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M2 34V52L18 60L30 49V32L14 26L2 34z"
/>
<path style="fill:#ec6666"
d="M2 34V52L18 60V41L2 34z"
/>
<linearGradient id="gradient0" gradientUnits="userSpaceOnUse" x1="46.61" y1="-4.85" x2="79.29" y2="20.92">
<stop offset="0" stop-color="#a3043c"/>
<stop offset="1" stop-color="#ff90af"/>
</linearGradient>
<path style="fill:url(#gradient0)"
d="M18 41V60L30 49V32L18 41z"
/>
<path style="fill:#0d2964"
d="M24 34L28 45V36L24 34z"
transform="matrix(1,0,0,1,0,1)"
/>
<path style="fill:#ffacac"
d="M2 34L18 41L30 32L14 26L2 34z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M30 34V52L46 60L58 48V31L42 25L30 34z"
/>
<linearGradient id="gradient1" gradientUnits="userSpaceOnUse" x1="-19.87" y1="-1.53" x2="5.48" y2="-26.29">
<stop offset="0" stop-color="#ffec4b"/>
<stop offset="1" stop-color="#f0a506"/>
</linearGradient>
<path style="fill:url(#gradient1)"
d="M33 49L33.99 53.99L46 60V41L41.07 38.84L33 49z"
/>
<linearGradient id="gradient2" gradientUnits="userSpaceOnUse" x1="46.61" y1="-4.85" x2="79.29" y2="20.92">
<stop offset="0" stop-color="#ed9306"/>
<stop offset="1" stop-color="#fcb23d"/>
</linearGradient>
<path style="fill:url(#gradient2)"
d="M30 34V52L33.99 53.99L33 49L41.07 38.84L30 34z"
/>
<linearGradient id="gradient3" gradientUnits="userSpaceOnUse" x1="118.72" y1="7.64" x2="121.66" y2="49.17">
<stop offset="0" stop-color="#edbf06"/>
<stop offset="1" stop-color="#fcec3d"/>
</linearGradient>
<path style="fill:url(#gradient3)"
d="M30 34L40.98 38.8L51.5 30.75L41.58 26.18L30 34z"
/>
<linearGradient id="gradient4" gradientUnits="userSpaceOnUse" x1="66.26" y1="9.32" x2="83.19" y2="22.3">
<stop offset="0" stop-color="#f99b05"/>
<stop offset="1" stop-color="#fcb23d"/>
</linearGradient>
<path style="fill:url(#gradient4)"
d="M32 18V37L44 28V10L32 18z
M46 41V60L58 48V30L46 41z"
/>
<linearGradient id="gradient5" gradientUnits="userSpaceOnUse" x1="45.5" y1="-4.56" x2="71.01" y2="9.11">
<stop offset="0" stop-color="#ffffff"/>
<stop offset="1" stop-color="#fff289"/>
</linearGradient>
<path style="fill:url(#gradient5)"
d="M51.5 30.75L40.98 38.8L46 41L58 31L42 25L41.58 26.18L51.5 30.75z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M16 12V30L32 37L44 28V10L28 5L16 12z"
/>
<linearGradient id="gradient6" gradientUnits="userSpaceOnUse" x1="10.36" y1="-26.67" x2="32.29" y2="-26.91">
<stop offset="0" stop-color="#d5dcff"/>
<stop offset="1" stop-color="#9d9bd5"/>
</linearGradient>
<path style="fill:url(#gradient6)"
d="M16 12V30L32 37V18L16 12z"
/>
<linearGradient id="gradient7" gradientUnits="userSpaceOnUse" x1="38.85" y1="-28.7" x2="61.14" y2="-16.76">
<stop offset="0" stop-color="#d7e6ff"/>
<stop offset="1" stop-color="#a4a3d7"/>
</linearGradient>
<path style="fill:url(#gradient7)"
d="M16 12L32 18L44 10L28 5L16 12z"
/>
<linearGradient id="gradient8" gradientUnits="userSpaceOnUse" x1="62.71" y1="-4.87" x2="77.45" y2="10.54">
<stop offset="0" stop-color="#343483"/>
<stop offset="1" stop-color="#6967c0"/>
</linearGradient>
<path style="fill:url(#gradient8)"
d="M32 18V37L44 28V10L32 18z"
/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,12 @@
#ifndef ITST_PLUGIN3_H
#define ITST_PLUGIN3_H
class Itst_plugin3
{
};
#define Itst_plugin3_iid "com.RTPTechGroup.Raindrop.Itst_plugin3/1.0"
Q_DECLARE_INTERFACE(Itst_plugin3, Itst_plugin3_iid)
#endif // IMAINWINDOW_H

View File

@ -0,0 +1,9 @@
#include "tst_plugin3.h"
tst_plugin3::tst_plugin3(QObject *parent):
QObject(parent), IPlugin("")
{
}

View File

@ -0,0 +1,58 @@
#ifndef TST_PLUGIN3_H
#define TST_PLUGIN3_H
#include <QObject>
#include <plugin/iplugin.h>
#include "tst_plugin3global.h"
#include "itst_plugin3.h"
#include "../tst_plugin4/itst_plugin4.h"
class TST_PLUGIN3LIB tst_plugin3:
public QObject,
public IPlugin,
public Itst_plugin3,
public Itst_plugin4
{
Q_OBJECT
Q_INTERFACES(IPlugin Itst_plugin3 Itst_plugin4)
Q_PLUGIN_METADATA(IID Itst_plugin3_iid FILE "tst_plugin3.json")
public:
//! Конструктор плагина
explicit tst_plugin3(QObject *parent = 0);
// IPlugin
//! Получение экземпляра
QObject *instance() { return this; }
//! Получение имени плагина
QString name() {return APP_NAME;};
//! Получение иконки плагина
QIcon icon() {return QIcon(":/tst_plugin3");};
//! Описание продукта
QString product() {return tr(APP_PRODUCT);};
//! Авторские права
QString copyright() {return tr(APP_COPYRIGHT);};
//! Описание плагина
QString descript() {return tr(APP_DESCRIPTION);};
//! Категория в которой состоит плагин
QString category() {return tr("");};
//! Версия плагина
QString version() {return APP_VERSION;};
//! Производитель плагина
QString vendor() {return tr(APP_COMPANY);};;
};
#endif

View File

@ -0,0 +1,2 @@
{}

View File

@ -0,0 +1,16 @@
include(../tst_plugin.pri)
CONFIG += plugin
TEMPLATE = lib
DEFINES += TST_PLUGIN3_LIBRARY
VERSION = 1.0.0
QMAKE_TARGET_COMPANY = "RTPTechGroup"
QMAKE_TARGET_PRODUCT = "TST_PLUGIN3"
QMAKE_TARGET_DESCRIPTION = "TST_PLUGIN3"
QMAKE_TARGET_COPYRIGHT = "Copyright (C) RTPTechGroup"
# Input
HEADERS = *.h
SOURCES = *.cpp
RESOURCES = *.qrc

View File

@ -0,0 +1,32 @@
import "../main.qbs" as PluginProduct
PluginProduct {
name: "tst_plugin3"
type: "dynamiclibrary"
productname: "TST_PLUGIN3"
version: "1.0.0"
description: "TST_PLUGIN3"
company: "RTPTechGroup"
copyright: "Copyright (C) RTPTechGroup"
cpp.defines: base.concat(["TST_PLUGIN3_LIBRARY"])
cpp.includePaths: base.concat(['.'])
Depends { name: "Qt"; submodules: ["widgets"] }
Depends { name: "plugin" }
files: [
"*.h",
"*.cpp",
"*.ui",
"*.qrc"
]
Group {
fileTagsFilter: [
"dynamiclibrary",
"dynamiclibrary_import"]
qbs.install: true
qbs.installDir: "tests/auto/plugin/plugins"
}
}

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file alias="tst_plugin3">icons/tst_plugin3.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,9 @@
#ifndef TST_PLUGIN3GLOBAL_H
#define TST_PLUGIN3GLOBAL_H
#if defined(TST_PLUGIN3_LIBRARY)
# define TST_PLUGIN3LIB Q_DECL_EXPORT
#else
# define TST_PLUGIN3LIB Q_DECL_IMPORT
#endif
#endif // TST_PLUGIN3GLOBAL_H

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg version="1.1" width="64" height="64" color-interpolation="linearRGB"
xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
<g>
<path style="fill:#010101; fill-opacity:0.4549"
d="M18 62H25L33 54L46 62H53L64 50L56 46L30 49L18 62z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M2 34V52L18 60L30 49V32L14 26L2 34z"
/>
<path style="fill:#ec6666"
d="M2 34V52L18 60V41L2 34z"
/>
<linearGradient id="gradient0" gradientUnits="userSpaceOnUse" x1="46.61" y1="-4.85" x2="79.29" y2="20.92">
<stop offset="0" stop-color="#a3043c"/>
<stop offset="1" stop-color="#ff90af"/>
</linearGradient>
<path style="fill:url(#gradient0)"
d="M18 41V60L30 49V32L18 41z"
/>
<path style="fill:#0d2964"
d="M24 34L28 45V36L24 34z"
transform="matrix(1,0,0,1,0,1)"
/>
<path style="fill:#ffacac"
d="M2 34L18 41L30 32L14 26L2 34z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M30 34V52L46 60L58 48V31L42 25L30 34z"
/>
<linearGradient id="gradient1" gradientUnits="userSpaceOnUse" x1="-19.87" y1="-1.53" x2="5.48" y2="-26.29">
<stop offset="0" stop-color="#ffec4b"/>
<stop offset="1" stop-color="#f0a506"/>
</linearGradient>
<path style="fill:url(#gradient1)"
d="M33 49L33.99 53.99L46 60V41L41.07 38.84L33 49z"
/>
<linearGradient id="gradient2" gradientUnits="userSpaceOnUse" x1="46.61" y1="-4.85" x2="79.29" y2="20.92">
<stop offset="0" stop-color="#ed9306"/>
<stop offset="1" stop-color="#fcb23d"/>
</linearGradient>
<path style="fill:url(#gradient2)"
d="M30 34V52L33.99 53.99L33 49L41.07 38.84L30 34z"
/>
<linearGradient id="gradient3" gradientUnits="userSpaceOnUse" x1="118.72" y1="7.64" x2="121.66" y2="49.17">
<stop offset="0" stop-color="#edbf06"/>
<stop offset="1" stop-color="#fcec3d"/>
</linearGradient>
<path style="fill:url(#gradient3)"
d="M30 34L40.98 38.8L51.5 30.75L41.58 26.18L30 34z"
/>
<linearGradient id="gradient4" gradientUnits="userSpaceOnUse" x1="66.26" y1="9.32" x2="83.19" y2="22.3">
<stop offset="0" stop-color="#f99b05"/>
<stop offset="1" stop-color="#fcb23d"/>
</linearGradient>
<path style="fill:url(#gradient4)"
d="M32 18V37L44 28V10L32 18z
M46 41V60L58 48V30L46 41z"
/>
<linearGradient id="gradient5" gradientUnits="userSpaceOnUse" x1="45.5" y1="-4.56" x2="71.01" y2="9.11">
<stop offset="0" stop-color="#ffffff"/>
<stop offset="1" stop-color="#fff289"/>
</linearGradient>
<path style="fill:url(#gradient5)"
d="M51.5 30.75L40.98 38.8L46 41L58 31L42 25L41.58 26.18L51.5 30.75z"
/>
<path style="fill:none; stroke:#000000; stroke-width:4"
d="M16 12V30L32 37L44 28V10L28 5L16 12z"
/>
<linearGradient id="gradient6" gradientUnits="userSpaceOnUse" x1="10.36" y1="-26.67" x2="32.29" y2="-26.91">
<stop offset="0" stop-color="#d5dcff"/>
<stop offset="1" stop-color="#9d9bd5"/>
</linearGradient>
<path style="fill:url(#gradient6)"
d="M16 12V30L32 37V18L16 12z"
/>
<linearGradient id="gradient7" gradientUnits="userSpaceOnUse" x1="38.85" y1="-28.7" x2="61.14" y2="-16.76">
<stop offset="0" stop-color="#d7e6ff"/>
<stop offset="1" stop-color="#a4a3d7"/>
</linearGradient>
<path style="fill:url(#gradient7)"
d="M16 12L32 18L44 10L28 5L16 12z"
/>
<linearGradient id="gradient8" gradientUnits="userSpaceOnUse" x1="62.71" y1="-4.87" x2="77.45" y2="10.54">
<stop offset="0" stop-color="#343483"/>
<stop offset="1" stop-color="#6967c0"/>
</linearGradient>
<path style="fill:url(#gradient8)"
d="M32 18V37L44 28V10L32 18z"
/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,12 @@
#ifndef ITST_PLUGIN4_H
#define ITST_PLUGIN4_H
class Itst_plugin4
{
};
#define Itst_plugin4_iid "com.RTPTechGroup.Raindrop.Itst_plugin4/1.0"
Q_DECLARE_INTERFACE(Itst_plugin4, Itst_plugin4_iid)
#endif // IMAINWINDOW_H

View File

@ -0,0 +1,9 @@
#include "tst_plugin4.h"
tst_plugin4::tst_plugin4(QObject *parent):
QObject(parent), IPlugin("Itst_plugin3")
{
}

View File

@ -0,0 +1,55 @@
#ifndef TST_PLUGIN4_H
#define TST_PLUGIN4_H
#include <QObject>
#include <plugin/iplugin.h>
#include "tst_plugin4global.h"
#include "itst_plugin4.h"
class TST_PLUGIN4LIB tst_plugin4:
public QObject,
public IPlugin,
public Itst_plugin4
{
Q_OBJECT
Q_INTERFACES(IPlugin Itst_plugin4)
Q_PLUGIN_METADATA(IID Itst_plugin4_iid FILE "tst_plugin4.json")
public:
//! Конструктор плагина
explicit tst_plugin4(QObject *parent = 0);
// IPlugin
//! Получение экземпляра
QObject *instance() { return this; }
//! Получение имени плагина
QString name() {return APP_NAME;};
//! Получение иконки плагина
QIcon icon() {return QIcon(":/tst_plugin4");};
//! Описание продукта
QString product() {return tr(APP_PRODUCT);};
//! Авторские права
QString copyright() {return tr(APP_COPYRIGHT);};
//! Описание плагина
QString descript() {return tr(APP_DESCRIPTION);};
//! Категория в которой состоит плагин
QString category() {return tr("");};
//! Версия плагина
QString version() {return APP_VERSION;};
//! Производитель плагина
QString vendor() {return tr(APP_COMPANY);};
};
#endif

View File

@ -0,0 +1,2 @@
{}

View File

@ -0,0 +1,15 @@
include(../tst_plugin.pri)
CONFIG += plugin
TEMPLATE = lib
DEFINES += TST_PLUGIN4_LIBRARY
VERSION = 1.0.0
QMAKE_TARGET_COMPANY = "RTPTechGroup"
QMAKE_TARGET_PRODUCT = "TST_PLUGIN4"
QMAKE_TARGET_DESCRIPTION = "TST_PLUGIN4"
QMAKE_TARGET_COPYRIGHT = "Copyright (C) RTPTechGroup"
# Input
HEADERS = *.h
SOURCES = *.cpp
RESOURCES = *.qrc

View File

@ -0,0 +1,32 @@
import "../main.qbs" as PluginProduct
PluginProduct {
name: "tst_plugin4"
type: "dynamiclibrary"
productname: "TST_PLUGIN4"
version: "1.0.0"
description: "TST_PLUGIN4"
company: "RTPTechGroup"
copyright: "Copyright (C) RTPTechGroup"
cpp.defines: base.concat(["TST_PLUGIN4_LIBRARY"])
cpp.includePaths: base.concat(['.'])
Depends { name: "Qt"; submodules: ["widgets"] }
Depends { name: "plugin" }
files: [
"*.h",
"*.cpp",
"*.ui",
"*.qrc"
]
Group {
fileTagsFilter: [
"dynamiclibrary",
"dynamiclibrary_import"]
qbs.install: true
qbs.installDir: "tests/auto/plugin/plugins"
}
}

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file alias="tst_plugin4">icons/tst_plugin4.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,9 @@
#ifndef TST_PLUGIN4GLOBAL_H
#define TST_PLUGIN4GLOBAL_H
#if defined(TST_PLUGIN4_LIBRARY)
# define TST_PLUGIN4LIB Q_DECL_EXPORT
#else
# define TST_PLUGIN4LIB Q_DECL_IMPORT
#endif
#endif // TST_PLUGIN4GLOBAL_H

View File

@ -0,0 +1,27 @@
#include "pluginloadlog.h"
PluginLoadLog::PluginLoadLog(QObject *parent) :
QObject(parent)
{
}
PluginLoadLog::~PluginLoadLog()
{
m_loadedPlugins.clear();
}
QStringList PluginLoadLog::loadedPlugins()
{
return m_loadedPlugins;
}
void PluginLoadLog::clearLoadedPlugins()
{
m_loadedPlugins.clear();
}
void PluginLoadLog::loadPlugin(QObject *plugin)
{
m_loadedPlugins.append(plugin->objectName());
}

View File

@ -0,0 +1,25 @@
#ifndef PLUGINLOADLOG_H
#define PLUGINLOADLOG_H
#include <QObject>
#include <plugin/iplugin.h>
class PluginLoadLog : public QObject
{
Q_OBJECT
public:
explicit PluginLoadLog(QObject *parent = 0);
virtual ~PluginLoadLog();
QStringList loadedPlugins();
void clearLoadedPlugins();
public slots:
void loadPlugin(QObject *plugin);
private:
QStringList m_loadedPlugins;
};
#endif // PLUGINLOADLOG_H

View File

@ -0,0 +1,232 @@
#include <QObject>
#include <QtTest/QtTest>
#include <QSettings>
#include <QApplication>
#include <plugin/pluginmanager.h>
#include "pluginloadlog.h"
using namespace RTPTechGroup::Plugin;
class tst_PluginManager : public QObject
{
Q_OBJECT
public:
//! Конструктор теста
explicit tst_PluginManager(QObject *parent = 0);
//! Конструктор теста
virtual ~tst_PluginManager();
public slots:
void initTestCase();
void cleanupTestCase();
void init();
void cleanup();
private slots:
void instance();
void interfaceObject();
void interfaceObjects();
void dependentPlugins();
void dependPlugins();
void loadPlugins();
void settings();
private:
PluginManager m_pluginManager;
PluginLoadLog *m_pluginLoadLog;
};
tst_PluginManager::tst_PluginManager(QObject *parent)
{
Q_UNUSED(parent)
m_pluginLoadLog = NULL;
}
tst_PluginManager::~tst_PluginManager()
{
}
void tst_PluginManager::initTestCase()
{
#if QT_VERSION < 0x050000
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
// Подключение перевода для Qt
QString translatorFileName = QLatin1String("qt_");
translatorFileName += QLocale::system().name();
QTranslator *translator = new QTranslator(this);
if (translator->load(translatorFileName,
QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
QApplication::installTranslator(translator);
m_pluginLoadLog = new PluginLoadLog();
connect(PluginManager::instance(), &PluginManager::loadedPlugin,
m_pluginLoadLog, &PluginLoadLog::loadPlugin);
m_pluginManager.setPluginsDir(QDir(qApp->applicationDirPath() + "/plugins/"));
m_pluginManager.loadPlugins();
}
void tst_PluginManager::cleanupTestCase()
{
PluginLoadLog *pluginUnloadLog = new PluginLoadLog();
connect(PluginManager::instance(), &PluginManager::removedPlugin,
pluginUnloadLog, &PluginLoadLog::loadPlugin);
delete m_pluginManager.interfaceObject("Itst_plugin3");
QStringList plugins = pluginUnloadLog->loadedPlugins();
QCOMPARE(plugins.count(), 4);
if (plugins.at(0) == "tst_plugin2") {
QVERIFY(plugins.at(0) == "tst_plugin2");
QVERIFY(plugins.at(1) == "tst_plugin1");
QVERIFY(plugins.at(2) == "tst_plugin4");
} else {
QVERIFY(plugins.at(0) == "tst_plugin1");
QVERIFY(plugins.at(1) == "tst_plugin2"
|| plugins.at(1) == "tst_plugin4");
QVERIFY(plugins.at(2) == "tst_plugin2"
|| plugins.at(2) == "tst_plugin4");
}
QVERIFY(plugins.at(3) == "tst_plugin3");
delete pluginUnloadLog;
delete m_pluginLoadLog;
}
void tst_PluginManager::init()
{
}
void tst_PluginManager::cleanup()
{
}
void tst_PluginManager::instance()
{
QCOMPARE(&m_pluginManager, PluginManager::instance());
}
void tst_PluginManager::interfaceObject()
{
QCOMPARE (m_pluginManager.interfaceObject("Itst_plugin1")->metaObject()->className(),
"tst_plugin1");
QCOMPARE (m_pluginManager.interfaceObject("Itst_plugin2")->metaObject()->className(),
"tst_plugin2");
QCOMPARE (m_pluginManager.interfaceObject("Itst_plugin3")->metaObject()->className(),
"tst_plugin3");
}
void tst_PluginManager::interfaceObjects()
{
QList<QObject *> listObject = m_pluginManager.interfaceObjects("Itst_plugin4");
QVERIFY(listObject.count() == 2);
QStringList objectName;
objectName << "tst_plugin3" << "tst_plugin4";
foreach (QObject *interfaceObject, listObject) {
QVERIFY(objectName.removeOne(interfaceObject->metaObject()->className()));
}
}
void tst_PluginManager::dependentPlugins()
{
QStringList dependentName1;
QStringList dependentName2;
QStringList dependentName3;
dependentName3 << "tst_plugin1" << "tst_plugin2" << "tst_plugin4";
QStringList dependentName4;
dependentName4 << "tst_plugin1";
QList<QObject *> plugins = m_pluginManager.interfaceObjects("IPlugin");
foreach (QObject *plugin, plugins) {
IPlugin *iplugin = qobject_cast<IPlugin *>(plugin);
QList<IPlugin *> listDependent = m_pluginManager.dependentPlugins(iplugin);
foreach (IPlugin *pluginDependent, listDependent) {
if (iplugin->name() == QString("tst_plugin1")) {
QVERIFY(dependentName1.removeOne(pluginDependent->name()));
} else if (iplugin->name() == QString("tst_plugin2")) {
QVERIFY(dependentName2.removeOne(pluginDependent->name()));
} else if (iplugin->name() == QString("tst_plugin3")) {
QVERIFY(dependentName3.removeOne(pluginDependent->name()));
} else if (iplugin->name() == QString("tst_plugin4")) {
QVERIFY(dependentName4.removeOne(pluginDependent->name()));
}
}
}
QCOMPARE(dependentName1.count(),0);
QCOMPARE(dependentName2.count(),0);
QCOMPARE(dependentName3.count(),0);
QCOMPARE(dependentName4.count(),0);
}
void tst_PluginManager::dependPlugins()
{
QStringList dependName1;
dependName1 << "tst_plugin3" << "tst_plugin4";
QStringList dependName2;
dependName2 << "tst_plugin3";
QStringList dependName3;
QStringList dependName4;
dependName4 << "tst_plugin3";
QList<QObject *> plugins = m_pluginManager.interfaceObjects("IPlugin");
foreach (QObject *plugin, plugins) {
IPlugin *iplugin = qobject_cast<IPlugin *>(plugin);
QList<IPlugin *> listDepend = m_pluginManager.dependPlugins(iplugin);
foreach (IPlugin *pluginDepend, listDepend) {
if (iplugin->name() == QString("tst_plugin1")) {
QVERIFY(dependName1.removeOne(pluginDepend->name()));
} else if (iplugin->name() == QString("tst_plugin2")) {
QVERIFY(dependName2.removeOne(pluginDepend->name()));
} else if (iplugin->name() == QString("tst_plugin3")) {
QVERIFY(dependName3.removeOne(pluginDepend->name()));
} else if (iplugin->name() == QString("tst_plugin4")) {
QVERIFY(dependName4.removeOne(pluginDepend->name()));
}
}
}
QCOMPARE(dependName1.count(),0);
QCOMPARE(dependName2.count(),0);
QCOMPARE(dependName3.count(),0);
QCOMPARE(dependName4.count(),0);
}
void tst_PluginManager::loadPlugins()
{
QStringList plugins = m_pluginLoadLog->loadedPlugins();
QCOMPARE(plugins.count(), 4);
QVERIFY(plugins.at(0) == "tst_plugin3");
QVERIFY(
(plugins.at(1) == "tst_plugin2"
&& (plugins.at(2) == "tst_plugin1" || plugins.at(3) == "tst_plugin1"))
|| (plugins.at(2) == "tst_plugin2" && plugins.at(3) == "tst_plugin1")
);
QVERIFY(plugins.at(3) == "tst_plugin1" || plugins.at(3) == "tst_plugin4");
}
void tst_PluginManager::settings()
{
QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
QLatin1String("RTPTechGroup"), QLatin1String("Raindrop"));
m_pluginManager.setSettings(settings);
QCOMPARE(settings, m_pluginManager.settings());
}
QTEST_MAIN(tst_PluginManager)
#include "tst_pluginmanager.moc"

View File

@ -0,0 +1,11 @@
include(../tst_plugin.pri)
TEMPLATE = app
CONFIG += plugin
DESTDIR = $$DESTDIR/../
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
}
LIBS += -lplugin
HEADERS = *.h
SOURCES = *.cpp

View File

@ -0,0 +1,23 @@
import "../main.qbs" as PluginProduct
PluginProduct {
name: "tst_pluginmanager"
productname: ""
version: "1.0.0"
description: ""
company: "RTPTechGroup"
copyright: "Copyright (C) RTPTechGroup"
cpp.includePaths: base.concat(['.'])
Depends { name: "Qt"; submodules: ["widgets", "testlib"] }
Depends { name: "plugin" }
files: [
"*.h",
"*.cpp",
"*.ui",
"*.qrc"
]
}

View File

@ -0,0 +1,6 @@
include(../tests.pri)
INCLUDEPATH += $$PWD
QT += testlib
CONFIG += qt warn_on console depend_includepath testcase
CONFIG -= app_bundle
DEFINES -= QT_NO_CAST_FROM_ASCII

View File

@ -0,0 +1,2 @@
TEMPLATE = subdirs
SUBDIRS += test_tmpl

View File

@ -0,0 +1,3 @@
Project {
references: []
}

View File

@ -0,0 +1,5 @@
import "../main.qbs" as TestProduct
TestProduct {
name: "manual"
type: "application"
}

View File

@ -0,0 +1,9 @@
import "../main.qbs" as LibProduct
LibProduct {
name: "test_tmpl"
Group {
fileTagsFilter: ["application"]
qbs.install: true
qbs.installDir: "tests/benchmarks/test_tmpl/"
}
}

View File

@ -0,0 +1,2 @@
TEMPLATE=subdirs
#SUBDIRS=tst_test_tmpl_prf

View File

@ -0,0 +1,3 @@
Project {
references: []
}

View File

@ -0,0 +1,14 @@
include(../../manual.pri)
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = tst_test_tmpl_prf
TEMPLATE = app
LIBS +=
# HEADERS = *.h
# SOURCES = *.cpp
# FORMS = *.ui

View File

@ -0,0 +1,21 @@
import "../main.qbs" as TestTmpl
TestTmpl {
name: "tst_test_tmpl_prf"
productname: ""
version: "1.0.0"
description: ""
company: "RTPTechGroup"
copyright: "Copyright (C) RTPTechGroup"
Depends { name: "Qt"; submodules: ["core", "gui", "widgets", "sql"] }
Depends { name: "sqlextension" }
files: [
"*.h",
"*.cpp",
"*.ui",
"*.qrc"
]
}

6
tests/main.qbs Normal file
View File

@ -0,0 +1,6 @@
import qbs.FileInfo
import "../main.qbs" as MainProduct
MainProduct {
name: "tests"
builtByDefault: false
}

10
tests/manual/main.qbs Normal file
View File

@ -0,0 +1,10 @@
import "../main.qbs" as TestProduct
TestProduct {
name: "manual"
type: "application"
Group {
fileTagsFilter: ["application"]
qbs.install: true
qbs.installDir: "tests/manual/plugin/"
}
}

2
tests/manual/manual.pri Normal file
View File

@ -0,0 +1,2 @@
include(../tests.pri)
INCLUDEPATH += $$PWD

4
tests/manual/manual.pro Normal file
View File

@ -0,0 +1,4 @@
TEMPLATE = subdirs
SUBDIRS += treexmlmodel
SUBDIRS += tilingframe
SUBDIRS += sqlextension

4
tests/manual/manual.qbs Normal file
View File

@ -0,0 +1,4 @@
Project {
references: [
]
}

30
tests/tests.pri Normal file
View File

@ -0,0 +1,30 @@
!greaterThan(QT_MAJOR_VERSION, 4) {
load(qttest_p4)
}
include(../main.pri)
INCLUDEPATH += $$PWD/../src/libs $$PWD/../src/shared $$PWD/../src/plugins
QMAKE_RPATHDIR += $$LIBRARY_PATH
unix {
QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$${QMAKE_RPATHDIR}\'
}
LIBS +=-L$$LIBRARY_PATH
LIBS +=-L$$PLUGINS_PATH
TEMPLATE = app
# DESTDIR = $$APP_PATH
# prefix test binary with tst_
!contains(TARGET, ^tst_.*):TARGET = $$join(TARGET,,"tst_")
win32 {
lib = $$APP_PATH;$$APP_PATH/plugins
lib ~= s,/,\\,g
# the below gets added to later by testcase.prf
check.commands = cd . & set PATH=$$lib;%PATH%& cmd /c
}
sub_dir = $$_PRO_FILE_PWD_
sub_dir ~= s,^$${PWD},,
DESTDIR = $$TESTS_PATH$$sub_dir

5
tests/tests.pro Normal file
View File

@ -0,0 +1,5 @@
TEMPLATE = subdirs
SUBDIRS += auto
SUBDIRS += benchmarks
SUBDIRS += manual

7
tests/tests.qbs Normal file
View File

@ -0,0 +1,7 @@
Project {
references: [
"auto/auto.qbs",
"benchmarks/benchmarks.qbs",
"manual/manual.qbs"
]
}