diff options
author | Weblate <noreply@weblate.org> | 2018-01-02 22:18:34 +0000 |
---|---|---|
committer | Weblate <noreply@weblate.org> | 2018-01-02 22:18:34 +0000 |
commit | 4bf6d3f38634dbb517055444a22d824d6eba99d8 (patch) | |
tree | bbe3e3e511f37222cdd9db145bde2f41a35e1260 /src-qt5 | |
parent | Translated using Weblate (Danish) (diff) | |
parent | Merge remote-tracking branch 'origin/master' (diff) | |
download | lumina-4bf6d3f38634dbb517055444a22d824d6eba99d8.tar.gz lumina-4bf6d3f38634dbb517055444a22d824d6eba99d8.tar.bz2 lumina-4bf6d3f38634dbb517055444a22d824d6eba99d8.zip |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src-qt5')
130 files changed, 4087 insertions, 1183 deletions
diff --git a/src-qt5/OS-detect.pri b/src-qt5/OS-detect.pri index 3d01ea5f..f7c65d6f 100644 --- a/src-qt5/OS-detect.pri +++ b/src-qt5/OS-detect.pri @@ -81,9 +81,6 @@ isEmpty(OS){ isEmpty(L_ETCDIR){ L_ETCDIR = $${PREFIX}/../etc } isEmpty(L_MANDIR){ L_MANDIR = $${PREFIX}/share/man } } - equals(LINUX_DISTRO,"Ubuntu"){ - INCLUDEPATH *= /usr/include/poppler/qt5 - } }else{ OS="Unknown"; } diff --git a/src-qt5/core-utils/lumina-config/lumina-config.pro b/src-qt5/core-utils/lumina-config/lumina-config.pro index 35f4b981..f36f67d6 100644 --- a/src-qt5/core-utils/lumina-config/lumina-config.pro +++ b/src-qt5/core-utils/lumina-config/lumina-config.pro @@ -115,13 +115,13 @@ TRANSLATIONS = i18n/lumina-config_af.ts \ i18n/lumina-config_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-config.desktop desktop.path=$${L_SHAREDIR}/applications/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-config.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-config.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-config.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-config.1.gz" INSTALLS += target desktop manpage diff --git a/src-qt5/core-utils/lumina-search/lumina-search.pro b/src-qt5/core-utils/lumina-search/lumina-search.pro index a8ea4060..42014c69 100644 --- a/src-qt5/core-utils/lumina-search/lumina-search.pro +++ b/src-qt5/core-utils/lumina-search/lumina-search.pro @@ -93,13 +93,13 @@ TRANSLATIONS = i18n/lumina-search_af.ts \ i18n/lumina-search_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-search.desktop desktop.path=$${L_SHAREDIR}/applications/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-search.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-search.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-search.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-search.1.gz" INSTALLS += target desktop manpage diff --git a/src-qt5/core-utils/lumina-xconfig/lumina-xconfig.pro b/src-qt5/core-utils/lumina-xconfig/lumina-xconfig.pro index 73399ee7..c6af2c3f 100644 --- a/src-qt5/core-utils/lumina-xconfig/lumina-xconfig.pro +++ b/src-qt5/core-utils/lumina-xconfig/lumina-xconfig.pro @@ -89,13 +89,13 @@ TRANSLATIONS = i18n/lumina-xconfig_af.ts \ i18n/lumina-xconfig_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-xconfig.desktop desktop.path=$${L_SHAREDIR}/applications/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-xconfig.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-xconfig.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-xconfig.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-xconfig.1.gz" INSTALLS += target desktop manpage diff --git a/src-qt5/core/libLumina/ExternalProcess.h b/src-qt5/core/libLumina/ExternalProcess.h index 2a6f4949..e75d6108 100644 --- a/src-qt5/core/libLumina/ExternalProcess.h +++ b/src-qt5/core/libLumina/ExternalProcess.h @@ -21,6 +21,7 @@ class ExternalProcess : public QProcess{ Q_OBJECT private: bool cursorRestored; + QString logoutput; private slots: void resetCursor(){ @@ -46,6 +47,9 @@ private slots: //Clean up this object this->deleteLater(); } + void updateLog(){ + logoutput.append( QString(this->readAllStandardOutput()) ); + } public: ExternalProcess(QString logfile = "", bool manageCursors = false) : QProcess(){ @@ -53,6 +57,8 @@ public: cursorRestored = !manageCursors; if(logfile.isEmpty()){ this->setStandardOutputFile(QProcess::nullDevice()); + }else if(logfile=="stdout"){ + connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(updateLog()) ); }else{ this->setStandardOutputFile(logfile); } @@ -67,6 +73,11 @@ public: }*/ } + QString log(){ + //NOTE: This will only contain output if the "stdout" argument is used as the logfile + return logoutput; + } + static void launch(QString program, QStringList args = QStringList(), bool manageCursors = true){ //Quick launch of a process with logging disabled and automatic cleanup ExternalProcess *tmp = new ExternalProcess("", manageCursors); diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index 69d4ba52..5595532a 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -13,10 +13,8 @@ #include "LuminaThemes.h" -static QStringList fav; - QString LDesktopUtils::LuminaDesktopVersion(){ - QString ver = "1.4.0"; + QString ver = "1.4.1"; #ifdef GIT_VERSION ver.append( QString(" (Git Revision: %1)").arg(GIT_VERSION) ); #endif @@ -80,22 +78,23 @@ QStringList LDesktopUtils::infoQuickPlugin(QString ID){ //Returns: [Name, Descri } QStringList LDesktopUtils::listFavorites(){ - static QDateTime lastRead; - QDateTime cur = QDateTime::currentDateTime(); - if(lastRead.isNull() || lastRead<QFileInfo( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list").lastModified()){ + //static QDateTime lastRead; + QStringList fav; + //QDateTime cur = QDateTime::currentDateTime(); + //if(lastRead.isNull() || fav.isEmpty() || lastRead<QFileInfo( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list").lastModified()){ fav = LUtils::readFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list"); fav.removeAll(""); //remove any empty lines fav.removeDuplicates(); - lastRead = cur; - } - + //lastRead = cur; + //} return fav; } bool LDesktopUtils::saveFavorites(QStringList list){ list.removeDuplicates(); + //qDebug() << "Save Favorites:" << list; bool ok = LUtils::writeFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/favorites.list", list, true); - if(ok){ fav = list; } //also save internally in case of rapid write/read of the file + //if(ok){ fav = list; } //also save internally in case of rapid write/read of the file return ok; } @@ -116,11 +115,13 @@ bool LDesktopUtils::addFavorite(QString path, QString name){ else{ type = LXDG::findAppMimeForFile(path); } //Assign a name if none given if(name.isEmpty()){ name = info.fileName(); } + //qDebug() << "Add Favorite:" << path << type << name; //Now add it to the list QStringList favs = LDesktopUtils::listFavorites(); + //qDebug() << "Current Favorites:" << favs; bool found = false; for(int i=0; i<favs.length(); i++){ - if(favs[i].endsWith("::::"+path)){ favs[i] = name+"::::"+type+"::::"+path; } + if(favs[i].endsWith("::::"+path)){ favs[i] = name+"::::"+type+"::::"+path; found = true; } } if(!found){ favs << name+"::::"+type+"::::"+path; } return LDesktopUtils::saveFavorites(favs); @@ -143,8 +144,15 @@ void LDesktopUtils::upgradeFavorites(int){ //fromoldversionnumber void LDesktopUtils::LoadSystemDefaults(bool skipOS){ //Will create the Lumina configuration files based on the current system template (if any) qDebug() << "Loading System Defaults"; + //Ensure that the settings directory exists + QString setdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop"; + if(!QFile::exists(setdir)){ + QDir dir; + dir.mkpath(setdir); + } + bool skipmime = QFile::exists( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-mimapps.list" ); - qDebug() << " - Skipping mimetype default apps" << skipmime; + //qDebug() << " - Skipping mimetype default apps" << skipmime; QStringList sysDefaults; if(!skipOS){ sysDefaults = LUtils::readFile(LOS::AppPrefix()+"etc/luminaDesktop.conf"); } if(sysDefaults.isEmpty() && !skipOS){ sysDefaults = LUtils::readFile(LOS::AppPrefix()+"etc/luminaDesktop.conf.dist"); } @@ -187,6 +195,8 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ if(var.endsWith("_ifexists") ){ var = var.remove("_ifexists"); //remove this flag from the variable //Check if the value exists (absolute path only) + val = LUtils::AppToAbsolute(val); + //qDebug() << "Checking if favorite app exists:" << val; if(!QFile::exists(val)){ continue; } //skip this line - value/file does not exist } @@ -231,20 +241,23 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ if(tmp[i].startsWith("#") || !tmp[i].contains("=") ){ continue; } QString var = tmp[i].section("=",0,0).toLower().simplified(); QString val = tmp[i].section("=",1,1).section("#",0,0).simplified(); + qDebug() << "Mime entry:" << var << val; if(val.isEmpty()){ continue; } QString istrue = (val.toLower()=="true") ? "true": "false"; //Change in 0.8.5 - use "_" instead of "." within variables names - need backwards compat for a little while if(var.contains(".")){ var.replace(".","_"); } //Now parse the variable and put the value in the proper file - val = LUtils::AppToAbsolute(val); //Special handling for values which need to exist first if(var.endsWith("_ifexists") ){ var = var.remove("_ifexists"); //remove this flag from the variable + val = LUtils::AppToAbsolute(val); + //qDebug() << "Checking if Mime app exists:" << val; //Check if the value exists (absolute path only) if(!QFile::exists(val)){ continue; } //skip this line - value/file does not exist } //Now turn this variable into the mimetype only var = var.section("_default_",1,-1); + //qDebug() << " - Set Default Mime:" << var << val; LXDG::setDefaultAppForMime(var, val); } @@ -326,6 +339,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ tmp = sysDefaults.filter("favorites_"); if(tmp.isEmpty()){ tmp = sysDefaults.filter("favorites."); } for(int i=0; i<tmp.length(); i++){ + //qDebug() << "Found Favorite Entry:" << tmp[i]; if(tmp[i].startsWith("#") || !tmp[i].contains("=") ){ continue; } QString var = tmp[i].section("=",0,0).toLower().simplified(); QString val = tmp[i].section("=",1,1).section("#",0,0).simplified(); @@ -334,7 +348,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ //Now parse the variable and put the value in the proper file qDebug() << "Favorite entry:" << var << val; val = LUtils::AppToAbsolute(val); //turn any relative files into absolute - if(var=="favorites_add_ifexists" && QFile::exists(val)){ qDebug() << " - Exists/Adding:"; LDesktopUtils::addFavorite(val); } + if(var=="favorites_add_ifexists" && QFile::exists(val)){ qDebug() << " - Exists/Adding:" << val; LDesktopUtils::addFavorite(val); } else if(var=="favorites_add"){ qDebug() << " - Adding:"; LDesktopUtils::addFavorite(val); } else if(var=="favorites_remove"){ qDebug() << " - Removing:"; LDesktopUtils::removeFavorite(val); } } @@ -385,6 +399,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ if(var.contains(".")){ var.replace(".","_"); } //Now parse the variable and put the value in the proper file if(var=="theme_themefile"){ themesettings[0] = val; } + else if(var=="theme_styles"){ LTHEME::setCurrentStyles( val.split(",",QString::SkipEmptyParts) ); } else if(var=="theme_colorfile"){ themesettings[1] = val; } else if(var=="theme_iconset"){ themesettings[2] = val; } else if(var=="theme_font"){ themesettings[3] = val; } @@ -425,12 +440,6 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ } //qDebug() << " - Final Theme Color:" << themesettings[1]; - //Ensure that the settings directory exists - QString setdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop"; - if(!QFile::exists(setdir)){ - QDir dir; - dir.mkpath(setdir); - } //Now save the settings files if(setTheme){ LTHEME::setCurrentSettings( themesettings[0], themesettings[1], themesettings[2], themesettings[3], themesettings[4]); @@ -538,7 +547,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ newtheme.setValue("Interface/desktop_stylesheets", QStringList() << enginedir+"desktop_qss/Glass.qss"); } newtheme.setValue("Appearance/style", "Fusion"); - newtheme.setValue("Interface/stylesheets", QStringList() << enginedir+"qss/tooltip-simple.qss" << enginedir+"qss/scrollbar-simple.qss" << enginedir+"qss/sliders-simple.qss"); + newtheme.setValue("Interface/stylesheets", QStringList() << enginedir+"qss/tooltip-simple.qss" << enginedir+"qss/scrollbar-simple.qss" << enginedir+"qss/sliders-simple.qss" << enginedir+"qss/traynotification-simple.qss"); newtheme.sync(); //flush this to file right now } //end check for theme file existance } @@ -569,7 +578,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ } int LDesktopUtils::VersionStringToNumber(QString version){ - version = version.section("-",0,0); //trim any extra labels off the end + version = version.section("_",0,0).section("-",0,0); //trim any extra labels off the end int maj, mid, min; //major/middle/minor version numbers (<Major>.<Middle>.<Minor>) maj = mid = min = 0; bool ok = true; diff --git a/src-qt5/core/libLumina/LUtils.pri b/src-qt5/core/libLumina/LUtils.pri index 6ce0839c..da5a78d5 100644 --- a/src-qt5/core/libLumina/LUtils.pri +++ b/src-qt5/core/libLumina/LUtils.pri @@ -15,8 +15,7 @@ GIT_VERSION=$$system(git describe --always) #DEFINES += BUILD_DATE='"\\\"$$system(date)\\\""' #LuminaOS files -HEADERS *= $${PWD}/LuminaOS.h \ - $${PWD}/OSInterface.h +HEADERS *= $${PWD}/LuminaOS.h # LuminaOS support functions (or fall back to generic one) exists($${PWD}/LuminaOS-$${LINUX_DISTRO}.cpp){ @@ -26,13 +25,6 @@ exists($${PWD}/LuminaOS-$${LINUX_DISTRO}.cpp){ }else{ SOURCES *= $${PWD}/LuminaOS-template.cpp } -exists($${PWD}/OSInterface-$${LINUX_DISTRO}.cpp){ - SOURCES *= $${PWD}/OSInterface-$${LINUX_DISTRO}.cpp -}else:exists($${PWD}/OSInterface-$${OS}.cpp){ - SOURCES *= $${PWD}/OSInterface-$${OS}.cpp -}else{ - SOURCES *= $${PWD}/OSInterface-template.cpp -} #LUtils Files SOURCES *= $${PWD}/LUtils.cpp diff --git a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp index dc7de37f..1ee8fb8a 100644 --- a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp +++ b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp @@ -30,7 +30,7 @@ QString LOS::AppStoreShortcut(){ return "/usr/local/share/applications/appcafe.d QStringList LOS::RSSFeeds(){ QStringList feeds; feeds << "FreeBSD News Feed::::https://www.freebsd.org/news/rss.xml"; - feeds << "TrueOS News Feed::::http://www.trueos.org/?feed=rss2"; + feeds << "TrueOS News Feed::::http://www.trueos.org/feed/"; return feeds; } diff --git a/src-qt5/core/libLumina/LuminaSingleApplication.cpp b/src-qt5/core/libLumina/LuminaSingleApplication.cpp index 5d276805..6107aff8 100644 --- a/src-qt5/core/libLumina/LuminaSingleApplication.cpp +++ b/src-qt5/core/libLumina/LuminaSingleApplication.cpp @@ -11,7 +11,7 @@ #include <QDebug> #include <QX11Info> -#include <unistd.h> //for getlogin() +#include <unistd.h> //for getuid() LSingleApplication::LSingleApplication(int &argc, char **argv, QString appname) : QApplication(argc, argv){ //Load the proper translation systems @@ -19,7 +19,7 @@ LSingleApplication::LSingleApplication(int &argc, char **argv, QString appname) if(appname!="lumina-desktop"){ cTrans = LUtils::LoadTranslation(this, appname); }//save the translator for later //Initialize a couple convenience internal variables cfile = QDir::tempPath()+"/.LSingleApp-%1-%2-%3"; - QString username = QString(getuid()); + QString username = QString::number(getuid()); //For locking the process use the official process name - not the user input (no masking) appname = this->applicationName(); cfile = cfile.arg( username, appname, QString::number(QX11Info::appScreen()) ); diff --git a/src-qt5/core/libLumina/LuminaThemes.cpp b/src-qt5/core/libLumina/LuminaThemes.cpp index 857e604b..03524941 100644 --- a/src-qt5/core/libLumina/LuminaThemes.cpp +++ b/src-qt5/core/libLumina/LuminaThemes.cpp @@ -34,6 +34,17 @@ QStringList LTHEME::availableSystemThemes(){ return list; } +QStringList LTHEME::availableSystemStyles(){ + //returns: [name::::path] for each item + QDir dir(LOS::LuminaShare()+"../lthemeengine/qss"); + QStringList list = dir.entryList(QStringList() <<"*.qss", QDir::Files, QDir::Name); + for(int i=0; i<list.length(); i++){ + //Format the output entry [<name>::::<fullpath>] + list[i] = list[i].section(".qss",0,0)+"::::"+dir.absoluteFilePath(list[i]); + } + return list; +} + QStringList LTHEME::availableLocalThemes(){ //returns: [name::::path] for each item QDir dir( QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/desktop_qss"); QStringList list = dir.entryList(QStringList() <<"*.qss", QDir::Files, QDir::Name); @@ -44,6 +55,16 @@ QStringList LTHEME::availableLocalThemes(){ //returns: [name::::path] for each i return list; } +QStringList LTHEME::availableLocalStyles(){ //returns: [name::::path] for each item + QDir dir( QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/qss"); + QStringList list = dir.entryList(QStringList() <<"*.qss", QDir::Files, QDir::Name); + for(int i=0; i<list.length(); i++){ + //Format the output entry [<name>::::<fullpath>] + list[i] = list[i].section(".qss",0,0)+"::::"+dir.absoluteFilePath(list[i]); + } + return list; +} + QStringList LTHEME::availableSystemColors(){ //returns: [name::::path] for each item //returns: [name::::path] for each item QDir dir(LOS::LuminaShare()+"../lthemeengine/colors"); @@ -244,6 +265,23 @@ bool LTHEME::setCursorTheme(QString cursorname){ return LUtils::writeFile(QDir::homePath()+"/.icons/default/index.theme", info, true); } +bool LTHEME::setCurrentStyles(QStringList paths){ + //Verify that the paths are all absolute paths, otherwise scan/replace with absolute paths + QStringList avail = LTHEME::availableSystemStyles(); + for(int i=0; i<paths.length(); i++){ + paths[i] = paths[i].simplified(); + if(paths[i].startsWith("/")){ continue; } //already an absolute path + for(int j=0; j<avail.length(); j++){ + if(avail[j].startsWith(paths[i].section("/",-1).section(".qss",0,0)+"::::") ){ paths[i] = avail[j].section("::::",1,-1); break; } + } + } + //ordered by priority: lowest -> highest + QSettings engineset("lthemeengine","lthemeengine"); + engineset.setValue("Interface/stylesheets",paths); + engineset.sync(); + return true; +} + //Return the complete stylesheet for a given theme/colors QString LTHEME::assembleStyleSheet(QString themepath, QString colorpath, QString font, QString fontsize){ QString stylesheet = LUtils::readFile(themepath).join("\n"); @@ -340,10 +378,10 @@ void LTHEME::LoadCustomEnvSettings(){ setenv(info[i].section("=",0,0).toLocal8Bit(), info[i].section("=",1,100).simplified().toLocal8Bit(), 1); } } - + } -bool LTHEME::setCustomEnvSetting(QString var, QString val){ +bool LTHEME::setCustomEnvSetting(QString var, QString val){ //variable/value pair (use an empty val to clear it) QStringList info = LTHEME::CustomEnvSettings(true); //user only bool changed = false; diff --git a/src-qt5/core/libLumina/LuminaThemes.h b/src-qt5/core/libLumina/LuminaThemes.h index ca79e0bd..133bd04d 100644 --- a/src-qt5/core/libLumina/LuminaThemes.h +++ b/src-qt5/core/libLumina/LuminaThemes.h @@ -25,7 +25,9 @@ class LTHEME{ public: //Read the Themes/Colors/Icons that are available on the system static QStringList availableSystemThemes();//returns: [name::::path] for each item + static QStringList availableSystemStyles();//returns: [name::::path] for each item static QStringList availableLocalThemes(); //returns: [name::::path] for each item + static QStringList availableLocalStyles(); //returns: [name::::path] for each item static QStringList availableSystemColors(); //returns: [name::::path] for each item static QStringList availableLocalColors(); //returns: [name::::path] for each item static QStringList availableSystemIcons(); //returns: [name] for each item @@ -42,6 +44,7 @@ public: //Change the current Theme/Colors/Icons static bool setCurrentSettings(QString themepath, QString colorpath, QString iconname, QString font, QString fontsize); static bool setCursorTheme(QString cursorname); + static bool setCurrentStyles(QStringList paths); //ordered by priority: lowest -> highest //Return the complete stylesheet for a given theme/colors static QString assembleStyleSheet(QString themepath, QString colorpath, QString font, QString fontsize); diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp index 1933ba93..e1c582d9 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -1294,6 +1294,7 @@ QStringList LXDG::findAvailableAppsForMime(QString mime){ } void LXDG::setDefaultAppForMime(QString mime, QString app){ + //qDebug() << "Set Default App For Mime:" << mime << app; QString filepath = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-mimeapps.list"; QStringList cinfo = LUtils::readFile(filepath); //If this is a new file, make sure to add the header appropriately diff --git a/src-qt5/core/libLumina/OSInterface-template.cpp b/src-qt5/core/libLumina/OSInterface-template.cpp deleted file mode 100644 index 96b01e60..00000000 --- a/src-qt5/core/libLumina/OSInterface-template.cpp +++ /dev/null @@ -1,100 +0,0 @@ -//=========================================== -// Lumina desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include <OSInterface.h> - -//=========== -// PUBLIC -//=========== - -//Simple functions used to determine if the current OS supports using this class, and what levels of support -QList<OSInterface::Interface> OSInterface::supportedNotifications(){ - //Which interfaces provide change notifications - return QList< OSInterface::Interface >(); -} - -QList<OSInterface::Interface> OSInterface::supportedStatus(){ - //Which interfaces are available for "status" requests - return QList< OSInterface::Interface >(); -} - -QList<OSInterface::Interface> OSInterface::supportedModify(){ - //Which interfaces are available for "modify" requests - return QList< OSInterface::Interface >(); -} - -//Start/stop interface watchers/notifications (each only called once per session) -void OSInterface::start(){ - //nothing to do -} - -void OSInterface::stop(){ - //nothing to do -} - -//Generic status update -QList<QVariant> OSInterface::status(OSInterface::Interface){ - // ==== Interface status output lists ==== - // Battery: [ float (percent charge), bool (is Charging), double (seconds remaining) ]; - // Volume: [int (percent volume) ] - // Devices: [ QStringList[ name, mountpoint, type (optional)] ] (List length depends on number of devices) - // Network: [bool (network access available)] - // PowerOff: [bool (can power off system)] - // Reboot: [bool (can reboot system)] - // Suspend: [bool (can suspend system)] - // Updates: [bool (is updating), bool (reboot required)] - // ========== - return QList<QVariant>(); -} - -//Individual Interface interactions -bool OSInterface::modify(OSInterface::Interface, QList<QVariant>){ //returns: success/failure - // ==== Interface modification argument lists ==== - // Battery: <NO MODIFICATION> - // Volume: [int (set percent volume) ] - // Devices: <NO MODIFICATION> - // Network: <NO MODIFICATION> - // PowerOff: [bool (skip updates - optional)] - // Reboot: [bool (skip updates - optional)] - // Suspend: [] (No input arguments) - // Updates: <NO MODIFICATION> - // ========== - return false; -} - -//================= -// PRIVATE SLOTS -//================= -//FileSystemWatcher slots -void OSInterface::watcherFileChanged(QString){ - -} - -void OSInterface::watcherDirChanged(QString){ - -} - -//IO Device slots -void OSInterface::iodeviceReadyRead(){ - -} - -void OSInterface::iodeviceAboutToClose(){ - -} - -//NetworkAccessManager slots -void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility){ - -} - -void OSInterface::netRequestFinished(QNetworkReply*){ - -} - -void OSInterface::netSslErrors(QNetworkReply*, const QList<QSslError>&){ - -} diff --git a/src-qt5/core/libLumina/OSInterface.h b/src-qt5/core/libLumina/OSInterface.h deleted file mode 100644 index acbd5c38..00000000 --- a/src-qt5/core/libLumina/OSInterface.h +++ /dev/null @@ -1,136 +0,0 @@ -//=========================================== -// 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 <QIODevice> -#include <QFileSystemWatcher> -#include <QNetworkAccessManager> -#include <QNetworkReply> -#include <QSslError> - -class OSInterface : public QObject{ - Q_OBJECT - -public: - enum Interface{ Battery, Volume, Devices, Network, PowerOff, Reboot, Suspend, Updates }; - -private slots: - //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>&); - -private: - //Internal persistant data storage, OS-specific usage implementation - QHash< OSInterface::Interface, QList<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; - - //Simplifications for connecting the various watcher objects to their respective slots - void connectWatcher(){ - if(watcher==0){ return; } - connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(watcherFileChanged(QString)) ); - connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(watcherDirChanged(QString)) ); - } - void connectIodevice(){ - if(iodevice==0){ return; } - connect(iodevice, SIGNAL(readyRead()), this, SLOT(iodeviceReadyRead()) ); - } - void connectNetman(){ - if(netman==0){ return; } - connect(netman, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(netAccessChanged(QNetworkAccessManager::NetworkAccessibility)) ); - connect(netman, SIGNAL(requestFinished(QNetworkReply*)), this, SLOT(netRequestFinished(QNetworkReply*)) ); - connect(netman, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(netSslErrors(QNetworkReply*, const QList<QSslError>&)) ); - } - -public: - OSInterface(QObject *parent = 0) : QObject(parent){ - watcher = 0; - iodevice = 0; - netman = 0; - } - ~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(); - } - } - - //Simple functions used to determine if the current OS supports using this class, and what levels of support - QList<OSInterface::Interface> supportedNotifications(); //Which interfaces provide change notifications - QList<OSInterface::Interface> supportedStatus(); //Which interfaces are available for "status" requests - QList<OSInterface::Interface> supportedModify(); //Which interfaces are available for "modify" requests - - //Start/stop interface watchers/notifications (each only called once per session) - void start(); - void stop(); - - //Generic status update - QList<QVariant> status(OSInterface::Interface); - // ==== Interface status output lists ==== - // Battery: [ float (percent charge), bool (is Charging), double (seconds remaining) ]; - // Volume: [int (percent volume) ] - // Devices: [ QStringList[ name, mountpoint, type (optional)] ] (List length depends on number of devices) - // Network: [bool (network access available)] - // PowerOff: [bool (can power off system)] - // Reboot: [bool (can reboot system)] - // Suspend: [bool (can suspend system)] - // Updates: [bool (is updating), bool (reboot required)] - // ========== - - //Individual Interface interactions - bool modify(OSInterface::Interface, QList<QVariant> args); //returns: success/failure - // ==== Interface modification argument lists ==== - // Battery: <NO MODIFICATION> - // Volume: [int (set percent volume) ] - // Devices: <NO MODIFICATION> - // Network: <NO MODIFICATION> - // PowerOff: [bool (skip updates - optional)] - // Reboot: [bool (skip updates - optional)] - // Suspend: [] (No input arguments) - // Updates: <NO MODIFICATION> - // ========== - -signals: - void interfaceChanged(OSInterface::Interface); - -}; -#endif diff --git a/src-qt5/core/lumina-desktop-unified/LSession.cpp b/src-qt5/core/lumina-desktop-unified/LSession.cpp index e1251c01..ed4d644b 100644 --- a/src-qt5/core/lumina-desktop-unified/LSession.cpp +++ b/src-qt5/core/lumina-desktop-unified/LSession.cpp @@ -22,6 +22,7 @@ QThread* Lumina::EVThread = 0; RootWindow* Lumina::ROOTWIN = 0; XDGDesktopList* Lumina::APPLIST = 0; LShortcutEvents* Lumina::SHORTCUTS = 0; +DesktopManager* Lumina::DESKMAN = 0; LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lumina-desktop-unified"){ //Initialize the global objects to null pointers @@ -49,10 +50,11 @@ LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lu Lumina::NEF = new NativeEventFilter(); Lumina::NWS = new NativeWindowSystem(); Lumina::SS = new LScreenSaver(); + Lumina::DESKMAN = new DesktopManager(); //Now put the Native Window System into it's own thread to keep things snappy Lumina::EVThread = new QThread(); - //Lumina::NWS->moveToThread(Lumina::EVThread); - //Lumina::EVThread->start(); + Lumina::DESKMAN->moveToThread(Lumina::EVThread); + Lumina::EVThread->start(); Lumina::APPLIST = XDGDesktopList::instance(); Lumina::ROOTWIN = new RootWindow(); Lumina::SHORTCUTS = new LShortcutEvents(); //this can be moved to it's own thread eventually as well @@ -73,6 +75,7 @@ LSession::~LSession(){ if(DesktopSettings::instance()!=0){ DesktopSettings::instance()->deleteLater(); } if(Lumina::ROOTWIN!=0){ Lumina::ROOTWIN->deleteLater(); } if(Lumina::APPLIST!=0){ Lumina::APPLIST->deleteLater(); } + if(Lumina::DESKMAN!=0){ Lumina::DESKMAN->deleteLater(); } } void LSession::setupSession(){ @@ -104,6 +107,10 @@ void LSession::setupSession(){ splash.showScreen("user"); if(DEBUG){ qDebug() << " - Init User Files:" << timer->elapsed();} //checkUserFiles(); //adds these files to the watcher as well + Lumina::NWS->setRoot_numberOfWorkspaces(QStringList() << "one" << "two"); + Lumina::NWS->setRoot_currentWorkspace(0); + + Lumina::DESKMAN->start(); Lumina::ROOTWIN->start(); //Initialize the internal variables //DESKTOPS.clear(); @@ -124,14 +131,12 @@ void LSession::setupSession(){ //Initialize the desktops splash.showScreen("desktop"); - if(DEBUG){ qDebug() << " - Init Desktops:" << timer->elapsed(); } + /*if(DEBUG){ qDebug() << " - Init Desktops:" << timer->elapsed(); } QList<QScreen*> scrns= QApplication::screens(); for(int i=0; i<scrns.length(); i++){ qDebug() << " --- Load Wallpaper for Screen:" << scrns[i]->name(); RootDesktopObject::instance()->ChangeWallpaper(scrns[i]->name(),QUrl::fromLocalFile(LOS::LuminaShare()+"desktop-background.jpg").toString() ); - } - Lumina::NWS->setRoot_numberOfWorkspaces(QStringList() << "one" << "two"); - Lumina::NWS->setRoot_currentWorkspace(0); + }*/ if(DEBUG){ qDebug() << " - Create Desktop Context Menu"; } diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Grav.json b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Grav.json new file mode 100644 index 00000000..8d75d399 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Grav.json @@ -0,0 +1,25 @@ +{ + "name" : { + "default" : "Grav" + }, + "description" : { + "default" : "Simulates a solar system, with a single star and planets erratically orbiting that star" + }, + "author" : { + "name" : "Zackary Welch", + "email" : "zwelch@ixsystems.com", + "website" : "https://github.com/ZackaryWelch", + "company" : "iXsystems", + "company_website" : "http://ixsystems.com" + }, + "meta" : { + "license" : "3-clause BSD", + "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE", + "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)", + "date_created" : "20171101", + "version" : "1.0" + }, + "qml" : { + "exec" : "qml_scripts/Grav.qml" + } +} diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml index 7a3c33cd..d1e5d3c9 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml @@ -4,11 +4,13 @@ import QtGraphicalEffects 1.0 Rectangle { id : canvas anchors.fill: parent - width: 800 - height: 600 + width: Screen.width + height: Screen.height color: "black" //TODO Add orbital trails option + //TODO Fix jitteryness and start position + //TODO Make orbits more extreme //Between 5 and 15 planets, read from settings property int planets: Math.round(( Math.random() * 10 ) + 5 ) @@ -30,6 +32,7 @@ Rectangle { property double a: Math.sqrt(b*b+c*c) //Random angle of rotation property double th: Math.random() * Math.PI + property var path: [] //Calculates starting position x: Math.round(cx + a * Math.cos(th)) @@ -45,34 +48,40 @@ Rectangle { //Give each planet a random color, semi-transparent color: Qt.rgba(Math.random(), Math.random(), Math.random(), 0.5) - Timer { + /*Timer { //Each planet updates between 1ms and 51ms (smaller times=faster) interval: Math.round(Math.random() * 50 ) + 1 repeat: true running: true - property bool starting: true property int time: 0 onTriggered: { - //Move a planet 80 pixels away from the sun if the planet is too close - if(starting) { - if(x > cx && Math.abs(cx-x) < 80) { - x+=80 - }else if(x < cx && Math.abs(cx-x) < 80) { - x-=80 - } - - if(y > cy && Math.abs(cy-y) < 80) { - y+=80 - }else if(y < cy && Math.abs(cy-y) < 80) { - y-=80 - } - starting = false; - } //Parametric equation that calculates the position of the general ellipse. Completes a loop ever 314 cycles. Credit to x = cx+a*Math.cos(2*Math.PI*(time/314.0))*Math.cos(th) - b*Math.sin(2*Math.PI*(time/314.0))*Math.sin(th) y = cy+a*Math.cos(2*Math.PI*(time/314.0))*Math.sin(th) + b*Math.sin(2*Math.PI*(time/314.0))*Math.cos(th) time++; + + //Move a planet 80 pixels away from the sun if the planet is too close + if(x > cx && Math.abs(cx-x) < 80) { + x+=80 + }else if(x < cx && Math.abs(cx-x) < 80) { + x-=80 + } + + if(y > cy && Math.abs(cy-y) < 80) { + y+=80 + }else if(y < cy && Math.abs(cy-y) < 80) { + y-=80 + } + } + }*/ + + Component.onCompleted: { + pahtX[0] = x + pahtY[0] = y + for(int i = 1; i <= 200; i++) { + pathX[i] = cx+a*Math.cos(2*Math.PI*(i/200.0)*Math.cos(th) - b*Math.sin(2*Math.PI*(i/200.0)*Math.sin(th) + pathY[i] = cy+a*Math.cos(2*Math.PI*(i/200.0)*Math.sin(th) + b*Math.sin(2*Math.PI*(i/200.0)*Math.cos(th) } } } diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Video.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Video.qml index e7d0626d..9948537b 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Video.qml +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Video.qml @@ -4,10 +4,8 @@ import QtQuick.Window 2.2 import Qt.labs.folderlistmodel 2.1 Rectangle { - //width: Screen.width - //height: Screen.height - width: 800 - height: 600 + width: Screen.width + height: Screen.height color: "black" FolderListModel { diff --git a/src-qt5/core/lumina-desktop-unified/global-includes.h b/src-qt5/core/lumina-desktop-unified/global-includes.h index 40987ad4..fbc3c4f7 100644 --- a/src-qt5/core/lumina-desktop-unified/global-includes.h +++ b/src-qt5/core/lumina-desktop-unified/global-includes.h @@ -59,10 +59,6 @@ #include <QQmlEngine> #include <QQuickImageProvider> -// C++ Backend classes for QML interface -#include <RootDesktopObject.h> -#include <ScreenObject.h> - // libLumina includes #include <LuminaX11.h> #include <LuminaXDG.h> @@ -80,6 +76,9 @@ #include <LIconCache.h> #include <LFileInfo.h> +// C++ Backend classes for QML interface +#include <RootDesktopObject.h> +#include <ScreenObject.h> //Setup any global defines (no classes or global objects: use "global-objects.h" for that) diff --git a/src-qt5/core/lumina-desktop-unified/global-objects.h b/src-qt5/core/lumina-desktop-unified/global-objects.h index c204587f..4cea60c2 100644 --- a/src-qt5/core/lumina-desktop-unified/global-objects.h +++ b/src-qt5/core/lumina-desktop-unified/global-objects.h @@ -22,9 +22,10 @@ //#include "src-events/LXcbEventFilter.h" //#endif #include "src-events/LShortcutEvents.h" - +#include "src-desktop/DesktopManager.h" #include "src-screensaver/LScreenSaver.h" //#include "src-WM/LWindowManager.h" + #include <RootWindow.h> #include "LSession.h" @@ -43,13 +44,13 @@ namespace Lumina{ //extern EventFilter *EFILTER; //Native Event Watcher extern LShortcutEvents *SHORTCUTS; //Keyboard/mouse shortcut events - //extern DesktopSettings *SETTINGS; //All Settings files + //ScreenSaver extern LScreenSaver *SS; //Root Window extern RootWindow *ROOTWIN; - //Window Manager - //LWindowManager *WM; + //Desktop Manager + extern DesktopManager *DESKMAN; //Application List extern XDGDesktopList *APPLIST; diff --git a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro index 21e46b22..bb987e25 100644 --- a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro @@ -24,7 +24,7 @@ include(../libLumina/ExternalProcess.pri) include(../../src-cpp/NativeWindow.pri) include(../libLumina/XDGMime.pri) -include(../../src-cpp/plugins-screensaver.pri) +include(../../src-cpp/plugins-base.pri) #include all the main individual source groups include(src-screensaver/screensaver.pri) @@ -124,7 +124,7 @@ TRANSLATIONS = i18n/lumina-desktop_af.ts \ i18n/lumina-desktop_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ INSTALLS += target desktop defaults extrafiles diff --git a/src-qt5/core/lumina-desktop-unified/main.cpp b/src-qt5/core/lumina-desktop-unified/main.cpp index ed2b9b4c..3cf35e50 100644 --- a/src-qt5/core/lumina-desktop-unified/main.cpp +++ b/src-qt5/core/lumina-desktop-unified/main.cpp @@ -39,11 +39,11 @@ int main(int argc, char ** argv) QTime *timer=0; if(DEBUG){ timer = new QTime(); timer->start(); } if(DEBUG){ qDebug() << "Theme Init:" << timer->elapsed(); } - LuminaThemeEngine theme(&a); - QObject::connect(&theme, SIGNAL(updateIcons()), &a, SLOT(reloadIconTheme()) ); + /*LuminaThemeEngine theme(&a); + QObject::connect(&theme, SIGNAL(updateIcons()), &a, SLOT(reloadIconTheme()) );*/ if(DEBUG){ qDebug() << "Session Setup:" << timer->elapsed(); } QTimer::singleShot(0, &a, SLOT(setupSession()) ); - theme.refresh(); + //theme.refresh(); if(DEBUG){ qDebug() << "Exec Time:" << timer->elapsed(); delete timer;} int retCode = a.exec(); qDebug() << "Finished Closing Down Unified Lumina"; diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp new file mode 100644 index 00000000..d6d06be9 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp @@ -0,0 +1,139 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017-2018, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "DesktopManager.h" + +#include "global-objects.h" + +// === PUBLIC === +DesktopManager::DesktopManager(){ + +} + +DesktopManager::~DesktopManager(){ + +} + +void DesktopManager::start(){ + connect(DesktopSettings::instance(), SIGNAL(FileModified(DesktopSettings::File)), this, SLOT(settingsChanged(DesktopSettings::File)) ); + //Perform the initial load of the settings files + QTimer::singleShot(0, this, SLOT(updateDesktopSettings()) ); + QTimer::singleShot(0, this, SLOT(updatePanelSettings()) ); + QTimer::singleShot(0, this, SLOT(updatePluginSettings()) ); + QTimer::singleShot(0, this, SLOT(updateMenuSettings()) ); + QTimer::singleShot(0, this, SLOT(updateAnimationSettings()) ); +} + +void DesktopManager::stop(){ + disconnect(DesktopSettings::instance(), SIGNAL(FileModified(DesktopSettings::File)), this, SLOT(settingsChanged(DesktopSettings::File)) ); +} + +// === PRIVATE === +void DesktopManager::updateWallpaper(QString screen_id, int wkspace){ + QString current = RootDesktopObject::instance()->CurrentWallpaper(screen_id); + if(!current.isEmpty()){ current = QUrl(current).toLocalFile(); } //convert it back to the normal file syntax + //First find the list of options from the settings + //First look for a list that matches this exact screen/workspace combo + QStringList wpaperList = DesktopSettings::instance()->value(DesktopSettings::Desktop, "wallpapers/"+screen_id+"_wk_"+QString::number(wkspace), QStringList()).toStringList(); + //Next look for a list that matches this exact workspace + if(wpaperList.isEmpty()){ wpaperList= DesktopSettings::instance()->value(DesktopSettings::Desktop, "wallpapers/default_wk_"+QString::number(wkspace), QStringList()).toStringList(); } + //Next look for a list that matches this exact screen + if(wpaperList.isEmpty()){ wpaperList= DesktopSettings::instance()->value(DesktopSettings::Desktop, "wallpapers/"+screen_id, QStringList()).toStringList(); } + //Now look for a list that matches any screen/workspace + if(wpaperList.isEmpty()){ wpaperList= DesktopSettings::instance()->value(DesktopSettings::Desktop, "wallpapers/default", QStringList()).toStringList(); } + //Now use the failover wallpaper directory + if(wpaperList.isEmpty()){ wpaperList << LOS::LuminaShare()+"../wallpapers/lumina-nature"; } + //Wallpaper selection/randomization + if(wpaperList.count()==1 && wpaperList.first()==current){ return; } //nothing to do - just the same image + QString wpaper; + QStringList bgL = wpaperList; //need a copy at the moment - could change the entire list in a second (opening a dir for instance) + while(wpaper.isEmpty() || QFileInfo(wpaper).isDir()){ + QString prefix; + if(!wpaper.isEmpty()){ + //Got a directory - update the list of files and re-randomize the selection + QStringList imgs = LUtils::imageExtensions(true); + QDir tdir(wpaper); + prefix=wpaper+"/"; + bgL = tdir.entryList(imgs, QDir::Files | QDir::NoDotAndDotDot, QDir::Name); + //If directory no longer has any valid images - remove it from list and try again + if(bgL.isEmpty()){ + wpaperList.removeAll(wpaper); //invalid directory - remove it from the list for the moment + bgL = wpaperList; //reset the list back to the original list (not within a directory) + } + } + //Verify that there are files in the list - otherwise use the default + if(bgL.isEmpty()){ wpaper="default"; break; } + int index = ( qrand() % bgL.length() ); + if(index== bgL.indexOf(current)){ //if the current wallpaper was selected by the randomization again + //Go to the next in the list + if(index < 0 || index >= bgL.length()-1){ index = 0; } //if invalid or last item in the list - go to first + else{ index++; } //go to next + } + wpaper = prefix+bgL[index]; + } + //Now go ahead and set the wallpaper in the screen object + if(wpaper.isEmpty() || wpaper=="default"){ wpaper = LOS::LuminaShare()+"desktop-background.jpg"; } //failover image + qDebug() << "Updating Wallpaper:" << screen_id << wpaper; + RootDesktopObject::instance()->ChangeWallpaper(screen_id,QUrl::fromLocalFile(wpaper).toString() ); +} + +void DesktopManager::updatePanels(QString panel_id){ + +} + +void DesktopManager::updatePlugins(QString plugin_id){ + +} + +// === PUBLIC SLOTS === +void DesktopManager::workspaceChanged(int wknum){ + qDebug() << "Got Workspace Changed:" << wknum; + +} + +void DesktopManager::settingsChanged(DesktopSettings::File type){ + switch(type){ + case DesktopSettings::Desktop: + QTimer::singleShot(0, this, SLOT(updateDesktopSettings()) ); + case DesktopSettings::Panels: + QTimer::singleShot(0, this, SLOT(updatePanelSettings()) ); + case DesktopSettings::Plugins: + QTimer::singleShot(0, this, SLOT(updatePluginSettings()) ); + case DesktopSettings::ContextMenu: + QTimer::singleShot(0, this, SLOT(updateMenuSettings()) ); + case DesktopSettings::Animation: + QTimer::singleShot(0, this, SLOT(updateAnimationSettings()) ); + default: + break; + //Do nothing - not a settings change we care about here + } +} + +// === PRIVATE SLOTS === +void DesktopManager::updateDesktopSettings(){ + qDebug() << "Update Desktop Settings..."; + QList<QScreen*> scrns= QApplication::screens(); + int wkspace = Lumina::NWS->currentWorkspace(); + for(int i=0; i<scrns.length(); i++){ updateWallpaper(scrns[i]->name(), wkspace); } + +} + +void DesktopManager::updatePanelSettings(){ + +} + +void DesktopManager::updatePluginSettings(){ + +} + +void DesktopManager::updateMenuSettings(){ + +} + +void DesktopManager::updateAnimationSettings(){ + +} + diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.h b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.h new file mode 100644 index 00000000..df681afa --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.h @@ -0,0 +1,44 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017-2018, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the main class that updates the interface objects +// on-demand as settings files and other stuff changes +//=========================================== +#ifndef _LUMINA_DESKTOP_OBJECT_MANAGER_H +#define _LUMINA_DESKTOP_OBJECT_MANAGER_H + +#include <global-includes.h> + +class DesktopManager : public QObject { + Q_OBJECT +public: + DesktopManager(); + ~DesktopManager(); + + void start(); + void stop(); + +private: + void updateWallpaper(QString screen_id, int wkspace); + void updatePanels(QString panel_id); + void updatePlugins(QString plugin_id); + +public slots: + void workspaceChanged(int); + void settingsChanged(DesktopSettings::File); + +private slots: + void updateDesktopSettings(); + void updatePanelSettings(); + void updatePluginSettings(); + void updateMenuSettings(); + void updateAnimationSettings(); + +signals: + void PanelLocationsChanged(); //reserved screen space changed +}; + +#endif diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri index e4c4faeb..f4a6882d 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri @@ -1,8 +1,10 @@ QT *= gui widgets qml quick -SOURCES *= $${PWD}/RootWindow.cpp +SOURCES *= $${PWD}/RootWindow.cpp \ + $${PWD}/Desktopmanager.cpp -HEADERS *= $${PWD}/RootWindow.h +HEADERS *= $${PWD}/RootWindow.h \ + $${PWD}/DesktopManager.h #update the includepath so we can just #include as needed without paths INCLUDEPATH *= $${PWD} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp new file mode 100644 index 00000000..471da58f --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp @@ -0,0 +1,44 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "PanelObject.h" +#include <QQmlEngine> +#include <QDebug> + +PanelObject::PanelObject(QString id, QObject *parent) : QObject(parent){ + panel_id = id; +} + +void PanelObject::RegisterType(){ + static bool done = false; + if(done){ return; } + done=true; + qmlRegisterType<PanelObject>("Lumina.Backend.PanelObject",2,0, "PanelObject"); +} + +QString PanelObject::name(){ return panel_id; } +QString PanelObject::background(){ + if(bg.isEmpty()){ return "transparent"; } + return bg; +} +int PanelObject::x(){ return geom.x(); } +int PanelObject::y(){ return geom.y(); } +int PanelObject::width(){ return geom.width(); } +int PanelObject::height(){ return geom.height(); } + +void PanelObject::setBackground(QString fileOrColor){ + if(bg!=fileOrColor){ + bg = fileOrColor; + emit backgroundChanged(); + } +} + +void PanelObject::setGeometry( QRect newgeom ){ + if(geom!=newgeom){ + geom = newgeom; + emit geomChanged(); + } +} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h new file mode 100644 index 00000000..a788fa07 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h @@ -0,0 +1,49 @@ +//=========================================== +// 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 base C++ object that is used to pass Panel info to the QML classes +//=========================================== +#ifndef _LUMINA_DESKTOP_PANEL_OBJECT_H +#define _LUMINA_DESKTOP_PANEL_OBJECT_H +#include <QObject> +#include <QString> +#include <QScreen> + +class PanelObject : public QObject { + Q_OBJECT + Q_PROPERTY( QString name READ name ) + Q_PROPERTY( QString background READ background NOTIFY backgroundChanged) + Q_PROPERTY( int x READ x NOTIFY geomChanged) + Q_PROPERTY( int y READ y NOTIFY geomChanged) + Q_PROPERTY( int width READ width NOTIFY geomChanged) + Q_PROPERTY( int height READ height NOTIFY geomChanged) + +private: + QString panel_id, bg; + QRect geom; + +public: + PanelObject(QString id = "", QObject *parent = 0); + + static void RegisterType(); + + Q_INVOKABLE QString name(); + Q_INVOKABLE QString background(); + Q_INVOKABLE int x(); + Q_INVOKABLE int y(); + Q_INVOKABLE int width(); + Q_INVOKABLE int height(); + +public slots: + void setBackground(QString fileOrColor); + void setGeometry(QRect newgeom); + +signals: + void backgroundChanged(); + void geomChanged(); +}; + +#endif diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp index 60cf56c3..4b01fa0d 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp @@ -21,6 +21,9 @@ RootDesktopObject::~RootDesktopObject(){ } void RootDesktopObject::RegisterType(){ + static bool done = false; + if(done){ return; } + done=true; qmlRegisterType<RootDesktopObject>("Lumina.Backend.RootDesktopObject", 2, 0, "RootDesktopObject"); //Also register any types that are needed by this class ScreenObject::RegisterType(); @@ -47,6 +50,47 @@ ScreenObject* RootDesktopObject::screen(QString id){ return 0; } +QStringList RootDesktopObject::panels(){ + //qDebug() << "Request Panels:" << panel_objects.length(); + QStringList names; + for(int i=0; i<panel_objects.length(); i++){ names << panel_objects[i]->name(); } + return names; +} + +PanelObject* RootDesktopObject::panel(QString id){ + //qDebug() << "Got Panel Request:" << id; + for(int i=0; i<panel_objects.length(); i++){ + if(panel_objects[i]->name()==id){ return panel_objects[i]; } + } + return 0; +} + +QStringList RootDesktopObject::windows(){ + //qDebug() << "Request Panels:" << panel_objects.length(); + QStringList names; + for(int i=0; i<window_objects.length(); i++){ names << QString::number(window_objects[i]->id()); } + return names; +} + +NativeWindow* RootDesktopObject::window(QString id){ + //qDebug() << "Got Panel Request:" << id; + WId chk = id.toInt(); //numerical ID's in this case + for(int i=0; i<window_objects.length(); i++){ + if(window_objects[i]->id()==chk){ return window_objects[i]; } + } + return 0; +} + +void RootDesktopObject::setPanels(QList<PanelObject*> list){ + panel_objects = list; + emit panelsChanged(); +} + +void RootDesktopObject::setWindows(QList<NativeWindow*> list){ + window_objects = list; + emit windowsChanged(); +} + void RootDesktopObject::logout(){ emit startLogout(); } @@ -85,4 +129,13 @@ void RootDesktopObject::ChangeWallpaper(QString screen, QString value){ } } +QString RootDesktopObject::CurrentWallpaper(QString screen){ + for(int i=0; i<s_objects.length(); i++){ + if(s_objects[i]->name()==screen){ return s_objects[i]->background();} + } + return ""; //unknown +} + + + // === PRIVATE === diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h index ba586701..7d5182c4 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h @@ -10,6 +10,7 @@ #define _LUMINA_DESKTOP_QML_BACKEND_ROOT_DESKTOP_OBJECT_H #include <QObject> #include <QList> +#include <global-includes.h> #include "ScreenObject.h" @@ -17,6 +18,8 @@ class RootDesktopObject : public QObject{ Q_OBJECT //Define all the QML Properties here (interface between QML and the C++ methods below) Q_PROPERTY( QStringList screens READ screens NOTIFY screensChanged) + Q_PROPERTY( QStringList panels READ panels NOTIFY panelsChanged) + Q_PROPERTY( QStringList windows READ windows NOTIFY windowsChanged); public: //main contructor/destructor @@ -29,24 +32,38 @@ public: static RootDesktopObject* instance(); //QML Read Functions - QStringList screens(); + Q_INVOKABLE QStringList screens(); Q_INVOKABLE ScreenObject* screen(QString id); + Q_INVOKABLE QStringList panels(); + Q_INVOKABLE PanelObject* panel(QString id); + Q_INVOKABLE QStringList windows(); + Q_INVOKABLE NativeWindow* window(QString id); + + void setPanels(QList<PanelObject*> list); + void setWindows(QList<NativeWindow*> list); //QML Access Functions Q_INVOKABLE void logout(); Q_INVOKABLE void lockscreen(); Q_INVOKABLE void mousePositionChanged(); + private: QList<ScreenObject*> s_objects; + QList<PanelObject*> panel_objects; + QList<NativeWindow*> window_objects; public slots: void updateScreens(); //rescan/update screen objects void ChangeWallpaper(QString screen, QString); + QString CurrentWallpaper(QString screen); private slots: signals: void screensChanged(); + void panelsChanged(); + void windowsChanged(); + void startLogout(); void mouseMoved(); void lockScreen(); diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp index 4c1d6189..82622403 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp @@ -13,7 +13,12 @@ ScreenObject::ScreenObject(QScreen *scrn, QObject *parent) : QObject(parent){ } void ScreenObject::RegisterType(){ + static bool done = false; + if(done){ return; } + done=true; qmlRegisterType<ScreenObject>("Lumina.Backend.ScreenObject",2,0, "ScreenObject"); + //Also register any types that are needed by this class + PanelObject::RegisterType(); } QString ScreenObject::name(){ return bg_screen->name(); } @@ -29,3 +34,24 @@ void ScreenObject::setBackground(QString fileOrColor){ emit backgroundChanged(); } } + +void ScreenObject::setPanels(QList<PanelObject*> list){ + panel_objects = list; + emit panelsChanged(); +} + +//QML Read Functions +QStringList ScreenObject::panels(){ + //qDebug() << "Request Panels:" << panel_objects.length(); + QStringList names; + for(int i=0; i<panel_objects.length(); i++){ names << panel_objects[i]->name(); } + return names; +} + +PanelObject* ScreenObject::panel(QString id){ + //qDebug() << "Got Panel Request:" << id; + for(int i=0; i<panel_objects.length(); i++){ + if(panel_objects[i]->name()==id){ return panel_objects[i]; } + } + return 0; +} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h index 8076f1ae..1afff6d2 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h @@ -12,6 +12,8 @@ #include <QString> #include <QScreen> +#include "PanelObject.h" + class ScreenObject : public QObject { Q_OBJECT Q_PROPERTY( QString name READ name ) @@ -20,10 +22,12 @@ class ScreenObject : public QObject { Q_PROPERTY( int y READ y NOTIFY geomChanged) Q_PROPERTY( int width READ width NOTIFY geomChanged) Q_PROPERTY( int height READ height NOTIFY geomChanged) + Q_PROPERTY( QStringList panels READ panels NOTIFY panelsChanged) private: QScreen *bg_screen; QString bg; + QList<PanelObject*> panel_objects; public: ScreenObject(QScreen *scrn = 0, QObject *parent = 0); @@ -36,6 +40,10 @@ public: Q_INVOKABLE int y(); Q_INVOKABLE int width(); Q_INVOKABLE int height(); + Q_INVOKABLE QStringList panels(); + Q_INVOKABLE PanelObject* panel(QString id); + + void setPanels(QList<PanelObject*> list); public slots: void setBackground(QString fileOrColor); @@ -43,6 +51,7 @@ public slots: signals: void backgroundChanged(); void geomChanged(); + void panelsChanged(); }; #endif diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri index 33b699da..899f4968 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri @@ -1,8 +1,9 @@ SOURCES *= $${PWD}/RootDesktopObject.cpp \ - $${PWD}/ScreenObject.cpp + $${PWD}/ScreenObject.cpp \ + $${PWD}/PanelObject.cpp HEADERS *= $${PWD}/RootDesktopObject.h \ - $${PWD}/ScreenObject.h + $${PWD}/ScreenObject.h \ + $${PWD}/PanelObject.h INCLUDEPATH *= $${PWD} - diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml new file mode 100644 index 00000000..846b5b55 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml @@ -0,0 +1,26 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +import QtQuick 2.2 +import QtQuick.Window 2.2 +import QtQuick.Controls 1 + +import Lumina.Backend.PanelObject 2.0 + +AnimatedImage { + //C++ backend object + property string screen_id + property PanelObject object + + //Normal geometries/placements + asynchronous: true + clip: true + source: object.background + x: object.x + y: object.y + width: object.width + height: object.height + } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml index e0381e23..c564ee42 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml @@ -46,11 +46,12 @@ Rectangle { //Create the context menu itself QML.ContextMenu { id: contextMenu } - //Setup the wallpapers + //Setup the screens/wallpapers Repeater{ model: RootObject.screens - QML.WallpaperImage{ + QML.Screen{ screen_id: modelData + object: RootObject.screen(modelData) z: 0+index } } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/WallpaperImage.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Screen.qml index 1b44963f..3b83653a 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/WallpaperImage.qml +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Screen.qml @@ -13,7 +13,7 @@ import Lumina.Backend.ScreenObject 2.0 AnimatedImage { //C++ backend object property string screen_id - property ScreenObject object: RootObject.screen(screen_id) + property ScreenObject object //Normal geometries/placements asynchronous: true diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri index fed18e02..ad07902a 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri @@ -2,7 +2,8 @@ lupdate_only{ SOURCES *= $${PWD}/RootDesktop.qml \ $${PWD}/ContextMenu.qml \ - $${PWD}/WallpaperImage.qml + $${PWD}/Screen.qml \ + $${PWD}/Panel.qml } RESOURCES *= $${PWD}/src-qml.qrc diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc index ebdcc606..b0c66e20 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc @@ -2,6 +2,7 @@ <qresource prefix="qml"> <file>RootDesktop.qml</file> <file>ContextMenu.qml</file> - <file>WallpaperImage.qml</file> + <file>Screen.qml</file> + <file>Panel.qml</file> </qresource> </RCC> diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp index 7c098887..aa3214a2 100644 --- a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp @@ -7,6 +7,9 @@ #include "SSBaseWidget.h" +//Relative directory to search along the XDG paths for screensavers +#define REL_DIR QString("/lumina-desktop/screensavers") + #define DEBUG 0 // ======== @@ -39,10 +42,10 @@ void SSBaseWidget::startPainting(){ stopPainting(); //If a random plugin - grab one of the known plugins if(plugType=="random"){ - QList<SSPlugin> valid = SSPluginSystem::findAllPlugins(); + QList<SSPlugin> valid = PluginSystem::findAllPlugins<SSPlugin>(REL_DIR); if(!valid.isEmpty()){ cplug = valid[ qrand()%valid.length() ]; } //grab a random plugin }else if(plugType!="none"){ - cplug = SSPluginSystem::findPlugin(plugType); + cplug = PluginSystem::findPlugin<SSPlugin>(plugType, REL_DIR); } if(DEBUG){ qDebug() << " - Screen Saver:" << plugType << cplug.scriptURL() << cplug.isValid(); } if(cplug.isValid()){ diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h index 72e02702..e0a03d17 100644 --- a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h +++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h @@ -10,6 +10,7 @@ #define _LUMINA_DESKTOP_SCREEN_SAVER_BASE_WIDGET_H #include "global-includes.h" +#include <plugins-base.h> #include <plugins-screensaver.h> class SSBaseWidget : public QQuickView{ @@ -25,8 +26,8 @@ public slots: void stopPainting(); private: - QString plugType; - SSPlugin cplug; + QString plugType; + SSPlugin cplug; QTimer *restartTimer; private slots: diff --git a/src-qt5/core/lumina-desktop/defaults/desktop-background-TrueOS.jpg b/src-qt5/core/lumina-desktop/defaults/desktop-background-TrueOS.jpg Binary files differindex de11074e..3fd8cc49 100644 --- a/src-qt5/core/lumina-desktop/defaults/desktop-background-TrueOS.jpg +++ b/src-qt5/core/lumina-desktop/defaults/desktop-background-TrueOS.jpg diff --git a/src-qt5/core/lumina-desktop/defaults/luminaDesktop-TrueOS.conf b/src-qt5/core/lumina-desktop/defaults/luminaDesktop-TrueOS.conf index e9520a3c..543f9eaa 100644 --- a/src-qt5/core/lumina-desktop/defaults/luminaDesktop-TrueOS.conf +++ b/src-qt5/core/lumina-desktop/defaults/luminaDesktop-TrueOS.conf @@ -53,6 +53,7 @@ mime_default_application/x-tar_ifexists=lumina-archiver.desktop #THEME SETTINGS theme_themefile=DarkGlass #Name of the theme to use (disable for Lumina-Default) +theme_styles=scrollbar-simple, tooltip-simple, sliders-simple, traynotification-simple theme_colorfile=darker #Name of the color spec file to use for theming theme_iconset=material-design-dark #Name of the icon theme to use theme_font=Noto Sans #Name of the font family to use @@ -60,14 +61,14 @@ theme_fontsize=10pt #Default size of the fonts to use on the desktop (can also u #DESKTOP SETTINGS (used for the primary screen in multi-screen setups) desktop_visiblepanels=1 #[0 - 12] The number of panels visible by default -desktop_backgroundfiles=/usr/local/share/wallpapers/TrueOS/trueos-1-4k.png #list of absolute file paths for image files (disable for Lumina default) +desktop_backgroundfiles=/usr/local/share/lumina-desktop/desktop-background.jpg #list of absolute file paths for image files (disable for Lumina default) desktop_backgroundrotateminutes=5 #[positive integer] number of minutes between background rotations (if multiple files) #desktop_plugins= #list of plugins to be shown on the desktop by default desktop_generate_icons=true #[true/false] Auto-generate launchers for ~/Desktop items #PANEL SETTINGS (preface with panel1.<setting> or panel2.<setting>, depending on the number of panels you have visible by default) panel1_location=bottom #[top/bottom/left/right] Screen edge the panel should be on -panel1_pixelsize=3.5%H #number of pixels wide/high the panel should be (or <number>%[W/H] for a percentage of the screen width/height) +panel1_pixelsize=5%H #number of pixels wide/high the panel should be (or <number>%[W/H] for a percentage of the screen width/height) panel1_autohide=false #[true/false] Have the panel become visible on mouse-over panel1_plugins=systemstart, taskmanager-nogroups, spacer, systemtray, clock, battery #list of plugins for the panel panel1_pinlocation=center #[left/center/right] Note:[left/right] corresponds to [top/bottom] for vertical panels diff --git a/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf b/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf index e4229038..0e6101c1 100644 --- a/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf +++ b/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf @@ -50,7 +50,8 @@ mime_default_unknown/*=lumina-textedit.desktop mime_default_application/x-shellscript=lumina-textedit.desktop #THEME SETTINGS -theme_themefile=DarkGlass #Name of the theme to use (disable for Lumina-Default) +theme_themefile=DarkGlass #Name of the theme to use +theme_styles=scrollbar-simple, tooltip-simple, sliders-simple, traynotification-simple theme_colorfile=darker #Name of the color spec file to use for theming theme_iconset=material-design-dark #Name of the icon theme to use theme_font=Arial #Name of the font family to use diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp index c330d6c0..e8e5adb4 100644 --- a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp +++ b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSFeedPlugin.cpp @@ -119,11 +119,13 @@ void RSSFeedPlugin::updateFeed(QString ID){ if(!data.items[i].author_email.isEmpty()){ html.append("<a href=\"mailto:"+data.items[i].author_email+"\" style=\"color: "+color+";\">"+data.items[i].author+"</a>"); } else{ html.append(data.items[i].author); } } - html.append(")</i><br>"); + html.append(")</i>"); + if(data.rss) + html.append("<br>"); } html.append(data.items[i].description); //html.append("</li>\n"); - if(i+1 < data.items.length()){ html.append("<br>"); } + if(i+1 < data.items.length() && data.rss){ html.append("<br>"); } } //html.append("</ul>\n"); // - load that html into the viewer diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.cpp b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.cpp index cd29d5f0..5f62f99f 100644 --- a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.cpp +++ b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.cpp @@ -10,6 +10,8 @@ #include "LSession.h" +#define DEBUG 0 + //============ // PUBLIC //============ @@ -116,18 +118,51 @@ RSSchannel RSSReader::readRSS(QByteArray bytes){ RSSchannel rssinfo; //qDebug() << "Can Read XML Stream:" << !xml.hasError(); if(xml.readNextStartElement()){ - //qDebug() << " - RSS Element:" << xml.name(); - if(xml.name() == "rss" && (xml.attributes().value("version") =="2.0" || xml.attributes().value("version") =="0.91") ){ + if(DEBUG) qDebug() << " - RSS Element:" << xml.name(); + if(xml.name() == "rss" && (xml.attributes().value("version") =="2.0" || xml.attributes().value("version") =="0.91")) { + rssinfo.rss = true; while(xml.readNextStartElement()){ //qDebug() << " - RSS Element:" << xml.name(); if(xml.name()=="channel"){ rssinfo = readRSSChannel(&xml); } else{ xml.skipCurrentElement(); } } + }else if(xml.name() == "feed") { + rssinfo.timetolive = -1; + rssinfo.rss = false; + while(xml.readNextStartElement()){ + if(DEBUG) qDebug() << " - ATOM Element (channel):" << xml.name(); + if(xml.name()=="entry") { + rssinfo.items << readRSSItemAtom(&xml); + }else if(xml.name()=="title"){ + rssinfo.title = xml.readElementText(); + if(DEBUG) qDebug() << "title" << rssinfo.link; + }else if(xml.name()=="link"){ + QXmlStreamAttributes att = xml.attributes(); + for(int i = 0; i < att.size(); i++) { + if(att[i].name() == "href") { + rssinfo.link = att[i].value().toString(); + } + } + xml.readElementText(); + if(DEBUG) qDebug() << "link" << rssinfo.link; + }else if(xml.name()=="subtitle"){ + rssinfo.description = xml.readElementText(); + }else if(xml.name()=="updated"){ + rssinfo.lastBuildDate = ATOMDateTime(xml.readElementText()); + }else if(xml.name()=="icon"){ + rssinfo.icon_url = xml.readElementText(); + if(DEBUG) qDebug() << "icon" << rssinfo.icon_url; + requestRSS(rssinfo.icon_url); + }else{ + xml.skipCurrentElement(); + } + } } } - if(xml.hasError()){ qDebug() << " - XML Read Error:" << xml.errorString() << "\n" << bytes; } + //if(xml.hasError()){ qDebug() << " - XML Read Error:" << xml.errorString() << "\n" << bytes; } return rssinfo; } + RSSchannel RSSReader::readRSSChannel(QXmlStreamReader *rss){ RSSchannel info; info.timetolive = -1; @@ -151,6 +186,40 @@ RSSchannel RSSReader::readRSSChannel(QXmlStreamReader *rss){ return info; } +RSSitem RSSReader::readRSSItemAtom(QXmlStreamReader *rss){ + RSSitem item; + while(rss->readNextStartElement()){ + if(rss->name()=="title"){ + item.title = rss->readElementText(); + if(DEBUG) qDebug() << rss->name() << item.title; + }else if(rss->name()=="link"){ + QXmlStreamAttributes att = rss->attributes(); + for(int i = 0; i < att.size(); i++) { + if(att[i].name() == "href") { + item.link = att[i].value().toString(); + } + } + rss->readElementText(); + if(DEBUG) qDebug() << rss->name() << item.link; + }else if(rss->name()=="summary"){ + item.description = rss->readElementText(); + if(DEBUG) qDebug() << rss->name() << item.description; + } else if(rss->name()=="comments"){ + item.comments_url = rss->readElementText(); + if(DEBUG) qDebug() << rss->name() << item.comments_url; + } else if(rss->name()=="author"){ + rss->readNextStartElement(); + item.author = rss->readElementText(); + if(DEBUG) qDebug() << "author" << item.author; + rss->skipCurrentElement(); + }else if(rss->name()=="updated"){ + item.pubdate = ATOMDateTime(rss->readElementText()); + if(DEBUG) qDebug() << rss->name() << item.pubdate; + } else{ rss->skipCurrentElement(); } + } + return item; +} + RSSitem RSSReader::readRSSItem(QXmlStreamReader *rss){ RSSitem item; while(rss->readNextStartElement()){ @@ -192,17 +261,21 @@ QDateTime RSSReader::RSSDateTime(QString datetime){ return QDateTime::fromString(datetime, Qt::RFC2822Date); } +QDateTime RSSReader::ATOMDateTime(QString datetime){ + return QDateTime::fromString(datetime, Qt::ISODate); +} + //================= // PRIVATE SLOTS //================= void RSSReader::replyFinished(QNetworkReply *reply){ QString url = reply->request().url().toString(); - //qDebug() << "Got Reply:" << url; + qDebug() << "Got Reply:" << url; QString key = keyForUrl(url); //current hash key for this URL QByteArray data = reply->readAll(); outstandingURLS.removeAll(url); if(data.isEmpty()){ - //qDebug() << "No data returned:" << url; + qDebug() << "No data returned:" << url; //see if the URL can be adjusted for known issues bool handled = false; QUrl redirecturl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); @@ -229,13 +302,13 @@ void RSSReader::replyFinished(QNetworkReply *reply){ //Could also be an icon fetch response QStringList keys = hash.keys(); for(int i=0; i<keys.length(); i++){ - //qDebug() << " - Check for icon URL:" << hash[keys[i]].icon_url; + qDebug() << " - Check for icon URL:" << hash[keys[i]].icon_url; if(hash[keys[i]].icon_url.toLower() == url.toLower()){ //needs to be case-insensitive //Icon fetch response RSSchannel info = hash[keys[i]]; QImage img = QImage::fromData(data); info.icon = QIcon( QPixmap::fromImage(img) ); - //qDebug() << "Got Icon response:" << url << info.icon; + qDebug() << "Got Icon response:" << url << info.icon; hash.insert(keys[i], info); //insert back into the hash emit rssChanged( hash[keys[i]].originalURL ); break; diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.h b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.h index 3069bf8d..9d65ee57 100644 --- a/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.h +++ b/src-qt5/core/lumina-desktop/desktop-plugins/rssreader/RSSObjects.h @@ -51,6 +51,7 @@ struct RSSchannel{ //Internal data for bookkeeping QDateTime lastsync, nextsync; QString originalURL; //in case it was redirected to some "fixed" url later + bool rss; }; class RSSReader : public QObject{ @@ -88,9 +89,12 @@ private: //RSS parsing functions RSSchannel readRSS(QByteArray bytes); RSSchannel readRSSChannel(QXmlStreamReader *rss); + RSSchannel readRSSChannelAtom(QXmlStreamReader *rss); RSSitem readRSSItem(QXmlStreamReader *rss); - void readRSSImage(RSSchannel *item, QXmlStreamReader *rss); + RSSitem readRSSItemAtom(QXmlStreamReader *rss); + void readRSSImage(RSSchannel *item, QXmlStreamReader *rss); QDateTime RSSDateTime(QString datetime); + QDateTime ATOMDateTime(QString datetime); private slots: void replyFinished(QNetworkReply *reply); diff --git a/src-qt5/core/lumina-desktop/lumina-desktop.pro b/src-qt5/core/lumina-desktop/lumina-desktop.pro index 9c8272c8..e36d11a2 100644 --- a/src-qt5/core/lumina-desktop/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop/lumina-desktop.pro @@ -170,10 +170,10 @@ TRANSLATIONS = i18n/lumina-desktop_af.ts \ i18n/lumina-desktop_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-desktop.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-desktop.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-desktop.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-desktop.1.gz" INSTALLS += target desktop icons defaults conf fluxconf manpage diff --git a/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp b/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp index 7a6b0e7c..69ea5faa 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp @@ -77,6 +77,7 @@ void LBattery::updateBattery(bool force){ label->setPixmap( LXDG::findIcon("battery-unknown", "battery-missing").pixmap(label->size()) ); break; } + } if(icon<iconOld && icon==0){ //Play some audio warning chime when bool playaudio = sessionsettings->value("PlayBatteryLowAudio",true).toBool(); @@ -97,7 +98,6 @@ void LBattery::updateBattery(bool force){ else{ tt = QString( tr("%1 % (%2 Remaining)") ).arg(QString::number(charge), getRemainingTime() ); } label->setToolTip(tt); } -} QString LBattery::getRemainingTime(){ int secs = LOS::batterySecondsLeft(); diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.cpp index f4382ffc..545000f4 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/ItemWidget.cpp @@ -70,12 +70,12 @@ ItemWidget::ItemWidget(QWidget *parent, QString itemPath, QString type, bool gob iconPath = itemPath; //icon->setPixmap( QIcon(itemPath).pixmap(64,64) ); }else{ - if( LUtils::isValidBinary(itemPath) ){ + if( LUtils::isValidBinary(itemPath) ){ if(ICONS->exists(type)){ iconPath = type; } else{ iconPath = "application-x-executable"; } }else{ iconPath = LXDG::findAppMimeForFile(itemPath.section("/",-1)).replace("/","-"); } } - name->setText( itemPath.section("/",-1) ); //this->fontMetrics().elidedText(itemPath.section("/",-1), Qt::ElideRight, TEXTCUTOFF) ); + name->setText( itemPath.section("/",-1) ); //this->fontMetrics().elidedText(itemPath.section("/",-1), Qt::ElideRight, TEXTCUTOFF) ); text = itemPath.section("/",-1) ; } ICONS->loadIcon(icon, iconPath); @@ -133,11 +133,11 @@ ItemWidget::~ItemWidget(){ //actButton->deleteLater(); contextMenu->clear(); //contextMenu->deleteLater(); - if(actButton->menu()!=0){ + if(actButton->menu()!=0){ for(int i=0; i<actButton->menu()->actions().length(); i++){ actButton->menu()->actions().at(i)->deleteLater(); } - actButton->menu()->deleteLater(); + actButton->menu()->deleteLater(); } //actButton->deleteLater(); //icon->deleteLater(); @@ -156,7 +156,7 @@ void ItemWidget::createWidget(){ menuopen = false; menureset = new QTimer(this); menureset->setSingleShot(true); - menureset->setInterval(1000); //1 second + menureset->setInterval(1000); //1 second this->setContentsMargins(0,0,0,0); contextMenu = new QMenu(this); connect(contextMenu, SIGNAL(aboutToShow()), this, SLOT(actionMenuOpen()) ); @@ -220,7 +220,7 @@ void ItemWidget::setupActions(XDGDesktop *app){ else{ ICONS->loadIcon(act, app->icon); } act->setToolTip(app->actions[i].ID); act->setWhatsThis(app->actions[i].ID); - actButton->menu()->addAction(act); + actButton->menu()->addAction(act); } connect(actButton->menu(), SIGNAL(triggered(QAction*)), this, SLOT(actionClicked(QAction*)) ); connect(actButton->menu(), SIGNAL(aboutToShow()), this, SLOT(actionMenuOpen()) ); @@ -230,9 +230,11 @@ void ItemWidget::setupActions(XDGDesktop *app){ void ItemWidget::updateItems(){ //update the text/icon to match sizes - int H = (2.5*name->fontMetrics().height() ) -4; //make sure the height is large enough for two lines + int H = (2.2*name->fontMetrics().height() ) -4; //make sure the height is large enough for two lines icon->setFixedSize(QSize(H, H)); + icon->setAlignment(Qt::AlignCenter); actButton->setFixedSize( QSize( H/2, H) ); + H = (1.8*name->fontMetrics().height() ) -4; QStringList newname = text.split("<br>"); for(int i=0; i<newname.length(); i++){ newname[i] = name->fontMetrics().elidedText(newname[i], Qt::ElideRight, name->width()); } name->setText( newname.join("<br>") ); @@ -271,9 +273,9 @@ void ItemWidget::RemoveFavorite(){ void ItemWidget::AddFavorite(){ if( LDesktopUtils::addFavorite(icon->whatsThis()) ){ linkPath = icon->whatsThis(); - emit NewShortcut(); + emit NewShortcut(); } - + } void ItemWidget::RemoveQL(){ qDebug() << "Remove QuickLaunch Button:" << icon->whatsThis(); @@ -282,7 +284,7 @@ void ItemWidget::RemoveQL(){ void ItemWidget::AddQL(){ qDebug() << "Add QuickLaunch Button:" << icon->whatsThis(); - emit toggleQuickLaunch(icon->whatsThis(), true); + emit toggleQuickLaunch(icon->whatsThis(), true); } diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp index 562122ae..d8014f4c 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp @@ -25,9 +25,11 @@ LStartButtonPlugin::LStartButtonPlugin(QWidget *parent, QString id, bool horizon startmenu = new StartMenu(this); connect(startmenu, SIGNAL(CloseMenu()), this, SLOT(closeMenu()) ); connect(startmenu, SIGNAL(UpdateQuickLaunch(QStringList)), this, SLOT(updateQuickLaunch(QStringList))); - //QRect screenSize = QApplication::desktop()->availableGeometry(this); - QSize saved = LSession::handle()->DesktopPluginSettings()->value("panelPlugs/"+this->type()+"/MenuSize", QSize(0, 0)).toSize(); - if(!saved.isNull()){ startmenu->setFixedSize(saved); } //re-load the previously saved value + + QRect screenSize = QApplication::desktop()->availableGeometry(this); + QSize saved = LSession::handle()->DesktopPluginSettings()->value("panelPlugs/"+this->type()+"/MenuSize",QSize(this->fontMetrics().width("x")*30 ,screenSize.height()/1.8)).toSize(); + //qDebug() << "Got Start Menu Saved Size:" << saved; + if(!saved.isNull() && saved.isValid()){ startmenu->setFixedSize(saved); } //re-load the previously saved value menu->setContents(startmenu); button->setMenu(menu); @@ -122,6 +124,7 @@ void LStartButtonPlugin::openMenu(){ menu->setContents(startmenu); if(old!=0){ old->deleteLater(); }*/ //-------- + //qDebug() << "Menu Size:" << startmenu->size(); startmenu->UpdateMenu(); button->showMenu(); } diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp index 272bf0fa..ee3e0f80 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp @@ -597,7 +597,7 @@ void StartMenu::on_tool_restart_clicked(){ LSession::handle()->StartReboot(true); } -void StartMenu::on_tool_restart_update_clicked(){ +void StartMenu::on_tool_restart_updates_clicked(){ emit CloseMenu(); QCoreApplication::processEvents(); //bool skipupdates = false; diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h index 41bc3ec4..0a90311d 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h @@ -73,7 +73,7 @@ private slots: void on_tool_lock_clicked(); void on_tool_logout_clicked(); void on_tool_restart_clicked(); - void on_tool_restart_update_clicked(); + void on_tool_restart_updates_clicked(); void on_tool_shutdown_clicked(); void on_tool_suspend_clicked(); diff --git a/src-qt5/core/lumina-info/lumina-info.pro b/src-qt5/core/lumina-info/lumina-info.pro index 0c8693a0..dc07c08e 100644 --- a/src-qt5/core/lumina-info/lumina-info.pro +++ b/src-qt5/core/lumina-info/lumina-info.pro @@ -92,13 +92,13 @@ TRANSLATIONS = i18n/lumina-info_af.ts \ i18n/lumina-info_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-info.desktop lumina-support.desktop desktop.path=$${L_SHAREDIR}/applications/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-info.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-info.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-info.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-info.1.gz" INSTALLS += target desktop manpage diff --git a/src-qt5/core/lumina-open/lumina-open.pro b/src-qt5/core/lumina-open/lumina-open.pro index b31c7a0e..3bc7e9bf 100644 --- a/src-qt5/core/lumina-open/lumina-open.pro +++ b/src-qt5/core/lumina-open/lumina-open.pro @@ -87,10 +87,10 @@ TRANSLATIONS = i18n/lumina-open_af.ts \ i18n/lumina-open_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-open.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-open.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-open.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-open.1.gz" INSTALLS += target manpage diff --git a/src-qt5/core/lumina-session/lumina-session.pro b/src-qt5/core/lumina-session/lumina-session.pro index 797547db..9d8e8f87 100644 --- a/src-qt5/core/lumina-session/lumina-session.pro +++ b/src-qt5/core/lumina-session/lumina-session.pro @@ -16,6 +16,6 @@ SOURCES += main.cpp \ HEADERS += session.h manpage.path=$${L_MANDIR}/man8/ -manpage.extra="$${MAN_ZIP} start-lumina-desktop.8 > $(INSTALL_ROOT)$${L_MANDIR}/man8/start-lumina-desktop.8.gz" +manpage.extra="$${MAN_ZIP} $$PWD/start-lumina-desktop.8 > $(INSTALL_ROOT)$${L_MANDIR}/man8/start-lumina-desktop.8.gz" INSTALLS += target manpage diff --git a/src-qt5/core/lumina-theme-engine/lumina-theme-engine.pro b/src-qt5/core/lumina-theme-engine/lumina-theme-engine.pro index e1023752..1e8b2ca4 100644 --- a/src-qt5/core/lumina-theme-engine/lumina-theme-engine.pro +++ b/src-qt5/core/lumina-theme-engine/lumina-theme-engine.pro @@ -3,7 +3,8 @@ include(../../OS-detect.pri) TEMPLATE = subdirs SUBDIRS += src/lthemeengine-qtplugin \ src/lthemeengine-style \ - src/lthemeengine + src/lthemeengine \ + src/lthemeengine-sstest colors.files = colors/*.conf colors.path = $${L_SHAREDIR}/lthemeengine/colors diff --git a/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss b/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss index e8311e92..a9b165a6 100644 --- a/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss +++ b/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss @@ -1,26 +1,26 @@ /* SLIDERS */ QSlider::groove:horizontal { -border: 1px solid transparent; +border: 1px solid palette(mid); background: palette(alternate-window); height: 10px; border-radius: 3px; } QSlider::groove:vertical { -border: 1px solid transparent; +border: 1px solid palette(mid); background: palette(alternate-window); width: 10px; border-radius: 3px; } QSlider::sub-page:horizontal { background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, - stop: 0 palette(highlight), stop: 1 palette(window)); + stop: 0 transparent, stop: 1 palette(highlight) ); border: 1px solid transparent; height: 10px; border-radius: 3px; } -QSlider::sub-page:vertical { +QSlider::add-page:vertical { background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, - stop: 0 palette(highlight), stop: 1 palette(window)); + stop: 0 transparent, stop: 1 palette(highlight) ); border: 1px solid transparent; width: 10px; border-radius: 3px; @@ -31,7 +31,7 @@ border: 1px solid transparent; height: 10px; border-radius: 3px; } -QSlider::add-page:vertical{ +QSlider::sub-page:vertical{ background: palette(alternate-window); border: 1px solid transparent; width: 10px; @@ -40,13 +40,13 @@ border-radius: 3px; QSlider::handle:horizontal{ background: palette(mid); border: 1px solid palette(mid); -width: 1em; +width: 1ex; border-radius: 1px; } QSlider::handle:vertical{ background: palette(mid); border: 1px solid palette(mid); -height: 1em; +height: 1ex; border-radius: 1px; } QSlider::handle:horizontal:hover, QSlider::handle:vertical:hover{ diff --git a/src-qt5/core/lumina-theme-engine/qss/traynotification-simple.qss b/src-qt5/core/lumina-theme-engine/qss/traynotification-simple.qss new file mode 100644 index 00000000..43aff087 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/qss/traynotification-simple.qss @@ -0,0 +1,4 @@ +QBalloonTip{ +background-color: palette(base); +color: palette(text); +} diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp index 670e1c9c..e581b016 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp @@ -43,7 +43,7 @@ lthemeenginePlatformTheme::lthemeenginePlatformTheme(){ #endif QGuiApplication::setFont(m_generalFont); } - qCDebug(llthemeengine) << "using lthemeengine plugin"; + //qCDebug(llthemeengine) << "using lthemeengine plugin"; #ifdef QT_WIDGETS_LIB if(!QStyleFactory::keys().contains("lthemeengine-style")) qCCritical(llthemeengine) << "unable to find lthemeengine proxy style"; @@ -60,7 +60,7 @@ QPlatformMenuBar *lthemeenginePlatformTheme::createPlatformMenuBar() const{ if(m_checkDBusGlobalMenu){ QDBusConnection conn = QDBusConnection::sessionBus(); m_dbusGlobalMenuAvailable = conn.interface()->isServiceRegistered("com.canonical.AppMenu.Registrar"); - qCDebug(llthemeengine) << "D-Bus global menu:" << (m_dbusGlobalMenuAvailable ? "yes" : "no"); + //qCDebug(llthemeengine) << "D-Bus global menu:" << (m_dbusGlobalMenuAvailable ? "yes" : "no"); } return (m_dbusGlobalMenuAvailable ? new QDBusMenuBar() : nullptr); } diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/lthemeengine-sstest.pro b/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/lthemeengine-sstest.pro new file mode 100644 index 00000000..fadc6fcb --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/lthemeengine-sstest.pro @@ -0,0 +1,11 @@ +include(../../lthemeengine.pri) +TEMPLATE = app +QT *= widgets + +SOURCES += \ + main.cpp + +TARGET = lthemeengine-sstest +target.path = $${L_BINDIR} + +INSTALLS += target diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/main.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/main.cpp new file mode 100644 index 00000000..bdab0a30 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/main.cpp @@ -0,0 +1,18 @@ +#include <QApplication> +//#include <QDebug> +#include <QWidget> + +#include <LUtils.h> + +int main(int argc, char **argv){ + if(argc<2){ return 1; } //error + unsetenv("QT_QPA_PLATFORMTHEME"); //Make sure we are not testing anything related to the current theme engine + QString stylesheet = LUtils::readFile(argv[1]).join("\n"); + //qDebug() << "Found Stylesheet:" << stylesheet; + QApplication app(argc, argv); + app.setStyleSheet(stylesheet); + //qDebug() << " Using Stylesheet:" << app.styleSheet(); + QWidget tmp(0,Qt::SplashScreen | Qt::BypassWindowManagerHint); + tmp.show(); //needed to actually run the parser on the stylesheet (unused/unchecked otherwise) + return 0; +} diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp index ac891a80..56289931 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp @@ -4,6 +4,12 @@ #include "qsseditordialog.h" #include "ui_qsseditordialog.h" +#include <QTemporaryFile> +#include <QTextStream> + +#include <LuminaXDG.h> +#include <LUtils.h> + QSSEditorDialog::QSSEditorDialog(const QString &filePath, QWidget *parent) : QDialog(parent), m_ui(new Ui::QSSEditorDialog){ m_ui->setupUi(this); m_filePath = filePath; @@ -37,6 +43,11 @@ QSSEditorDialog::QSSEditorDialog(const QString &filePath, QWidget *parent) : QDi for(int i=0; i<colors.length(); i++){ colorMenu->addAction( colors[i].section("::::",0,0) )->setWhatsThis(colors[i].section("::::",1,1) ); } m_ui->tool_color->setMenu(colorMenu); connect(colorMenu, SIGNAL(triggered(QAction*)), this, SLOT(colorPicked(QAction*)) ); + validateTimer = new QTimer(this); + validateTimer->setInterval(500); //1/2 second after finish typing + validateTimer->setSingleShot(true); + connect(validateTimer, SIGNAL(timeout()), this, SLOT(validateStyleSheet()) ); + connect(m_ui->textEdit, SIGNAL(textChanged()), validateTimer, SLOT(start()) ); } QSSEditorDialog::~QSSEditorDialog(){ @@ -69,3 +80,31 @@ void QSSEditorDialog::colorPicked(QAction* act){ if(id.isEmpty()){ return; } m_ui->textEdit->insertPlainText( QString("palette(%1)").arg(id) ); } + +bool QSSEditorDialog::isStyleSheetValid(const QString &styleSheet){ + QTemporaryFile tempfile; + if(tempfile.open()){ + QTextStream out(&tempfile); + out << styleSheet; + out.flush(); + tempfile.close(); + } + QStringList log = LUtils::getCmdOutput("lthemeengine-sstest", QStringList() << tempfile.fileName()); + qDebug() << "Got Validation Log:" << log; + return log.join("").simplified().isEmpty(); +} + +void QSSEditorDialog::validateStyleSheet(){ + qDebug() << "Validating StyleSheet:"; + bool ok = isStyleSheetValid(m_ui->textEdit->toPlainText()); + + //Now update the button/label as needed + int sz = this->fontMetrics().height(); + if(ok){ + m_ui->label_status_icon->setPixmap(LXDG::findIcon("dialog-ok","").pixmap(sz,sz) ); + m_ui->label_status_icon->setToolTip(tr("Valid StyleSheet")); + }else{ + m_ui->label_status_icon->setPixmap(LXDG::findIcon("dialog-cancel","").pixmap(sz,sz) ); + m_ui->label_status_icon->setToolTip(tr("Invalid StyleSheet")); + } +} diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h index 114611fe..f51434e9 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h @@ -5,6 +5,7 @@ #include <QString> #include <QMenu> #include <QAction> +#include <QTimer> namespace Ui { class QSSEditorDialog; @@ -23,6 +24,8 @@ public: private slots: void on_buttonBox_clicked(QAbstractButton *button); void colorPicked(QAction*); + bool isStyleSheetValid(const QString&); + void validateStyleSheet(); private: void save(); @@ -30,6 +33,7 @@ private: Ui::QSSEditorDialog *m_ui; QString m_filePath; QMenu *colorMenu; + QTimer *validateTimer; }; diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui index f75a21c6..68a14fb1 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>643</width> - <height>499</height> + <width>808</width> + <height>512</height> </rect> </property> <property name="windowTitle"> @@ -53,6 +53,38 @@ </widget> </item> <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_status_icon"> + <property name="minimumSize"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + <property name="text"> + <string notr="true"/> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> <widget class="QDialogButtonBox" name="buttonBox"> <property name="orientation"> <enum>Qt::Horizontal</enum> diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp index 47c6bfe1..3d901e8c 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp @@ -67,6 +67,8 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ ui->actionUSB_Image->setEnabled(false); loadIcons(); ui->tree_contents->setHeaderLabels( QStringList() << tr("File") << tr("MimeType") << tr("Size")+" " ); + + preservePaths = false; } MainUI::~MainUI(){ @@ -296,7 +298,7 @@ void MainUI::simpleExtractFiles(){ void MainUI::autoArchiveFiles(){ qDebug() << "Auto Archive Files:" << aaFileList; ui->label_progress->setText(tr("Adding Items...")); - BACKEND->startAdd(aaFileList); + BACKEND->startAdd(aaFileList, true); } void MainUI::extractSelection(){ diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.h b/src-qt5/desktop-utils/lumina-archiver/MainUI.h index 1a9d287c..0a5c094c 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.h +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.h @@ -26,13 +26,14 @@ public: void LoadArguments(QStringList); void loadIcons(); + bool preservePaths; private: Ui::MainUI *ui; - Backend *BACKEND; - QStringList aaFileList, sxList; - QString sxPath, sxFile; - QTimer *delayClose; + Backend *BACKEND; + QStringList aaFileList, sxList; + QString sxPath, sxFile; + QTimer *delayClose; QTreeWidgetItem* findItem(QString path, QTreeWidgetItem *start = 0); bool cleanItems(QStringList list, QTreeWidgetItem *start = 0); //returns true if anything gets cleaned diff --git a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp index 5338efec..91e233d0 100644 --- a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp @@ -91,7 +91,7 @@ QString Backend::linkTo(QString file){ } //Modification routines -void Backend::startAdd(QStringList paths){ +void Backend::startAdd(QStringList paths, bool absolutePaths){ //if(paths.isEmpty() && !insertQueue.isEmpty()){ paths = insertQueue; } //load the queue if(paths.contains(filepath)){ paths.removeAll(filepath); } if(paths.isEmpty()){ return; } @@ -109,11 +109,12 @@ void Backend::startAdd(QStringList paths){ args << "-c" << "-a"; args << flags; //Now setup the parent dir - for(int i=0; i<paths.length(); i++){ - paths[i] = paths[i].section(parent,1,-1); - if(paths[i].startsWith("/")){ paths[i].remove(0,1); } - } - args << "-C" << parent; + if(!absolutePaths) { + for(int i=0; i<paths.length(); i++){ + paths[i] = paths[i].section(parent,1,-1); + if(paths[i].startsWith("/")){ paths[i].remove(0,1); } + } + args << "-C" << parent; } args << paths; if(QFile::exists(filepath)){ //append to existing args.replaceInStrings(filepath, tmpfilepath); diff --git a/src-qt5/desktop-utils/lumina-archiver/TarBackend.h b/src-qt5/desktop-utils/lumina-archiver/TarBackend.h index 56a7dcfe..cb24a053 100644 --- a/src-qt5/desktop-utils/lumina-archiver/TarBackend.h +++ b/src-qt5/desktop-utils/lumina-archiver/TarBackend.h @@ -33,7 +33,7 @@ public: QString linkTo(QString file); //Modification routines - void startAdd(QStringList paths); + void startAdd(QStringList paths, bool absolutePaths = false); void startRemove(QStringList paths); void startExtract(QString path, bool overwrite, QString file=""); //path to dir, overwrite, optional file to extract (everything otherwise) void startExtract(QString path, bool overwrite, QStringList files); diff --git a/src-qt5/desktop-utils/lumina-archiver/lumina-archiver.pro b/src-qt5/desktop-utils/lumina-archiver/lumina-archiver.pro index 763407b9..a1b10109 100644 --- a/src-qt5/desktop-utils/lumina-archiver/lumina-archiver.pro +++ b/src-qt5/desktop-utils/lumina-archiver/lumina-archiver.pro @@ -87,7 +87,7 @@ TRANSLATIONS = i18n/l-archiver_af.ts \ i18n/l-archiver_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-archiver.desktop desktop.path=$${L_SHAREDIR}/applications/ @@ -96,7 +96,7 @@ desktop.path=$${L_SHAREDIR}/applications/ #link.extra=ln -sf lumina-archiver $(INSTALL_ROOT)$${L_BINDIR}/lpac manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-archiver.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-archiver.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-archiver.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-archiver.1.gz" INSTALLS += target desktop manpage diff --git a/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_da.ts b/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_da.ts index 5cdf9fa4..7ae80a69 100644 --- a/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_da.ts +++ b/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_da.ts @@ -16,7 +16,7 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="610"/> <source>Education</source> - <translation>Uddannelse</translation> + <translation>Læring</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="611"/> @@ -41,7 +41,7 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="615"/> <source>Science</source> - <translation>Videnskab</translation> + <translation>Naturvidenskab</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="616"/> @@ -56,7 +56,7 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="618"/> <source>Utility</source> - <translation>Hjælpeværktøj</translation> + <translation>Redskab</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="619"/> diff --git a/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_nl.ts b/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_nl.ts index 9947da6d..1cba660b 100644 --- a/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_nl.ts +++ b/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_nl.ts @@ -6,67 +6,67 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="608"/> <source>Multimedia</source> - <translation type="unfinished"></translation> + <translation>Multimedia</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="609"/> <source>Development</source> - <translation type="unfinished"></translation> + <translation>Ontwikkeling</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="610"/> <source>Education</source> - <translation type="unfinished"></translation> + <translation>Onderwijs</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="611"/> <source>Games</source> - <translation type="unfinished"></translation> + <translation>Spellen</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="612"/> <source>Graphics</source> - <translation type="unfinished"></translation> + <translation>Grafisch</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="613"/> <source>Network</source> - <translation type="unfinished"></translation> + <translation>Netwerk</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="614"/> <source>Office</source> - <translation type="unfinished"></translation> + <translation>Kantoor</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="615"/> <source>Science</source> - <translation type="unfinished"></translation> + <translation>Wetenschappelijk</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="616"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>Instellingen</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="617"/> <source>System</source> - <translation type="unfinished"></translation> + <translation>Systeem</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="618"/> <source>Utility</source> - <translation type="unfinished"></translation> + <translation>Hulpmiddel</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="619"/> <source>Wine</source> - <translation type="unfinished"></translation> + <translation>Wine</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="620"/> <source>Unsorted</source> - <translation type="unfinished"></translation> + <translation>Ongesorteerd</translation> </message> </context> <context> @@ -75,22 +75,22 @@ <location filename="../mainUI.ui" line="14"/> <location filename="../mainUI.cpp" line="53"/> <source>Calculator</source> - <translation type="unfinished"></translation> + <translation>Rekenmachine</translation> </message> <message> <location filename="../mainUI.ui" line="657"/> <source>Advanced Operations</source> - <translation type="unfinished"></translation> + <translation>Geavanceerde bewerkingen</translation> </message> <message> <location filename="../mainUI.cpp" line="83"/> <source>Percentage %1</source> - <translation type="unfinished"></translation> + <translation>Percentage %1</translation> </message> <message> <location filename="../mainUI.cpp" line="85"/> <source>Power %1</source> - <translation type="unfinished"></translation> + <translation>Prestatie %1</translation> </message> <message> <location filename="../mainUI.cpp" line="87"/> diff --git a/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_pt_BR.ts b/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_pt_BR.ts index 153a01b4..e26ecb58 100644 --- a/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_pt_BR.ts +++ b/src-qt5/desktop-utils/lumina-calculator/i18n/l-calc_pt_BR.ts @@ -6,67 +6,67 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="608"/> <source>Multimedia</source> - <translation type="unfinished"></translation> + <translation>Multimídia</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="609"/> <source>Development</source> - <translation type="unfinished"></translation> + <translation>Desenvolvimento</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="610"/> <source>Education</source> - <translation type="unfinished"></translation> + <translation>Educação</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="611"/> <source>Games</source> - <translation type="unfinished"></translation> + <translation>Jogos</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="612"/> <source>Graphics</source> - <translation type="unfinished"></translation> + <translation>Gráficos</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="613"/> <source>Network</source> - <translation type="unfinished"></translation> + <translation>Rede</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="614"/> <source>Office</source> - <translation type="unfinished"></translation> + <translation>Escritório</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="615"/> <source>Science</source> - <translation type="unfinished"></translation> + <translation>Ciência</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="616"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>Configurações</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="617"/> <source>System</source> - <translation type="unfinished"></translation> + <translation>Sistema</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="618"/> <source>Utility</source> - <translation type="unfinished"></translation> + <translation>Utilitários</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="619"/> <source>Wine</source> - <translation type="unfinished"></translation> + <translation>Wine</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="620"/> <source>Unsorted</source> - <translation type="unfinished"></translation> + <translation>Não classificado</translation> </message> </context> <context> diff --git a/src-qt5/desktop-utils/lumina-calculator/lumina-calculator.pro b/src-qt5/desktop-utils/lumina-calculator/lumina-calculator.pro index c2314545..07490634 100644 --- a/src-qt5/desktop-utils/lumina-calculator/lumina-calculator.pro +++ b/src-qt5/desktop-utils/lumina-calculator/lumina-calculator.pro @@ -84,13 +84,13 @@ TRANSLATIONS = i18n/l-calc_af.ts \ i18n/l-calc_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-calculator.desktop desktop.path=$${L_SHAREDIR}/applications/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-calculator.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-calculator.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-calculator.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-calculator.1.gz" INSTALLS += target desktop manpage diff --git a/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro b/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro index 8a850a1c..dcfee470 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro +++ b/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro @@ -89,13 +89,13 @@ TRANSLATIONS = i18n/l-fileinfo_af.ts \ i18n/l-fileinfo_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-fileinfo.desktop desktop.path=$${L_SHAREDIR}/applications/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-fileinfo.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-fileinfo.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-fileinfo.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-fileinfo.1.gz" INSTALLS += target desktop manpage diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp index 28bfa20b..8455e3aa 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp @@ -118,6 +118,7 @@ QSize orig = settings->value("preferences/MainWindowSize", QSize()).toSize(); connect(TRAY, SIGNAL(JobsFinished()), this, SLOT(TrayJobsFinished()) ); if(DEBUG){ qDebug() << " - Done with init"; } ui->actionOpen_as_Root->setVisible(LUtils::isValidBinary("qsudo")); + ui->transferTreeView->setVisible(false); } MainUI::~MainUI(){ diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.ui b/src-qt5/desktop-utils/lumina-fm/MainUI.ui index a15f91c9..5f067786 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.ui @@ -69,7 +69,7 @@ <x>0</x> <y>0</y> <width>567</width> - <height>359</height> + <height>161</height> </rect> </property> <layout class="QHBoxLayout" name="BrowserLayout"> @@ -98,6 +98,16 @@ <widget class="QWidget" name="page_image"/> </widget> </item> + <item> + <widget class="QTreeView" name="transferTreeView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> </layout> </widget> <widget class="QMenuBar" name="menubar"> diff --git a/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro b/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro index 4f66ce0a..b59aface 100644 --- a/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro +++ b/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro @@ -126,13 +126,13 @@ TRANSLATIONS = i18n/lumina-fm_af.ts \ i18n/lumina-fm_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-fm.desktop desktop.path=$${L_SHAREDIR}/applications/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-fm.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-fm.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-fm.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-fm.1.gz" INSTALLS += target desktop icons manpage diff --git a/src-qt5/desktop-utils/lumina-fm/transferd.cpp b/src-qt5/desktop-utils/lumina-fm/transferd.cpp new file mode 100644 index 00000000..c5a0a156 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/transferd.cpp @@ -0,0 +1,28 @@ + + +int totaltransactions = sel.length(); +QList<TransactionInfo> transaction; +for(int i=0;i<sel.length();i++){ + QStringList info; + info << sel[i] << sel[i].size() << false; + totalsize = totalsize + sel[i].size(); +} +bool paused = false; +for(int i=0; i<transaction.length(); i++){ + +while(paused = 1 ){ + pausetimer = new QTimer(this); + pausetimer->start(5000); +} +QElapsedTimer timer; +timer.start(); +//copy/move file +timer.elapsed(); // "milliseconds" +transferTime = transferTime + timer.elapsed() +transaction[i].value(2) = true; +currentTransfered++; +currentTransferedSize = currentTransferedSize + transaction[i].value(1); +//calculate transfer data rate from transferTime and currentTransferedSize +avgTransferRate = ( currentTransferedSize / (transferTime * 1000) ) +//can do estimates on potential time? +} diff --git a/src-qt5/desktop-utils/lumina-fm/transferd.h b/src-qt5/desktop-utils/lumina-fm/transferd.h new file mode 100644 index 00000000..291541e8 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/transferd.h @@ -0,0 +1,13 @@ +class transactionInfo{ +public: + QString filepath; + qint64 filesize; + Bool finished; +}; + + +QStringList sel; +int totaltransactions currentTransfered; +qint64 totalsize, currentTransferedSize, transferTime, avgTransferRate; +bool paused; +QElapsedTimer timer; diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_ca.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_ca.ts index ba197b5c..de6a4daf 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_ca.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_ca.ts @@ -59,12 +59,12 @@ <message> <location filename="../mainUI.ui" line="368"/> <source>Love this song</source> - <translation>M'agrada aquesta cançó</translation> + <translation>M'agrada aquesta cançó</translation> </message> <message> <location filename="../mainUI.ui" line="384"/> <source>Tired of this song (will not play for a month)</source> - <translation>Cansat d'aquesta cançó (no sonarà durant un mes)</translation> + <translation>Cansat d'aquesta cançó (no sonarà durant un mes)</translation> </message> <message> <location filename="../mainUI.ui" line="397"/> @@ -84,7 +84,7 @@ <message> <location filename="../mainUI.ui" line="479"/> <source>Delete current station</source> - <translation>Suprimeix l'emissora actual</translation> + <translation>Suprimeix l'emissora actual</translation> </message> <message> <location filename="../mainUI.ui" line="482"/> @@ -129,17 +129,17 @@ <message> <location filename="../mainUI.ui" line="573"/> <source>Audio Quality</source> - <translation>Qualitat de l'àudio</translation> + <translation>Qualitat de l'àudio</translation> </message> <message> <location filename="../mainUI.ui" line="583"/> <source>Proxy URL</source> - <translation>URL de l'intermediari</translation> + <translation>URL de l'intermediari</translation> </message> <message> <location filename="../mainUI.ui" line="593"/> <source>Control Proxy URL</source> - <translation>Control de l'URL de l'intermediari</translation> + <translation>Control de l'URL de l'intermediari</translation> </message> <message> <location filename="../mainUI.ui" line="618"/> @@ -149,7 +149,7 @@ <message> <location filename="../mainUI.ui" line="656"/> <source>Audio Driver</source> - <translation>Controlador d'àudio</translation> + <translation>Controlador d'àudio</translation> </message> <message> <location filename="../mainUI.ui" line="681"/> @@ -194,7 +194,7 @@ <message> <location filename="../mainUI.ui" line="751"/> <source>Raise audio volume</source> - <translation>Apuja el volum de l'àudio</translation> + <translation>Apuja el volum de l'àudio</translation> </message> <message> <location filename="../mainUI.ui" line="756"/> @@ -204,12 +204,12 @@ <message> <location filename="../mainUI.ui" line="759"/> <source>Lower audio volume</source> - <translation>Abaixa el volum de l'àudio</translation> + <translation>Abaixa el volum de l'àudio</translation> </message> <message> <location filename="../mainUI.ui" line="764"/> <source>Close Application</source> - <translation>Tanca l'aplicació</translation> + <translation>Tanca l'aplicació</translation> </message> <message> <location filename="../mainUI.ui" line="767"/> @@ -224,12 +224,12 @@ <message> <location filename="../mainUI.ui" line="786"/> <source>From current artist</source> - <translation>De l'artista actual</translation> + <translation>De l'artista actual</translation> </message> <message> <location filename="../mainUI.ui" line="789"/> <source>Create station from current artist</source> - <translation>Crea una emissora de l'artista actual</translation> + <translation>Crea una emissora de l'artista actual</translation> </message> <message> <location filename="../mainUI.ui" line="794"/> @@ -280,7 +280,7 @@ <message> <location filename="../mainUI.cpp" line="105"/> <source>Please install the `pianobar` utility to enable this functionality</source> - <translation>Si us plau, instal·leu la utilitat "pianobar" per habilitar aquesta funcionalitat.</translation> + <translation>Si us plau, instal·leu la utilitat "pianobar" per habilitar aquesta funcionalitat.</translation> </message> <message> <location filename="../mainUI.cpp" line="109"/> @@ -332,7 +332,7 @@ <message> <location filename="../mainUI.cpp" line="492"/> <source>Media Buffering...</source> - <translation>S'omple la memòria intermèdia...</translation> + <translation>S'omple la memòria intermèdia...</translation> </message> <message> <location filename="../mainUI.cpp" line="576"/> @@ -368,67 +368,67 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="608"/> <source>Multimedia</source> - <translation type="unfinished"></translation> + <translation>Multimèdia</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="609"/> <source>Development</source> - <translation type="unfinished"></translation> + <translation>Desenvolupament</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="610"/> <source>Education</source> - <translation type="unfinished"></translation> + <translation>Educació</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="611"/> <source>Games</source> - <translation type="unfinished"></translation> + <translation>Jocs</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="612"/> <source>Graphics</source> - <translation type="unfinished"></translation> + <translation>Gràfics</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="613"/> <source>Network</source> - <translation type="unfinished"></translation> + <translation>Xarxa</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="614"/> <source>Office</source> - <translation type="unfinished"></translation> + <translation>Oficina</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="615"/> <source>Science</source> - <translation type="unfinished"></translation> + <translation>Ciència</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="616"/> <source>Settings</source> - <translation type="unfinished">Paràmetres</translation> + <translation>Paràmetres</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="617"/> <source>System</source> - <translation type="unfinished"></translation> + <translation>Sistema</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="618"/> <source>Utility</source> - <translation type="unfinished"></translation> + <translation>Utilitat</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="619"/> <source>Wine</source> - <translation type="unfinished"></translation> + <translation>Wine</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="620"/> <source>Unsorted</source> - <translation type="unfinished"></translation> + <translation>Sense classificar</translation> </message> </context> </TS> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_cs.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_cs.ts index b434a529..d1e93554 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_cs.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_cs.ts @@ -368,67 +368,67 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="608"/> <source>Multimedia</source> - <translation type="unfinished"></translation> + <translation>Multimédia</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="609"/> <source>Development</source> - <translation type="unfinished"></translation> + <translation>Vývoj</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="610"/> <source>Education</source> - <translation type="unfinished"></translation> + <translation>Výuka</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="611"/> <source>Games</source> - <translation type="unfinished"></translation> + <translation>Hry</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="612"/> <source>Graphics</source> - <translation type="unfinished"></translation> + <translation>Grafika</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="613"/> <source>Network</source> - <translation type="unfinished"></translation> + <translation>Sítě</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="614"/> <source>Office</source> - <translation type="unfinished"></translation> + <translation>Kancelář</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="615"/> <source>Science</source> - <translation type="unfinished"></translation> + <translation>Věda</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="616"/> <source>Settings</source> - <translation type="unfinished">Nastavení</translation> + <translation>Nastavení</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="617"/> <source>System</source> - <translation type="unfinished"></translation> + <translation>Systém</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="618"/> <source>Utility</source> - <translation type="unfinished"></translation> + <translation>Nástroje</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="619"/> <source>Wine</source> - <translation type="unfinished"></translation> + <translation>Wine</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="620"/> <source>Unsorted</source> - <translation type="unfinished"></translation> + <translation>Různé</translation> </message> </context> </TS> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_da.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_da.ts index b2f87e32..612ae523 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_da.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_da.ts @@ -368,67 +368,67 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="608"/> <source>Multimedia</source> - <translation type="unfinished"></translation> + <translation>Multimedie</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="609"/> <source>Development</source> - <translation type="unfinished"></translation> + <translation>Udvikling</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="610"/> <source>Education</source> - <translation type="unfinished"></translation> + <translation>Læring</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="611"/> <source>Games</source> - <translation type="unfinished"></translation> + <translation>Spil</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="612"/> <source>Graphics</source> - <translation type="unfinished"></translation> + <translation>Grafik</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="613"/> <source>Network</source> - <translation type="unfinished"></translation> + <translation>Netværk</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="614"/> <source>Office</source> - <translation type="unfinished"></translation> + <translation>Kontor</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="615"/> <source>Science</source> - <translation type="unfinished"></translation> + <translation>Naturvidenskab</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="616"/> <source>Settings</source> - <translation type="unfinished">Indstillinger</translation> + <translation>Indstillinger</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="617"/> <source>System</source> - <translation type="unfinished"></translation> + <translation>System</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="618"/> <source>Utility</source> - <translation type="unfinished"></translation> + <translation>Redskab</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="619"/> <source>Wine</source> - <translation type="unfinished"></translation> + <translation>Wine</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="620"/> <source>Unsorted</source> - <translation type="unfinished"></translation> + <translation>Usorteret</translation> </message> </context> </TS> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_de.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_de.ts index 7ab5151e..ac56615b 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_de.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_de.ts @@ -7,94 +7,94 @@ <location filename="../mainUI.ui" line="14"/> <location filename="../mainUI.cpp" line="285"/> <source>Media Player</source> - <translation type="unfinished"></translation> + <translation>Medienabspieler</translation> </message> <message> <location filename="../mainUI.ui" line="50"/> <location filename="../mainUI.ui" line="261"/> <location filename="../mainUI.cpp" line="631"/> <source>Now Playing</source> - <translation type="unfinished"></translation> + <translation>Wiedergabe läuft jetzt</translation> </message> <message> <location filename="../mainUI.ui" line="74"/> <source>(No Running Video)</source> - <translation type="unfinished"></translation> + <translation>(Kein laufendes Video)</translation> </message> <message> <location filename="../mainUI.ui" line="105"/> <source>Playlist</source> - <translation type="unfinished"></translation> + <translation>Wiedergabeliste</translation> </message> <message> <location filename="../mainUI.ui" line="167"/> <source>up</source> - <translation type="unfinished"></translation> + <translation>hinauf</translation> </message> <message> <location filename="../mainUI.ui" line="183"/> <source>down</source> - <translation type="unfinished"></translation> + <translation>herab</translation> </message> <message> <location filename="../mainUI.ui" line="267"/> <source>Current Song</source> - <translation type="unfinished"></translation> + <translation>Aktueller Song</translation> </message> <message> <location filename="../mainUI.ui" line="303"/> <source>TITLE</source> - <translation type="unfinished"></translation> + <translation>TITEL</translation> </message> <message> <location filename="../mainUI.ui" line="327"/> <source>ARTIST</source> - <translation type="unfinished"></translation> + <translation>INTERPRET</translation> </message> <message> <location filename="../mainUI.ui" line="337"/> <source>ALBUM</source> - <translation type="unfinished"></translation> + <translation>ALBUM</translation> </message> <message> <location filename="../mainUI.ui" line="368"/> <source>Love this song</source> - <translation type="unfinished"></translation> + <translation>Liebe diesen Song</translation> </message> <message> <location filename="../mainUI.ui" line="384"/> <source>Tired of this song (will not play for a month)</source> - <translation type="unfinished"></translation> + <translation>Müde von diesem Song (wird einen Monat lang nicht gespielt)</translation> </message> <message> <location filename="../mainUI.ui" line="397"/> <source>Ban this song (will never play again)</source> - <translation type="unfinished"></translation> + <translation>Diesen Song verbannen (wird nie wieder abgespielt)</translation> </message> <message> <location filename="../mainUI.ui" line="417"/> <source>View details about song (launches web browser)</source> - <translation type="unfinished"></translation> + <translation>Details zum Song anzeigen (startet den Webbrowser)</translation> </message> <message> <location filename="../mainUI.ui" line="448"/> <source>Current Station</source> - <translation type="unfinished"></translation> + <translation>Aktueller Sender</translation> </message> <message> <location filename="../mainUI.ui" line="479"/> <source>Delete current station</source> - <translation type="unfinished"></translation> + <translation>Aktuellen Sender löschen</translation> </message> <message> <location filename="../mainUI.ui" line="482"/> <source>rm</source> - <translation type="unfinished"></translation> + <translation>rm</translation> </message> <message> <location filename="../mainUI.ui" line="492"/> <source>Create new station</source> - <translation type="unfinished"></translation> + <translation>Neuen Sender erstellen</translation> </message> <message> <location filename="../mainUI.ui" line="495"/> @@ -104,37 +104,37 @@ <message> <location filename="../mainUI.ui" line="512"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>Einstellungen</translation> </message> <message> <location filename="../mainUI.ui" line="521"/> <source>Pandora Account Login</source> - <translation type="unfinished"></translation> + <translation>Pandora-Kontoanmeldung</translation> </message> <message> <location filename="../mainUI.ui" line="527"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>E-Mail</translation> </message> <message> <location filename="../mainUI.ui" line="537"/> <source>Password</source> - <translation type="unfinished"></translation> + <translation>Passwort</translation> </message> <message> <location filename="../mainUI.ui" line="557"/> <source><a href=https://www.pandora.com/account/register>Need an account?</a></source> - <translation type="unfinished"></translation> + <translation><a href=https://www.pandora.com/account/register>Benötigen Sie ein Konto?</a></translation> </message> <message> <location filename="../mainUI.ui" line="573"/> <source>Audio Quality</source> - <translation type="unfinished"></translation> + <translation>Audioqualität</translation> </message> <message> <location filename="../mainUI.ui" line="583"/> <source>Proxy URL</source> - <translation type="unfinished"></translation> + <translation>Proxy-URL</translation> </message> <message> <location filename="../mainUI.ui" line="593"/> @@ -144,77 +144,77 @@ <message> <location filename="../mainUI.ui" line="618"/> <source>Apply Settings</source> - <translation type="unfinished"></translation> + <translation>Einstellungen anwenden</translation> </message> <message> <location filename="../mainUI.ui" line="656"/> <source>Audio Driver</source> - <translation type="unfinished"></translation> + <translation>Audiotreiber</translation> </message> <message> <location filename="../mainUI.ui" line="681"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>Datei</translation> </message> <message> <location filename="../mainUI.ui" line="688"/> <source>View</source> - <translation type="unfinished"></translation> + <translation>Ansicht</translation> </message> <message> <location filename="../mainUI.ui" line="723"/> <source>Play</source> - <translation type="unfinished"></translation> + <translation>Wiedergabe</translation> </message> <message> <location filename="../mainUI.ui" line="728"/> <source>Pause</source> - <translation type="unfinished"></translation> + <translation>Pause</translation> </message> <message> <location filename="../mainUI.ui" line="733"/> <source>Stop</source> - <translation type="unfinished"></translation> + <translation>Stopp</translation> </message> <message> <location filename="../mainUI.ui" line="738"/> <source>Next</source> - <translation type="unfinished"></translation> + <translation>Weiter</translation> </message> <message> <location filename="../mainUI.ui" line="743"/> <source>Back</source> - <translation type="unfinished"></translation> + <translation>Zurück</translation> </message> <message> <location filename="../mainUI.ui" line="748"/> <source>VolUp</source> - <translation type="unfinished"></translation> + <translation>Lautstärke erhöhen</translation> </message> <message> <location filename="../mainUI.ui" line="751"/> <source>Raise audio volume</source> - <translation type="unfinished"></translation> + <translation>Audiolautstärke erhöhen</translation> </message> <message> <location filename="../mainUI.ui" line="756"/> <source>VolDown</source> - <translation type="unfinished"></translation> + <translation>Lautstärke verringern</translation> </message> <message> <location filename="../mainUI.ui" line="759"/> <source>Lower audio volume</source> - <translation type="unfinished"></translation> + <translation>Audiolautstärke verringern</translation> </message> <message> <location filename="../mainUI.ui" line="764"/> <source>Close Application</source> - <translation type="unfinished"></translation> + <translation>Anwendung schließen</translation> </message> <message> <location filename="../mainUI.ui" line="767"/> <source>Ctrl+Q</source> - <translation type="unfinished"></translation> + <translation>Strg+Q</translation> </message> <message> <location filename="../mainUI.ui" line="781"/> @@ -224,7 +224,7 @@ <message> <location filename="../mainUI.ui" line="786"/> <source>From current artist</source> - <translation type="unfinished"></translation> + <translation>Vom aktuellen Interpreten</translation> </message> <message> <location filename="../mainUI.ui" line="789"/> @@ -234,7 +234,7 @@ <message> <location filename="../mainUI.ui" line="794"/> <source>From current song</source> - <translation type="unfinished"></translation> + <translation>Vom aktuellen Song</translation> </message> <message> <location filename="../mainUI.ui" line="797"/> @@ -244,84 +244,85 @@ <message> <location filename="../mainUI.ui" line="808"/> <source>Show song notifications</source> - <translation type="unfinished"></translation> + <translation>Song-Benachrichtigungen anzeigen</translation> </message> <message> <location filename="../mainUI.ui" line="813"/> <source>Search...</source> - <translation type="unfinished"></translation> + <translation>Suchen...</translation> </message> <message> <location filename="../mainUI.ui" line="816"/> <source>Search for a new station</source> - <translation type="unfinished"></translation> + <translation>Einen neuen Sender suchen</translation> </message> <message> <location filename="../mainUI.ui" line="828"/> <location filename="../mainUI.cpp" line="276"/> <source>Pandora Radio</source> - <translation type="unfinished"></translation> + <translation>Pandora Radio</translation> </message> <message> <location filename="../mainUI.ui" line="831"/> <source>Stream from Pandora Radio</source> - <translation type="unfinished"></translation> + <translation>Stream von Pandora Radio</translation> </message> <message> <location filename="../mainUI.ui" line="839"/> <source>Local Files</source> - <translation type="unfinished"></translation> + <translation>Lokale Dateien</translation> </message> <message> <location filename="../mainUI.ui" line="842"/> <source>Play Local Files</source> - <translation type="unfinished"></translation> + <translation>Lokale Dateien wiedergeben</translation> </message> <message> <location filename="../mainUI.cpp" line="105"/> <source>Please install the `pianobar` utility to enable this functionality</source> - <translation type="unfinished"></translation> + <translation>Bitte installieren Sie das Dienstprogramm `pianobar`, um diese Funktionalität zu aktivieren</translation> </message> <message> <location filename="../mainUI.cpp" line="109"/> <source>Stream music from the Pandora online radio service</source> - <translation type="unfinished"></translation> + <translation>Streaming von Musik vom Pandora Online-Radiodienst</translation> </message> <message> <location filename="../mainUI.cpp" line="122"/> <source>Low</source> - <translation type="unfinished"></translation> + <translation>Niedrig</translation> </message> <message> <location filename="../mainUI.cpp" line="123"/> <source>Medium</source> - <translation type="unfinished"></translation> + <translation>Mittel</translation> </message> <message> <location filename="../mainUI.cpp" line="124"/> <source>High</source> - <translation type="unfinished"></translation> + <translation>Hoch</translation> </message> <message> <location filename="../mainUI.cpp" line="358"/> <source>Open Multimedia Files</source> - <translation type="unfinished"></translation> + <translation>Multimedia-Dateien öffnen</translation> </message> <message> <location filename="../mainUI.cpp" line="406"/> <source>Now Playing:</source> - <translation type="unfinished"></translation> + <translation>Wird gerade wiedergegeben:</translation> </message> <message> <location filename="../mainUI.cpp" line="471"/> <source>[PLAYBACK ERROR] %1</source> - <translation type="unfinished"></translation> + <translation>[WIEDERGABEFEHLER] +%1</translation> </message> <message> <location filename="../mainUI.cpp" line="488"/> <source>Media Loading...</source> - <translation type="unfinished"></translation> + <translation>Medieninhalt wird geladen...</translation> </message> <message> <location filename="../mainUI.cpp" line="490"/> @@ -331,27 +332,27 @@ <message> <location filename="../mainUI.cpp" line="492"/> <source>Media Buffering...</source> - <translation type="unfinished"></translation> + <translation>Medieninhalt wird gepuffert...</translation> </message> <message> <location filename="../mainUI.cpp" line="576"/> <source>Pandora: Create Station</source> - <translation type="unfinished"></translation> + <translation>Pandora: Sender erstellen</translation> </message> <message> <location filename="../mainUI.cpp" line="576"/> <source>Search Term</source> - <translation type="unfinished"></translation> + <translation>Suchbegriff</translation> </message> <message> <location filename="../mainUI.cpp" line="654"/> <source>Pandora Question</source> - <translation type="unfinished"></translation> + <translation>Pandora-Frage</translation> </message> <message> <location filename="../mainUI.cpp" line="659"/> <source>Pandora Error</source> - <translation type="unfinished"></translation> + <translation>Pandora-Fehler</translation> </message> </context> <context> @@ -359,7 +360,7 @@ <message> <location filename="../PianoBarProcess.cpp" line="358"/> <source>Could not find any matches. Please try a different search term</source> - <translation type="unfinished"></translation> + <translation>Keine Treffer gefunden. Bitte versuchen Sie einen anderen Suchbegriff</translation> </message> </context> <context> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_fi.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_fi.ts index 632ef536..5d01912a 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_fi.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_fi.ts @@ -7,134 +7,134 @@ <location filename="../mainUI.ui" line="14"/> <location filename="../mainUI.cpp" line="285"/> <source>Media Player</source> - <translation type="unfinished"></translation> + <translation>Mediasoitin</translation> </message> <message> <location filename="../mainUI.ui" line="50"/> <location filename="../mainUI.ui" line="261"/> <location filename="../mainUI.cpp" line="631"/> <source>Now Playing</source> - <translation type="unfinished"></translation> + <translation>Nyt soi</translation> </message> <message> <location filename="../mainUI.ui" line="74"/> <source>(No Running Video)</source> - <translation type="unfinished"></translation> + <translation>(Ei videota käynnissä)</translation> </message> <message> <location filename="../mainUI.ui" line="105"/> <source>Playlist</source> - <translation type="unfinished"></translation> + <translation>Soittolista</translation> </message> <message> <location filename="../mainUI.ui" line="167"/> <source>up</source> - <translation type="unfinished"></translation> + <translation>ylemmäs</translation> </message> <message> <location filename="../mainUI.ui" line="183"/> <source>down</source> - <translation type="unfinished"></translation> + <translation>alemmas</translation> </message> <message> <location filename="../mainUI.ui" line="267"/> <source>Current Song</source> - <translation type="unfinished"></translation> + <translation>Nykyinen kappale</translation> </message> <message> <location filename="../mainUI.ui" line="303"/> <source>TITLE</source> - <translation type="unfinished"></translation> + <translation>NIMI</translation> </message> <message> <location filename="../mainUI.ui" line="327"/> <source>ARTIST</source> - <translation type="unfinished"></translation> + <translation>ARTISTI</translation> </message> <message> <location filename="../mainUI.ui" line="337"/> <source>ALBUM</source> - <translation type="unfinished"></translation> + <translation>ALBUMI</translation> </message> <message> <location filename="../mainUI.ui" line="368"/> <source>Love this song</source> - <translation type="unfinished"></translation> + <translation>Tykkään tästä</translation> </message> <message> <location filename="../mainUI.ui" line="384"/> <source>Tired of this song (will not play for a month)</source> - <translation type="unfinished"></translation> + <translation>Kyllästynyt tähän (ei soiteta kuukauteen)</translation> </message> <message> <location filename="../mainUI.ui" line="397"/> <source>Ban this song (will never play again)</source> - <translation type="unfinished"></translation> + <translation>Estä tämä (ei soiteta enää)</translation> </message> <message> <location filename="../mainUI.ui" line="417"/> <source>View details about song (launches web browser)</source> - <translation type="unfinished"></translation> + <translation>Näytä kappaleen tiedot (käynnistää verkkoselaimen)</translation> </message> <message> <location filename="../mainUI.ui" line="448"/> <source>Current Station</source> - <translation type="unfinished"></translation> + <translation>Nykyinen asema</translation> </message> <message> <location filename="../mainUI.ui" line="479"/> <source>Delete current station</source> - <translation type="unfinished"></translation> + <translation>Poista nykyinen asema</translation> </message> <message> <location filename="../mainUI.ui" line="482"/> <source>rm</source> - <translation type="unfinished"></translation> + <translation>poista</translation> </message> <message> <location filename="../mainUI.ui" line="492"/> <source>Create new station</source> - <translation type="unfinished"></translation> + <translation>Luo uusi asema</translation> </message> <message> <location filename="../mainUI.ui" line="495"/> <source>add</source> - <translation type="unfinished"></translation> + <translation>lisää</translation> </message> <message> <location filename="../mainUI.ui" line="512"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>Asetukset</translation> </message> <message> <location filename="../mainUI.ui" line="521"/> <source>Pandora Account Login</source> - <translation type="unfinished"></translation> + <translation>Kirjautuminen Pandora-tilille</translation> </message> <message> <location filename="../mainUI.ui" line="527"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>Sähköposti</translation> </message> <message> <location filename="../mainUI.ui" line="537"/> <source>Password</source> - <translation type="unfinished"></translation> + <translation>Salasana</translation> </message> <message> <location filename="../mainUI.ui" line="557"/> <source><a href=https://www.pandora.com/account/register>Need an account?</a></source> - <translation type="unfinished"></translation> + <translation><a href=https://www.pandora.com/account/register>Tarvitsetko tilin?</a></translation> </message> <message> <location filename="../mainUI.ui" line="573"/> <source>Audio Quality</source> - <translation type="unfinished"></translation> + <translation>Äänenlaatu</translation> </message> <message> <location filename="../mainUI.ui" line="583"/> <source>Proxy URL</source> - <translation type="unfinished"></translation> + <translation>Välityspalvelimen osoite</translation> </message> <message> <location filename="../mainUI.ui" line="593"/> @@ -144,47 +144,47 @@ <message> <location filename="../mainUI.ui" line="618"/> <source>Apply Settings</source> - <translation type="unfinished"></translation> + <translation>Ota asetukset käyttöön</translation> </message> <message> <location filename="../mainUI.ui" line="656"/> <source>Audio Driver</source> - <translation type="unfinished"></translation> + <translation>Ääniajuri</translation> </message> <message> <location filename="../mainUI.ui" line="681"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>Tiedosto</translation> </message> <message> <location filename="../mainUI.ui" line="688"/> <source>View</source> - <translation type="unfinished"></translation> + <translation>Näytä</translation> </message> <message> <location filename="../mainUI.ui" line="723"/> <source>Play</source> - <translation type="unfinished"></translation> + <translation>Toista</translation> </message> <message> <location filename="../mainUI.ui" line="728"/> <source>Pause</source> - <translation type="unfinished"></translation> + <translation>Tauko</translation> </message> <message> <location filename="../mainUI.ui" line="733"/> <source>Stop</source> - <translation type="unfinished"></translation> + <translation>Pysäytä</translation> </message> <message> <location filename="../mainUI.ui" line="738"/> <source>Next</source> - <translation type="unfinished"></translation> + <translation>Seuraava</translation> </message> <message> <location filename="../mainUI.ui" line="743"/> <source>Back</source> - <translation type="unfinished"></translation> + <translation>Takaisin</translation> </message> <message> <location filename="../mainUI.ui" line="748"/> @@ -194,7 +194,7 @@ <message> <location filename="../mainUI.ui" line="751"/> <source>Raise audio volume</source> - <translation type="unfinished"></translation> + <translation>Nosta äänenvoimakkuutta</translation> </message> <message> <location filename="../mainUI.ui" line="756"/> @@ -204,12 +204,12 @@ <message> <location filename="../mainUI.ui" line="759"/> <source>Lower audio volume</source> - <translation type="unfinished"></translation> + <translation>Laske äänenvoimakkuutta</translation> </message> <message> <location filename="../mainUI.ui" line="764"/> <source>Close Application</source> - <translation type="unfinished"></translation> + <translation>Sulje sovellus</translation> </message> <message> <location filename="../mainUI.ui" line="767"/> @@ -219,27 +219,27 @@ <message> <location filename="../mainUI.ui" line="781"/> <source>Close to tray when active</source> - <translation type="unfinished"></translation> + <translation>Sulje aktiivisena ilmoitusalueelle</translation> </message> <message> <location filename="../mainUI.ui" line="786"/> <source>From current artist</source> - <translation type="unfinished"></translation> + <translation>Nykyiseltä artistilta</translation> </message> <message> <location filename="../mainUI.ui" line="789"/> <source>Create station from current artist</source> - <translation type="unfinished"></translation> + <translation>Luo nykyisestä artistista asema</translation> </message> <message> <location filename="../mainUI.ui" line="794"/> <source>From current song</source> - <translation type="unfinished"></translation> + <translation>Nykyisestä kappaleesta</translation> </message> <message> <location filename="../mainUI.ui" line="797"/> <source>Create station from current song</source> - <translation type="unfinished"></translation> + <translation>Luo nykyisestä kappaleesta asema</translation> </message> <message> <location filename="../mainUI.ui" line="808"/> @@ -249,43 +249,43 @@ <message> <location filename="../mainUI.ui" line="813"/> <source>Search...</source> - <translation type="unfinished"></translation> + <translation>Etsi...</translation> </message> <message> <location filename="../mainUI.ui" line="816"/> <source>Search for a new station</source> - <translation type="unfinished"></translation> + <translation>Etsi uutta asemaa</translation> </message> <message> <location filename="../mainUI.ui" line="828"/> <location filename="../mainUI.cpp" line="276"/> <source>Pandora Radio</source> - <translation type="unfinished"></translation> + <translation>Pandora-radio</translation> </message> <message> <location filename="../mainUI.ui" line="831"/> <source>Stream from Pandora Radio</source> - <translation type="unfinished"></translation> + <translation>Virtaus Pandora-radiosta</translation> </message> <message> <location filename="../mainUI.ui" line="839"/> <source>Local Files</source> - <translation type="unfinished"></translation> + <translation>Paikalliset tiedostot</translation> </message> <message> <location filename="../mainUI.ui" line="842"/> <source>Play Local Files</source> - <translation type="unfinished"></translation> + <translation>Toista paikallisia tiedostoja</translation> </message> <message> <location filename="../mainUI.cpp" line="105"/> <source>Please install the `pianobar` utility to enable this functionality</source> - <translation type="unfinished"></translation> + <translation>Toiminnon käyttäminen vaatii pianobar-ohjelman asentamista</translation> </message> <message> <location filename="../mainUI.cpp" line="109"/> <source>Stream music from the Pandora online radio service</source> - <translation type="unfinished"></translation> + <translation>Virtauta musiikkia Pandora-verkkoradiopalvelusta</translation> </message> <message> <location filename="../mainUI.cpp" line="122"/> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_hu.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_hu.ts index 80414a8b..1a2cf1aa 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_hu.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_hu.ts @@ -7,7 +7,7 @@ <location filename="../mainUI.ui" line="14"/> <location filename="../mainUI.cpp" line="285"/> <source>Media Player</source> - <translation type="unfinished"></translation> + <translation>Média lejátszó</translation> </message> <message> <location filename="../mainUI.ui" line="50"/> @@ -154,7 +154,7 @@ <message> <location filename="../mainUI.ui" line="681"/> <source>File</source> - <translation type="unfinished"></translation> + <translation type="unfinished">Fájl</translation> </message> <message> <location filename="../mainUI.ui" line="688"/> @@ -362,72 +362,4 @@ <translation type="unfinished"></translation> </message> </context> -<context> - <name>XDGDesktopList</name> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="608"/> - <source>Multimedia</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="609"/> - <source>Development</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="610"/> - <source>Education</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="611"/> - <source>Games</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="612"/> - <source>Graphics</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="613"/> - <source>Network</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="614"/> - <source>Office</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="615"/> - <source>Science</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="616"/> - <source>Settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="617"/> - <source>System</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="618"/> - <source>Utility</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="619"/> - <source>Wine</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../../core/libLumina/LuminaXDG.cpp" line="620"/> - <source>Unsorted</source> - <translation type="unfinished"></translation> - </message> -</context> </TS> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_lt.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_lt.ts index ecaf4cbc..f10cf90d 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_lt.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_lt.ts @@ -19,7 +19,7 @@ <message> <location filename="../mainUI.ui" line="74"/> <source>(No Running Video)</source> - <translation type="unfinished"></translation> + <translation>(Nėra paleisto vaizdo įrašo)</translation> </message> <message> <location filename="../mainUI.ui" line="105"/> @@ -89,7 +89,7 @@ <message> <location filename="../mainUI.ui" line="482"/> <source>rm</source> - <translation type="unfinished"></translation> + <translation>šalinti</translation> </message> <message> <location filename="../mainUI.ui" line="492"/> @@ -109,7 +109,7 @@ <message> <location filename="../mainUI.ui" line="521"/> <source>Pandora Account Login</source> - <translation type="unfinished"></translation> + <translation>Pandora paskyros prisijungimas</translation> </message> <message> <location filename="../mainUI.ui" line="527"/> @@ -139,7 +139,7 @@ <message> <location filename="../mainUI.ui" line="593"/> <source>Control Proxy URL</source> - <translation type="unfinished"></translation> + <translation>Valdymo įgaliotojo serverio URL</translation> </message> <message> <location filename="../mainUI.ui" line="618"/> @@ -224,22 +224,22 @@ <message> <location filename="../mainUI.ui" line="786"/> <source>From current artist</source> - <translation type="unfinished"></translation> + <translation>Iš esamo atlikėjo</translation> </message> <message> <location filename="../mainUI.ui" line="789"/> <source>Create station from current artist</source> - <translation type="unfinished"></translation> + <translation>Sukurti stotį iš esamo atlikėjo</translation> </message> <message> <location filename="../mainUI.ui" line="794"/> <source>From current song</source> - <translation type="unfinished"></translation> + <translation>Iš esamos dainos</translation> </message> <message> <location filename="../mainUI.ui" line="797"/> <source>Create station from current song</source> - <translation type="unfinished"></translation> + <translation>Sukurti stotį iš esamos dainos</translation> </message> <message> <location filename="../mainUI.ui" line="808"/> @@ -249,23 +249,23 @@ <message> <location filename="../mainUI.ui" line="813"/> <source>Search...</source> - <translation type="unfinished"></translation> + <translation>Ieškoti...</translation> </message> <message> <location filename="../mainUI.ui" line="816"/> <source>Search for a new station</source> - <translation type="unfinished"></translation> + <translation>Ieškoti naujos stoties</translation> </message> <message> <location filename="../mainUI.ui" line="828"/> <location filename="../mainUI.cpp" line="276"/> <source>Pandora Radio</source> - <translation type="unfinished"></translation> + <translation>Pandora radijas</translation> </message> <message> <location filename="../mainUI.ui" line="831"/> <source>Stream from Pandora Radio</source> - <translation type="unfinished"></translation> + <translation>Transliuoti iš Pandora radijo</translation> </message> <message> <location filename="../mainUI.ui" line="839"/> @@ -280,27 +280,27 @@ <message> <location filename="../mainUI.cpp" line="105"/> <source>Please install the `pianobar` utility to enable this functionality</source> - <translation>Norėdami įjungti šį funkcionalumą, įdiekite "pianobar" paslaugų programą</translation> + <translation>Norėdami įjungti šį funkcionalumą, įdiekite "pianobar" paslaugų programą</translation> </message> <message> <location filename="../mainUI.cpp" line="109"/> <source>Stream music from the Pandora online radio service</source> - <translation type="unfinished"></translation> + <translation>Transliuoti muziką iš Pandora internetinio radijo paslaugos</translation> </message> <message> <location filename="../mainUI.cpp" line="122"/> <source>Low</source> - <translation type="unfinished"></translation> + <translation>Žema</translation> </message> <message> <location filename="../mainUI.cpp" line="123"/> <source>Medium</source> - <translation type="unfinished"></translation> + <translation>Vidutinė</translation> </message> <message> <location filename="../mainUI.cpp" line="124"/> <source>High</source> - <translation type="unfinished"></translation> + <translation>Aukšta</translation> </message> <message> <location filename="../mainUI.cpp" line="358"/> @@ -316,32 +316,33 @@ <location filename="../mainUI.cpp" line="471"/> <source>[PLAYBACK ERROR] %1</source> - <translation type="unfinished"></translation> + <translation>[ATKŪRIMO KLAIDA] +%1</translation> </message> <message> <location filename="../mainUI.cpp" line="488"/> <source>Media Loading...</source> - <translation type="unfinished"></translation> + <translation>Medija įkeliama...</translation> </message> <message> <location filename="../mainUI.cpp" line="490"/> <source>Media Stalled...</source> - <translation type="unfinished"></translation> + <translation>Medija atitrūko...</translation> </message> <message> <location filename="../mainUI.cpp" line="492"/> <source>Media Buffering...</source> - <translation type="unfinished"></translation> + <translation>Medijos buferizacija...</translation> </message> <message> <location filename="../mainUI.cpp" line="576"/> <source>Pandora: Create Station</source> - <translation type="unfinished"></translation> + <translation>Pandora: Sukurti stotį</translation> </message> <message> <location filename="../mainUI.cpp" line="576"/> <source>Search Term</source> - <translation type="unfinished"></translation> + <translation>Ieškomas žodis</translation> </message> <message> <location filename="../mainUI.cpp" line="654"/> @@ -359,7 +360,7 @@ <message> <location filename="../PianoBarProcess.cpp" line="358"/> <source>Could not find any matches. Please try a different search term</source> - <translation type="unfinished"></translation> + <translation>Nepavyko rasti jokių atitikmenų. Pabandykite kitokį ieškomą žodį</translation> </message> </context> <context> @@ -367,67 +368,67 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="608"/> <source>Multimedia</source> - <translation type="unfinished"></translation> + <translation>Multimedija</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="609"/> <source>Development</source> - <translation type="unfinished"></translation> + <translation>Programavimas</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="610"/> <source>Education</source> - <translation type="unfinished"></translation> + <translation>Švietimas</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="611"/> <source>Games</source> - <translation type="unfinished"></translation> + <translation>Žaidimai</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="612"/> <source>Graphics</source> - <translation type="unfinished"></translation> + <translation>Grafika</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="613"/> <source>Network</source> - <translation type="unfinished"></translation> + <translation>Tinklas</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="614"/> <source>Office</source> - <translation type="unfinished"></translation> + <translation>Raštinė</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="615"/> <source>Science</source> - <translation type="unfinished"></translation> + <translation>Mokslas</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="616"/> <source>Settings</source> - <translation type="unfinished">Nustatymai</translation> + <translation>Nustatymai</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="617"/> <source>System</source> - <translation type="unfinished"></translation> + <translation>Sistema</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="618"/> <source>Utility</source> - <translation type="unfinished"></translation> + <translation>Paslaugų programos</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="619"/> <source>Wine</source> - <translation type="unfinished"></translation> + <translation>Wine</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="620"/> <source>Unsorted</source> - <translation type="unfinished"></translation> + <translation>Nesurūšiuota</translation> </message> </context> </TS> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_nl.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_nl.ts index ba312720..860a0aaa 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_nl.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_nl.ts @@ -7,310 +7,310 @@ <location filename="../mainUI.ui" line="14"/> <location filename="../mainUI.cpp" line="285"/> <source>Media Player</source> - <translation type="unfinished"></translation> + <translation>Mediaspeler</translation> </message> <message> <location filename="../mainUI.ui" line="50"/> <location filename="../mainUI.ui" line="261"/> <location filename="../mainUI.cpp" line="631"/> <source>Now Playing</source> - <translation type="unfinished"></translation> + <translation>Nu wordt afgespeeld</translation> </message> <message> <location filename="../mainUI.ui" line="74"/> <source>(No Running Video)</source> - <translation type="unfinished"></translation> + <translation>(geen video wordt op dit moment afgespeeld)</translation> </message> <message> <location filename="../mainUI.ui" line="105"/> <source>Playlist</source> - <translation type="unfinished"></translation> + <translation>Afspeellijst</translation> </message> <message> <location filename="../mainUI.ui" line="167"/> <source>up</source> - <translation type="unfinished"></translation> + <translation>omhoog</translation> </message> <message> <location filename="../mainUI.ui" line="183"/> <source>down</source> - <translation type="unfinished"></translation> + <translation>omlaag</translation> </message> <message> <location filename="../mainUI.ui" line="267"/> <source>Current Song</source> - <translation type="unfinished"></translation> + <translation>Huidig nummer</translation> </message> <message> <location filename="../mainUI.ui" line="303"/> <source>TITLE</source> - <translation type="unfinished"></translation> + <translation>TITEL</translation> </message> <message> <location filename="../mainUI.ui" line="327"/> <source>ARTIST</source> - <translation type="unfinished"></translation> + <translation>ARTIEST</translation> </message> <message> <location filename="../mainUI.ui" line="337"/> <source>ALBUM</source> - <translation type="unfinished"></translation> + <translation>ALBUM</translation> </message> <message> <location filename="../mainUI.ui" line="368"/> <source>Love this song</source> - <translation type="unfinished"></translation> + <translation>Houd van dit dit nummer</translation> </message> <message> <location filename="../mainUI.ui" line="384"/> <source>Tired of this song (will not play for a month)</source> - <translation type="unfinished"></translation> + <translation>Heb het even gehad met dit nummer (wordt gedurende een maand niet afgespeeld)</translation> </message> <message> <location filename="../mainUI.ui" line="397"/> <source>Ban this song (will never play again)</source> - <translation type="unfinished"></translation> + <translation>Verban dit nummer! (zal nooit meer worden afgespeeld)</translation> </message> <message> <location filename="../mainUI.ui" line="417"/> <source>View details about song (launches web browser)</source> - <translation type="unfinished"></translation> + <translation>Bekijk meer informatie over dit nummer (start je internet browser op)</translation> </message> <message> <location filename="../mainUI.ui" line="448"/> <source>Current Station</source> - <translation type="unfinished"></translation> + <translation>Huidig radiostation</translation> </message> <message> <location filename="../mainUI.ui" line="479"/> <source>Delete current station</source> - <translation type="unfinished"></translation> + <translation>Verwijder huidig radiostation</translation> </message> <message> <location filename="../mainUI.ui" line="482"/> <source>rm</source> - <translation type="unfinished"></translation> + <translation>rm</translation> </message> <message> <location filename="../mainUI.ui" line="492"/> <source>Create new station</source> - <translation type="unfinished"></translation> + <translation>Maak een nieuw station aan</translation> </message> <message> <location filename="../mainUI.ui" line="495"/> <source>add</source> - <translation type="unfinished"></translation> + <translation>voeg toe</translation> </message> <message> <location filename="../mainUI.ui" line="512"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>Voorkeuren</translation> </message> <message> <location filename="../mainUI.ui" line="521"/> <source>Pandora Account Login</source> - <translation type="unfinished"></translation> + <translation>Inloggen met uw Pandora Account</translation> </message> <message> <location filename="../mainUI.ui" line="527"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>E-mail</translation> </message> <message> <location filename="../mainUI.ui" line="537"/> <source>Password</source> - <translation type="unfinished"></translation> + <translation>Wachtwoord</translation> </message> <message> <location filename="../mainUI.ui" line="557"/> <source><a href=https://www.pandora.com/account/register>Need an account?</a></source> - <translation type="unfinished"></translation> + <translation><a href=https://www.pandora.com/account/register>Nog geen account?</a></translation> </message> <message> <location filename="../mainUI.ui" line="573"/> <source>Audio Quality</source> - <translation type="unfinished"></translation> + <translation>Geluidskwaliteit</translation> </message> <message> <location filename="../mainUI.ui" line="583"/> <source>Proxy URL</source> - <translation type="unfinished"></translation> + <translation>Proxy URL</translation> </message> <message> <location filename="../mainUI.ui" line="593"/> <source>Control Proxy URL</source> - <translation type="unfinished"></translation> + <translation>Controle Proxy URL</translation> </message> <message> <location filename="../mainUI.ui" line="618"/> <source>Apply Settings</source> - <translation type="unfinished"></translation> + <translation>Pas voorkeuren toe</translation> </message> <message> <location filename="../mainUI.ui" line="656"/> <source>Audio Driver</source> - <translation type="unfinished"></translation> + <translation>Geluidskaart</translation> </message> <message> <location filename="../mainUI.ui" line="681"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>Bestand</translation> </message> <message> <location filename="../mainUI.ui" line="688"/> <source>View</source> - <translation type="unfinished"></translation> + <translation>Weergave</translation> </message> <message> <location filename="../mainUI.ui" line="723"/> <source>Play</source> - <translation type="unfinished"></translation> + <translation>Speel af</translation> </message> <message> <location filename="../mainUI.ui" line="728"/> <source>Pause</source> - <translation type="unfinished"></translation> + <translation>Pauze</translation> </message> <message> <location filename="../mainUI.ui" line="733"/> <source>Stop</source> - <translation type="unfinished"></translation> + <translation>Stop</translation> </message> <message> <location filename="../mainUI.ui" line="738"/> <source>Next</source> - <translation type="unfinished"></translation> + <translation>Volgende</translation> </message> <message> <location filename="../mainUI.ui" line="743"/> <source>Back</source> - <translation type="unfinished"></translation> + <translation>Vorige</translation> </message> <message> <location filename="../mainUI.ui" line="748"/> <source>VolUp</source> - <translation type="unfinished"></translation> + <translation>Volume omhoog</translation> </message> <message> <location filename="../mainUI.ui" line="751"/> <source>Raise audio volume</source> - <translation type="unfinished"></translation> + <translation>Verhoog het geluidsvolume</translation> </message> <message> <location filename="../mainUI.ui" line="756"/> <source>VolDown</source> - <translation type="unfinished"></translation> + <translation>Volume omlaag</translation> </message> <message> <location filename="../mainUI.ui" line="759"/> <source>Lower audio volume</source> - <translation type="unfinished"></translation> + <translation>Verlaag het geluidsvolume</translation> </message> <message> <location filename="../mainUI.ui" line="764"/> <source>Close Application</source> - <translation type="unfinished"></translation> + <translation>Sluit de applicatie af</translation> </message> <message> <location filename="../mainUI.ui" line="767"/> <source>Ctrl+Q</source> - <translation type="unfinished"></translation> + <translation>Ctrl+Q</translation> </message> <message> <location filename="../mainUI.ui" line="781"/> <source>Close to tray when active</source> - <translation type="unfinished"></translation> + <translation>Breng naar terug naar het systeemvak wanneer actief</translation> </message> <message> <location filename="../mainUI.ui" line="786"/> <source>From current artist</source> - <translation type="unfinished"></translation> + <translation>Van de huidige artiest</translation> </message> <message> <location filename="../mainUI.ui" line="789"/> <source>Create station from current artist</source> - <translation type="unfinished"></translation> + <translation>Maak een station aan voor de huidige artiest</translation> </message> <message> <location filename="../mainUI.ui" line="794"/> <source>From current song</source> - <translation type="unfinished"></translation> + <translation>Van het huidige nummer</translation> </message> <message> <location filename="../mainUI.ui" line="797"/> <source>Create station from current song</source> - <translation type="unfinished"></translation> + <translation>Maak een station aan op basis van het huidige nummer</translation> </message> <message> <location filename="../mainUI.ui" line="808"/> <source>Show song notifications</source> - <translation type="unfinished"></translation> + <translation>Laat afspeelberichten zien</translation> </message> <message> <location filename="../mainUI.ui" line="813"/> <source>Search...</source> - <translation type="unfinished"></translation> + <translation>Zoeken...</translation> </message> <message> <location filename="../mainUI.ui" line="816"/> <source>Search for a new station</source> - <translation type="unfinished"></translation> + <translation>Zoek een nieuw station</translation> </message> <message> <location filename="../mainUI.ui" line="828"/> <location filename="../mainUI.cpp" line="276"/> <source>Pandora Radio</source> - <translation type="unfinished"></translation> + <translation></translation> </message> <message> <location filename="../mainUI.ui" line="831"/> <source>Stream from Pandora Radio</source> - <translation type="unfinished"></translation> + <translation>Stream van Pandora Radio</translation> </message> <message> <location filename="../mainUI.ui" line="839"/> <source>Local Files</source> - <translation type="unfinished"></translation> + <translation>Lokale bestanden</translation> </message> <message> <location filename="../mainUI.ui" line="842"/> <source>Play Local Files</source> - <translation type="unfinished"></translation> + <translation>Speel lokale bestanden af</translation> </message> <message> <location filename="../mainUI.cpp" line="105"/> <source>Please install the `pianobar` utility to enable this functionality</source> - <translation type="unfinished"></translation> + <translation>Installeer alstublieft de 'pianobar' toepassing om deze functionaliteit te kunnen gebruiken</translation> </message> <message> <location filename="../mainUI.cpp" line="109"/> <source>Stream music from the Pandora online radio service</source> - <translation type="unfinished"></translation> + <translation>Stream muziek vanaf de Pandora online radio service</translation> </message> <message> <location filename="../mainUI.cpp" line="122"/> <source>Low</source> - <translation type="unfinished"></translation> + <translation>Laag</translation> </message> <message> <location filename="../mainUI.cpp" line="123"/> <source>Medium</source> - <translation type="unfinished"></translation> + <translation>Gemiddeld</translation> </message> <message> <location filename="../mainUI.cpp" line="124"/> <source>High</source> - <translation type="unfinished"></translation> + <translation>Hoog</translation> </message> <message> <location filename="../mainUI.cpp" line="358"/> <source>Open Multimedia Files</source> - <translation type="unfinished"></translation> + <translation>Open Multimedia bestanden</translation> </message> <message> <location filename="../mainUI.cpp" line="406"/> <source>Now Playing:</source> - <translation type="unfinished"></translation> + <translation>Nu aan het afspelen:</translation> </message> <message> <location filename="../mainUI.cpp" line="471"/> @@ -321,37 +321,37 @@ <message> <location filename="../mainUI.cpp" line="488"/> <source>Media Loading...</source> - <translation type="unfinished"></translation> + <translation>Media aan het laden...</translation> </message> <message> <location filename="../mainUI.cpp" line="490"/> <source>Media Stalled...</source> - <translation type="unfinished"></translation> + <translation>Media loopt vast...</translation> </message> <message> <location filename="../mainUI.cpp" line="492"/> <source>Media Buffering...</source> - <translation type="unfinished"></translation> + <translation>Media aan het bufferen....</translation> </message> <message> <location filename="../mainUI.cpp" line="576"/> <source>Pandora: Create Station</source> - <translation type="unfinished"></translation> + <translation>Pandora: Maak een station aan</translation> </message> <message> <location filename="../mainUI.cpp" line="576"/> <source>Search Term</source> - <translation type="unfinished"></translation> + <translation>Zoekterm</translation> </message> <message> <location filename="../mainUI.cpp" line="654"/> <source>Pandora Question</source> - <translation type="unfinished"></translation> + <translation>Pandora vraag</translation> </message> <message> <location filename="../mainUI.cpp" line="659"/> <source>Pandora Error</source> - <translation type="unfinished"></translation> + <translation>Pandora foutmelding</translation> </message> </context> <context> @@ -359,7 +359,7 @@ <message> <location filename="../PianoBarProcess.cpp" line="358"/> <source>Could not find any matches. Please try a different search term</source> - <translation type="unfinished"></translation> + <translation>Kon geen resultaten vinden. Probeer alstublieft een andere zoekterm</translation> </message> </context> <context> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_pt_BR.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_pt_BR.ts index f60ce2a0..d30de8ba 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_pt_BR.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_pt_BR.ts @@ -7,7 +7,7 @@ <location filename="../mainUI.ui" line="14"/> <location filename="../mainUI.cpp" line="285"/> <source>Media Player</source> - <translation type="unfinished">Media Player</translation> + <translation>Media Player</translation> </message> <message> <location filename="../mainUI.ui" line="50"/> @@ -24,7 +24,7 @@ <message> <location filename="../mainUI.ui" line="105"/> <source>Playlist</source> - <translation type="unfinished">Playlist</translation> + <translation>Lista de reprodução</translation> </message> <message> <location filename="../mainUI.ui" line="167"/> @@ -74,82 +74,82 @@ <message> <location filename="../mainUI.ui" line="417"/> <source>View details about song (launches web browser)</source> - <translation type="unfinished"></translation> + <translation>Ver detalhes da música (abre o navegador web)</translation> </message> <message> <location filename="../mainUI.ui" line="448"/> <source>Current Station</source> - <translation type="unfinished"></translation> + <translation>Estação atual</translation> </message> <message> <location filename="../mainUI.ui" line="479"/> <source>Delete current station</source> - <translation type="unfinished"></translation> + <translation>Remover estação atual</translation> </message> <message> <location filename="../mainUI.ui" line="482"/> <source>rm</source> - <translation type="unfinished"></translation> + <translation>rm</translation> </message> <message> <location filename="../mainUI.ui" line="492"/> <source>Create new station</source> - <translation type="unfinished"></translation> + <translation>Criar nova estação</translation> </message> <message> <location filename="../mainUI.ui" line="495"/> <source>add</source> - <translation type="unfinished"></translation> + <translation>Add</translation> </message> <message> <location filename="../mainUI.ui" line="512"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>Configurações</translation> </message> <message> <location filename="../mainUI.ui" line="521"/> <source>Pandora Account Login</source> - <translation type="unfinished"></translation> + <translation>Login na conta Pandora</translation> </message> <message> <location filename="../mainUI.ui" line="527"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>E-mail</translation> </message> <message> <location filename="../mainUI.ui" line="537"/> <source>Password</source> - <translation type="unfinished"></translation> + <translation>Senha</translation> </message> <message> <location filename="../mainUI.ui" line="557"/> <source><a href=https://www.pandora.com/account/register>Need an account?</a></source> - <translation type="unfinished"></translation> + <translation><a href=https://www.pandora.com/account/register>Precisa de uma conta?</a></translation> </message> <message> <location filename="../mainUI.ui" line="573"/> <source>Audio Quality</source> - <translation type="unfinished"></translation> + <translation>Qualidade do áudio</translation> </message> <message> <location filename="../mainUI.ui" line="583"/> <source>Proxy URL</source> - <translation type="unfinished"></translation> + <translation>URL do proxy</translation> </message> <message> <location filename="../mainUI.ui" line="593"/> <source>Control Proxy URL</source> - <translation type="unfinished"></translation> + <translation>URL do Proxy de Controle</translation> </message> <message> <location filename="../mainUI.ui" line="618"/> <source>Apply Settings</source> - <translation type="unfinished"></translation> + <translation>Aplicar configurações</translation> </message> <message> <location filename="../mainUI.ui" line="656"/> <source>Audio Driver</source> - <translation type="unfinished"></translation> + <translation>Driver de áudio</translation> </message> <message> <location filename="../mainUI.ui" line="681"/> @@ -159,57 +159,57 @@ <message> <location filename="../mainUI.ui" line="688"/> <source>View</source> - <translation type="unfinished"></translation> + <translation>Ver</translation> </message> <message> <location filename="../mainUI.ui" line="723"/> <source>Play</source> - <translation type="unfinished"></translation> + <translation>Tocar</translation> </message> <message> <location filename="../mainUI.ui" line="728"/> <source>Pause</source> - <translation type="unfinished"></translation> + <translation>Pausar</translation> </message> <message> <location filename="../mainUI.ui" line="733"/> <source>Stop</source> - <translation type="unfinished"></translation> + <translation>Parar</translation> </message> <message> <location filename="../mainUI.ui" line="738"/> <source>Next</source> - <translation type="unfinished"></translation> + <translation>Avançar</translation> </message> <message> <location filename="../mainUI.ui" line="743"/> <source>Back</source> - <translation type="unfinished"></translation> + <translation>Voltar</translation> </message> <message> <location filename="../mainUI.ui" line="748"/> <source>VolUp</source> - <translation type="unfinished"></translation> + <translation>VolUp</translation> </message> <message> <location filename="../mainUI.ui" line="751"/> <source>Raise audio volume</source> - <translation type="unfinished"></translation> + <translation>Aumentar o volume do áudio</translation> </message> <message> <location filename="../mainUI.ui" line="756"/> <source>VolDown</source> - <translation type="unfinished"></translation> + <translation>VolDown</translation> </message> <message> <location filename="../mainUI.ui" line="759"/> <source>Lower audio volume</source> - <translation type="unfinished"></translation> + <translation>Diminuir o volume do áudio</translation> </message> <message> <location filename="../mainUI.ui" line="764"/> <source>Close Application</source> - <translation type="unfinished"></translation> + <translation>Fechar aplicação</translation> </message> <message> <location filename="../mainUI.ui" line="767"/> @@ -219,139 +219,140 @@ <message> <location filename="../mainUI.ui" line="781"/> <source>Close to tray when active</source> - <translation type="unfinished"></translation> + <translation>Fechar para a bandeja quando ativo</translation> </message> <message> <location filename="../mainUI.ui" line="786"/> <source>From current artist</source> - <translation type="unfinished"></translation> + <translation>Do artista atual</translation> </message> <message> <location filename="../mainUI.ui" line="789"/> <source>Create station from current artist</source> - <translation type="unfinished"></translation> + <translation>Criar estação do artista atual</translation> </message> <message> <location filename="../mainUI.ui" line="794"/> <source>From current song</source> - <translation type="unfinished"></translation> + <translation>Da música atual</translation> </message> <message> <location filename="../mainUI.ui" line="797"/> <source>Create station from current song</source> - <translation type="unfinished"></translation> + <translation>Criar uma estação da música atual</translation> </message> <message> <location filename="../mainUI.ui" line="808"/> <source>Show song notifications</source> - <translation type="unfinished"></translation> + <translation>Mostrar notificações de músicas</translation> </message> <message> <location filename="../mainUI.ui" line="813"/> <source>Search...</source> - <translation type="unfinished"></translation> + <translation>Procurar...</translation> </message> <message> <location filename="../mainUI.ui" line="816"/> <source>Search for a new station</source> - <translation type="unfinished"></translation> + <translation>Procurar uma nova estação</translation> </message> <message> <location filename="../mainUI.ui" line="828"/> <location filename="../mainUI.cpp" line="276"/> <source>Pandora Radio</source> - <translation type="unfinished"></translation> + <translation>Pandora Radio</translation> </message> <message> <location filename="../mainUI.ui" line="831"/> <source>Stream from Pandora Radio</source> - <translation type="unfinished"></translation> + <translation>Transmissão da Pandora Radio</translation> </message> <message> <location filename="../mainUI.ui" line="839"/> <source>Local Files</source> - <translation type="unfinished"></translation> + <translation>Arquivos locais</translation> </message> <message> <location filename="../mainUI.ui" line="842"/> <source>Play Local Files</source> - <translation type="unfinished"></translation> + <translation>Tocar arquivos locais</translation> </message> <message> <location filename="../mainUI.cpp" line="105"/> <source>Please install the `pianobar` utility to enable this functionality</source> - <translation type="unfinished"></translation> + <translation>Instale o utilitário `pianobar` para habilitar esta funcionalidade</translation> </message> <message> <location filename="../mainUI.cpp" line="109"/> <source>Stream music from the Pandora online radio service</source> - <translation type="unfinished"></translation> + <translation>Transmitir música do serviço de rádio on-line Pandora</translation> </message> <message> <location filename="../mainUI.cpp" line="122"/> <source>Low</source> - <translation type="unfinished"></translation> + <translation>Baixo</translation> </message> <message> <location filename="../mainUI.cpp" line="123"/> <source>Medium</source> - <translation type="unfinished"></translation> + <translation>Médio</translation> </message> <message> <location filename="../mainUI.cpp" line="124"/> <source>High</source> - <translation type="unfinished"></translation> + <translation>Alto</translation> </message> <message> <location filename="../mainUI.cpp" line="358"/> <source>Open Multimedia Files</source> - <translation type="unfinished"></translation> + <translation>Abrir arquivos multimídia</translation> </message> <message> <location filename="../mainUI.cpp" line="406"/> <source>Now Playing:</source> - <translation type="unfinished"></translation> + <translation>Tocando agora:</translation> </message> <message> <location filename="../mainUI.cpp" line="471"/> <source>[PLAYBACK ERROR] %1</source> - <translation type="unfinished"></translation> + <translation>[PLAYBACK ERROR] +%1</translation> </message> <message> <location filename="../mainUI.cpp" line="488"/> <source>Media Loading...</source> - <translation type="unfinished"></translation> + <translation>Carregando mídia...</translation> </message> <message> <location filename="../mainUI.cpp" line="490"/> <source>Media Stalled...</source> - <translation type="unfinished"></translation> + <translation>Mídia parada...</translation> </message> <message> <location filename="../mainUI.cpp" line="492"/> <source>Media Buffering...</source> - <translation type="unfinished"></translation> + <translation>Carregando mídia...</translation> </message> <message> <location filename="../mainUI.cpp" line="576"/> <source>Pandora: Create Station</source> - <translation type="unfinished"></translation> + <translation>Pandora: Criar estação</translation> </message> <message> <location filename="../mainUI.cpp" line="576"/> <source>Search Term</source> - <translation type="unfinished"></translation> + <translation>Procurar termo</translation> </message> <message> <location filename="../mainUI.cpp" line="654"/> <source>Pandora Question</source> - <translation type="unfinished"></translation> + <translation>Pergunta Pandora</translation> </message> <message> <location filename="../mainUI.cpp" line="659"/> <source>Pandora Error</source> - <translation type="unfinished"></translation> + <translation>Erro Pandora</translation> </message> </context> <context> @@ -359,7 +360,7 @@ <message> <location filename="../PianoBarProcess.cpp" line="358"/> <source>Could not find any matches. Please try a different search term</source> - <translation type="unfinished"></translation> + <translation>Não foi possível encontrar nenhum resultado. Experimente um termo de pesquisa diferente</translation> </message> </context> <context> @@ -367,67 +368,67 @@ <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="608"/> <source>Multimedia</source> - <translation type="unfinished"></translation> + <translation>Multimídia</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="609"/> <source>Development</source> - <translation type="unfinished"></translation> + <translation>Desenvolvimento</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="610"/> <source>Education</source> - <translation type="unfinished"></translation> + <translation>Educação</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="611"/> <source>Games</source> - <translation type="unfinished"></translation> + <translation>Jogos</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="612"/> <source>Graphics</source> - <translation type="unfinished"></translation> + <translation>Gráficos</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="613"/> <source>Network</source> - <translation type="unfinished"></translation> + <translation>Rede</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="614"/> <source>Office</source> - <translation type="unfinished"></translation> + <translation>Escritório</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="615"/> <source>Science</source> - <translation type="unfinished"></translation> + <translation>Ciência</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="616"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>Configurações</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="617"/> <source>System</source> - <translation type="unfinished"></translation> + <translation>Sistema</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="618"/> <source>Utility</source> - <translation type="unfinished"></translation> + <translation>Utilitários</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="619"/> <source>Wine</source> - <translation type="unfinished"></translation> + <translation>Wine</translation> </message> <message> <location filename="../../../core/libLumina/LuminaXDG.cpp" line="620"/> <source>Unsorted</source> - <translation type="unfinished"></translation> + <translation>Não classificado</translation> </message> </context> </TS> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_ru.ts b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_ru.ts index 0664622c..364ffb87 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_ru.ts +++ b/src-qt5/desktop-utils/lumina-mediaplayer/i18n/l-mediap_ru.ts @@ -114,12 +114,12 @@ <message> <location filename="../mainUI.ui" line="527"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>Эл.почта</translation> </message> <message> <location filename="../mainUI.ui" line="537"/> <source>Password</source> - <translation type="unfinished"></translation> + <translation>Пароль</translation> </message> <message> <location filename="../mainUI.ui" line="557"/> @@ -154,7 +154,7 @@ <message> <location filename="../mainUI.ui" line="681"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>Файл</translation> </message> <message> <location filename="../mainUI.ui" line="688"/> @@ -164,17 +164,17 @@ <message> <location filename="../mainUI.ui" line="723"/> <source>Play</source> - <translation type="unfinished"></translation> + <translation>Пуск</translation> </message> <message> <location filename="../mainUI.ui" line="728"/> <source>Pause</source> - <translation type="unfinished"></translation> + <translation>Пауза</translation> </message> <message> <location filename="../mainUI.ui" line="733"/> <source>Stop</source> - <translation type="unfinished"></translation> + <translation>Стоп</translation> </message> <message> <location filename="../mainUI.ui" line="738"/> @@ -189,7 +189,7 @@ <message> <location filename="../mainUI.ui" line="748"/> <source>VolUp</source> - <translation type="unfinished"></translation> + <translation>Громче</translation> </message> <message> <location filename="../mainUI.ui" line="751"/> @@ -199,7 +199,7 @@ <message> <location filename="../mainUI.ui" line="756"/> <source>VolDown</source> - <translation type="unfinished"></translation> + <translation>Тише</translation> </message> <message> <location filename="../mainUI.ui" line="759"/> @@ -310,7 +310,7 @@ <message> <location filename="../mainUI.cpp" line="406"/> <source>Now Playing:</source> - <translation type="unfinished"></translation> + <translation>Воспроизводится:</translation> </message> <message> <location filename="../mainUI.cpp" line="471"/> @@ -341,7 +341,7 @@ <message> <location filename="../mainUI.cpp" line="576"/> <source>Search Term</source> - <translation type="unfinished"></translation> + <translation>Что искать</translation> </message> <message> <location filename="../mainUI.cpp" line="654"/> @@ -359,7 +359,7 @@ <message> <location filename="../PianoBarProcess.cpp" line="358"/> <source>Could not find any matches. Please try a different search term</source> - <translation type="unfinished"></translation> + <translation>Совпадений не найдено. Попробуйте поискать что-то другое</translation> </message> </context> <context> diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/lumina-mediaplayer.pro b/src-qt5/desktop-utils/lumina-mediaplayer/lumina-mediaplayer.pro index c9ea6a5b..d7423485 100644 --- a/src-qt5/desktop-utils/lumina-mediaplayer/lumina-mediaplayer.pro +++ b/src-qt5/desktop-utils/lumina-mediaplayer/lumina-mediaplayer.pro @@ -90,7 +90,7 @@ TRANSLATIONS = i18n/l-mediap_af.ts \ i18n/l-mediap_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-mediaplayer.desktop desktop.path=$${L_SHAREDIR}/applications/ @@ -99,7 +99,7 @@ desktop.path=$${L_SHAREDIR}/applications/ #link.extra=ln -sf lumina-mediaplayer $(INSTALL_ROOT)$${L_BINDIR}/lplay manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-mediaplayer.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-mediaplayer.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-mediaplayer.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-mediaplayer.1.gz" INSTALLS += target desktop manpage diff --git a/src-qt5/desktop-utils/lumina-pdf/PresentationLabel.h b/src-qt5/desktop-utils/lumina-pdf/PresentationLabel.h new file mode 100644 index 00000000..c5b552a6 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/PresentationLabel.h @@ -0,0 +1,35 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// Simple subclass of QLabel to provide +// some overlay information as a presentation window +//=========================================== +#ifndef _PRESENTATION_LABEL_WIDGET_H +#define _PRESENTATION_LABEL_WIDGET_H + +#include <QLabel> +#include <QMouseEvent> +#include <QDebug> + +class PresentationLabel : public QLabel{ + Q_OBJECT + +signals: + void nextSlide(); + +public: + PresentationLabel() : QLabel(0, Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint){ + this->setContextMenuPolicy(Qt::CustomContextMenu); + } + +protected: + void mousePressEvent(QMouseEvent *ev){ + QLabel::mousePressEvent(ev); + if(ev->button()==Qt::LeftButton){ emit nextSlide(); } + } +}; + +#endif diff --git a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp new file mode 100644 index 00000000..be00e675 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp @@ -0,0 +1,279 @@ +#include "PrintWidget.h" + +PrintWidget::PrintWidget(QWidget *parent) : QGraphicsView(parent), scene(0), curPage(1), + viewMode(SinglePageView), zoomMode(FitInView), zoomFactor(1), initialized(false), fitting(true) { + + this->setMouseTracking(true); + QList<QWidget*> children = this->findChildren<QWidget*>("",Qt::FindChildrenRecursively); + for(int i=0; i<children.length(); i++){ + children[i]->setContextMenuPolicy(Qt::CustomContextMenu); + connect(children[i], SIGNAL(customContextMenuRequested(const QPoint&)), this, SIGNAL(customContextMenuRequested(const QPoint&)) ); + } + this->setInteractive(false); + this->setDragMode(QGraphicsView::ScrollHandDrag); + this->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); + this->setFocusPolicy(Qt::NoFocus); + QObject::connect(this->verticalScrollBar(), SIGNAL(valueChanged(int)), + this, SLOT(updateCurrentPage())); + QObject::connect(this, SIGNAL(resized()), this, SLOT(fit())); + + scene = new QGraphicsScene(this); + scene->setBackgroundBrush(Qt::gray); + this->setScene(scene); + + /*QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(this);*/ +} + +PrintWidget::~PrintWidget() { + //delete scene; + //delete items in pages(?) +} + +//Public Slots + +void PrintWidget::fitView() { + setZoomMode(FitInView); +} + +void PrintWidget::fitToWidth() { + setZoomMode(FitToWidth); +} + +void PrintWidget::setZoomMode(ZoomMode mode) { + zoomMode = mode; + fitting = true; + fit(true); +} + +void PrintWidget::setAllPagesViewMode() { + setViewMode(AllPagesView); +} + +void PrintWidget::setSinglePageViewMode() { + setViewMode(SinglePageView); +} + +void PrintWidget::setFacingPagesViewMode() { + setViewMode(FacingPagesView); +} + +void PrintWidget::setViewMode(ViewMode mode) { + viewMode = mode; + layoutPages(); + if (viewMode == AllPagesView) { + this->fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio); + fitting = false; + zoomMode = CustomZoom; + //zoomFactor = this->transform().m11() * (double(printer->logicalDpiY()) / logicalDpiY()); + } else { + fitting = true; + fit(); + } +} + +void PrintWidget::zoomIn(double factor) { + fitting = false; + zoomMode = CustomZoom; + zoomFactor *= factor; + this->scale(factor, factor); +} + +void PrintWidget::zoomOut(double factor) { + fitting = false; + zoomMode = CustomZoom; + zoomFactor *= factor; + this->scale(1/factor, 1/factor); +} + +void PrintWidget::updatePreview() { + initialized = true; + generatePreview(); + this->updateGeometry(); +} + +void PrintWidget::setVisible(bool visible) { + if(visible and !initialized) + updatePreview(); + QGraphicsView::setVisible(visible); +} + +void PrintWidget::setCurrentPage(int pageNumber) { + if(pageNumber < 1 || pageNumber > pages.count()) + return; + + int lastPage = curPage; + curPage = pageNumber; + + if (lastPage != curPage && lastPage > 0 && lastPage <= pages.count()) { + if (zoomMode != FitInView) { + QScrollBar *hsc = this->horizontalScrollBar(); + QScrollBar *vsc = this->verticalScrollBar(); + QPointF pt = this->transform().map(pages.at(curPage-1)->pos()); + vsc->setValue(int(pt.y()) - 10); + hsc->setValue(int(pt.x()) - 10); + } else { + this->centerOn(pages.at(curPage-1)); + } + } +} + +void PrintWidget::highlightText(int pageNum, QRectF textBox) { + PageItem *item = static_cast<PageItem*>(pages[pageNum]); + QPainter painter(this); + painter.fillRect(textBox, QColor(255, 255, 177, 128)); +} + +//Private functions + +void PrintWidget::generatePreview() { + populateScene(); // i.e. setPreviewPrintedPictures() e.l. + layoutPages(); + curPage = qBound(1, curPage, pages.count()); + if (fitting) + fit(); +} + +void PrintWidget::layoutPages() { + int numPages = pages.count(); + if (numPages < 1) + return; + + int numPagePlaces = numPages; + int cols = 1; // singleMode and default + if (viewMode == AllPagesView) { + cols = ((pictures->value(0)).width() > (pictures->value(0)).height()) ? qFloor(qSqrt(numPages)) : qCeil(qSqrt(numPages)); + cols += cols % 2; // Nicer with an even number of cols + } else if (viewMode == FacingPagesView) { + cols = 2; + numPagePlaces += 1; + } + int rows = qCeil(double(numPagePlaces) / cols); + + double itemWidth = pages.at(0)->boundingRect().width(); + double itemHeight = pages.at(0)->boundingRect().height(); + int pageNum = 1; for (int i = 0; i < rows && pageNum <= numPages; i++) { + for (int j = 0; j < cols && pageNum <= numPages; j++) { + if (!i && !j && viewMode == FacingPagesView) { + continue; + } else { + pages.at(pageNum-1)->setPos(QPointF(j*itemWidth, i*itemHeight)); + pageNum++; + } + } + } + scene->setSceneRect(scene->itemsBoundingRect()); +} + +void PrintWidget::populateScene() +{ + for (int i = 0; i < pages.size(); i++) + scene->removeItem(pages.at(i)); + qDeleteAll(pages); + pages.clear(); + + int numPages = pictures->count(); + //Replace from loadingHash resolution + QSize paperSize = pictures->value(0).size(); + qDebug() << "Image paperSize" << paperSize; + + for (int i = 0; i < numPages; i++) { + PageItem* item = new PageItem(i+1, (*pictures)[i], paperSize); + scene->addItem(item); + pages.append(item); + } +} + +//Private Slots +void PrintWidget::updateCurrentPage() { + if (viewMode == AllPagesView) + return; + + int newPage = calcCurrentPage(); + if (newPage != curPage) { + curPage = newPage; + } +} + +int PrintWidget::calcCurrentPage() { + int maxArea = 0; + int newPage = curPage; + QRect viewRect = this->viewport()->rect(); + QList<QGraphicsItem*> items = this->items(viewRect); + for (int i=0; i<items.size(); ++i) { + PageItem* pg = static_cast<PageItem*>(items.at(i)); + QRect overlap = this->mapFromScene(pg->sceneBoundingRect()).boundingRect() & viewRect; + int area = overlap.width() * overlap.height(); + if (area > maxArea) { + maxArea = area; + newPage = pg->pageNumber(); + } else if (area == maxArea && pg->pageNumber() < newPage) { + newPage = pg->pageNumber(); + } + } + return newPage; +} + +void PrintWidget::fit(bool doFitting) { + if (curPage < 1 || curPage > pages.count()) + return; + if (!doFitting && !fitting) + return; + + if (doFitting && fitting) { + QRect viewRect = this->viewport()->rect(); + if (zoomMode == FitInView) { + QList<QGraphicsItem*> containedItems = this->items(viewRect, Qt::ContainsItemBoundingRect); + foreach(QGraphicsItem* item, containedItems) { + PageItem* pg = static_cast<PageItem*>(item); + if (pg->pageNumber() == curPage) + return; + } + } + + int newPage = calcCurrentPage(); + if (newPage != curPage) + curPage = newPage; + } + + QRectF target = pages.at(curPage-1)->sceneBoundingRect(); + if (viewMode == FacingPagesView) { + if (curPage % 2) + target.setLeft(target.left() - target.width()); + else + target.setRight(target.right() + target.width()); + } else if (viewMode == AllPagesView) { + target = scene->itemsBoundingRect(); + } + + if (zoomMode == FitToWidth) { + QTransform t; + qreal scale = this->viewport()->width() / target.width(); + t.scale(scale, scale); + this->setTransform(t); + if (doFitting && fitting) { + QRectF viewSceneRect = this->viewportTransform().mapRect(this->viewport()->rect()); + viewSceneRect.moveTop(target.top()); + this->ensureVisible(viewSceneRect); // Nah... + } + } else { + this->fitInView(target, Qt::KeepAspectRatio); + if (zoomMode == FitInView) { + int step = qRound(this->matrix().mapRect(target).height()); + this->verticalScrollBar()->setSingleStep(step); + this->verticalScrollBar()->setPageStep(step); + } + } + + //zoomFactor = this->transform().m11() * (float(printer->logicalDpiY()) / this->logicalDpiY()); +} + +void PrintWidget::setPictures(QHash<int, QImage> *hash) { + pictures = hash; +} + +void PrintWidget::setOrientation(QPageLayout::Orientation ori) { + this->orientation = ori; +} diff --git a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h new file mode 100644 index 00000000..62543e45 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h @@ -0,0 +1,164 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// Simple subclass of QPrintPreviewWidget to provide +// notification when a context menu is requested +//=========================================== +#ifndef _PRINT_GRAPHICS_H +#define _PRINT_GRAPHICS_H + +#include <QMouseEvent> +#include <QDebug> +#include <QGraphicsView> +#include <QGraphicsItem> +#include <QBoxLayout> +#include <QScrollBar> +#include <QStyleOptionGraphicsItem> +#include <QtMath> +#include <QPageLayout> + +namespace { +class PageItem : public QGraphicsItem +{ +public: + PageItem(int _pageNum, const QImage _pagePicture, QSize _paperSize) + : pageNum(_pageNum), pagePicture(_pagePicture), + paperSize(_paperSize) + { + brect = QRectF(QPointF(-25, -25), + QSizeF(paperSize)+QSizeF(50, 50)); + setCacheMode(DeviceCoordinateCache); + } + + QRectF boundingRect() const Q_DECL_OVERRIDE + { return brect; } + + inline int pageNumber() const + { return pageNum; } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) Q_DECL_OVERRIDE; + +private: + int pageNum; + const QImage pagePicture; + QSize paperSize; + QRectF brect; +}; + +void PageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(widget); + QRectF paperRect(0,0, paperSize.width(), paperSize.height()); + + // Draw shadow + painter->setClipRect(option->exposedRect); + qreal shWidth = paperRect.width()/100; + QRectF rshadow(paperRect.topRight() + QPointF(0, shWidth), + paperRect.bottomRight() + QPointF(shWidth, 0)); + QLinearGradient rgrad(rshadow.topLeft(), rshadow.topRight()); + rgrad.setColorAt(0.0, QColor(0,0,0,255)); + rgrad.setColorAt(1.0, QColor(0,0,0,0)); + painter->fillRect(rshadow, QBrush(rgrad)); + QRectF bshadow(paperRect.bottomLeft() + QPointF(shWidth, 0), + paperRect.bottomRight() + QPointF(0, shWidth)); + QLinearGradient bgrad(bshadow.topLeft(), bshadow.bottomLeft()); + bgrad.setColorAt(0.0, QColor(0,0,0,255)); + bgrad.setColorAt(1.0, QColor(0,0,0,0)); + painter->fillRect(bshadow, QBrush(bgrad)); + QRectF cshadow(paperRect.bottomRight(), + paperRect.bottomRight() + QPointF(shWidth, shWidth)); + QRadialGradient cgrad(cshadow.topLeft(), shWidth, cshadow.topLeft()); + cgrad.setColorAt(0.0, QColor(0,0,0,255)); + cgrad.setColorAt(1.0, QColor(0,0,0,0)); + painter->fillRect(cshadow, QBrush(cgrad)); + + painter->setClipRect(paperRect & option->exposedRect); + painter->fillRect(paperRect, Qt::white); + if (pagePicture.isNull()){ + qDebug() << "NULL"; + return; + } + painter->drawImage(QPoint(0,0), pagePicture); +} +} + +class PrintWidget : public QGraphicsView +{ + Q_OBJECT +public: + PrintWidget(QWidget *parent = 0); + ~PrintWidget(); + enum ViewMode { + SinglePageView, + FacingPagesView, + AllPagesView + }; + + enum ZoomMode { + CustomZoom, + FitToWidth, + FitInView + }; + + double getZoomFactor() const { return this->zoomFactor; }; + ZoomMode getZoomMode() const { return this->zoomMode; }; + int currentPage() const { return curPage; }; + void setPictures(QHash<int, QImage>*); + +signals: + void resized(); + void customContextMenuRequested(const QPoint&); +public slots: + void zoomIn(double factor=1.2); + void zoomOut(double factor=1.2); + void setCurrentPage(int); + void setVisible(bool) Q_DECL_OVERRIDE; + void setOrientation(QPageLayout::Orientation); + void highlightText(int, QRectF); + + void updatePreview(); + void fitView(); + void fitToWidth(); + void setAllPagesViewMode(); + void setSinglePageViewMode(); + void setFacingPagesViewMode(); + +private slots: + void updateCurrentPage(); + int calcCurrentPage(); + void fit(bool doFitting=false); +protected: + void resizeEvent(QResizeEvent* e) Q_DECL_OVERRIDE { + /*{ + const QSignalBlocker blocker(verticalScrollBar()); // Don't change page, QTBUG-14517 + QGraphicsView::resizeEvent(e); + }*/ + QGraphicsView::resizeEvent(e); + emit resized(); + } + + void showEvent(QShowEvent* e) Q_DECL_OVERRIDE { + QGraphicsView::showEvent(e); + emit resized(); + } +private: + void generatePreview(); + void layoutPages(); + void populateScene(); + void setViewMode(ViewMode); + void setZoomMode(ZoomMode); + QGraphicsScene *scene; + + int curPage; + ViewMode viewMode; + ZoomMode zoomMode; + QPageLayout::Orientation orientation; + double zoomFactor; + bool initialized, fitting; + QList<QGraphicsItem*> pages; + QHash<int, QImage> *pictures; +}; +#endif diff --git a/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro b/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro index e17e59c5..8ee67d06 100644 --- a/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro +++ b/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro @@ -18,14 +18,19 @@ include(../../core/libLumina/LuminaXDG.pri) message("Qt Modules Needed: $${QT}") SOURCES += main.cpp \ - mainUI.cpp + mainUI.cpp \ + propDialog.cpp \ + PrintWidget.cpp -HEADERS += mainUI.h +HEADERS += mainUI.h \ + PrintWidget.h \ + PresentationLabel.h \ + PropDialog.h -FORMS += mainUI.ui +FORMS += mainUI.ui \ + propDialog.ui LIBS += -lpoppler-qt5 -INCLUDEPATH+= $${L_INCLUDEDIR}/poppler/qt5 TRANSLATIONS = i18n/l-pdf_af.ts \ i18n/l-pdf_ar.ts \ @@ -95,7 +100,7 @@ TRANSLATIONS = i18n/l-pdf_af.ts \ i18n/l-pdf_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-pdf.desktop desktop.path=$${L_SHAREDIR}/applications/ diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp index 7a310e85..57afbfe1 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp @@ -16,21 +16,24 @@ #include <QApplication> #include <QScreen> #include <QTimer> +#include <iostream> #include <QtConcurrent> #include <LuminaXDG.h> +#include "PrintWidget.h" MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ ui->setupUi(this); - presentationLabel = 0; this->setWindowTitle(tr("Lumina PDF Viewer")); this->setWindowIcon( LXDG::findIcon("application-pdf","unknown")); - CurrentPage = 0; + presentationLabel = 0; + CurrentPage = 1; lastdir = QDir::homePath(); - Printer = new QPrinter(); //Create the interface widgets - WIDGET = new QPrintPreviewWidget(Printer,this); + WIDGET = new PrintWidget(this); + WIDGET->setVisible(false); + WIDGET->setContextMenuPolicy(Qt::CustomContextMenu); clockTimer = new QTimer(this); clockTimer->setInterval(1000); //1-second updates to clock connect(clockTimer, SIGNAL(timeout()), this, SLOT(updateClock()) ); @@ -39,15 +42,22 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ label_clock->setAlignment(Qt::AlignCenter ); label_clock->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); label_clock->setStyleSheet("QLabel{color: palette(highlight-text); background-color: palette(highlight); border-radius: 5px; }"); + //Context Menu + contextMenu = new QMenu(this); + connect(contextMenu, SIGNAL(aboutToShow()), this, SLOT(updateContextMenu())); //Now put the widgets into the UI + ui->bookmarksFrame->setParent(WIDGET); + ui->findGroup->setParent(WIDGET); + qDebug() << "Setting central widget"; this->setCentralWidget(WIDGET); - connect(WIDGET, SIGNAL(paintRequested(QPrinter*)), this, SLOT(paintOnWidget(QPrinter*)) ); + WIDGET->setContextMenuPolicy(Qt::CustomContextMenu); + connect(WIDGET, SIGNAL(customContextMenuRequested(const QPoint&)),this, SLOT(showContextMenu(const QPoint&)) ); DOC = 0; connect(this, SIGNAL(PageLoaded(int)), this, SLOT(slotPageLoaded(int)) ); PrintDLG = new QPrintDialog(this); connect(PrintDLG, SIGNAL(accepted(QPrinter*)), this, SLOT(paintToPrinter(QPrinter*)) ); - connect(ui->menuStart_Presentation, SIGNAL(triggered(QAction*)), this, SLOT(slotStartPresentation(QAction*)) ); + //connect(ui->menuStart_Presentation, SIGNAL(triggered(QAction*)), this, SLOT(slotStartPresentation(QAction*)) ); //Create the other interface widgets progress = new QProgressBar(this); @@ -57,6 +67,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ progAct->setVisible(false); clockAct = ui->toolBar->addWidget(label_clock); clockAct->setVisible(false); + //Put the various actions into logical groups QActionGroup *tmp = new QActionGroup(this); tmp->setExclusive(true); @@ -71,15 +82,66 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ tmp->addAction(ui->actionAll_Pages); ui->actionSingle_Page->setChecked(true); + qDebug() << "Starting connections"; + //Connect up the buttons connect(ui->actionClose, SIGNAL(triggered()), this, SLOT(close()) ); connect(ui->actionPrint, SIGNAL(triggered()), PrintDLG, SLOT(open()) ); connect(ui->actionFit_Width, SIGNAL(triggered()), WIDGET, SLOT(fitToWidth()) ); - connect(ui->actionFit_Page, SIGNAL(triggered()), WIDGET, SLOT(fitInView()) ); + connect(ui->actionFit_Page, SIGNAL(triggered()), WIDGET, SLOT(fitView()) ); connect(ui->actionOpen_PDF, SIGNAL(triggered()), this, SLOT(OpenNewFile()) ); connect(ui->actionSingle_Page, SIGNAL(triggered()), WIDGET, SLOT(setSinglePageViewMode()) ); connect(ui->actionDual_Pages, SIGNAL(triggered()), WIDGET, SLOT(setFacingPagesViewMode()) ); connect(ui->actionAll_Pages, SIGNAL(triggered()), WIDGET, SLOT(setAllPagesViewMode()) ); + //connect(ui->actionScroll_Mode, &QAction::triggered, this, [&] { this->setScroll(true); }); + //connect(ui->actionSelect_Mode, &QAction::triggered, this, [&] { this->setScroll(false); }); + connect(ui->actionZoom_In, &QAction::triggered, WIDGET, [&] { WIDGET->zoomIn(1.2); }); + connect(ui->actionZoom_Out, &QAction::triggered, WIDGET, [&] { WIDGET->zoomOut(1.2); }); + connect(ui->actionRotate_Counterclockwise, &QAction::triggered, this, [&] { this->rotate(true); }); + connect(ui->actionRotate_Clockwise, &QAction::triggered, this, [&] { this->rotate(false); }); + connect(ui->actionZoom_In_2, &QAction::triggered, WIDGET, [&] { WIDGET->zoomIn(1.2); }); + connect(ui->actionZoom_Out_2, &QAction::triggered, WIDGET, [&] { WIDGET->zoomOut(1.2); }); + connect(ui->actionFirst_Page, SIGNAL(triggered()), this, SLOT(firstPage()) ); + connect(ui->actionPrevious_Page, SIGNAL(triggered()), this, SLOT(prevPage()) ); + connect(ui->actionNext_Page, SIGNAL(triggered()), this, SLOT(nextPage()) ); + connect(ui->actionLast_Page, SIGNAL(triggered()), this, SLOT(lastPage()) ); + connect(ui->actionProperties, SIGNAL(triggered()), this, SLOT(showInformation())); + connect(ui->actionFind, SIGNAL(triggered()), this, SLOT(enableFind())); + connect(ui->actionFind_Next, &QAction::triggered, this, + [&] { find(ui->textEdit->text(), true); }); + connect(ui->actionFind_Previous, &QAction::triggered, this, + [&] { find(ui->textEdit->text(), false); }); + connect(ui->findNextB, &QPushButton::clicked, this, + [&] { find(ui->textEdit->text(), true); }); + connect(ui->findPrevB, &QPushButton::clicked, this, + [&] { find(ui->textEdit->text(), false); }); + connect(ui->matchCase, &QPushButton::clicked, this, + [&] (bool value) { this->matchCase = value; }); + connect(ui->closeFind, &QPushButton::clicked, this, + [&] { ui->findGroup->setVisible(false); this->setFocus(); }); + connect(ui->actionClearHighlights, &QAction::triggered, WIDGET, + [&] { WIDGET->updatePreview(); }); + connect(ui->actionBookmarks, SIGNAL(triggered()), this, SLOT(showBookmarks())); + + qDebug() << "Finished connctions"; + + //int curP = WIDGET->currentPage()-1; //currentPage reports pages starting at 1 + //int lastP = numPages-1; + ui->actionFirst_Page->setText(tr("First Page")); + ui->actionPrevious_Page->setText(tr("Previous Page")); + ui->actionNext_Page->setText(tr("Next Page")); + ui->actionLast_Page->setText(tr("Last Page")); + /*ui->actionFirst_Page->setEnabled(curP!=0); + ui->actionPrevious_Page->setEnabled(curP>0); + ui->actionNext_Page->setEnabled(curP<lastP); + ui->actionLast_Page->setEnabled(curP!=lastP);*/ + + ui->actionStart_Here->setText(tr("Start Presentation (current slide)")); + connect(ui->actionStart_Here, SIGNAL(triggered()), this, SLOT(startPresentationHere()) ); + ui->actionStart_Begin->setText(tr("Start Presentation (at beginning)")); + connect(ui->actionStart_Begin, SIGNAL(triggered()), this, SLOT(startPresentationBeginning()) ); + ui->actionStop_Presentation->setText(tr("Stop Presentation")); + connect(ui->actionStop_Presentation, SIGNAL(triggered()), this, SLOT(closePresentation()) ); //Setup all the icons ui->actionPrint->setIcon( LXDG::findIcon("document-print","")); @@ -90,10 +152,41 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ ui->actionSingle_Page->setIcon(LXDG::findIcon("format-view-agenda","")); ui->actionDual_Pages->setIcon(LXDG::findIcon("format-view-grid-small","")); ui->actionAll_Pages->setIcon(LXDG::findIcon("format-view-grid-large","")); + ui->actionScroll_Mode->setIcon(LXDG::findIcon("cursor-pointer","")); + ui->actionSelect_Mode->setIcon(LXDG::findIcon("cursor-text","")); + ui->actionZoom_In->setIcon(LXDG::findIcon("zoom-in","")); + ui->actionZoom_Out->setIcon(LXDG::findIcon("zoom-out","")); + ui->actionZoom_In_2->setIcon(LXDG::findIcon("zoom-in","")); + ui->actionZoom_Out_2->setIcon(LXDG::findIcon("zoom-out","")); + ui->actionRotate_Counterclockwise->setIcon(LXDG::findIcon("object-rotate-left","")); + ui->actionRotate_Clockwise->setIcon(LXDG::findIcon("object-rotate-right","")); + ui->actionFirst_Page->setIcon(LXDG::findIcon("go-first","")); + ui->actionPrevious_Page->setIcon(LXDG::findIcon("go-previous","")); + ui->actionNext_Page->setIcon(LXDG::findIcon("go-next","")); + ui->actionLast_Page->setIcon(LXDG::findIcon("go-last","")); + ui->actionStart_Here->setIcon(LXDG::findIcon("media-playback-start-circled","")); + ui->actionStart_Begin->setIcon(LXDG::findIcon("presentation-play","")); + ui->actionStop_Presentation->setIcon(LXDG::findIcon("media-playback-stop-circled","")); + ui->actionBookmarks->setIcon(LXDG::findIcon("bookmark-new","")); + ui->actionFind->setIcon(LXDG::findIcon("edit-find","")); + ui->actionFind_Next->setIcon(LXDG::findIcon("edit-find-next","")); + ui->actionFind_Previous->setIcon(LXDG::findIcon("edit-find-prev","")); + ui->actionProperties->setIcon(LXDG::findIcon("dialog-information","")); + ui->actionSettings->setIcon(LXDG::findIcon("document-properties","")); + ui->findNextB->setIcon(LXDG::findIcon("go-down-search")); + ui->findPrevB->setIcon(LXDG::findIcon("go-up-search")); + ui->matchCase->setIcon(LXDG::findIcon("format-text-italic")); + ui->closeFind->setIcon(LXDG::findIcon("dialog-close")); + + qDebug() << "Finished setting icons"; //Now set the default state of the menu's and actions - ui->menuStart_Presentation->setEnabled(false); ui->actionStop_Presentation->setEnabled(false); + ui->actionStart_Here->setEnabled(false); + ui->actionStart_Begin->setEnabled(false); + + ui->findGroup->setVisible(false); + ui->bookmarksFrame->setVisible(false); } MainUI::~MainUI(){ @@ -101,8 +194,8 @@ MainUI::~MainUI(){ } void MainUI::loadFile(QString path){ - if(!QFile::exists(path) || path.isEmpty() ){ return; } + Poppler::Document *TDOC = Poppler::Document::load(path); if(TDOC==0){ qDebug() << "Could not open file:" << path; @@ -116,44 +209,56 @@ void MainUI::loadFile(QString path){ } if(TDOC->isLocked()){ return; } //Cancelled - still locked } + //qpdf.processFile(path.toLatin1().data(), pass.toLatin1().data()); if(DOC!=0){ //Clear out the old document first delete DOC; DOC=0; } - loadingHash.clear(); //clear out this hash + //loadingHash.clear(); //clear out this hash numPages = -1; DOC = TDOC; //Save this for later qDebug() << "Opening File:" << path; - this->setWindowTitle(DOC->title()); + this->setWindowTitle(TDOC->title()); if(this->windowTitle().isEmpty()){ this->setWindowTitle(path.section("/",-1)); } //Setup the Document + //QVector<QPDFObjectHandle> pages = (QVector<QPDFObjectHandle>)pdf.getAllPages(); + //QPDFObjectHandle page = pages.at(0); Poppler::Page *PAGE = DOC->page(0); if(PAGE!=0){ lastdir = path.section("/",0,-2); //save this for later - Printer->setPageSize( QPageSize(PAGE->pageSize(), QPageSize::Point) ); - Printer->setPageMargins(QMarginsF(0,0,0,0), QPageLayout::Point); switch(PAGE->orientation()){ - case Poppler::Page::Landscape: - Printer->setOrientation(QPrinter::Landscape); break; - default: - Printer->setOrientation(QPrinter::Portrait); + case Poppler::Page::Landscape: + WIDGET->setOrientation(QPageLayout::Landscape); break; + default: + WIDGET->setOrientation(QPageLayout::Portrait); } delete PAGE; - //qDebug() << " - Document Setup : start loading pages now"; - QTimer::singleShot(10, WIDGET, SLOT(updatePreview())); //start loading the file preview + qDebug() << " - Document Setup : start loading pages now"; + startLoadingPages(); + //QTimer::singleShot(10, WIDGET, SLOT(updatePreview())); //start loading the file preview } } void MainUI::loadPage(int num, Poppler::Document *doc, MainUI *obj, QSize dpi, QSizeF page){ + //PERFORMANCE NOTES: + // Using Poppler to scale the image (adjust dpi value) helps a bit but you take a large CPU loading hit (and still quite a lot of pixelization) + // Using Qt to scale the image (adjust page value) smooths out the image quite a bit without a lot of performance loss (but cannot scale up without pixelization) + // The best approach seams to be to increase the DPI a bit, but match that with the same scaling on the page size (smoothing) + //qDebug() << " - Render Page:" << num; Poppler::Page *PAGE = doc->page(num); if(PAGE!=0){ - //qDebug() << "DPI:" << 4*dpi; - loadingHash.insert(num, PAGE->renderToImage(2.5*dpi.width(), 2.5*dpi.height()).scaled(2*page.width(), 2*page.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) ); + //qDebug() << "DPI:" << dpi << "Size:" << page << "Page Size (pt):" << PAGE->pageSize(); + float scalefactor = (dpi.width()/72.0); //How different the screen DPI compares to standard page DPI + //qDebug() << "Scale Factor:" << scalefactor; + QImage raw = PAGE->renderToImage((scalefactor+0.2)*dpi.width(), (scalefactor+0.2)*dpi.height()); //make the raw image a tiny bit larger than the end result + //qDebug() << " - Raw Image Size:" << raw.size(); + loadingHash.insert(num, raw.scaled(scalefactor*page.width(), scalefactor*page.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation) ); + raw = QImage(); //clear it /* QList<Annotation*> anno = PAGE->annotations(Annotations::AText ); QStringList annoS; @@ -212,16 +317,20 @@ void MainUI::startPresentation(bool atStart){ //Now create the full-screen window on the selected screen if(presentationLabel == 0){ //Create the label and any special flags for it - presentationLabel = new QLabel(0, Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + presentationLabel = new PresentationLabel(); presentationLabel->setStyleSheet("background-color: black;"); presentationLabel->setAlignment(Qt::AlignCenter); + presentationLabel->setContextMenuPolicy(Qt::CustomContextMenu); + connect(presentationLabel, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&)) ); + connect(presentationLabel, SIGNAL(nextSlide()), this, SLOT(nextPage()) ); } //Now put the label in the proper location presentationLabel->setGeometry(screen->geometry()); presentationLabel->showFullScreen(); ui->actionStop_Presentation->setEnabled(true); - ui->menuStart_Presentation->setEnabled(false); + ui->actionStart_Here->setEnabled(false); + ui->actionStart_Begin->setEnabled(false); updateClock(); clockAct->setVisible(true); clockTimer->start(); @@ -238,7 +347,7 @@ void MainUI::ShowPage(int page){ endPresentation(); return; //invalid - no document loaded or invalid page specified } - WIDGET->setCurrentPage(page+1); //page numbers start at 1 for this widget + WIDGET->setCurrentPage(page); //page numbers start at 1 for this widget //Stop here if no presentation currently running if(presentationLabel == 0 || !presentationLabel->isVisible()){ return; } CurrentPage = page; @@ -261,57 +370,58 @@ void MainUI::endPresentation(){ if(presentationLabel==0 || !presentationLabel->isVisible()){ return; } //not in presentation mode presentationLabel->hide(); //just hide this (no need to re-create the label for future presentations) ui->actionStop_Presentation->setEnabled(false); - ui->menuStart_Presentation->setEnabled(true); + ui->actionStart_Here->setEnabled(true); + ui->actionStart_Begin->setEnabled(true); clockTimer->stop(); clockAct->setVisible(false); this->releaseKeyboard(); } -void MainUI::startLoadingPages(QPrinter *printer){ +void MainUI::startLoadingPages(){ if(numPages>0){ return; } //currently loaded[ing] - //qDebug() << " - Start Loading Pages"; + qDebug() << " - Start Loading Pages"; numPages = DOC->numPages(); //qDebug() << "numPages:" << numPages; progress->setRange(0,numPages); progress->setValue(0); progAct->setVisible(true); - QRectF pageSize = printer->pageRect(QPrinter::DevicePixel); - QSize DPI(printer->resolution(),printer->resolution()); + QSizeF pageSize = DOC->page(0)->pageSizeF()*2; + //QSize DPI(loadingHash[0]->resolution(),loadingHash[0]->resolution()); + QSize DPI(76,76); + /*qDebug() << "Screen Resolutions:"; + QList<QScreen*> screens = QApplication::screens(); + for(int i=0; i<screens.length(); i++){ + qDebug() << screens[i]->name() << screens[i]->logicalDotsPerInchX() << screens[i]->logicalDotsPerInchY(); + }*/ + qDebug() << "Poppler pageSize: " << pageSize; for(int i=0; i<numPages; i++){ //qDebug() << " - Kickoff page load:" << i; - QtConcurrent::run(this, &MainUI::loadPage, i, DOC, this, DPI, pageSize.size() ); + QtConcurrent::run(this, &MainUI::loadPage, i, DOC, this, DPI, pageSize); } } void MainUI::slotPageLoaded(int page){ + Q_UNUSED(page); //qDebug() << "Page Loaded:" << page; int finished = loadingHash.keys().length(); if(finished == numPages){ progAct->setVisible(false); - QTimer::singleShot(0, WIDGET, SLOT(updatePreview())); + qDebug() << "Setting Pictures"; + WIDGET->setPictures(&loadingHash); + WIDGET->setVisible(true); + //QTimer::singleShot(10, WIDGET, SLOT(updatePreview())); + //qDebug() << "Updating"; ui->actionStop_Presentation->setEnabled(false); - ui->menuStart_Presentation->setEnabled(true); + ui->actionStart_Here->setEnabled(true); + ui->actionStart_Begin->setEnabled(true); }else{ progress->setValue(finished); } } -void MainUI::slotStartPresentation(QAction *act){ +/*void MainUI::slotStartPresentation(QAction *act){ startPresentation(act == ui->actionAt_Beginning); -} - -void MainUI::paintOnWidget(QPrinter *PRINTER){ - if(DOC==0){ return; } - //this->show(); - if(loadingHash.keys().length() != numPages){ startLoadingPages(PRINTER); return; } - - QPainter painter(PRINTER); - for(int i=0; i<numPages; i++){ - if(i != 0){ PRINTER->newPage(); } //this is the start of the next page (not needed for first) - if(loadingHash.contains(i)){ painter.drawImage(0,0, loadingHash[i].scaled(PRINTER->pageRect().size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); } - else{ painter.drawImage(0,0, QImage()); } - } -} +}*/ void MainUI::paintToPrinter(QPrinter *PRINTER){ if(loadingHash.keys().length() != numPages){ return; } @@ -320,7 +430,7 @@ void MainUI::paintToPrinter(QPrinter *PRINTER){ int firstpage = 0; int copies = PRINTER->copyCount(); bool collate = PRINTER->collateCopies(); - bool duplex = (PRINTER->duplex()!=QPrinter::DuplexNone); + //bool duplex = (PRINTER->duplex()!=QPrinter::DuplexNone); //Determine the first page that needs to be printed, and the range if((PRINTER->fromPage() != PRINTER->toPage() || PRINTER->fromPage()!=0 ) && PRINTER->printRange()==QPrinter::PageRange ){ firstpage = PRINTER->fromPage() - 1; @@ -350,7 +460,6 @@ void MainUI::paintToPrinter(QPrinter *PRINTER){ } } //qDebug() << "Final Page Range:" << pageCount; - //return; //Generate the sizing information for the printer QSize sz(PRINTER->pageRect().width(), PRINTER->pageRect().height()); bool landscape = PRINTER->orientation()==QPrinter::Landscape; @@ -383,3 +492,166 @@ void MainUI::OpenNewFile(){ void MainUI::updateClock(){ label_clock->setText( QDateTime::currentDateTime().toString("<b>hh:mm:ss</b>") ); } + +void MainUI::setScroll(bool tog) { + if(tog) { + QApplication::setOverrideCursor(Qt::OpenHandCursor); + }else{ + QApplication::setOverrideCursor(Qt::IBeamCursor); + } +} + +void MainUI::rotate(bool ccw) { + for(int i = 0; i < numPages; i++) { + QImage image = loadingHash[i]; + qDebug() << "Page rotating: " << i; + //Setup a rotation matrix that rotates 90 degrees clockwise or counterclockwise + QMatrix matrix = (ccw) ? QMatrix(0, -1, 1, 0, 0, 0) : QMatrix(0, 1, -1, 0, 0, 0); + image = image.transformed(matrix, Qt::SmoothTransformation); + //Updates the image in the hash + loadingHash.insert(i, image); + } + //Rotates the page as well as the image + //WIDGET->setOrientation((WIDGET->orientation() == QPageLayout::Landscape) ? + //QPageLayout::Portrait : QPageLayout::Landscape); + QTimer::singleShot(0, WIDGET, SLOT(updatePreview())); +} + +void MainUI::updateContextMenu(){ + contextMenu->clear(); + contextMenu->addSection( QString(tr("Page %1 of %2")).arg(QString::number(WIDGET->currentPage()), + QString::number(numPages) ) ); + contextMenu->addAction(ui->actionPrevious_Page); + contextMenu->addAction(ui->actionNext_Page); + contextMenu->addSeparator(); + contextMenu->addAction(ui->actionFirst_Page); + contextMenu->addAction(ui->actionLast_Page); + contextMenu->addSeparator(); + if(presentationLabel==0 || !presentationLabel->isVisible()){ + contextMenu->addAction(ui->actionStart_Begin); + contextMenu->addAction(ui->actionStart_Here); + }else{ + contextMenu->addAction(ui->actionStop_Presentation); + } +} + +void MainUI::keyPressEvent(QKeyEvent *event){ + //See if this is one of the special hotkeys and act appropriately + bool inPresentation = (presentationLabel!=0); + if( event->key()==Qt::Key_Escape || event->key()==Qt::Key_Backspace){ + if(inPresentation){ endPresentation(); } + }else if(event->key()==Qt::Key_Right || event->key()==Qt::Key_Space || + event->key()==Qt::Key_PageDown){ + nextPage(); + }else if(event->key()==Qt::Key_Left || event->key()==Qt::Key_PageUp){ + prevPage(); + }else if(event->key()==Qt::Key_Home){ + firstPage(); + }else if(event->key()==Qt::Key_End){ + lastPage(); + }else if(event->key()==Qt::Key_F11){ + if(inPresentation){ endPresentation(); } + else{ startPresentationHere(); } + }else if(event->key() == Qt::Key_Up) { + //Scroll the widget up + }else if(event->key() == Qt::Key_Down) { + //Scroll the widget down + /*qDebug() << "Send Wheel Event"; + QWheelEvent wEvent( WIDGET->mapFromGlobal(QCursor::pos()), QCursor::pos(),QPoint(0,0), QPoint(0,30), 0, Qt::Vertical, Qt::LeftButton, Qt::NoModifier); + QApplication::sendEvent(WIDGET, &wEvent);*/ + }else{ + QMainWindow::keyPressEvent(event); + } +} + +void MainUI::wheelEvent(QWheelEvent *event) { + //Scroll the window according to the mouse wheel + QMainWindow::wheelEvent(event); +} + +void MainUI::showInformation() { + PROPDIALOG = new PropDialog(DOC); + PROPDIALOG->show(); +} + +void MainUI::find(QString text, bool forward) { + if(!text.isEmpty()) { + qDebug() << "Finding Text"; + bool newText = results.empty(); + bool research = false; + if(!newText) + research = !results.keys()[0]->text().contains(text); + //Clear results if the user gives a new search string + if(research) + results.clear(); + + if(research or newText) { + for(int i = 0; i < numPages; i++) { + QList<Poppler::TextBox*> textList = DOC->page(i)->textList(); + for(int j = 0; j < textList.size(); j++) { + if(textList[j]->text().contains(text, (matchCase) + ? Qt::CaseSensitive : Qt::CaseInsensitive)) { + results.insert(textList[j], i); + } + } + } + currentHighlight = (forward) ? -1 : results.size(); + } + + qDebug() << "Jumping to next result"; + if(!results.empty()) { + //Jump to the location of the next or previous textbox and highlight + if(forward) { + currentHighlight = (currentHighlight + 1) % results.size(); + }else{ + currentHighlight--; + //Ensure currentHighlight will be between 0 and results.size() - 1 + if(currentHighlight < 0) + currentHighlight = results.size() - 1; + } + + qDebug() << "Jump to location: " << currentHighlight; + + Poppler::TextBox *currentText = results.keys()[currentHighlight]; + WIDGET->setCurrentPage(results.value(currentText)); + WIDGET->highlightText(currentHighlight, currentText->boundingBox()); + + QTimer::singleShot(10, WIDGET, SLOT(updatePreview())); + }else{ + //Print "No results found" + } + } +} + +void MainUI::enableFind() { + if(ui->findGroup->isVisible()) { + qDebug() << "Disabling Find"; + ui->findGroup->setVisible(false); + WIDGET->setGeometry(QRect(WIDGET->pos(), + QSize(WIDGET->width(), WIDGET->height()+ui->findGroup->height()))); + QTimer::singleShot(0, WIDGET, SLOT(updatePreview())); + this->setFocus(); + }else{ + qDebug() << "Enabling Find"; + ui->findGroup->setGeometry(QRect(QPoint(0, WIDGET->height()-ui->findGroup->height()), + QSize(WIDGET->width()-12, ui->findGroup->height()))); + ui->findGroup->setVisible(true); + WIDGET->setGeometry(QRect(WIDGET->pos(), + QSize(WIDGET->width(), WIDGET->height()-ui->findGroup->height()))); + + QTimer::singleShot(0, WIDGET, SLOT(updatePreview())); + ui->findGroup->setFocus(); + } +} + +void MainUI::showBookmarks() { + ui->bookmarksFrame->setVisible(true); +} + +void MainUI::resizeEvent(QResizeEvent *event) { + if(ui->findGroup->isVisible()) { + ui->findGroup->setGeometry(QRect(QPoint(0, WIDGET->height()-ui->findGroup->height()), + QSize(WIDGET->width()-10, ui->findGroup->height()))); + } + QMainWindow::resizeEvent(event); +} diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.h b/src-qt5/desktop-utils/lumina-pdf/mainUI.h index 87d2a4e4..2d23b402 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.h +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.h @@ -17,8 +17,12 @@ #include <QDebug> #include <QWheelEvent> #include <QApplication> +#include <QMenu> -#include <poppler-qt5.h> +#include <poppler/qt5/poppler-qt5.h> +#include "PresentationLabel.h" +#include "propDialog.h" +#include "PrintWidget.h" namespace Ui{ class MainUI; @@ -32,20 +36,22 @@ public: void loadFile(QString path); - private: Poppler::Document *DOC; - QPrintPreviewWidget *WIDGET; + PrintWidget *WIDGET; Ui::MainUI *ui; - QPrinter* Printer; + PropDialog *PROPDIALOG; QPrintDialog *PrintDLG; - QString lastdir; + bool matchCase; + QMap<Poppler::TextBox*, int> results; + int currentHighlight; //Other Interface elements QProgressBar *progress; QAction *progAct; //action associated with the progressbar QTimer *clockTimer; + QMenu *contextMenu; //QFrame *frame_presenter; QLabel *label_clock; QAction *clockAct; @@ -57,7 +63,7 @@ private: void loadPage(int num, Poppler::Document *doc, MainUI *obj, QSize dpi, QSizeF page); //Functions/variables for the presentation mode - QLabel *presentationLabel; + PresentationLabel *presentationLabel; QScreen *getScreen(bool current, bool &cancelled); int CurrentPage; void startPresentation(bool atStart); @@ -65,11 +71,24 @@ private: void endPresentation(); private slots: - void startLoadingPages(QPrinter *printer); + void startLoadingPages(); void slotPageLoaded(int); - void slotStartPresentation(QAction *act); + //void slotStartPresentation(QAction *act); + + //Simplification routines + void nextPage(){ ShowPage( WIDGET->currentPage() ); } //currentPage() starts at 1 rather than 0 + void prevPage(){ ShowPage( WIDGET->currentPage()-2 ); } //currentPage() starts at 1 rather than 0 + void firstPage(){ ShowPage(0); } + void lastPage(){ ShowPage(numPages-1); } + void startPresentationHere(){ startPresentation(false); } + void startPresentationBeginning(){ startPresentation(true); } + void closePresentation(){ endPresentation(); } + + void showInformation(); + void find(QString text, bool forward); + void enableFind(); + void showBookmarks(); - void paintOnWidget(QPrinter *PRINTER); void paintToPrinter(QPrinter *PRINTER); //Button Slots @@ -77,49 +96,18 @@ private slots: //Other interface slots void updateClock(); + void showContextMenu(const QPoint&){ contextMenu->popup(QCursor::pos()); } + void updateContextMenu(); + + void setScroll(bool); + void rotate(bool); signals: void PageLoaded(int); protected: - void keyPressEvent(QKeyEvent *event){ - //See if this is one of the special hotkeys and act appropriately - //qDebug() << "Got Key Press:"; - bool inPresentation = (presentationLabel!=0); - if(!inPresentation){ - //Alternate functionality when **not** in presentation mode - /*if(event->key()==Qt::Key_Down){ - qDebug() << "Send Wheel Event"; - QWheelEvent event( WIDGET->mapFromGlobal(QCursor::pos()), QCursor::pos(),QPoint(0,0), QPoint(0,30), 0, Qt::Vertical, Qt::LeftButton, Qt::NoModifier); - QApplication::sendEvent(WIDGET, &event); - //WIDGET->scrollDown(); - return; - }else if(event->key()==Qt::Key_Up){ - return; - }*/ - } - - if( event->key()==Qt::Key_Escape || event->key()==Qt::Key_Backspace){ - //qDebug() << " - Escape/Backspace"; - endPresentation(); - }else if(event->key()==Qt::Key_Right || event->key()==Qt::Key_Down || event->key()==Qt::Key_Space || event->key()==Qt::Key_PageDown){ - //qDebug() << " - Right/Down/Spacebar" << inPresentation; - ShowPage( WIDGET->currentPage() ); //currentPage() starts at 1 rather than 0 - }else if(event->key()==Qt::Key_Left || event->key()==Qt::Key_Up || event->key()==Qt::Key_PageUp){ - //qDebug() << " - Left/Up"; - ShowPage( WIDGET->currentPage()-2 ); //currentPage() starts at 1 rather than 0 - }else if(event->key()==Qt::Key_Home){ - //qDebug() << " - Home"; - ShowPage(0); //go to the first page - }else if(event->key()==Qt::Key_End){ - //qDebug() << " - End"; - ShowPage( numPages-1 ); //go to the last page - }else if(event->key()==Qt::Key_F11){ - //qDebug() << " - F11"; - endPresentation(); - }else{ - QMainWindow::keyPressEvent(event); - } - } + void keyPressEvent(QKeyEvent*); + void wheelEvent(QWheelEvent*); + void resizeEvent(QResizeEvent*); }; #endif diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.ui b/src-qt5/desktop-utils/lumina-pdf/mainUI.ui index 7f555d01..8f6fff27 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.ui +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.ui @@ -6,21 +6,120 @@ <rect> <x>0</x> <y>0</y> - <width>659</width> - <height>588</height> + <width>697</width> + <height>694</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> - <widget class="QWidget" name="centralwidget"/> + <widget class="QWidget" name="centralwidget"> + <widget class="QFrame" name="findGroup"> + <property name="geometry"> + <rect> + <x>0</x> + <y>560</y> + <width>691</width> + <height>61</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="closeFind"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="textEdit"/> + </item> + <item> + <widget class="QPushButton" name="findPrevB"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="findNextB"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="matchCase"> + <property name="text"> + <string/> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Find...</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QFrame" name="bookmarksFrame"> + <property name="geometry"> + <rect> + <x>0</x> + <y>9</y> + <width>81</width> + <height>601</height> + </rect> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <widget class="QLabel" name="label_2"> + <property name="geometry"> + <rect> + <x>10</x> + <y>0</y> + <width>71</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Bookmarks</string> + </property> + </widget> + </widget> + </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>659</width> - <height>28</height> + <width>697</width> + <height>21</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -32,22 +131,53 @@ <addaction name="actionOpen_PDF"/> <addaction name="separator"/> <addaction name="actionClose"/> + <addaction name="separator"/> + <addaction name="actionProperties"/> </widget> <widget class="QMenu" name="menuPresentation"> <property name="title"> <string>&Presentation</string> </property> - <widget class="QMenu" name="menuStart_Presentation"> - <property name="title"> - <string>Start Presentation</string> - </property> - <addaction name="actionAt_Beginning"/> - </widget> - <addaction name="menuStart_Presentation"/> + <addaction name="actionStart_Begin"/> + <addaction name="actionStart_Here"/> <addaction name="actionStop_Presentation"/> </widget> + <widget class="QMenu" name="menuSettings"> + <property name="title"> + <string>Edit</string> + </property> + <addaction name="actionFind"/> + <addaction name="actionFind_Next"/> + <addaction name="actionFind_Previous"/> + <addaction name="actionClearHighlights"/> + <addaction name="separator"/> + <addaction name="actionSettings"/> + <addaction name="separator"/> + <addaction name="actionScroll_Mode"/> + <addaction name="actionSelect_Mode"/> + <addaction name="separator"/> + </widget> + <widget class="QMenu" name="menuView"> + <property name="title"> + <string>View</string> + </property> + <addaction name="actionZoom_In"/> + <addaction name="actionZoom_Out"/> + <addaction name="separator"/> + <addaction name="actionFirst_Page"/> + <addaction name="actionPrevious_Page"/> + <addaction name="actionNext_Page"/> + <addaction name="actionLast_Page"/> + <addaction name="separator"/> + <addaction name="actionBookmarks"/> + <addaction name="separator"/> + <addaction name="actionRotate_Counterclockwise"/> + <addaction name="actionRotate_Clockwise"/> + </widget> <addaction name="menuFile"/> <addaction name="menuPresentation"/> + <addaction name="menuSettings"/> + <addaction name="menuView"/> </widget> <widget class="QStatusBar" name="statusbar"/> <widget class="QToolBar" name="toolBar"> @@ -72,6 +202,9 @@ <addaction name="actionSingle_Page"/> <addaction name="actionDual_Pages"/> <addaction name="actionAll_Pages"/> + <addaction name="separator"/> + <addaction name="actionZoom_In_2"/> + <addaction name="actionZoom_Out_2"/> </widget> <action name="actionOpen_PDF"> <property name="text"> @@ -137,9 +270,9 @@ <string>All Pages</string> </property> </action> - <action name="actionAt_Beginning"> + <action name="actionStart_Begin"> <property name="text"> - <string>At Beginning</string> + <string>Start Presentation (at beginning)</string> </property> </action> <action name="actionStop_Presentation"> @@ -147,6 +280,118 @@ <string>Stop Presentation</string> </property> </action> + <action name="actionFind"> + <property name="text"> + <string>Find</string> + </property> + </action> + <action name="actionFind_Next"> + <property name="text"> + <string>Find Next</string> + </property> + </action> + <action name="actionFind_Previous"> + <property name="text"> + <string>Find Previous</string> + </property> + </action> + <action name="actionSettings"> + <property name="text"> + <string>Settings</string> + </property> + </action> + <action name="actionZoom_In"> + <property name="text"> + <string>Zoom In</string> + </property> + </action> + <action name="actionZoom_Out"> + <property name="text"> + <string>Zoom Out</string> + </property> + </action> + <action name="actionFirst_Page"> + <property name="text"> + <string>First Page</string> + </property> + </action> + <action name="actionPrevious_Page"> + <property name="text"> + <string>Previous Page</string> + </property> + </action> + <action name="actionNext_Page"> + <property name="text"> + <string>Next Page</string> + </property> + </action> + <action name="actionLast_Page"> + <property name="text"> + <string>Last Page</string> + </property> + </action> + <action name="actionProperties"> + <property name="text"> + <string>Properties</string> + </property> + </action> + <action name="actionBookmarks"> + <property name="text"> + <string>Bookmarks</string> + </property> + </action> + <action name="actionRotate_Counterclockwise"> + <property name="text"> + <string>Rotate Counterclockwise</string> + </property> + </action> + <action name="actionRotate_Clockwise"> + <property name="text"> + <string>Rotate Clockwise</string> + </property> + </action> + <action name="actionScroll_Mode"> + <property name="checkable"> + <bool>false</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Scroll Mode</string> + </property> + </action> + <action name="actionZoom_Out_2"> + <property name="text"> + <string/> + </property> + </action> + <action name="actionZoom_In_2"> + <property name="text"> + <string/> + </property> + </action> + <action name="actionStart_Here"> + <property name="text"> + <string>Start Presentation (current slide)</string> + </property> + </action> + <action name="actionSelect_Mode"> + <property name="checkable"> + <bool>false</bool> + </property> + <property name="text"> + <string>Select Mode</string> + </property> + </action> + <action name="actionClearHighlights"> + <property name="text"> + <string>Clear Highlights</string> + </property> + </action> </widget> <resources/> <connections/> diff --git a/src-qt5/desktop-utils/lumina-pdf/propDialog.cpp b/src-qt5/desktop-utils/lumina-pdf/propDialog.cpp new file mode 100644 index 00000000..0c26af74 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/propDialog.cpp @@ -0,0 +1,56 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== + +#include "propDialog.h" +#include "ui_propDialog.h" + +#include <LuminaXDG.h> + +PropDialog::PropDialog(Poppler::Document *DOC) : QDialog(), ui(new Ui::PropDialog()){ + this->setWindowTitle(tr("PDF Information")); + this->setWindowIcon( LXDG::findIcon("dialog-information","unknown")); + int verMa, verMi; + QString version; + QSize size = DOC->page(0)->pageSize(); + + //Grab the version + DOC->getPdfVersion(&verMa, &verMi); + version = QString::number(verMa)+"."+QString::number(verMi); + + ui->setupUi(this); + + connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(close())); + + //Setup translations + ui->titleL->setText(tr("Title:")); + ui->subjectL->setText(tr("Subject:")); + ui->authorL->setText(tr("Author:")); + ui->creatorL->setText(tr("Creator:")); + ui->producerL->setText(tr("Producer:")); + ui->keywordsL->setText(tr("Keywords:")); + ui->createdL->setText(tr("Created:")); + ui->modifiedL->setText(tr("Modified:")); + ui->versionL->setText(tr("PDF Version:")); + ui->sizeL->setText(tr("Page Size:")); + ui->numberL->setText(tr("Number of Pages:")); + ui->saveButton->setText(tr("Save")); + ui->closeButton->setText(tr("Close")); + + //Fill the text boxes with information from the document + ui->titleE->setText(DOC->title()); + ui->subjectE->setText(DOC->subject()); + ui->authorE->setText(DOC->author()); + ui->creatorE->setText(DOC->creator()); + ui->producerE->setText(DOC->producer()); + ui->keywordE->setText(DOC->keywords()); + ui->createdEntry->setText(DOC->creationDate().toString(Qt::TextDate)); + ui->modifiedEntry->setText(DOC->modificationDate().toString(Qt::TextDate)); + ui->versionL->setText(ui->versionL->text()+version); + ui->sizeL->setText(ui->sizeL->text()+QString::number(size.height())+ + ", "+QString::number(size.width())); + ui->numberL->setText(ui->numberL->text()+QString::number(DOC->numPages())); +} diff --git a/src-qt5/desktop-utils/lumina-pdf/propDialog.h b/src-qt5/desktop-utils/lumina-pdf/propDialog.h new file mode 100644 index 00000000..be67ebd3 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/propDialog.h @@ -0,0 +1,25 @@ +//=========================================== +// 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_PDF_VIEWER_PROP_DIALOG_H +#define _LUMINA_PDF_VIEWER_PROP_DIALOG_H + +#include <QDialog> +#include <poppler/qt5/poppler-qt5.h> + +namespace Ui{ + class PropDialog; +}; + +class PropDialog : public QDialog { + Q_OBJECT + public: + PropDialog(Poppler::Document*); + + private: + Ui::PropDialog *ui; +}; +#endif diff --git a/src-qt5/desktop-utils/lumina-pdf/propDialog.ui b/src-qt5/desktop-utils/lumina-pdf/propDialog.ui new file mode 100644 index 00000000..6806f81a --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/propDialog.ui @@ -0,0 +1,477 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PropDialog</class> + <widget class="QDialog" name="PropDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>PDF Information</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="titleL"> + <property name="text"> + <string>Title:</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QTextEdit" name="titleE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="subjectL"> + <property name="text"> + <string>Subject:</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QTextEdit" name="subjectE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="authorL"> + <property name="text"> + <string>Author:</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="QTextEdit" name="authorE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="creatorL"> + <property name="text"> + <string>Creator:</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="2"> + <widget class="QTextEdit" name="creatorE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="producerL"> + <property name="text"> + <string>Producer:</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="2"> + <widget class="QTextEdit" name="producerE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="keywordsL"> + <property name="text"> + <string>Keywords:</string> + </property> + </widget> + </item> + <item row="5" column="1" colspan="2"> + <widget class="QTextEdit" name="keywordE"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="createdL"> + <property name="text"> + <string>Created: </string> + </property> + </widget> + </item> + <item row="6" column="1" colspan="2"> + <widget class="QTextEdit" name="createdEntry"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="modifiedL"> + <property name="text"> + <string>Modified: </string> + </property> + </widget> + </item> + <item row="7" column="1" colspan="2"> + <widget class="QTextEdit" name="modifiedEntry"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="8" column="0" colspan="3"> + <widget class="QLabel" name="versionL"> + <property name="text"> + <string>PDF Version:</string> + </property> + </widget> + </item> + <item row="9" column="0" colspan="3"> + <widget class="QLabel" name="sizeL"> + <property name="text"> + <string>Page Size:</string> + </property> + </widget> + </item> + <item row="10" column="0" colspan="3"> + <widget class="QLabel" name="numberL"> + <property name="text"> + <string>Number of Pages:</string> + </property> + </widget> + </item> + <item row="11" column="1"> + <widget class="QPushButton" name="saveButton"> + <property name="text"> + <string>Save</string> + </property> + </widget> + </item> + <item row="11" column="2"> + <widget class="QPushButton" name="closeButton"> + <property name="text"> + <string>Close</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src-qt5/desktop-utils/lumina-screenshot/lumina-screenshot.pro b/src-qt5/desktop-utils/lumina-screenshot/lumina-screenshot.pro index d0cce451..f5118db7 100644 --- a/src-qt5/desktop-utils/lumina-screenshot/lumina-screenshot.pro +++ b/src-qt5/desktop-utils/lumina-screenshot/lumina-screenshot.pro @@ -90,13 +90,13 @@ TRANSLATIONS = i18n/l-screenshot_af.ts \ i18n/l-screenshot_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-screenshot.desktop desktop.path=$${L_SHAREDIR}/applications/ manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-screenshot.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-screenshot.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-screenshot.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-screenshot.1.gz" INSTALLS += target desktop manpage diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp index 9e4ce499..bdb9d29c 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp @@ -29,15 +29,26 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ fontbox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); QWidget *spacer = new QWidget(this); spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + QWidget *spacer2 = new QWidget(this); + spacer2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + label_readonly = new QAction(tr("Read-Only File"), this); + label_readonly->setEnabled(false); //not an actual button + label_readonly->setToolTip(""); + QFont fnt = this->font(); + fnt.setItalic(true); + fnt.setBold(true); + label_readonly->setFont(fnt); fontSizes = new QSpinBox(this); fontSizes->setRange(5, 72); - fontSizes->setValue(9); + fontSizes->setValue(this->font().pointSize()); fontSizes->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); //For some reason, the FontComboBox is always 2 pixels taller than the SpinBox - manually fix that here - fontbox->setFixedHeight(30); - fontSizes->setFixedHeight(32); + fontbox->setFixedHeight(ui->toolBar->iconSize().height()-2); + fontSizes->setFixedHeight(ui->toolBar->iconSize().height()); ui->toolBar->addWidget(spacer); + ui->toolBar->addAction(label_readonly); + ui->toolBar->addWidget(spacer2); ui->toolBar->addWidget(fontbox); ui->toolBar->addWidget(fontSizes); //Load the special Drag and Drop QTabWidget @@ -72,6 +83,10 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ for(int i=0; i<smodes.length(); i++){ ui->menuSyntax_Highlighting->addAction(smodes[i]); } + + bool toolbarVisible = settings->value("showToolbar",true).toBool(); + ui->toolBar->setHidden(!toolbarVisible); + ui->actionShow_Toolbar->setChecked(toolbarVisible); ui->actionLine_Numbers->setChecked( settings->value("showLineNumbers",true).toBool() ); ui->actionWrap_Lines->setChecked( settings->value("wrapLines",true).toBool() ); ui->actionShow_Popups->setChecked( settings->value("showPopupWarnings",true).toBool() ); @@ -96,6 +111,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ connect(tabWidget->dndTabBar(), SIGNAL(DetachTab(int)), this, SLOT(tabDetached(int)) ); connect(tabWidget->dndTabBar(), SIGNAL(DroppedIn(QStringList)), this, SLOT(LoadArguments(QStringList)) ); connect(tabWidget->dndTabBar(), SIGNAL(DraggedOut(int, Qt::DropAction)), this, SLOT(tabDraggedOut(int, Qt::DropAction)) ); + connect(ui->actionShow_Toolbar, SIGNAL(toggled(bool)), this, SLOT(showToolbar(bool)) ); connect(ui->actionLine_Numbers, SIGNAL(toggled(bool)), this, SLOT(showLineNumbers(bool)) ); connect(ui->actionWrap_Lines, SIGNAL(toggled(bool)), this, SLOT(wrapLines(bool)) ); connect(ui->actionShow_Popups, SIGNAL(toggled(bool)), this, SLOT(showPopupWarnings(bool)) ); @@ -184,6 +200,17 @@ QString MainUI::currentFileDir(){ return dir; } +QStringList MainUI::unsavedFiles(){ + QStringList unsaved; + for(int i=0; i<tabWidget->count(); i++){ + PlainTextEditor *tmp = static_cast<PlainTextEditor*>(tabWidget->widget(i)); + if(tmp->hasChange()){ + unsaved << tmp->currentFile(); + } + } + return unsaved; +} + // ================= // PRIVATE SLOTS //================= @@ -234,16 +261,27 @@ void MainUI::CloseFile(){ if(index>=0){ tabClosed(index); } } -void MainUI::SaveFile(){ +bool MainUI::SaveFile(){ PlainTextEditor *cur = currentEditor(); - if(cur==0){ return; } - cur->SaveFile(); + if(cur==0){ return true; } //nothing to do + return cur->SaveFile(); } -void MainUI::SaveFileAs(){ +bool MainUI::SaveFileAs(){ PlainTextEditor *cur = currentEditor(); - if(cur==0){ return; } - cur->SaveFile(true); + if(cur==0){ return true; } //nothing to do + return cur->SaveFile(true); +} + +bool MainUI::SaveAllFiles(){ + bool ok = true; + for(int i=0; i<tabWidget->count() && ok; i++){ + PlainTextEditor *tmp = static_cast<PlainTextEditor*>(tabWidget->widget(i)); + if(tmp->hasChange()){ + ok = ok && tmp->SaveFile(); + } + } + return ok; } void MainUI::Print() { @@ -337,6 +375,11 @@ void MainUI::showPopupWarnings(bool show){ settings->setValue("showPopupWarnings",show); } +void MainUI::showToolbar(bool show){ + settings->setValue("showToolbar",show); + ui->toolBar->setHidden(!show); +} + void MainUI::updateTab(QString file){ PlainTextEditor *cur = 0; int index = -1; @@ -356,6 +399,7 @@ void MainUI::updateTab(QString file){ tabWidget->setTabWhatsThis(index, file); //needed for drag/drop functionality ui->actionSave_File->setEnabled(changes); this->setWindowTitle( (changes ? "*" : "") + file.section("/",-2) ); + label_readonly->setVisible( cur->readOnlyFile() ); } void MainUI::tabChanged(){ @@ -373,6 +417,7 @@ void MainUI::tabChanged(){ fontbox->setCurrentFont(font); fontSizes->setValue( font.pointSize() ); ui->actionWrap_Lines->setChecked( cur->lineWrapMode()==QPlainTextEdit::WidgetWidth ); + label_readonly->setVisible( cur->readOnlyFile() ); } void MainUI::tabClosed(int tab){ @@ -489,21 +534,31 @@ PlainTextEditor *cur = currentEditor(); //============= void MainUI::closeEvent(QCloseEvent *ev){ //See if any of the open editors have unsaved changes first - QStringList unsaved; - for(int i=0; i<tabWidget->count(); i++){ - PlainTextEditor *tmp = static_cast<PlainTextEditor*>(tabWidget->widget(i)); - if(tmp->hasChange()){ - unsaved << tmp->currentFile(); - } + QStringList unsaved = unsavedFiles(); + if(unsaved.isEmpty() || !ui->actionShow_Popups->isChecked()){ + QMainWindow::closeEvent(ev); + return; + } + + //Otherwise, ask the user what to do. + QMessageBox::StandardButton but = QMessageBox::question( + this, + tr("Save Changes before closing?"), + QString(tr("There are unsaved changes.\nDo you want save them before you close the editor?\n\n%1")).arg(unsaved.join("\n")), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::No); + + if(but == QMessageBox::Cancel){ + ev->ignore(); + return; } - if(unsaved.isEmpty()){ QMainWindow::closeEvent(ev); return; } - bool savenow = false; - if(!savenow && !ui->actionShow_Popups->isChecked()){ savenow = true; } - if(!savenow){ - QMessageBox::StandardButton but = QMessageBox::question(this, tr("Save Changes before closing?"), QString(tr("There are unsaved changes.\nDo you want save them before you close the editor?\n\n%1")).arg(unsaved.join("\n")), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No); - savenow = (but == QMessageBox::Yes); - if(but == QMessageBox::Cancel){ ev->ignore(); return; } + else if(but == QMessageBox::Yes){ + if( !SaveAllFiles() ){ + //cancelled by user + ev->ignore(); + return; } - if(savenow){ SaveFile(); } - QMainWindow::closeEvent(ev); + + } + QMainWindow::closeEvent(ev); } diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.h b/src-qt5/desktop-utils/lumina-textedit/MainUI.h index 6e5d2d23..464e7a52 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.h +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.h @@ -13,6 +13,8 @@ #include <QShortcut> #include <QFontComboBox> #include <QSpinBox> +#include <QAction> +#include <QApplication> #include "PlainTextEditor.h" #include "ColorDialog.h" @@ -40,18 +42,21 @@ private: QSettings *settings; QShortcut *closeFindS; QSpinBox *fontSizes; + QAction *label_readonly; //Simplification functions PlainTextEditor* currentEditor(); QString currentFileDir(); + QStringList unsavedFiles(); private slots: //Main Actions void NewFile(); void OpenFile(QString file = ""); void CloseFile(); //current file only - void SaveFile(); - void SaveFileAs(); + bool SaveFile(); + bool SaveFileAs(); + bool SaveAllFiles(); void Print(); void fontChanged(const QFont &font); void updateStatusTip(); @@ -60,6 +65,7 @@ private slots: //Other Menu Actions void UpdateHighlighting(QAction *act = 0); + void showToolbar(bool); void showLineNumbers(bool); void wrapLines(bool); void ModifyColors(); diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.ui b/src-qt5/desktop-utils/lumina-textedit/MainUI.ui index 026521b3..f88f3976 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.ui @@ -182,7 +182,7 @@ <x>0</x> <y>0</y> <width>505</width> - <height>28</height> + <height>24</height> </rect> </property> <property name="contextMenuPolicy"> @@ -224,6 +224,7 @@ </widget> <addaction name="menuSyntax_Highlighting"/> <addaction name="menuTabs_Location"/> + <addaction name="actionShow_Toolbar"/> <addaction name="actionLine_Numbers"/> <addaction name="actionWrap_Lines"/> <addaction name="actionShow_Popups"/> @@ -436,6 +437,17 @@ <string>Ctrl+P</string> </property> </action> + <action name="actionShow_Toolbar"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="text"> + <string>Show Toolbar</string> + </property> + </action> </widget> <tabstops> <tabstop>line_find</tabstop> diff --git a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp index 653bd0e8..b1592cc3 100644 --- a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp @@ -24,7 +24,7 @@ PlainTextEditor::PlainTextEditor(QSettings *set, QWidget *parent) : QPlainTextEd LNW = new LNWidget(this); showLNW = true; watcher = new QFileSystemWatcher(this); - hasChanges = false; + hasChanges = readonly = false; lastSaveContents.clear(); matchleft = matchright = -1; this->setTabStopWidth( 8 * this->fontMetrics().width(" ") ); //8 character spaces per tab (UNIX standard) @@ -76,17 +76,22 @@ void PlainTextEditor::LoadFile(QString filepath){ bool diffFile = (filepath != this->whatsThis()); this->setWhatsThis(filepath); this->clear(); - QList<SyntaxFile> files = SyntaxFile::availableFiles(settings); + /*QList<SyntaxFile> files = SyntaxFile::availableFiles(settings); for(int i=0; i<files.length(); i++){ if(files[i].supportsFile(filepath) ){ files[i].SetupDocument(this); SYNTAX->loadRules(files[i]); break; } - } + }*/ //SYNTAX->loadRules( Custom_Syntax::ruleForFile(filepath.section("/",-1), settings) ); lastSaveContents = LUtils::readFile(filepath).join("\n"); if(diffFile){ + SYNTAX->loadRules( Custom_Syntax::ruleForFile(this->whatsThis().section("/",-1), settings) ); + if(SYNTAX->loadedRules().isEmpty()){ + SYNTAX->loadRules( Custom_Syntax::ruleForFirstLine( lastSaveContents.section("\n",0,0,QString::SectionSkipEmpty) , settings) ); + } + SYNTAX->setupDocument(this); this->setPlainText( lastSaveContents ); }else{ //Try to keep the mouse cursor/scroll in the same position @@ -99,18 +104,34 @@ void PlainTextEditor::LoadFile(QString filepath){ this->centerCursor(); //scroll until cursor is centered (if possible) } hasChanges = false; - if(QFile::exists(filepath)){ watcher->addPath(filepath); } + readonly = false; + if(QFile::exists(filepath)){ + readonly = !QFileInfo(filepath).isWritable(); + watcher->addPath(filepath); + }else if(filepath.startsWith("/")){ + //See if the containing directory is writable instead + readonly = !QFileInfo(filepath.section("/",0,-2)).isWritable(); + } emit FileLoaded(this->whatsThis()); } -void PlainTextEditor::SaveFile(bool newname){ +bool PlainTextEditor::SaveFile(bool newname){ + //NOTE: This returns true for proper behaviour, and false for a user-cancelled process //qDebug() << "Save File:" << this->whatsThis(); + //Quick check for a non-editable file + if(!newname && this->whatsThis().startsWith("/")){ + if(!QFileInfo(this->whatsThis()).isWritable()){ newname = true; } //cannot save the current file name/location + } if( !this->whatsThis().startsWith("/") || newname ){ //prompt for a filename/path QString file = QFileDialog::getSaveFileName(this, tr("Save File"), this->whatsThis(), tr("Text File (*)")); - if(file.isEmpty()){ return; } + if(file.isEmpty()){ return false; } //cancelled this->setWhatsThis(file); SYNTAX->loadRules( Custom_Syntax::ruleForFile(this->whatsThis().section("/",-1), settings) ); + if(SYNTAX->loadedRules().isEmpty()){ + SYNTAX->loadRules( Custom_Syntax::ruleForFirstLine( this->toPlainText().section("\n",0,0,QString::SectionSkipEmpty) , settings) ); + } + SYNTAX->setupDocument(this); SYNTAX->rehighlight(); } if( !watcher->files().isEmpty() ){ watcher->removePaths(watcher->files()); } @@ -118,6 +139,8 @@ void PlainTextEditor::SaveFile(bool newname){ hasChanges = !ok; if(ok){ lastSaveContents = this->toPlainText(); emit FileLoaded(this->whatsThis()); } watcher->addPath(currentFile()); + readonly = !QFileInfo(this->whatsThis()).isWritable(); //update this flag + return true; //qDebug() << " - Success:" << ok << hasChanges; } @@ -129,6 +152,11 @@ bool PlainTextEditor::hasChange(){ return hasChanges; } +bool PlainTextEditor::readOnlyFile(){ + //qDebug() << "Read Only File:" << readonly << this->whatsThis(); + return readonly; +} + //Functions for managing the line number widget int PlainTextEditor::LNWWidth(){ //Get the number of chars we need for line numbers diff --git a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h index 0c83b7ce..b0a6cbc7 100644 --- a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h +++ b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h @@ -21,7 +21,7 @@ class PlainTextEditor : public QPlainTextEdit{ public: PlainTextEditor(QSettings *set, QWidget *parent = 0); ~PlainTextEditor(); - + //Functions for setting up the editor void showLineNumbers(bool show = true); void LoadSyntaxRule(QString type); @@ -29,18 +29,19 @@ public: //File loading/setting options void LoadFile(QString filepath); - void SaveFile(bool newname = false); + bool SaveFile(bool newname = false); QString currentFile(); bool hasChange(); + bool readOnlyFile(); //Functions for managing the line number widget (internal - do not need to run directly) int LNWWidth(); //replacing the LNW size hint detection void paintLNW(QPaintEvent *ev); //forwarded from the LNW paint event - void updateLNW(); + void updateLNW(); QFontMetrics *metrics; - + private: QWidget *LNW; //Line Number Widget bool showLNW; @@ -55,8 +56,9 @@ private: void clearMatchData(); void highlightMatch(QChar ch, bool forward, int fromPos, QChar startch); - //Flags to keep track of changes - bool hasChanges; + //Flags to keep track of changes/status + bool hasChanges, readonly; + private slots: //Functions for managing the line number widget void LNW_updateWidth(); // Tied to the QPlainTextEdit::blockCountChanged() signal @@ -68,7 +70,7 @@ private slots: void textChanged(); void cursorMoved(); //Function for prompting the user if the file changed externally - void fileChanged(); + void fileChanged(); protected: void resizeEvent(QResizeEvent *ev); diff --git a/src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro b/src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro index a9c16a0c..77cd8798 100644 --- a/src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro +++ b/src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro @@ -91,7 +91,7 @@ TRANSLATIONS = i18n/l-te_af.ts \ i18n/l-te_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-textedit.desktop desktop.path=$${L_SHAREDIR}/applications/ @@ -103,7 +103,7 @@ syntax.path=$${L_SHAREDIR}/lumina-desktop/syntax_rules syntax.files=syntax_rules/* manpage.path=$${L_MANDIR}/man1/ -manpage.extra="$${MAN_ZIP} lumina-textedit.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-textedit.1.gz" +manpage.extra="$${MAN_ZIP} $$PWD/lumina-textedit.1 > $(INSTALL_ROOT)$${L_MANDIR}/man1/lumina-textedit.1.gz" INSTALLS += target desktop link syntax manpage diff --git a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp index 53f51f4e..a80d4149 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.cpp @@ -83,6 +83,16 @@ bool SyntaxFile::supportsFile(QString file){ return false; } +bool SyntaxFile::supportsFirstLine(QString line){ + line = line.simplified(); + if(metaObj.contains("first_line_match")){ + return metaObj.value("first_line_match").toArray().contains(line); + }else if(metaObj.contains("first_line_regex")){ + return (QRegExp( metaObj.value("first_line_regex").toString() ).indexIn(line) >=0 ); + } + return false; +} + bool SyntaxFile::LoadFile(QString file, QSettings *settings){ QStringList contents = LUtils::readFile(file); //Now trim the extra non-JSON off the beginning of the file @@ -209,6 +219,13 @@ QString Custom_Syntax::ruleForFile(QString filename, QSettings *settings){ return ""; } +QString Custom_Syntax::ruleForFirstLine(QString line, QSettings *settings){ + QList<SyntaxFile> files = SyntaxFile::availableFiles(settings); + for(int i=0; i<files.length(); i++){ + if(files[i].supportsFirstLine(line)){ return files[i].name(); } + } + return ""; +} void Custom_Syntax::loadRules(QString type){ QList<SyntaxFile> files = SyntaxFile::availableFiles(settings); diff --git a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h index bffbfd1a..9949a90c 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h +++ b/src-qt5/desktop-utils/lumina-textedit/syntaxSupport.h @@ -46,6 +46,7 @@ public: void SetupDocument(QPlainTextEdit *editor); bool supportsFile(QString file); //does this syntax set support the file? + bool supportsFirstLine(QString line); //is the type of file defined by the first line of the file? ("#!/bin/<something>" for instance) //Main Loading routine (run this before other functions) bool LoadFile(QString file, QSettings *settings); @@ -66,10 +67,13 @@ public: } ~Custom_Syntax(){} + QString loadedRules(){ return syntax.name(); } + static QStringList availableRules(QSettings *settings); static QStringList knownColors(); static void SetupDefaultColors(QSettings *settings); static QString ruleForFile(QString filename, QSettings *settings); + static QString ruleForFirstLine(QString line, QSettings *settings); void loadRules(QString type); void loadRules(SyntaxFile sfile); @@ -77,6 +81,8 @@ public: loadRules( syntax.name() ); } + void setupDocument(QPlainTextEdit *edit){ syntax.SetupDocument(edit); } //simple redirect for the function in the currently-loaded rules + protected: void highlightBlock(const QString &text){ //qDebug() << "Highlight Block:" << text; @@ -159,7 +165,7 @@ protected: int last = text.length()-1; while(last>=0 && (text[last]==' ' || text[last]=='\t' ) ){ last--; } if(last < text.length()-1){ - setFormat(last+1, text.length()-1-last, fmt); + setFormat(last+1, text.length()-1-last, fmt); } } } diff --git a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/README.md b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/README.md index fa00b557..04190672 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/README.md +++ b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/README.md @@ -9,9 +9,11 @@ A small comment section may be placed at the top of the file where every line st # Requirements 1. A "meta" object containing the following variables (meta information about the rules): 1. "name" : The name that will be shown to the user for this set of syntax rules. - 2. If this syntax file is to be automatically applied to particular file type, then one of the following options must be set: + 2. If this syntax file is to be automatically applied to particular file type, then at least one of the following options must be set: 1. "file_suffix" : An array of file extensions which are supported by this syntax rule set (Example: temp.foo will be matched by "file_suffix"=["foo"] ) 2. "file_regex" : A regular expression which should be used to find if the filename matches this rule set. + 3. "first_line_match" : *(only used if no filename rules matched)* Exact match for the first line of text in the file (Example: "#!/bin/sh") + 4. "first_line_regex" : *(only used if no filename rules matched)* Regular expression to use when find a match for the first line of text in the file 2. A "format" object containing the following variables (file-wide formatting): 1. "columns_per_line" : (integer, optional) For file formats with line-length restrictions, this will automatically highlight/flag any "overage" of the designated limit. 2. "highlight_whitespace_eol" : (boolian, optional) Highlight any excess whitespace at the end of a line. diff --git a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/json.syntax b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/json.syntax index ab67d384..1982e599 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/json.syntax +++ b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/json.syntax @@ -8,7 +8,8 @@ { "meta": { "name": "JSON", - "file_suffix": ["json", "syntax"] + "file_suffix": ["json", "syntax"], + "first_line_match":["{"] }, "format": { "line_wrap": false, diff --git a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/python.syntax b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/python.syntax index 6690d98c..2145beec 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/python.syntax +++ b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/python.syntax @@ -8,7 +8,8 @@ { "meta": { "name": "Python", - "file_suffix": ["py", "pyc"] + "file_suffix": ["py", "pyc"], + "first_line_regex" : "(#!).+(python)" }, "format": { "line_wrap": false, diff --git a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/sh.syntax b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/sh.syntax index 5f38cadc..f2256731 100644 --- a/src-qt5/desktop-utils/lumina-textedit/syntax_rules/sh.syntax +++ b/src-qt5/desktop-utils/lumina-textedit/syntax_rules/sh.syntax @@ -8,7 +8,8 @@ { "meta": { "name": "Shell", - "file_suffix": ["sh"] + "file_suffix": ["sh"], + "first_line_match":["#!/bin/sh", "#!/sbin/openrc-run"] }, "format": { "line_wrap": false, diff --git a/src-qt5/experimental/lumina-screencast/lumina-screencast.pro b/src-qt5/experimental/lumina-screencast/lumina-screencast.pro index 5cfe89ef..5c6a1e76 100644 --- a/src-qt5/experimental/lumina-screencast/lumina-screencast.pro +++ b/src-qt5/experimental/lumina-screencast/lumina-screencast.pro @@ -87,7 +87,7 @@ TRANSLATIONS = i18n/l-screencast_af.ts \ i18n/l-screencast_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-screencast.desktop desktop.path=$${L_SHAREDIR}/applications/ diff --git a/src-qt5/experimental/lumina-terminal/lumina-terminal.pro b/src-qt5/experimental/lumina-terminal/lumina-terminal.pro index 7f5d979c..668a8741 100644 --- a/src-qt5/experimental/lumina-terminal/lumina-terminal.pro +++ b/src-qt5/experimental/lumina-terminal/lumina-terminal.pro @@ -91,7 +91,7 @@ TRANSLATIONS = i18n/l-terminal_af.ts \ i18n/l-terminal_zu.ts dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ -dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ +dotrans.extra=cd $$PWD/i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ desktop.files=lumina-terminal.desktop desktop.path=$${L_SHAREDIR}/applications/ 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 diff --git a/src-qt5/src-qml/test/Grav.qml b/src-qt5/src-qml/test/Grav.qml new file mode 100644 index 00000000..d7404a56 --- /dev/null +++ b/src-qt5/src-qml/test/Grav.qml @@ -0,0 +1,164 @@ +import QtQuick 2.7 +import QtQuick.Window 2.2 +import QtGraphicalEffects 1.0 + +Rectangle { + id : canvas + anchors.fill: parent + width: Screen.width + height: Screen.height + color: "black" + + //TODO Add orbital trails option + //TODO Fix jitteryness and start position + //TODO Make orbits more extreme + + //Between 5 and 15 planets, read from settings + property int planets: Math.round(( Math.random() * 10 ) + 5 ) + property int cx: Math.round(width/2) + property int cy: Math.round(height/2) + + //Create planets + Repeater { + id: planetRepeater + model: planets + + Rectangle { + id : index + parent: canvas + + //Creates random distance for elipse + property double c: Math.random() * 250 + property double b: Math.random() * 150 + c + property double a: Math.sqrt(b*b+c*c) + //Random angle of rotation + property double th: Math.random() * Math.PI + property var pathX: createPathX() + property var pathY: createPathY() + property var testArray: createTest() + + //Calculates starting position + x: Math.round(cx + a * Math.cos(th)) + y: Math.round(cy + b * Math.sin(th)) + + //Planet size between 14 and 32 pixels + width: Math.round(1.75 * (((Math.random() * 10) + 8 ))) + height: width + + //Make each rectangle look circular + radius: width / 2 + + //Give each planet a random color, semi-transparent + color: Qt.rgba(Math.random(), Math.random(), Math.random(), 0.5) + + PathAnimation on x{ + loops: Animation.Infinite + duration: 200 + path: Path { + startX: x + startY: y + PathCurve { x: pathX; y: pathY } + } + } + + NumberAnimation { + + } + + function createTest() { + var test = [] + for(var i = 1; i <= 200; i++) { + test.push(PathCurve { x: pathX[i]; y: pathY[i] }) + } + return test + } + + function createPathX() { + var pathX = [] + for(var i = 1; i <= 200; i++) { + pathX.push(cx+a*Math.cos(2*Math.PI*(i/200.0))*Math.cos(th) - b*Math.sin(2*Math.PI*(i/200.0))*Math.sin(th)) + } + return pathX + } + + function createPathY() { + var pathY = [] + for(var i = 1; i <= 200; i++) { + pathY.push(cy+a*Math.cos(2*Math.PI*(i/200.0))*Math.sin(th) + b*Math.sin(2*Math.PI*(i/200.0))*Math.cos(th)) + } + return pathY + } + + /*Timer { + //Each planet updates between 1ms and 51ms (smaller times=faster) + interval: Math.round(Math.random() * 50 ) + 1 + repeat: true + running: true + property int time: 0 + + onTriggered: { + //Parametric equation that calculates the position of the general ellipse. Completes a loop ever 314 cycles. Credit to + x = cx+a*Math.cos(2*Math.PI*(time/314.0))*Math.cos(th) - b*Math.sin(2*Math.PI*(time/314.0))*Math.sin(th) + y = cy+a*Math.cos(2*Math.PI*(time/314.0))*Math.sin(th) + b*Math.sin(2*Math.PI*(time/314.0))*Math.cos(th) + time++; + + //Move a planet 80 pixels away from the sun if the planet is too close + if(x > cx && Math.abs(cx-x) < 80) { + x+=80 + }else if(x < cx && Math.abs(cx-x) < 80) { + x-=80 + } + + if(y > cy && Math.abs(cy-y) < 80) { + y+=80 + }else if(y < cy && Math.abs(cy-y) < 80) { + y-=80 + } + } + }*/ + } + } + + //Create the star + Rectangle{ + id: star + parent: canvas + + //Centers in star in the center of the canvas, with an offset to center the animation + x: cx - 30 + y: cy - 30 + + width: 60 + height: width + + //Create the wobble animation + SequentialAnimation on height { + loops: Animation.Infinite + PropertyAnimation { duration: 2000; to: 90 } + PropertyAnimation { duration: 2000; to: 60 } + } + + SequentialAnimation on width { + loops: Animation.Infinite + PropertyAnimation { duration: 2000; to: 90 } + PropertyAnimation { duration: 2000; to: 60 } + } + + color: "black" + radius: width / 2 + + //Creates a radial gradient to make the star look cool + RadialGradient { + anchors.fill: parent + gradient: Gradient { + GradientStop { position:0 ;color: Qt.rgba(0,0,0,0)} + GradientStop { position:0.18 ;color: Qt.rgba(0,0,0,0)} + GradientStop { position:0.2 ;color: Qt.rgba(0.32,0.47,0.30,0.13)} + GradientStop { position:0.3 ;color: Qt.rgba(0.62,0.92,0.58,0.25)} + GradientStop { position:0.4 ;color: Qt.rgba(1.00,0.93,0.59,0.51)} + GradientStop { position:0.5 ;color: Qt.rgba(0,0,0,0)} + } + } + + } +} diff --git a/src-qt5/src-qml/test/Test.qml b/src-qt5/src-qml/test/Test.qml new file mode 100644 index 00000000..a2407b6c --- /dev/null +++ b/src-qt5/src-qml/test/Test.qml @@ -0,0 +1,7 @@ +import QtQuick 2.7 + +Rectangle { + id : canvas + anchors.fill: parent + color: "black" +} |