Add preferences dialog with TLS and timeout settings
- Add PreferencesDialog with settings for TLS verification and request timeout - Update HttpClient to respect TLS verification setting - Add GSettings schema keys for force-tls-verification and request-timeout - Wire up preferences action to show dialog - Settings changes apply immediately to HTTP session
This commit is contained in:
parent
66719a5d0c
commit
2545cdd88d
@ -1,5 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<schemalist gettext-domain="roster">
|
<schemalist gettext-domain="roster">
|
||||||
<schema id="cz.vesp.roster" path="/cz/vesp/roster/">
|
<schema id="cz.vesp.roster" path="/cz/vesp/roster/">
|
||||||
|
<key name="force-tls-verification" type="b">
|
||||||
|
<default>true</default>
|
||||||
|
<summary>Force TLS verification</summary>
|
||||||
|
<description>When enabled, TLS certificates will be verified. Disable to test endpoints with self-signed or invalid certificates.</description>
|
||||||
|
</key>
|
||||||
|
<key name="request-timeout" type="i">
|
||||||
|
<default>30</default>
|
||||||
|
<summary>Request timeout</summary>
|
||||||
|
<description>Timeout for HTTP requests in seconds</description>
|
||||||
|
</key>
|
||||||
</schema>
|
</schema>
|
||||||
</schemalist>
|
</schemalist>
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
import gi
|
import gi
|
||||||
gi.require_version('Soup', '3.0')
|
gi.require_version('Soup', '3.0')
|
||||||
from gi.repository import Soup, GLib
|
from gi.repository import Soup, GLib, Gio
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from typing import Optional, Callable, Any
|
from typing import Optional, Callable, Any
|
||||||
@ -32,7 +32,36 @@ class HttpClient:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize HTTP client with reusable session."""
|
"""Initialize HTTP client with reusable session."""
|
||||||
self.session = Soup.Session.new()
|
self.session = Soup.Session.new()
|
||||||
self.session.set_timeout(30) # 30 second timeout
|
|
||||||
|
# Load settings
|
||||||
|
self.settings = Gio.Settings.new('cz.vesp.roster')
|
||||||
|
|
||||||
|
# Initialize TLS verification flag
|
||||||
|
self.force_tls_verification = True
|
||||||
|
|
||||||
|
# Apply initial settings
|
||||||
|
self._apply_settings()
|
||||||
|
|
||||||
|
# Listen for settings changes
|
||||||
|
self.settings.connect('changed::force-tls-verification', self._on_settings_changed)
|
||||||
|
self.settings.connect('changed::request-timeout', self._on_settings_changed)
|
||||||
|
|
||||||
|
def _apply_settings(self):
|
||||||
|
"""Apply settings to the HTTP session."""
|
||||||
|
# Store TLS verification preference (will be applied per-message)
|
||||||
|
self.force_tls_verification = self.settings.get_boolean('force-tls-verification')
|
||||||
|
|
||||||
|
# Apply timeout setting
|
||||||
|
timeout = self.settings.get_int('request-timeout')
|
||||||
|
self.session.set_timeout(timeout)
|
||||||
|
|
||||||
|
def _on_settings_changed(self, settings, key):
|
||||||
|
"""Handle settings changes."""
|
||||||
|
self._apply_settings()
|
||||||
|
|
||||||
|
def _accept_all_certificates(self, msg, tls_certificate, tls_errors):
|
||||||
|
"""Accept all TLS certificates when verification is disabled."""
|
||||||
|
return True # Accept certificate regardless of errors
|
||||||
|
|
||||||
def execute_request_async(self, request: HttpRequest, callback: Callable, user_data: Any = None):
|
def execute_request_async(self, request: HttpRequest, callback: Callable, user_data: Any = None):
|
||||||
"""
|
"""
|
||||||
@ -59,6 +88,11 @@ class HttpClient:
|
|||||||
callback(None, f"Invalid URL: {e}", user_data)
|
callback(None, f"Invalid URL: {e}", user_data)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Handle TLS certificate verification
|
||||||
|
if not self.force_tls_verification:
|
||||||
|
# Connect signal to accept all certificates when verification is disabled
|
||||||
|
msg.connect('accept-certificate', self._accept_all_certificates)
|
||||||
|
|
||||||
# Add headers
|
# Add headers
|
||||||
headers = msg.get_request_headers()
|
headers = msg.get_request_headers()
|
||||||
for key, value in request.headers.items():
|
for key, value in request.headers.items():
|
||||||
|
|||||||
@ -25,6 +25,7 @@ gi.require_version('Adw', '1')
|
|||||||
|
|
||||||
from gi.repository import Gtk, Gio, Adw
|
from gi.repository import Gtk, Gio, Adw
|
||||||
from .window import RosterWindow
|
from .window import RosterWindow
|
||||||
|
from .preferences_dialog import PreferencesDialog
|
||||||
|
|
||||||
|
|
||||||
class RosterApplication(Adw.Application):
|
class RosterApplication(Adw.Application):
|
||||||
@ -67,7 +68,9 @@ class RosterApplication(Adw.Application):
|
|||||||
|
|
||||||
def on_preferences_action(self, widget, _):
|
def on_preferences_action(self, widget, _):
|
||||||
"""Callback for the app.preferences action."""
|
"""Callback for the app.preferences action."""
|
||||||
print('app.preferences action activated')
|
preferences = PreferencesDialog()
|
||||||
|
preferences.set_transient_for(self.props.active_window)
|
||||||
|
preferences.present()
|
||||||
|
|
||||||
def on_shortcuts_action(self, widget, _):
|
def on_shortcuts_action(self, widget, _):
|
||||||
"""Callback for the app.shortcuts action."""
|
"""Callback for the app.shortcuts action."""
|
||||||
|
|||||||
@ -37,6 +37,7 @@ roster_sources = [
|
|||||||
'tab_manager.py',
|
'tab_manager.py',
|
||||||
'constants.py',
|
'constants.py',
|
||||||
'icon_picker_dialog.py',
|
'icon_picker_dialog.py',
|
||||||
|
'preferences_dialog.py',
|
||||||
]
|
]
|
||||||
|
|
||||||
install_data(roster_sources, install_dir: moduledir)
|
install_data(roster_sources, install_dir: moduledir)
|
||||||
|
|||||||
49
src/preferences-dialog.ui
Normal file
49
src/preferences-dialog.ui
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<requires lib="Adw" version="1.0"/>
|
||||||
|
|
||||||
|
<template class="PreferencesDialog" parent="AdwPreferencesWindow">
|
||||||
|
<property name="title" translatable="yes">Preferences</property>
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<property name="default-width">600</property>
|
||||||
|
<property name="default-height">400</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesPage">
|
||||||
|
<property name="title" translatable="yes">General</property>
|
||||||
|
<property name="icon-name">preferences-system-symbolic</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">Network</property>
|
||||||
|
<property name="description" translatable="yes">HTTP connection settings</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="AdwSwitchRow" id="tls_verification_row">
|
||||||
|
<property name="title" translatable="yes">Force TLS Verification</property>
|
||||||
|
<property name="subtitle" translatable="yes">Verify TLS certificates for HTTPS connections. Disable to test endpoints with self-signed certificates.</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="AdwSpinRow" id="timeout_row">
|
||||||
|
<property name="title" translatable="yes">Request Timeout</property>
|
||||||
|
<property name="subtitle" translatable="yes">Maximum time to wait for a response (in seconds)</property>
|
||||||
|
<property name="adjustment">
|
||||||
|
<object class="GtkAdjustment">
|
||||||
|
<property name="lower">5</property>
|
||||||
|
<property name="upper">300</property>
|
||||||
|
<property name="step-increment">5</property>
|
||||||
|
<property name="page-increment">10</property>
|
||||||
|
<property name="value">30</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
||||||
49
src/preferences_dialog.py
Normal file
49
src/preferences_dialog.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# preferences_dialog.py
|
||||||
|
#
|
||||||
|
# Copyright 2025 Pavel Baksy
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from gi.repository import Adw, Gtk, Gio
|
||||||
|
|
||||||
|
|
||||||
|
@Gtk.Template(resource_path='/cz/vesp/roster/preferences-dialog.ui')
|
||||||
|
class PreferencesDialog(Adw.PreferencesWindow):
|
||||||
|
__gtype_name__ = 'PreferencesDialog'
|
||||||
|
|
||||||
|
tls_verification_row = Gtk.Template.Child()
|
||||||
|
timeout_row = Gtk.Template.Child()
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
# Get settings
|
||||||
|
self.settings = Gio.Settings.new('cz.vesp.roster')
|
||||||
|
|
||||||
|
# Bind settings to UI
|
||||||
|
self.settings.bind(
|
||||||
|
'force-tls-verification',
|
||||||
|
self.tls_verification_row,
|
||||||
|
'active',
|
||||||
|
Gio.SettingsBindFlags.DEFAULT
|
||||||
|
)
|
||||||
|
|
||||||
|
self.settings.bind(
|
||||||
|
'request-timeout',
|
||||||
|
self.timeout_row,
|
||||||
|
'value',
|
||||||
|
Gio.SettingsBindFlags.DEFAULT
|
||||||
|
)
|
||||||
@ -3,6 +3,7 @@
|
|||||||
<gresource prefix="/cz/vesp/roster">
|
<gresource prefix="/cz/vesp/roster">
|
||||||
<file preprocess="xml-stripblanks">main-window.ui</file>
|
<file preprocess="xml-stripblanks">main-window.ui</file>
|
||||||
<file preprocess="xml-stripblanks">shortcuts-dialog.ui</file>
|
<file preprocess="xml-stripblanks">shortcuts-dialog.ui</file>
|
||||||
|
<file preprocess="xml-stripblanks">preferences-dialog.ui</file>
|
||||||
<file preprocess="xml-stripblanks">icon-picker-dialog.ui</file>
|
<file preprocess="xml-stripblanks">icon-picker-dialog.ui</file>
|
||||||
<file preprocess="xml-stripblanks">widgets/header-row.ui</file>
|
<file preprocess="xml-stripblanks">widgets/header-row.ui</file>
|
||||||
<file preprocess="xml-stripblanks">widgets/history-item.ui</file>
|
<file preprocess="xml-stripblanks">widgets/history-item.ui</file>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user