Преглед изворни кода

Merge branch 'master' of https://github.com/Maldela/Fancontrol-GUI

Malte Veerman пре 10 година
родитељ
комит
b4c736fd70

+ 6 - 1
CMakeLists.txt

@@ -8,6 +8,7 @@ option(NO_SYSTEMD "Compile without Systemd support. Reduces functionality signif
 option(BUILD_GUI "Build the standalone application" ON)
 option(BUILD_KCM "Build the KCM" OFF)
 option(INSTALL_SHARED "Install the shared parts" ON)
+option(INSTALL_HELPER "Install the KHelper" ON)
 
 
 #KCM can't be build without systemd support
@@ -66,7 +67,11 @@ add_subdirectory(lib)
 
 
 #KHelper for actions that require superuser rights
-add_subdirectory(helper)
+if(INSTALL_HELPER)
+
+    add_subdirectory(helper)
+    
+endif(INSTALL_HELPER)
 
 
 #Build the standalone application

+ 1 - 1
fancontrol-gui/src/main.cpp

@@ -63,4 +63,4 @@ int main(int argc, char *argv[])
     engine.load(QUrl::fromLocalFile(package.path() + "/contents/ui/Application.qml"));
 
     return app.exec();
-}
+}

+ 3 - 3
helper/src/helper.cpp

@@ -108,8 +108,8 @@ ActionReply Helper::action(const QVariantMap &arguments)
         
         QProcess process;
         process.start(program, arguments);
-        
-        if (!process.waitForStarted(), 10000)
+
+        if (!process.waitForStarted(10000))
         {
             reply = ActionReply::HelperErrorType;
             reply.addData("errorDescription", process.errorString());
@@ -117,7 +117,7 @@ ActionReply Helper::action(const QVariantMap &arguments)
             return reply;
         }
         
-        if (!process.waitForFinished(), 10000)
+        if (!process.waitForFinished(10000))
         {
             reply = ActionReply::HelperErrorType;
             reply.addData("errorDescription", process.errorString());

+ 9 - 10
kcm/src/fancontrolkcm.cpp

@@ -54,30 +54,30 @@ FancontrolKCM::FancontrolKCM(QObject *parent, const QVariantList& args)
     setAuthActionName("fancontrol.gui.helper.action");
     
     connect(m_base->loader(), &Loader::configFileChanged, [this] () { setNeedsSave(true); });
-    connect(m_base, &GUIBase::configChanged, this, &FancontrolKCM::emitConfigChanged);
-    connect(m_base, &GUIBase::unitChanged, this, &FancontrolKCM::emitUnitChanged);
+    connect(m_base, &GUIBase::minTempChanged, [this] () { setNeedsSave(true); });
+    connect(m_base, &GUIBase::maxTempChanged, [this] () { setNeedsSave(true); });
+    connect(m_base, &GUIBase::serviceNameChanged, [this] () { setNeedsSave(true); });
     
     qmlRegisterType<GUIBase>();
 }
 
 void FancontrolKCM::save()
 {
-    bool save = false;
-    save = m_base->loader()->save() ? save : true;
+    m_base->loader()->save();
     
     if (m_base->systemdCommunicator()->serviceActive() && m_manualControl)
-        save = m_base->systemdCommunicator()->restartService() ? save : true;
+        m_base->systemdCommunicator()->restartService();
     else 
-        save = m_base->systemdCommunicator()->setServiceActive(m_manualControl) ? save : true;
+        m_base->systemdCommunicator()->setServiceActive(m_manualControl);
 
-    save = m_base->systemdCommunicator()->setServiceEnabled(m_manualControl) ? save : true;
-    setNeedsSave(save);
+    m_base->systemdCommunicator()->setServiceEnabled(m_manualControl);
+    setNeedsSave(false);
 }
 
 void FancontrolKCM::load()
 {
+    m_base->load();
     setManualControl(m_base->systemdCommunicator()->serviceEnabled());
-    m_base->loader()->load(QUrl::fromLocalFile("/etc/fancontrol"));
     setNeedsSave(false);
 }
 
@@ -98,5 +98,4 @@ void FancontrolKCM::setManualControl(bool manualControl)
 }
 
 
-
 #include "fancontrolkcm.moc"

+ 0 - 20
kcm/src/fancontrolkcm.h

@@ -37,11 +37,6 @@ class FancontrolKCM : public ConfigModule
     Q_PROPERTY(bool manualControl READ manualControl WRITE setManualControl NOTIFY manualControlChanged)
     Q_PROPERTY(Loader* loader READ loader CONSTANT)
     Q_PROPERTY(SystemdCommunicator* systemdCom READ systemdCommunicator CONSTANT)
-    Q_PROPERTY(qreal minTemp READ minTemp WRITE setMinTemp NOTIFY configChanged)
-    Q_PROPERTY(qreal maxTemp READ maxTemp WRITE setMaxTemp NOTIFY configChanged)
-    Q_PROPERTY(int unit READ unit WRITE setUnit NOTIFY unitChanged)
-    Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName NOTIFY configChanged)
-    Q_PROPERTY(int interval READ interval WRITE setInterval NOTIFY configChanged)
     
 public:
     
@@ -54,16 +49,6 @@ public:
     //wrap base
     Loader *loader() const { return m_base->loader(); }
     SystemdCommunicator *systemdCommunicator() const { return m_base->systemdCommunicator(); }
-    qreal minTemp() const { return m_base->minTemp(); }
-    qreal maxTemp() const { return m_base->maxTemp(); }
-    int unit() const { return m_base->unit(); }
-    QString serviceName() const { return m_base->serviceName(); }
-    int interval() const { return m_base->interval(); }
-    void setMinTemp(int temp) { m_base->setMinTemp(temp); }
-    void setMaxTemp(int temp) { m_base->setMaxTemp(temp); }
-    void setUnit(int unit) { m_base->setUnit(unit); }
-    void setServiceName(const QString &name) { m_base->setServiceName(name); }
-    void setInterval(int interval) { m_base->setInterval(interval); }
     
     
 public slots:
@@ -76,15 +61,10 @@ public slots:
 signals:
     
     void manualControlChanged();
-    void configChanged();
-    void unitChanged();
     
 
 protected:
     
-    void emitConfigChanged() { emit configChanged(); }
-    void emitUnitChanged() { emit unitChanged(); }
-    
     GUIBase *const m_base;
     bool m_manualControl;
 };

+ 23 - 13
lib/src/guibase.cpp

@@ -56,6 +56,17 @@ GUIBase::GUIBase(QObject *parent) : QObject(parent),
     
 }
 
