commit 282985f0b34b09b001e0a3c14fe8361c4d17282c
parent b68489e813410b19b4a5f766be76d92ade4d449f
Author: Daniel Vrátil <dvratil@kde.org>
Date: Thu, 14 Feb 2019 22:19:54 +0100
Make password expiration customizable
Diffstat:
11 files changed, 286 insertions(+), 5 deletions(-)
diff --git a/harbour-passilic.pro b/harbour-passilic.pro
@@ -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 += \
@@ -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 \
@@ -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
diff --git a/qml/components/GlobalPullDownMenu.qml b/qml/components/GlobalPullDownMenu.qml
@@ -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)
}
diff --git a/qml/pages/SettingsPage.qml b/qml/pages/SettingsPage.qml
@@ -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
+ }
+ }
+}
diff --git a/src/main.cpp b/src/main.cpp
@@ -19,6 +19,8 @@
#include "passwordfiltermodel.h"
#include "passwordsortproxymodel.h"
#include "imageprovider.h"
+#include "scopeguard.h"
+#include "settings.h"
#include <QQuickView>
#include <QQmlEngine>
@@ -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"));
diff --git a/src/passwordprovider.cpp b/src/passwordprovider.cpp
@@ -18,6 +18,7 @@
*/
#include "passwordprovider.h"
+#include "settings.h"
#include <QProcess>
#include <QStandardPaths>
@@ -26,7 +27,6 @@
namespace {
-static const auto PasswordTimeout = 45 * 1000;
static const auto PasswordTimeoutUpdateInterval = 100;
}
@@ -168,7 +168,7 @@ int PasswordProvider::timeout() const
int PasswordProvider::defaultTimeout() const
{
- return PasswordTimeout;
+ return Settings::self()->expirationTimeout() * 1000;
}
QString PasswordProvider::error() const
diff --git a/src/passwordsmodel.cpp b/src/passwordsmodel.cpp
@@ -41,6 +41,9 @@ public:
~Node()
{
+ if (provider) {
+ provider->expirePassword();
+ }
qDeleteAll(children);
}
diff --git a/src/scopeguard.h b/src/scopeguard.h
@@ -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
diff --git a/src/settings.cpp b/src/settings.cpp
@@ -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
diff --git a/src/settings.h b/src/settings.h
@@ -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
diff --git a/translations/harbour-passilic-zh_cn.ts b/translations/harbour-passilic-zh_cn.ts
@@ -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>
@@ -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>
diff --git a/translations/harbour-passilic.ts b/translations/harbour-passilic.ts
@@ -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>
@@ -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>