loader.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. /*
  2. * Copyright (C) 2015 Malte Veerman <maldela@halloarsch.de>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. *
  18. */
  19. #include "loader.h"
  20. #include "hwmon.h"
  21. #include "fancontrolaction.h"
  22. #include <QtCore/QFile>
  23. #include <QtCore/QDir>
  24. #include <QtCore/QTextStream>
  25. #include <QtCore/QTimer>
  26. #include <QtCore/QDebug>
  27. #include <KAuth/KAuthExecuteJob>
  28. #include <KI18n/KLocalizedString>
  29. #define HWMON_PATH "/sys/class/hwmon"
  30. #ifndef STANDARD_CONFIG_FILE
  31. #define STANDARD_CONFIG_FILE "/etc/fancontrol"
  32. #endif
  33. namespace Fancontrol
  34. {
  35. Loader::Loader(QObject *parent) : QObject(parent),
  36. m_interval(10),
  37. m_configUrl(QUrl::fromLocalFile(QStringLiteral(STANDARD_CONFIG_FILE))),
  38. m_timer(new QTimer(this))
  39. {
  40. parseHwmons();
  41. m_timer->setSingleShot(false);
  42. m_timer->start(1);
  43. connect(m_timer, SIGNAL(timeout()), this, SLOT(updateSensors()));
  44. }
  45. void Loader::parseHwmons()
  46. {
  47. QDir hwmonDir(QStringLiteral(HWMON_PATH));
  48. QStringList list;
  49. if (hwmonDir.isReadable())
  50. list = hwmonDir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
  51. else if (hwmonDir.exists())
  52. {
  53. setError(i18n("%1 is not readable!", QStringLiteral(HWMON_PATH)), true);
  54. return;
  55. }
  56. else
  57. {
  58. setError(i18n("%1 does not exist!", QStringLiteral(HWMON_PATH)), true);
  59. return;
  60. }
  61. QStringList dereferencedList;
  62. while (!list.isEmpty())
  63. dereferencedList << QFile::symLinkTarget(hwmonDir.absoluteFilePath(list.takeFirst()));
  64. foreach (Hwmon *hwmon, m_hwmons)
  65. {
  66. if (!dereferencedList.contains(hwmon->path()))
  67. {
  68. m_hwmons.removeOne(hwmon);
  69. emit hwmonsChanged();
  70. hwmon->deleteLater();
  71. }
  72. else
  73. hwmon->initialize();
  74. }
  75. foreach (const QString &hwmonPath, dereferencedList)
  76. {
  77. bool hwmonExists = false;
  78. foreach (const Hwmon *hwmon, m_hwmons)
  79. {
  80. if (hwmon->path() == hwmonPath)
  81. {
  82. hwmonExists = true;
  83. break;
  84. }
  85. }
  86. if (!hwmonExists)
  87. {
  88. Hwmon *newHwmon = new Hwmon(hwmonPath, this);
  89. if (newHwmon->isValid())
  90. {
  91. connect(this, SIGNAL(sensorsUpdateNeeded()), newHwmon, SLOT(updateSensors()));
  92. m_hwmons << newHwmon;
  93. emit hwmonsChanged();
  94. }
  95. else
  96. delete newHwmon;
  97. }
  98. }
  99. }
  100. PwmFan * Loader::getPwmFan(const QPair<int, int> &indexPair) const
  101. {
  102. Hwmon *hwmon = m_hwmons.value(indexPair.first, Q_NULLPTR);
  103. if (!hwmon)
  104. return Q_NULLPTR;
  105. return hwmon->pwmFan(indexPair.second);
  106. }
  107. Temp * Loader::getTemp(const QPair<int, int> &indexPair) const
  108. {
  109. Hwmon *hwmon = m_hwmons.value(indexPair.first, Q_NULLPTR);
  110. if (!hwmon)
  111. return Q_NULLPTR;
  112. return hwmon->temp(indexPair.second);
  113. }
  114. QPair<int, int> Loader::getEntryNumbers(const QString &entry)
  115. {
  116. if (entry.isEmpty())
  117. {
  118. qWarning() << "Loader::getHwmonNumber(): given empty string.";
  119. return QPair<int, int>(-1, -1);
  120. }
  121. QStringList list = entry.split('/', QString::SkipEmptyParts);
  122. if (list.size() != 2)
  123. {
  124. qWarning() << "Invalid entry to parse:" << entry << "Should contain exactly one \'/\'";
  125. return QPair<int, int>(-1, -1);
  126. }
  127. QString hwmon = list.at(0);
  128. QString sensor = list.at(1);
  129. if (!hwmon.startsWith(QStringLiteral("hwmon")))
  130. {
  131. qWarning() << "Invalid entry to parse:" << entry << "Should begin with \"hwmon\"";
  132. return QPair<int, int>(-1, -1);
  133. }
  134. if (!sensor.contains(QRegExp("^(pwm|fan|temp)\\d+")))
  135. {
  136. qWarning() << "Invalid entry to parse:" << entry << "\n Sensor should begin with pwm|fan|temp followed by a number";
  137. return QPair<int, int>(-1, -1);
  138. }
  139. bool success;
  140. hwmon.remove(QStringLiteral("hwmon"));
  141. sensor.remove(QRegExp("^(pwm|fan|temp)"));
  142. sensor.remove(QStringLiteral("_input"));
  143. int hwmonResult = hwmon.toInt(&success);
  144. if (!success)
  145. {
  146. qWarning() << "Invalid entry to parse:" << entry << "Could not convert" << hwmon << "to int";
  147. return QPair<int, int>(-1, -1);
  148. }
  149. int sensorResult = sensor.toInt(&success);
  150. if (!success)
  151. {
  152. qWarning() << "Invalid entry to parse:" << entry << "Could not convert" << sensor << "to int";
  153. return QPair<int, int>(-1, -1);
  154. }
  155. return QPair<int, int>(hwmonResult, sensorResult - 1);
  156. }
  157. void Loader::parseConfigLine(const QString &line, void (PwmFan::*memberSetFunction)(int)) const
  158. {
  159. if (!memberSetFunction)
  160. {
  161. qWarning() << "Loader::parseConfigLine(): Null for member function pointer";
  162. return;
  163. }
  164. QStringList entries = line.split(' ');
  165. foreach (const QString &entry, entries)
  166. {
  167. QStringList fanValuePair = entry.split('=');
  168. if (fanValuePair.size() == 2)
  169. {
  170. QString fanString = fanValuePair.at(0);
  171. QString valueString = fanValuePair.at(1);
  172. bool success;
  173. int value = valueString.toInt(&success);
  174. if (success)
  175. {
  176. PwmFan *fan = getPwmFan(getEntryNumbers(fanString));
  177. if (fan)
  178. (fan->*memberSetFunction)(value);
  179. }
  180. else
  181. qWarning() << valueString << "is not an int";
  182. }
  183. else
  184. qWarning() << "Invalid Entry:" << entry;
  185. }
  186. }
  187. bool Loader::load(const QUrl &url)
  188. {
  189. QString fileName;
  190. if (url.isEmpty())
  191. {
  192. qDebug() << "Given empty url. Fallback to " << m_configUrl;
  193. fileName = m_configUrl.toLocalFile();
  194. }
  195. else if (url.isValid())
  196. {
  197. if (url.isLocalFile())
  198. fileName = url.toLocalFile();
  199. else
  200. {
  201. setError(i18n("%1 is not a local file!", url.toDisplayString()));
  202. return false;
  203. }
  204. }
  205. else
  206. {
  207. setError(i18n("%1 is not a valid url!", url.toDisplayString()));
  208. return false;
  209. }
  210. QTextStream stream;
  211. QFile file(fileName);
  212. QString fileContent;
  213. if (file.open(QFile::ReadOnly | QFile::Text))
  214. {
  215. if (!url.isEmpty())
  216. {
  217. m_configUrl = url;
  218. emit configUrlChanged();
  219. }
  220. stream.setDevice(&file);
  221. fileContent = stream.readAll();
  222. }
  223. else if (file.exists())
  224. {
  225. KAuth::Action action = newFancontrolAction();
  226. QVariantMap map;
  227. map[QStringLiteral("action")] = QVariant("read");
  228. map[QStringLiteral("filename")] = fileName;
  229. action.setArguments(map);
  230. KAuth::ExecuteJob *reply = action.execute();
  231. if (!reply->exec())
  232. {
  233. if (reply->error() == 4)
  234. {
  235. qDebug() << "Aborted by user";
  236. return false;
  237. }
  238. qDebug() << "Error while loading:" << reply->error();
  239. setError(reply->errorString() + reply->errorText(), true);
  240. return false;
  241. }
  242. else
  243. {
  244. if (!url.isEmpty())
  245. {
  246. m_configUrl = url;
  247. emit configUrlChanged();
  248. }
  249. fileContent = reply->data().value(QStringLiteral("content")).toString();
  250. }
  251. }
  252. else
  253. {
  254. if (!url.isEmpty())
  255. {
  256. emit invalidConfigUrl();
  257. setError(i18n("%1 does not exist!", file.fileName()));
  258. }
  259. return false;
  260. }
  261. //Disconnect hwmons for performance reasons
  262. //They get reconnected later
  263. foreach (Hwmon *hwmon, m_hwmons)
  264. {
  265. disconnect(hwmon, SIGNAL(configUpdateNeeded()), this, SLOT(createConfigFile()));
  266. foreach (QObject *pwmFan, hwmon->pwmFans())
  267. {
  268. qobject_cast<PwmFan *>(pwmFan)->reset();
  269. }
  270. }
  271. stream.setString(&fileContent);
  272. QStringList lines;
  273. do
  274. {
  275. QString line(stream.readLine());
  276. if (line.startsWith('#') || line.trimmed().isEmpty())
  277. continue;
  278. int offset = line.indexOf('#');
  279. if (offset != -1)
  280. line.truncate(offset-1);
  281. line = line.simplified();
  282. lines << line;
  283. }
  284. while(!stream.atEnd());
  285. foreach (QString line, lines)
  286. {
  287. if (line.startsWith(QStringLiteral("INTERVAL=")))
  288. {
  289. line.remove(QStringLiteral("INTERVAL="));
  290. bool success;
  291. int interval = line.toInt(&success);
  292. if (success)
  293. {
  294. setInterval(interval, false);
  295. }
  296. else
  297. {
  298. //Connect hwmons again
  299. foreach (Hwmon *hwmon, m_hwmons)
  300. connect(hwmon, SIGNAL(configUpdateNeeded()), this, SLOT(createConfigFile()));
  301. setError(i18n("Unable to parse interval line: \n %1", line), true);
  302. return false;
  303. }
  304. }
  305. else if (line.startsWith(QStringLiteral("FCTEMPS=")))
  306. {
  307. line.remove(QStringLiteral("FCTEMPS="));
  308. QStringList fctemps = line.split(' ');
  309. foreach (const QString &fctemp, fctemps)
  310. {
  311. QStringList nameValuePair = fctemp.split('=');
  312. if (nameValuePair.size() == 2)
  313. {
  314. QString pwm = nameValuePair.at(0);
  315. QString temp = nameValuePair.at(1);
  316. PwmFan *pwmPointer = getPwmFan(getEntryNumbers(pwm));
  317. Temp *tempPointer = getTemp(getEntryNumbers(temp));
  318. if (pwmPointer && tempPointer)
  319. {
  320. pwmPointer->setTemp(tempPointer);
  321. pwmPointer->setHasTemp(true);
  322. pwmPointer->setMinPwm(0);
  323. }
  324. }
  325. else
  326. qWarning() << "Invalid entry:" << fctemp;
  327. }
  328. }
  329. else if (line.startsWith(QStringLiteral("DEVNAME=")))
  330. {
  331. line.remove(QStringLiteral("DEVNAME="));
  332. QStringList devnames = line.split(' ');
  333. foreach (const QString &devname, devnames)
  334. {
  335. QStringList indexNamePair = devname.split('=');
  336. if (indexNamePair.size() == 2)
  337. {
  338. QString hwmon = indexNamePair.at(0);
  339. QString name = indexNamePair.at(1);
  340. bool success;
  341. Hwmon *hwmonPointer = m_hwmons.value(hwmon.remove(QStringLiteral("hwmon")).toInt(&success), Q_NULLPTR);
  342. if (!success)
  343. {
  344. //Connect hwmons again
  345. foreach (Hwmon *hwmon, m_hwmons)
  346. connect(hwmon, SIGNAL(configUpdateNeeded()), this, SLOT(createConfigFile()));
  347. setError(i18n("Can not parse %1", devname), true);
  348. return false;
  349. }
  350. if (!hwmonPointer || hwmonPointer->name().split('.').first() != name)
  351. {
  352. //Connect hwmons again
  353. foreach (Hwmon *hwmon, m_hwmons)
  354. connect(hwmon, SIGNAL(configUpdateNeeded()), this, SLOT(createConfigFile()));
  355. setError(i18n("Invalid config file!"), true);
  356. return false;
  357. }
  358. }
  359. }
  360. }
  361. else if (line.startsWith(QStringLiteral("MINTEMP=")))
  362. {
  363. line.remove(QStringLiteral("MINTEMP="));
  364. parseConfigLine(line, &PwmFan::setMinTemp);
  365. }
  366. else if (line.startsWith(QStringLiteral("MAXTEMP=")))
  367. {
  368. line.remove(QStringLiteral("MAXTEMP="));
  369. parseConfigLine(line, &PwmFan::setMaxTemp);
  370. }
  371. else if (line.startsWith(QStringLiteral("MINSTART=")))
  372. {
  373. line.remove(QStringLiteral("MINSTART="));
  374. parseConfigLine(line, &PwmFan::setMinStart);
  375. }
  376. else if (line.startsWith(QStringLiteral("MINSTOP=")))
  377. {
  378. line.remove(QStringLiteral("MINSTOP="));
  379. parseConfigLine(line, &PwmFan::setMinStop);
  380. }
  381. else if (line.startsWith(QStringLiteral("MINPWM=")))
  382. {
  383. line.remove(QStringLiteral("MINPWM="));
  384. parseConfigLine(line, &PwmFan::setMinPwm);
  385. }
  386. else if (line.startsWith(QStringLiteral("MAXPWM=")))
  387. {
  388. line.remove(QStringLiteral("MAXPWM="));
  389. parseConfigLine(line, &PwmFan::setMaxPwm);
  390. }
  391. else if (!line.startsWith(QStringLiteral("DEVPATH=")) &&
  392. !line.startsWith(QStringLiteral("FCFANS=")))
  393. {
  394. //Connect hwmons again
  395. foreach (Hwmon *hwmon, m_hwmons)
  396. connect(hwmon, SIGNAL(configUpdateNeeded()), this, SLOT(createConfigFile()));
  397. setError(i18n("Unrecognized line in config:\n%1", line), true);
  398. return false;
  399. }
  400. }
  401. createConfigFile();
  402. //Connect hwmons again
  403. foreach (Hwmon *hwmon, m_hwmons)
  404. connect(hwmon, SIGNAL(configUpdateNeeded()), this, SLOT(createConfigFile()));
  405. emit configUrlChanged();
  406. return true;
  407. }
  408. bool Loader::save(const QUrl &url)
  409. {
  410. QString fileName;
  411. if (url.isEmpty())
  412. {
  413. qDebug() << "Given empty url. Fallback to " << m_configUrl;
  414. fileName = m_configUrl.toLocalFile();
  415. }
  416. else if (url.isLocalFile())
  417. fileName = url.toLocalFile();
  418. else
  419. {
  420. setError(i18n("%1 is not a local file!", url.toDisplayString()), true);
  421. return false;
  422. }
  423. QFile file(fileName);
  424. if (file.open(QFile::WriteOnly | QFile::Text))
  425. {
  426. QTextStream stream(&file);
  427. stream << m_configFile;
  428. }
  429. else
  430. {
  431. KAuth::Action action = newFancontrolAction();
  432. QVariantMap map;
  433. map[QStringLiteral("action")] = QVariant("write");
  434. map[QStringLiteral("filename")] = fileName;
  435. map[QStringLiteral("content")] = m_configFile;
  436. action.setArguments(map);
  437. KAuth::ExecuteJob *reply = action.execute();
  438. if (!reply->exec())
  439. {
  440. if (reply->error() == 4)
  441. {
  442. qDebug() << "Aborted by user";
  443. return false;
  444. }
  445. qDebug() << "Error while saving:" << reply->error();
  446. setError(reply->errorString() + reply->errorText(), true);
  447. return false;
  448. }
  449. }
  450. return true;
  451. }
  452. void Loader::createConfigFile()
  453. {
  454. QList<Hwmon *> usedHwmons;
  455. QList<PwmFan *> usedFans;
  456. foreach (Hwmon *hwmon, m_hwmons)
  457. {
  458. if (hwmon->pwmFans().size() > 0)
  459. usedHwmons << hwmon;
  460. foreach (QObject *fan, hwmon->pwmFans())
  461. {
  462. PwmFan *pwmFan = qobject_cast<PwmFan *>(fan);
  463. if (pwmFan->hasTemp() && pwmFan->temp() && !pwmFan->testing())
  464. {
  465. usedFans << pwmFan;
  466. if (!usedHwmons.contains(pwmFan->temp()->parent()))
  467. usedHwmons << pwmFan->temp()->parent();
  468. }
  469. }
  470. }
  471. QString configFile = QStringLiteral("# This file was created by Fancontrol-GUI") + QChar(QChar::LineFeed);
  472. if (m_interval != 0)
  473. configFile += QStringLiteral("INTERVAL=") + QString::number(m_interval) + QChar(QChar::LineFeed);
  474. if (!usedHwmons.isEmpty())
  475. {
  476. configFile += QStringLiteral("DEVPATH=");
  477. foreach (Hwmon *hwmon, usedHwmons)
  478. {
  479. QString sanitizedPath = hwmon->path();
  480. sanitizedPath.remove(QRegExp("^/sys/"));
  481. sanitizedPath.remove(QRegExp("/hwmon/hwmon\\d\\s*$"));
  482. configFile += QStringLiteral("hwmon") + QString::number(hwmon->index()) + "=" + sanitizedPath + QChar(QChar::Space);
  483. }
  484. configFile += QChar(QChar::LineFeed);
  485. configFile += QStringLiteral("DEVNAME=");
  486. foreach (Hwmon *hwmon, usedHwmons)
  487. {
  488. configFile += QStringLiteral("hwmon") + QString::number(hwmon->index()) + "=" + hwmon->name().split('.').first() + QChar(QChar::Space);
  489. }
  490. configFile += QChar(QChar::LineFeed);
  491. if (!usedFans.isEmpty())
  492. {
  493. configFile += QStringLiteral("FCTEMPS=");
  494. foreach (PwmFan *pwmFan, usedFans)
  495. {
  496. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->parent()->index()) + "/";
  497. configFile += QStringLiteral("pwm") + QString::number(pwmFan->index()) + "=";
  498. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->temp()->parent()->index()) + "/";
  499. configFile += QStringLiteral("temp") + QString::number(pwmFan->temp()->index()) + QStringLiteral("_input ");
  500. }
  501. configFile += QChar(QChar::LineFeed);
  502. configFile += QStringLiteral("FCFANS=");
  503. foreach (PwmFan *pwmFan, usedFans)
  504. {
  505. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->parent()->index()) + "/";
  506. configFile += QStringLiteral("pwm") + QString::number(pwmFan->index()) + "=";
  507. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->parent()->index()) + "/";
  508. configFile += QStringLiteral("fan") + QString::number(pwmFan->index()) + QStringLiteral("_input ");
  509. }
  510. configFile += QChar(QChar::LineFeed);
  511. configFile += QStringLiteral("MINTEMP=");
  512. foreach (PwmFan *pwmFan, usedFans)
  513. {
  514. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->parent()->index()) + "/";
  515. configFile += QStringLiteral("pwm") + QString::number(pwmFan->index()) + "=";
  516. configFile += QString::number(pwmFan->minTemp()) + QChar(QChar::Space);
  517. }
  518. configFile += QChar(QChar::LineFeed);
  519. configFile += QStringLiteral("MAXTEMP=");
  520. foreach (PwmFan *pwmFan, usedFans)
  521. {
  522. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->parent()->index()) + "/";
  523. configFile += QStringLiteral("pwm") + QString::number(pwmFan->index()) + "=";
  524. configFile += QString::number(pwmFan->maxTemp()) + QChar(QChar::Space);
  525. }
  526. configFile += QChar(QChar::LineFeed);
  527. configFile += QStringLiteral("MINSTART=");
  528. foreach (PwmFan *pwmFan, usedFans)
  529. {
  530. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->parent()->index()) + "/";
  531. configFile += QStringLiteral("pwm") + QString::number(pwmFan->index()) + "=";
  532. configFile += QString::number(pwmFan->minStart()) + QChar(QChar::Space);
  533. }
  534. configFile += QChar(QChar::LineFeed);
  535. configFile += QStringLiteral("MINSTOP=");
  536. foreach (PwmFan *pwmFan, usedFans)
  537. {
  538. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->parent()->index()) + "/";
  539. configFile += QStringLiteral("pwm") + QString::number(pwmFan->index()) + "=";
  540. configFile += QString::number(pwmFan->minStop()) + QChar(QChar::Space);
  541. }
  542. configFile += QChar(QChar::LineFeed);
  543. configFile += QStringLiteral("MINPWM=");
  544. foreach (PwmFan *pwmFan, usedFans)
  545. {
  546. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->parent()->index()) + "/";
  547. configFile += QStringLiteral("pwm") + QString::number(pwmFan->index()) + "=";
  548. configFile += QString::number(pwmFan->minPwm()) + QChar(QChar::Space);
  549. }
  550. configFile += QChar(QChar::LineFeed);
  551. configFile += QStringLiteral("MAXPWM=");
  552. foreach (PwmFan *pwmFan, usedFans)
  553. {
  554. configFile += QStringLiteral("hwmon") + QString::number(pwmFan->parent()->index()) + "/";
  555. configFile += QStringLiteral("pwm") + QString::number(pwmFan->index()) + "=";
  556. configFile += QString::number(pwmFan->maxPwm()) + QChar(QChar::Space);
  557. }
  558. configFile += QChar(QChar::LineFeed);
  559. }
  560. }
  561. if (configFile != m_configFile)
  562. {
  563. m_configFile = configFile;
  564. emit configFileChanged();
  565. }
  566. }
  567. void Loader::setInterval(int interval, bool writeNewConfig)
  568. {
  569. if (interval != m_interval)
  570. {
  571. m_interval = interval;
  572. emit intervalChanged();
  573. if (writeNewConfig)
  574. createConfigFile();
  575. }
  576. }
  577. void Loader::testFans()
  578. {
  579. for (int i=0; i<m_hwmons.size(); i++)
  580. {
  581. m_hwmons.at(i)->testFans();
  582. }
  583. }
  584. void Loader::abortTestingFans()
  585. {
  586. for (int i=0; i<m_hwmons.size(); i++)
  587. {
  588. m_hwmons.at(i)->abortTestingFans();
  589. }
  590. }
  591. void Loader::detectSensors()
  592. {
  593. KAuth::Action action = newFancontrolAction();
  594. QVariantMap map;
  595. map[QStringLiteral("action")] = QVariant("detectSensors");
  596. action.setArguments(map);
  597. KAuth::ExecuteJob *job = action.execute();
  598. connect(job, SIGNAL(result(KJob*)), this, SLOT(handleDetectSensorsResult(KJob*)));
  599. job->start();
  600. }
  601. void Loader::handleDetectSensorsResult(KJob *job)
  602. {
  603. if (job->error())
  604. {
  605. qDebug() << "Error while detecting sensors:" << job->error();
  606. setError(job->errorString() + job->errorText(), true);
  607. }
  608. else
  609. parseHwmons();
  610. }
  611. QList<QObject *> Loader::hwmonsAsObjects() const
  612. {
  613. QList<QObject *> list;
  614. foreach (Hwmon *hwmon, m_hwmons)
  615. {
  616. list << qobject_cast<QObject *>(hwmon);
  617. }
  618. return list;
  619. }
  620. QList<QObject *> Loader::allTemps() const
  621. {
  622. QList<QObject *> list;
  623. foreach (const Hwmon *hwmon, m_hwmons)
  624. {
  625. list += hwmon->tempsAsObjects();
  626. }
  627. return list;
  628. }
  629. void Loader::setError (const QString &error, bool critical)
  630. {
  631. m_error = error;
  632. emit errorChanged();
  633. if (critical)
  634. {
  635. qCritical() << error;
  636. emit criticalError();
  637. }
  638. else
  639. qWarning() << error;
  640. }
  641. }