+void GUIBase::load()
+{
+    m_config->load();
+    emitConfigChanged();
+    m_loader->load();
+    
+#ifndef NO_SYSTEMD
+    m_com->setServiceName(m_config->findItem("ServiceName")->property().toString());
+#endif
+}
+
 qreal GUIBase::maxTemp() const
 {
     return m_config->findItem("MaxTemp")->property().toReal();
@@ -71,21 +82,22 @@ QString GUIBase::serviceName() const
     return m_config->findItem("ServiceName")->property().toString();
 }
 
-int GUIBase::interval() const
-{
-    return m_loader->interval();
-}
-
 void GUIBase::setMaxTemp(qreal temp)
 {
     if (temp != maxTemp())
+    {
         m_config->findItem("MaxTemp")->setProperty(temp);
+        emit maxTempChanged();
+    }
 }
 
 void GUIBase::setMinTemp(qreal temp)
 {
     if (temp != minTemp())
+    {
         m_config->findItem("MinTemp")->setProperty(temp);
+        emit minTempChanged();
+    }
 }
 
 void GUIBase::setServiceName(const QString& name)
@@ -97,16 +109,14 @@ void GUIBase::setServiceName(const QString& name)
 #ifndef NO_SYSTEMD
         m_com->setServiceName(name);
 #endif
-            
+        
+        emit serviceNameChanged();
     }
 }
 
-void GUIBase::setInterval(int i)
-{
-    m_loader->setInterval(i);
-}
-
-void GUIBase::saveConfig()
+void GUIBase::emitConfigChanged()
 {
-    m_config->save();
+    emit serviceNameChanged();
+    emit minTempChanged();
+    emit maxTempChanged();
 }

+ 8 - 10
lib/src/guibase.h

@@ -50,16 +50,14 @@ class FANCONTROL_GUI_LIB_EXPORT GUIBase : public QObject
     Q_PROPERTY(SystemdCommunicator* systemdCom READ systemdCommunicator CONSTANT)
 #endif
     
-    Q_PROPERTY(qreal minTemp READ minTemp WRITE setMinTemp NOTIFY configChanged)
-    Q_PROPERTY(qreal maxTemp READ maxTemp WRITE setMaxTemp NOTIFY configChanged)
+    Q_PROPERTY(qreal minTemp READ minTemp WRITE setMinTemp NOTIFY minTempChanged)
+    Q_PROPERTY(qreal maxTemp READ maxTemp WRITE setMaxTemp NOTIFY maxTempChanged)
     Q_PROPERTY(int unit READ unit WRITE setUnit NOTIFY unitChanged)
-    Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName NOTIFY configChanged)
-    Q_PROPERTY(int interval READ interval WRITE setInterval NOTIFY configChanged)
+    Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName NOTIFY serviceNameChanged)
 
 public:
     
     explicit GUIBase(QObject *parent = Q_NULLPTR);
-    ~GUIBase() { saveConfig(); }
 
     Loader *loader() const { return m_loader; }
     
@@ -70,27 +68,27 @@ public:
     qreal minTemp() const;
     qreal maxTemp() const;
     QString serviceName() const;
-    int interval() const;
     int unit() const { return m_unit; }
     void setMinTemp(qreal minTemp);
     void setMaxTemp(qreal maxTemp);
     void setServiceName(const QString &name);
-    void setInterval(int i);
     void setUnit(int unit) { if (unit != m_unit) { m_unit = unit; emit unitChanged(); } }
-    void saveConfig();
+    void load();
 
     Q_INVOKABLE bool hasSystemdCommunicator() const { return SYSTEMD_BOOL; }
     
     
 signals:
 
-    void configChanged();
+    void minTempChanged();
+    void maxTempChanged();
+    void serviceNameChanged();
     void unitChanged();
     
     
 protected:
     
-    void emitConfigChanged() { emit configChanged(); }
+    void emitConfigChanged();
 
     Config *m_config;
 

+ 3 - 0
lib/src/hwmon.cpp

@@ -62,6 +62,7 @@ void Hwmon::initialize()
                     if (pwmFan->index() == index)
                     {
                         newPwmFan = pwmFan;
+                        newPwmFan->reset();
                         break;
                     }
                 }
@@ -90,6 +91,7 @@ void Hwmon::initialize()
                     if (fan->index() == index)
                     {
                         newFan = fan;
+                        newFan->reset();
                         break;
                     }
                 }
@@ -113,6 +115,7 @@ void Hwmon::initialize()
                 if (temp->index() == index)
                 {
                     newTemp = temp;
+                    newTemp->reset();
                     break;
                 }
             }

+ 93 - 16
lib/src/sensors.cpp

@@ -51,9 +51,7 @@ Fan::Fan(Hwmon *parent, uint index) :
             *m_rpmStream >> m_rpm;
         }
         else
-        {
             qDebug() << "Can't open rpmFile " << parent->path() + "/fan" + QString::number(index) + "_input";
-        }
     }
 }
 
@@ -84,6 +82,26 @@ void Fan::setName(const QString &name)
     }
 }
 
+void Fan::reset()
+{
+    QIODevice *oldFile = m_rpmStream->device();
+    delete m_rpmStream;
+    delete oldFile;
+    
+    if (QDir(m_parent->path()).isReadable())
+    {
+        QFile *rpmFile = new QFile(m_parent->path() + "/fan" + QString::number(m_index) + "_input", this);
+
+        if (rpmFile->open(QFile::ReadOnly))
+        {
+            m_rpmStream = new QTextStream(rpmFile);
+            *m_rpmStream >> m_rpm;
+        }
+        else
+            qDebug() << "Can't open rpmFile " << m_parent->path() + "/fan" + QString::number(m_index) + "_input";
+    }
+}
+
 void Fan::update()
 {
     m_rpmStream->seek(0);
@@ -169,6 +187,47 @@ void PwmFan::update()
     setPwmMode(m_modeStream->readAll().toInt(), false);
 }
 
+void PwmFan::reset()
+{
+    Fan::reset();
+    
+    QIODevice *oldFile = m_pwmStream->device();
+    delete m_pwmStream;
+    delete oldFile;
+    
+    oldFile = m_modeStream->device();
+    delete m_modeStream;
+    delete oldFile;
+    
+    QFile *pwmFile = new QFile(m_parent->path() + "/pwm" + QString::number(m_index), this);
+        if (pwmFile->open(QFile::ReadWrite))
+        {
+            m_pwmStream = new QTextStream(pwmFile);
+            *m_pwmStream >> m_pwm;
+        }
+        else if (pwmFile->open(QFile::ReadOnly))
+        {
+            m_pwmStream = new QTextStream(pwmFile);
+            *m_pwmStream >> m_pwm;
+        }
+        else
+            qDebug() << "Can't open pwmFile " << pwmFile->fileName();
+
+        QFile *pwmModeFile = new QFile(m_parent->path() + "/pwm" + QString::number(m_index) + "_mode", this);
+        if (pwmModeFile->open(QFile::ReadWrite))
+        {
+            m_modeStream = new QTextStream(pwmModeFile);
+            *m_modeStream >> m_pwmMode;
+        }
+        else if (pwmModeFile->open(QFile::ReadOnly))
+        {
+            m_modeStream = new QTextStream(pwmModeFile);
+            *m_modeStream >> m_pwmMode;
+        }
+        else
+            qDebug() << "Can't open pwmModeFile " << pwmModeFile->fileName();
+}
+
 void PwmFan::setPwm(int pwm, bool write)
 {
     if (m_pwm != pwm)
@@ -326,16 +385,16 @@ void PwmFan::continueTest()
     }
 }
 
