tMake password expiration customizable - sailfish-safe - Sailfish frontend for safe(1)
 (HTM) git clone git://git.z3bra.org/sailfish-safe.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 282985f0b34b09b001e0a3c14fe8361c4d17282c
 (DIR) parent b68489e813410b19b4a5f766be76d92ade4d449f
 (HTM) Author: Daniel Vrátil <dvratil@kde.org>
       Date:   Thu, 14 Feb 2019 22:19:54 +0100
       
       Make password expiration customizable
       
       Diffstat:
         M harbour-passilic.pro                |      10 +++++++---
         M qml/components/GlobalPullDownMenu.… |       4 ++++
         A qml/pages/SettingsPage.qml          |      71 +++++++++++++++++++++++++++++++
         M src/main.cpp                        |       9 +++++++++
         M src/passwordprovider.cpp            |       4 ++--
         M src/passwordsmodel.cpp              |       3 +++
         A src/scopeguard.h                    |      49 +++++++++++++++++++++++++++++++
         A src/settings.cpp                    |      56 +++++++++++++++++++++++++++++++
         A src/settings.h                      |      53 ++++++++++++++++++++++++++++++
         M translations/harbour-passilic-zh_c… |      16 ++++++++++++++++
         M translations/harbour-passilic.ts    |      16 ++++++++++++++++
       
       11 files changed, 286 insertions(+), 5 deletions(-)
       ---
 (DIR) diff --git a/harbour-passilic.pro b/harbour-passilic.pro
       t@@ -22,7 +22,8 @@ SOURCES += \
            src/passwordprovider.cpp \
            src/passwordsmodel.cpp \
            src/passwordsortproxymodel.cpp \
       -    3rdparty/kitemmodels/kdescendantsproxymodel.cpp
       +    3rdparty/kitemmodels/kdescendantsproxymodel.cpp \
       +    src/settings.cpp
        
        
        HEADERS += \
       t@@ -32,7 +33,9 @@ HEADERS += \
            src/passwordprovider.h \
            src/passwordsmodel.h \
            src/passwordsortproxymodel.h \
       -    3rdparty/kitemmodels/kdescendantsproxymodel.h
       +    3rdparty/kitemmodels/kdescendantsproxymodel.h \
       +    src/settings.h \
       +    src/scopeguard.h
        
        DISTFILES += \
            qml/harbour-passilic.qml \
       t@@ -48,7 +51,8 @@ DISTFILES += \
            translations/*.ts \
            harbour-passilic.desktop \
            qml/pages/SearchPage.qml \
       -    qml/components/PasswordDelegate.qml
       +    qml/components/PasswordDelegate.qml \
       +    qml/pages/SettingsPage.qml
        
        OTHER_FILES += \
            README.md
 (DIR) diff --git a/qml/components/GlobalPullDownMenu.qml b/qml/components/GlobalPullDownMenu.qml
       t@@ -25,6 +25,10 @@ PullDownMenu {
                onClicked: app.pageStack.push(Qt.resolvedUrl("../pages/AboutPage.qml"))
            }
            MenuItem {
       +        text: qsTr("Settings")
       +        onClicked: app.pageStack.push(Qt.resolvedUrl("../pages/SettingsPage.qml"))
       +    }
       +    MenuItem {
                text: qsTr("Search")
                onClicked: app.pageStack.push(searchPage)
            }
 (DIR) diff --git a/qml/pages/SettingsPage.qml b/qml/pages/SettingsPage.qml
       t@@ -0,0 +1,71 @@
       +/*
       + *   Copyright (C) 2019  Daniel Vrátil <dvratil@kde.org>
       + *
       + *   This program is free software: you can redistribute it and/or modify
       + *   it under the terms of the GNU General Public License as published by
       + *   the Free Software Foundation, either version 3 of the License, or
       + *   (at your option) any later version.
       + *
       + *   This program is distributed in the hope that it will be useful,
       + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
       + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       + *   GNU General Public License for more details.
       + *
       + *   You should have received a copy of the GNU General Public License
       + *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
       + */
       +
       +import QtQuick 2.0
       +import Sailfish.Silica 1.0
       +import QtQuick 2.0
       +import harbour.passilic 1.0
       +
       +Dialog {
       +    id: settingsDialog
       +
       +    onAccepted: {
       +        Settings.expirationTimeout = expirationSlider.sliderValue
       +        Settings.save()
       +    }
       +
       +    DialogHeader {
       +        id: dialogHeader
       +        width: parent.width
       +    }
       +
       +    SilicaFlickable {
       +        anchors {
       +            left: parent.left
       +            right: parent.right
       +            top: dialogHeader.bottom
       +            bottom: parent.bottom
       +            leftMargin: Theme.horizontalPageMargin
       +            rightMargin: Theme.horizontalPageMargin
       +        }
       +
       +        Column {
       +            spacing: Theme.paddingMedium
       +            width: parent.width
       +
       +            Label {
       +                text: qsTr("Password expiration")
       +            }
       +            Slider {
       +                id: expirationSlider
       +                width: parent.width
       +
       +                minimumValue: 10
       +                maximumValue: 120
       +                stepSize: 1
       +                //: number of seconds
       +                valueText: qsTr("%1 s").arg(sliderValue)
       +
       +                Component.onCompleted: value = Settings.expirationTimeout
       +            }
       +        }
       +
       +        VerticalScrollDecorator {
       +            flickable: parent
       +        }
       +    }
       +}
 (DIR) diff --git a/src/main.cpp b/src/main.cpp
       t@@ -19,6 +19,8 @@
        #include "passwordfiltermodel.h"
        #include "passwordsortproxymodel.h"
        #include "imageprovider.h"
       +#include "scopeguard.h"
       +#include "settings.h"
        
        #include <QQuickView>
        #include <QQmlEngine>
       t@@ -41,10 +43,17 @@ int main(int argc, char *argv[])
            app->setOrganizationName(QObject::tr("Daniel Vrátil"));
        
            QScopedPointer<QQuickView> view(SailfishApp::createView());
       +    const auto settingsGuard = scopeGuard([]() {
       +        Settings::destroy();
       +    });
        
            qmlRegisterType<PasswordsModel>("harbour.passilic", 1, 0, "PasswordsModel");
            qmlRegisterType<PasswordFilterModel>("harbour.passilic", 1, 0, "PasswordFilterModel");
            qmlRegisterType<PasswordSortProxyModel>("harbour.passilic", 1, 0, "PasswordSortProxyModel");
       +    qmlRegisterSingletonType<Settings>("harbour.passilic", 1, 0, "Settings",
       +                                       [](QQmlEngine *, QJSEngine *) -> QObject* {
       +                                            return Settings::self();
       +                                       });
        
            addImageProvider(view->engine(), QStringLiteral("passIcon"));
            addImageProvider(view->engine(), QStringLiteral("passImage"));
 (DIR) diff --git a/src/passwordprovider.cpp b/src/passwordprovider.cpp
       t@@ -18,6 +18,7 @@
         */
        
        #include "passwordprovider.h"
       +#include "settings.h"
        
        #include <QProcess>
        #include <QStandardPaths>
       t@@ -26,7 +27,6 @@
        
        namespace {
        
       -static const auto PasswordTimeout = 45 * 1000;
        static const auto PasswordTimeoutUpdateInterval = 100;
        
        }
       t@@ -168,7 +168,7 @@ int PasswordProvider::timeout() const
        
        int PasswordProvider::defaultTimeout() const
        {
       -    return PasswordTimeout;
       +    return Settings::self()->expirationTimeout() * 1000;
        }
        
        QString PasswordProvider::error() const
 (DIR) diff --git a/src/passwordsmodel.cpp b/src/passwordsmodel.cpp
       t@@ -41,6 +41,9 @@ public:
        
            ~Node()
            {
       +        if (provider) {
       +            provider->expirePassword();
       +        }
                qDeleteAll(children);
            }
        
 (DIR) diff --git a/src/scopeguard.h b/src/scopeguard.h
       t@@ -0,0 +1,49 @@
       +/*
       + *   Copyright (C) 2019  Daniel Vrátil <dvratil@kde.org>
       + *
       + *   This program is free software: you can redistribute it and/or modify
       + *   it under the terms of the GNU General Public License as published by
       + *   the Free Software Foundation, either version 3 of the License, or
       + *   (at your option) any later version.
       + *
       + *   This program is distributed in the hope that it will be useful,
       + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
       + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       + *   GNU General Public License for more details.
       + *
       + *   You should have received a copy of the GNU General Public License
       + *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
       + */
       +
       +#ifndef SCOPEGUARD_H
       +#define SCOPEGUARD_H
       +
       +template<typename Func>
       +class ScopeGuard
       +{
       +public:
       +    ScopeGuard(Func &&func)
       +        : mFunc(std::move(func))
       +    {}
       +
       +    ScopeGuard(ScopeGuard<Func> &&) = default;
       +    ScopeGuard<Func> &operator=(ScopeGuard<Func> &&) = default;
       +    ScopeGuard(const ScopeGuard<Func> &) = delete;
       +    ScopeGuard<Func> &operator=(const ScopeGuard<Func> &) = delete;
       +
       +    ~ScopeGuard()
       +    {
       +        mFunc();
       +    }
       +
       +private:
       +    Func mFunc;
       +};
       +
       +template<typename Func>
       +ScopeGuard<Func> scopeGuard(Func &&func)
       +{
       +    return ScopeGuard<Func>(std::move(func));
       +}
       +
       +#endif // SCOPEGUARD_H
 (DIR) diff --git a/src/settings.cpp b/src/settings.cpp
       t@@ -0,0 +1,56 @@
       +/*
       + *   Copyright (C) 2019  Daniel Vrátil <dvratil@kde.org>
       + *
       + *   This program is free software: you can redistribute it and/or modify
       + *   it under the terms of the GNU General Public License as published by
       + *   the Free Software Foundation, either version 3 of the License, or
       + *   (at your option) any later version.
       + *
       + *   This program is distributed in the hope that it will be useful,
       + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
       + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       + *   GNU General Public License for more details.
       + *
       + *   You should have received a copy of the GNU General Public License
       + *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
       + */
       +
       +#include "settings.h"
       +
       +std::unique_ptr<Settings> Settings::kInstance = {};
       +
       +Settings::Settings(): QObject() {}
       +
       +Settings *Settings::self()
       +{
       +    if (!kInstance) {
       +        kInstance.reset(new Settings);
       +    }
       +    return kInstance.get();
       +}
       +
       +void Settings::destroy()
       +{
       +    kInstance.reset();
       +}
       +
       +void Settings::save()
       +{
       +    mSettings.sync();
       +}
       +
       +#define IMPLEMENT_OPTION(type, lc, uc, name, defValue) \
       +    void Settings::set##uc(type val) { \
       +        if (lc() != val) { \
       +            mSettings.setValue(QStringLiteral(name), val); \
       +            Q_EMIT lc##Changed(); \
       +        } \
       +    } \
       +    type Settings::lc() const { \
       +        return mSettings.value(QStringLiteral(name), defValue).value<type>(); \
       +    }
       +
       +IMPLEMENT_OPTION(int, expirationTimeout, ExpirationTimeout, "expirationTimeout", 45)
       +
       +
       +#undef IMPLEMENT_OPTION
 (DIR) diff --git a/src/settings.h b/src/settings.h
       t@@ -0,0 +1,53 @@
       +/*
       + *   Copyright (C) 2019  Daniel Vrátil <dvratil@kde.org>
       + *
       + *   This program is free software: you can redistribute it and/or modify
       + *   it under the terms of the GNU General Public License as published by
       + *   the Free Software Foundation, either version 3 of the License, or
       + *   (at your option) any later version.
       + *
       + *   This program is distributed in the hope that it will be useful,
       + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
       + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       + *   GNU General Public License for more details.
       + *
       + *   You should have received a copy of the GNU General Public License
       + *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
       + */
       +
       +#ifndef SETTINGS_H
       +#define SETTINGS_H
       +
       +#include <QObject>
       +#include <QSettings>
       +
       +#include <memory>
       +
       +#define DECLARE_OPTION(type, lc, uc) \
       +    private: Q_PROPERTY(type lc READ lc WRITE set##uc NOTIFY lc##Changed) \
       +    public: type lc() const; \
       +    public: void set##uc(type val); \
       +    Q_SIGNALS: void lc##Changed();
       +
       +
       +class Settings : public QObject
       +{
       +    Q_OBJECT
       +public:
       +    static Settings *self();
       +    static void destroy();
       +
       +    Q_INVOKABLE void save();
       +
       +    DECLARE_OPTION(int, expirationTimeout, ExpirationTimeout)
       +
       +private:
       +    explicit Settings();
       +    QSettings mSettings;
       +
       +    static std::unique_ptr<Settings> kInstance;
       +};
       +
       +#undef DECLARE_OPTION
       +
       +#endif // SETTINGS_H
 (DIR) diff --git a/translations/harbour-passilic-zh_cn.ts b/translations/harbour-passilic-zh_cn.ts
       t@@ -38,6 +38,10 @@
                <source>Search</source>
                <translation type="unfinished"></translation>
            </message>
       +    <message>
       +        <source>Settings</source>
       +        <translation type="unfinished"></translation>
       +    </message>
        </context>
        <context>
            <name>PasswordDelegate</name>
       t@@ -95,4 +99,16 @@
                <translation>Daniel Vrátil</translation>
            </message>
        </context>
       +<context>
       +    <name>SettingsPage</name>
       +    <message>
       +        <source>Password expiration</source>
       +        <translation type="unfinished"></translation>
       +    </message>
       +    <message>
       +        <source>%1 s</source>
       +        <extracomment>number of seconds</extracomment>
       +        <translation type="unfinished"></translation>
       +    </message>
       +</context>
        </TS>
 (DIR) diff --git a/translations/harbour-passilic.ts b/translations/harbour-passilic.ts
       t@@ -38,6 +38,10 @@
                <source>Search</source>
                <translation type="unfinished"></translation>
            </message>
       +    <message>
       +        <source>Settings</source>
       +        <translation type="unfinished"></translation>
       +    </message>
        </context>
        <context>
            <name>PasswordDelegate</name>
       t@@ -95,4 +99,16 @@
                <translation type="unfinished"></translation>
            </message>
        </context>
       +<context>
       +    <name>SettingsPage</name>
       +    <message>
       +        <source>Password expiration</source>
       +        <translation type="unfinished"></translation>
       +    </message>
       +    <message>
       +        <source>%1 s</source>
       +        <extracomment>number of seconds</extracomment>
       +        <translation type="unfinished"></translation>
       +    </message>
       +</context>
        </TS>