aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/src-cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/src-cpp')
-rw-r--r--src-qt5/src-cpp/framework-OSInterface-template.cpp150
-rw-r--r--src-qt5/src-cpp/framework-OSInterface.h190
-rw-r--r--src-qt5/src-cpp/framework-OSInterface.pri9
-rw-r--r--src-qt5/src-cpp/framework-OSInterface_private.cpp110
-rw-r--r--src-qt5/src-cpp/plugins-base.cpp50
-rw-r--r--src-qt5/src-cpp/plugins-base.h107
-rw-r--r--src-qt5/src-cpp/plugins-base.pri8
-rw-r--r--src-qt5/src-cpp/plugins-desktop.cpp40
-rw-r--r--src-qt5/src-cpp/plugins-desktop.h29
-rw-r--r--src-qt5/src-cpp/plugins-screensaver.cpp118
-rw-r--r--src-qt5/src-cpp/plugins-screensaver.h37
-rw-r--r--src-qt5/src-cpp/plugins-screensaver.pri4
-rw-r--r--src-qt5/src-cpp/tests/main.cpp38
-rw-r--r--src-qt5/src-cpp/tests/test.pro7
14 files changed, 749 insertions, 148 deletions
diff --git a/src-qt5/src-cpp/framework-OSInterface-template.cpp b/src-qt5/src-cpp/framework-OSInterface-template.cpp
new file mode 100644
index 00000000..972e02e0
--- /dev/null
+++ b/src-qt5/src-cpp/framework-OSInterface-template.cpp
@@ -0,0 +1,150 @@
+//===========================================
+// Lumina desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include <framework-OSInterface.h>
+#include <QNetworkConfiguration>
+#include <QNetworkInterface>
+
+//Start/stop interface watchers/notifications
+void OSInterface::start(){
+ setupMediaWatcher(); //will create/connect the filesystem watcher automatically
+ setupNetworkManager();
+}
+
+void OSInterface::stop(){
+ if(isRunning()){
+ watcher->deleteLater();
+ watcher = 0;
+ }
+}
+
+bool OSInterface::isRunning(){ return (watcher!=0); } //status of the object - whether it has been started yet
+
+// = Battery =
+bool OSInterface::batteryAvailable(){ return false; }
+float OSInterface::batteryCharge(){ return -1; }
+bool OSInterface::batteryCharging(){ return false; }
+double OSInterface::batterySecondsLeft(){ return -1; }
+
+// = Volume =
+bool OSInterface::volumeAvailable(){ return false; }
+int OSInterface::volume(){ return -1; }
+void OSInterface::setVolume(int){}
+
+// = Network Information =
+bool OSInterface::networkAvailable(){
+ if(INFO.contains("netaccess/available")){ return INFO.value("netaccess/available").toBool(); }
+ return false;
+}
+
+QString OSInterface::networkType(){
+ if(INFO.contains("netaccess/type")){ return INFO.value("netaccess/type").toString(); } //"wifi", "wired", or "cell"
+ return "";
+}
+
+float OSInterface::networkStrength(){ return -1; } //percentage. ("wired" type should always be 100%)
+
+QString OSInterface::networkHostname(){
+ return QHostInfo::localHostName();
+}
+
+QHostAddress OSInterface::networkAddress(){
+ QString addr;
+ if(INFO.contains("netaccess/address")){ addr = INFO.value("netaccess/address").toString(); }
+ return QHostAddress(addr);
+}
+// = Network Modification =
+
+// = Media Shortcuts =
+QStringList OSInterface::mediaDirectories(){ return QStringList() << "/media"; } //directory where XDG shortcuts are placed for interacting with media (local/remote)
+QStringList OSInterface::mediaShortcuts(){ return autoHandledMediaFiles(); } //List of currently-available XDG shortcut file paths
+
+// = Updates =
+bool OSInterface::updatesAvailable(){ return false; }
+QString OSInterface::updateDetails(){ return QString(); } //Information about any available updates
+bool OSInterface::updatesRunning(){ return false; }
+QString OSInterface::updateLog(){ return QString(); } //Information about any currently-running update
+bool OSInterface::updatesFinished(){ return false; }
+QString OSInterface::updateResults(){ return QString(); } //Information about any finished update
+void OSInterface::startUpdates(){}
+bool OSInterface::updateOnlyOnReboot(){ return false; } //Should the startUpdates function be called only when rebooting the system?
+QDateTime OSInterface::lastUpdate(){ return QDateTime(); } //The date/time of the previous updates
+QString OSInterface::lastUpdateResults(){ return QString(); } //Information about the previously-finished update
+
+// = System Power =
+bool OSInterface::canReboot(){ return false; }
+void OSInterface::startReboot(){}
+bool OSInterface::canShutdown(){ return false; }
+void OSInterface::startShutdown(){}
+bool OSInterface::canSuspend(){ return false; }
+void OSInterface::startSuspend(){}
+
+// = Screen Brightness =
+int OSInterface::brightness(){ return -1; } //percentage: 0-100 with -1 for errors
+void OSInterface::setBrightness(int){}
+
+// = System Status Monitoring
+QList<int> OSInterface::cpuPercentage(){ return QList<int>(); } // (one per CPU) percentage: 0-100 with empty list for errors
+QStringList OSInterface::cpuTemperatures(){ return QStringList(); } // (one per CPU) Temperature of CPU ("50C" for example)
+int OSInterface::memoryUsedPercentage(){ return -1; } //percentage: 0-100 with -1 for errors
+QString OSInterface::memoryTotal(){ return QString(); } //human-readable form - does not tend to change within a session
+QStringList OSInterface::diskIO(){ return QStringList(); } //Returns list of current read/write stats for each device
+int OSInterface::fileSystemPercentage(QString dir){ return -1; } //percentage of capacity used: 0-100 with -1 for errors
+QString OSInterface::fileSystemCapacity(QString dir){ return QString(); } //human-readable form - total capacity
+
+// = OS-Specific Utilities =
+bool OSInterface::hasControlPanel(){ return false; }
+QString OSInterface::controlPanelShortcut(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
+bool OSInterface::hasAudioMixer(){ return false; }
+QString OSInterface::audioMixerShortcut(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
+bool OSInterface::hasAppStore(){ return false; }
+QString OSInterface::appStoreShortcut(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
+
+//FileSystemWatcher slots
+void OSInterface::watcherFileChanged(QString){}
+void OSInterface::watcherDirChanged(QString dir){
+ if(handleMediaDirChange(dir)){ return; }
+}
+
+//IO Device slots
+void OSInterface::iodeviceReadyRead(){}
+void OSInterface::iodeviceAboutToClose(){}
+
+//NetworkAccessManager slots
+void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility stat){
+ INFO.insert("netaccess/available", stat== QNetworkAccessManager::Accessible);
+ //Update all the other network status info at the same time
+ QNetworkConfiguration active = netman->activeConfiguration();
+ //Type of connection
+ QString type;
+ switch(active.bearerTypeFamily()){
+ case QNetworkConfiguration::BearerEthernet: type="wired"; break;
+ case QNetworkConfiguration::BearerWLAN: type="wifi"; break;
+ case QNetworkConfiguration::Bearer2G: type="cell-2G"; break;
+ case QNetworkConfiguration::Bearer3G: type="cell-3G"; break;
+ case QNetworkConfiguration::Bearer4G: type="cell-4G"; break;
+ default: type="";
+ }
+ INFO.insert("netaccess/type", type);
+ qDebug() << "Detected Device Status:" << active.identifier() << type << stat;
+ QNetworkInterface iface = QNetworkInterface::interfaceFromName(active.name());
+ qDebug() << " - Configuration: Name:" << active.name() << active.bearerTypeName() << active.identifier();
+ qDebug() << " - Interface: MAC Address:" << iface.hardwareAddress() << "Name:" << iface.name() << iface.humanReadableName() << iface.isValid();
+ QList<QNetworkAddressEntry> addressList = iface.addressEntries();
+ QStringList address;
+ //NOTE: There are often 2 addresses, IPv4 and IPv6
+ for(int i=0; i<addressList.length(); i++){
+ address << addressList[i].ip().toString();
+ }
+ qDebug() << " - IP Address:" << address;
+ qDebug() << " - Hostname:" << networkHostname();
+ INFO.insert("netaccess/address", address.join(", "));
+ emit networkStatusChanged();
+}
+
+void OSInterface::netRequestFinished(QNetworkReply*){}
+void OSInterface::netSslErrors(QNetworkReply*, const QList<QSslError>&){}
+void OSInterface::timerUpdate(){}
diff --git a/src-qt5/src-cpp/framework-OSInterface.h b/src-qt5/src-cpp/framework-OSInterface.h
new file mode 100644
index 00000000..a173ad5a
--- /dev/null
+++ b/src-qt5/src-cpp/framework-OSInterface.h
@@ -0,0 +1,190 @@
+//===========================================
+// Lumina desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This is the main interface for any OS-specific system calls
+// To port Lumina to a different operating system, just create a file
+// called "OSInterface-<Operating System>.cpp"
+//===========================================
+#ifndef _LUMINA_LIBRARY_OS_INTERFACE_H
+#define _LUMINA_LIBRARY_OS_INTERFACE_H
+
+#include <QString>
+#include <QStringList>
+#include <QList>
+#include <QObject>
+#include <QVariant>
+#include <QHash>
+#include <QTimer>
+
+#include <QIODevice>
+#include <QFileSystemWatcher>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QSslError>
+#include <QHostInfo>
+#include <QHostAddress>
+
+class OSInterface : public QObject{
+ Q_OBJECT
+ // == QML ACCESSIBLE PROPERTIES ==
+ //Battery
+ Q_PROPERTY( float batteryCharge READ batteryCharge NOTIFY batteryChargeChanged)
+ Q_PROPERTY( bool batteryCharging READ batteryCharging NOTIFY batteryChargingChanged)
+ Q_PROPERTY( double batterySecondsLeft READ batterySecondsLeft NOTIFY batterySecondsLeftChanged)
+ //Volume
+ Q_PROPERTY( int volume READ volume WRITE setVolume NOTIFY volumeChanged)
+ //Network
+ Q_PROPERTY( bool networkAvailable READ networkAvailable NOTIFY networkStatusChanged)
+ Q_PROPERTY( QString networkType READ networkType NOTIFY networkStatusChanged)
+ Q_PROPERTY( float networkStrength READ networkStrength NOTIFY networkStatusChanged)
+ Q_PROPERTY( QString networkHostname READ networkHostname NOTIFY networkStatusChanged)
+ Q_PROPERTY( QHostAddress networkAddress READ networkAddress NOTIFY networkStatusChanged)
+ //Media
+ Q_PROPERTY( QStringList mediaShortcuts READ mediaShortcuts NOTIFY mediaShortcutsChanged)
+ //Updates
+ Q_PROPERTY( bool updatesAvailable READ updatesAvailable NOTIFY updateStatusChanged)
+ Q_PROPERTY( bool updatesRunning READ updatesRunning NOTIFY updateStatusChanged)
+ Q_PROPERTY( bool updatesFinished READ updatesFinished NOTIFY updateStatusChanged)
+ //Power options
+ Q_PROPERTY( bool canReboot READ canReboot NOTIFY powerAvailableChanged)
+ Q_PROPERTY( bool canShutdown READ canShutdown NOTIFY powerAvailableChanged)
+ Q_PROPERTY( bool canSuspend READ canSuspend NOTIFY powerAvailableChanged)
+ //Brightness
+ Q_PROPERTY( int brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged)
+
+public:
+ // ================
+ // SEMI-VIRTUAL FUNCTIONS - NEED TO BE DEFINED IN THE OS-SPECIFIC FILES
+ // ================
+ //Start/stop interface watchers/notifications
+ void start();
+ void stop();
+ bool isRunning(); //status of the object - whether it has been started yet
+
+ // = Battery =
+ Q_INVOKABLE bool batteryAvailable();
+ Q_INVOKABLE float batteryCharge();
+ Q_INVOKABLE bool batteryCharging();
+ Q_INVOKABLE double batterySecondsLeft();
+ // = Volume =
+ Q_INVOKABLE bool volumeAvailable();
+ Q_INVOKABLE int volume();
+ Q_INVOKABLE void setVolume(int);
+ // = Network Information =
+ Q_INVOKABLE bool networkAvailable();
+ Q_INVOKABLE QString networkType(); //"wifi", "wired", "cell", "cell-2G", "cell-3G", "cell-4G"
+ Q_INVOKABLE float networkStrength(); //percentage. ("wired" type should always be 100%)
+ Q_INVOKABLE QString networkHostname();
+ Q_INVOKABLE QHostAddress networkAddress();
+ // = Network Modification =
+
+ // = Media Shortcuts =
+ Q_INVOKABLE QStringList mediaDirectories(); //directory where XDG shortcuts are placed for interacting with media (local/remote)
+ Q_INVOKABLE QStringList mediaShortcuts(); //List of currently-available XDG shortcut file paths
+ // = Updates =
+ Q_INVOKABLE bool updatesAvailable();
+ Q_INVOKABLE QString updateDetails(); //Information about any available updates
+ Q_INVOKABLE bool updatesRunning();
+ Q_INVOKABLE QString updateLog(); //Information about any currently-running update
+ Q_INVOKABLE bool updatesFinished();
+ Q_INVOKABLE QString updateResults(); //Information about any finished update
+ Q_INVOKABLE void startUpdates();
+ Q_INVOKABLE bool updateOnlyOnReboot(); //Should the startUpdates function be called only when rebooting the system?
+ Q_INVOKABLE QDateTime lastUpdate(); //The date/time of the previous updates
+ Q_INVOKABLE QString lastUpdateResults(); //Information about the previously-finished update
+ // = System Power =
+ Q_INVOKABLE bool canReboot();
+ Q_INVOKABLE void startReboot();
+ Q_INVOKABLE bool canShutdown();
+ Q_INVOKABLE void startShutdown();
+ Q_INVOKABLE bool canSuspend();
+ Q_INVOKABLE void startSuspend();
+ // = Screen Brightness =
+ Q_INVOKABLE int brightness(); //percentage: 0-100 with -1 for errors
+ Q_INVOKABLE void setBrightness(int);
+ // = System Status Monitoring
+ Q_INVOKABLE QList<int> cpuPercentage(); // (one per CPU) percentage: 0-100 with -1 for errors
+ Q_INVOKABLE QStringList cpuTemperatures(); // (one per CPU) Temperature of CPU ("50C" for example)
+ Q_INVOKABLE int memoryUsedPercentage(); //percentage: 0-100 with -1 for errors
+ Q_INVOKABLE QString memoryTotal(); //human-readable form - does not tend to change within a session
+ Q_INVOKABLE QStringList diskIO(); //Returns list of current read/write stats for each device
+ Q_INVOKABLE int fileSystemPercentage(QString dir); //percentage of capacity used: 0-100 with -1 for errors
+ Q_INVOKABLE QString fileSystemCapacity(QString dir); //human-readable form - total capacity
+ // = OS-Specific Utilities =
+ Q_INVOKABLE bool hasControlPanel();
+ Q_INVOKABLE QString controlPanelShortcut(); //relative *.desktop shortcut name (Example: "some_utility.desktop")
+ Q_INVOKABLE bool hasAudioMixer();
+ Q_INVOKABLE QString audioMixerShortcut(); //relative *.desktop shortcut name (Example: "some_utility.desktop")
+ Q_INVOKABLE bool hasAppStore();
+ Q_INVOKABLE QString appStoreShortcut(); //relative *.desktop shortcut name (Example: "some_utility.desktop")
+
+private slots:
+ // ================
+ // SEMI-VIRTUAL FUNCTIONS - NEED TO BE DEFINED IN THE OS-SPECIFIC FILES
+ // ================
+ //FileSystemWatcher slots
+ void watcherFileChanged(QString);
+ void watcherDirChanged(QString);
+ //IO Device slots
+ void iodeviceReadyRead();
+ void iodeviceAboutToClose();
+ //NetworkAccessManager slots
+ void netAccessChanged(QNetworkAccessManager::NetworkAccessibility);
+ void netRequestFinished(QNetworkReply*);
+ void netSslErrors(QNetworkReply*, const QList<QSslError>&);
+ //Timer slots
+ void timerUpdate();
+
+signals:
+ void batteryChargeChanged();
+ void batteryChargingChanged();
+ void batterySecondsLeftChanged();
+ void volumeChanged();
+ void networkStatusChanged();
+ void mediaShortcutsChanged();
+ void updateStatusChanged();
+ void powerAvailableChanged();
+ void brightnessChanged();
+
+private:
+ //Internal persistant data storage, OS-specific usage implementation
+ QHash< QString, QVariant> INFO;
+
+ // ============
+ // Internal possibilities for watching the system (OS-Specific usage/implementation)
+ // ============
+ //File System Watcher
+ QFileSystemWatcher *watcher;
+ //IO Device (QLocalSocket, QTcpConnection, QFile, etc)
+ QIODevice *iodevice;
+ //Network Access Manager (check network connectivity, etc)
+ QNetworkAccessManager *netman;
+ //Timer for regular probes/updates
+ QTimer *timer;
+
+ // Internal implifications for connecting the various watcher objects to their respective slots
+ // (OS-agnostic - defined in the "OSInterface_private.cpp" file)
+ void connectWatcher(); //setup the internal connections *only*
+ void connectIodevice(); //setup the internal connections *only*
+ void connectNetman(); //setup the internal connections *only*
+ void connectTimer(); //setup the internal connections *only*
+
+ // External Media Management (if system uses *.desktop shortcuts only)
+ void setupMediaWatcher();
+ bool handleMediaDirChange(QString dir); //returns true if directory was handled
+ QStringList autoHandledMediaFiles();
+
+ // Qt-based NetworkAccessManager usage
+ void setupNetworkManager();
+
+public:
+ OSInterface(QObject *parent = 0);
+ ~OSInterface();
+
+ static OSInterface* instance(); //Get the currently-active instance of this class (or make a new one)
+
+};
+#endif
diff --git a/src-qt5/src-cpp/framework-OSInterface.pri b/src-qt5/src-cpp/framework-OSInterface.pri
new file mode 100644
index 00000000..be705e44
--- /dev/null
+++ b/src-qt5/src-cpp/framework-OSInterface.pri
@@ -0,0 +1,9 @@
+QT *= core network
+
+HEADERS *= $${PWD}/framework-OSInterface.h
+SOURCES *= $${PWD}/framework-OSInterface_private.cpp
+
+_os=template
+SOURCES *= $${PWD}/framework-OSInterface-$${_os}.cpp
+
+INCLUDEPATH *= $${PWD}
diff --git a/src-qt5/src-cpp/framework-OSInterface_private.cpp b/src-qt5/src-cpp/framework-OSInterface_private.cpp
new file mode 100644
index 00000000..d15d9be8
--- /dev/null
+++ b/src-qt5/src-cpp/framework-OSInterface_private.cpp
@@ -0,0 +1,110 @@
+//===========================================
+// Lumina desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// Internal, OS-agnostic functionality for managing the object itself
+//===========================================
+#include <framework-OSInterface.h>
+#include <QFile>
+#include <QDir>
+#include <QVariant>
+
+OSInterface::OSInterface(QObject *parent) : QObject(parent){
+ watcher = 0;
+ iodevice = 0;
+ netman = 0;
+}
+
+OSInterface::~OSInterface(){
+ if(watcher!=0){
+ QStringList paths; paths << watcher->files() << watcher->directories();
+ if(!paths.isEmpty()){ watcher->removePaths(paths); }
+ watcher->deleteLater();
+ }
+ if(iodevice!=0){
+ if(iodevice->isOpen()){ iodevice->close(); }
+ iodevice->deleteLater();
+ }
+ if(netman!=0){
+ netman->deleteLater();
+ }
+}
+
+OSInterface* OSInterface::instance(){
+ static OSInterface* m_os_object = 0;
+ if(m_os_object==0){
+ m_os_object = new OSInterface();
+ }
+ return m_os_object;
+}
+
+void OSInterface::connectWatcher(){
+ if(watcher==0){ return; }
+ connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(watcherFileChanged(QString)) );
+ connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(watcherDirChanged(QString)) );
+}
+
+void OSInterface::connectIodevice(){
+ if(iodevice==0){ return; }
+ connect(iodevice, SIGNAL(readyRead()), this, SLOT(iodeviceReadyRead()) );
+}
+
+void OSInterface::connectNetman(){
+ if(netman==0){ return; }
+ connect(netman, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(netAccessChanged(QNetworkAccessManager::NetworkAccessibility)) );
+ connect(netman, SIGNAL(finished(QNetworkReply*)), this, SLOT(netRequestFinished(QNetworkReply*)) );
+ connect(netman, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(netSslErrors(QNetworkReply*, const QList<QSslError>&)) );
+}
+
+void OSInterface::connectTimer(){
+ if(timer==0){ return; }
+ connect(timer, SIGNAL(timeout()), this, SLOT(timerUpdate()) );
+}
+
+// External Media Management (if system uses *.desktop shortcuts)
+void OSInterface::setupMediaWatcher(){
+ //Create/connect the watcher if needed
+ if(watcher == 0){ watcher = new QFileSystemWatcher(); connectWatcher(); }
+ QStringList dirs = this->mediaDirectories();
+ if(dirs.isEmpty()){ return; } //nothing to do
+ //Make sure each directory is scanned **right now** (if it exists)
+ for(int i=0; i<dirs.length(); i++){
+ if(QFile::exists(dirs[i])){
+ handleMediaDirChange(dirs[i]);
+ }
+ }
+}
+
+bool OSInterface::handleMediaDirChange(QString dir){ //returns true if directory was handled
+ if( !this->mediaDirectories().contains(dir) ){ return false; } //not a media directory
+ QDir qdir(dir);
+ QStringList files = qdir.entryList(QStringList() << "*.desktop", QDir::Files, QDir::Name);
+ for(int i=0; i<files.length(); i++){ files[i] = qdir.absoluteFilePath(files[i]); }
+ QString key = "media_files/"+dir;
+ if(files.isEmpty() && INFO.contains(key)){ INFO.remove(key); emit mediaShortcutsChanged(); } //no files for this directory at the moment
+ else{ INFO.insert("media_files/"+dir, files); emit mediaShortcutsChanged(); } //save these file paths for later
+ //Make sure the directory is still watched (sometimes the dir is removed/recreated on modification)
+ if(!watcher->directories().contains(dir)){ watcher->addPath(dir); }
+ return true;
+}
+
+QStringList OSInterface::autoHandledMediaFiles(){
+ QStringList files;
+ QStringList keys = INFO.keys().filter("media_files/");
+ for(int i=0; i<keys.length(); i++){
+ if(keys[i].startsWith("media_files/")){ files << INFO[keys[i]].toStringList(); }
+ }
+ return files;
+}
+
+// Qt-based NetworkAccessManager usage
+void OSInterface::setupNetworkManager(){
+ if(netman==0){
+ netman = new QNetworkAccessManager(this);
+ connectNetman();
+ }
+ //Load the initial state of the network accessibility
+ netAccessChanged(netman->networkAccessible());
+}
diff --git a/src-qt5/src-cpp/plugins-base.cpp b/src-qt5/src-cpp/plugins-base.cpp
new file mode 100644
index 00000000..f38374df
--- /dev/null
+++ b/src-qt5/src-cpp/plugins-base.cpp
@@ -0,0 +1,50 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "plugins-base.h"
+
+// ============
+// Base PLUGIN
+// ============
+BasePlugin::BasePlugin(){
+
+}
+
+BasePlugin::~BasePlugin(){
+
+}
+
+void BasePlugin::loadFile(QString path){
+ data = QJsonObject();
+ currentfile = path;
+ QFile file(path);
+ if(!file.exists() || !file.open(QIODevice::ReadOnly)){ return; }
+ data = QJsonDocument::fromJson(file.readAll()).object();
+ //qDebug() << "Loaded ScreenSaver Data:" << currentfile << data;
+ file.close();
+}
+
+QString BasePlugin::translatedObject(QString obj){
+ QJsonObject tmp = data.value(obj).toObject();
+ //Get the current locale
+ QString locale = getenv("LC_ALL");
+ if(locale.isEmpty()){ locale = getenv("LC_MEBaseAGES"); }
+ if(locale.isEmpty()){ locale = getenv("LANG"); }
+ if(locale.isEmpty()){ locale = "default"; }
+ if(locale.contains(".")){ locale = locale.section(".",0,0); } //chop any charset code off the end
+ //Now find which localized string is available and return it
+ if(tmp.contains(locale)){ return tmp.value(locale).toString(); }
+ locale = locale.section("_",0,0); //full locale not found - look for shortened form
+ if(tmp.contains(locale)){ return tmp.value(locale).toString(); }
+ return tmp.value("default").toString(); //use the default version
+}
+
+QUrl BasePlugin::scriptURL(){
+ QString exec = data.value("qml").toObject().value("exec").toString();
+ if(!exec.startsWith("/")){ exec.prepend( currentfile.section("/",0,-2)+"/" ); }
+ return QUrl::fromLocalFile(exec);
+}
+
diff --git a/src-qt5/src-cpp/plugins-base.h b/src-qt5/src-cpp/plugins-base.h
new file mode 100644
index 00000000..26b0eacc
--- /dev/null
+++ b/src-qt5/src-cpp/plugins-base.h
@@ -0,0 +1,107 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This is a simple class for managing all the various desktop
+// screensaver plugins that could be available
+//===========================================
+// NOTE:
+// This class has a heirarchy-based lookup system
+// USER plugins > SYSTEM plugins
+// XDG_DATA_HOME/lumina-desktop/screensavers > XDG_DATA_DIRS/lumina-desktop/screensavers
+//===========================================
+#ifndef _LUMINA_DESKTOP_BASE_PLUGINS_CLASS_H
+#define _LUMINA_DESKTOP_BASE_PLUGINS_CLASS_H
+
+#include <QJsonObject>
+#include <QString>
+#include <QUrl>
+#include <QObject>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QFile>
+#include <QDir>
+#include <QDebug>
+
+class BasePlugin{
+protected:
+ QString currentfile;
+
+public:
+ BasePlugin();
+ virtual ~BasePlugin();
+
+ virtual void loadFile(QString path);
+ bool isLoaded() { return !data.isEmpty(); };
+ bool containsDefault(QString obj) { return data.value(obj).toObject().contains("default"); }
+
+ /**
+ * Check if the plugin is valid as long as the JSON is not empty,
+ * it contains at least a "name", "qml", and "description" object,
+ * and the "name" and "description" objects contain a "default" key.
+ **/
+ virtual bool isValid() = 0;
+
+ virtual QString translatedObject(QString obj);
+ virtual QUrl scriptURL();
+
+ QJsonObject data; //Hazardous to manually modify
+ QString relDir;
+};
+
+class PluginSystem{
+public:
+ template <class T>
+ static T findPlugin(QString, QString);
+
+ template <class T>
+ static QList<T> findAllPlugins(QString, bool validonly=true);
+};
+
+// ===================
+// Base PLUGIN SYSTEM
+// ===================
+template <class T>
+T PluginSystem::findPlugin(QString name, QString REL_DIR){
+ //qDebug() << "FindPlugin:" << name;
+ T BaseP;
+ if(name.startsWith("/") && QFile::exists(name)){ BaseP.loadFile(name); return BaseP;} //absolute path give - just load that one
+ //Cleanup the input name and ensure it has the right suffix
+ name = name.section("/",-1);
+ if(!name.endsWith(".json")){ name.append(".json"); }
+ //Get the list of directories to search
+ QStringList dirs;
+ dirs << QString(getenv("XDG_DATA_HOME")) << QString(getenv("XDG_DATA_DIRS")).split(":");
+ //Look for that file within these directories and return the first one found
+ for(int i=0; i<dirs.length(); i++){
+ if(!QFile::exists(dirs[i]+REL_DIR+"/"+name)){ continue; }
+ BaseP.loadFile(dirs[i]+REL_DIR+"/"+name);
+ if(BaseP.isValid()){ break; } //got a good one - stop here
+ }
+ return BaseP;
+}
+
+template <class T>
+QList<T> PluginSystem::findAllPlugins(QString REL_DIR, bool validonly) {
+ QList<T> LIST;
+ //Get the list of directories to search
+ QStringList dirs;
+ dirs << QString(getenv("XDG_DATA_HOME")) << QString(getenv("XDG_DATA_DIRS")).split(":");
+ //Look for that file within these directories and return the first one found
+ for(int i=0; i<dirs.length(); i++){
+ if(!QFile::exists(dirs[i]+REL_DIR)){ continue; }
+ QDir dir(dirs[i]+REL_DIR);
+ QStringList files = dir.entryList(QStringList() << "*.json", QDir::Files, QDir::Name);
+ //qDebug() << "Found Files:" << files;
+ for(int j=0; j<files.length(); j++){
+ T tmp;
+ tmp.loadFile(dir.absoluteFilePath(files[j]));
+ //qDebug() << "Loaded File:" << files[j] << tmp.isValid();
+ if(!validonly || tmp.isValid()){ LIST << tmp; }
+ }
+ }
+ return LIST;
+}
+#endif
diff --git a/src-qt5/src-cpp/plugins-base.pri b/src-qt5/src-cpp/plugins-base.pri
new file mode 100644
index 00000000..4aa9d96e
--- /dev/null
+++ b/src-qt5/src-cpp/plugins-base.pri
@@ -0,0 +1,8 @@
+HEADERS *= $${PWD}/plugins-base.h \
+ $${PWD}/plugins-screensaver.h \
+ $${PWD}/plugins-desktop.h
+SOURCES *= $${PWD}/plugins-base.cpp \
+ $${PWD}/plugins-screensaver.cpp \
+ $${PWD}/plugins-desktop.cpp
+
+INCLUDEPATH *= $${PWD}
diff --git a/src-qt5/src-cpp/plugins-desktop.cpp b/src-qt5/src-cpp/plugins-desktop.cpp
new file mode 100644
index 00000000..fdbd676d
--- /dev/null
+++ b/src-qt5/src-cpp/plugins-desktop.cpp
@@ -0,0 +1,40 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "plugins-desktop.h"
+
+// ============
+// DT PLUGIN
+// ============
+DTPlugin::DTPlugin(){
+
+}
+
+DTPlugin::~DTPlugin(){
+
+}
+
+bool DTPlugin::isValid(){
+ if(data.isEmpty()){ return false; }
+ bool ok = data.contains("name") && data.contains("qml") && data.contains("description");
+ ok &= containsDefault("name");
+ ok &= containsDefault("description");
+ if(ok) {
+ QJsonObject tmp = data.value("qml").toObject();
+ QStringList mustexist;
+ QString exec = tmp.value("exec").toString();
+ if(exec.isEmpty() || !exec.endsWith(".qml")){ return false; }
+ mustexist << exec;
+ QJsonArray tmpA = data.value("additional_files").toArray();
+ for(int i=0; i<tmpA.count(); i++){ mustexist << tmpA[i].toString(); }
+ QString reldir = currentfile.section("/",0,-2) + "/";
+ for(int i=0; i<mustexist.length() && ok; i++){
+ if(mustexist[i].startsWith("/")){ ok = QFile::exists(mustexist[i]); }
+ else { ok = QFile::exists(reldir+mustexist[i]); }
+ }
+ }
+ return ok;
+}
diff --git a/src-qt5/src-cpp/plugins-desktop.h b/src-qt5/src-cpp/plugins-desktop.h
new file mode 100644
index 00000000..ed576db1
--- /dev/null
+++ b/src-qt5/src-cpp/plugins-desktop.h
@@ -0,0 +1,29 @@
+//===========================================
+// Lumina-desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_DESKTOP_PLUGINS_CLASS_H
+#define _LUMINA_DESKTOP_DESKTOP_PLUGINS_CLASS_H
+
+#include "plugins-base.h"
+#include <QJsonObject>
+#include <QString>
+#include <QUrl>
+#include <QObject>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QFile>
+#include <QDir>
+#include <QDebug>
+
+class DTPlugin : public BasePlugin{
+public:
+ DTPlugin();
+ ~DTPlugin();
+
+ virtual bool isValid() Q_DECL_OVERRIDE;
+};
+
+#endif
diff --git a/src-qt5/src-cpp/plugins-screensaver.cpp b/src-qt5/src-cpp/plugins-screensaver.cpp
index 4cb90aff..6370b068 100644
--- a/src-qt5/src-cpp/plugins-screensaver.cpp
+++ b/src-qt5/src-cpp/plugins-screensaver.cpp
@@ -5,14 +5,6 @@
// See the LICENSE file for full details
//===========================================
#include "plugins-screensaver.h"
-#include <QJsonDocument>
-#include <QJsonArray>
-#include <QFile>
-#include <QDir>
-#include <QDebug>
-
-//Relative directory to search along the XDG paths for screensavers
-#define REL_DIR QString("/lumina-desktop/screensavers")
// ============
// SS PLUGIN
@@ -25,35 +17,12 @@ SSPlugin::~SSPlugin(){
}
-void SSPlugin::loadFile(QString path){
- data = QJsonObject();
- currentfile = path;
- QFile file(path);
- if(!file.exists() || !file.open(QIODevice::ReadOnly)){ return; }
- data = QJsonDocument::fromJson(file.readAll()).object();
- qDebug() << "Loaded ScreenSaver Data:" << currentfile << data;
- file.close();
-}
-
-bool SSPlugin::isLoaded(){
- return !data.isEmpty();
-}
-
bool SSPlugin::isValid(){
if(data.isEmpty()){ return false; }
bool ok = data.contains("name") && data.contains("qml") && data.contains("description");
- if(ok){
- //go to the next name level and see if required sub-items exist
- QJsonObject tmp = data.value("name").toObject();
- ok = tmp.contains("default");
- }
- if(ok){
- //go to the next description level and see if required sub-items exist
- QJsonObject tmp = data.value("description").toObject();
- ok = tmp.contains("default");
- }
-if(ok){
- //go to the next qml level and see if required sub-items exist
+ ok &= containsDefault("name");
+ ok &= containsDefault("description");
+ if(ok) {
QJsonObject tmp = data.value("qml").toObject();
QStringList mustexist;
QString exec = tmp.value("exec").toString();
@@ -62,7 +31,6 @@ if(ok){
QJsonArray tmpA = data.value("additional_files").toArray();
for(int i=0; i<tmpA.count(); i++){ mustexist << tmpA[i].toString(); }
QString reldir = currentfile.section("/",0,-2) + "/";
- //qDebug() << "Got MustExist:" << mustexist << reldir;
for(int i=0; i<mustexist.length() && ok; i++){
if(mustexist[i].startsWith("/")){ ok = QFile::exists(mustexist[i]); }
else { ok = QFile::exists(reldir+mustexist[i]); }
@@ -70,83 +38,3 @@ if(ok){
}
return ok;
}
-
-QString SSPlugin::translatedName(){
- QJsonObject tmp = data.value("name").toObject();
- //Get the current locale
- QString locale = getenv("LC_ALL");
- if(locale.isEmpty()){ locale = getenv("LC_MESSAGES"); }
- if(locale.isEmpty()){ locale = getenv("LANG"); }
- if(locale.isEmpty()){ locale = "default"; }
- if(locale.contains(".")){ locale = locale.section(".",0,0); } //chop any charset code off the end
- //Now find which localized string is available and return it
- if(tmp.contains(locale)){ return tmp.value(locale).toString(); }
- locale = locale.section("_",0,0); //full locale not found - look for shortened form
- if(tmp.contains(locale)){ return tmp.value(locale).toString(); }
- return tmp.value("default").toString(); //use the default version
-}
-
-QString SSPlugin::translatedDescription(){
- QJsonObject tmp = data.value("description").toObject();
- //Get the current locale
- QString locale = getenv("LC_ALL");
- if(locale.isEmpty()){ locale = getenv("LC_MESSAGES"); }
- if(locale.isEmpty()){ locale = getenv("LANG"); }
- if(locale.isEmpty()){ locale = "default"; }
- if(locale.contains(".")){ locale = locale.section(".",0,0); } //chop any charset code off the end
- //Now find which localized string is available and return it
- if(tmp.contains(locale)){ return tmp.value(locale).toString(); }
- locale = locale.section("_",0,0); //full locale not found - look for shortened form
- if(tmp.contains(locale)){ return tmp.value(locale).toString(); }
- return tmp.value("default").toString(); //use the default version
-}
-
-QUrl SSPlugin::scriptURL(){
- QString exec = data.value("qml").toObject().value("exec").toString();
- qDebug() << "got exec:" << exec << data;
- if(!exec.startsWith("/")){ exec.prepend( currentfile.section("/",0,-2)+"/" ); }
- return QUrl::fromLocalFile(exec);
-}
-
-// ===================
-// SS PLUGIN SYSTEM
-// ===================
-SSPlugin SSPluginSystem::findPlugin(QString name){
- //qDebug() << "FindPlugin:" << name;
- SSPlugin SSP;
- if(name.startsWith("/") && QFile::exists(name)){ SSP.loadFile(name); return SSP;} //absolute path give - just load that one
- //Cleanup the input name and ensure it has the right suffix
- name = name.section("/",-1);
- if(!name.endsWith(".json")){ name.append(".json"); }
- //Get the list of directories to search
- QStringList dirs;
- dirs << QString(getenv("XDG_DATA_HOME")) << QString(getenv("XDG_DATA_DIRS")).split(":");
- //Look for that file within these directories and return the first one found
- for(int i=0; i<dirs.length(); i++){
- if(!QFile::exists(dirs[i]+REL_DIR+"/"+name)){ continue; }
- SSP.loadFile(dirs[i]+REL_DIR+"/"+name);
- if(SSP.isValid()){ break; } //got a good one - stop here
- }
- return SSP;
-}
-
-QList<SSPlugin> SSPluginSystem::findAllPlugins(bool validonly){
- QList<SSPlugin> LIST;
- //Get the list of directories to search
- QStringList dirs;
- dirs << QString(getenv("XDG_DATA_HOME")) << QString(getenv("XDG_DATA_DIRS")).split(":");
- //Look for that file within these directories and return the first one found
- for(int i=0; i<dirs.length(); i++){
- if(!QFile::exists(dirs[i]+REL_DIR)){ continue; }
- QDir dir(dirs[i]+REL_DIR);
- QStringList files = dir.entryList(QStringList() << "*.json", QDir::Files, QDir::Name);
- //qDebug() << "Found Files:" << files;
- for(int j=0; j<files.length(); j++){
- SSPlugin tmp;
- tmp.loadFile(dir.absoluteFilePath(files[j]));
- //qDebug() << "Loaded File:" << files[j] << tmp.isValid();
- if(!validonly || tmp.isValid()){ LIST << tmp; }
- }
- }
- return LIST;
-}
diff --git a/src-qt5/src-cpp/plugins-screensaver.h b/src-qt5/src-cpp/plugins-screensaver.h
index 9a7e98f5..042f824d 100644
--- a/src-qt5/src-cpp/plugins-screensaver.h
+++ b/src-qt5/src-cpp/plugins-screensaver.h
@@ -4,47 +4,26 @@
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
-// This is a simple class for managing all the various desktop
-// screensaver plugins that could be available
-//===========================================
-// NOTE:
-// This class has a heirarchy-based lookup system
-// USER plugins > SYSTEM plugins
-// XDG_DATA_HOME/lumina-desktop/screensavers > XDG_DATA_DIRS/lumina-desktop/screensavers
-//===========================================
#ifndef _LUMINA_DESKTOP_SCREENSAVER_PLUGINS_CLASS_H
#define _LUMINA_DESKTOP_SCREENSAVER_PLUGINS_CLASS_H
+#include "plugins-base.h"
#include <QJsonObject>
#include <QString>
#include <QUrl>
#include <QObject>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QFile>
+#include <QDir>
+#include <QDebug>
-class SSPlugin{
-private:
- QString currentfile;
-
+class SSPlugin : public BasePlugin {
public:
- QJsonObject data; //Hazardous to manually modify
-
SSPlugin();
~SSPlugin();
- void loadFile(QString path);
- bool isLoaded();
-
- bool isValid();
-
- QString translatedName();
- QString translatedDescription();
- QUrl scriptURL();
-};
-
-class SSPluginSystem{
-public:
- static SSPlugin findPlugin(QString name);
- static QList<SSPlugin> findAllPlugins(bool validonly = true);
-
+ virtual bool isValid() Q_DECL_OVERRIDE;
};
#endif
diff --git a/src-qt5/src-cpp/plugins-screensaver.pri b/src-qt5/src-cpp/plugins-screensaver.pri
deleted file mode 100644
index ad03f34c..00000000
--- a/src-qt5/src-cpp/plugins-screensaver.pri
+++ /dev/null
@@ -1,4 +0,0 @@
-HEADERS *= $${PWD}/plugins-screensaver.h
-SOURCES *= $${PWD}/plugins-screensaver.cpp
-
-INCLUDEPATH *= $${PWD}
diff --git a/src-qt5/src-cpp/tests/main.cpp b/src-qt5/src-cpp/tests/main.cpp
new file mode 100644
index 00000000..682c318a
--- /dev/null
+++ b/src-qt5/src-cpp/tests/main.cpp
@@ -0,0 +1,38 @@
+#include <QDebug>
+#include <QApplication>
+
+#include <framework-OSInterface.h>
+
+/*
+class tester : public QObject{
+ Q_OBJECT
+public slots:
+ void finished(){ QApplication::exit(0); }
+
+public:
+ QTimer *timer;
+
+ tester(){
+ timer = new QTimer(this);
+ timer->setInterval(5000);
+ timer->setSingleShot(true);
+ connect(timer, SIGNAL(timeout()), this, SLOT(finished()) );
+ }
+
+};
+*/
+
+int main(int argc, char** argv){
+
+ QApplication A(argc,argv);
+ OSInterface OS;
+ OS.start();
+ QTimer *timer = new QTimer();
+ timer->setInterval(5000);
+ timer->setSingleShot(true);
+ QObject::connect(timer, SIGNAL(timeout()), &A, SLOT(quit()) );
+ timer->start();
+ int ret = A.exec();
+ qDebug() << " - Finished";
+ return ret;
+}
diff --git a/src-qt5/src-cpp/tests/test.pro b/src-qt5/src-cpp/tests/test.pro
new file mode 100644
index 00000000..425e7de6
--- /dev/null
+++ b/src-qt5/src-cpp/tests/test.pro
@@ -0,0 +1,7 @@
+QT = core gui widgets
+
+include(../framework-OSInterface.pri)
+
+TARGET = test
+
+SOURCES += main.cpp
bgstack15