Port to GTK4#260
Open
jmallach wants to merge 104 commits into
Open
Conversation
Switch CMakeLists.txt from the dual GTK_TARGET=2/3 build to a single gtk4 target. Add src/gtk4-compat.h, a thin compatibility header that stubs out the removed GTK2/3 widgets (GtkCList, GtkCTree, GtkHBox, GtkVBox, GtkTable, GtkAlignment, GtkItemFactory, etc.) so the rest of the codebase can be ported incrementally without the whole tree breaking at once. Update the UI file (src/xqf.ui, replaces xqf-gtk2.ui/xqf-gtk3.ui), dialogs (event-key → GtkEventControllerKey, gtk_dialog_run → nested GMainLoop), pixmap loading (drop direct GdkWindow access), and miscellaneous deprecated-API call sites throughout src/. Add docs/gtk4-migration-plan.md describing the full migration roadmap and tools/docker/ with a build container for reproducible GTK 4 builds. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Add GObject wrapper types XqfServerItem and XqfPlayerItem
(src/xqf-{server,player}-item.{c,h}) to wrap struct server * and
struct player * as GListStore items. XqfPlayerItem also holds a
server_ref on the owning server to keep the player list alive.
Add src/xqf-lists.{c,h} which creates the GtkColumnView + GListStore
+ GtkSortListModel + GtkMultiSelection/GtkSingleSelection stack for
both the server and player panels. Per-column GtkCustomSorters
delegate to the existing compare_servers()/compare_players() logic.
Initial sort is set via gtk_column_view_sort_by_column() (GTK 4.10+):
Ping/ascending for servers, Frags/descending for players.
Rewrite src/srv-list.c to drive GListStore instead of GtkCList rows.
Key mechanisms:
- server_store_rebind(): splice a fresh XqfServerItem in place to
force GtkColumnView to rebind the factory for updated rows.
- server_list_sync_selection(): read GtkBitset from GtkMultiSelection
to update cur_server.
- server_list_build_filtered(): save/restore selection around a full
store rebuild using server_store_find() on the sort model.
Update src/xqf.c to call create_server_column_view() /
create_player_column_view() instead of create_cwidget(), and switch
all selection/row queries to the new GListStore-based helpers.
Rename legacy GtkCList-era identifiers throughout:
- Global widgets: server_clist → server_view, player_clist → player_view
- All server_clist_* functions → server_list_*
- All player_clist_* functions → player_list_*
- struct clist_def → struct list_def, struct clist_column → struct list_column
- enum cwidget_type/CWIDGET_CLIST/CWIDGET_CTREE → enum cview_type/CVIEW_LIST/CVIEW_TREE
- Callback/compare functions renamed to drop the clist infix
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The server-info panel was the last remaining GtkCTree consumer. Replace it with a plain GtkTreeView backed by a GtkTreeStore with three columns: RULE (string), VALUE (string), INFO_PTR (pointer to the info[] pair used for sorting top-level rows). - srvinf_treeview_new(): creates store + treeview, sets custom sort funcs so child flag-rows stay in insertion order while top-level rows are sorted by compare_srvinfo(). - srvinf_treeview_set_server(): populates the store; show_extended_flags and show_split_value now take GtkTreeIter* instead of GtkCTreeNode*. - srvinf_copy_selected_values(): replaces the gtk_ctree_node_get_text loop; reads VALUE column from GtkTreeSelection. - Drop create_ctree_widget(), list_sort_column(), column_header_set_title(), srvinf_list_def, srvinf_columns[], srvinf_list_compare_func(), and server_info_event_cb() — all now dead code. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The sources panel (left pane, game groups → masters) was the last remaining GtkCTree consumer. Replace it with a GtkTreeView backed by a three-column GtkTreeStore: MASTER (G_TYPE_POINTER), PIXBUF (GDK_TYPE_PIXBUF), NAME (G_TYPE_STRING). Key changes: - source_store (GtkTreeStore) + source_find_master() helper replace gtk_ctree_find_by_row_data() throughout. - source_treeview_enable_master_group() uses gtk_tree_store_insert_before() to preserve the correct game-type order. - source_treeview_add_master() expands the parent after inserting the child so new masters are immediately visible. - fill_source_treeview() restores expand/collapse state from config after building the tree. - ui_done() saves collapse state via gtk_tree_view_row_expanded(). - source_selection_changed() reads GtkTreeSelection instead of iterating the old GtkCList selection list. - Selection signal: GtkTreeSelection::changed replaces the GtkCTree tree_select_row / tree_unselect_row pair. - source_treeview_has_master() replaces the gtk_ctree_find_by_row_data existence check in source.c::refresh_source_list(). - All functions renamed source_ctree_* → source_treeview_* to match the new widget type. - source_ctree_event_callback stub removed (was no-op). Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- callbacks.c: use GListModel API (server_store) for server count and cur_server for selection test instead of always-NULL gtk_clist compat stubs - xqf-ui.c: save_view_geometry uses gtk_column_view_column_get_fixed_width instead of gtk_clist_get_column_width (which returned 0) - xqf.c: remove no-op gtk_clist_freeze/sort/thaw around server refresh; GtkSortListModel sorts automatically - psearch.c: rewrite psearch_next_player/find_player using GListModel API (player_selection, server_selection, XqfPlayerItem, XqfServerItem) - skin.c: replace gtk_clist_get_row_height stub (always 18) with literal 16 Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- pref.c: arguments_list (custom game args) migrated to GtkListStore with 2 text columns; cursor-changed replaces select_row - flt-player.c: pattern_list migrated to GtkListStore with 3 pixbuf columns (group icons) + mode text + pattern text; GtkGestureClick for group toggle; row swap via data exchange instead of clist_swap_rows - filter.c: country_filter_list, country_left_list, country_right_list all migrated to GtkListStore (id/pixbuf/name columns); GtkTreeSelection changed signal replaces select_row/unselect_row; gtk_clist_get_row_data country ID storage replaced by proper COUNTRY_COL_ID column reads - xqf.c: remove dead server_list_compare_func and player_list_compare_func All GtkCList/GtkCTree usage outside gtk4-compat.h is now eliminated. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Bulk replace all gtk_vbox_new(homogeneous, spacing) and gtk_hbox_new(homogeneous, spacing) calls with the GTK4 form gtk_box_new(GTK_ORIENTATION_VERTICAL/HORIZONTAL, spacing) across all source files (152 occurrences). The homogeneous flag is dropped as none of the callers used TRUE. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all gtk_table_new/gtk_table_set_*_spacing/gtk_table_attach* with the GTK4 equivalents: gtk_grid_new, gtk_grid_set_row/column_spacing, and gtk_grid_attach. Per-column/row spacing overrides are dropped (no GtkGrid equivalent); the visual difference is negligible. Local variable names are updated from "table" to "grid" throughout. Also replace gtk_misc_set_alignment on labels with gtk_label_set_xalign. Files changed: addmaster.c, flt-player.c, filter.c, pref.c, srv-prop.c, statistics.c. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The type_hint property was removed from GtkWindow in GTK4 and causes a fatal error when GtkBuilder loads the UI file. Remove it from GtkAboutDialog and the preferences dialog. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Both objects used internal-child="vbox" and internal-child="action_area" which were removed in GTK4. Neither object is referenced by the code via gtk_builder_get_object() — about_dialog() uses gtk_show_about_dialog() directly and preferences are built entirely in pref.c. Remove both dead objects to fix the fatal GtkBuilder load error. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Tasks complete: - 1: GtkCList → GtkColumnView (xqf-lists.c, 415 lines, full impl) - 5: gdk_window decorations removed (no remaining calls) - 6: #ifdef GUI_GTK2/3 blocks removed (none in source) - 8: CMakeLists.txt GTK4-only (single gtk4 target) Only task 10 (gtk_dialog_run → async) remains in Phase 1.
set_widgets_sensitivity() now calls set_action_enabled() which toggles GSimpleAction enabled state instead of manipulating removed GtkMenuItem widgets. pref.c updates show-hostnames/show-default-port via the action group state rather than gtk_check_menu_item_set_active(). Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
srv-info.c replaces GtkCTree stubs with a real GtkTreeView+GtkTreeStore implementation for the server rules/cvars panel. xqf-ui.c/h updated for GTK4 widget API (gtk_widget_show → gtk_widget_set_visible, etc.). Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
xqf.ui rewritten for GTK4: GtkBox layout replaces deprecated containers, GtkPopoverMenuBar + GMenuModel replaces removed GtkMenuBar/GtkMenu, paned/scroll structure updated to GTK4 child-setter API. Old xqf-gtk2.ui and xqf-gtk3.ui deleted — xqf.ui is now the sole UI file. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
GtkWindow does not implement GActionMap in GTK4; replace with a GSimpleActionGroup inserted via gtk_widget_insert_action_group(). Add win_action_group() for cross-TU access. Replace gtk_main() app loop with an explicit GMainLoop. Fix main window close-request: use dedicated main_window_close_cb returning FALSE so GTK4 proceeds with normal window destruction and the process exits cleanly. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…MainLoop gtk_main()/gtk_main_quit() were removed in GTK4. All 10 dialog call sites now use dialog_run_modal(window) — a nested GMainLoop that auto-quits when the window is destroyed. utils.c external-program loop gets its own GMainLoop via a new loop field on the connection struct, removing the do_quit/gtk_main_quit pattern. gtk_main/gtk_main_quit removed from gtk4-compat.h. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
All 11 Phase 1 tasks marked done. Task 10 note clarifies that no gtk_dialog_run() calls existed; the real work was replacing gtk_main() compat shims with dialog_run_modal() and an explicit app GMainLoop. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire up the gestures and controllers that GtkCList provided for free: - Double-click server row → connect (GtkGestureClick, button 1) - Enter/KP_Enter → connect; Space → refresh selected (GtkEventControllerKey) - Right-click server list → GtkPopoverMenu with Connect, Observe, Record Demo, Refresh Selected, Properties, Add to Favorites, DNS Lookup, RCON - Right-click player list → GtkPopoverMenu with Add to Red/Green/Blue filter All menu items resolve to existing "win.*" actions in the GSimpleActionGroup. Removed the dead player_view_event_cb stub that predated GtkColumnView. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove g_object_set_property("tab-hborder") from pref.c, statistics.c,
filter.c: property was removed in GTK4; each dialog with a GtkNotebook
was emitting a GTK-CRITICAL on open
- Fix combo_get_entry() in srv-prop.c: use gtk_combo_box_get_child()
instead of gtk_bin_get_child()/gtk_widget_get_first_child(), which
returned the internal GtkBox rather than the entry in GTK4 — this was
silently dropping typed text in Add Server / Add Master dialogs
- Move expand-row logic out of fill_source_treeview() into
source_treeview_restore_expand_state(), called after source_treeview
global is set; previously all game groups were left collapsed at startup
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Document the Docker-based build workflow (xqf-dev image, cmake --build + cmake --install, WITH_QSTAT=quakestat already in CMakeCache). Also add a note on the one-commit-per-fix discipline for easier review. Includes a "Current Known Bugs" section capturing the two known startup issues as of 2026-05-11 (18× GDK_TYPE_PIXBUF CRITICALs, Favorites-only source pane) — to be updated once fixes are verified and committed. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
GtkCellRendererPixbuf's "pixbuf" property causes type-compatibility CRITICALs on GTK 4.22 because the model column type (GDK_TYPE_PIXBUF) no longer matches what the property binding expects. Switch all GtkTreeStore/GtkListStore pixbuf columns to GDK_TYPE_TEXTURE, bind them with the "texture" attribute, and add GdkTexture* to struct pixmap (created from the GdkPixbuf via gdk_texture_new_for_pixbuf). Affects: pixmaps.h, loadpixmap.c, pixmaps.c, xqf-ui.c/h, pref.c, filter.c, flt-player.c. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
gtk_column_view_column_new() takes (transfer full) for its factory argument — it calls g_clear_object(&factory) internally. Our subsequent g_object_unref(factory) freed it a second time, leaving every column with a dangling factory pointer. This caused 18x startup CRITICALs in gtk_column_view_cell_widget_new when items were first added to the server list (g_value_type_compatible src_type=0, invalid object type). Drop the redundant g_object_unref(factory) in both server and player column setup loops. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the 18× CRITICAL bug entry; both root causes are now fixed: - GtkCellRendererPixbuf "texture"/GDK_TYPE_TEXTURE (commit d529ab8) - GtkListItemFactory double-unref in column view setup (commit 9c1c2fa) Update "Current Known Bugs" date to 2026-05-17. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
All APIs XQF uses are available since GTK 4.0 (no Since: annotations on any of them). Set the pkg_check_modules floor to 4.0 so distributors targeting older GTK4 stacks can try it without an artificial barrier. Add a "Deprecated API in active use" section to the migration plan listing GtkCellRenderer*/GtkTreeView (deprecated 4.10) and gdk_texture_new_for_pixbuf (deprecated 4.20), along with which source files are affected and how each resolves as migration progresses. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
GtkCheckButton no longer inherits from GtkToggleButton in GTK4, and
GtkRadioButton is entirely removed. Replace all affected call sites:
- gtk_toggle_button_{get,set}_active → gtk_check_button_{get,set}_active
- GTK_TOGGLE_BUTTON(x) → GTK_CHECK_BUTTON(x) (for GtkCheckButton widgets)
- gtk_radio_button_new_with_label / gtk_radio_button_get_group →
gtk_check_button_new_with_label + gtk_check_button_set_group
- CMakeLists.txt: fix pkg_check_modules version syntax (gtk4>=4.0)
Files changed: addmaster.c, dialogs.c, filter.c, flt-player.c, pref.c,
psearch.c, scripts.c, srv-prop.c, CMakeLists.txt.
xqf.c filter_buttons[] are genuine GtkToggleButton and are left unchanged.
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
GtkCheckButton in GTK4 no longer inherits from GtkButton and does not emit 'clicked'. Use 'toggled' for the radio-style mode buttons in the player filter pattern editor. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The "None" filter skip (0→1) was unconditional, so opening the filter dialog with an empty filter list triggered debug(0) "invalid filter nr 1" on every open. Guard the bump with server_filters->len > 0 so it only fires when at least one filter actually exists. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Three issues in pref.c:
- gtk_widget_set_size_request(..., -2): invalid height; change to -1
- g_signal_connect("focus_out_event"): removed in GTK4; replace with
GtkEventControllerFocus + "leave" signal (g_signal_connect_swapped so
dir_entry_activate_callback receives the GtkEntry as its widget arg)
- g_signal_connect("event") on color buttons: the callback was already
a no-op stub; remove the four dead connections
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
When the prefs dialog is destroyed, GtkTreeView emits cursor-changed / selection-changed while its GtkTreeSelection is already being finalized, causing 60+ CRITICALs of the form: gtk_tree_selection_get_selected: assertion 'GTK_IS_TREE_SELECTION' failed Fix: - custom_args_list_select_row_callback: return early if the tree view is in destruction (gtk_widget_in_destruction) - game_selection_changed_callback: guard with GTK_IS_TREE_SELECTION check since the selection pointer passed by GTK may be stale during teardown Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
gtk_widget_in_destruction only checks the specific widget, not ancestors, so the previous guard in custom_args_list_select_row_callback was ineffective. Replace all teardown guards with GTK_IS_TREE_SELECTION() checks, which correctly detect a finalized selection regardless of which widget triggered the destruction chain. Fixed callbacks: - pref.c: custom_args_list_select_row_callback (cursor-changed on per-game tree) - scripts.c: script_selection_changed_callback (changed on scripts tree) - flt-player.c: pattern_list_selection_changed (changed on pattern list) Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove gtk4-compat.h shim calls from the five small dialog files (addmaster, addserver, redial, psearch, statistics): - gtk_box_pack_start/end → gtk_box_append - gtk_entry_get/set_text → gtk_editable_get/set_text - gtk_hseparator_new → gtk_separator_new(HORIZONTAL) - gtk_hbutton_box_new + gtk_button_box_set_layout → gtk_box_new - gtk_widget_destroy(window) → gtk_window_destroy - gtk_widget_set_can_default / gtk_widget_grab_default → removed - gtk_misc_set_alignment → gtk_label_set_xalign (statistics.c) Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove gtk4-compat.h shim calls from dialogs, rcon, srv-prop and game: - gtk_box_pack_start/end → gtk_box_append - gtk_entry_get/set_text → gtk_editable_get/set_text - gtk_hseparator_new → gtk_separator_new(HORIZONTAL) - gtk_frame_set_shadow_type → removed - gtk_widget_destroy(window) → gtk_window_destroy - gtk_widget_set_can_default / gtk_widget_grab_default → removed Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- gtk_box_pack_start/end → gtk_box_append - gtk_entry_get/set_text → gtk_editable_get/set_text - gtk_widget_destroy(window) → gtk_window_destroy - gtk_frame_set_shadow_type → removed - gtk_scrolled_window_add_with_viewport → gtk_scrolled_window_set_child Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all deprecated shim calls with native GTK4 API: gtk_box_pack_start/end → gtk_box_append, gtk_entry_get/set_text → gtk_editable_get/set_text (both GTK_ENTRY and combo_get_entry variants), gtk_widget_destroy → gtk_window_destroy, gtk_frame_set_shadow_type / gtk_widget_set_can_default / gtk_widget_grab_default → removed, gtk_misc_set_alignment → gtk_label_set_xalign, gtk_scrolled_window_add_with_viewport → gtk_scrolled_window_set_child. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all deprecated shim calls with native GTK4 API: gtk_box_pack_start/end → gtk_box_append, gtk_entry_set_text → gtk_editable_set_text, gtk_hbutton_box_new/gtk_vbutton_box_new → gtk_box_new, gtk_button_box_set_layout / gtk_frame_set_shadow_type / gtk_widget_set_can_default / gtk_widget_grab_default → removed, gtk_scrolled_window_add_with_viewport → gtk_scrolled_window_set_child, gtk_widget_destroy → gtk_window_destroy in signal connects. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix remaining shim calls missed in earlier batches: - addmaster.c: gtk_entry_set_text(combo_get_entry) → gtk_editable_set_text - srv-prop.c: one gtk_box_pack_start → gtk_box_append - xqf.c: gtk_widget_destroy (×3) → gtk_window_destroy, gtk_entry_get_text → gtk_editable_get_text Remove now-unused shim definitions from gtk4-compat.h: gtk_box_pack_start/end, gtk_widget_destroy, gtk_widget_set_can_default, gtk_widget_grab_default, gtk_widget_show_all, gtk_entry_get/set_text, gtk_hseparator_new, gtk_misc_set_alignment, GTK_SHADOW_* enums, gtk_frame_set_shadow_type, gtk_scrolled_window_add_with_viewport, GtkButtonBox/gtk_button_box_set_layout/gtk_vbutton_box_new/gtk_hbutton_box_new. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all surviving shim call sites with native GTK4 API: - gtk_scrolled_window_new(NULL,NULL) → gtk_scrolled_window_new() (12 sites) - gtk_window_new(GTK_WINDOW_TOPLEVEL) → gtk_window_new() in redial.c - gtk_paned_get_child1 → gtk_paned_get_start_child in xqf-ui.c (3 sites) - GTK_SELECTION_EXTENDED → GTK_SELECTION_MULTIPLE in xqf-ui.c (2 sites) - gtk_text_view_get_vadjustment → gtk_scrollable_get_vadjustment in rcon.c (2 sites) - gtk_misc_set_padding/GTK_BIN/gtk_bin_get_child in pref.c → inline margin calls Remove now-unused shims from gtk4-compat.h: gtk_box_pack_start/end (already done), gtk_scrolled_window_new(h,v), gtk_window_new(type), gtk_paned_get_child1/2, GTK_SELECTION_EXTENDED, gtk_init(argc,argv). Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove all shim definitions whose call sites have been inlined: GtkContainer/gtk_container_add, GTK_MISC, gtk_misc_set_padding, GtkBin/GTK_BIN/gtk_bin_get_child, gtk_text_view_get_vadjustment/hadjustment, GdkEventButton, GTK_SELECTION_EXTENDED, gtk_paned_get_child1/2, gtk_window_new(type), gtk_scrolled_window_new(h,v), gtk_init(argc,argv). Also remove two dead never-connected signal handler stubs in filter.c (country_mouse_click_left/right_list) that were the only GdkEventButton users. gtk4-compat.h now contains only gtk_file_chooser_get/set_filename helpers, which wrap the deprecated-but-functional gtk_file_chooser_get/set_file — tied to GtkFileChooserDialog which itself needs replacement in a later pass. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace GtkTreeStore + GtkTreeView (used as a flat single-column list) with GtkStringList + GtkSingleSelection + GtkListView using a GtkSignalListItemFactory. The script index now maps directly to the list position, eliminating the SCRIPTSLIST_ATTR_INDEX column. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace GtkTreeStore + GtkTreeView (used as flat icon+text list) with GListStore<GObject> + GtkSingleSelection + GtkListView. Game type now maps directly to list position, eliminating GAMESLIST_ATTR_* columns and the genprefs[].tree_path field. Selection model uses notify::selected instead of GtkTreeSelection::changed. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ColumnView Replace GtkListStore + GtkTreeView (2-column game/args list) with GListStore<GObject> + GtkSingleSelection + GtkColumnView. Each list item stores "game" and "args" strings via g_object_set_data_full. Callbacks updated to use GListStore API (g_list_store_append/remove) instead of GtkListStore API. Selection uses notify::selected signal instead of cursor-changed. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…istView Replace three GtkListStore + GtkTreeView country list widgets (filter display, popup left/right selection lists) with GListStore<GObject> + GtkListView backed by GtkNoSelection/GtkSingleSelection. Items store code/texture/name via g_object_set_data_full. All list manipulation (append, clear, remove by position) uses GListStore API. Selection callbacks use notify::selected instead of GtkTreeSelection::changed. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…mnView Replace GtkListStore+GtkTreeView with GListStore+GtkColumnView+GtkSingleSelection for the player filter pattern list. - make_pattern_item() creates GObject items with grp0/1/2 (GdkTexture*), mode, and pattern string data - pattern_list_update_row() uses g_list_store_splice() to replace items - pattern_list_insert_row() uses g_list_store_insert/append() - Group icon columns use per-cell GtkGestureClick; on_grp_cell_click() reads gtk_list_item_get_position() to call pattern_set_groups() - Selection via GtkSingleSelection notify::selected signal - Move up/down uses gtk_column_view_scroll_to() + set_selected() - Remove PLT_COL_* enum, show_pattern_error() (dead code), aligned_image() Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 5 (deprecated tree widgets) is complete for all list-style widgets: filter.c, flt-player.c, scripts.c, pref.c all migrated to GListStore + GtkColumnView/GtkListView. srv-info.c and xqf-ui.c intentionally kept as GtkTreeView (genuine hierarchical trees). Phase 6 (compat shims) is complete except gtk_file_chooser_get/set_filename which requires a separate GtkFileDialog migration pass. gtk4-compat.h is now 44 lines. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
scroll_to was added in GTK 4.12; guard it so the build works on 4.10/4.11. Selection still works on older versions, item may just not scroll into view. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The 4.10 floor was set in anticipation of GtkFileDialog (still pending). Current code builds on 4.0+; the one 4.12 API (gtk_column_view_scroll_to) is already guarded with GTK_CHECK_VERSION. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Already implemented: gtk_application_new("io.github.xqf"), xqf_activate,
g_application_run, gtk_application_add_window.
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Rewrites src/config.c (~860 lines) to use GLib GKeyFile throughout while preserving the identical public API from config.h. The custom hand-rolled INI parser is removed entirely. Key changes: - Single GKeyFile *main_kf replaces the old per-section hash table - Script metadata loaded via GKeyFile after stripping the "# " prefix from the ### BEGIN/END XQF INFO block - config_sync() uses g_key_file_save_to_file() (atomic write) - Iterator structs hold a strv + index instead of custom linked-list state - Internal path-parsing function renamed cfg_parse_path() to avoid the name collision with resolve_path() declared in utils.h Existing config files are format-compatible: GKeyFile accepts keys containing '/' and spaces, and uses the same \n/\r/\\ escaping as the old parser. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…tk4-compat.h
Migrate all file-open dialogs to GtkFileDialog (GTK ≥ 4.10) with a
GtkFileChooserDialog fallback for GTK < 4.10, wrapped in
G_GNUC_{BEGIN,END}_IGNORE_DEPRECATIONS.
Changes:
- New file_dialog_cb_t typedef: (const char *path, gpointer data)
- file_dialog() and file_dialog_textentry() changed from GtkWidget*-
returning (response-callback style) to void, taking file_dialog_cb_t
- All four response callbacks converted to the new signature
(dialogs.c, pref.c ×2, scripts.c)
- sound_file_btn_clicked() in pref.c migrated to GtkFileDialog with
GTK_CHECK_VERSION(4, 10, 0) guard; fallback uses GtkFileChooserDialog
with native gtk_file_chooser_get_file() instead of the removed _get_filename()
- gtk4-compat.h deleted (provided gtk_file_chooser_get/set_filename shims
that are now superseded)
- #include "gtk4-compat.h" removed from xqf.h, pixmaps.h, utils.c
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 2 converted all 101 XPM files to PNG and moved them to pixmaps/default/. The src/xpm/ directory was left in the tree as a safety net; it is no longer referenced by any code or build rule. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Mark Phase 6 fully complete (gtk4-compat.h deleted) - Mark Phase 7 fully complete (config.c rewritten with GKeyFile) - Add Phase 2 task 6: src/xpm/ deletion (done) - Update Current State Summary to reflect completed work - Add Phase 8: GtkComboBox → GtkDropDown (9 files, no version guard needed) - Add Phase 9: gtk_image_*_from_pixbuf + gtk_widget_get_allocation (5+2 files) - Update deprecated-API table with replacement version and phase reference - Remove stale "src/xpm/ deletion" entry from Deferred section Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Non-editable combo boxes → GtkDropDown + GtkStringList (GTK 4.0+):
- filter.c: filter_option_menu now uses GtkDropDown + GtkStringList;
set_filter_menu() uses gtk_string_list_splice(); "changed" signal
replaced by "notify::selected"
- pref.c: weapon-switch, backpack-switch, noskins menus replaced with
gtk_drop_down_new_from_strings(); callbacks updated for notify::selected
Editable combo boxes → plain GtkEntry (history dropdown dropped):
- addserver.c, addmaster.c, psearch.c, rcon.c: gtk_combo_box_text_new_with_entry()
replaced with gtk_entry_new(); combo_get_entry() / combo_set_vals() calls
remain valid via updated helpers in srv-prop.c
- pref.c: qw_skin_combo, q2_skin_combo, cfg_combo, proto_entry → GtkEntry
- srv-prop.c: customcfg_combo → GtkEntry; combo_get_entry() simplified to
return GTK_ENTRY(widget); combo_set_vals() simplified to set text only
Custom model with icon+text → GListStore + GtkSignalListItemFactory:
- xqf-ui.c: create_server_type_menu() rewritten using GListStore of GObject
items (with g_object_set_data keys "server-type", "icon", "name") and a
GtkSignalListItemFactory that builds GtkBox(GtkImage + GtkLabel) per row
- xqf-ui.h: SERVERTYPE_ATTR_* enum removed (no longer needed)
- statistics.c: "All Games" item prepended using g_list_store_insert +
g_object_set_data instead of GtkListStore + GtkTreeIter
Also fix stray src/xpm/noflag.xpm include in country-filter.c left over
from Phase 2 (xpm deletion): replaced with find_pixmap_directory("noflag.png")
+ gdk_pixbuf_new_from_file().
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace gtk_image_new/set_from_pixbuf with gtk_image_new/set_from_paintable using GdkTexture. Country flag loading now also creates pix->texture so all call sites can use the paintable API uniformly. Replace gtk_widget_get_allocation with gtk_widget_get_width/height in the three geometry-save callbacks (main window, rcon, statistics). Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ource tree Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace libgtk2.0-dev with libgtk-4-dev - Replace intltool with gettext (CMakeLists uses find_package(Gettext)) - Add libxml2-dev (required by gamesxml2c, was missing from dep list) - Drop -Werror (GTK4 deprecated APIs trigger -Wdeprecated-declarations) - Update actions/checkout from v2 to v4 Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- loadpixmap.c: fix excess initializer in struct pixmap (struct now has
2 members after GTK2 fields were removed; 3-element { 0,0,0 } → { 0,0 })
- xqf-ui.h: remove dangling unclosed block comment left when the Glade
widget-lookup function was dropped; was causing -Wcomment on every TU
that includes this header
- pref.c: escape /* in "audio/* filter" comment to suppress -Wcomment
- xqf.c: remove unused `hbox` and `i` declarations/assignments in
populate_main_window (dead code left after GTK4 refactor)
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
srv-info.c, xqf-ui.c and xqf.c intentionally retain GtkTreeView, GtkTreeStore and GtkTreeSelection for the source-tree and server-info panels until those panels are ported to GtkListView/GtkColumnView in a later migration phase. Scoping the suppression to the xqf target means the rcon standalone binary, which does not link GTK, keeps full warning coverage. Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
|
ffs dont use ai this shit is not good for open source projects |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a big PR, mostly an experiment with Claude, to take the GTK3 port where it was left and move it to GTK4.
The file docs/gtk4-migration-plan.md has details on what happened during the process. I tried to make each change self contained on its own commit so reviewing would be somewhat easier, but I know it's a huge PR to review, so take your time, or feel free to reject if this is just not wanted. I thought that pouring more time on GTK3 was pointless, as that version is also deprecated at this point.