Commit fd63e9c5 authored by Falk Alexander Seidl's avatar Falk Alexander Seidl

Use dconf as settings interface

Dropped the config file settings implementation. Using dconf instead.
parent 0cb68ef9
......@@ -344,12 +344,10 @@
</packing>
</child>
<child>
<object class="GtkButton" id="show_password_button">
<object class="GtkToggleButton" id="show_password_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<child>
<object class="GtkImage" id="show_password_button_image">
<property name="visible">True</property>
......@@ -361,7 +359,6 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
......
......@@ -23,6 +23,10 @@
color: alpha(currentColor,0.5);
}
#SubtitleLabel {
color: red;
}
.PathbarButtonActive {
box-shadow: none;
transition-property: none;
......
......@@ -11,6 +11,12 @@ gnome.compile_resources(
install: true
)
# Installing the schema file
install_data(
project_id + '.gschema.xml',
install_dir: 'share/glib-2.0/schemas'
)
# Merging the translations with the desktop file
i18n.merge_file(
output: project_id + '.desktop',
......
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema path="/run/terminal/KeepassGtk/" id="run.terminal.KeepassGtk" gettext-domain="keepassgtk">
<key type="b" name="dark-theme">
<default>false</default>
<summary>Use dark Gtk theme</summary>
<description>Use the dark variant of your Gtk theme. Please note that not every Gtk theme has a dark variant.</description>
</key>
<key type="b" name="first-start-screen">
<default>true</default>
<summary>Reopen last opened database</summary>
<description>Automatically open the unlock screen of the last opened database, otherwise show the welcome screen.</description>
</key>
<key type="b" name="save-automatically">
<default>false</default>
<summary>Save every change automatically</summary>
<description>Save every change you made instantly into the database. Please note that you cannot revert changes if Autosave is enabled.</description>
</key>
<key type="i" name="database-lock-timeout">
<default>5</default>
<summary>Lock database after x minutes</summary>
<description>Automatically lock your database after a given amount of minutes to improve the security.</description>
</key>
<key type="i" name="clear-clipboard">
<default>30</default>
<summary>Clear clipboard after x seconds</summary>
<description>After copying the password clear the clipboard for security reasons.</description>
</key>
<key type="b" name="show-password-fields">
<default>false</default>
<summary>Display passwords in plain text</summary>
<description>Show the passwords in the entry fields by default.</description>
</key>
<key type="ai" name="window-size">
<default>[800, 500]</default>
<summary>Window size</summary>
<description>Remember the window size.</description>
</key>
<key type="s" name="last-opened-database">
<default>""</default>
<summary>Last opened database</summary>
<description>Path to the last opened database.</description>
</key>
</schema>
</schemalist>
......@@ -102,6 +102,7 @@
</child>
<child>
<object class="GtkLabel" id="settings_theme_description">
<property name="name">SubtitleLabel</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
......@@ -170,7 +171,7 @@
<property name="halign">start</property>
<property name="valign">end</property>
<property name="vexpand">True</property>
<property name="label" translatable="yes">First Start Screen</property>
<property name="label" translatable="yes">Hide First Start Screen</property>
</object>
<packing>
<property name="expand">False</property>
......@@ -180,6 +181,7 @@
</child>
<child>
<object class="GtkLabel" id="settings_fstart_description">
<property name="name">SubtitleLabel</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
......@@ -297,6 +299,7 @@
</child>
<child>
<object class="GtkLabel" id="settings_save_description">
<property name="name">SubtitleLabel</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
......@@ -414,6 +417,7 @@
</child>
<child>
<object class="GtkLabel" id="settings_lockdb_description">
<property name="name">SubtitleLabel</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
......@@ -439,21 +443,14 @@
</packing>
</child>
<child>
<object class="GtkMenuButton" id="settings_lockdb_menubutton">
<object class="GtkSpinButton" id="settings_lockdb_spin_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="margin_right">15</property>
<property name="popover">settings_lockdb_popover</property>
<child>
<object class="GtkLabel" id="settings_lockdb_menubutton_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Off</property>
</object>
</child>
<property name="max_length">2</property>
<property name="input_purpose">number</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="expand">False</property>
......@@ -500,12 +497,13 @@
</child>
<child>
<object class="GtkLabel" id="settings_clearcb_description">
<property name="name">SubtitleLabel</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">start</property>
<property name="vexpand">True</property>
<property name="label" translatable="yes">Clear Clipboard after copying password</property>
<property name="label" translatable="yes">Clear Clipboard after x seconds</property>
<attributes>
<attribute name="foreground" value="#555557575353"/>
<attribute name="size" value="9500"/>
......@@ -525,13 +523,14 @@
</packing>
</child>
<child>
<object class="GtkSwitch" id="settings_clearcb_switch">
<object class="GtkSpinButton" id="settings_clearcb_spin_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="margin_right">15</property>
<property name="hexpand">False</property>
<property name="max_length">4</property>
<property name="input_purpose">number</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="expand">False</property>
......@@ -578,6 +577,7 @@
</child>
<child>
<object class="GtkLabel" id="settings_showpw_description">
<property name="name">SubtitleLabel</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
......@@ -637,113 +637,4 @@
</object>
</child>
</object>
<object class="GtkPopover" id="settings_lockdb_popover">
<property name="can_focus">False</property>
<property name="relative_to">settings_lockdb_menubutton</property>
<child>
<object class="GtkBox" id="popover_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkModelButton" id="popover_entry_off">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.settings_timeout_off</property>
<property name="text" translatable="yes">Off</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="popover_entry_30sec">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.settings_timeout_30sec</property>
<property name="text" translatable="yes">30 seconds</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="popover_entry_1min">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.settings_timeout_1min</property>
<property name="text" translatable="yes">1 minute</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="popover_entry_5min">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.settings_timeout_5min</property>
<property name="text" translatable="yes">5 minutes</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="popover_entry_15min">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.settings_timeout_15min</property>
<property name="text" translatable="yes">15 minutes</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="popover_entry_30min">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.settings_timeout_30min</property>
<property name="text" translatable="yes">30 minutes</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="popover_entry_1h">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.settings_timeout_1h</property>
<property name="text" translatable="yes">1 hour</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
......@@ -3,6 +3,7 @@ import sys
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gio, Gtk
from keepassgtk.main_window import MainWindow
from keepassgtk.settings_dialog import SettingsDialog
class Application(Gtk.Application):
......@@ -15,6 +16,7 @@ class Application(Gtk.Application):
def do_startup(self):
Gtk.Application.do_startup(self)
GLib.set_application_name('KeepassGtk')
GLib.set_prgname("KeepassGtk")
self.assemble_application_menu()
......@@ -52,12 +54,7 @@ class Application(Gtk.Application):
self.set_app_menu(app_menu)
def on_settings_menu_clicked(self, action, param):
builder = Gtk.Builder()
builder.add_from_resource("/run/terminal/KeepassGtk/settings_dialog.ui")
settings_dialog = builder.get_object("settings_dialog")
settings_dialog.set_modal(True)
settings_dialog.set_transient_for(self.window)
settings_dialog.present()
SettingsDialog(self.window).on_settings_menu_clicked(action, param)
def on_about_menu_clicked(self, action, param):
builder = Gtk.Builder()
......
import os
from os.path import exists, join
from gi.repository import GLib
from gi.repository import GLib, Gio
cfg = GLib.KeyFile()
setting = Gio.Settings.new("run.terminal.KeepassGtk")
HOME = os.getenv("HOME")
CONFIG_PATH = join(HOME, '.config/keepassgtk')
CONFIG_FILE = join(CONFIG_PATH, 'config.conf')
clear_clipboard = "clear-clipboard"
dark_theme = "dark-theme"
database_lock_timeout = "database-lock-timeout"
first_start_screen = "first-start-screen"
last_opened_database = "last-opened-database"
save_automatically = "save-automatically"
show_password_fields = "show-password-fields"
window_size = "window-size"
#
# Create Config (First Run)
#
def get_clear_clipboard():
return setting.get_int(clear_clipboard)
def set_clear_clipboard(value):
setting.set_int(clear_clipboard, value)
def configure():
if not exists(CONFIG_PATH):
create_config_dir(CONFIG_PATH)
def get_dark_theme():
return setting.get_boolean(dark_theme)
if not exists(CONFIG_FILE):
create_config_file(CONFIG_FILE)
def set_dark_theme(value):
setting.set_boolean(dark_theme, value)
def get_database_lock_timeout():
return setting.get_int(database_lock_timeout)
def create_config_dir(path):
os.mkdir(path)
def set_database_lock_timeout(value):
setting.set_int(database_lock_timeout, value)
def get_first_start_screen():
return setting.get_boolean(first_start_screen)
def create_config_file(filename):
create_config_entry_string('settings', 'theme-variant', 'white')
cfg.save_to_file(filename)
def set_first_start_screen(value):
setting.set_boolean(first_start_screen, value)
#
# Write Into Config
#
def get_last_opened_database():
return setting.get_string(last_opened_database)
def set_last_opened_database(value):
setting.set_string(last_opened_database, value)
def create_config_entry_string(group, key, string):
cfg.set_string(group, key, string)
def get_save_automatically():
return setting.get_boolean(save_automatically)
def set_save_automatically(value):
setting.set_boolean(save_automatically, value)
def create_config_entry_integer(group, key, integer):
cfg.set_integer(group, key, integer)
def get_show_password_fields():
return setting.get_boolean(show_password_fields)
def set_show_password_fields(value):
setting.set_boolean(show_password_fields, value)
def create_config_entry_double(group, key, double):
cfg.set_double(group, key, double)
def get_window_size():
return setting.get_value(window_size)
def create_config_entry_boolean(group, key, boolean):
cfg.set_boolean(group, key, boolean)
#
# Checks
#
def has_group(group):
cfg.load_from_file(CONFIG_FILE, GLib.KeyFileFlags.KEEP_COMMENTS)
return cfg.has_group(group)
# def has_key(key, group):
# config_file = cfg.load_from_file(CONFIG_FILE, GLib.KeyFileFlags.KEEP_COMMENTS)
# group = cfg.
# return cfg.has_key(group, key)
def get_string(key, group):
cfg.load_from_file(CONFIG_FILE, GLib.KeyFileFlags.KEEP_COMMENTS)
return cfg.get_string(key, group)
#
# Save Config
#
def save_config():
cfg.save_to_file(CONFIG_FILE)
def unref_config():
cfg.unref()
def set_window_size(list):
g_variant = GLib.Variant('ai', list)
setting.set_value(window_size, g_variant)
from gi.repository import Gio, Gdk, Gtk
from gi.repository import Gio, GLib, Gdk, Gtk
from keepassgtk.logging_manager import LoggingManager
from keepassgtk.database_manager import DatabaseManager
from keepassgtk.create_database import CreateDatabase
......@@ -29,11 +29,11 @@ class MainWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
keepassgtk.config_manager.configure()
self.assemble_window()
def assemble_window(self):
self.set_default_size(800, 500)
window_size = keepassgtk.config_manager.get_window_size()
self.set_default_size(window_size[0], window_size[1])
self.create_headerbar()
self.first_start_screen()
......@@ -41,6 +41,7 @@ class MainWindow(Gtk.ApplicationWindow):
self.connect("delete-event", self.on_application_quit)
self.custom_css()
self.apply_theme()
#
# Headerbar
......@@ -82,23 +83,26 @@ class MainWindow(Gtk.ApplicationWindow):
context.add_provider_for_screen(
screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
def apply_theme(self):
gtk_settings = Gtk.Settings.get_default()
if keepassgtk.config_manager.get_dark_theme() is True:
gtk_settings.set_property("gtk-application-prefer-dark-theme", True)
else:
gtk_settings.set_property("gtk-application-prefer-dark-theme", False)
#
# First Start Screen
#
def first_start_screen(self):
if keepassgtk.config_manager.has_group("history") and keepassgtk.config_manager.get_string("history", "last-opened-db") != "" and exists(keepassgtk.config_manager.get_string("history", "last-opened-db")):
self.logging_manager.log_debug(
"Found last opened database entry (" +
keepassgtk.config_manager.get_string(
"history", "last-opened-db") + ")")
tab_title = ntpath.basename(keepassgtk.config_manager.get_string(
"history", "last-opened-db"))
self.start_database_opening_routine(
tab_title,
keepassgtk.config_manager.get_string(
"history", "last-opened-db"))
filepath = keepassgtk.config_manager.get_last_opened_database()
if keepassgtk.config_manager.get_first_start_screen() is True and filepath is not "":
self.logging_manager.log_debug("Found last opened database entry (" + filepath + ")")
tab_title = ntpath.basename(filepath)
self.start_database_opening_routine(tab_title, filepath)
else:
self.logging_manager.log_debug(
"No / Not valid last opened database entry found.")
......@@ -337,12 +341,17 @@ class MainWindow(Gtk.ApplicationWindow):
db.database_manager.save_database()
self.quit_dialog.destroy()
self.save_window_size()
self.application.quit()
#
# Application Quit Dialog
#
def save_window_size(self):
window_size = [self.get_size().width, self.get_size().height]
keepassgtk.config_manager.set_window_size(window_size)
def on_application_quit(self, window, event):
unsaved_databases_list = []
for db in self.opened_databases:
......@@ -378,4 +387,7 @@ class MainWindow(Gtk.ApplicationWindow):
self.quit_dialog.present()
return(True)
return(True)
else:
self.save_window_size()
......@@ -17,6 +17,8 @@ class ScrolledPage(Gtk.ScrolledWindow):
password_property_row = NotImplemented
password_property_value_entry = NotImplemented
show_password_button = NotImplemented
generate_password_button = NotImplemented
url_property_row = NotImplemented
url_property_value_entry = NotImplemented
......
from gi.repository import Gtk
import keepassgtk.config_manager
import gi
class SettingsDialog():
window = NotImplemented
builder = NotImplemented
def __init__(self, window):
self.window = window
self.builder = Gtk.Builder()
self.builder.add_from_resource("/run/terminal/KeepassGtk/settings_dialog.ui")
def on_settings_menu_clicked(self, action, param):
settings_dialog = self.builder.get_object("settings_dialog")
settings_dialog.set_modal(True)
settings_dialog.set_transient_for(self.window)
settings_dialog.present()
self.set_config_values()
def set_config_values(self):
settings_theme_switch = self.builder.get_object("settings_theme_switch")
settings_theme_switch.connect("notify::active", self.on_settings_theme_switch_switched)
settings_theme_switch_value = keepassgtk.config_manager.get_dark_theme()
settings_theme_switch.set_active(settings_theme_switch_value)
settings_fstart_switch = self.builder.get_object("settings_fstart_switch")
settings_fstart_switch.connect("notify::active", self.on_settings_fstart_switch_switched)
settings_fstart_switch_value = keepassgtk.config_manager.get_first_start_screen()
settings_fstart_switch.set_active(settings_fstart_switch_value)
settings_save_switch = self.builder.get_object("settings_save_switch")
settings_save_switch.connect("notify::active", self.on_settings_save_switch_switched)
settings_save_switch_value = keepassgtk.config_manager.get_save_automatically()
settings_save_switch.set_active(settings_save_switch_value)
settings_lockdb_spin_button = self.builder.get_object("settings_lockdb_spin_button")
settings_lockdb_spin_button.connect("value-changed", self.on_settings_lockdb_spin_button_changed)
settings_lockdb_spin_button_value = keepassgtk.config_manager.get_database_lock_timeout()
lockdb_adjustment = Gtk.Adjustment(settings_lockdb_spin_button_value, 0, 60, 1, 5)
settings_lockdb_spin_button.set_adjustment(lockdb_adjustment)
settings_clearcb_spin_button = self.builder.get_object("settings_clearcb_spin_button")
settings_clearcb_spin_button.connect("value-changed", self.on_settings_clearcb_spin_button_changed)
settings_clearcb_spin_button_value = keepassgtk.config_manager.get_clear_clipboard()
clearcb_adjustment = Gtk.Adjustment(settings_clearcb_spin_button_value, 0, 300, 1, 5)
settings_clearcb_spin_button.set_adjustment(clearcb_adjustment)
settings_showpw_switch = self.builder.get_object("settings_showpw_switch")
settings_showpw_switch.connect("notify::active", self.on_settings_showpw_switch_switched)
settings_showpw_switch_value = keepassgtk.config_manager.get_show_password_fields()
settings_showpw_switch.set_active(settings_showpw_switch_value)
def on_settings_theme_switch_switched(self, switch_button, gparam):
gtk_settings = Gtk.Settings.get_default()
if switch_button.get_active():
keepassgtk.config_manager.set_dark_theme(True)
gtk_settings.set_property("gtk-application-prefer-dark-theme", True)
else:
keepassgtk.config_manager.set_dark_theme(False)
gtk_settings.set_property("gtk-application-prefer-dark-theme", False)
def on_settings_fstart_switch_switched(self, switch_button, gparam):
if switch_button.get_active():
keepassgtk.config_manager.set_first_start_screen(True)
else:
keepassgtk.config_manager.set_first_start_screen(False)
def on_settings_save_switch_switched(self, switch_button, gparam):
if switch_button.get_active():
keepassgtk.config_manager.set_save_automatically(True)
else:
keepassgtk.config_manager.set_save_automatically(False)
def on_settings_lockdb_spin_button_changed(self, spin_button):
keepassgtk.config_manager.set_database_lock_timeout(spin_button.get_value())
def on_settings_clearcb_spin_button_changed(self, spin_button):
keepassgtk.config_manager.set_clear_clipboard(spin_button.get_value())
def on_settings_showpw_switch_switched(self, switch_button, gparam):
if switch_button.get_active():
keepassgtk.config_manager.set_show_password_fields(True)
else:
keepassgtk.config_manager.set_show_password_fields(False)
......@@ -243,8 +243,7 @@ class UnlockDatabase:
#
def open_database_page(self):
self.clear_input_fields()
keepassgtk.config_manager.create_config_entry_string("history", "last-opened-db", str(self.database_filepath))
keepassgtk.config_manager.save_config()
keepassgtk.config_manager.set_last_opened_database(str(self.database_filepath))
self.unlock_database_stack_box.destroy()
UnlockedDatabase(self.window, self.parent_widget, self.database_manager)
......
......@@ -4,6 +4,7 @@ from keepassgtk.pathbar import Pathbar
from keepassgtk.entry_row import EntryRow
from keepassgtk.group_row import GroupRow
from keepassgtk.scrolled_page import ScrolledPage
import keepassgtk.config_manager
import gi
import ntpath
import threading
......@@ -338,16 +339,22 @@ class UnlockedDatabase:
scrolled_page.username_property_value_entry.connect("changed", self.on_property_value_entry_changed, "username")
properties_list_box.add(scrolled_page.username_property_row)
if self.database_manager.has_entry_password(entry_uuid) is True or add_all is True:
if self.database_manager.has_entry_password(entry_uuid) is True or add_all is True:
if scrolled_page.password_property_row is NotImplemented:
scrolled_page.password_property_row = builder.get_object("password_property_row")
scrolled_page.password_property_value_entry = builder.get_object("password_property_value_entry")
scrolled_page.show_password_button = builder.get_object("show_password_button")
value = self.database_manager.get_entry_password_from_entry_uuid(entry_uuid)
if self.database_manager.has_entry_password(entry_uuid) is True:
scrolled_page.password_property_value_entry.set_text(value)
else:
scrolled_page.password_property_value_entry.set_text("")
scrolled_page.password_property_value_entry.connect("changed", self.on_property_value_entry_changed, "password")
self.change_password_entry_visibility(scrolled_page.password_property_value_entry, scrolled_page.show_password_button)
properties_list_box.add(scrolled_page.password_property_row)
elif scrolled_page.password_property_row is not "":
value = self.database_manager.get_entry_password_from_entry_uuid(entry_uuid)
......@@ -356,6 +363,7 @@ class UnlockedDatabase:
else:
scrolled_page.password_property_value_entry.set_text("")
scrolled_page.password_property_value_entry.connect("changed", self.on_property_value_entry_changed, "password")
self.change_password_entry_visibility(scrolled_page.password_property_value_entry)
properties_list_box.add(scrolled_page.password_property_row)
if self.database_manager.has_entry_url(entry_uuid) is True or add_all is True:
......@@ -570,6 +578,12 @@ class UnlockedDatabase:
self.pathbar.add_pathbar_button_to_pathbar(group_uuid)
self.show_page_of_new_directory(True)
def on_show_password_button_toggled(self, toggle_button, entry):
if entry.get_visibility() is True:
entry.set_visibility(False)
else:
entry.set_visibility(True)
#
# Dialog Creator
#
......@@ -612,3 +626,16 @@ class UnlockedDatabase: