Add history deletion features - clear all in preferences and delete individual items
This commit is contained in:
parent
2797a320c1
commit
c9e53de55d
@ -78,3 +78,18 @@ class HistoryManager:
|
|||||||
entries = entries[:100]
|
entries = entries[:100]
|
||||||
|
|
||||||
self.save_history(entries)
|
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([])
|
||||||
|
|||||||
@ -68,8 +68,10 @@ 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."""
|
||||||
preferences = PreferencesDialog()
|
window = self.props.active_window
|
||||||
preferences.set_transient_for(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()
|
preferences.present()
|
||||||
|
|
||||||
def on_shortcuts_action(self, widget, _):
|
def on_shortcuts_action(self, widget, _):
|
||||||
|
|||||||
@ -43,6 +43,30 @@
|
|||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title" translatable="yes">History</property>
|
||||||
|
<property name="description" translatable="yes">Manage request history</property>
|
||||||
|
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="title" translatable="yes">Clear All History</property>
|
||||||
|
<property name="subtitle" translatable="yes">Remove all saved request and response history</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="clear_history_button">
|
||||||
|
<property name="label" translatable="yes">Clear</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<signal name="clicked" handler="on_clear_history_clicked" swapped="no"/>
|
||||||
|
<style>
|
||||||
|
<class name="destructive-action"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
#
|
#
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# 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')
|
@Gtk.Template(resource_path='/cz/vesp/roster/preferences-dialog.ui')
|
||||||
@ -26,10 +26,17 @@ class PreferencesDialog(Adw.PreferencesWindow):
|
|||||||
|
|
||||||
tls_verification_row = Gtk.Template.Child()
|
tls_verification_row = Gtk.Template.Child()
|
||||||
timeout_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)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
self.history_manager = history_manager
|
||||||
|
|
||||||
# Get settings
|
# Get settings
|
||||||
self.settings = Gio.Settings.new('cz.vesp.roster')
|
self.settings = Gio.Settings.new('cz.vesp.roster')
|
||||||
|
|
||||||
@ -47,3 +54,30 @@ class PreferencesDialog(Adw.PreferencesWindow):
|
|||||||
'value',
|
'value',
|
||||||
Gio.SettingsBindFlags.DEFAULT
|
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)
|
||||||
|
|||||||
@ -62,6 +62,20 @@
|
|||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
||||||
|
<!-- Delete Button -->
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="delete_button">
|
||||||
|
<property name="icon-name">user-trash-symbolic</property>
|
||||||
|
<property name="tooltip-text">Delete this history item</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<signal name="clicked" handler="on_delete_clicked" swapped="no"/>
|
||||||
|
<style>
|
||||||
|
<class name="flat"/>
|
||||||
|
<class name="circular"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
<!-- Click gesture for toggling expansion (only on summary) -->
|
<!-- Click gesture for toggling expansion (only on summary) -->
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkGestureClick" id="click_gesture">
|
<object class="GtkGestureClick" id="click_gesture">
|
||||||
|
|||||||
@ -33,6 +33,7 @@ class HistoryItem(Gtk.Box):
|
|||||||
url_label = Gtk.Template.Child()
|
url_label = Gtk.Template.Child()
|
||||||
timestamp_label = Gtk.Template.Child()
|
timestamp_label = Gtk.Template.Child()
|
||||||
status_label = Gtk.Template.Child()
|
status_label = Gtk.Template.Child()
|
||||||
|
delete_button = Gtk.Template.Child()
|
||||||
request_headers_label = Gtk.Template.Child()
|
request_headers_label = Gtk.Template.Child()
|
||||||
request_body_scroll = Gtk.Template.Child()
|
request_body_scroll = Gtk.Template.Child()
|
||||||
request_body_text = Gtk.Template.Child()
|
request_body_text = Gtk.Template.Child()
|
||||||
@ -48,7 +49,8 @@ class HistoryItem(Gtk.Box):
|
|||||||
load_button = Gtk.Template.Child()
|
load_button = Gtk.Template.Child()
|
||||||
|
|
||||||
__gsignals__ = {
|
__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):
|
def __init__(self, entry):
|
||||||
@ -140,6 +142,11 @@ class HistoryItem(Gtk.Box):
|
|||||||
"""Emit load signal when load button clicked."""
|
"""Emit load signal when load button clicked."""
|
||||||
self.emit('load-requested')
|
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()
|
@Gtk.Template.Callback()
|
||||||
def on_request_expander_clicked(self, gesture, n_press, x, y):
|
def on_request_expander_clicked(self, gesture, n_press, x, y):
|
||||||
"""Toggle request body expansion."""
|
"""Toggle request body expansion."""
|
||||||
|
|||||||
@ -437,6 +437,7 @@ class RosterWindow(Adw.ApplicationWindow):
|
|||||||
for entry in entries:
|
for entry in entries:
|
||||||
item = HistoryItem(entry)
|
item = HistoryItem(entry)
|
||||||
item.connect('load-requested', self._on_history_load_requested, 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)
|
self.history_listbox.append(item)
|
||||||
|
|
||||||
def _on_history_load_requested(self, widget, entry):
|
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
|
# Smart loading: replaces empty tabs or creates new tab if modified
|
||||||
self._load_request_from_entry(entry)
|
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):
|
def _load_request_from_entry(self, entry):
|
||||||
"""Load request from history entry - smart loading based on current tab state."""
|
"""Load request from history entry - smart loading based on current tab state."""
|
||||||
request = entry.request
|
request = entry.request
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user