-void PwmFan::reset()
-{
-    setTemp(Q_NULLPTR);
-    setMinTemp(0);
-    setMaxTemp(100);
-    setMinPwm(255);
-    setMaxPwm(255);
-    setMinStart(255);
-    setMinStop(255);
-}
+// void PwmFan::reset()
+// {
+//     setTemp(Q_NULLPTR);
+//     setMinTemp(0);
+//     setMaxTemp(100);
+//     setMinPwm(255);
+//     setMaxPwm(255);
+//     setMinStart(255);
+//     setMinStop(255);
+// }
 
 bool PwmFan::active() const
 {
@@ -375,13 +434,10 @@ Temp::Temp(Hwmon *parent, uint index) :
             qDebug() << "Can't open valueFile " << parent->path() + "/temp" + QString::number(index) + "_input";
 
         if (labelFile.open(QFile::ReadOnly))
-        {
             m_label = QTextStream(&labelFile).readLine();
-        }
+
         else
-        {
             qDebug() << "Can't open labelFile " << parent->path() + "/temp" + QString::number(index) + "_label";
-        }
     }
 }
 
@@ -416,6 +472,27 @@ void Temp::setName(const QString &name)
     }
 }
 
+void Temp::reset()
+{
+    QIODevice *oldFile = m_valueStream->device();
+    delete m_valueStream;
+    delete oldFile;
+    
+    if (QDir(m_parent->path()).isReadable())
+    {
+        QFile *valueFile = new QFile(m_parent->path() + "/temp" + QString::number(m_index) + "_input", this);
+
+        if (valueFile->open(QFile::ReadOnly))
+        {
+            m_valueStream = new QTextStream(valueFile);
+            *m_valueStream >> m_value;
+            m_value /= 1000;
+        }
+        else
+            qDebug() << "Can't open valueFile " << m_parent->path() + "/temp" + QString::number(m_index) + "_input";
+    }
+}
+
 void Temp::update()
 {
     m_valueStream->seek(0);

+ 8 - 5
lib/src/sensors.h

@@ -43,6 +43,7 @@ public:
 
     virtual QString name() const = 0;
     virtual void setName(const QString &name) = 0;
+    virtual void reset() = 0;
     QString path() const { return m_path; }
     Hwmon * parent() const { return m_parent; }
     uint index() const { return m_index; }
@@ -79,8 +80,9 @@ public:
 
     QString label() const { return m_label; }
     int value() const { return m_value; }
-    QString name() const;
-    void setName(const QString &name);
+    QString name() const Q_DECL_OVERRIDE;
+    void setName(const QString &name) Q_DECL_OVERRIDE;
+    void reset() Q_DECL_OVERRIDE;
 
 
 public slots:
@@ -113,8 +115,9 @@ public:
     virtual ~Fan();
 
     int rpm() const { return m_rpm; }
-    QString name() const;
-    void setName(const QString &name);
+    QString name() const Q_DECL_OVERRIDE;
+    void setName(const QString &name) Q_DECL_OVERRIDE;
+    void reset() Q_DECL_OVERRIDE;
 
     virtual int pwm() const { return 255; }
     virtual void setPwm(int, bool) { }
@@ -181,7 +184,7 @@ public:
     void setMinStop(int minStop) { if (minStop != m_minStop) { m_minStop = minStop; emit minStopChanged(); } }
     void setPwmMode(int pwmMode, bool write = true);
     void setActive(bool active);
-    void reset();
+    void reset() Q_DECL_OVERRIDE;
     Q_INVOKABLE void test();
     Q_INVOKABLE void abortTest();
 

+ 8 - 15
lib/src/systemdcommunicator.cpp

@@ -243,15 +243,15 @@ bool SystemdCommunicator::dbusAction(const QString &method, const QVariantList &
             ExecuteJob *reply = action.execute();
 
             if (!reply->exec())
-	    {
+            {
                 setError(reply->errorString());
-		return false;
-	    }
+                return false;
+            }
             else
-	    {
+            {
                 success();
-		return true;
-	    }
+                return true;
+            }
         }
         setError(dbusreply.errorMessage());
         return false;
@@ -275,19 +275,12 @@ bool SystemdCommunicator::restartService()
 }
 
 void SystemdCommunicator::updateServiceProperties(QString, QVariantMap propchanged, QStringList)
