From 7fa541bc0608fa07b7493fc467a64a9dadc5afdb Mon Sep 17 00:00:00 2001 From: arcan1s Date: Thu, 7 Aug 2014 19:44:29 +0400 Subject: [PATCH] rewrite dataengine to use task --- CHANGELOG | 2 + CHANGELOG-RU | 2 + PKGBUILD | 2 +- sources/3rdparty/task/README.md | 41 ++ sources/3rdparty/task/task.h | 385 ++++++++++++++++ sources/3rdparty/task/taskadds.cpp | 34 ++ sources/3rdparty/task/taskadds.h | 35 ++ sources/CMakeLists.txt | 9 +- sources/ext-sysmon/CMakeLists.txt | 4 +- sources/ext-sysmon/extsysmon.conf | 2 +- sources/ext-sysmon/extsysmon.cpp | 674 ++++++++++------------------- sources/ext-sysmon/extsysmon.h | 42 +- sources/ext-sysmon/task.h | 1 + sources/ext-sysmon/taskadds.cpp | 1 + sources/ext-sysmon/taskadds.h | 1 + 15 files changed, 745 insertions(+), 490 deletions(-) create mode 100644 sources/3rdparty/task/README.md create mode 100644 sources/3rdparty/task/task.h create mode 100644 sources/3rdparty/task/taskadds.cpp create mode 100644 sources/3rdparty/task/taskadds.h create mode 120000 sources/ext-sysmon/task.h create mode 120000 sources/ext-sysmon/taskadds.cpp create mode 120000 sources/ext-sysmon/taskadds.h diff --git a/CHANGELOG b/CHANGELOG index 9fb8626..c10ff30 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,8 @@ Ver.1.11.0: + added desktop DataEngine + added PTM desktop panel + added desktop label (tags $name, $number, $total) +* rewrite dataengine to use tasks +* fix nvidia temperature definition Ver.1.10.2: - fix error with tempUnits in hddtemp label diff --git a/CHANGELOG-RU b/CHANGELOG-RU index 5cdec6c..8b9fcdf 100644 --- a/CHANGELOG-RU +++ b/CHANGELOG-RU @@ -3,6 +3,8 @@ + добавлен desktop DataEngine + добавлен виджет PTM desktop panel + добавлено поле текущий рабочий стол (теги $name, $number, $total) +* dataengine переписан с использованием tasks +* фикс чтения температуры nvidia Вер.1.10.2: - фикс ошибки с tempUnits в поле hddtemp diff --git a/PKGBUILD b/PKGBUILD index b242cd7..a8509fb 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -21,7 +21,7 @@ optdepends=("amarok: for music player monitor" makedepends=('automoc4' 'cmake') source=(https://github.com/arcan1s/pytextmonitor/releases/download/V.${pkgver}/${_pkgname}-${pkgver}-src.tar.xz) install=${pkgname}.install -md5sums=('302183c0a39d8c718490eed606ca7795') +md5sums=('b5f8383c198e7059f463678f84a16273') backup=('usr/share/config/extsysmon.conf') prepare() { diff --git a/sources/3rdparty/task/README.md b/sources/3rdparty/task/README.md new file mode 100644 index 0000000..c375afb --- /dev/null +++ b/sources/3rdparty/task/README.md @@ -0,0 +1,41 @@ + + +Asynchronous programming in Qt/C++ using tasks,continuations and resumable functions. + +This project is inspired by this[1] video on channel9. + +The project seeks to do async based programming in Qt/C++ using modern C++ with lambdas. + +The project has two sets of APIs. + +1. Task::run().then() API provides async based programming with continuation[4]. + +2. Task::await() API provides the first API presented in a different way[5]. + +Under certain use cases,they can be used interchangeably, and in others,only one or the other can be used.Some of the problems +the first API causes and solved by the second API are discussed in this[7] youtube video. + +Example use case for the Task::run().then() API can be found here[0]. Additional example is [2] where an API is +declared and [3] where the declared API is used. + +Example use case of the Task::await() API is here[6] where a function call "blocks" waiting for a result without "hanging" the entire GUI application. + +A short tutorial on task/async/await as implemented in C# can be viewed from this[8] link. + +[0] https://github.com/mhogomchungu/tasks/blob/master/example.cpp + +[1] http://channel9.msdn.com/Blogs/Charles/Asynchronous-Programming-for-C-Developers-PPL-Tasks-and-Windows-8 + +[2] https://github.com/mhogomchungu/zuluCrypt/blob/d0439a4e36521e42fa9392b82dcefd3224d53334/zuluMount-gui/zulumounttask.h#L61 + +[3] https://github.com/mhogomchungu/zuluCrypt/blob/d0439a4e36521e42fa9392b82dcefd3224d53334/zuluMount-gui/mainwindow.cpp#L812 + +[4] Disscussion about this can be found on the following link among other places: http://isocpp.org/files/papers/N3558.pdf + +[5] Disscussion about this can be found on the following link among other places: http://isocpp.org/files/papers/N3564.pdf + +[6] https://github.com/mhogomchungu/zuluCrypt/blob/7123e3c3a7c8c5b3b3b6958464fd92a7f780d827/zuluMount-gui/keydialog.cpp#L511 + +[7] https://www.youtube.com/watch?v=Y475RshtAHA + +[8] http://www.youtube.com/watch?v=DqjIQiZ_ql4 diff --git a/sources/3rdparty/task/task.h b/sources/3rdparty/task/task.h new file mode 100644 index 0000000..bc1259e --- /dev/null +++ b/sources/3rdparty/task/task.h @@ -0,0 +1,385 @@ +/* + * copyright: 2014 + * name : mhogo mchungu + * email: mhogomchungu@gmail.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __TASK_H_INCLUDED__ +#define __TASK_H_INCLUDED__ + +#include +#include +#include +#include +#include + +/* + * + * Examples on how to use the library are at the end of this file. + * + */ + +namespace Task +{ + class Thread : public QThread + { + Q_OBJECT + public: + Thread() + { + connect( this,SIGNAL( finished() ),this,SLOT( deleteLater() ) ) ; + } + protected: + virtual ~Thread() + { + } + private: + virtual void run( void ) + { + } + }; + + template< typename T > + class future + { + public: + future() : m_function( []( T t ){ Q_UNUSED( t ) ; } ) + { + } + void setActions( std::function< void( void ) > start, + std::function< void( void ) > cancel, + std::function< T ( void ) > get ) + { + m_start = std::move( start ) ; + m_cancel = std::move( cancel ) ; + m_get = std::move( get ) ; + } + void then( std::function< void( T ) > function ) + { + m_function = std::move( function ) ; + m_start() ; + } + T get() + { + return m_get() ; + } + T await() + { + QEventLoop p ; + + T q ; + + m_function = [ & ]( T r ){ q = std::move( r ) ; p.exit() ; } ; + + m_start() ; + + p.exec() ; + + return q ; + } + void start() + { + m_start() ; + } + void cancel() + { + m_cancel() ; + } + void run( T r ) + { + m_function( std::move( r ) ) ; + } + private: + std::function< void( T ) > m_function ; + std::function< void( void ) > m_start ; + std::function< void( void ) > m_cancel ; + std::function< T ( void ) > m_get ; + }; + + template< typename T > + class ThreadHelper : public Thread + { + public: + ThreadHelper( std::function< T ( void ) >&& function ) : m_function( std::move( function ) ) + { + } + future& Future( void ) + { + m_future.setActions( [ this ](){ this->start() ; }, + [ this ](){ this->deleteLater() ; }, + [ this ](){ T r = m_function() ; this->deleteLater() ; return r ; } ) ; + return m_future ; + } + private: + ~ThreadHelper() + { + m_future.run( std::move( m_cargo ) ) ; + } + void run( void ) + { + m_cargo = m_function() ; + } + std::function< T ( void ) > m_function ; + future m_future ; + T m_cargo ; + }; + + class future_1 + { + public: + future_1() : m_function( [](){} ) + { + } + void setActions( std::function< void( void ) > start, + std::function< void( void ) > cancel, + std::function< void( void ) > get ) + { + m_start = std::move( start ) ; + m_cancel = std::move( cancel ) ; + m_get = std::move( get ) ; + } + void then( std::function< void( void ) > function ) + { + m_function = std::move( function ) ; + m_start() ; + } + void get() + { + m_get() ; + } + void await() + { + QEventLoop p ; + + m_function = [ & ](){ p.exit() ; } ; + + m_start() ; + + p.exec() ; + } + void start() + { + m_start() ; + } + void run() + { + m_function() ; + } + void cancel() + { + m_cancel() ; + } + private: + std::function< void( void ) > m_function ; + std::function< void( void ) > m_start ; + std::function< void( void ) > m_cancel ; + std::function< void( void ) > m_get ; + }; + + class ThreadHelper_1 : public Thread + { + public: + ThreadHelper_1( std::function< void ( void ) >&& function ) : m_function( std::move( function ) ) + { + } + future_1& Future( void ) + { + m_future.setActions( [ this ](){ this->start() ; }, + [ this ](){ this->deleteLater() ; }, + [ this ](){ m_function() ; this->deleteLater() ; } ) ; + return m_future ; + } + private: + ~ThreadHelper_1() + { + m_future.run() ; + } + void run( void ) + { + m_function() ; + } + std::function< void ( void ) > m_function ; + future_1 m_future ; + }; + + /* + * Below APIs runs two tasks,the first one will run in a different thread and + * the second one will be run on the original thread after the completion of the + * first one. + */ + + template< typename T > + future& run( std::function< T ( void ) > function ) + { + auto t = new ThreadHelper( std::move( function ) ) ; + return t->Future() ; + } + + static inline future_1& run( std::function< void( void ) > function ) + { + auto t = new ThreadHelper_1( std::move( function ) ) ; + return t->Future() ; + } + + static inline void exec( std::function< void( void ) > function ) + { + Task::run( std::move( function ) ).start() ; + } + + /* + * Below APIs implements resumable functions where a function will be "blocked" + * waiting for the function to return without "hanging" the current thread. + * + * recommending reading up on C#'s await keyword to get a sense of what is being + * discussed below. + */ + + static inline void await( Task::future_1& e ) + { + e.await() ; + } + + static inline void await( std::function< void( void ) > function ) + { + Task::run( std::move( function ) ).await() ; + } + + template< typename T > + T await( std::function< T ( void ) > function ) + { + return Task::run( std::move( function ) ).await() ; + } + + template< typename T > + T await( Task::future& e ) + { + return e.await() ; + } + + template< typename T > + T await( std::future&& t ) + { + return Task::await( [ & ](){ return t.get() ; } ) ; + } +} + +#if 0 + +/* + * Examples on how to use the library + */ +/* + * templated version that passes a return value of one function to another function + */ +auto _a = [](){ + /* + * task _a does what task _a does here. + * + * This function body will run on a different thread + */ + return 0 ; +} + +auto _b = []( int r ){ + /* + * + * task _b does what task _b does here. + * + * r is a const reference to a value returned by _a + * + * This function body will run on the original thread + */ +} + +Task::run( _a ).then( _b ) ; + +alternatively, + +Task::future& e = Task::run( _a ) ; + +e.then( _b ) ; + +/* + * Non templated version that does not pass around return value + */ +auto _c = [](){ + /* + * task _a does what task _a does here. + * + * This function body will run on a different thread + */ +} + +auto _d = [](){ + /* + * task _b does what task _b does here. + * + * r is a const reference to a value returned by _a + * + * This function body will run on the original thread + */ +} + +Task::run( _c ).then( _d ) ; + +/* + * if no continuation + */ +Task::exec( _c ) ; + +/* + * Task::await() is used to "block" without "hanging" the calling thread until the function returns. + * + * Its use case is to do sync programming without hanging the calling thread. + * + * example use case for it is to "block" on function in a GUI thread withough blocking the GUI thread + * hanging the application. + */ + +/* + * await example when the called function return no result + */ +Task::await( _c ) ; + +/* + * await example when the called function return a result + */ +int r = Task::await( _a ) ; + +alternatively, + +Task::future& e = Task::run( _a ) ; + +int r = e.await() ; + +alternatively, + +int r = Task::run( _a ).await() ; + +#endif + +#endif //__TASK_H_INCLUDED__ diff --git a/sources/3rdparty/task/taskadds.cpp b/sources/3rdparty/task/taskadds.cpp new file mode 100644 index 0000000..b8a8165 --- /dev/null +++ b/sources/3rdparty/task/taskadds.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** + * This file is part of netctl-gui * + * * + * netctl-gui 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. * + * * + * netctl-gui 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 netctl-gui. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + + +#include "taskadds.h" + + +TaskResult runTask(const QString cmd) +{ + return Task::await( [ & ]() { + QProcess command; + command.start(cmd); + command.waitForFinished(-1); + TaskResult r; + r.exitCode = command.exitCode(); + r.output = command.readAllStandardOutput(); + + return r; + }); +} diff --git a/sources/3rdparty/task/taskadds.h b/sources/3rdparty/task/taskadds.h new file mode 100644 index 0000000..6de905b --- /dev/null +++ b/sources/3rdparty/task/taskadds.h @@ -0,0 +1,35 @@ +/*************************************************************************** + * This file is part of netctl-gui * + * * + * netctl-gui 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. * + * * + * netctl-gui 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 netctl-gui. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + + +#ifndef TASKADDS_H +#define TASKADDS_H + +#include + +#include "task.h" + + +struct TaskResult +{ + int exitCode; + QByteArray output; +}; +TaskResult runTask(const QString cmd); + + +#endif /* TASKADDS_H */ diff --git a/sources/CMakeLists.txt b/sources/CMakeLists.txt index feee866..788f639 100644 --- a/sources/CMakeLists.txt +++ b/sources/CMakeLists.txt @@ -15,12 +15,11 @@ message (STATUS "Version: ${PROJECT_VERSION}") # flags if (CMAKE_COMPILER_IS_GNUCXX) - set (ADD_CXX_FLAGS "-Wall") - set (CMAKE_CXX_FLAGS "-O0 ${ADD_CXX_FLAGS}") - set (CMAKE_CXX_FLAGS_DEBUG "-g -O0") - set (CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") + set (CMAKE_CXX_FLAGS "-Wall -std=c++11") + set (CMAKE_CXX_FLAGS_DEBUG "-g -O0") + set (CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") else () - message (STATUS "Unknown compiler") + message (STATUS "Unknown compiler") endif () add_subdirectory (ext-sysmon) diff --git a/sources/ext-sysmon/CMakeLists.txt b/sources/ext-sysmon/CMakeLists.txt index 491c15e..0c87dd1 100644 --- a/sources/ext-sysmon/CMakeLists.txt +++ b/sources/ext-sysmon/CMakeLists.txt @@ -12,13 +12,15 @@ set (PLUGIN_NAME ${SUBPROJECT}) file (GLOB SUBPROJECT_DESKTOP_IN *.desktop) file (RELATIVE_PATH SUBPROJECT_DESKTOP ${CMAKE_SOURCE_DIR} ${SUBPROJECT_DESKTOP_IN}) file (GLOB SUBPROJECT_SOURCE *.cpp) +set (TASK_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/task.h) file (GLOB SUBPROJECT_CONF *.conf) # prepare configure_file (${SUBPROJECT_DESKTOP_IN} ${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_DESKTOP}) # make -kde4_add_plugin (${PLUGIN_NAME} ${SUBPROJECT_SOURCE}) +qt4_wrap_cpp (TASK_MOC_SOURCE ${TASK_HEADER}) +kde4_add_plugin (${PLUGIN_NAME} ${SUBPROJECT_SOURCE} ${TASK_MOC_SOURCE}) target_link_libraries (${PLUGIN_NAME} ${KDE4_KDECORE_LIBS} ${KDE4_PLASMA_LIBS}) # install diff --git a/sources/ext-sysmon/extsysmon.conf b/sources/ext-sysmon/extsysmon.conf index 7287428..d2d1cb7 100644 --- a/sources/ext-sysmon/extsysmon.conf +++ b/sources/ext-sysmon/extsysmon.conf @@ -2,7 +2,7 @@ # $kdehome/share/config/extsysmon.conf # Custom command, separator is '@@' -#CUSTOM=wget -qO- http://ifconfig.me/ip +#CUSTOM=curl ip4.telize.com # Command which returns number of the current desktop #DESKTOPCMD=qdbus org.kde.kwin /KWin currentDesktop diff --git a/sources/ext-sysmon/extsysmon.cpp b/sources/ext-sysmon/extsysmon.cpp index fe00987..c09c903 100644 --- a/sources/ext-sysmon/extsysmon.cpp +++ b/sources/ext-sysmon/extsysmon.cpp @@ -28,6 +28,8 @@ #include #include +#include "taskadds.h" + ExtendedSysMon::ExtendedSysMon(QObject* parent, const QVariantList& args) : Plasma::DataEngine(parent, args) @@ -44,7 +46,6 @@ ExtendedSysMon::ExtendedSysMon(QObject* parent, const QVariantList& args) setMinimumPollingInterval(333); readConfiguration(); - setProcesses(); setKeys(); } @@ -53,19 +54,17 @@ QString ExtendedSysMon::getAllHdd() { if (debug) qDebug() << "[DE]" << "[getAllHdd]"; - QProcess command; QStringList devices; QString cmd = QString("find /dev -name [hms]d[a-z]"); - QString qoutput = QString(""); - if (debug) qDebug() << "[DE]" << "[getAllHdd]" << ":" << "Run cmd" << cmd; - command.start(cmd); - command.waitForFinished(-1); - if (debug) qDebug() << "[DE]" << "[getAllHdd]" << ":" << "Cmd returns" << command.exitCode(); - qoutput = QTextCodec::codecForMib(106)->toUnicode(command.readAllStandardOutput()); + if (debug) qDebug() << "[DE]" << "[getAllHdd]" << ":" << "cmd" << cmd; + TaskResult process = runTask(cmd); + if (debug) qDebug() << "[DE]" << "[getAllHdd]" << ":" << "Cmd returns" << process.exitCode; + + QString qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output); for (int i=0; itoUnicode(command.readAllStandardOutput()); + if (debug) qDebug() << "[DE]" << "[getAutoGpu]" << ":" << "cmd" << cmd; + TaskResult process = runTask(cmd); + if (debug) qDebug() << "[DE]" << "[getAutoGpu]" << ":" << "Cmd returns" << process.exitCode; + + QString qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output); if (qoutput.toLower().contains("nvidia")) gpu = QString("nvidia"); else if (qoutput.toLower().contains("radeon")) gpu = QString("ati"); - if (debug) qDebug() << "[DE]" << "[getAutoGpu]" << ":" << "Device" << gpu; + if (debug) qDebug() << "[DE]" << "[getAutoGpu]" << ":" << "Device" << gpu; return gpu; } @@ -97,15 +94,14 @@ QString ExtendedSysMon::getAutoMpris() { if (debug) qDebug() << "[DE]" << "[getAutoMpris]"; - QProcess command; QString mpris; QString cmd = QString("bash -c \"qdbus 'org.mpris.MediaPlayer2.*'\""); - if (debug) qDebug() << "[DE]" << "[getAutoMpris]" << ":" << "Run cmd" << cmd; - command.start(cmd); - command.waitForFinished(-1); - QString cmdOutput = QTextCodec::codecForMib(106)->toUnicode(command.readAllStandardOutput()).trimmed(); - if (cmdOutput.split(QChar('\n'))[0].split(QChar('.')).count() > 3) - mpris = cmdOutput.split(QChar('\n'))[0].split(QChar('.'))[3]; + if (debug) qDebug() << "[DE]" << "[getAutoMpris]" << ":" << "cmd" << cmd; + TaskResult process = runTask(cmd); + + QString qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output).trimmed(); + if (qoutput.split(QChar('\n'))[0].split(QChar('.')).count() > 3) + mpris = qoutput.split(QChar('\n'))[0].split(QChar('.'))[3]; if (debug) qDebug() << "[DE]" << "[getAutoMpris]" << ":" << "Player found" << mpris; return mpris; @@ -162,8 +158,8 @@ QStringList ExtendedSysMon::sources() const source.append(QString("pkg")); source.append(QString("player")); source.append(QString("ps")); - if (debug) qDebug() << "[DE]" << "[sources]" << ":" << "Sources" << source; + if (debug) qDebug() << "[DE]" << "[sources]" << ":" << "Sources" << source; return source; } @@ -178,13 +174,53 @@ void ExtendedSysMon::initValues() } +void ExtendedSysMon::setKeys() +{ + if (debug) qDebug() << "[DE]" << "[setKeys]"; + + // custom + for (int i=0; i rawConfig; - rawConfig[QString("CUSTOM")] = QString("wget -qO- http://ifconfig.me/ip"); + rawConfig[QString("CUSTOM")] = QString("curl ip4.telize.com"); rawConfig[QString("DESKTOP")] = QString(""); rawConfig[QString("DESKTOPCMD")] = QString("qdbus org.kde.kwin /KWin currentDesktop"); rawConfig[QString("GPUDEV")] = QString("auto"); @@ -225,121 +261,6 @@ void ExtendedSysMon::readConfiguration() } -void ExtendedSysMon::setKeys() -{ - if (debug) qDebug() << "[DE]" << "[setKeys]"; - - QString key, source; - // custom - source = QString("custom"); - for (int i=0; i ExtendedSysMon::updateConfiguration(const QMap rawConfig) { if (debug) qDebug() << "[DE]" << "[updateConfiguration]"; @@ -400,107 +321,61 @@ QMap ExtendedSysMon::updateConfiguration(const QMapstate() != QProcess::Running) && - (processes[QString("desktop")][0]->state() != QProcess::Starting)) - processes[QString("desktop")][0]->start(QString("bash -c \"") + cmd + QString("\"")); -} + TaskResult process = runTask(QString("bash -c \"") + cmd + QString("\"")); + if (debug) qDebug() << "[DE]" << "[getCurrentDesktop]" << ":" << "Cmd returns" << process.exitCode; - -void ExtendedSysMon::setCurrentDesktop(int exitCode, QProcess::ExitStatus exitStatus) -{ - Q_UNUSED(exitStatus) - if (debug) qDebug() << "[DE]" << "[setCurrentDesktop]"; - if (debug) qDebug() << "[DE]" << "[setCurrentDesktop]" << ":" << "Cmd returns" << exitCode; - - QString qoutput = QTextCodec::codecForMib(106)->toUnicode(processes[QString("desktop")][0]->readAllStandardOutput()).trimmed(); + QString qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output).trimmed(); int number = qoutput.toInt(); - QString key, source, value; - source = QString("desktop"); + QMap currentDesktop; + currentDesktop[QString("currentName")] = configuration[QString("DESKTOP")].split(QString(";;"))[number-1]; + currentDesktop[QString("currentNumber")] = number; + currentDesktop[QString("list")] = configuration[QString("DESKTOP")]; + currentDesktop[QString("number")] = configuration[QString("DESKTOP")].split(QString(";;")).count(); - key = QString("list"); - setData(source, key, configuration[QString("DESKTOP")]); - key = QString("number"); - setData(source, key, configuration[QString("DESKTOP")].split(QString(";;")).count()); - key = QString("currentName"); - setData(source, key, configuration[QString("DESKTOP")].split(QString(";;"))[number-1]); - key = QString("currentNumber"); - setData(source, key, number); + return currentDesktop; } -void ExtendedSysMon::getCustomCmd(const QString cmd, const int number) +QString ExtendedSysMon::getCustomCmd(const QString cmd) { if (debug) qDebug() << "[DE]" << "[getCustomCmd]"; - if (debug) qDebug() << "[DE]" << "[getCustomCmd]" << ":" << "Run function with cmd" << cmd; - if (debug) qDebug() << "[DE]" << "[getCustomCmd]" << ":" << "Run function with number" << number; - if (debug) qDebug() << "[DE]" << "[getCustomCmd]" << ":" << "Run cmd" << QString("bash -c \"") + cmd + QString("\""); + if (debug) qDebug() << "[DE]" << "[getCustomCmd]" << ":" << "cmd" << cmd; - if ((processes[QString("custom")][number]->state() != QProcess::Running) && - (processes[QString("custom")][number]->state() != QProcess::Starting)) - processes[QString("custom")][number]->start(QString("bash -c \"") + cmd + QString("\"")); + TaskResult process = runTask(QString("bash -c \"") + cmd + QString("\"")); + if (debug) qDebug() << "[DE]" << "[getCustomCmd]" << ":" << "Cmd returns" << process.exitCode; + + return QTextCodec::codecForMib(106)->toUnicode(process.output).trimmed(); } -void ExtendedSysMon::setCustomCmd(int exitCode, QProcess::ExitStatus exitStatus) -{ - Q_UNUSED(exitStatus) - if (debug) qDebug() << "[DE]" << "[setCustomCmd]"; - if (debug) qDebug() << "[DE]" << "[setCustomCmd]" << ":" << "Cmd returns" << exitCode; - - for (int i=0; itoUnicode(processes[QString("custom")][i]->readAllStandardOutput()).trimmed(); - if (!value.isEmpty()) { - if (debug) qDebug() << "[DE]" << "[setCustomCmd]" << ":" << "Found data for cmd" << i; - if (debug) qDebug() << "[DE]" << "[setCustomCmd]" << ":" << "Return" << value; - QString source = QString("custom"); - QString key = QString("custom") + QString::number(i); - setData(source, key, value); - } - } -} - - -void ExtendedSysMon::getGpu(const QString device) +float ExtendedSysMon::getGpu(const QString device) { if (debug) qDebug() << "[DE]" << "[getGpu]"; - if (debug) qDebug() << "[DE]" << "[getGpu]" << ":" << "Run function with device" << device; + if (debug) qDebug() << "[DE]" << "[getGpu]" << ":" << "Device" << device; + float value = 0.0; if ((device != QString("nvidia")) && (device != QString("ati"))) - return; + return value; QString cmd = QString(""); if (device == QString("nvidia")) cmd = QString("nvidia-smi -q -d UTILIZATION"); else if (device == QString("ati")) cmd = QString("aticonfig --od-getclocks"); - if (debug) qDebug() << "[DE]" << "[getGpu]" << ":" << "Run cmd" << cmd; - if ((processes[QString("gpu")][0]->state() != QProcess::Running) && - (processes[QString("gpu")][0]->state() != QProcess::Starting)) - processes[QString("gpu")][0]->start(cmd); -} + if (debug) qDebug() << "[DE]" << "[getGpu]" << ":" << "cmd" << cmd; + TaskResult process = runTask(QString("bash -c \"") + cmd + QString("\"")); + if (debug) qDebug() << "[DE]" << "[getGpu]" << ":" << "Cmd returns" << process.exitCode; - -void ExtendedSysMon::setGpu(int exitCode, QProcess::ExitStatus exitStatus) -{ - Q_UNUSED(exitStatus) - if (debug) qDebug() << "[DE]" << "[setGpu]"; - if (debug) qDebug() << "[DE]" << "[setGpu]" << ":" << "Cmd returns" << exitCode; - - float value = 0.0; - QString qoutput; - if (configuration[QString("GPUDEV")] == QString("nvidia")) { - qoutput = QTextCodec::codecForMib(106)->toUnicode(processes[QString("gpu")][0]->readAllStandardOutput()); + QString qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output).trimmed(); + if (configuration[QString("GPUDEV")] == QString("nvidia")) for (int i=0; itoUnicode(processes[QString("gpu")][0]->readAllStandardOutput()); + else if (configuration[QString("GPUDEV")] == QString("ati")) for (int i=0; istate() != QProcess::Running) && - (processes[QString("gputemp")][0]->state() != QProcess::Running)) - processes[QString("gputemp")][0]->start(cmd); -} + if (debug) qDebug() << "[DE]" << "[getGpuTemp]" << ":" << "cmd" << cmd; + TaskResult process = runTask(QString("bash -c \"") + cmd + QString("\"")); + if (debug) qDebug() << "[DE]" << "[getGpuTemp]" << ":" << "Cmd returns" << process.exitCode; - -void ExtendedSysMon::setGpuTemp(int exitCode, QProcess::ExitStatus exitStatus) -{ - Q_UNUSED(exitStatus) - if (debug) qDebug() << "[DE]" << "[setGpuTemp]"; - if (debug) qDebug() << "[DE]" << "[setGpuTemp]" << ":" << "Cmd returns" << exitCode; - - float value = 0.0; - QString qoutput; - if (configuration[QString("GPUDEV")] == QString("nvidia")) { - qoutput = QTextCodec::codecForMib(106)->toUnicode(processes[QString("gputemp")][0]->readAllStandardOutput()); + QString qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output); + if (configuration[QString("GPUDEV")] == QString("nvidia")) for (int i=0; itoUnicode(processes[QString("gputemp")][0]->readAllStandardOutput()); + else if (configuration[QString("GPUDEV")] == QString("ati")) for (int i=0; istate() != QProcess::Running) && - (processes[QString("hddtemp")][number]->state() != QProcess::Starting)) - processes[QString("hddtemp")][number]->start(cmd + QString(" ") + device); -} + float value = 0.0; + TaskResult process = runTask(cmd + QString(" ") + device); + if (debug) qDebug() << "[DE]" << "[getHddTemp]" << ":" << "Cmd returns" << process.exitCode; - -void ExtendedSysMon::setHddTemp(int exitCode, QProcess::ExitStatus exitStatus) -{ - Q_UNUSED(exitStatus) - if (debug) qDebug() << "[DE]" << "[setHddTemp]"; - if (debug) qDebug() << "[DE]" << "[setHddTemp]" << ":" << "Cmd returns" << exitCode; - - for (int i=0; itoUnicode(processes[QString("hddtemp")][i]->readAllStandardOutput()).trimmed(); - if (qoutput.split(QChar(':'), QString::SkipEmptyParts).count() >= 3) { - if (debug) qDebug() << "[DE]" << "[setHddTemp]" << ":" << "Found data for cmd" << i; - QString temp = qoutput.split(QChar(':'), QString::SkipEmptyParts)[2]; - temp.remove(QChar(0260)).remove(QChar('C')); - value = temp.toFloat(); - if (debug) qDebug() << "[DE]" << "[setHddTemp]" << ":" << "Return" << value; - QString source = QString("hddtemp"); - QString key = configuration[QString("HDDDEV")].split(QChar(','), QString::SkipEmptyParts)[i]; - setData(source, key, value); - } + QString qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output).trimmed(); + if (qoutput.split(QChar(':'), QString::SkipEmptyParts).count() >= 3) { + QString temp = qoutput.split(QChar(':'), QString::SkipEmptyParts)[2]; + temp.remove(QChar(0260)).remove(QChar('C')); + value = temp.toFloat(); } + + return value; } -void ExtendedSysMon::getPlayerInfo(const QString playerName, - const QString mpdAddress, - const QString mpdPort, - QString mpris) +QMap ExtendedSysMon::getPlayerInfo(const QString playerName, + const QString mpdAddress, + const QString mpdPort, + QString mpris) { if (debug) qDebug() << "[DE]" << "[getPlayerInfo]"; - if (debug) qDebug() << "[DE]" << "[getPlayerInfo]" << ":" << "Run function with player" << playerName; - if (debug) qDebug() << "[DE]" << "[getPlayerInfo]" << ":" << "Run function with MPD parameters" << - mpdAddress + QString(":") + mpdPort; - if (debug) qDebug() << "[DE]" << "[getPlayerInfo]" << ":" << "Run function with MPRIS" << mpris; + if (debug) qDebug() << "[DE]" << "[getPlayerInfo]" << ":" << "player" << playerName; + if (debug) qDebug() << "[DE]" << "[getPlayerInfo]" << ":" << "MPD" << mpdAddress + QString(":") + mpdPort; + if (debug) qDebug() << "[DE]" << "[getPlayerInfo]" << ":" << "MPRIS" << mpris; + QMap info; + info[QString("album")] = QString("unknown"); + info[QString("artist")] = QString("unknown"); + info[QString("duration")] = QString("0"); + info[QString("progress")] = QString("0"); + info[QString("title")] = QString("unknown"); QString cmd; if (playerName == QString("mpd")) // mpd - cmd = QString("bash -c \"echo 'currentsong\nstatus\nclose' | curl --connect-timeout 1 -fsm 3 telnet://") + - mpdAddress + QString(":") + mpdPort + QString("\""); + cmd = QString("bash -c \"echo 'currentsong\nstatus\nclose' | curl --connect-timeout 1 -fsm 3 telnet://%1:%2\"") + .arg(mpdAddress) + .arg(mpdPort); else if (playerName == QString("mpris")) { // players which supports mpris if (mpris == "auto") @@ -645,224 +487,150 @@ void ExtendedSysMon::getPlayerInfo(const QString playerName, cmd = QString("bash -c \"qdbus org.mpris.%1 /Player GetMetadata && qdbus org.mpris.%1 /Player PositionGet\"") .arg(mpris); } - if (debug) qDebug() << "[DE]" << "[getPlayerInfo]" << ":" << "Run cmd" << cmd; - if ((processes[QString("player")][0]->state() != QProcess::Running) && - (processes[QString("player")][0]->state() != QProcess::Starting)) - processes[QString("player")][0]->start(cmd); -} + if (debug) qDebug() << "[DE]" << "[getPlayerInfo]" << ":" << "cmd" << cmd; + TaskResult process = runTask(cmd); + if (debug) qDebug() << "[DE]" << "[getPlayerInfo]" << ":" << "Cmd returns" << process.exitCode; - -void ExtendedSysMon::setPlayer(int exitCode, QProcess::ExitStatus exitStatus) -{ - Q_UNUSED(exitStatus) - if (debug) qDebug() << "[DE]" << "[setPlayer]"; - if (debug) qDebug() << "[DE]" << "[setPlayer]" << ":" << "Cmd returns" << exitCode; - - QString playerName = configuration[QString("PLAYER")]; - QString qoutput = QString(""); + QString qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output).trimmed(); QString qstr = QString(""); - QStringList info; - // album - info.append(QString("unknown")); - // artist - info.append(QString("unknown")); - // progress - info.append(QString("0")); - // duration - info.append(QString("0")); - // title - info.append(QString("unknown")); - if (playerName == QString("mpd")) { - qoutput = QTextCodec::codecForMib(106)->toUnicode(processes[QString("player")][0]->readAllStandardOutput()); - for (int i=0; i 1) { - if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("Album")) - info[0] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); - else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("Artist")) - info[1] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); - else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("time")) { - info[3] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed().split(QString(":"))[0]; - info[2] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed().split(QString(":"))[1]; - } - else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("Title")) - info[4] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); + if (playerName == QString("mpd")) + for (int i=0; i 1) { + if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("Album")) + info[QString("album")] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); + else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("Artist")) + info[QString("artist")] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); + else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("time")) { + info[QString("duration")] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed().split(QString(":"))[0]; + info[QString("progress")] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed().split(QString(":"))[1]; } + else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("Title")) + info[QString("title")] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); } } - else if (playerName == QString("mpris")) { - qoutput = QTextCodec::codecForMib(106)->toUnicode(processes[QString("player")][0]->readAllStandardOutput()); - if (!qoutput.isEmpty()) { - for (int i=0; i 1) { - if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("album")) - info[0] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); - else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("artist")) - info[1] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); - else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("time")) - info[3] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); - else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("title")) - info[4] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); - } - else { - int time = qstr.toInt() / 1000; - info[2] = QString::number(time); - } + else if (playerName == QString("mpris")) + for (int i=0; i 1) { + if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("album")) + info[QString("album")] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); + else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("artist")) + info[QString("artist")] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); + else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("time")) + info[QString("duration")] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); + else if (qstr.split(QString(": "), QString::SkipEmptyParts)[0] == QString("title")) + info[QString("title")] = qstr.split(QString(": "), QString::SkipEmptyParts)[1].trimmed(); + } + else { + int time = qstr.toInt() / 1000; + info[QString("progress")] = QString::number(time); } } - } - QString source = QString("player"); - QString key; - key = QString("album"); - setData(source, key, info[0]); - key = QString("artist"); - setData(source, key, info[1]); - key = QString("progress"); - setData(source, key, info[2]); - key = QString("duration"); - setData(source, key, info[3]); - key = QString("title"); - setData(source, key, info[4]); + return info; } -void ExtendedSysMon::getPsStats() +QMap ExtendedSysMon::getPsStats() { if (debug) qDebug() << "[DE]" << "[getPsStats]"; - QString cmd; + QMap psStats; + QString cmd, qoutput; cmd = QString("ps --no-headers -o command"); if (debug) qDebug() << "[DE]" << "[getPsStats]" << ":" << "Run cmd" << cmd; - if ((processes[QString("ps")][0]->state() != QProcess::Running) && - (processes[QString("ps")][0]->state() != QProcess::Starting)) - processes[QString("ps")][0]->start(cmd); + TaskResult process = runTask(cmd); + if (debug) qDebug() << "[DE]" << "[getPsStats]" << ":" << "Cmd returns" << process.exitCode; + + qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output).trimmed(); + QStringList psList; + for (int i=0; istate() != QProcess::Running) && - (processes[QString("ps")][1]->state() != QProcess::Starting)) - processes[QString("ps")][1]->start(cmd); + process = runTask(cmd); + if (debug) qDebug() << "[DE]" << "[getPsStats]" << ":" << "Cmd returns" << process.exitCode; + + qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output).trimmed(); + psStats[QString("psTotal")] = qoutput.split(QChar('\n'), QString::SkipEmptyParts).count(); + + return psStats; } -void ExtendedSysMon::setPs(int exitCode, QProcess::ExitStatus exitStatus) -{ - Q_UNUSED(exitStatus) - if (debug) qDebug() << "[DE]" << "[setPs]"; - if (debug) qDebug() << "[DE]" << "[setPs]" << ":" << "Cmd returns" << exitCode; - - QString qoutput = QString(""); - for (int i=0; itoUnicode(processes[QString("ps")][i]->readAllStandardOutput()).trimmed(); - if (!qoutput.isEmpty()) { - if (debug) qDebug() << "[DE]" << "[setPs]" << ":" << "Found data for cmd" << i; - if (i == 0) { - // pscount && ps - QStringList psList; - for (int i=0; istate() != QProcess::Running) && - (processes[QString("pkg")][number]->state() != QProcess::Starting)) - processes[QString("pkg")][number]->start(cmd); + TaskResult process = runTask(QString("bash -c \"") + cmd + QString("\"")); + if (debug) qDebug() << "[DE]" << "[getUpgradeInfo]" << ":" << "Cmd returns" << process.exitCode; + + QString qoutput = QTextCodec::codecForMib(106)->toUnicode(process.output).trimmed(); + + return qoutput.split(QChar('\n')).count(); } -void ExtendedSysMon::setUpgradeInfo(int exitCode, QProcess::ExitStatus exitStatus) -{ - Q_UNUSED(exitStatus) - if (debug) qDebug() << "[DE]" << "[setUpgradeInfo]"; - if (debug) qDebug() << "[DE]" << "[setUpgradeInfo]" << ":" << "Cmd returns" << exitCode; - - for (int i=0; itoUnicode(processes[QString("pkg")][i]->readAllStandardOutput()).trimmed(); - if (!qoutput.isEmpty()) { - if (debug) qDebug() << "[DE]" << "[setUpgradeInfo]" << ":" << "Found data for cmd" << i; - pkgNull = configuration[QString("PKGNULL")].split(QString(","), QString::SkipEmptyParts)[i].toInt(); - value = qoutput.toInt(); - if (debug) qDebug() << "[DE]" << "[setUpgradeInfo]" << ":" << "Return" << value; - QString source = QString("pkg"); - QString key = QString("pkgCount") + QString::number(i); - setData(source, key, value - pkgNull); - } - } -} - - -bool ExtendedSysMon::sourceRequestEvent(const QString &name) +bool ExtendedSysMon::sourceRequestEvent(const QString &source) { if (debug) qDebug() << "[DE]" << "[sourceRequestEvent]"; - if (debug) qDebug() << "[DE]" << "[sourceRequestEvent]" << ":" << "Run function with source name" << name; + if (debug) qDebug() << "[DE]" << "[sourceRequestEvent]" << ":" << "Source" << source; - return updateSourceEvent(name); + return updateSourceEvent(source); } bool ExtendedSysMon::updateSourceEvent(const QString &source) { if (debug) qDebug() << "[DE]" << "[updateSourceEvent]"; - if (debug) qDebug() << "[DE]" << "[updateSourceEvent]" << ":" << "Run function with source name" << source; + if (debug) qDebug() << "[DE]" << "[updateSourceEvent]" << ":" << "Source" << source; if (source == QString("custom")) { - for (int i=0; i desktop = getCurrentDesktop(configuration[QString("DESKTOPCMD")]); + for (int i=0; i player = getPlayerInfo(configuration[QString("PLAYER")], + configuration[QString("MPDADDRESS")], + configuration[QString("MPDPORT")], + configuration[QString("MPRIS")]); + for (int i=0; i ps = getPsStats(); + for (int i=0; i getCurrentDesktop(const QString cmd); + QString getCustomCmd(const QString cmd); + float getGpu(const QString device); + float getGpuTemp(const QString device); + float getHddTemp(const QString cmd, const QString device); + QMap getPlayerInfo(const QString playerName, + const QString mpdAddress = 0, + const QString mpdPort = 0, + QString mpris = 0); + QMap getPsStats(); + int getUpgradeInfo(const QString cmd); protected: - bool sourceRequestEvent(const QString &name); + bool sourceRequestEvent(const QString &source); bool updateSourceEvent(const QString &source); QStringList sources() const; -private slots: - void setCurrentDesktop(int exitCode, QProcess::ExitStatus exitStatus); - void setCustomCmd(int exitCode, QProcess::ExitStatus exitStatus); - void setGpu(int exitCode, QProcess::ExitStatus exitStatus); - void setGpuTemp(int exitCode, QProcess::ExitStatus exitStatus); - void setHddTemp(int exitCode, QProcess::ExitStatus exitStatus); - void setUpgradeInfo(int exitCode, QProcess::ExitStatus exitStatus); - void setPlayer(int exitCode, QProcess::ExitStatus exitStatus); - void setPs(int exitCode, QProcess::ExitStatus exitStatus); - private: - // processes - QMap > processes; // configuration QMap configuration; bool debug; @@ -70,9 +55,8 @@ private: QString getAutoMpris(); QStringList getDesktopNames(); void initValues(); - void readConfiguration(); void setKeys(); - void setProcesses(); + void readConfiguration(); QMap updateConfiguration(const QMap rawConfig); }; diff --git a/sources/ext-sysmon/task.h b/sources/ext-sysmon/task.h new file mode 120000 index 0000000..254b484 --- /dev/null +++ b/sources/ext-sysmon/task.h @@ -0,0 +1 @@ +../3rdparty/task/task.h \ No newline at end of file diff --git a/sources/ext-sysmon/taskadds.cpp b/sources/ext-sysmon/taskadds.cpp new file mode 120000 index 0000000..97b06b2 --- /dev/null +++ b/sources/ext-sysmon/taskadds.cpp @@ -0,0 +1 @@ +../3rdparty/task/taskadds.cpp \ No newline at end of file diff --git a/sources/ext-sysmon/taskadds.h b/sources/ext-sysmon/taskadds.h new file mode 120000 index 0000000..55b2cd9 --- /dev/null +++ b/sources/ext-sysmon/taskadds.h @@ -0,0 +1 @@ +../3rdparty/task/taskadds.h \ No newline at end of file