*.prl
*.app
moc_*.cpp
-ui_*.h
+#ui_*.h
qrc_*.cpp
*.qmake.stash
SUBDIRS += \
core \
backendplugins \
+ uiplugins \
featureplugins
-INCLUDEPATH += $$PWD/include\r
+INCLUDEPATH += $$PWD/include
include(../buildconfig.pri)
\ No newline at end of file
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)
--- /dev/null
+#ifndef UIPLUGINBASE_H
+#define UIPLUGINBASE_H
+
+#include <QObject>
+
+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
#include <QDataStream>
#include <QDir>
#include <QLoggingCategory>
-#include <QQmlApplicationEngine>
-#include <QQmlContext>
#include "aniplayer/featurepluginbase.h"
+#include "aniplayer/uipluginbase.h"
#include "player.h"
#include "pluginmanager.h"
-#include "timeformatter.h"
Q_LOGGING_CATEGORY(imCategory, "InstanceManager")
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"});
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<UiPluginBase>();
+ 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 {
return QUrl::fromUserInput(arg, workingDirectory, QUrl::AssumeLocalFile);
}
-Player *InstanceManager::createInstance() {
+Player *InstanceManager::createPlayerInstance() {
#ifdef Q_OS_WIN
static QStringList pluginPaths{"backendplugins"};
#else
explicit InstanceManager(QObject *parent = 0);
void startFirstInstance();
- void startInstance();
public slots:
QString encodeCommandLine() const;
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"};
QCommandLineParser m_parser;
QSet<Player *> m_instances;
PluginManager *m_backendPluginManager;
+ PluginManager *m_uiPluginManager;
PluginManager *m_featurePluginManager;
};
<RCC>
- <qresource prefix="/">
+ <qresource prefix="/ui_desktop_qml_default">
<file>qml/main.qml</file>
<file>qml/OpenButton.qml</file>
<file>qml/PlayerControls.qml</file>
--- /dev/null
+TARGET = ui_desktop_qml_default\r
+QT += qml quick\r
+TEMPLATE = lib\r
+\r
+include(../../core/core.pri)\r
+include(../uibuildconfig.pri)\r
+\r
+DEFINES += UI_DESKTOP_QML_DEFAULT_LIBRARY QT_DEPRECATED_WARNINGS\r
+\r
+SOURCES += \\r
+ uidesktopqmldefault.cpp \\r
+ timeformatter.cpp\r
+\r
+HEADERS += \\r
+ ui_desktop_qml_default_global.h \\r
+ uidesktopqmldefault.h \\r
+ timeformatter.h\r
+\r
+RESOURCES += qml.qrc\r
+\r
+DISTFILES += ui_desktop_qml_default.json\r
+\r
+unix {\r
+ target.path = $${PREFIX}/lib/aniplayer/uiplugins\r
+ INSTALLS += target\r
+}\r
--- /dev/null
+#ifndef UI_DESKTOP_QML_DEFAULT_GLOBAL_H
+#define UI_DESKTOP_QML_DEFAULT_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#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
--- /dev/null
+#include "uidesktopqmldefault.h"\r
+\r
+#include <QQmlApplicationEngine>\r
+#include <QQmlContext>\r
+#include <QLoggingCategory>\r
+\r
+#include "timeformatter.h"\r
+\r
+Q_LOGGING_CATEGORY(uidqdCategory, "UiDefault")\r
+\r
+UiDesktopQmlDefaultInstance::UiDesktopQmlDefaultInstance(QObject *player, QObject *parent)\r
+: QObject{parent} {\r
+ player->setParent(this);\r
+ QQmlApplicationEngine *engine = new QQmlApplicationEngine{this};\r
+ Q_CHECK_PTR(engine);\r
+ auto timeFormatter = new TimeFormatter{this};\r
+ engine->rootContext()->setContextProperty("player", player);\r
+ engine->rootContext()->setContextProperty("timeFormatter", timeFormatter);\r
+ qCDebug(uidqdCategory, "Player Added");\r
+ engine->load(QUrl(QStringLiteral("qrc:/ui_desktop_qml_default/qml/main.qml")));\r
+ qCDebug(uidqdCategory, "QML engine loaded");\r
+}\r
+\r
+UiInstance *UiDesktopQmlDefault::createUi(QObject *player, QObject *parent) {\r
+ return new UiDesktopQmlDefaultInstance{player, parent};\r
+}\r
--- /dev/null
+#ifndef UIDESKTOPQMLDEFAULT_H\r
+#define UIDESKTOPQMLDEFAULT_H\r
+\r
+#include "aniplayer/uipluginbase.h"\r
+#include "ui_desktop_qml_default_global.h"\r
+\r
+class UI_DESKTOP_QML_DEFAULTSHARED_EXPORT UiDesktopQmlDefaultInstance\r
+ : public QObject,\r
+ public UiInstance {\r
+ Q_OBJECT\r
+public:\r
+ explicit UiDesktopQmlDefaultInstance(QObject *player,\r
+ QObject *parent = nullptr);\r
+};\r
+\r
+class UI_DESKTOP_QML_DEFAULTSHARED_EXPORT UiDesktopQmlDefault\r
+ : public QObject,\r
+ public UiPluginBase {\r
+ Q_OBJECT\r
+ Q_PLUGIN_METADATA(IID ANIPLAYER_UI_PLUGIN_INTERFACE_IID FILE\r
+ "ui_desktop_qml_default.json")\r
+ Q_INTERFACES(UiPluginBase)\r
+public:\r
+ UiInstance *createUi(QObject *player, QObject *parent) override;\r
+};\r
+\r
+#endif // UIDESKTOPQMLDEFAULT_H\r
--- /dev/null
+include(../buildconfig.pri)
+DESTDIR=../../build/uiplugins
\ No newline at end of file
--- /dev/null
+TEMPLATE = subdirs\r
+\r
+include(../config.pri)\r
+\r
+!no_ui_desktop_qml_default {\r
+ SUBDIRS += ui_desktop_qml_default\r
+}\r