From 4c59c725c7b5933684f000e77820174b548c8c69 Mon Sep 17 00:00:00 2001 From: APTX Date: Thu, 2 Mar 2017 00:24:28 +0100 Subject: [PATCH] Add UI plugins --- .gitignore | 2 +- aniplayer3.pro | 1 + core/backendapi.pri | 2 +- core/core.pro | 8 +--- core/include/aniplayer/uipluginbase.h | 22 ++++++++++ core/instancemanager.cpp | 43 +++++++++++-------- core/instancemanager.h | 4 +- .../ui_desktop_qml_default}/qml.qrc | 2 +- .../ui_desktop_qml_default}/qml/Button.qml | 0 .../qml/OpenButton.qml | 0 .../qml/PlaybackPosition.qml | 0 .../qml/PlayerControls.qml | 0 .../qml/SeekSlider.qml | 0 .../qml/VolumeSlider.qml | 0 .../ui_desktop_qml_default}/qml/main.qml | 0 .../ui_desktop_qml_default}/timeformatter.cpp | 0 .../ui_desktop_qml_default}/timeformatter.h | 0 .../ui_desktop_qml_default.json | 0 .../ui_desktop_qml_default.pro | 26 +++++++++++ .../ui_desktop_qml_default_global.h | 12 ++++++ .../uidesktopqmldefault.cpp | 26 +++++++++++ .../uidesktopqmldefault.h | 27 ++++++++++++ uiplugins/uibuildconfig.pri | 2 + uiplugins/uiplugins.pro | 7 +++ 24 files changed, 153 insertions(+), 31 deletions(-) create mode 100644 core/include/aniplayer/uipluginbase.h rename {core => uiplugins/ui_desktop_qml_default}/qml.qrc (84%) rename {core => uiplugins/ui_desktop_qml_default}/qml/Button.qml (100%) rename {core => uiplugins/ui_desktop_qml_default}/qml/OpenButton.qml (100%) rename {core => uiplugins/ui_desktop_qml_default}/qml/PlaybackPosition.qml (100%) rename {core => uiplugins/ui_desktop_qml_default}/qml/PlayerControls.qml (100%) rename {core => uiplugins/ui_desktop_qml_default}/qml/SeekSlider.qml (100%) rename {core => uiplugins/ui_desktop_qml_default}/qml/VolumeSlider.qml (100%) rename {core => uiplugins/ui_desktop_qml_default}/qml/main.qml (100%) rename {core => uiplugins/ui_desktop_qml_default}/timeformatter.cpp (100%) rename {core => uiplugins/ui_desktop_qml_default}/timeformatter.h (100%) create mode 100644 uiplugins/ui_desktop_qml_default/ui_desktop_qml_default.json create mode 100644 uiplugins/ui_desktop_qml_default/ui_desktop_qml_default.pro create mode 100644 uiplugins/ui_desktop_qml_default/ui_desktop_qml_default_global.h create mode 100644 uiplugins/ui_desktop_qml_default/uidesktopqmldefault.cpp create mode 100644 uiplugins/ui_desktop_qml_default/uidesktopqmldefault.h create mode 100644 uiplugins/uibuildconfig.pri create mode 100644 uiplugins/uiplugins.pro diff --git a/.gitignore b/.gitignore index f298019..fa63ce1 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ Makefile* *.prl *.app moc_*.cpp -ui_*.h +#ui_*.h qrc_*.cpp *.qmake.stash diff --git a/aniplayer3.pro b/aniplayer3.pro index fb53cae..a4531eb 100644 --- a/aniplayer3.pro +++ b/aniplayer3.pro @@ -3,4 +3,5 @@ TEMPLATE = subdirs SUBDIRS += \ core \ backendplugins \ + uiplugins \ featureplugins diff --git a/core/backendapi.pri b/core/backendapi.pri index 2dba128..3b5ca33 100644 --- a/core/backendapi.pri +++ b/core/backendapi.pri @@ -1,2 +1,2 @@ -INCLUDEPATH += $$PWD/include +INCLUDEPATH += $$PWD/include include(../buildconfig.pri) \ No newline at end of file diff --git a/core/core.pro b/core/core.pro index 22a282b..37cc4a2 100644 --- a/core/core.pro +++ b/core/core.pro @@ -10,22 +10,16 @@ SOURCES += main.cpp \ player.cpp \ pluginmanager.cpp \ videoelement.cpp \ - timeformatter.cpp \ instancemanager.cpp -RESOURCES += qml.qrc - -# Additional import path used to resolve QML modules in Qt Creator's code model -QML_IMPORT_PATH = - HEADERS += \ player.h \ include/aniplayer/backendpluginbase.h \ include/aniplayer/playerplugininterface.h \ include/aniplayer/featurepluginbase.h \ + include/aniplayer/uipluginbase.h \ pluginmanager.h \ videoelement.h \ - timeformatter.h \ instancemanager.h include(qtsingleapplication/qtsingleapplication.pri) diff --git a/core/include/aniplayer/uipluginbase.h b/core/include/aniplayer/uipluginbase.h new file mode 100644 index 0000000..16572e4 --- /dev/null +++ b/core/include/aniplayer/uipluginbase.h @@ -0,0 +1,22 @@ +#ifndef UIPLUGINBASE_H +#define UIPLUGINBASE_H + +#include + +class UiInstance { +public: + virtual ~UiInstance() = default; +}; + +class UiPluginBase { +public: + virtual ~UiPluginBase() = default; + + virtual UiInstance *createUi(QObject *player, QObject *parent = nullptr) = 0; +}; + +#define ANIPLAYER_UI_PLUGIN_INTERFACE_IID "org.aptx.aniplayer.UiPluginInterface" + +Q_DECLARE_INTERFACE(UiPluginBase, ANIPLAYER_UI_PLUGIN_INTERFACE_IID) + +#endif // UIPLUGINBASE_H diff --git a/core/instancemanager.cpp b/core/instancemanager.cpp index d04d10d..1ad5495 100644 --- a/core/instancemanager.cpp +++ b/core/instancemanager.cpp @@ -3,13 +3,11 @@ #include #include #include -#include -#include #include "aniplayer/featurepluginbase.h" +#include "aniplayer/uipluginbase.h" #include "player.h" #include "pluginmanager.h" -#include "timeformatter.h" Q_LOGGING_CATEGORY(imCategory, "InstanceManager") @@ -25,14 +23,21 @@ InstanceManager::InstanceManager(QObject *parent) m_parser.addOption(cwdOption); #ifdef Q_OS_WIN - static QStringList pluginPaths{"featureplugins"}; + static QStringList featurePluginPaths{"featureplugins"}; + static QStringList uiPluginPaths{"uiplugins"}; #else - static QStringList pluginPaths{"featureplugins", - "/usr/lib/aniplayer/featureplugins"}; + static QStringList featurePluginPaths{"featureplugins", + "/usr/lib/aniplayer/featureplugins"}; + static QStringList uiPluginPaths{"uiplugins", "/usr/lib/aniplayer/uiplugins"}; #endif - m_featurePluginManager = new PluginManager; - m_featurePluginManager->setPluginDirectories(pluginPaths); + m_uiPluginManager = new PluginManager{this}; + m_uiPluginManager->setPluginDirectories(uiPluginPaths); + m_uiPluginManager->setPluginPrefix("ui"); + m_uiPluginManager->setPreferredPlugins({"desktop_qml_default"}); + + m_featurePluginManager = new PluginManager{this}; + m_featurePluginManager->setPluginDirectories(featurePluginPaths); m_featurePluginManager->setPluginPrefix("feature"); // TODO feature plugins should be looked up and not preferred. m_featurePluginManager->setPreferredPlugins({"localmylist"}); @@ -44,25 +49,25 @@ void InstanceManager::startFirstInstance() { const auto positionalArgs = m_parser.positionalArguments(); - QQmlApplicationEngine *engine = new QQmlApplicationEngine{this}; - Q_CHECK_PTR(engine); - - auto player = createInstance(); + auto player = createPlayerInstance(); qCDebug(imCategory, "Player Created"); m_instances.insert(player); + m_uiPluginManager->loadBestPlugin(); + auto uiInstance = m_uiPluginManager->bestInstance(); + if (!uiInstance) + throw std::runtime_error{std::string("Failed to load ui: ") + + qPrintable(m_uiPluginManager->errorString())}; + + auto ui = uiInstance->createUi(player, this); + Q_CHECK_PTR(ui); + if (!positionalArgs.empty()) { auto url = parseUserInput(positionalArgs[0], m_parser.value(cwdOption)); qCDebug(imCategory) << "Parsed positional argument as" << url; player->setNextSource(url); } - auto timeFormatter = new TimeFormatter{this}; - engine->rootContext()->setContextProperty("player", player); - engine->rootContext()->setContextProperty("timeFormatter", timeFormatter); - qCDebug(imCategory, "Player Added"); - engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); - qCDebug(imCategory, "QML engine loaded"); } QString InstanceManager::encodeCommandLine() const { @@ -122,7 +127,7 @@ QUrl InstanceManager::parseUserInput(const QString &arg, return QUrl::fromUserInput(arg, workingDirectory, QUrl::AssumeLocalFile); } -Player *InstanceManager::createInstance() { +Player *InstanceManager::createPlayerInstance() { #ifdef Q_OS_WIN static QStringList pluginPaths{"backendplugins"}; #else diff --git a/core/instancemanager.h b/core/instancemanager.h index d852c09..0c2168a 100644 --- a/core/instancemanager.h +++ b/core/instancemanager.h @@ -17,7 +17,6 @@ public: explicit InstanceManager(QObject *parent = 0); void startFirstInstance(); - void startInstance(); public slots: QString encodeCommandLine() const; @@ -28,7 +27,7 @@ public: const QString &workingDirectory); private: - Player *createInstance(); + Player *createPlayerInstance(); const QCommandLineOption backendOption{"backend", "Use backend", "name of backend plugin", "default"}; const QCommandLineOption uiOption{"ui", "Use ui", "name of ui", "default"}; @@ -42,6 +41,7 @@ private: QCommandLineParser m_parser; QSet m_instances; PluginManager *m_backendPluginManager; + PluginManager *m_uiPluginManager; PluginManager *m_featurePluginManager; }; diff --git a/core/qml.qrc b/uiplugins/ui_desktop_qml_default/qml.qrc similarity index 84% rename from core/qml.qrc rename to uiplugins/ui_desktop_qml_default/qml.qrc index 0e27bae..4ba679c 100644 --- a/core/qml.qrc +++ b/uiplugins/ui_desktop_qml_default/qml.qrc @@ -1,5 +1,5 @@ - + qml/main.qml qml/OpenButton.qml qml/PlayerControls.qml diff --git a/core/qml/Button.qml b/uiplugins/ui_desktop_qml_default/qml/Button.qml similarity index 100% rename from core/qml/Button.qml rename to uiplugins/ui_desktop_qml_default/qml/Button.qml diff --git a/core/qml/OpenButton.qml b/uiplugins/ui_desktop_qml_default/qml/OpenButton.qml similarity index 100% rename from core/qml/OpenButton.qml rename to uiplugins/ui_desktop_qml_default/qml/OpenButton.qml diff --git a/core/qml/PlaybackPosition.qml b/uiplugins/ui_desktop_qml_default/qml/PlaybackPosition.qml similarity index 100% rename from core/qml/PlaybackPosition.qml rename to uiplugins/ui_desktop_qml_default/qml/PlaybackPosition.qml diff --git a/core/qml/PlayerControls.qml b/uiplugins/ui_desktop_qml_default/qml/PlayerControls.qml similarity index 100% rename from core/qml/PlayerControls.qml rename to uiplugins/ui_desktop_qml_default/qml/PlayerControls.qml diff --git a/core/qml/SeekSlider.qml b/uiplugins/ui_desktop_qml_default/qml/SeekSlider.qml similarity index 100% rename from core/qml/SeekSlider.qml rename to uiplugins/ui_desktop_qml_default/qml/SeekSlider.qml diff --git a/core/qml/VolumeSlider.qml b/uiplugins/ui_desktop_qml_default/qml/VolumeSlider.qml similarity index 100% rename from core/qml/VolumeSlider.qml rename to uiplugins/ui_desktop_qml_default/qml/VolumeSlider.qml diff --git a/core/qml/main.qml b/uiplugins/ui_desktop_qml_default/qml/main.qml similarity index 100% rename from core/qml/main.qml rename to uiplugins/ui_desktop_qml_default/qml/main.qml diff --git a/core/timeformatter.cpp b/uiplugins/ui_desktop_qml_default/timeformatter.cpp similarity index 100% rename from core/timeformatter.cpp rename to uiplugins/ui_desktop_qml_default/timeformatter.cpp diff --git a/core/timeformatter.h b/uiplugins/ui_desktop_qml_default/timeformatter.h similarity index 100% rename from core/timeformatter.h rename to uiplugins/ui_desktop_qml_default/timeformatter.h diff --git a/uiplugins/ui_desktop_qml_default/ui_desktop_qml_default.json b/uiplugins/ui_desktop_qml_default/ui_desktop_qml_default.json new file mode 100644 index 0000000..e69de29 diff --git a/uiplugins/ui_desktop_qml_default/ui_desktop_qml_default.pro b/uiplugins/ui_desktop_qml_default/ui_desktop_qml_default.pro new file mode 100644 index 0000000..85c1769 --- /dev/null +++ b/uiplugins/ui_desktop_qml_default/ui_desktop_qml_default.pro @@ -0,0 +1,26 @@ +TARGET = ui_desktop_qml_default +QT += qml quick +TEMPLATE = lib + +include(../../core/core.pri) +include(../uibuildconfig.pri) + +DEFINES += UI_DESKTOP_QML_DEFAULT_LIBRARY QT_DEPRECATED_WARNINGS + +SOURCES += \ + uidesktopqmldefault.cpp \ + timeformatter.cpp + +HEADERS += \ + ui_desktop_qml_default_global.h \ + uidesktopqmldefault.h \ + timeformatter.h + +RESOURCES += qml.qrc + +DISTFILES += ui_desktop_qml_default.json + +unix { + target.path = $${PREFIX}/lib/aniplayer/uiplugins + INSTALLS += target +} diff --git a/uiplugins/ui_desktop_qml_default/ui_desktop_qml_default_global.h b/uiplugins/ui_desktop_qml_default/ui_desktop_qml_default_global.h new file mode 100644 index 0000000..7bc7ee7 --- /dev/null +++ b/uiplugins/ui_desktop_qml_default/ui_desktop_qml_default_global.h @@ -0,0 +1,12 @@ +#ifndef UI_DESKTOP_QML_DEFAULT_GLOBAL_H +#define UI_DESKTOP_QML_DEFAULT_GLOBAL_H + +#include + +#if defined(UI_DESKTOP_QML_DEFAULT_LIBRARY) +# define UI_DESKTOP_QML_DEFAULTSHARED_EXPORT Q_DECL_EXPORT +#else +# define UI_DESKTOP_QML_DEFAULTSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // UI_DESKTOP_QML_DEFAULT_GLOBAL_H diff --git a/uiplugins/ui_desktop_qml_default/uidesktopqmldefault.cpp b/uiplugins/ui_desktop_qml_default/uidesktopqmldefault.cpp new file mode 100644 index 0000000..d1bec91 --- /dev/null +++ b/uiplugins/ui_desktop_qml_default/uidesktopqmldefault.cpp @@ -0,0 +1,26 @@ +#include "uidesktopqmldefault.h" + +#include +#include +#include + +#include "timeformatter.h" + +Q_LOGGING_CATEGORY(uidqdCategory, "UiDefault") + +UiDesktopQmlDefaultInstance::UiDesktopQmlDefaultInstance(QObject *player, QObject *parent) +: QObject{parent} { + player->setParent(this); + QQmlApplicationEngine *engine = new QQmlApplicationEngine{this}; + Q_CHECK_PTR(engine); + auto timeFormatter = new TimeFormatter{this}; + engine->rootContext()->setContextProperty("player", player); + engine->rootContext()->setContextProperty("timeFormatter", timeFormatter); + qCDebug(uidqdCategory, "Player Added"); + engine->load(QUrl(QStringLiteral("qrc:/ui_desktop_qml_default/qml/main.qml"))); + qCDebug(uidqdCategory, "QML engine loaded"); +} + +UiInstance *UiDesktopQmlDefault::createUi(QObject *player, QObject *parent) { + return new UiDesktopQmlDefaultInstance{player, parent}; +} diff --git a/uiplugins/ui_desktop_qml_default/uidesktopqmldefault.h b/uiplugins/ui_desktop_qml_default/uidesktopqmldefault.h new file mode 100644 index 0000000..389c5d7 --- /dev/null +++ b/uiplugins/ui_desktop_qml_default/uidesktopqmldefault.h @@ -0,0 +1,27 @@ +#ifndef UIDESKTOPQMLDEFAULT_H +#define UIDESKTOPQMLDEFAULT_H + +#include "aniplayer/uipluginbase.h" +#include "ui_desktop_qml_default_global.h" + +class UI_DESKTOP_QML_DEFAULTSHARED_EXPORT UiDesktopQmlDefaultInstance + : public QObject, + public UiInstance { + Q_OBJECT +public: + explicit UiDesktopQmlDefaultInstance(QObject *player, + QObject *parent = nullptr); +}; + +class UI_DESKTOP_QML_DEFAULTSHARED_EXPORT UiDesktopQmlDefault + : public QObject, + public UiPluginBase { + Q_OBJECT + Q_PLUGIN_METADATA(IID ANIPLAYER_UI_PLUGIN_INTERFACE_IID FILE + "ui_desktop_qml_default.json") + Q_INTERFACES(UiPluginBase) +public: + UiInstance *createUi(QObject *player, QObject *parent) override; +}; + +#endif // UIDESKTOPQMLDEFAULT_H diff --git a/uiplugins/uibuildconfig.pri b/uiplugins/uibuildconfig.pri new file mode 100644 index 0000000..424939d --- /dev/null +++ b/uiplugins/uibuildconfig.pri @@ -0,0 +1,2 @@ +include(../buildconfig.pri) +DESTDIR=../../build/uiplugins \ No newline at end of file diff --git a/uiplugins/uiplugins.pro b/uiplugins/uiplugins.pro new file mode 100644 index 0000000..2a46a74 --- /dev/null +++ b/uiplugins/uiplugins.pro @@ -0,0 +1,7 @@ +TEMPLATE = subdirs + +include(../config.pri) + +!no_ui_desktop_qml_default { + SUBDIRS += ui_desktop_qml_default +} -- 2.52.0