diff --git a/src/history_manager.py b/src/history_manager.py
index b527854..b9b39ee 100644
--- a/src/history_manager.py
+++ b/src/history_manager.py
@@ -78,3 +78,18 @@ class HistoryManager:
entries = entries[:100]
self.save_history(entries)
+
+ def delete_entry(self, entry: HistoryEntry):
+ """Delete a specific entry from history."""
+ entries = self.load_history()
+ # Filter out the entry by comparing timestamps and URLs
+ entries = [e for e in entries if not (
+ e.timestamp == entry.timestamp and
+ e.request.url == entry.request.url and
+ e.request.method == entry.request.method
+ )]
+ self.save_history(entries)
+
+ def clear_history(self):
+ """Clear all history entries."""
+ self.save_history([])
diff --git a/src/main.py b/src/main.py
index 98e4a04..f846adc 100644
--- a/src/main.py
+++ b/src/main.py
@@ -68,8 +68,10 @@ class RosterApplication(Adw.Application):
def on_preferences_action(self, widget, _):
"""Callback for the app.preferences action."""
- preferences = PreferencesDialog()
- preferences.set_transient_for(self.props.active_window)
+ window = self.props.active_window
+ preferences = PreferencesDialog(history_manager=window.history_manager)
+ preferences.set_transient_for(window)
+ preferences.connect('history-cleared', lambda d: window._load_history())
preferences.present()
def on_shortcuts_action(self, widget, _):
diff --git a/src/preferences-dialog.ui b/src/preferences-dialog.ui
index 9c175be..578bf37 100644
--- a/src/preferences-dialog.ui
+++ b/src/preferences-dialog.ui
@@ -43,6 +43,30 @@
+
+
+
+
diff --git a/src/preferences_dialog.py b/src/preferences_dialog.py
index 6f97848..5be345b 100644
--- a/src/preferences_dialog.py
+++ b/src/preferences_dialog.py
@@ -17,7 +17,7 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-from gi.repository import Adw, Gtk, Gio
+from gi.repository import Adw, Gtk, Gio, GObject
@Gtk.Template(resource_path='/cz/vesp/roster/preferences-dialog.ui')
@@ -26,10 +26,17 @@ class PreferencesDialog(Adw.PreferencesWindow):
tls_verification_row = Gtk.Template.Child()
timeout_row = Gtk.Template.Child()
+ clear_history_button = Gtk.Template.Child()
- def __init__(self, **kwargs):
+ __gsignals__ = {
+ 'history-cleared': (GObject.SIGNAL_RUN_FIRST, None, ())
+ }
+
+ def __init__(self, history_manager=None, **kwargs):
super().__init__(**kwargs)
+ self.history_manager = history_manager
+
# Get settings
self.settings = Gio.Settings.new('cz.vesp.roster')
@@ -47,3 +54,30 @@ class PreferencesDialog(Adw.PreferencesWindow):
'value',
Gio.SettingsBindFlags.DEFAULT
)
+
+ @Gtk.Template.Callback()
+ def on_clear_history_clicked(self, button):
+ """Clear all history after confirmation."""
+ if not self.history_manager:
+ return
+
+ # Create confirmation dialog
+ dialog = Adw.AlertDialog.new(
+ "Clear All History?",
+ "This will permanently delete all saved request and response history. This action cannot be undone."
+ )
+ dialog.add_response("cancel", "Cancel")
+ dialog.add_response("clear", "Clear History")
+ dialog.set_response_appearance("clear", Adw.ResponseAppearance.DESTRUCTIVE)
+ dialog.set_default_response("cancel")
+ dialog.set_close_response("cancel")
+
+ def on_response(dialog, response):
+ if response == "clear":
+ # Clear the history
+ self.history_manager.clear_history()
+ # Notify the main window to refresh
+ self.emit('history-cleared')
+
+ dialog.connect("response", on_response)
+ dialog.present(self)
diff --git a/src/widgets/history-item.ui b/src/widgets/history-item.ui
index d63ef26..de60bd2 100644
--- a/src/widgets/history-item.ui
+++ b/src/widgets/history-item.ui
@@ -62,6 +62,20 @@
+
+
+
+ user-trash-symbolic
+ Delete this history item
+ center
+
+
+
+
+
diff --git a/src/widgets/history_item.py b/src/widgets/history_item.py
index 70158bf..5e2db0d 100644
--- a/src/widgets/history_item.py
+++ b/src/widgets/history_item.py
@@ -33,6 +33,7 @@ class HistoryItem(Gtk.Box):
url_label = Gtk.Template.Child()
timestamp_label = Gtk.Template.Child()
status_label = Gtk.Template.Child()
+ delete_button = Gtk.Template.Child()
request_headers_label = Gtk.Template.Child()
request_body_scroll = Gtk.Template.Child()
request_body_text = Gtk.Template.Child()
@@ -48,7 +49,8 @@ class HistoryItem(Gtk.Box):
load_button = Gtk.Template.Child()
__gsignals__ = {
- 'load-requested': (GObject.SIGNAL_RUN_FIRST, None, ())
+ 'load-requested': (GObject.SIGNAL_RUN_FIRST, None, ()),
+ 'delete-requested': (GObject.SIGNAL_RUN_FIRST, None, ())
}
def __init__(self, entry):
@@ -140,6 +142,11 @@ class HistoryItem(Gtk.Box):
"""Emit load signal when load button clicked."""
self.emit('load-requested')
+ @Gtk.Template.Callback()
+ def on_delete_clicked(self, button):
+ """Emit delete signal when delete button clicked."""
+ self.emit('delete-requested')
+
@Gtk.Template.Callback()
def on_request_expander_clicked(self, gesture, n_press, x, y):
"""Toggle request body expansion."""
diff --git a/src/window.py b/src/window.py
index c0ea580..4e29851 100644
--- a/src/window.py
+++ b/src/window.py
@@ -437,6 +437,7 @@ class RosterWindow(Adw.ApplicationWindow):
for entry in entries:
item = HistoryItem(entry)
item.connect('load-requested', self._on_history_load_requested, entry)
+ item.connect('delete-requested', self._on_history_delete_requested, entry)
self.history_listbox.append(item)
def _on_history_load_requested(self, widget, entry):
@@ -444,6 +445,13 @@ class RosterWindow(Adw.ApplicationWindow):
# Smart loading: replaces empty tabs or creates new tab if modified
self._load_request_from_entry(entry)
+ def _on_history_delete_requested(self, widget, entry):
+ """Handle delete request from history item."""
+ # Delete the entry from history
+ self.history_manager.delete_entry(entry)
+ # Refresh the history panel
+ self._load_history()
+
def _load_request_from_entry(self, entry):
"""Load request from history entry - smart loading based on current tab state."""
request = entry.request