diff --git a/.travis.yml b/.travis.yml index a2047b0..5615fd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,33 @@ sudo: required dist: trusty -install: - - sudo apt-add-repository -y ppa:kubuntu-ppa/backports +language: cpp +os: + - linux + +before_install: + - sudo sed -i 's/trusty/wily/g' /etc/apt/sources.list - sudo apt-get update -qq - - sudo apt-get -y -q -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew dist-upgrade - - sudo apt-get install -y -q cmake extra-cmake-modules g++ git libkf5i18n-dev libkf5notifications-dev libkf5service-dev libkf5windowsystem-dev plasma-framework-dev qtbase5-dev qtdeclarative5-dev + - sudo apt-get upgrade + +addons: + apt: + sources: + - kubuntu-backports + packages: + - cmake + - extra-cmake-modules + - g++ + - git + - libkf5i18n-dev + - libkf5notifications-dev + - libkf5service-dev + - libkf5windowsystem-dev + - plasma-framework-dev + - qtbase5-dev + - qtdeclarative5-dev + +before_script: - rm -rf build - mkdir build diff --git a/sources/CMakeLists.txt b/sources/CMakeLists.txt index bc96fb9..1ff1734 100644 --- a/sources/CMakeLists.txt +++ b/sources/CMakeLists.txt @@ -41,14 +41,14 @@ set(CPPCHECK_EXECUTABLE "/usr/bin/cppcheck" CACHE STRING "Path to cppcheck execu # flags if (CMAKE_COMPILER_IS_GNUCXX) - set(CMAKE_CXX_FLAGS "-Wall -Wno-cpp -std=c++11") + set(CMAKE_CXX_FLAGS "-Wall -Wno-cpp -std=c++14") set(CMAKE_CXX_FLAGS_DEBUG "-g -O0") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") set(CMAKE_CXX_FLAGS_OPTIMIZATION "-Ofast -DNDEBUG") # avoid newer gcc warnings add_definitions(-D_DEFAULT_SOURCE) elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -stdlib=libc++") + set(CMAKE_CXX_FLAGS "-Wall -std=c++14 -stdlib=libc++") set(CMAKE_CXX_FLAGS_DEBUG "-g -O0") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") set(CMAKE_CXX_FLAGS_OPTIMIZATION "-Ofast -DNDEBUG") diff --git a/sources/awesome-widget/plugin/awactions.cpp b/sources/awesome-widget/plugin/awactions.cpp index 399219b..8ac7a4d 100644 --- a/sources/awesome-widget/plugin/awactions.cpp +++ b/sources/awesome-widget/plugin/awactions.cpp @@ -235,12 +235,12 @@ void AWActions::versionReplyRecieved(QNetworkReply *reply, QJsonParseError error; QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error); - reply->deleteLater(); if ((reply->error() != QNetworkReply::NoError) || (error.error != QJsonParseError::NoError)) { qCWarning(LOG_AW) << "Parse error" << error.errorString(); return; } + reply->deleteLater(); // convert to map QVariantMap firstRelease = jsonDoc.toVariant().toList().first().toMap(); @@ -252,9 +252,9 @@ void AWActions::versionReplyRecieved(QNetworkReply *reply, int old_major = QString(VERSION).split(QChar('.')).at(0).toInt(); int old_minor = QString(VERSION).split(QChar('.')).at(1).toInt(); int old_patch = QString(VERSION).split(QChar('.')).at(2).toInt(); - int new_major = QString(version).split(QChar('.')).at(0).toInt(); - int new_minor = QString(version).split(QChar('.')).at(1).toInt(); - int new_patch = QString(version).split(QChar('.')).at(2).toInt(); + int new_major = version.split(QChar('.')).at(0).toInt(); + int new_minor = version.split(QChar('.')).at(1).toInt(); + int new_patch = version.split(QChar('.')).at(2).toInt(); if ((old_major < new_major) || ((old_major == new_major) && (old_minor < new_minor)) || ((old_major == new_major) && (old_minor == new_minor) diff --git a/sources/awesome-widget/plugin/awkeycache.cpp b/sources/awesome-widget/plugin/awkeycache.cpp new file mode 100644 index 0000000..6d3e45a --- /dev/null +++ b/sources/awesome-widget/plugin/awkeycache.cpp @@ -0,0 +1,101 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets is free software: you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + +#include "awkeycache.h" + +#include +#include +#include +#include +#include + +#include "awdebug.h" + + +void AWKeyCache::addKeyToCache(const QString type, const QString key) +{ + qCDebug(LOG_AW) << "Key type" << type; + qCDebug(LOG_AW) << "Key" << key; + + QString fileName = QString("%1/awesomewidgets.ndx") + .arg(QStandardPaths::writableLocation( + QStandardPaths::GenericCacheLocation)); + qCInfo(LOG_AW) << "Cache file" << fileName; + QSettings cache(fileName, QSettings::IniFormat); + + cache.beginGroup(type); + QStringList cachedValues; + for (auto key : cache.allKeys()) + cachedValues.append(cache.value(key).toString()); + + if (type == QString("hdd")) { + QStringList allDevices + = QDir(QString("/dev")).entryList(QDir::System, QDir::Name); + QStringList devices + = allDevices.filter(QRegExp(QString("^[hms]d[a-z]$"))); + for (auto dev : devices) { + QString device = QString("/dev/%1").arg(dev); + if (cachedValues.contains(device)) + continue; + qCInfo(LOG_AW) << "Found new key" << device << "for type" << type; + cache.setValue( + QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), + device); + } + } else if (type == QString("net")) { + QList rawInterfaceList + = QNetworkInterface::allInterfaces(); + for (auto interface : rawInterfaceList) { + QString device = interface.name(); + if (cachedValues.contains(device)) + continue; + qCInfo(LOG_AW) << "Found new key" << device << "for type" << type; + cache.setValue( + QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), + device); + } + } else { + if (cachedValues.contains(key)) + return; + qCInfo(LOG_AW) << "Found new key" << key << "for type" << type; + cache.setValue( + QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), key); + } + cache.endGroup(); + + cache.sync(); +} + + +QHash AWKeyCache::loadKeysFromCache() +{ + QString fileName = QString("%1/awesomewidgets.ndx") + .arg(QStandardPaths::writableLocation( + QStandardPaths::GenericCacheLocation)); + qCInfo(LOG_AW) << "Cache file" << fileName; + QSettings cache(fileName, QSettings::IniFormat); + + QHash devices; + for (auto group : cache.childGroups()) { + cache.beginGroup(group); + for (auto key : cache.allKeys()) + devices[group].append(cache.value(key).toString()); + cache.endGroup(); + } + + return devices; +} diff --git a/sources/awesome-widget/plugin/awkeycache.h b/sources/awesome-widget/plugin/awkeycache.h new file mode 100644 index 0000000..040a43e --- /dev/null +++ b/sources/awesome-widget/plugin/awkeycache.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets is free software: you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + + +#ifndef AWKEYCACHE_H +#define AWKEYCACHE_H + +#include +#include + + +namespace AWKeyCache +{ +void addKeyToCache(const QString type, const QString key = QString("")); +QHash loadKeysFromCache(); +}; + + +#endif /* AWKEYCACHE_H */ diff --git a/sources/awesome-widget/plugin/awkeyoperations.cpp b/sources/awesome-widget/plugin/awkeyoperations.cpp new file mode 100644 index 0000000..e1210da --- /dev/null +++ b/sources/awesome-widget/plugin/awkeyoperations.cpp @@ -0,0 +1,412 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets is free software: you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + +#include "awkeyoperations.h" + +#include +#include +#include +#include + +#include "awdebug.h" +#include "awkeycache.h" +#include "awpatternfunctions.h" +#include "version.h" +// extensions +#include "extquotes.h" +#include "extscript.h" +#include "extupgrade.h" +#include "extweather.h" +#include "graphicalitem.h" + + +AWKeyOperations::AWKeyOperations(QObject *parent) + : QObject(parent) +{ + qCDebug(LOG_AW) << __PRETTY_FUNCTION__; +} + + +AWKeyOperations::~AWKeyOperations() +{ + qCDebug(LOG_AW) << __PRETTY_FUNCTION__; + + // extensions + delete graphicalItems; + delete extQuotes; + delete extScripts; + delete extUpgrade; + delete extWeather; +} + + +void AWKeyOperations::addDevice(const QString source) +{ + qCDebug(LOG_AW) << "Source" << source; + + QRegExp diskRegexp + = QRegExp(QString("disk/(?:md|sd|hd)[a-z|0-9]_.*/Rate/(?:rblk)")); + QRegExp mountRegexp = QRegExp(QString("partitions/.*/filllevel")); + + if (source.contains(diskRegexp)) { + QString device = source; + device.remove(QString("/Rate/rblk")); + addKeyToCache(QString("disk"), device); + } else if (source.contains(mountRegexp)) { + QString device = source; + device.remove(QString("partitions")).remove(QString("/filllevel")); + addKeyToCache(QString("mount"), device); + } else if (source.startsWith(QString("lmsensors"))) { + addKeyToCache(QString("temp"), source); + } +} + + +QStringList AWKeyOperations::devices(const QString type) const +{ + qCDebug(LOG_AW) << "Looking for type" << type; + + return m_devices[type]; +} + + +QHash AWKeyOperations::devices() const +{ + return m_devices; +} + + +void AWKeyOperations::updateCache() +{ + // update network and hdd list + addKeyToCache(QString("hdd")); + addKeyToCache(QString("net")); +} + + +QStringList AWKeyOperations::dictKeys() const +{ + QStringList allKeys; + // weather + for (int i = extWeather->activeItems().count() - 1; i >= 0; i--) { + allKeys.append( + extWeather->activeItems().at(i)->tag(QString("weatherId"))); + allKeys.append( + extWeather->activeItems().at(i)->tag(QString("weather"))); + allKeys.append( + extWeather->activeItems().at(i)->tag(QString("humidity"))); + allKeys.append( + extWeather->activeItems().at(i)->tag(QString("pressure"))); + allKeys.append( + extWeather->activeItems().at(i)->tag(QString("temperature"))); + allKeys.append( + extWeather->activeItems().at(i)->tag(QString("timestamp"))); + } + // time + allKeys.append(QString("time")); + allKeys.append(QString("isotime")); + allKeys.append(QString("shorttime")); + allKeys.append(QString("longtime")); + allKeys.append(QString("ctime")); + // uptime + allKeys.append(QString("uptime")); + allKeys.append(QString("cuptime")); + // cpuclock & cpu + for (int i = QThread::idealThreadCount() - 1; i >= 0; i--) { + allKeys.append(QString("cpucl%1").arg(i)); + allKeys.append(QString("cpu%1").arg(i)); + } + allKeys.append(QString("cpucl")); + allKeys.append(QString("cpu")); + // temperature + for (int i = m_devices[QString("temp")].count() - 1; i >= 0; i--) + allKeys.append(QString("temp%1").arg(i)); + // gputemp + allKeys.append(QString("gputemp")); + // gpu + allKeys.append(QString("gpu")); + // memory + allKeys.append(QString("memmb")); + allKeys.append(QString("memgb")); + allKeys.append(QString("memfreemb")); + allKeys.append(QString("memfreegb")); + allKeys.append(QString("memtotmb")); + allKeys.append(QString("memtotgb")); + allKeys.append(QString("memusedmb")); + allKeys.append(QString("memusedgb")); + allKeys.append(QString("mem")); + // swap + allKeys.append(QString("swapmb")); + allKeys.append(QString("swapgb")); + allKeys.append(QString("swapfreemb")); + allKeys.append(QString("swapfreegb")); + allKeys.append(QString("swaptotmb")); + allKeys.append(QString("swaptotgb")); + allKeys.append(QString("swap")); + // hdd + for (int i = m_devices[QString("mount")].count() - 1; i >= 0; i--) { + allKeys.append(QString("hddmb%1").arg(i)); + allKeys.append(QString("hddgb%1").arg(i)); + allKeys.append(QString("hddfreemb%1").arg(i)); + allKeys.append(QString("hddfreegb%1").arg(i)); + allKeys.append(QString("hddtotmb%1").arg(i)); + allKeys.append(QString("hddtotgb%1").arg(i)); + allKeys.append(QString("hdd%1").arg(i)); + } + // hdd speed + for (int i = m_devices[QString("disk")].count() - 1; i >= 0; i--) { + allKeys.append(QString("hddr%1").arg(i)); + allKeys.append(QString("hddw%1").arg(i)); + } + // hdd temp + for (int i = m_devices[QString("hdd")].count() - 1; i >= 0; i--) + allKeys.append(QString("hddtemp%1").arg(i)); + // network + for (int i = m_devices[QString("net")].count() - 1; i >= 0; i--) { + allKeys.append(QString("downunits%1").arg(i)); + allKeys.append(QString("upunits%1").arg(i)); + allKeys.append(QString("downkb%1").arg(i)); + allKeys.append(QString("down%1").arg(i)); + allKeys.append(QString("upkb%1").arg(i)); + allKeys.append(QString("up%1").arg(i)); + } + allKeys.append(QString("downunits")); + allKeys.append(QString("upunits")); + allKeys.append(QString("downkb")); + allKeys.append(QString("down")); + allKeys.append(QString("upkb")); + allKeys.append(QString("up")); + allKeys.append(QString("netdev")); + // battery + allKeys.append(QString("ac")); + QStringList allBatteryDevices + = QDir(QString("/sys/class/power_supply")) + .entryList(QStringList() << QString("BAT*"), + QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + for (int i = allBatteryDevices.count() - 1; i >= 0; i--) + allKeys.append(QString("bat%1").arg(i)); + allKeys.append(QString("bat")); + // player + allKeys.append(QString("album")); + allKeys.append(QString("artist")); + allKeys.append(QString("duration")); + allKeys.append(QString("progress")); + allKeys.append(QString("title")); + allKeys.append(QString("dalbum")); + allKeys.append(QString("dartist")); + allKeys.append(QString("dtitle")); + allKeys.append(QString("salbum")); + allKeys.append(QString("sartist")); + allKeys.append(QString("stitle")); + // ps + allKeys.append(QString("pscount")); + allKeys.append(QString("pstotal")); + allKeys.append(QString("ps")); + // package manager + for (int i = extUpgrade->activeItems().count() - 1; i >= 0; i--) + allKeys.append( + extUpgrade->activeItems().at(i)->tag(QString("pkgcount"))); + // quotes + for (int i = extQuotes->activeItems().count() - 1; i >= 0; i--) { + allKeys.append(extQuotes->activeItems().at(i)->tag(QString("ask"))); + allKeys.append(extQuotes->activeItems().at(i)->tag(QString("askchg"))); + allKeys.append( + extQuotes->activeItems().at(i)->tag(QString("percaskchg"))); + allKeys.append(extQuotes->activeItems().at(i)->tag(QString("bid"))); + allKeys.append(extQuotes->activeItems().at(i)->tag(QString("bidchg"))); + allKeys.append( + extQuotes->activeItems().at(i)->tag(QString("percbidchg"))); + allKeys.append(extQuotes->activeItems().at(i)->tag(QString("price"))); + allKeys.append( + extQuotes->activeItems().at(i)->tag(QString("pricechg"))); + allKeys.append( + extQuotes->activeItems().at(i)->tag(QString("percpricechg"))); + } + // custom + for (int i = extScripts->activeItems().count() - 1; i >= 0; i--) + allKeys.append(extScripts->activeItems().at(i)->tag(QString("custom"))); + // desktop + allKeys.append(QString("desktop")); + allKeys.append(QString("ndesktop")); + allKeys.append(QString("tdesktops")); + // load average + allKeys.append(QString("la15")); + allKeys.append(QString("la5")); + allKeys.append(QString("la1")); + // bars + QStringList graphicalItemsKeys; + for (auto item : graphicalItems->items()) + graphicalItemsKeys.append(item->tag()); + graphicalItemsKeys.sort(); + for (int i = graphicalItemsKeys.count() - 1; i >= 0; i--) + allKeys.append(graphicalItemsKeys.at(i)); + + return allKeys; +} + + +GraphicalItem *AWKeyOperations::giByKey(const QString key) const +{ + qCDebug(LOG_AW) << "Looking for item" << key; + + return graphicalItems->itemByTag(key); +} + + +QString AWKeyOperations::infoByKey(QString key) const +{ + qCDebug(LOG_AW) << "Requested key" << key; + + key.remove(QRegExp(QString("^bar[0-9]{1,}"))); + if (key.startsWith(QString("custom"))) + return extScripts->itemByTagNumber( + key.remove(QString("custom")).toInt()) + ->uniq(); + else if (key.contains(QRegExp(QString("^hdd[rw]")))) + return QString("%1").arg(m_devices[QString( + "disk")][key.remove(QRegExp(QString("hdd[rw]"))).toInt()]); + else if (key.contains(QRegExp( + QString("^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)")))) + return QString("%1").arg(m_devices[QString( + "mount")][key + .remove(QRegExp(QString( + "^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)"))) + .toInt()]); + else if (key.startsWith(QString("hddtemp"))) + return QString("%1").arg( + m_devices[QString("hdd")][key.remove(QString("hddtemp")).toInt()]); + else if (key.contains(QRegExp(QString("^(down|up)[0-9]")))) + return QString("%1").arg(m_devices[QString( + "net")][key.remove(QRegExp(QString("^(down|up)"))).toInt()]); + else if (key.startsWith(QString("pkgcount"))) + return extUpgrade->itemByTagNumber( + key.remove(QString("pkgcount")).toInt()) + ->uniq(); + else if (key.contains(QRegExp(QString("(^|perc)(ask|bid|price)(chg|)")))) + return extQuotes->itemByTagNumber( + key.remove(QRegExp(QString( + "(^|perc)(ask|bid|price)(chg|)"))) + .toInt()) + ->uniq(); + else if (key.contains(QRegExp( + QString("(weather|weatherId|humidity|pressure|temperature)")))) + return extWeather + ->itemByTagNumber( + key + .remove(QRegExp(QString( + "(weather|weatherId|humidity|pressure|temperature)"))) + .toInt()) + ->uniq(); + else if (key.startsWith(QString("temp"))) + return QString("%1").arg( + m_devices[QString("temp")][key.remove(QString("temp")).toInt()]); + + return QString("(none)"); +} + + +QString AWKeyOperations::pattern() const +{ + return m_pattern; +} + + +void AWKeyOperations::setPattern(const QString currentPattern) +{ + qCDebug(LOG_AW) << "Set pattern" << currentPattern; + + m_pattern = currentPattern; +} + + +void AWKeyOperations::editItem(const QString type) +{ + qCDebug(LOG_AW) << "Item type" << type; + + if (type == QString("graphicalitem")) { + QStringList keys = dictKeys().filter(QRegExp( + QString("^(cpu(?!cl).*|gpu$|mem$|swap$|hdd[0-9].*|bat.*)"))); + keys.sort(); + graphicalItems->setConfigArgs(keys); + return graphicalItems->editItems(); + } else if (type == QString("extquotes")) { + return extQuotes->editItems(); + } else if (type == QString("extscript")) { + return extScripts->editItems(); + } else if (type == QString("extupgrade")) { + return extUpgrade->editItems(); + } else if (type == QString("extweather")) { + return extWeather->editItems(); + } +} + + +void AWKeyOperations::addKeyToCache(const QString type, const QString key) +{ + qCDebug(LOG_AW) << "Key type" << type; + qCDebug(LOG_AW) << "Key" << key; + + AWKeyCache::addKeyToCache(type, key); + m_devices = AWKeyCache::loadKeysFromCache(); + reinitKeys(); +} + + +void AWKeyOperations::reinitKeys() +{ + // renew extensions + // delete them if any + delete graphicalItems; + graphicalItems = nullptr; + delete extQuotes; + extQuotes = nullptr; + delete extScripts; + extScripts = nullptr; + delete extUpgrade; + extUpgrade = nullptr; + delete extWeather; + extWeather = nullptr; + // create + graphicalItems + = new ExtItemAggregator(nullptr, QString("desktops")); + extQuotes = new ExtItemAggregator(nullptr, QString("quotes")); + extScripts = new ExtItemAggregator(nullptr, QString("scripts")); + extUpgrade = new ExtItemAggregator(nullptr, QString("upgrade")); + extWeather = new ExtItemAggregator(nullptr, QString("weather")); + + // init + QStringList allKeys = dictKeys(); + +#ifdef BUILD_TESTING + // not documented feature - place all available tags + m_pattern = m_pattern.replace(QString("$ALL"), [allKeys]() { + QStringList strings; + for (auto tag : allKeys) + strings.append(QString("%1: $%1").arg(tag)); + return strings.join(QString(" | ")); + }()); +#endif /* BUILD_TESTING */ + + // apply aw_* functions + m_pattern = AWPatternFunctions::insertKeyCount(m_pattern, allKeys); + m_pattern = AWPatternFunctions::insertKeyNames(m_pattern, allKeys); + m_pattern = AWPatternFunctions::insertKeys(m_pattern, allKeys); + // wrap templates + m_pattern = AWPatternFunctions::expandTemplates(m_pattern); + + emit(updateKeys(allKeys)); +} diff --git a/sources/awesome-widget/plugin/awkeyoperations.h b/sources/awesome-widget/plugin/awkeyoperations.h new file mode 100644 index 0000000..8510914 --- /dev/null +++ b/sources/awesome-widget/plugin/awkeyoperations.h @@ -0,0 +1,81 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets is free software: you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + + +#ifndef AWKEYOPERATIONS_H +#define AWKEYOPERATIONS_H + +#include + +#include +#include + +#include "extitemaggregator.h" + + +class AWDataAggregator; +class AWDataEngineAggregator; +class AWKeysAggregator; +class ExtQuotes; +class ExtScript; +class ExtUpgrade; +class ExtWeather; +class GraphicalItem; +class QThreadPool; + +class AWKeyOperations : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString pattern READ pattern WRITE setPattern) + +public: + explicit AWKeyOperations(QObject *parent = nullptr); + virtual ~AWKeyOperations(); + void addDevice(const QString source); + QStringList devices(const QString type) const; + QHash devices() const; + void updateCache(); + // keys + QStringList dictKeys() const; + GraphicalItem *giByKey(const QString key) const; + // values + QString infoByKey(QString key) const; + QString pattern() const; + void setPattern(const QString currentPattern); + // configuration + void editItem(const QString type); + +signals: + void updateKeys(const QStringList currentKeys); + +private: + // methods + void addKeyToCache(const QString type, const QString key = QString("")); + void reinitKeys(); + // objects + ExtItemAggregator *graphicalItems = nullptr; + ExtItemAggregator *extQuotes = nullptr; + ExtItemAggregator *extScripts = nullptr; + ExtItemAggregator *extUpgrade = nullptr; + ExtItemAggregator *extWeather = nullptr; + // variables + QHash m_devices; + QString m_pattern; +}; + + +#endif /* AWKEYOPERATIONS_H */ diff --git a/sources/awesome-widget/plugin/awkeys.cpp b/sources/awesome-widget/plugin/awkeys.cpp index 8a87bd6..f329c71 100644 --- a/sources/awesome-widget/plugin/awkeys.cpp +++ b/sources/awesome-widget/plugin/awkeys.cpp @@ -18,23 +18,15 @@ #include "awkeys.h" #include -#include -#include #include -#include #include -#include -#include #include #include "awdataaggregator.h" #include "awdataengineaggregator.h" #include "awdebug.h" +#include "awkeyoperations.h" #include "awkeysaggregator.h" -#include "extquotes.h" -#include "extscript.h" -#include "extupgrade.h" -#include "extweather.h" #include "graphicalitem.h" #include "version.h" @@ -52,6 +44,10 @@ AWKeys::AWKeys(QObject *parent) aggregator = new AWKeysAggregator(this); dataAggregator = new AWDataAggregator(this); + keyOperator = new AWKeyOperations(this); + // update key data if required + connect(keyOperator, SIGNAL(updateKeys(QStringList)), this, + SLOT(reinitKeys(QStringList))); // transfer signal from AWDataAggregator object to QML ui connect(dataAggregator, SIGNAL(toolTipPainted(const QString)), this, SIGNAL(needToolTipToBeUpdated(const QString))); @@ -63,18 +59,12 @@ AWKeys::~AWKeys() { qCDebug(LOG_AW) << __PRETTY_FUNCTION__; - // extensions - delete graphicalItems; - delete extQuotes; - delete extScripts; - delete extUpgrade; - delete extWeather; - // core delete dataEngineAggregator; delete m_threadPool; delete aggregator; delete dataAggregator; + delete keyOperator; } @@ -94,7 +84,7 @@ void AWKeys::initKeys(const QString currentPattern, const int interval, qCDebug(LOG_AW) << "Queue limit" << limit; // init - m_pattern = currentPattern; + keyOperator->setPattern(currentPattern); if (dataEngineAggregator == nullptr) { dataEngineAggregator = new AWDataEngineAggregator(this, interval); connect(this, SIGNAL(dropSourceFromDataengine(QString)), @@ -103,7 +93,7 @@ void AWKeys::initKeys(const QString currentPattern, const int interval, dataEngineAggregator->setInterval(interval); m_threadPool->setMaxThreadCount(limit == 0 ? QThread::idealThreadCount() : limit); - updateCache(); + keyOperator->updateCache(); return dataEngineAggregator->reconnectSources(); } @@ -128,9 +118,7 @@ void AWKeys::setWrapNewLines(const bool wrap) void AWKeys::updateCache() { - // update network and hdd list - addKeyToCache(QString("hdd")); - addKeyToCache(QString("net")); + return keyOperator->updateCache(); } @@ -139,161 +127,7 @@ QStringList AWKeys::dictKeys(const bool sorted, const QString regexp) const qCDebug(LOG_AW) << "Should be sorted" << sorted; qCDebug(LOG_AW) << "Filter" << regexp; - QStringList allKeys; - // weather - for (int i = extWeather->activeItems().count() - 1; i >= 0; i--) { - allKeys.append( - extWeather->activeItems().at(i)->tag(QString("weatherId"))); - allKeys.append( - extWeather->activeItems().at(i)->tag(QString("weather"))); - allKeys.append( - extWeather->activeItems().at(i)->tag(QString("humidity"))); - allKeys.append( - extWeather->activeItems().at(i)->tag(QString("pressure"))); - allKeys.append( - extWeather->activeItems().at(i)->tag(QString("temperature"))); - allKeys.append( - extWeather->activeItems().at(i)->tag(QString("timestamp"))); - } - // time - allKeys.append(QString("time")); - allKeys.append(QString("isotime")); - allKeys.append(QString("shorttime")); - allKeys.append(QString("longtime")); - allKeys.append(QString("ctime")); - // uptime - allKeys.append(QString("uptime")); - allKeys.append(QString("cuptime")); - // cpuclock & cpu - for (int i = QThread::idealThreadCount() - 1; i >= 0; i--) { - allKeys.append(QString("cpucl%1").arg(i)); - allKeys.append(QString("cpu%1").arg(i)); - } - allKeys.append(QString("cpucl")); - allKeys.append(QString("cpu")); - // temperature - for (int i = m_devices[QString("temp")].count() - 1; i >= 0; i--) - allKeys.append(QString("temp%1").arg(i)); - // gputemp - allKeys.append(QString("gputemp")); - // gpu - allKeys.append(QString("gpu")); - // memory - allKeys.append(QString("memmb")); - allKeys.append(QString("memgb")); - allKeys.append(QString("memfreemb")); - allKeys.append(QString("memfreegb")); - allKeys.append(QString("memtotmb")); - allKeys.append(QString("memtotgb")); - allKeys.append(QString("memusedmb")); - allKeys.append(QString("memusedgb")); - allKeys.append(QString("mem")); - // swap - allKeys.append(QString("swapmb")); - allKeys.append(QString("swapgb")); - allKeys.append(QString("swapfreemb")); - allKeys.append(QString("swapfreegb")); - allKeys.append(QString("swaptotmb")); - allKeys.append(QString("swaptotgb")); - allKeys.append(QString("swap")); - // hdd - for (int i = m_devices[QString("mount")].count() - 1; i >= 0; i--) { - allKeys.append(QString("hddmb%1").arg(i)); - allKeys.append(QString("hddgb%1").arg(i)); - allKeys.append(QString("hddfreemb%1").arg(i)); - allKeys.append(QString("hddfreegb%1").arg(i)); - allKeys.append(QString("hddtotmb%1").arg(i)); - allKeys.append(QString("hddtotgb%1").arg(i)); - allKeys.append(QString("hdd%1").arg(i)); - } - // hdd speed - for (int i = m_devices[QString("disk")].count() - 1; i >= 0; i--) { - allKeys.append(QString("hddr%1").arg(i)); - allKeys.append(QString("hddw%1").arg(i)); - } - // hdd temp - for (int i = m_devices[QString("hdd")].count() - 1; i >= 0; i--) - allKeys.append(QString("hddtemp%1").arg(i)); - // network - for (int i = m_devices[QString("net")].count() - 1; i >= 0; i--) { - allKeys.append(QString("downunits%1").arg(i)); - allKeys.append(QString("upunits%1").arg(i)); - allKeys.append(QString("downkb%1").arg(i)); - allKeys.append(QString("down%1").arg(i)); - allKeys.append(QString("upkb%1").arg(i)); - allKeys.append(QString("up%1").arg(i)); - } - allKeys.append(QString("downunits")); - allKeys.append(QString("upunits")); - allKeys.append(QString("downkb")); - allKeys.append(QString("down")); - allKeys.append(QString("upkb")); - allKeys.append(QString("up")); - allKeys.append(QString("netdev")); - // battery - allKeys.append(QString("ac")); - QStringList allBatteryDevices - = QDir(QString("/sys/class/power_supply")) - .entryList(QStringList() << QString("BAT*"), - QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); - for (int i = allBatteryDevices.count() - 1; i >= 0; i--) - allKeys.append(QString("bat%1").arg(i)); - allKeys.append(QString("bat")); - // player - allKeys.append(QString("album")); - allKeys.append(QString("artist")); - allKeys.append(QString("duration")); - allKeys.append(QString("progress")); - allKeys.append(QString("title")); - allKeys.append(QString("dalbum")); - allKeys.append(QString("dartist")); - allKeys.append(QString("dtitle")); - allKeys.append(QString("salbum")); - allKeys.append(QString("sartist")); - allKeys.append(QString("stitle")); - // ps - allKeys.append(QString("pscount")); - allKeys.append(QString("pstotal")); - allKeys.append(QString("ps")); - // package manager - for (int i = extUpgrade->activeItems().count() - 1; i >= 0; i--) - allKeys.append( - extUpgrade->activeItems().at(i)->tag(QString("pkgcount"))); - // quotes - for (int i = extQuotes->activeItems().count() - 1; i >= 0; i--) { - allKeys.append(extQuotes->activeItems().at(i)->tag(QString("ask"))); - allKeys.append(extQuotes->activeItems().at(i)->tag(QString("askchg"))); - allKeys.append( - extQuotes->activeItems().at(i)->tag(QString("percaskchg"))); - allKeys.append(extQuotes->activeItems().at(i)->tag(QString("bid"))); - allKeys.append(extQuotes->activeItems().at(i)->tag(QString("bidchg"))); - allKeys.append( - extQuotes->activeItems().at(i)->tag(QString("percbidchg"))); - allKeys.append(extQuotes->activeItems().at(i)->tag(QString("price"))); - allKeys.append( - extQuotes->activeItems().at(i)->tag(QString("pricechg"))); - allKeys.append( - extQuotes->activeItems().at(i)->tag(QString("percpricechg"))); - } - // custom - for (int i = extScripts->activeItems().count() - 1; i >= 0; i--) - allKeys.append(extScripts->activeItems().at(i)->tag(QString("custom"))); - // desktop - allKeys.append(QString("desktop")); - allKeys.append(QString("ndesktop")); - allKeys.append(QString("tdesktops")); - // load average - allKeys.append(QString("la15")); - allKeys.append(QString("la5")); - allKeys.append(QString("la1")); - // bars - QStringList graphicalItemsKeys; - for (auto item : graphicalItems->items()) - graphicalItemsKeys.append(item->tag()); - graphicalItemsKeys.sort(); - for (int i = graphicalItemsKeys.count() - 1; i >= 0; i--) - allKeys.append(graphicalItemsKeys.at(i)); - + QStringList allKeys = keyOperator->dictKeys(); // sort if required if (sorted) allKeys.sort(); @@ -304,7 +138,7 @@ QStringList AWKeys::dictKeys(const bool sorted, const QString regexp) const QStringList AWKeys::getHddDevices() const { - QStringList devices = m_devices[QString("hdd")]; + QStringList devices = keyOperator->devices(QString("hdd")); // required by selector in the UI devices.insert(0, QString("disable")); devices.insert(0, QString("auto")); @@ -317,51 +151,7 @@ QString AWKeys::infoByKey(QString key) const { qCDebug(LOG_AW) << "Requested key" << key; - key.remove(QRegExp(QString("^bar[0-9]{1,}"))); - if (key.startsWith(QString("custom"))) - return extScripts->itemByTagNumber( - key.remove(QString("custom")).toInt()) - ->uniq(); - else if (key.contains(QRegExp(QString("^hdd[rw]")))) - return QString("%1").arg(m_devices[QString( - "disk")][key.remove(QRegExp(QString("hdd[rw]"))).toInt()]); - else if (key.contains(QRegExp( - QString("^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)")))) - return QString("%1").arg(m_devices[QString( - "mount")][key - .remove(QRegExp(QString( - "^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)"))) - .toInt()]); - else if (key.startsWith(QString("hddtemp"))) - return QString("%1").arg( - m_devices[QString("hdd")][key.remove(QString("hddtemp")).toInt()]); - else if (key.contains(QRegExp(QString("^(down|up)[0-9]")))) - return QString("%1").arg(m_devices[QString( - "net")][key.remove(QRegExp(QString("^(down|up)"))).toInt()]); - else if (key.startsWith(QString("pkgcount"))) - return extUpgrade->itemByTagNumber( - key.remove(QString("pkgcount")).toInt()) - ->uniq(); - else if (key.contains(QRegExp(QString("(^|perc)(ask|bid|price)(chg|)")))) - return extQuotes->itemByTagNumber( - key.remove(QRegExp(QString( - "(^|perc)(ask|bid|price)(chg|)"))) - .toInt()) - ->uniq(); - else if (key.contains(QRegExp( - QString("(weather|weatherId|humidity|pressure|temperature)")))) - return extWeather - ->itemByTagNumber( - key - .remove(QRegExp(QString( - "(weather|weatherId|humidity|pressure|temperature)"))) - .toInt()) - ->uniq(); - else if (key.startsWith(QString("temp"))) - return QString("%1").arg( - m_devices[QString("temp")][key.remove(QString("temp")).toInt()]); - - return QString("(none)"); + return keyOperator->infoByKey(key); } @@ -379,19 +169,7 @@ void AWKeys::editItem(const QString type) { qCDebug(LOG_AW) << "Item type" << type; - if (type == QString("graphicalitem")) { - graphicalItems->setConfigArgs(dictKeys( - true, QString("^(cpu(?!cl).*|gpu$|mem$|swap$|hdd[0-9].*|bat.*)"))); - return graphicalItems->editItems(); - } else if (type == QString("extquotes")) { - return extQuotes->editItems(); - } else if (type == QString("extscript")) { - return extScripts->editItems(); - } else if (type == QString("extupgrade")) { - return extUpgrade->editItems(); - } else if (type == QString("extweather")) { - return extWeather->editItems(); - } + return keyOperator->editItem(type); } @@ -399,21 +177,7 @@ void AWKeys::addDevice(const QString source) { qCDebug(LOG_AW) << "Source" << source; - QRegExp diskRegexp - = QRegExp(QString("disk/(?:md|sd|hd)[a-z|0-9]_.*/Rate/(?:rblk)")); - QRegExp mountRegexp = QRegExp(QString("partitions/.*/filllevel")); - - if (source.contains(diskRegexp)) { - QString device = source; - device.remove(QString("/Rate/rblk")); - addKeyToCache(QString("disk"), device); - } else if (source.contains(mountRegexp)) { - QString device = source; - device.remove(QString("partitions")).remove(QString("/filllevel")); - addKeyToCache(QString("mount"), device); - } else if (source.startsWith(QString("lmsensors"))) { - addKeyToCache(QString("temp"), source); - } + return keyOperator->addDevice(source); } @@ -432,73 +196,15 @@ void AWKeys::dataUpdated(const QString &sourceName, } -void AWKeys::loadKeysFromCache() +void AWKeys::reinitKeys(const QStringList currentKeys) { - QString fileName = QString("%1/awesomewidgets.ndx") - .arg(QStandardPaths::writableLocation( - QStandardPaths::GenericCacheLocation)); - qCInfo(LOG_AW) << "Cache file" << fileName; - QSettings cache(fileName, QSettings::IniFormat); - - for (auto group : cache.childGroups()) { - cache.beginGroup(group); - m_devices.remove(group); - for (auto key : cache.allKeys()) - m_devices[group].append(cache.value(key).toString()); - cache.endGroup(); - } - - return reinitKeys(); -} - - -void AWKeys::reinitKeys() -{ - // renew extensions - // delete them if any - delete graphicalItems; - graphicalItems = nullptr; - delete extQuotes; - extQuotes = nullptr; - delete extScripts; - extScripts = nullptr; - delete extUpgrade; - extUpgrade = nullptr; - delete extWeather; - extWeather = nullptr; - // create - graphicalItems - = new ExtItemAggregator(nullptr, QString("desktops")); - extQuotes = new ExtItemAggregator(nullptr, QString("quotes")); - extScripts = new ExtItemAggregator(nullptr, QString("scripts")); - extUpgrade = new ExtItemAggregator(nullptr, QString("upgrade")); - extWeather = new ExtItemAggregator(nullptr, QString("weather")); - - // init - QStringList allKeys = dictKeys(); - -#ifdef BUILD_TESTING - // not documented feature - place all available tags - m_pattern = m_pattern.replace(QString("$ALL"), [allKeys]() { - QStringList strings; - for (auto tag : allKeys) - strings.append(QString("%1: $%1").arg(tag)); - return strings.join(QString(" | ")); - }()); -#endif /* BUILD_TESTING */ - - // apply aw_* functions - m_pattern = insertKeyCount(m_pattern); - m_pattern = insertKeyNames(m_pattern); - m_pattern = insertKeys(m_pattern); - // wrap templates - expandTemplates(); + qCDebug(LOG_AW) << "Update found keys by using list" << currentKeys; // append lists // bars - m_foundBars = [allKeys](const QString pattern) { + m_foundBars = [currentKeys](const QString pattern) { QStringList selectedKeys; - for (auto key : allKeys) + for (auto key : currentKeys) if ((key.startsWith(QString("bar"))) && (pattern.contains(QString("$%1").arg(key)))) { qCInfo(LOG_AW) << "Found bar" << key; @@ -507,12 +213,12 @@ void AWKeys::reinitKeys() if (selectedKeys.isEmpty()) qCWarning(LOG_AW) << "No bars found"; return selectedKeys; - }(m_pattern); + }(keyOperator->pattern()); // main key list - m_foundKeys = [allKeys](const QString pattern) { + m_foundKeys = [currentKeys](const QString pattern) { QStringList selectedKeys; - for (auto key : allKeys) + for (auto key : currentKeys) if ((!key.startsWith(QString("bar"))) && (pattern.contains(QString("$%1").arg(key)))) { qCInfo(LOG_AW) << "Found key" << key; @@ -521,7 +227,7 @@ void AWKeys::reinitKeys() if (selectedKeys.isEmpty()) qCWarning(LOG_AW) << "No keys found"; return selectedKeys; - }(m_pattern); + }(keyOperator->pattern()); // lambdas m_foundLambdas = [](const QString pattern) { @@ -536,7 +242,7 @@ void AWKeys::reinitKeys() while (it.hasNext()) { QRegularExpressionMatch match = it.next(); QString lambda = match.captured(); - // drop brakets + // drop brackets lambda.remove(QRegExp(QString("^\\$\\{\\{"))); lambda.remove(QRegExp(QString("\\}\\}$"))); // append @@ -546,10 +252,10 @@ void AWKeys::reinitKeys() if (selectedKeys.isEmpty()) qCWarning(LOG_AW) << "No lambdas found"; return selectedKeys; - }(m_pattern); + }(keyOperator->pattern()); // set key data to aggregator - aggregator->setDevices(m_devices); + aggregator->setDevices(keyOperator->devices()); } @@ -557,7 +263,7 @@ void AWKeys::updateTextData() { QFuture text = QtConcurrent::run(m_threadPool, [this]() { calculateValues(); - return parsePattern(m_pattern); + return parsePattern(keyOperator->pattern()); }); emit(needTextToBeUpdated(text)); @@ -565,69 +271,14 @@ void AWKeys::updateTextData() } -void AWKeys::addKeyToCache(const QString type, const QString key) -{ - qCDebug(LOG_AW) << "Key type" << type; - qCDebug(LOG_AW) << "Key" << key; - - QString fileName = QString("%1/awesomewidgets.ndx") - .arg(QStandardPaths::writableLocation( - QStandardPaths::GenericCacheLocation)); - qCInfo(LOG_AW) << "Cache file" << fileName; - QSettings cache(fileName, QSettings::IniFormat); - - cache.beginGroup(type); - QStringList cachedValues; - for (auto key : cache.allKeys()) - cachedValues.append(cache.value(key).toString()); - - if (type == QString("hdd")) { - QStringList allDevices - = QDir(QString("/dev")).entryList(QDir::System, QDir::Name); - QStringList devices - = allDevices.filter(QRegExp(QString("^[hms]d[a-z]$"))); - for (auto dev : devices) { - QString device = QString("/dev/%1").arg(dev); - if (cachedValues.contains(device)) - continue; - qCInfo(LOG_AW) << "Found new key" << device << "for type" << type; - cache.setValue( - QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), - device); - } - } else if (type == QString("net")) { - QList rawInterfaceList - = QNetworkInterface::allInterfaces(); - for (auto interface : rawInterfaceList) { - QString device = interface.name(); - if (cachedValues.contains(device)) - continue; - qCInfo(LOG_AW) << "Found new key" << device << "for type" << type; - cache.setValue( - QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), - device); - } - } else { - if (cachedValues.contains(key)) - return; - qCInfo(LOG_AW) << "Found new key" << key << "for type" << type; - cache.setValue( - QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), key); - } - cache.endGroup(); - - cache.sync(); - return loadKeysFromCache(); -} - - // HACK this method is required since I could not define some values by using // specified pattern. Usually they are values which depend on several others void AWKeys::calculateValues() { // hddtot* - for (auto device : m_devices[QString("mount")]) { - int index = m_devices[QString("mount")].indexOf(device); + QStringList mountDevices = keyOperator->devices(QString("mount")); + for (auto device : mountDevices) { + int index = mountDevices.indexOf(device); values[QString("hddtotmb%1").arg(index)] = QString("%1").arg( values[QString("hddfreemb%1").arg(index)].toFloat() + values[QString("hddmb%1").arg(index)].toFloat(), @@ -654,7 +305,8 @@ void AWKeys::calculateValues() 5, 'f', 1); // up, down, upkb, downkb, upunits, downunits - int netIndex = m_devices[QString("net")].indexOf(values[QString("netdev")]); + int netIndex = keyOperator->devices(QString("net")) + .indexOf(values[QString("netdev")]); values[QString("down")] = values[QString("down%1").arg(netIndex)]; values[QString("downkb")] = values[QString("downkb%1").arg(netIndex)]; values[QString("downunits")] = values[QString("downunits%1").arg(netIndex)]; @@ -699,136 +351,6 @@ void AWKeys::calculateValues() } -void AWKeys::expandTemplates() -{ - // match the following construction $template{{some code here}} - QRegularExpression templatesRegexp( - QString("\\$template\\{\\{((?!\\$template\\{\\{).)*?\\}\\}")); - templatesRegexp.setPatternOptions( - QRegularExpression::DotMatchesEverythingOption); - - QRegularExpressionMatchIterator it = templatesRegexp.globalMatch(m_pattern); - while (it.hasNext()) { - QRegularExpressionMatch match = it.next(); - QString fullTemplate = match.captured(); - - // drop additional markers - QString templ = fullTemplate; - templ.remove(QRegExp(QString("^\\$template\\{\\{"))); - templ.remove(QRegExp(QString("\\}\\}$"))); - - QJSEngine engine; - qCInfo(LOG_AW) << "Expression" << templ; - QJSValue result = engine.evaluate(templ); - QString templateResult = QString(""); - if (result.isError()) { - qCWarning(LOG_AW) << "Uncaught exception at line" - << result.property("lineNumber").toInt() << ":" - << result.toString(); - } else { - templateResult = result.toString(); - } - - // replace template - m_pattern.replace(fullTemplate, templateResult); - } -} - - -QString AWKeys::insertKeyCount(QString code) const -{ - qCDebug(LOG_AW) << "Looking for count in code" << code; - - QRegularExpression countRegexp(QString("aw_count\\(((?!\\aw_count\\().)*?\\)")); - countRegexp.setPatternOptions( - QRegularExpression::DotMatchesEverythingOption); - - QRegularExpressionMatchIterator it = countRegexp.globalMatch(code); - while (it.hasNext()) { - QRegularExpressionMatch match = it.next(); - QString count = match.captured(); - - // get regexp to search - QString regex = count; - regex.remove(QRegExp(QString("^aw_count\\("))); - regex.remove(QRegExp(QString("\\)$"))); - qCInfo(LOG_AW) << "Looking for" << regex; - - code.replace(count, QString::number(dictKeys(false, regex).count())); - } - - return code; -} - - -QString AWKeys::insertKeyNames(QString code) const -{ - qCDebug(LOG_AW) << "Looking for keys in code" << code; - - QRegularExpression keysRegexp(QString("aw_names\\(((?!\\aw_names\\().)*?\\)")); - keysRegexp.setPatternOptions( - QRegularExpression::DotMatchesEverythingOption); - - QRegularExpressionMatchIterator it = keysRegexp.globalMatch(code); - while (it.hasNext()) { - QRegularExpressionMatch match = it.next(); - QString keys = match.captured(); - - // get regexp to search - QString condition = keys; - condition.remove(QRegExp(QString("^aw_names\\("))); - condition.remove(QRegExp(QString("\\)$"))); - QStringList conditionList = condition.split(QChar(',')); - // regexp - QString regex = conditionList.at(0); - // separator to join - QString separator = conditionList.size() == 1 ? QString("") : conditionList.at(1); - qCInfo(LOG_AW) << "Looking for" << regex << "with separator" << separator; - - code.replace(keys, dictKeys(true, regex).join(separator)); - } - - return code; -} - - -QString AWKeys::insertKeys(QString code) const -{ - qCDebug(LOG_AW) << "Looking for keys in code" << code; - - QRegularExpression keysRegexp(QString("aw_keys\\(((?!\\aw_keys\\().)*?\\)")); - keysRegexp.setPatternOptions( - QRegularExpression::DotMatchesEverythingOption); - - QRegularExpressionMatchIterator it = keysRegexp.globalMatch(code); - while (it.hasNext()) { - QRegularExpressionMatch match = it.next(); - QString keys = match.captured(); - - // get regexp to search - QString condition = keys; - condition.remove(QRegExp(QString("^aw_keys\\("))); - condition.remove(QRegExp(QString("\\)$"))); - QStringList conditionList = condition.split(QChar(',')); - // regexp - QString regex = conditionList.at(0); - // separator to join - QString separator = conditionList.size() == 1 ? QString("") : conditionList.at(1); - qCInfo(LOG_AW) << "Looking for" << regex << "with separator" << separator; - - // find keys and add $ at the beginning of the line - QStringList foundKeys = dictKeys(true, regex); - std::for_each(foundKeys.begin(), foundKeys.end(), [](QString &value) { - value = QString("$%1").arg(value); - }); - - code.replace(keys, foundKeys.join(separator)); - } - - return code; -} - - QString AWKeys::parsePattern(QString pattern) const { // screen sign @@ -850,7 +372,7 @@ QString AWKeys::parsePattern(QString pattern) const // bars for (auto bar : m_foundBars) { - GraphicalItem *item = graphicalItems->itemByTag(bar); + GraphicalItem *item = keyOperator->giByKey(bar); QString key = bar; key.remove(QRegExp(QString("^bar[0-9]{1,}"))); if (item->type() == GraphicalItem::Graph) diff --git a/sources/awesome-widget/plugin/awkeys.h b/sources/awesome-widget/plugin/awkeys.h index 321a4cb..36c99c2 100644 --- a/sources/awesome-widget/plugin/awkeys.h +++ b/sources/awesome-widget/plugin/awkeys.h @@ -24,17 +24,11 @@ #include #include -#include "extitemaggregator.h" - class AWDataAggregator; class AWDataEngineAggregator; +class AWKeyOperations; class AWKeysAggregator; -class ExtQuotes; -class ExtScript; -class ExtUpgrade; -class ExtWeather; -class GraphicalItem; class QThreadPool; class AWKeys : public QObject @@ -50,6 +44,8 @@ public: Q_INVOKABLE void setAggregatorProperty(const QString key, const QVariant value); Q_INVOKABLE void setWrapNewLines(const bool wrap = false); + // additional method to force load keys from Qml UI. Used in some + // configuration pages Q_INVOKABLE void updateCache(); // keys Q_INVOKABLE QStringList dictKeys(const bool sorted = false, @@ -75,33 +71,21 @@ signals: void needToBeUpdated(); private slots: - void loadKeysFromCache(); - void reinitKeys(); + void reinitKeys(const QStringList currentKeys); void updateTextData(); private: // methods - void addKeyToCache(const QString type, const QString key = QString("")); void calculateValues(); - void expandTemplates(); - QString insertKeyCount(QString code) const; - QString insertKeyNames(QString code) const; - QString insertKeys(QString code) const; QString parsePattern(QString pattern) const; void setDataBySource(const QString &sourceName, const QVariantMap &data); // objects AWDataAggregator *dataAggregator = nullptr; AWDataEngineAggregator *dataEngineAggregator = nullptr; AWKeysAggregator *aggregator = nullptr; - ExtItemAggregator *graphicalItems = nullptr; - ExtItemAggregator *extQuotes = nullptr; - ExtItemAggregator *extScripts = nullptr; - ExtItemAggregator *extUpgrade = nullptr; - ExtItemAggregator *extWeather = nullptr; + AWKeyOperations *keyOperator = nullptr; // variables - QHash m_devices; QStringList m_foundBars, m_foundKeys, m_foundLambdas; - QString m_pattern; QHash values; bool m_wrapNewLines = false; // multithread features diff --git a/sources/awesome-widget/plugin/awpatternfunctions.cpp b/sources/awesome-widget/plugin/awpatternfunctions.cpp new file mode 100644 index 0000000..333700c --- /dev/null +++ b/sources/awesome-widget/plugin/awpatternfunctions.cpp @@ -0,0 +1,160 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets is free software: you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + +#include "awpatternfunctions.h" + +#include +#include + +#include "awdebug.h" + + +QVariantList AWPatternFunctions::findFunctionCalls(const QString function, + const QString code) +{ + qCDebug(LOG_AW) << "Looking for function" << function << "in" << code; + + QRegularExpression regex( + QString("%1\\<(?.*?)\\>\\((?.*?)\\)").arg(function)); + regex.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); + + QVariantList foundFunctions; + QRegularExpressionMatchIterator it = regex.globalMatch(code); + while (it.hasNext()) { + QRegularExpressionMatch match = it.next(); + + QVariantHash metadata; + metadata[QString("args")] + = match.captured(QString("args")).split(QChar(',')); + metadata[QString("body")] = match.captured(QString("body")); + metadata[QString("what")] = match.captured(); + foundFunctions.append(metadata); + } + + return foundFunctions; +} + + +QString AWPatternFunctions::expandTemplates(QString code) +{ + qCDebug(LOG_AW) << "Expand tempaltes in" << code; + + // match the following construction $template{{some code here}} + QRegularExpression templatesRegexp( + QString("\\$template\\{\\{((?!\\$template\\{\\{).)*?\\}\\}")); + templatesRegexp.setPatternOptions( + QRegularExpression::DotMatchesEverythingOption); + + QRegularExpressionMatchIterator it = templatesRegexp.globalMatch(code); + while (it.hasNext()) { + QRegularExpressionMatch match = it.next(); + QString fullTemplate = match.captured(); + + // drop additional markers + QString templ = fullTemplate; + templ.remove(QRegExp(QString("^\\$template\\{\\{"))); + templ.remove(QRegExp(QString("\\}\\}$"))); + + QJSEngine engine; + qCInfo(LOG_AW) << "Expression" << templ; + QJSValue result = engine.evaluate(templ); + QString templateResult = QString(""); + if (result.isError()) { + qCWarning(LOG_AW) << "Uncaught exception at line" + << result.property("lineNumber").toInt() << ":" + << result.toString(); + } else { + templateResult = result.toString(); + } + + // replace template + code.replace(fullTemplate, templateResult); + } + + return code; +} + + +QString AWPatternFunctions::insertKeyCount(QString code, const QStringList keys) +{ + qCDebug(LOG_AW) << "Looking for count in code" << code << "using list" + << keys; + + QVariantList found + = AWPatternFunctions::findFunctionCalls(QString("aw_count"), code); + for (auto function : found) { + QVariantHash metadata = function.toHash(); + int count = keys.filter(QRegExp(metadata[QString("body")].toString())) + .count(); + + code.replace(metadata[QString("what")].toString(), + QString::number(count)); + } + + return code; +} + + +QString AWPatternFunctions::insertKeyNames(QString code, const QStringList keys) +{ + qCDebug(LOG_AW) << "Looking for keys in code" << code << "using list" + << keys; + + QVariantList found + = AWPatternFunctions::findFunctionCalls(QString("aw_names"), code); + for (auto function : found) { + QVariantHash metadata = function.toHash(); + QString separator + = metadata[QString("args")].toStringList().isEmpty() + ? QString(",") + : metadata[QString("args")].toStringList().at(0); + QStringList required + = keys.filter(QRegExp(metadata[QString("body")].toString())); + + code.replace(metadata[QString("what")].toString(), + required.join(separator)); + } + + return code; +} + + +QString AWPatternFunctions::insertKeys(QString code, const QStringList keys) +{ + qCDebug(LOG_AW) << "Looking for keys in code" << code << "using list" + << keys; + + QVariantList found + = AWPatternFunctions::findFunctionCalls(QString("aw_keys"), code); + for (auto function : found) { + QVariantHash metadata = function.toHash(); + QString separator + = metadata[QString("args")].toStringList().isEmpty() + ? QString(",") + : metadata[QString("args")].toStringList().at(0); + QStringList required + = keys.filter(QRegExp(metadata[QString("body")].toString())); + std::for_each(required.begin(), required.end(), [](QString &value) { + value = QString("$%1").arg(value); + }); + + code.replace(metadata[QString("what")].toString(), + required.join(separator)); + } + + return code; +} diff --git a/sources/awesome-widget/plugin/awpatternfunctions.h b/sources/awesome-widget/plugin/awpatternfunctions.h new file mode 100644 index 0000000..c53d77a --- /dev/null +++ b/sources/awesome-widget/plugin/awpatternfunctions.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets is free software: you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + + +#ifndef AWPATTERNFUNCTIONS_H +#define AWPATTERNFUNCTIONS_H + +#include +#include + + +namespace AWPatternFunctions +{ +QString expandTemplates(QString code); +QVariantList findFunctionCalls(const QString function, const QString code); +QString insertKeyCount(QString code, const QStringList keys); +QString insertKeyNames(QString code, const QStringList keys); +QString insertKeys(QString code, const QStringList keys); +}; + + +#endif /* AWPATTERNFUNCTIONS_H */