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
32d5af04b6
commit
d50622700e
@ -144,16 +144,68 @@
|
|||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
||||||
<!-- AdwTabView as main content area -->
|
<!-- Vertical Paned: Tab View | History Panel -->
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwTabView" id="tab_view">
|
<object class="GtkPaned">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
<property name="vexpand">True</property>
|
<property name="vexpand">True</property>
|
||||||
</object>
|
<property name="position">600</property>
|
||||||
</child>
|
<property name="shrink-start-child">False</property>
|
||||||
<!-- Hidden history list for backward compatibility -->
|
<property name="shrink-end-child">True</property>
|
||||||
<child>
|
<property name="resize-start-child">True</property>
|
||||||
<object class="GtkListBox" id="history_listbox">
|
<property name="resize-end-child">True</property>
|
||||||
<property name="visible">False</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>
|
||||||
|
</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">
|
||||||
|
<style>
|
||||||
|
<class name="boxed-list"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
import gi
|
import gi
|
||||||
gi.require_version('GtkSource', '5')
|
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 .models import HttpRequest, HttpResponse
|
||||||
from .widgets.header_row import HeaderRow
|
from .widgets.header_row import HeaderRow
|
||||||
import json
|
import json
|
||||||
@ -392,8 +392,18 @@ class RequestTabWidget(Gtk.Box):
|
|||||||
return
|
return
|
||||||
|
|
||||||
current = self.get_request()
|
current = self.get_request()
|
||||||
|
was_modified = self.modified
|
||||||
self.modified = self._is_different_from_original(current)
|
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):
|
def _is_different_from_original(self, request):
|
||||||
"""Check if current request differs from original."""
|
"""Check if current request differs from original."""
|
||||||
if not self.original_request:
|
if not self.original_request:
|
||||||
|
|||||||
@ -80,6 +80,7 @@ class RosterWindow(Adw.ApplicationWindow):
|
|||||||
# Setup UI
|
# Setup UI
|
||||||
self._setup_tab_system()
|
self._setup_tab_system()
|
||||||
self._load_projects()
|
self._load_projects()
|
||||||
|
self._load_history()
|
||||||
|
|
||||||
# Connect to close-request to warn about unsaved changes
|
# Connect to close-request to warn about unsaved changes
|
||||||
self.connect("close-request", self._on_close_request)
|
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_tab[page] = tab
|
||||||
self.page_to_widget[page] = widget
|
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
|
# Select this new page
|
||||||
self.tab_view.set_selected_page(page)
|
self.tab_view.set_selected_page(page)
|
||||||
|
|
||||||
return tab.id
|
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):
|
def _switch_to_tab(self, tab_id):
|
||||||
"""Switch to a tab by its ID."""
|
"""Switch to a tab by its ID."""
|
||||||
# Find the page for this tab
|
# Find the page for this tab
|
||||||
@ -580,7 +591,18 @@ class RosterWindow(Adw.ApplicationWindow):
|
|||||||
@Gtk.Template.Callback()
|
@Gtk.Template.Callback()
|
||||||
def on_save_request_clicked(self, button):
|
def on_save_request_clicked(self, button):
|
||||||
"""Save current request to a project."""
|
"""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():
|
if not request.url.strip():
|
||||||
self._show_toast("Cannot save: URL is empty")
|
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"
|
# Check if current tab is an empty "New Request"
|
||||||
if self._is_empty_new_request_tab():
|
if self._is_empty_new_request_tab():
|
||||||
# Replace the empty tab with this request
|
# Replace the empty tab with this request
|
||||||
if self.current_tab_id:
|
page = self.tab_view.get_selected_page()
|
||||||
current_tab = self.tab_manager.get_tab_by_id(self.current_tab_id)
|
if page:
|
||||||
if current_tab:
|
widget = self.page_to_widget.get(page)
|
||||||
# Update the tab
|
current_tab = self.page_to_tab.get(page)
|
||||||
|
|
||||||
|
if widget and current_tab:
|
||||||
|
# Update the tab metadata
|
||||||
current_tab.name = tab_name
|
current_tab.name = tab_name
|
||||||
current_tab.request = req
|
current_tab.request = req
|
||||||
current_tab.saved_request_id = link_to_saved
|
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:
|
if is_copy:
|
||||||
# This is a copy - mark as unsaved
|
# This is a copy - mark as unsaved
|
||||||
current_tab.original_request = None
|
current_tab.original_request = None
|
||||||
current_tab.modified = True
|
widget.original_request = None
|
||||||
|
widget.modified = True
|
||||||
else:
|
else:
|
||||||
# This is linked to saved request
|
# This is linked to saved request
|
||||||
current_tab.original_request = HttpRequest(
|
original = HttpRequest(
|
||||||
method=req.method,
|
method=req.method,
|
||||||
url=req.url,
|
url=req.url,
|
||||||
headers=req.headers.copy(),
|
headers=req.headers.copy(),
|
||||||
body=req.body,
|
body=req.body,
|
||||||
syntax=req.syntax
|
syntax=req.syntax
|
||||||
)
|
)
|
||||||
current_tab.modified = False
|
current_tab.original_request = original
|
||||||
|
widget.original_request = original
|
||||||
# Load into UI
|
widget.modified = False
|
||||||
self._load_request_to_ui(req)
|
|
||||||
self._update_tab_bar_visibility()
|
|
||||||
else:
|
else:
|
||||||
# Current tab has changes or is not a "New Request"
|
# Current tab has changes or is not a "New Request"
|
||||||
# Create a new tab
|
# Create a new tab
|
||||||
@ -822,6 +852,14 @@ class RosterWindow(Adw.ApplicationWindow):
|
|||||||
new_tab.original_request = None
|
new_tab.original_request = None
|
||||||
new_tab.modified = True
|
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):
|
def _on_delete_request(self, widget, saved_request, project):
|
||||||
"""Delete saved request with confirmation."""
|
"""Delete saved request with confirmation."""
|
||||||
dialog = Adw.AlertDialog()
|
dialog = Adw.AlertDialog()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user