diff options
6 files changed, 205 insertions, 8 deletions
diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json index e01d6d2b..8d0d25c4 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json @@ -18,7 +18,7 @@ "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)", "date_created" : "20171010", "version" : "1.0" - } + }, "qml" : { "qml_file" : "qml_scripts/Fireflies.qml", "additional_files" : ["qml_scripts/Firefly.qml"] diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md index 768f0e14..d9093b44 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md @@ -13,22 +13,22 @@ Example JSON manifest file (sample.json): { "name" : { "default" : "sample", - "en_US" : "US English localization of the name" + "en_US" : "US English localization of the name", "en" : "Generic english localization of the name" - } + }, "description" : { "default" : "sample screensaver", "en_US" : "US English Localization of the description" - } + }, "author" : { "name" : "Me", "email" : "Me@myself.net", "website" : "http://mywebsite.net", - "company" : "iXsystems" + "company" : "iXsystems", "company_website" : "http://ixsystems.com" - } + }, "meta" : { "license" : "3-clause BSD", @@ -37,7 +37,7 @@ Example JSON manifest file (sample.json): "date_created" : "20171010", "date_updated" : "20171011", "version" : "1.0" - } + }, "qml" : { "exec" : "absolute/or/relative/path/to/script.qml", diff --git a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro index ba958401..9b0c2fb3 100644 --- a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro @@ -123,7 +123,7 @@ TRANSLATIONS = i18n/lumina-desktop_af.ts \ dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ -INSTALLS += target desktop defaults +INSTALLS += target desktop defaults extrafiles WITH_I18N{ INSTALLS += dotrans diff --git a/src-qt5/src-cpp/plugins-screensaver.cpp b/src-qt5/src-cpp/plugins-screensaver.cpp new file mode 100644 index 00000000..8271e7ac --- /dev/null +++ b/src-qt5/src-cpp/plugins-screensaver.cpp @@ -0,0 +1,143 @@ +//=========================================== +// 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-screensaver.h" +#include <QJsonDocument> + +//Relative directory to search along the XDG paths for screensavers +#define REL_DIR QString("/lumina-desktop/screensavers") + +// ============ +// SS PLUGIN +// ============ +SSPlugin::SSPlugin(){ + +} + +SSPlugin::~SSPlugin(){ + +} + +void SSPlugin::loadFile(QString path){ + data = QJsonObject(); + currentfile = path; + SSPlugin SSP; + QFile file(path); + if(!file.exists() || !file.open(QIODevice::ReadOnly)){ return SSP; } + SSP.data = QJsonDocument::fromJson(file.readAll()).object(); + file.close(); + return SSP; +} + +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 + QJsonObject tmp = data.value("qml").toObject(); + QStringList mustexist; + mustexist << tmp.value("exec").toString(); + ok = !mustexist.isEmpty(); //exec file should **always** be listed + 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; +} + +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(); + if(!exec.startsWith("/")){ exec.prepend( currentfile.section("/",0,-2)+"/" ); } + return QUrl::fromLocalFile(exec); +} + +// =================== +// SS PLUGIN SYSTEM +// =================== +SSPlugin SSPluginSystem::findPlugin(QString 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 = true){ + 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::Names); + for(int j=0; j<files.length(); j++){ + SSPlugin tmp; + tmp.loadFile(dir.canonicalFilePath(files[j])); + 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 new file mode 100644 index 00000000..9a7e98f5 --- /dev/null +++ b/src-qt5/src-cpp/plugins-screensaver.h @@ -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 +//=========================================== +// 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 <QJsonObject> +#include <QString> +#include <QUrl> +#include <QObject> + +class SSPlugin{ +private: + QString currentfile; + +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); + +}; + +#endif diff --git a/src-qt5/src-cpp/plugins-screensaver.pri b/src-qt5/src-cpp/plugins-screensaver.pri new file mode 100644 index 00000000..883a850f --- /dev/null +++ b/src-qt5/src-cpp/plugins-screensaver.pri @@ -0,0 +1,4 @@ +HEADERS *= $${PWD}/plugins-screensaver.h +SOURCES *= $${PWD}/plugins-screensaver.cpp + +INCLUDEPATH *= ${PWD} |