Initial support of templates and so on (#71)

* Initial syntax is the following:

    * $template{{ some JS code here }} - simple template based on JS
      code inside. It works the same as lambda functions, but calculates
      only once.
    * aw_count(regex) - keys count found for given regex
    * aw_keys(regex, [separator]) - keys found for given regex and
      joined by using given separator
    * aw_names(regex, [separator]) - key names found for given regex and
      joined by using given separator (the same as previous but w\o $)

  The template and function syntax may be changed before release.

* replace `foreach` to `for (auto foo : bar)` and update CONTRIBUTING.md
  accordingly
This commit is contained in:
2016-01-30 00:07:47 +07:00
parent fba58c27e8
commit 1c78e0d779
23 changed files with 224 additions and 106 deletions

View File

@ -61,7 +61,7 @@ bool AWConfigHelper::exportConfiguration(QObject *nativeConfig,
QQmlPropertyMap *configuration
= static_cast<QQmlPropertyMap *>(nativeConfig);
settings.beginGroup(QString("plasmoid"));
foreach (QString key, configuration->keys()) {
for (auto key : configuration->keys()) {
QVariant value = configuration->value(key);
if (!value.isValid())
continue;
@ -70,13 +70,13 @@ bool AWConfigHelper::exportConfiguration(QObject *nativeConfig,
settings.endGroup();
// extensions
foreach (QString item, m_dirs) {
for (auto item : m_dirs) {
QStringList items
= QDir(QString("%1/%2").arg(m_baseDir).arg(item))
.entryList(QStringList() << QString("*.desktop"),
QDir::Files);
settings.beginGroup(item);
foreach (QString it, items)
for (auto it : items)
copyExtensions(it, item, settings, false);
settings.endGroup();
}
@ -112,9 +112,9 @@ QVariantMap AWConfigHelper::importConfiguration(const QString fileName,
// extensions
if (importExtensions) {
foreach (QString item, m_dirs) {
for (auto item : m_dirs) {
settings.beginGroup(item);
foreach (QString it, settings.childGroups())
for (auto it : settings.childGroups())
copyExtensions(it, item, settings, true);
settings.endGroup();
}
@ -137,7 +137,7 @@ QVariantMap AWConfigHelper::importConfiguration(const QString fileName,
// plasmoid configuration
if (importPlasmoid) {
settings.beginGroup(QString("plasmoid"));
foreach (QString key, settings.childKeys())
for (auto key : settings.childKeys())
configuration[key] = settings.value(key);
settings.endGroup();
}
@ -239,7 +239,7 @@ void AWConfigHelper::copyExtensions(const QString item, const QString type,
void AWConfigHelper::copySettings(QSettings &from, QSettings &to) const
{
foreach (QString key, from.childKeys())
for (auto key : from.childKeys())
to.setValue(key, from.value(key));
}

View File

@ -131,7 +131,7 @@ QPixmap AWDataAggregator::tooltipImage()
toolTipScene->clear();
QPen pen;
bool down = false;
foreach (QString key, requiredKeys) {
for (auto key : requiredKeys) {
// create frame
float normX = 100.0 / static_cast<float>(data[key].count());
float normY = 100.0 / (1.5 * boundaries[key]);

View File

@ -45,8 +45,8 @@ AWDataEngineAggregator::~AWDataEngineAggregator()
void AWDataEngineAggregator::disconnectSources()
{
foreach (QString dataengine, m_dataEngines.keys())
foreach (QString source, m_dataEngines[dataengine]->sources())
for (auto dataengine : m_dataEngines.keys())
for (auto source : m_dataEngines[dataengine]->sources())
m_dataEngines[dataengine]->disconnectSource(source, parent());
}

View File

@ -44,13 +44,11 @@ AWKeys::AWKeys(QObject *parent)
{
qSetMessagePattern(LOG_FORMAT);
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
foreach (const QString metadata, getBuildData())
for (auto metadata : getBuildData())
qCDebug(LOG_AW) << metadata;
#ifdef BUILD_FUTURE
// thread pool
m_threadPool = new QThreadPool(this);
#endif /* BUILD_FUTURE */
aggregator = new AWKeysAggregator(this);
dataAggregator = new AWDataAggregator(this);
@ -103,10 +101,8 @@ void AWKeys::initKeys(const QString currentPattern, const int interval,
dataEngineAggregator, SLOT(dropSource(QString)));
} else
dataEngineAggregator->setInterval(interval);
#ifdef BUILD_FUTURE
m_threadPool->setMaxThreadCount(limit == 0 ? QThread::idealThreadCount()
: limit);
#endif /* BUILD_FUTURE */
updateCache();
return dataEngineAggregator->reconnectSources();
@ -292,7 +288,7 @@ QStringList AWKeys::dictKeys(const bool sorted, const QString regexp) const
allKeys.append(QString("la1"));
// bars
QStringList graphicalItemsKeys;
foreach (GraphicalItem *item, graphicalItems->items())
for (auto item : graphicalItems->items())
graphicalItemsKeys.append(item->tag());
graphicalItemsKeys.sort();
for (int i = graphicalItemsKeys.count() - 1; i >= 0; i--)
@ -430,13 +426,9 @@ void AWKeys::dataUpdated(const QString &sourceName,
return emit(needToBeUpdated());
}
#ifdef BUILD_FUTURE
// run concurrent data update
QtConcurrent::run(m_threadPool, this, &AWKeys::setDataBySource, sourceName,
data);
#else /* BUILD_FUTURE */
return setDataBySource(sourceName, data);
#endif /* BUILD_FUTURE */
}
@ -448,10 +440,10 @@ void AWKeys::loadKeysFromCache()
qCInfo(LOG_AW) << "Cache file" << fileName;
QSettings cache(fileName, QSettings::IniFormat);
foreach (QString group, cache.childGroups()) {
for (auto group : cache.childGroups()) {
cache.beginGroup(group);
m_devices.remove(group);
foreach (QString key, cache.allKeys())
for (auto key : cache.allKeys())
m_devices[group].append(cache.value(key).toString());
cache.endGroup();
}
@ -489,17 +481,24 @@ void AWKeys::reinitKeys()
// not documented feature - place all available tags
m_pattern = m_pattern.replace(QString("$ALL"), [allKeys]() {
QStringList strings;
foreach (QString tag, allKeys)
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();
// append lists
// bars
m_foundBars = [allKeys](QString pattern) {
m_foundBars = [allKeys](const QString pattern) {
QStringList selectedKeys;
foreach (QString key, allKeys)
for (auto key : allKeys)
if ((key.startsWith(QString("bar")))
&& (pattern.contains(QString("$%1").arg(key)))) {
qCInfo(LOG_AW) << "Found bar" << key;
@ -511,9 +510,9 @@ void AWKeys::reinitKeys()
}(m_pattern);
// main key list
m_foundKeys = [allKeys](QString pattern) {
m_foundKeys = [allKeys](const QString pattern) {
QStringList selectedKeys;
foreach (QString key, allKeys)
for (auto key : allKeys)
if ((!key.startsWith(QString("bar")))
&& (pattern.contains(QString("$%1").arg(key)))) {
qCInfo(LOG_AW) << "Found key" << key;
@ -525,7 +524,7 @@ void AWKeys::reinitKeys()
}(m_pattern);
// lambdas
m_foundLambdas = [](QString pattern) {
m_foundLambdas = [](const QString pattern) {
QStringList selectedKeys;
// substring inside ${{ }} (with brackets) which should not contain ${{
QRegularExpression lambdaRegexp(
@ -556,15 +555,10 @@ void AWKeys::reinitKeys()
void AWKeys::updateTextData()
{
#ifdef BUILD_FUTURE
QFuture<QString> text = QtConcurrent::run(m_threadPool, [this]() {
calculateValues();
return parsePattern(m_pattern);
});
#else /* BUILD_FUTURE */
calculateValues();
QString text = parsePattern(m_pattern);
#endif /* BUILD_FUTURE */
emit(needTextToBeUpdated(text));
emit(dataAggregator->updateData(values));
@ -584,7 +578,7 @@ void AWKeys::addKeyToCache(const QString type, const QString key)
cache.beginGroup(type);
QStringList cachedValues;
foreach (QString key, cache.allKeys())
for (auto key : cache.allKeys())
cachedValues.append(cache.value(key).toString());
if (type == QString("hdd")) {
@ -592,7 +586,7 @@ void AWKeys::addKeyToCache(const QString type, const QString key)
= QDir(QString("/dev")).entryList(QDir::System, QDir::Name);
QStringList devices
= allDevices.filter(QRegExp(QString("^[hms]d[a-z]$")));
foreach (QString dev, devices) {
for (auto dev : devices) {
QString device = QString("/dev/%1").arg(dev);
if (cachedValues.contains(device))
continue;
@ -604,7 +598,7 @@ void AWKeys::addKeyToCache(const QString type, const QString key)
} else if (type == QString("net")) {
QList<QNetworkInterface> rawInterfaceList
= QNetworkInterface::allInterfaces();
foreach (QNetworkInterface interface, rawInterfaceList) {
for (auto interface : rawInterfaceList) {
QString device = interface.name();
if (cachedValues.contains(device))
continue;
@ -632,7 +626,7 @@ void AWKeys::addKeyToCache(const QString type, const QString key)
void AWKeys::calculateValues()
{
// hddtot*
foreach (QString device, m_devices[QString("mount")]) {
for (auto device : m_devices[QString("mount")]) {
int index = m_devices[QString("mount")].indexOf(device);
values[QString("hddtotmb%1").arg(index)] = QString("%1").arg(
values[QString("hddfreemb%1").arg(index)].toFloat()
@ -684,12 +678,12 @@ void AWKeys::calculateValues()
5, 'f', 1);
// lambdas
foreach (QString key, m_foundLambdas)
for (auto key : m_foundLambdas)
values[key] = [this](QString key) {
QJSEngine engine;
// apply $this values
key.replace(QString("$this"), values[key]);
foreach (QString lambdaKey, m_foundKeys)
for (auto lambdaKey : m_foundKeys)
key.replace(QString("$%1").arg(lambdaKey), values[lambdaKey]);
qCInfo(LOG_AW) << "Expression" << key;
QJSValue result = engine.evaluate(key);
@ -705,17 +699,147 @@ 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
pattern.replace(QString("$$"), QString("$\\$\\"));
// lambdas
foreach (QString key, m_foundLambdas)
for (auto key : m_foundLambdas)
pattern.replace(QString("${{%1}}").arg(key), values[key]);
// main keys
foreach (QString key, m_foundKeys)
for (auto key : m_foundKeys)
pattern.replace(QString("$%1").arg(key),
[](QString key, QString value) {
if ((!key.startsWith(QString("custom")))
@ -725,7 +849,7 @@ QString AWKeys::parsePattern(QString pattern) const
}(key, values[key]));
// bars
foreach (QString bar, m_foundBars) {
for (auto bar : m_foundBars) {
GraphicalItem *item = graphicalItems->itemByTag(bar);
QString key = bar;
key.remove(QRegExp(QString("^bar[0-9]{1,}")));
@ -763,9 +887,7 @@ void AWKeys::setDataBySource(const QString &sourceName, const QVariantMap &data)
qCDebug(LOG_AW) << "Source" << sourceName << "not found";
emit(dropSourceFromDataengine(sourceName));
} else {
#ifdef BUILD_FUTURE
m_mutex.lock();
#endif /* BUILD_FUTURE */
// HACK workaround for time values which are stored in the different
// path
QVariant value = sourceName == QString("Local")
@ -775,8 +897,6 @@ void AWKeys::setDataBySource(const QString &sourceName, const QVariantMap &data)
[this, value](const QString tag) {
values[tag] = aggregator->formater(value, tag);
});
#ifdef BUILD_FUTURE
m_mutex.unlock();
#endif /* BUILD_FUTURE */
}
}

View File

@ -83,6 +83,10 @@ 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

View File

@ -102,7 +102,7 @@ QString AWKeysAggregator::formater(const QVariant &data,
case TimeCustom:
output = m_customTime;
[&output, loc, this](const QDateTime dt) {
foreach (QString key, timeKeys)
for (auto key : timeKeys)
output.replace(QString("$%1").arg(key), loc.toString(dt, key));
}(data.toDateTime());
break;