diff options
author | Ken Moore <ken@ixsystems.com> | 2018-02-01 17:10:42 -0500 |
---|---|---|
committer | Ken Moore <ken@ixsystems.com> | 2018-02-01 17:10:42 -0500 |
commit | 6f251cac292ee2657ec60e0e33ba02e3d08fade8 (patch) | |
tree | 5f5d7eacbf12bff4d7dd6061a8b5b747f12a8fa8 | |
parent | Fix up the single application numbering. (diff) | |
download | lumina-6f251cac292ee2657ec60e0e33ba02e3d08fade8.tar.gz lumina-6f251cac292ee2657ec60e0e33ba02e3d08fade8.tar.bz2 lumina-6f251cac292ee2657ec60e0e33ba02e3d08fade8.zip |
Get the FreeBSD OSInterface class all setup.
Also test/fix some stuff in the build side of things. OSInterface no longer uses the LUtils and LXDG classes from libLumina.
6 files changed, 383 insertions, 33 deletions
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/plugins/status_tray/BatteryButton.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/plugins/status_tray/BatteryButton.qml index 38ed6a64..8603e072 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/plugins/status_tray/BatteryButton.qml +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/plugins/status_tray/BatteryButton.qml @@ -16,5 +16,5 @@ ToolButton{ iconName: os.batteryIcon tooltip: os.batteryCharge+"%: "+os.batteryRemaining visible: os.batteryAvailable() - enabled: false + //enabled: false } diff --git a/src-qt5/src-cpp/framework-OSInterface-FreeBSD.cpp b/src-qt5/src-cpp/framework-OSInterface-FreeBSD.cpp new file mode 100644 index 00000000..a1bdbdca --- /dev/null +++ b/src-qt5/src-cpp/framework-OSInterface-FreeBSD.cpp @@ -0,0 +1,245 @@ +//=========================================== +// Lumina desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// FreeBSD/TrueOS specific OS Interactions +//=========================================== +// USEFUL INTERNAL FUNCTIONS: +//---------------------------------------------- +// bool verifyAppOrBin(QString chk) +//=========================================== +#include <framework-OSInterface.h> + +#include <unistd.h> +#include <sys/types.h> +#include <sys/sysctl.h> +#include <sys/unistd.h> + +// = Battery = +bool OSInterface::OS_batteryAvailable(){ + static int bat_avail = -1; //this will not change during a single session - keep later calls fast + if(bat_avail < 0){ + int val = getCmdOutput("apm -l").join("").toInt(); + bat_avail = ((val >= 0 && val <= 100) ? 1 : 0 ); + } + return (bat_avail==1); +} + +float OSInterface::OS_batteryCharge(){ + int charge = getCmdOutput("apm -l").join("").toInt(); + if(charge > 100){ charge = -1; } //invalid charge + return charge; +} + +bool OSInterface::OS_batteryCharging(){ + return (getCmdOutput("apm -a").join("").simplified() == "1"); +} + +double OSInterface::OS_batterySecondsLeft(){ //Returns: estimated number of seconds remaining + return getCmdOutput("apm -t").join("").toDouble(); +} + +// = Volume = +bool OSInterface::OS_volumeSupported(){ return true; } +int OSInterface::OS_volume(){ + int out = -1; + /*bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty(); + if(remoteSession){ + QStringList info = getCmdOutput("pactl list short sinks"); + qDebug() << "Got PA sinks:" << info; + out = 50; //TEMPORARY - still need to write up the info parsing + }else{*/ + //probe the system for the current volume (other utils could be changing it) + QString info = getCmdOutput("mixer -S vol").join(":").simplified(); //ignores any other lines + if(!info.isEmpty()){ + int L = info.section(":",1,1).toInt(); + int R = info.section(":",2,2).toInt(); + if(L>R){ out = L; } + else{ out = R; } + } + //} //end of Remote Session check + return out; +} + +bool OSInterface::OS_setVolume(int percent){ + if(percent<0){percent=0;} + else if(percent>100){percent=100;} + /*bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty(); + if(remoteSession){ + runCmd(QString("pactl set-sink-volume @DEFAULT_SINK@ ")+QString::number(percent)+"%"); + }else{*/ + QString info = getCmdOutput("mixer -S vol").join(":").simplified(); //ignores any other lines + if(!info.isEmpty()){ + int L = info.section(":",1,1).toInt(); + int R = info.section(":",2,2).toInt(); + int diff = L-R; + if((percent == L) && (L==R)){ return false; } //already set to that volume + if(diff<0){ R=percent; L=percent+diff; } //R Greater + else{ L=percent; R=percent-diff; } //L Greater or equal + //Check bounds + if(L<0){L=0;}else if(L>100){L=100;} + if(R<0){R=0;}else if(R>100){R=100;} + //Run Command + return (0==runCmd("mixer vol "+QString::number(L)+":"+QString::number(R)) ); + } + //} //end of Remote Session check + return false; +} + +// = Network Information = +QString OSInterface::OS_networkTypeFromDeviceName(QString name){ + //Return options: wifi, wired, cell, cell-2G, cell-3G, cell-4G + QString type = "wired"; + if(name.startsWith("wlan")){ type = "wifi"; } + //Not sure about cell connections . Probably still treated as wifi devices (wlan*) + return type; +} + +float OSInterface::OS_networkStrengthFromDeviceName(QString name){ + //NOTE: This will only run for non-wired devices (wifi, cell[-*]) + // Step 1 : Figure out which access point is currently connected + QStringList info = getCmdOutput("ifconfig", QStringList() << name).filter("bssid"); + if(info.isEmpty()){ return -1; } + QString bssid = info.first().section("bssid ",1,-1).section(" ",0,0); + // Step 2: Scan access point to get signal/noise + info = getCmdOutput("ifconfig", QStringList() << name << "list" << "scan").filter(bssid); + if(info.isEmpty()){ return -1; } + QString signoise =info.first().section(" ", 4,4).simplified(); + int sig = signoise.section(":",0,0).toInt(); + int noise = signoise.section(":",1,1).toInt(); + // Step 3: Turn signal/noise ratio into a percentage + int perc = qAbs(sig - noise) * 4; + return perc; //percentage +} + +// = Media Shortcuts = +QStringList OSInterface::OS_mediaDirectories(){ return QStringList() << "/media"; } //directory where XDG shortcuts are placed for interacting with media (local/remote) + +// = Updates = +bool OSInterface::OS_updatesSupported(){ return verifyAppOrBin("pc-updatemanager"); } + +bool OSInterface::OS_updatesAvailable(){ return QFile::exists("/tmp/.trueos-update-staged"); } +QString OSInterface::OS_updateDetails(){ return readFile("/tmp/.trueos-update-staged"); } //Information about any available updates + +bool OSInterface::OS_updatesRunning(){ return (runCmd("pgrep -F /tmp/.updateInProgress")==0); } +QString OSInterface::OS_updateLog(){ return QString(); } //Information about any currently-running update + +//Note: Because the second-stage updates on TrueOS actually happen on reboot, we never see a "finished" update +bool OSInterface::OS_updatesFinished(){ return false; } +QString OSInterface::OS_updateResults(){ return QString(); } //Information about any finished update + +void OSInterface::OS_startUpdates(){ runCmd("pc-updatemanager", QStringList() << "startupdate"); } //start stage 2 on reboot +bool OSInterface::OS_updateOnlyOnReboot(){ return true; } //Should the startUpdates function be called only when rebooting the system? +bool OSInterface::OS_updateCausesReboot(){ return true; } + +QDateTime OSInterface::OS_lastUpdate(){ return QDateTime(); } //The date/time of the previous updates +QString OSInterface::OS_lastUpdateResults(){ return QString(); } //Information about the previously-finished update + +// = System Power = +bool OSInterface::OS_canReboot(){ + int ret = eaccess("/sbin/shutdown", X_OK); + return (ret==0); +} +void OSInterface::OS_startReboot(){ runCmd("/sbin/shutdown", QStringList() << "-ro" << "now"); } + +bool OSInterface::OS_canShutdown(){ + int ret = eaccess("/sbin/shutdown", X_OK); + return (ret==0); +} +void OSInterface::OS_startShutdown(){ runCmd("/sbin/shutdown", QStringList() << "-po" << "now"); } + +bool OSInterface::OS_canSuspend(){ + int ret = eaccess("/usr/sbin/acpiconf", X_OK); + return (ret==0); +} +void OSInterface::OS_startSuspend(){ runCmd("zzz"); } //zzz runs "acpiconf -s <suspend state>" + +// = Screen Brightness = +bool OSInterface::OS_brightnessSupported(){ +//First run a quick check to ensure this is not a VirtualBox VM (no brightness control) + static int goodsys = -1; //This will not change over time - only check/set once + if(goodsys<0){ + //Make sure we are not running in VirtualBox (does not work in a VM) + QStringList info = getCmdOutput("pciconf -lv"); + if( info.filter("VirtualBox", Qt::CaseInsensitive).isEmpty() ){ goodsys = 1; } + else{ goodsys = 0; } //not a good system + } + if(goodsys!=1){ return false; } //go ahead and stop here - not a good system + QStringList tools; tools << "intel_backlight" << "xbrightness"; + bool ok = false; + for(int i=0; i<tools.length() && !ok; i++){ ok = verifyAppOrBin(tools[i]); } + return ok; +} + +int OSInterface::OS_brightness(){ + //return percentage: 0-100 with -1 for errors + QStringList tools; tools << "intel_backlight" << "xbrightness"; + //NOTE: xbacklight does not have a way to return the current brightness + int num = -1; + for(int i=0; i<tools.length() && num<0; i++){ + if(!verifyAppOrBin(tools[i])){ continue; } + switch(i){ + case 0: //intel_backlight + num = getCmdOutput("intel_backlight").join("").section("%",0,0).section(":",1,1).simplified().toInt(); + break; + default: + num = -1; + } + } + if(num>100){ num=100; } //quick verification of upper limit + else if(num<-1){ num = -1; } //something really messed up - return the error code + return num; +} + +bool OSInterface::OS_setBrightness(int percent){ + QStringList tools; tools << "intel_backlight" << "xbrightness"; + for(int i=0; i<tools.length(); i++){ + if(!verifyAppOrBin(tools[i])){ continue; } + QStringList args; + switch(i){ + case 0: //intel_backlight + args << QString::number(percent); + break; + case 1: //xbrightness + args << QString::number( qRound( (percent/100.0)*65535) ); //xbrightness has a scale of 0-65535 + break; + } + return (0 == runCmd(tools[i], args) ); + } + return false; +} + +// = System Status Monitoring +bool OSInterface::OS_cpuSupported(){ return false; } +QList<int> OSInterface::OS_cpuPercentage(){ return QList<int>(); } // (one per CPU) percentage: 0-100 with empty list for errors +QStringList OSInterface::OS_cpuTemperatures(){ return QStringList(); } // (one per CPU) Temperature of CPU ("50C" for example) + +bool OSInterface::OS_memorySupported(){ return false; } +int OSInterface::OS_memoryUsedPercentage(){ return -1; } //percentage: 0-100 with -1 for errors +QString OSInterface::OS_memoryTotal(){ return QString(); } //human-readable form - does not tend to change within a session +QStringList OSInterface::OS_diskIO(){ return QStringList(); } //Returns list of current read/write stats for each device + +bool OSInterface::OS_diskSupported(){ return false; } +int OSInterface::OS_fileSystemPercentage(QString dir){ return -1; } //percentage of capacity used: 0-100 with -1 for errors +QString OSInterface::OS_fileSystemCapacity(QString dir){ return QString(); } //human-readable form - total capacity + +// = OS-Specific Utilities = +QString OSInterface::controlPanelShortcut(){ return "pccontrol.desktop"; } //relative *.desktop shortcut name (Example: "some_utility.desktop") +QString OSInterface::audioMixerShortcut(){ return "pc-mixer -notray"; } //relative *.desktop shortcut name (Example: "some_utility.desktop") +QString OSInterface::appStoreShortcut(){ return "appcafe.desktop"; } //relative *.desktop shortcut name (Example: "some_utility.desktop") +QString OSInterface::networkManagerUtility(){ return "pc-netmanager.desktop"; } //relative *.desktop shortcut name (Example: "some_utility.desktop") + +//FileSystemWatcher slots (optional - re-implement only if needed/used by this OS) +void OSInterface::watcherFileChanged(QString){} //any additional parsing for files that are watched +void OSInterface::watcherDirChanged(QString dir){ //any additional parsing for watched directories + if(handleMediaDirChange(dir)){ return; } //auto-handled media directories +} + +//IO Device slots (optional - implement only if needed/used by this OS) +void OSInterface::iodeviceReadyRead(){} +void OSInterface::iodeviceAboutToClose(){} + +void OSInterface::netRequestFinished(QNetworkReply*){} +void OSInterface::netSslErrors(QNetworkReply*, const QList<QSslError>&){} diff --git a/src-qt5/src-cpp/framework-OSInterface-template.cpp b/src-qt5/src-cpp/framework-OSInterface-template.cpp index 6d1a7e74..c9c7775a 100644 --- a/src-qt5/src-cpp/framework-OSInterface-template.cpp +++ b/src-qt5/src-cpp/framework-OSInterface-template.cpp @@ -4,6 +4,12 @@ // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== +// USEFUL INTERNAL FUNCTIONS: (See framework-OSInterface.h for all possibilities); +//---------------------------------------------- +// bool verifyAppOrBin(QString chk) : Returns true is the check is a valid binary or application (*.desktop) +// int runCmd(QString command, QStringList arguments) : return code of command is returned +// QStringList getCmdOutput(QString command, QStringList arguments) : returns standard output of command +//=========================================== #include <framework-OSInterface.h> // = Battery = @@ -15,7 +21,7 @@ double OSInterface::OS_batterySecondsLeft(){ return -1; } // = Volume = bool OSInterface::OS_volumeSupported(){ return false; } int OSInterface::OS_volume(){ return -1; } -void OSInterface::OS_setVolume(int){} +bool OSInterface::OS_setVolume(int){ return false;} // = Network Information = QString OSInterface::OS_networkTypeFromDeviceName(QString name){ @@ -56,7 +62,7 @@ void OSInterface::OS_startSuspend(){} // = Screen Brightness = bool OSInterface::OS_brightnessSupported(){ return false; } int OSInterface::OS_brightness(){ return -1; } //percentage: 0-100 with -1 for errors -void OSInterface::OS_setBrightness(int){} +bool OSInterface::OS_setBrightness(int){ return false; } // = System Status Monitoring bool OSInterface::OS_cpuSupported(){ return false; } diff --git a/src-qt5/src-cpp/framework-OSInterface.h b/src-qt5/src-cpp/framework-OSInterface.h index 2f1795a1..2c4a4e0c 100644 --- a/src-qt5/src-cpp/framework-OSInterface.h +++ b/src-qt5/src-cpp/framework-OSInterface.h @@ -33,7 +33,7 @@ #include <QNetworkInterface> //Lumina Utils class -#include <LUtils.h> +//#include <LUtils.h> class OSInterface : public QObject{ Q_OBJECT @@ -165,7 +165,7 @@ public: // = Volume = bool OS_volumeSupported(); int OS_volume(); - void OS_setVolume(int); + bool OS_setVolume(int); // = Network Information = QString OS_networkTypeFromDeviceName(QString name); float OS_networkStrengthFromDeviceName(QString name); @@ -194,7 +194,7 @@ public: // = Screen Brightness = bool OS_brightnessSupported(); int OS_brightness(); - void OS_setBrightness(int); + bool OS_setBrightness(int); // = System Status Monitoring bool OS_cpuSupported(); QList<int> OS_cpuPercentage(); @@ -219,10 +219,10 @@ private slots: void iodeviceReadyRead(); void iodeviceAboutToClose(); //NetworkAccessManager slots - void netAccessChanged(QNetworkAccessManager::NetworkAccessibility); void netRequestFinished(QNetworkReply*); void netSslErrors(QNetworkReply*, const QList<QSslError>&); //Timer slots + void NetworkTimerUpdate(); void BatteryTimerUpdate(); void UpdateTimerUpdate(); void BrightnessTimerUpdate(); @@ -259,7 +259,7 @@ private: //Network Access Manager (check network connectivity, etc) QNetworkAccessManager *netman; //Timer for regular probes/updates - QTimer *batteryTimer, *updateTimer, *brightnessTimer, *volumeTimer, *cpuTimer, *memTimer, *diskTimer; + QTimer *networkTimer, *batteryTimer, *updateTimer, *brightnessTimer, *volumeTimer, *cpuTimer, *memTimer, *diskTimer; // Internal implifications for connecting the various watcher objects to their respective slots // (OS-agnostic - defined in the "OSInterface_private.cpp" file) @@ -269,16 +269,19 @@ private: //Internal simplification routines bool verifyAppOrBin(QString chk); + QString runProcess(int &retcode, QString command, QStringList arguments, QString workdir = "", QStringList env = QStringList()); + int runCmd(QString command, QStringList args = QStringList()); + QStringList getCmdOutput(QString command, QStringList args = QStringList()); + bool findInDirectory(QString file, QString dirpath, bool recursive=true); + QString readFile(QString path); // External Media Management (if system uses *.desktop shortcuts only) void setupMediaWatcher(); bool handleMediaDirChange(QString dir); //returns true if directory was handled QStringList autoHandledMediaFiles(); - // Qt-based NetworkAccessManager usage - void setupNetworkManager(); - - // Timer-based monitors + // Timer-based setups + void setupNetworkManager(int update_ms, int delay_ms); void setupBatteryMonitor(int update_ms, int delay_ms); void setupUpdateMonitor(int update_ms, int delay_ms); void setupBrightnessMonitor(int update_ms, int delay_ms); @@ -288,6 +291,7 @@ private: void setupDiskMonitor(int update_ms, int delay_ms); // Timer-based monitor update routines (NOTE: these are all run in a separate thread!!) + void syncNetworkInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer); void syncBatteryInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer); void syncUpdateInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer); void syncBrightnessInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer); diff --git a/src-qt5/src-cpp/framework-OSInterface.pri b/src-qt5/src-cpp/framework-OSInterface.pri index fa6e966c..3a456382 100644 --- a/src-qt5/src-cpp/framework-OSInterface.pri +++ b/src-qt5/src-cpp/framework-OSInterface.pri @@ -1,11 +1,18 @@ -QT *= core network quick +QT *= core network quick concurrent + +#include(../core/libLumina/LUtils.pri) +#include(../core/libLumina/LuminaXDG.pri) -include(../core/libLumina/LUtils.pri) -include(../core/libLumina/LuminaXDG.pri) HEADERS *= $${PWD}/framework-OSInterface.h SOURCES *= $${PWD}/framework-OSInterface_private.cpp -_os=template -SOURCES *= $${PWD}/framework-OSInterface-$${_os}.cpp +#Load the proper OS *.cpp file +exists($${PWD}/framework-OSInterface-$${LINUX_DISTRO}.cpp){ + SOURCES *= $${PWD}/framework-OSInterface-$${LINUX_DISTRO}.cpp +}else:exists($${PWD}/framework-OSInterface-$${OS}.cpp){ + SOURCES *= $${PWD}/framework-OSInterface-$${OS}.cpp +}else{ + SOURCES *= $${PWD}/framework-OSInterface-template.cpp +} INCLUDEPATH *= $${PWD} diff --git a/src-qt5/src-cpp/framework-OSInterface_private.cpp b/src-qt5/src-cpp/framework-OSInterface_private.cpp index 733fc61f..36da1bd4 100644 --- a/src-qt5/src-cpp/framework-OSInterface_private.cpp +++ b/src-qt5/src-cpp/framework-OSInterface_private.cpp @@ -50,7 +50,7 @@ void OSInterface::RegisterType(){ //Start/stop interface systems void OSInterface::start(){ if(!mediaDirectories().isEmpty()){ setupMediaWatcher(); }//will create/connect the filesystem watcher automatically - setupNetworkManager(); //will create/connect the network monitor automatically + setupNetworkManager(60000, 1); //will create/connect the network monitor automatically if(batteryAvailable()){ setupBatteryMonitor(30000, 1); } //30 second updates, 1 ms init delay if(brightnessSupported()){ setupBrightnessMonitor(60000, 1); } //1 minute updates, 1 ms init delay if(volumeSupported()){ setupVolumeMonitor(60000, 2); } //1 minute updates, 2 ms init delay @@ -87,22 +87,100 @@ void OSInterface::connectIodevice(){ void OSInterface::connectNetman(){ if(netman==0){ return; } - connect(netman, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(netAccessChanged(QNetworkAccessManager::NetworkAccessibility)) ); + connect(netman, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(netAccessChanged()) ); connect(netman, SIGNAL(finished(QNetworkReply*)), this, SLOT(netRequestFinished(QNetworkReply*)) ); connect(netman, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(netSslErrors(QNetworkReply*, const QList<QSslError>&)) ); } bool OSInterface::verifyAppOrBin(QString chk){ bool valid = !chk.isEmpty(); + if(chk.contains(" ")){ chk = chk.section(" ",0,0); } if(valid && chk.endsWith(".desktop")){ - chk = LUtils::AppToAbsolute(chk); - valid = QFile::exists(chk); + if(chk.startsWith("/")){ return QFile::exists(chk); } + valid = false; + QStringList paths; + paths << QString(getenv("XDG_DATA_HOME")) << QString(getenv("XDG_DATA_DIRS")).split(":"); + for(int i=0; i<paths.length() && !valid; i++){ + if(QFile::exists(paths[i]+"/applications")){ valid = findInDirectory(chk, paths[i]+"/applications", true); } + } }else if(valid){ - valid = LUtils::isValidBinary(chk); + //Find the absolute path for this binary + if(!chk.startsWith("/")){ + QStringList paths = QString(getenv("PATH")).split(":"); + for(int i=0; i<paths.length(); i++){ + if(QFile::exists(paths[i]+"/"+chk)){ chk = paths[i]+"/"+chk; break; } + } + if(!chk.startsWith("/")){ return false; } //could not find the file + }else if(!QFile::exists(chk)){ + return false; //file does not exist + } + //Make sure it is executable by the user + valid = QFileInfo(chk).isExecutable(); } return valid; } +QString OSInterface::runProcess(int &retcode, QString command, QStringList arguments, QString workdir, QStringList env){ + QProcess proc; + proc.setProcessChannelMode(QProcess::MergedChannels); //need output + //First setup the process environment as necessary + QProcessEnvironment PE = QProcessEnvironment::systemEnvironment(); + if(!env.isEmpty()){ + for(int i=0; i<env.length(); i++){ + if(!env[i].contains("=")){ continue; } + PE.insert(env[i].section("=",0,0), env[i].section("=",1,100)); + } + } + proc.setProcessEnvironment(PE); + //if a working directory is specified, check it and use it + if(!workdir.isEmpty()){ + proc.setWorkingDirectory(workdir); + } + //Now run the command (with any optional arguments) + if(arguments.isEmpty()){ proc.start(command); } + else{ proc.start(command, arguments); } + //Wait for the process to finish (but don't block the event loop) + for(int i=0; i<10 && !proc.waitForFinished(500); i++){ //maximum of 5 seconds for command to finish + if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal - go ahead and stop now + } + if(proc.state() != QProcess::NotRunning){ proc.terminate(); } //just in case - make sure to kill off the process + QString info = proc.readAllStandardOutput(); + retcode = proc.exitCode(); //return success/failure + return info; +} + +int OSInterface::runCmd(QString command, QStringList args){ + int retcode; + runProcess(retcode, command, args); + return retcode; +} + +QStringList OSInterface::getCmdOutput(QString command, QStringList args){ + int retcode; + return runProcess(retcode, command, args).split("\n"); +} + +bool OSInterface::findInDirectory(QString file, QString dirpath, bool recursive){ + bool found = QFile::exists(dirpath+"/"+file); + if(!found && recursive){ + QDir dir(dirpath); + QStringList dirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + for(int i=0; i<dirs.length() && !found; i++){ found = findInDirectory(file, dir.absoluteFilePath(dirs[i]), recursive); } + } + return found; +} + +QString OSInterface::readFile(QString path){ + QFile file(path); + QString info; + if(file.open(QIODevice::ReadOnly)){ + QTextStream out(&file); + info = out.readAll(); + file.close(); + } + return info; +} + // =========================== // OS SPECIFIC EXISTANCE CHECKS // =========================== @@ -162,13 +240,16 @@ QStringList OSInterface::autoHandledMediaFiles(){ // NETWORK INTERFACE FUNCTIONS // ============================= // Qt-based NetworkAccessManager usage -void OSInterface::setupNetworkManager(){ +void OSInterface::setupNetworkManager(int update_ms, int delay_ms){ if(netman==0){ netman = new QNetworkAccessManager(this); connectNetman(); } - //Load the initial state of the network accessibility - netAccessChanged(netman->networkAccessible()); + networkTimer = new QTimer(this); + networkTimer->setSingleShot(true); + networkTimer->setInterval(update_ms); + connect(networkTimer, SIGNAL(timeout()), this, SLOT(NetworkTimerUpdate()) ); + QTimer::singleShot(delay_ms, this, SLOT(NetworkTimerUpdate()) ); } bool OSInterface::networkAvailable(){ @@ -211,9 +292,9 @@ QString OSInterface::networkStatus(){ } //NetworkAccessManager slots -void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility stat){ +void OSInterface::syncNetworkInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){ //qDebug() << "[DEBUG] Got Net Access Changed"; - INFO.insert("netaccess/available", stat== QNetworkAccessManager::Accessible); + hash->insert("netaccess/available", netman->networkAccessible()== QNetworkAccessManager::Accessible); //Update all the other network status info at the same time QNetworkConfiguration active = netman->activeConfiguration(); //Type of connection @@ -226,10 +307,10 @@ void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility s case QNetworkConfiguration::Bearer4G: type="cell-4G"; break; default: type=OS_networkTypeFromDeviceName(active.name()); //could not be auto-determined - run the OS-specific routine } - INFO.insert("netaccess/type", type); + hash->insert("netaccess/type", type); float strength = 100; if(type!="wired"){ strength = OS_networkStrengthFromDeviceName(active.name()); } - INFO.insert("netaccess/strength", strength); + hash->insert("netaccess/strength", strength); //qDebug() << "Detected Device Status:" << active.identifier() << type << stat; QNetworkInterface iface = QNetworkInterface::interfaceFromName(active.name()); @@ -243,7 +324,7 @@ void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility s } //qDebug() << " - IP Address:" << address; //qDebug() << " - Hostname:" << networkHostname(); - INFO.insert("netaccess/address", address.join(", ")); + hash->insert("netaccess/address", address.join(", ")); //Figure out the icon used for this type/strnegth QString icon; @@ -270,9 +351,10 @@ void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility s }else{ icon = "network-workgroup"; //failover to a generic "network" icon } - INFO.insert("netaccess/icon",icon); + hash->insert("netaccess/icon",icon); //qDebug() << "[DEBUG] Emit NetworkStatusChanged"; - emit networkStatusChanged(); + os->emit networkStatusChanged(); + timer->start(); } @@ -280,6 +362,12 @@ void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility s // TIMER-BASED MONITORS // ======================== //Timer slots + +void OSInterface::NetworkTimerUpdate(){ + if(networkTimer->isActive()){ networkTimer->stop(); } //just in case this was manually triggered + QtConcurrent::run(this, &OSInterface::syncNetworkInfo, this, &INFO, networkTimer); +} + void OSInterface::BatteryTimerUpdate(){ if(batteryTimer->isActive()){ batteryTimer->stop(); } //just in case this was manually triggered QtConcurrent::run(this, &OSInterface::syncBatteryInfo, this, &INFO, batteryTimer); @@ -431,7 +519,7 @@ void OSInterface::syncBrightnessInfo(OSInterface *os, QHash<QString, QVariant> * void OSInterface::syncVolumeInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){ int oldvol = volume(); int newvol = OS_volume(); - if(oldvol!=newvol){ + if(oldvol!=newvol && newvol>=0){ hash->insert("volume/current",newvol); QString icon; if(newvol>66){ icon = "audio-volume-high"; } |