-{ 
-    qDebug() << "Properties changed...";
-    
+{
     if (propchanged.value("ActiveState").isValid())
-    {
         emit serviceActiveChanged();
-        qDebug() << "Active changed...";
-    }
+
     if (propchanged.value("UnitFileState").isValid())
-    {
         emit serviceEnabledChanged();
-        qDebug() << "Enabled changed...";
-    }
 }
 
 

+ 4 - 4
package/contents/scripts/units.js

@@ -19,7 +19,7 @@
 
 function round(number, dec) {
     if (!dec || dec == 0) return Math.round(number);
-    return Math.round(number*10*dec) / (10*dec);
+    return Math.round(number*Math.pow(10, dec)) / Math.pow(10, dec);
 }
 
 function toCelsius(degrees, currentUnit) {
@@ -31,7 +31,7 @@ function toCelsius(degrees, currentUnit) {
 
 function fromCelsius(degrees, newUnit) {
     var float = parseFloat(degrees);
-    if (newUnit == 1) { return round(float + 273.15); }
-    if (newUnit == 2) { return round(float * 9 / 5 + 32); }
-    return round(float);
+    if (newUnit == 1) { return round(float + 273.15, 2); }
+    if (newUnit == 2) { return round(float * 9 / 5 + 32, 2); }
+    return round(float, 2);
 }

+ 157 - 11
package/contents/ui/KCM.qml

@@ -23,28 +23,55 @@ import QtQuick.Controls 1.3
 import QtQuick.Layouts 1.1
 import org.kde.kcm 1.0
 import "../scripts/arrayfunctions.js" as ArrayFunctions
+import "../scripts/units.js" as Units
 
 Item {
-    implicitWidth: 800
-    implicitHeight: 600
+    property QtObject base: kcm.base
+    property var locale: Qt.locale()
+    property real textWidth: 0
     
-    ColumnLayout {
-        anchors.fill: parent    
+    id: root
+    implicitWidth: 1024
+    implicitHeight: 768
+       
+    Column {
+        id: header
+        width: parent.width
         
         CheckBox {
             id: enabledBox
+            visible: kcm.loader.allPwmFans.length > 0
             Layout.alignment: Qt.AlignLeft | Qt.AlignTop
             text: i18n("Control fans manually")
             checked: kcm.manualControl
+            onCheckedChanged: kcm.manualControl = checked
+            
+            Connections {
+                target: kcm
+                onManualControlChanged: enabledBox.checked = kcm.manualControl
+            }
         }
         
         Label {
-            visible: enabledBox.checked && kcm.loader.allPwmFans.length == 0
+            visible: kcm.loader.allPwmFans.length == 0
             text: i18n("There are no pwm capable fans in your system.")
             anchors.top: enabledBox.bottom
             anchors.margins: 20
         }
         
+        Button {
+            text: i18n("Detect fans")
+            visible: kcm.loader.allPwmFans.length == 0
+            onClicked: kcm.loader.detectSensors()
+        }
+    }
+        
+    ColumnLayout {
+        width: parent.width
+        anchors.bottom: parent.bottom
+        anchors.top: header.bottom
+        visible: enabledBox.checked
+
         RowLayout {  
             visible: enabledBox.checked && kcm.loader.allPwmFans.length > 0
             
@@ -59,21 +86,140 @@ Item {
                 Layout.fillWidth: true
                 Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
             }
+            Button {
+                Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+                text: i18n("Detect fans")
+                onClicked: kcm.loader.detectSensors()
+            }
         }
         
         Loader {
-            active: enabledBox.checked && !!kcm.loader.allPwmFans[fanCombobox.currentIndex]
+            Layout.fillWidth: true
+            Layout.fillHeight: true
+            active: !!kcm.loader.allPwmFans[fanCombobox.currentIndex]
             sourceComponent: PwmFan {
-                id: fan
                 minimizable: false
-                unit: kcm.unit
+                unit: kcm.base.unit
                 fan: kcm.loader.allPwmFans[fanCombobox.currentIndex]
                 loader: kcm.loader
                 systemdCom: kcm.systemdCom
-                minTemp: kcm.minTemp
-                maxTemp: kcm.maxTemp
+                minTemp: kcm.base.minTemp
+                maxTemp: kcm.base.maxTemp
+            }
+        }
+        
+        Label {
+            property bool expanded: false
+            property string prefix: expanded ? "v " : "> "
+
+            id: expandLabel
+            text: prefix + i18n("Advanced settings")
+            font.bold: true
+            
+            MouseArea {
+                anchors.fill: parent
+                onClicked: parent.expanded = parent.expanded ? false : true
+            }
+        }
+        
+        RowLayout {
+            visible: expandLabel.expanded
+
+            Label {
+                Layout.preferredWidth: root.textWidth
+                clip: true
+                text: i18n("Interval:")
+                horizontalAlignment: Text.AlignRight
+                Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
+            }
+            OptionInput {
+                id: intervalValue
+                Layout.minimumWidth: implicitWidth
+                Layout.fillWidth: true
+                inputMethodHints: Qt.ImhDigitsOnly
+                validator: IntValidator { bottom: 0 }
+                value: base.loader ? base.loader.interval : 1
+                type: "int"
+                
+                onTextChanged: {
+                    if (activeFocus && text && root.locale) {
+                        var value = Number.fromLocaleString(root.locale, text);
+                        if (value) base.loader.interval = value;
+                    }
+                }
+            }
+        }
+        RowLayout {
+            visible: expandLabel.expanded
+
+            Label {
+                Layout.preferredWidth: root.textWidth
+                clip: true
+                text: i18n("Minimum temperature for fan graphs:")
+                horizontalAlignment: Text.AlignRight
+                Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
+            }
+            OptionInput {
+                id: minTempValue
+                Layout.minimumWidth: implicitWidth
+                Layout.fillWidth: true
+                inputMethodHints: Qt.ImhFormattedNumbersOnly
+                validator: DoubleValidator { top: base.maxTemp }
+                value: Units.fromCelsius(base.minTemp, base.unit)
+                type: "double"
+                
+                onTextChanged: {
+                    if (activeFocus && text && root.locale) {
+                        var value = Units.toCelsius(Number.fromLocaleString(locale, text), base.unit);
+                        if (value) base.minTemp = value;
+                    }
+                }
+            }
+        }
+        RowLayout {
+            visible: expandLabel.expanded
+
+            Label {
+                Layout.preferredWidth: root.textWidth
+                clip: true
+                text: i18n("Maximum temperature for fan graphs:")
+                horizontalAlignment: Text.AlignRight
+                Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
+            }
+            OptionInput {
+                id: maxTempValue
+                Layout.minimumWidth: implicitWidth
+                Layout.fillWidth: true
+                inputMethodHints: Qt.ImhFormattedNumbersOnly
+                validator: DoubleValidator { bottom: base.minTemp }
+                value: Units.fromCelsius(base.maxTemp, base.unit)
+                type: "double"
+                
+                onTextChanged: {
+                    if (activeFocus && text && root.locale) {
+                        var value = Units.toCelsius(Number.fromLocaleString(locale, text), base.unit);
+                        if (value) base.maxTemp = value;
+                    }
+                }
+            }
+        }        
+        RowLayout {
+            visible: expandLabel.expanded
+
+            Label {
+                Layout.preferredWidth: root.textWidth
+                clip: true
+                text: i18n("Name of the fancontrol systemd service:")
+                horizontalAlignment: Text.AlignRight
+                Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
+            }
+            OptionInput {
+                Layout.minimumWidth: implicitWidth
                 Layout.fillWidth: true
-                Layout.fillHeight: true
+                color: base.systemdCom.serviceExists ? "green" : "red"
+                value: base.serviceName
+                type: "string"
+                onTextChanged: base.serviceName = text
             }
         }
     }

+ 25 - 7
package/contents/ui/OptionInput.qml

@@ -21,14 +21,32 @@ import QtQuick 2.4
 import QtQuick.Layouts 1.1
 
 FocusScope {
-    property alias text: value.text
-    property alias font: value.font
-    property alias inputMethodHints: value.inputMethodHints
-    property alias color: value.color
+    property alias text: textField.text
+    property alias font: textField.font
+    property alias inputMethodHints: textField.inputMethodHints
+    property alias validator: textField.validator
+    property alias color: textField.color
     property real margin: 6
+    property var value
+    property string type: "int"
+    property var locale: Qt.locale()
 
-    implicitHeight: value.implicitHeight + margin*2
-    implicitWidth: value.implicitWidth + margin*2
+    id: root
+    implicitHeight: textField.implicitHeight + margin*2
+    implicitWidth: textField.implicitWidth + margin*2
+    
+    onValueChanged: {
+        if (type == "int" || type == "double") {
+            if (textField.text != Number(value).toLocaleString()) {
+                textField.text = Number(value).toLocaleString();
+            }
+        }
+        else if (type == "string") {
+            if (textField.text != value) {
+                textField.text = value;
+            }
+        }
+    }
 
     Rectangle {
         id: rect
@@ -38,7 +56,7 @@ FocusScope {
         border.color: enabled ? palette.text : disabledPalette.text
 
         TextInput {
-            id: value
+            id: textField
             anchors.fill: parent
             anchors.leftMargin: margin
             horizontalAlignment: TextEdit.AlignLeft

+ 12 - 16
package/contents/ui/PwmFan.qml

@@ -29,8 +29,8 @@ Rectangle {
     property QtObject fan
     property QtObject loader
     property QtObject systemdCom
-    property real minTemp: 20.0
-    property real maxTemp: 100.0
+    property real minTemp: 40.0
+    property real maxTemp: 90.0
     property int margin: 5
     property int minimizeDuration: 400
     property int unit: 0
@@ -48,7 +48,6 @@ Rectangle {
         if (fan) {
             hasTempCheckBox.checked = Qt.binding(function() { return fan.hasTemp; })
             fanOffCheckBox.checked = Qt.binding(function() { return (fan.minPwm == 0); })
-            minStartInput.text = Qt.binding(function() { return fan.minStart; })
             if (fan.hasTemp && loader) {
                 tempBox.currentIndex = loader.allTemps.indexOf(fan.temp);
             }
@@ -168,8 +167,8 @@ Rectangle {
         property int bottomPadding: fontSize * 2
         property int plotWidth: width - leftPadding - rightPadding
         property int plotHeight: height - topPadding - bottomPadding
-        property alias minTemp: root.minTemp
-        property alias maxTemp: root.maxTemp
+        property alias minTemp: root.minTemp        //needed for pwmPoints
+        property alias maxTemp: root.maxTemp        //needed for pwmPoints
 
         id: canvas
         renderTarget: Canvas.FramebufferObject
@@ -328,7 +327,7 @@ Rectangle {
             var convertedMaxTemp = Units.fromCelsius(maxTemp, unit);
             var suffix = (unit == 0) ? "°C" : (unit == 1) ? "K" : "°F"
             var lastTemp;
-            for (i=convertedMinTemp; i<convertedMaxTemp; i+= 10) {
+            for (var i=convertedMinTemp; i<convertedMaxTemp; i+= 10) {
                 lastTemp = i;
                 var x = scaleX(Units.toCelsius(i, unit));
                 c.fillText(i + suffix, x, topPadding+plotHeight+fontSize/2);
@@ -403,22 +402,19 @@ Rectangle {
                 Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
                 renderType: Text.NativeRendering
             }
-            OptionInput {
+            SpinBox {
                 id: minStartInput
                 Layout.fillWidth: true
-                text: fan.minStart
-                onTextChanged: fan.minStart = parseInt(text)
+                minimumValue: 1
+                maximumValue: 255
+                value: fan.minStart
+                onValueChanged: fan.minStart = value
             }
         }
 
         RowLayout {
             visible: systemdCom
             
-            Label {
-                text: i18n("Test start and stop values")
-                Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
-                renderType: Text.NativeRendering
-            }
             Item {
                 Layout.fillWidth: true
             }
@@ -426,7 +422,7 @@ Rectangle {
                 property bool reactivateAfterTesting
 
                 id: testButton
-                text: fan.testing? i18n("Abort") : i18n("Test")
+                text: fan.testing ? i18n("Abort test") : i18n("Test start and stop values")
                 anchors.right: parent.right
                 onClicked: {
                     if (fan.testing) {
@@ -435,7 +431,7 @@ Rectangle {
                     } else {
                         reactivateAfterTesting = systemdCom.serviceActive;
                         systemdCom.serviceActive = false;
-                        minStartInput.text = Qt.binding(function() { return fan.minStart });
+                        minStartInput.value = Qt.binding(function() { return fan.minStart });
                         fan.test();
                     }
                 }

+ 6 - 0
package/contents/ui/PwmFansTab.qml

@@ -67,4 +67,10 @@ ScrollView {
         text: i18n("There are no pwm capable fans in your system.")
         font.bold: true
     }
+    Button {
+        anchors.centerIn: parent
+        visible: repeater.fans.length == 0
+        text: i18n("Detect fans")
+        onClicked: loader.detectSensors()
+    }
 }

+ 38 - 18
package/contents/ui/SettingsTab.qml

@@ -27,6 +27,7 @@ import "../scripts/units.js" as Units
 Item {
     property QtObject gui
     property QtObject systemdCom: gui && gui.hasSystemdCommunicator() ? gui.systemdCom : null
+    property QtObject loader : gui ? gui.loader : null
     property int padding: 10
     property real textWidth: 0
     property var locale: Qt.locale()
@@ -56,8 +57,16 @@ Item {
                 Layout.minimumWidth: implicitWidth
                 Layout.fillWidth: true
                 inputMethodHints: Qt.ImhDigitsOnly
-                text: Number(gui ? gui.interval : 1).toLocaleString(locale, 'f', 0)
-                onTextChanged: if (text && text != "0") gui.interval = parseInt(Number.fromLocaleString(root.locale, text))
+                validator: IntValidator { bottom: 0 }
+                value: gui.loader ? gui.loader.interval : 1
+                type: "int"
+                
+                onTextChanged: {
+                    if (activeFocus && text && root.locale) {
+                        var value = Number.fromLocaleString(root.locale, text);
+                        if (value) gui.loader.interval = value;
+                    }
+                }
             }
         }
         RowLayout {
@@ -71,16 +80,18 @@ Item {
                 Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
             }
             OptionInput {
-                id: minTempValue
                 Layout.minimumWidth: implicitWidth
                 Layout.fillWidth: true
-                inputMethodHints: Qt.ImhDigitsOnly
-                onTextChanged: if (activeFocus) gui.minTemp = Units.toCelsius(Number.fromLocaleString(locale, text), gui.unit)
-                Component.onCompleted: text = Units.fromCelsius(gui.minTemp, gui.unit)
+                inputMethodHints: Qt.ImhFormattedNumbersOnly
+                validator: DoubleValidator { top: gui.maxTemp }
+                value: Units.fromCelsius(gui.minTemp, gui.unit)
+                type: "double"
                 
-                Connections {
-                    target: gui
-                    onUnitChanged: minTempValue.text = Units.fromCelsius(gui.minTemp, gui.unit)
+                onTextChanged: {
+                    if (activeFocus && text && root.locale) {
+                        var value = Units.toCelsius(Number.fromLocaleString(locale, text), gui.unit);
+                        if (value) gui.minTemp = value;
+                    }
                 }
             }
         }
@@ -98,16 +109,19 @@ Item {
                 id: maxTempValue
                 Layout.minimumWidth: implicitWidth
                 Layout.fillWidth: true
-                inputMethodHints: Qt.ImhDigitsOnly
-                onTextChanged: if (activeFocus) gui.maxTemp = Units.toCelsius(Number.fromLocaleString(locale, text), gui.unit)
-                Component.onCompleted: text = Units.fromCelsius(gui.maxTemp, gui.unit)
+                inputMethodHints: Qt.ImhFormattedNumbersOnly
+                validator: DoubleValidator { bottom: gui.minTemp }
+                value: Units.fromCelsius(gui.maxTemp, gui.unit)
+                type: "double"
                 
-                Connections {
-                    target: gui
-                    onUnitChanged: maxTempValue.text = Units.fromCelsius(gui.maxTemp, gui.unit)
+                onTextChanged: {
+                    if (activeFocus && text && root.locale) {
+                        var value = Units.toCelsius(Number.fromLocaleString(locale, text), gui.unit);
+                        if (value) gui.maxTemp = value;
+                    }
                 }
             }
-        }
+        }        
         Loader {
             active: systemdCom
             sourceComponent: RowLayout {
@@ -121,11 +135,11 @@ Item {
                     Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
                 }
                 OptionInput {
-                    id: serviceName
                     Layout.minimumWidth: implicitWidth
                     Layout.fillWidth: true
                     color: systemdCom.serviceExists ? "green" : "red"
-                    text: gui.serviceName
+                    value: gui.serviceName
+                    type: "string"
                     onTextChanged: gui.serviceName = text
                 }
             }
@@ -151,5 +165,11 @@ Item {
                 }
             }
         }
+        
+        Button {
+            x: maxTempValue.x
+            text: i18n("Detect fans")
+            onClicked: loader.detectSensors()
+        }
     }
 }

+ 81 - 79
po/de/kcm_fancontrol.po

@@ -6,8 +6,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: fancontrol-gui\n"
 "Report-Msgid-Bugs-To: http://github.com/maldela/fancontrol-gui\n"
-"POT-Creation-Date: 2015-08-15 14:40+0200\n"
-"PO-Revision-Date: 2015-08-15 14:44+0100\n"
+"POT-Creation-Date: 2015-08-25 02:48+0200\n"
+"PO-Revision-Date: 2015-08-25 02:48+0100\n"
 "Last-Translator: Malte Veerman <maldela@halloarsch.de>\n"
 "Language-Team: German <kde-i18n-de@kde.org>\n"
 "Language: de_DE\n"
@@ -17,7 +17,7 @@ msgstr ""
 "X-Generator: Lokalize 2.0\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: fancontrol-gui/src/main.cpp:38 package/contents/ui/Application.qml:28
+#: fancontrol-gui/src/main.cpp:38 package/contents/ui/Application.qml:27
 msgid "Fancontrol-GUI"
 msgstr "Fancontrol-GUI"
 
@@ -25,157 +25,139 @@ msgstr "Fancontrol-GUI"
 msgid "Graphical user interface for fancontrol"
 msgstr "Graphische Benutzeroberfläche für fanontrol"
 
-#: fancontrol-gui/src/main.cpp:46 kcm/src/fancontrolkcm.cpp:47
+#: fancontrol-gui/src/main.cpp:46 kcm/src/fancontrolkcm.cpp:50
 msgid "Malte Veerman"
 msgstr "Malte Veerman"
 
-#: fancontrol-gui/src/main.cpp:46 kcm/src/fancontrolkcm.cpp:47
+#: fancontrol-gui/src/main.cpp:46 kcm/src/fancontrolkcm.cpp:50
 msgid "Main Developer"
 msgstr "Hauptentwickler"
 
-#: kcm/src/fancontrolkcm.cpp:39
+#: kcm/src/fancontrolkcm.cpp:42
 msgid "Fancontrol-KCM"
 msgstr "Fancontrol-KCM"
 
-#: kcm/src/fancontrolkcm.cpp:41
+#: kcm/src/fancontrolkcm.cpp:44
 msgid "KDE Fancontrol Module"
 msgstr "KDE Fancontrol Modul"
 
-#: package/contents/ui/Application.qml:35
+#: package/contents/ui/Application.qml:34
 msgid "File"
 msgstr "Datei"
 
-#: package/contents/ui/Application.qml:39
-#: package/contents/ui/Application.qml:174
+#: package/contents/ui/Application.qml:38
+#: package/contents/ui/Application.qml:151
 msgid "Save configuration file as"
 msgstr "Konfigurationsdatei speichern unter..."
 
-#: package/contents/ui/Application.qml:44
+#: package/contents/ui/Application.qml:43
 msgid "Exit"
 msgstr "Schließen"
 
-#: package/contents/ui/Application.qml:62
+#: package/contents/ui/Application.qml:61
 msgid "Restart fancontrol"
 msgstr "Fancontrol neustarten"
 
-#: package/contents/ui/Application.qml:62
+#: package/contents/ui/Application.qml:61
 msgid "Start fancontrol"
 msgstr "Fancontrol starten"
 
-#: package/contents/ui/Application.qml:71
+#: package/contents/ui/Application.qml:70
 msgid "Stop fancontrol"
 msgstr "Fancontrol stoppen"
 
-#: package/contents/ui/Application.qml:94
+#: package/contents/ui/Application.qml:93
 msgid "Sensors"
 msgstr "Sensoren"
 
-#: package/contents/ui/Application.qml:100
+#: package/contents/ui/Application.qml:99
 msgid "PwmFans"
 msgstr "PwmLüfter"
 
-#: package/contents/ui/Application.qml:107
+#: package/contents/ui/Application.qml:106
 msgid "Configfile"
 msgstr "Konfigurationsdatei"
 
-#: package/contents/ui/Application.qml:114
+#: package/contents/ui/Application.qml:113
 msgid "Settings"
 msgstr "Einstellungen"
 
-#: package/contents/ui/Application.qml:145
-#: package/contents/ui/Application.qml:148
+#: package/contents/ui/Application.qml:122
+#: package/contents/ui/Application.qml:125
 msgid "Load configuration file"
 msgstr "Konfigurationsdatei öffnen"
 
-#: package/contents/ui/Application.qml:153
-#: package/contents/ui/Application.qml:156
+#: package/contents/ui/Application.qml:130
+#: package/contents/ui/Application.qml:133
 msgid "Save configuration file"
 msgstr "Konfigurationsdatei speichern"
 
-#: package/contents/ui/Application.qml:162
+#: package/contents/ui/Application.qml:139
 msgid "Please choose a configuration file"
 msgstr "Konfigurationsdatei auswählen"
 
-#: package/contents/ui/KCM.qml:34
+#: package/contents/ui/KCM.qml:45
 msgid "Control fans manually"
 msgstr "Lüfter manuell kontrollieren"
 
-#: package/contents/ui/KCM.qml:44
-msgid "Fan:"
-msgstr "Lüfter:"
-
-#: package/contents/ui/PwmFan.qml:344
-msgid "Controlled by:"
-msgstr "Kontrolliert von:"
-
-#: package/contents/ui/PwmFan.qml:384
-msgid "Turn Fan off if temp < MINTEMP"
-msgstr "Lüfter abschalten, wenn MINTEMP unterschritten"
-
-#: package/contents/ui/PwmFan.qml:397
-msgid "Pwm value for fan to start:"
-msgstr "Wert ab dem der Lüfter startet:"
-
-#: package/contents/ui/PwmFan.qml:414
-msgid "Test start and stop values"
-msgstr "Start und Stopwerte testen"
+#: package/contents/ui/KCM.qml:57 package/contents/ui/PwmFansTab.qml:67
+msgid "There are no pwm capable fans in your system."
+msgstr "Es gibt keine pwm-fähigen Lüfter in ihrem System."
 
-#: package/contents/ui/PwmFan.qml:425
-msgid "Abort"
-msgstr "Abbrechen"
+#: package/contents/ui/KCM.qml:63 package/contents/ui/KCM.qml:91
+#: package/contents/ui/PwmFansTab.qml:73
+#: package/contents/ui/SettingsTab.qml:171
+msgid "Detect fans"
+msgstr "Finde Lüfter"
 
-#: package/contents/ui/PwmFan.qml:425
-msgid "Test"
-msgstr "Testen"
+#: package/contents/ui/KCM.qml:79
+msgid "Fan:"
+msgstr "Lüfter:"
 
-#: package/contents/ui/PwmFansTab.qml:67
-msgid "There are no pwm capable fans in your system."
-msgstr "Es gibt keine pwm-fähigen Lüfter in ihrem System."
+#: package/contents/ui/KCM.qml:116
+msgid "Advanced settings"
+msgstr "Erweiterte Einstellungen"
 
-#: package/contents/ui/SettingsTab.qml:50
+#: package/contents/ui/KCM.qml:131 package/contents/ui/SettingsTab.qml:51
 msgid "Interval:"
 msgstr "Intervall:"
 
-#: package/contents/ui/SettingsTab.qml:69
+#: package/contents/ui/KCM.qml:158 package/contents/ui/SettingsTab.qml:78
 msgid "Minimum temperature for fan graphs:"
 msgstr "Minimale Temperatur für Lüftergraphen:"
 
-#: package/contents/ui/SettingsTab.qml:93
+#: package/contents/ui/KCM.qml:185 package/contents/ui/SettingsTab.qml:104
 msgid "Maximum temperature for fan graphs:"
 msgstr "Maximale Temperatur für Lüftergraphen:"
 
-#: package/contents/ui/SettingsTab.qml:117
-msgid "Unit:"
-msgstr "Einheit:"
+#: package/contents/ui/KCM.qml:212 package/contents/ui/SettingsTab.qml:133
+msgid "Name of the fancontrol systemd service:"
+msgstr "Name des fancontrol systemd services:"
 
-#: package/contents/ui/SettingsTab.qml:125
-msgid "Celsius"
-msgstr "Celsius"
+#: package/contents/ui/PwmFan.qml:365
+msgid "Controlled by:"
+msgstr "Kontrolliert von:"
+
+#: package/contents/ui/PwmFan.qml:386
+msgid "Turn Fan off if temp < MINTEMP"
+msgstr "Lüfter abschalten, wenn MINTEMP unterschritten"
 
-#: package/contents/ui/SettingsTab.qml:125
-msgid "Kelvin"
-msgstr "Kelvin"
+#: package/contents/ui/PwmFan.qml:399
+msgid "Pwm value for fan to start:"
+msgstr "Wert ab dem der Lüfter startet:"
 
-#: package/contents/ui/SettingsTab.qml:125
-msgid "Fahrenheit"
-msgstr "Fahrenheit"
+#: package/contents/ui/PwmFan.qml:423
+msgid "Abort test"
+msgstr "Test abbrechen"
 
-#: package/contents/ui/SettingsTab.qml:140
-msgid "Name of the fancontrol systemd service:"
-msgstr "Name des fancontrol systemd services:"
+#: package/contents/ui/PwmFan.qml:423
+msgid "Test start and stop values"
+msgstr "Start und Stopwerte testen"
 
-#: package/contents/ui/SettingsTab.qml:162
+#: package/contents/ui/SettingsTab.qml:155
 msgid "Fancontrol systemd service autostart:"
 msgstr "Fancontrol systemd service Autostart:"
 
-#: package/contents/ui/SettingsTab.qml:170
-msgid "disabled"
-msgstr "deaktiviert"
-
-#: package/contents/ui/SettingsTab.qml:170
-msgid "enabled"
-msgstr "aktiviert"
-
 #: po/rc.cpp:1 rc.cpp:1
 msgctxt "NAME OF TRANSLATORS"
 msgid "Your names"
@@ -186,3 +168,23 @@ msgctxt "EMAIL OF TRANSLATORS"
 msgid "Your emails"
 msgstr "maldela@halloarsch.de"
 
+#~ msgid "Test"
+#~ msgstr "Testen"
+
+#~ msgid "Unit:"
+#~ msgstr "Einheit:"
+
+#~ msgid "Celsius"
+#~ msgstr "Celsius"
+
+#~ msgid "Kelvin"
+#~ msgstr "Kelvin"
+
+#~ msgid "Fahrenheit"
+#~ msgstr "Fahrenheit"
+
+#~ msgid "disabled"
+#~ msgstr "deaktiviert"
+
+#~ msgid "enabled"
+#~ msgstr "aktiviert"

+ 50 - 68
po/kcm_fancontrol.pot

@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: http://github.com/maldela/fancontrol-gui\n"
-"POT-Creation-Date: 2015-08-15 14:40+0200\n"
+"POT-Creation-Date: 2015-08-25 02:48+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,7 +17,7 @@ msgstr ""
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: fancontrol-gui/src/main.cpp:38 package/contents/ui/Application.qml:28
+#: fancontrol-gui/src/main.cpp:38 package/contents/ui/Application.qml:27
 msgid "Fancontrol-GUI"
 msgstr ""
 
@@ -25,155 +25,137 @@ msgstr ""
 msgid "Graphical user interface for fancontrol"
 msgstr ""
 
-#: fancontrol-gui/src/main.cpp:46 kcm/src/fancontrolkcm.cpp:47
+#: fancontrol-gui/src/main.cpp:46 kcm/src/fancontrolkcm.cpp:50
 msgid "Malte Veerman"
 msgstr ""
 
-#: fancontrol-gui/src/main.cpp:46 kcm/src/fancontrolkcm.cpp:47
+#: fancontrol-gui/src/main.cpp:46 kcm/src/fancontrolkcm.cpp:50
 msgid "Main Developer"
 msgstr ""
 
-#: kcm/src/fancontrolkcm.cpp:39
+#: kcm/src/fancontrolkcm.cpp:42
 msgid "Fancontrol-KCM"
 msgstr ""
 
-#: kcm/src/fancontrolkcm.cpp:41
+#: kcm/src/fancontrolkcm.cpp:44
 msgid "KDE Fancontrol Module"
 msgstr ""
 
-#: package/contents/ui/Application.qml:35
+#: package/contents/ui/Application.qml:34
 msgid "File"
 msgstr ""
 
-#: package/contents/ui/Application.qml:39
-#: package/contents/ui/Application.qml:174
+#: package/contents/ui/Application.qml:38
+#: package/contents/ui/Application.qml:151
 msgid "Save configuration file as"
 msgstr ""
 
-#: package/contents/ui/Application.qml:44
+#: package/contents/ui/Application.qml:43
 msgid "Exit"
 msgstr ""
 
-#: package/contents/ui/Application.qml:62
+#: package/contents/ui/Application.qml:61
 msgid "Restart fancontrol"
 msgstr ""
 
-#: package/contents/ui/Application.qml:62
+#: package/contents/ui/Application.qml:61
 msgid "Start fancontrol"
 msgstr ""
 
-#: package/contents/ui/Application.qml:71
+#: package/contents/ui/Application.qml:70
 msgid "Stop fancontrol"
 msgstr ""
 
-#: package/contents/ui/Application.qml:94
+#: package/contents/ui/Application.qml:93
 msgid "Sensors"
 msgstr ""
 
-#: package/contents/ui/Application.qml:100
+#: package/contents/ui/Application.qml:99
 msgid "PwmFans"
 msgstr ""
 
-#: package/contents/ui/Application.qml:107
+#: package/contents/ui/Application.qml:106
 msgid "Configfile"
 msgstr ""
 
-#: package/contents/ui/Application.qml:114
+#: package/contents/ui/Application.qml:113
 msgid "Settings"
 msgstr ""
 
-#: package/contents/ui/Application.qml:145
-#: package/contents/ui/Application.qml:148
+#: package/contents/ui/Application.qml:122
+#: package/contents/ui/Application.qml:125
 msgid "Load configuration file"
 msgstr ""
 
-#: package/contents/ui/Application.qml:153
-#: package/contents/ui/Application.qml:156
+#: package/contents/ui/Application.qml:130
+#: package/contents/ui/Application.qml:133
 msgid "Save configuration file"
 msgstr ""
 
-#: package/contents/ui/Application.qml:162
+#: package/contents/ui/Application.qml:139
 msgid "Please choose a configuration file"
 msgstr ""
 
-#: package/contents/ui/KCM.qml:34
+#: package/contents/ui/KCM.qml:45
 msgid "Control fans manually"
 msgstr ""
 
-#: package/contents/ui/KCM.qml:44
-msgid "Fan:"
-msgstr ""
-
-#: package/contents/ui/PwmFan.qml:344
-msgid "Controlled by:"
-msgstr ""
-
-#: package/contents/ui/PwmFan.qml:384
-msgid "Turn Fan off if temp < MINTEMP"
-msgstr ""
-
-#: package/contents/ui/PwmFan.qml:397
-msgid "Pwm value for fan to start:"
-msgstr ""
-
-#: package/contents/ui/PwmFan.qml:414
-msgid "Test start and stop values"
+#: package/contents/ui/KCM.qml:57 package/contents/ui/PwmFansTab.qml:67
+msgid "There are no pwm capable fans in your system."
 msgstr ""
 
-#: package/contents/ui/PwmFan.qml:425
-msgid "Abort"
+#: package/contents/ui/KCM.qml:63 package/contents/ui/KCM.qml:91
+#: package/contents/ui/PwmFansTab.qml:73
+#: package/contents/ui/SettingsTab.qml:171
+msgid "Detect fans"
 msgstr ""
 
-#: package/contents/ui/PwmFan.qml:425
-msgid "Test"
+#: package/contents/ui/KCM.qml:79
+msgid "Fan:"
 msgstr ""
 
-#: package/contents/ui/PwmFansTab.qml:67
-msgid "There are no pwm capable fans in your system."
+#: package/contents/ui/KCM.qml:116
+msgid "Advanced settings"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:50
+#: package/contents/ui/KCM.qml:131 package/contents/ui/SettingsTab.qml:51
 msgid "Interval:"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:69
+#: package/contents/ui/KCM.qml:158 package/contents/ui/SettingsTab.qml:78
 msgid "Minimum temperature for fan graphs:"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:93
+#: package/contents/ui/KCM.qml:185 package/contents/ui/SettingsTab.qml:104
 msgid "Maximum temperature for fan graphs:"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:117
-msgid "Unit:"
-msgstr ""
-
-#: package/contents/ui/SettingsTab.qml:125
-msgid "Celsius"
+#: package/contents/ui/KCM.qml:212 package/contents/ui/SettingsTab.qml:133
+msgid "Name of the fancontrol systemd service:"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:125
-msgid "Kelvin"
+#: package/contents/ui/PwmFan.qml:365
+msgid "Controlled by:"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:125
-msgid "Fahrenheit"
+#: package/contents/ui/PwmFan.qml:386
+msgid "Turn Fan off if temp < MINTEMP"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:140
-msgid "Name of the fancontrol systemd service:"
+#: package/contents/ui/PwmFan.qml:399
+msgid "Pwm value for fan to start:"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:162
-msgid "Fancontrol systemd service autostart:"
+#: package/contents/ui/PwmFan.qml:423
+msgid "Abort test"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:170
-msgid "disabled"
+#: package/contents/ui/PwmFan.qml:423
+msgid "Test start and stop values"
 msgstr ""
 
-#: package/contents/ui/SettingsTab.qml:170
-msgid "enabled"
+#: package/contents/ui/SettingsTab.qml:155
+msgid "Fancontrol systemd service autostart:"
 msgstr ""
 
 #: po/rc.cpp:1 rc.cpp:1