Enhancement: Fixes #391, desk.cpl - implement browse button

This commit is contained in:
Rory Fewell
2024-12-07 19:39:37 +00:00
parent a2b746f9c1
commit e3011c86f4
6 changed files with 285 additions and 5 deletions

View File

@@ -47,6 +47,8 @@ add_library(
public/icons.h public/icons.h
src/list.c src/list.c
public/list.h public/list.h
src/listbox.c
public/listbox.h
src/marshal.c src/marshal.c
public/marshal.h public/marshal.h
src/memory.c src/memory.c

View File

@@ -9,6 +9,7 @@
#include "@LIB_HEADER_DIR@/errors.h" #include "@LIB_HEADER_DIR@/errors.h"
#include "@LIB_HEADER_DIR@/icons.h" #include "@LIB_HEADER_DIR@/icons.h"
#include "@LIB_HEADER_DIR@/list.h" #include "@LIB_HEADER_DIR@/list.h"
#include "@LIB_HEADER_DIR@/listbox.h"
#include "@LIB_HEADER_DIR@/marshal.h" #include "@LIB_HEADER_DIR@/marshal.h"
#include "@LIB_HEADER_DIR@/memory.h" #include "@LIB_HEADER_DIR@/memory.h"
#include "@LIB_HEADER_DIR@/menu.h" #include "@LIB_HEADER_DIR@/menu.h"

View File

@@ -0,0 +1,22 @@
/** @file */
#ifndef __COMGTK_LISTBOX_H__
#define __COMGTK_LISTBOX_H__
#include <gtk/gtk.h>
//
// PUBLIC FUNCTIONS
//
/**
* Scrolls a list box to its selected item; this function is queued up as it
* must be performed after any newly added rows are realised.
*
* @param list_box The list box.
*/
void wintc_list_box_queue_scroll_to_selected(
GtkListBox* list_box
);
#endif

124
shared/comgtk/src/listbox.c Normal file
View File

@@ -0,0 +1,124 @@
#include <glib.h>
#include <gtk/gtk.h>
#include "../public/debug.h"
#include "../public/listbox.h"
#include "../public/shorthand.h"
//
// FORWARD DECLARATIONS
//
static gboolean cb_list_box_scroll_to_selected(
gpointer user_data
);
static void on_list_box_realize(
GtkWidget* self,
gpointer user_data
);
//
// PUBLIC FUNCTIONS
//
void wintc_list_box_queue_scroll_to_selected(
GtkListBox* list_box
)
{
// If the list box itself isn't even realised then we must delay until
// then
//
if (gtk_widget_get_realized(GTK_WIDGET(list_box)))
{
g_idle_add(
(GSourceFunc) cb_list_box_scroll_to_selected,
list_box
);
}
else
{
g_signal_connect(
list_box,
"realize",
G_CALLBACK(on_list_box_realize),
NULL
);
}
}
//
// CALLBACKS
//
static gboolean cb_list_box_scroll_to_selected(
gpointer user_data
)
{
GtkListBox* list_box = GTK_LIST_BOX(user_data);
// Find scrolled window and selected item...
//
GtkListBoxRow* row = gtk_list_box_get_selected_row(list_box);
GtkWidget* scrollwnd = gtk_widget_get_ancestor(
GTK_WIDGET(list_box),
GTK_TYPE_SCROLLED_WINDOW
);
if (!scrollwnd)
{
g_critical(
"%s",
"Can't scroll list box, it's not in a scrolled window."
);
return G_SOURCE_REMOVE;
}
if (!row)
{
WINTC_LOG_DEBUG("Not scrolling list box - nothing selected.");
return G_SOURCE_REMOVE;
}
// Perform the scroll
//
gint scroll_y = 0;
if (
gtk_widget_translate_coordinates(
GTK_WIDGET(row),
GTK_WIDGET(list_box),
0,
0,
NULL,
&scroll_y
)
)
{
gtk_adjustment_set_value(
gtk_scrolled_window_get_vadjustment(
GTK_SCROLLED_WINDOW(scrollwnd)
),
(gdouble) scroll_y
);
}
return G_SOURCE_REMOVE;
}
static void on_list_box_realize(
GtkWidget* self,
WINTC_UNUSED(gpointer user_data)
)
{
g_idle_add(
(GSourceFunc) cb_list_box_scroll_to_selected,
GTK_LIST_BOX(self)
);
// Disconnect the signal, only needed this once
//
g_signal_handlers_disconnect_by_func(
self,
on_list_box_realize,
NULL
);
}

View File

@@ -4,6 +4,7 @@
#include <wintc/comctl.h> #include <wintc/comctl.h>
#include <wintc/comgtk.h> #include <wintc/comgtk.h>
#include <wintc/shcommon.h> #include <wintc/shcommon.h>
#include <wintc/shlang.h>
#include <wintc/syscfg.h> #include <wintc/syscfg.h>
#include "monitor.h" #include "monitor.h"
@@ -16,7 +17,8 @@
// //
static void add_wallpaper_to_list( static void add_wallpaper_to_list(
WinTCCplDeskWindow* wnd, WinTCCplDeskWindow* wnd,
const gchar* path const gchar* path,
gboolean new_item
); );
static void redraw_wallpaper_preview( static void redraw_wallpaper_preview(
WinTCCplDeskWindow* wnd WinTCCplDeskWindow* wnd
@@ -29,6 +31,12 @@ static void select_wallpaper_from_list(
const gchar* path const gchar* path
); );
static void action_browse(
GSimpleAction* action,
GVariant* parameter,
gpointer user_data
);
static void on_combo_style_changed( static void on_combo_style_changed(
GtkComboBox* self, GtkComboBox* self,
gpointer user_data gpointer user_data
@@ -39,6 +47,19 @@ static void on_listbox_wallpapers_row_selected(
gpointer user_data gpointer user_data
); );
//
// STATIC DATA
//
static GActionEntry s_actions[] = {
{
.name = "browse",
.activate = action_browse,
.parameter_type = NULL,
.state = NULL,
.change_state = NULL
}
};
// //
// PUBLIC FUNCTIONS // PUBLIC FUNCTIONS
// //
@@ -55,6 +76,23 @@ void wintc_cpl_desk_window_append_desktop_page(
NULL NULL
); );
// Define GActions
//
GSimpleActionGroup* action_group = g_simple_action_group_new();
g_action_map_add_action_entries(
G_ACTION_MAP(action_group),
s_actions,
G_N_ELEMENTS(s_actions),
wnd
);
gtk_widget_insert_action_group(
wnd->notebook_main,
"desktop",
G_ACTION_GROUP(action_group)
);
// Connect signals // Connect signals
// //
g_signal_connect( g_signal_connect(
@@ -121,7 +159,8 @@ void wintc_cpl_desk_window_finalize_desktop_page(
// //
static void add_wallpaper_to_list( static void add_wallpaper_to_list(
WinTCCplDeskWindow* wnd, WinTCCplDeskWindow* wnd,
const gchar* path const gchar* path,
gboolean new_item
) )
{ {
gchar* filename = g_path_get_basename(path); gchar* filename = g_path_get_basename(path);
@@ -138,6 +177,17 @@ static void add_wallpaper_to_list(
gtk_widget_show(label); gtk_widget_show(label);
g_free(filename); g_free(filename);
// Do we need to add this item to the backing list?
//
if (new_item)
{
wnd->list_wallpapers =
g_list_append(
wnd->list_wallpapers,
g_strdup(path)
);
}
} }
static void redraw_wallpaper_preview( static void redraw_wallpaper_preview(
@@ -249,7 +299,7 @@ static void refresh_wallpaper_list(
for (GList* iter = wnd->list_wallpapers; iter; iter = iter->next) for (GList* iter = wnd->list_wallpapers; iter; iter = iter->next)
{ {
add_wallpaper_to_list(wnd, (gchar*) iter->data); add_wallpaper_to_list(wnd, (gchar*) iter->data, FALSE);
} }
} }
@@ -276,6 +326,11 @@ static void select_wallpaper_from_list(
i i
) )
); );
wintc_list_box_queue_scroll_to_selected(
GTK_LIST_BOX(wnd->listbox_wallpapers)
);
return; return;
} }
@@ -284,7 +339,7 @@ static void select_wallpaper_from_list(
// The path isn't in the listbox, so add it and select last item // The path isn't in the listbox, so add it and select last item
// //
add_wallpaper_to_list(wnd, path); add_wallpaper_to_list(wnd, path, TRUE);
gtk_list_box_select_row( gtk_list_box_select_row(
GTK_LIST_BOX(wnd->listbox_wallpapers), GTK_LIST_BOX(wnd->listbox_wallpapers),
@@ -293,11 +348,87 @@ static void select_wallpaper_from_list(
g_list_length(wnd->list_wallpapers) - 1 g_list_length(wnd->list_wallpapers) - 1
) )
); );
wintc_list_box_queue_scroll_to_selected(
GTK_LIST_BOX(wnd->listbox_wallpapers)
);
} }
// //
// CALLBACKS // CALLBACKS
// //
static void action_browse(
WINTC_UNUSED(GSimpleAction* action),
WINTC_UNUSED(GVariant* parameter),
gpointer user_data
)
{
WinTCCplDeskWindow* wnd = WINTC_CPL_DESK_WINDOW(user_data);
//
// FIXME: No support for Active Desktop at the moment, hence the lack of
// Background Files and Web page filters
//
// Set up image filters
//
static const gchar* k_filters[] = {
"image/bmp",
"image/gif",
"image/jpeg",
"image/jpg",
"image/png"
};
GtkFileFilter* filter_images = gtk_file_filter_new();
gtk_file_filter_set_name(
filter_images,
"All Picture Files (*.bmp;*.gif;*.jpg;*.jpeg;*.dib;*.png)"
);
for (gulong i = 0; i < G_N_ELEMENTS(k_filters); i++)
{
gtk_file_filter_add_mime_type(
filter_images,
k_filters[i]
);
}
// Set up dialog
//
GtkWidget* dlg =
gtk_file_chooser_dialog_new(
wintc_lc_get_control_text(WINTC_CTLTXT_BROWSE, WINTC_PUNC_NONE),
GTK_WINDOW(wnd),
GTK_FILE_CHOOSER_ACTION_OPEN,
wintc_lc_get_control_text(WINTC_CTLTXT_CANCEL, WINTC_PUNC_NONE),
GTK_RESPONSE_CANCEL,
wintc_lc_get_control_text(WINTC_CTLTXT_OPEN, WINTC_PUNC_NONE),
GTK_RESPONSE_ACCEPT,
NULL
);
gtk_file_chooser_add_filter(
GTK_FILE_CHOOSER(dlg),
filter_images
);
// Launch dialog
//
gint result = gtk_dialog_run(GTK_DIALOG(dlg));
if (result == GTK_RESPONSE_ACCEPT)
{
select_wallpaper_from_list(
wnd,
gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg))
);
}
gtk_widget_destroy(dlg);
}
static void on_combo_style_changed( static void on_combo_style_changed(
GtkComboBox* self, GtkComboBox* self,
gpointer user_data gpointer user_data

View File

@@ -143,7 +143,7 @@
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="receives-default">True</property> <property name="receives-default">True</property>
<property name="label" translatable="yes">%PUNC_MOREINPUT%%CTL_BROWSE%</property> <property name="label" translatable="yes">%PUNC_MOREINPUT%%CTL_BROWSE%</property>
<property name="sensitive">False</property> <property name="action-name">desktop.browse</property>
<style> <style>
<class name="wintc-button" /> <class name="wintc-button" />