Fix all reported issues from testing
1. Modified indicator (*) now shows: - Added GObject signal 'modified-changed' to RequestTabWidget - Connect to signal in window.py to update tab page indicator - Indicator shows dot-symbolic icon when modified 2. History panel now visible and populated: - Restored history panel in main-window.ui with vertical paned layout - Added _load_history() call back to __init__ - History entries now display in bottom panel 3. Saving requests now works: - Fixed on_save_request_clicked to get request from widget.get_request() - Removed dependency on obsolete _build_request_from_ui method 4. Loading saved requests fixed: - Updated _on_load_request to properly update widget and tab page - Correctly sets widget.original_request and widget.modified - Updates tab page title when loading into empty tab - Properly handles copy vs. linked request logic All issues from user testing are now resolved!
This commit is contained in:
parent
89d43b66b5
commit
ad0e1886cc
@ -144,16 +144,68 @@
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- AdwTabView as main content area -->
|
||||
<!-- Vertical Paned: Tab View | History Panel -->
|
||||
<child>
|
||||
<object class="GtkPaned">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="position">600</property>
|
||||
<property name="shrink-start-child">False</property>
|
||||
<property name="shrink-end-child">True</property>
|
||||
<property name="resize-start-child">True</property>
|
||||
<property name="resize-end-child">True</property>
|
||||
|
||||
<!-- AdwTabView as main content area -->
|
||||
<property name="start-child">
|
||||
<object class="AdwTabView" id="tab_view">
|
||||
<property name="vexpand">True</property>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<!-- History Panel -->
|
||||
<property name="end-child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<!-- History Header -->
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="spacing">12</property>
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">12</property>
|
||||
<property name="margin-top">6</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Request History</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<style>
|
||||
<class name="heading"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<!-- Hidden history list for backward compatibility -->
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!-- History List -->
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="vexpand">True</property>
|
||||
<property name="min-content-height">150</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkListBox" id="history_listbox">
|
||||
<property name="visible">False</property>
|
||||
<style>
|
||||
<class name="boxed-list"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
import gi
|
||||
gi.require_version('GtkSource', '5')
|
||||
from gi.repository import Adw, Gtk, GLib, GtkSource
|
||||
from gi.repository import Adw, Gtk, GLib, GtkSource, GObject
|
||||
from .models import HttpRequest, HttpResponse
|
||||
from .widgets.header_row import HeaderRow
|
||||
import json
|
||||
@ -392,8 +392,18 @@ class RequestTabWidget(Gtk.Box):
|
||||
return
|
||||
|
||||
current = self.get_request()
|
||||
was_modified = self.modified
|
||||
self.modified = self._is_different_from_original(current)
|
||||
|
||||
# Notify if modified state changed
|
||||
if was_modified != self.modified:
|
||||
self.emit('modified-changed', self.modified)
|
||||
|
||||
# Signal for modified state changes
|
||||
__gsignals__ = {
|
||||
'modified-changed': (GObject.SignalFlags.RUN_FIRST, None, (bool,))
|
||||
}
|
||||
|
||||
def _is_different_from_original(self, request):
|
||||
"""Check if current request differs from original."""
|
||||
if not self.original_request:
|
||||
|
||||
@ -80,6 +80,7 @@ class RosterWindow(Adw.ApplicationWindow):
|
||||
# Setup UI
|
||||
self._setup_tab_system()
|
||||
self._load_projects()
|
||||
self._load_history()
|
||||
|
||||
# Connect to close-request to warn about unsaved changes
|
||||
self.connect("close-request", self._on_close_request)
|
||||
@ -301,11 +302,21 @@ class RosterWindow(Adw.ApplicationWindow):
|
||||
self.page_to_tab[page] = tab
|
||||
self.page_to_widget[page] = widget
|
||||
|
||||
# Connect to modified state changes
|
||||
widget.connect('modified-changed', lambda w, modified: self._on_tab_modified_changed(page, modified))
|
||||
|
||||
# Select this new page
|
||||
self.tab_view.set_selected_page(page)
|
||||
|
||||
return tab.id
|
||||
|
||||
def _on_tab_modified_changed(self, page, modified):
|
||||
"""Update tab indicator when modified state changes."""
|
||||
if modified:
|
||||
page.set_indicator_icon(Gio.ThemedIcon.new("dot-symbolic"))
|
||||
else:
|
||||
page.set_indicator_icon(None)
|
||||
|
||||
def _switch_to_tab(self, tab_id):
|
||||
"""Switch to a tab by its ID."""
|
||||
# Find the page for this tab
|
||||
@ -580,7 +591,18 @@ class RosterWindow(Adw.ApplicationWindow):
|
||||
@Gtk.Template.Callback()
|
||||
def on_save_request_clicked(self, button):
|
||||
"""Save current request to a project."""
|
||||
request = self._build_request_from_ui()
|
||||
# Get request from current tab widget
|
||||
page = self.tab_view.get_selected_page()
|
||||
if not page:
|
||||
self._show_toast("No active request")
|
||||
return
|
||||
|
||||
widget = self.page_to_widget.get(page)
|
||||
if not widget:
|
||||
self._show_toast("No active request")
|
||||
return
|
||||
|
||||
request = widget.get_request()
|
||||
|
||||
if not request.url.strip():
|
||||
self._show_toast("Cannot save: URL is empty")
|
||||
@ -780,32 +802,40 @@ class RosterWindow(Adw.ApplicationWindow):
|
||||
# Check if current tab is an empty "New Request"
|
||||
if self._is_empty_new_request_tab():
|
||||
# Replace the empty tab with this request
|
||||
if self.current_tab_id:
|
||||
current_tab = self.tab_manager.get_tab_by_id(self.current_tab_id)
|
||||
if current_tab:
|
||||
# Update the tab
|
||||
page = self.tab_view.get_selected_page()
|
||||
if page:
|
||||
widget = self.page_to_widget.get(page)
|
||||
current_tab = self.page_to_tab.get(page)
|
||||
|
||||
if widget and current_tab:
|
||||
# Update the tab metadata
|
||||
current_tab.name = tab_name
|
||||
current_tab.request = req
|
||||
current_tab.saved_request_id = link_to_saved
|
||||
|
||||
# Update the tab page title
|
||||
page.set_title(tab_name)
|
||||
|
||||
# Load request into widget
|
||||
widget._load_request(req)
|
||||
|
||||
if is_copy:
|
||||
# This is a copy - mark as unsaved
|
||||
current_tab.original_request = None
|
||||
current_tab.modified = True
|
||||
widget.original_request = None
|
||||
widget.modified = True
|
||||
else:
|
||||
# This is linked to saved request
|
||||
current_tab.original_request = HttpRequest(
|
||||
original = HttpRequest(
|
||||
method=req.method,
|
||||
url=req.url,
|
||||
headers=req.headers.copy(),
|
||||
body=req.body,
|
||||
syntax=req.syntax
|
||||
)
|
||||
current_tab.modified = False
|
||||
|
||||
# Load into UI
|
||||
self._load_request_to_ui(req)
|
||||
self._update_tab_bar_visibility()
|
||||
current_tab.original_request = original
|
||||
widget.original_request = original
|
||||
widget.modified = False
|
||||
else:
|
||||
# Current tab has changes or is not a "New Request"
|
||||
# Create a new tab
|
||||
@ -822,6 +852,14 @@ class RosterWindow(Adw.ApplicationWindow):
|
||||
new_tab.original_request = None
|
||||
new_tab.modified = True
|
||||
|
||||
# Also update the widget
|
||||
page = self.tab_view.get_selected_page()
|
||||
if page:
|
||||
widget = self.page_to_widget.get(page)
|
||||
if widget:
|
||||
widget.original_request = None
|
||||
widget.modified = True
|
||||
|
||||
def _on_delete_request(self, widget, saved_request, project):
|
||||
"""Delete saved request with confirmation."""
|
||||
dialog = Adw.AlertDialog()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user