Skip to content

Commit 2ca0218

Browse files
committed
metadata
1 parent b91a919 commit 2ca0218

4 files changed

Lines changed: 193 additions & 46 deletions

File tree

libnemo-private/nemo-metadata.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ static char *used_metadata_names[] = {
4646
(char *)NEMO_METADATA_KEY_WINDOW_MAXIMIZED,
4747
(char *)NEMO_METADATA_KEY_WINDOW_STICKY,
4848
(char *)NEMO_METADATA_KEY_WINDOW_KEEP_ABOVE,
49+
(char *)NEMO_METADATA_KEY_WINDOW_SHOW_PREVIEW_PANE,
4950
(char *)NEMO_METADATA_KEY_SIDEBAR_BACKGROUND_COLOR,
5051
(char *)NEMO_METADATA_KEY_SIDEBAR_BACKGROUND_IMAGE,
5152
(char *)NEMO_METADATA_KEY_SIDEBAR_BUTTONS,

libnemo-private/nemo-metadata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#define NEMO_METADATA_KEY_WINDOW_MAXIMIZED "nemo-window-maximized"
6161
#define NEMO_METADATA_KEY_WINDOW_STICKY "nemo-window-sticky"
6262
#define NEMO_METADATA_KEY_WINDOW_KEEP_ABOVE "nemo-window-keep-above"
63+
#define NEMO_METADATA_KEY_WINDOW_SHOW_PREVIEW_PANE "nemo-window-show-preview-pane"
6364

6465
#define NEMO_METADATA_KEY_SIDEBAR_BACKGROUND_COLOR "nemo-sidebar-background-color"
6566
#define NEMO_METADATA_KEY_SIDEBAR_BACKGROUND_IMAGE "nemo-sidebar-background-image"

libnemo-private/nemo-preview-image.c

Lines changed: 146 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "nemo-preview-image.h"
2525
#include "nemo-file-attributes.h"
26+
#include "nemo-icon-info.h"
2627
#include <glib/gi18n.h>
2728

2829
#define RESIZE_DEBOUNCE_MS 150
@@ -34,6 +35,7 @@ struct _NemoPreviewImage {
3435
};
3536

3637
typedef struct {
38+
GtkWidget *frame;
3739
GtkWidget *drawing_area;
3840
GtkWidget *message_label;
3941
NemoFile *file;
@@ -48,6 +50,9 @@ typedef struct {
4850

4951
/* Current surface to draw */
5052
cairo_surface_t *current_surface;
53+
54+
/* Track if showing an icon vs image */
55+
gboolean showing_icon;
5156
} NemoPreviewImagePrivate;
5257

5358
G_DEFINE_TYPE_WITH_PRIVATE (NemoPreviewImage, nemo_preview_image, GTK_TYPE_BOX)
@@ -101,6 +106,17 @@ nemo_preview_image_init (NemoPreviewImage *preview)
101106
priv->current_height = 0;
102107
priv->current_pixbuf = NULL;
103108
priv->current_surface = NULL;
109+
priv->showing_icon = FALSE;
110+
111+
/* Create frame to hold drawing area */
112+
priv->frame = gtk_frame_new (NULL);
113+
gtk_frame_set_shadow_type (GTK_FRAME (priv->frame), GTK_SHADOW_IN);
114+
gtk_widget_set_halign (priv->frame, GTK_ALIGN_FILL);
115+
gtk_widget_set_valign (priv->frame, GTK_ALIGN_FILL);
116+
gtk_widget_set_hexpand (priv->frame, TRUE);
117+
gtk_widget_set_vexpand (priv->frame, TRUE);
118+
119+
gtk_box_pack_start (GTK_BOX (preview), priv->frame, TRUE, TRUE, 0);
104120

105121
/* Create drawing area widget */
106122
priv->drawing_area = gtk_drawing_area_new ();
@@ -110,7 +126,7 @@ nemo_preview_image_init (NemoPreviewImage *preview)
110126
gtk_widget_set_vexpand (priv->drawing_area, TRUE);
111127
g_signal_connect (priv->drawing_area, "draw",
112128
G_CALLBACK (on_drawing_area_draw), preview);
113-
gtk_box_pack_start (GTK_BOX (preview), priv->drawing_area, TRUE, TRUE, 0);
129+
gtk_container_add (GTK_CONTAINER (priv->frame), priv->drawing_area);
114130

115131
/* Create message label (hidden by default) */
116132
priv->message_label = gtk_label_new ("");
@@ -120,6 +136,8 @@ nemo_preview_image_init (NemoPreviewImage *preview)
120136
"dim-label");
121137
gtk_box_pack_start (GTK_BOX (preview), priv->message_label, TRUE, TRUE, 0);
122138

139+
gtk_container_set_border_width (GTK_CONTAINER (preview), 4);
140+
gtk_widget_show_all (GTK_WIDGET (preview));
123141
/* Connect size-allocate signal for resize handling */
124142
g_signal_connect (preview, "size-allocate",
125143
G_CALLBACK (on_size_allocate), NULL);
@@ -173,9 +191,30 @@ on_drawing_area_draw (GtkWidget *widget,
173191
x_offset = (widget_width - surface_width) / 2.0;
174192
y_offset = (widget_height - surface_height) / 2.0;
175193

194+
/* Draw the image first */
176195
cairo_set_source_surface (cr, priv->current_surface, x_offset, y_offset);
177196
cairo_paint (cr);
178197

198+
/* If showing an image (not an icon), draw a border on top of it */
199+
if (!priv->showing_icon) {
200+
GtkStyleContext *style_context;
201+
GdkRGBA border_color;
202+
gdouble border_width = 1.0;
203+
gdouble inset = 0.5; /* Inset border slightly inside image bounds */
204+
205+
/* Get the border color from the frame's style context */
206+
style_context = gtk_widget_get_style_context (priv->frame);
207+
gtk_style_context_get_border_color (style_context, GTK_STATE_FLAG_NORMAL, &border_color);
208+
209+
/* Draw border rectangle inset from the image edge */
210+
cairo_set_source_rgba (cr, border_color.red, border_color.green,
211+
border_color.blue, border_color.alpha);
212+
cairo_set_line_width (cr, border_width);
213+
cairo_rectangle (cr, x_offset + inset, y_offset + inset,
214+
surface_width - (inset * 2), surface_height - (inset * 2));
215+
cairo_stroke (cr);
216+
}
217+
179218
return TRUE;
180219
}
181220

@@ -196,6 +235,100 @@ is_image_file (NemoFile *file)
196235
return is_image;
197236
}
198237

238+
static void
239+
load_icon_at_size (NemoPreviewImage *widget,
240+
gint width,
241+
gint height)
242+
{
243+
NemoPreviewImagePrivate *priv;
244+
NemoIconInfo *icon_info = NULL;
245+
GtkIconTheme *icon_theme;
246+
GdkPixbuf *icon_pixbuf = NULL;
247+
cairo_surface_t *surface = NULL;
248+
gint ui_scale;
249+
gint icon_size;
250+
const char *icon_name;
251+
GError *error = NULL;
252+
253+
priv = nemo_preview_image_get_instance_private (widget);
254+
255+
if (priv->file == NULL) {
256+
return;
257+
}
258+
259+
if (width <= 1 || height <= 1) {
260+
return;
261+
}
262+
263+
ui_scale = gtk_widget_get_scale_factor (GTK_WIDGET (widget));
264+
265+
/* Calculate icon size - use the smaller dimension to fit in the space */
266+
icon_size = MIN (width, height) * ui_scale;
267+
268+
/* Get the icon info from the file */
269+
icon_info = nemo_file_get_icon (priv->file, icon_size, 0, ui_scale, 0);
270+
271+
if (icon_info != NULL && icon_info->icon_name != NULL) {
272+
icon_name = icon_info->icon_name;
273+
icon_theme = gtk_icon_theme_get_default ();
274+
275+
/* Load the icon at the exact size we need */
276+
icon_pixbuf = gtk_icon_theme_load_icon_for_scale (icon_theme,
277+
icon_name,
278+
icon_size / ui_scale,
279+
ui_scale,
280+
GTK_ICON_LOOKUP_FORCE_SIZE,
281+
&error);
282+
283+
if (icon_pixbuf != NULL) {
284+
/* Save pixbuf for quick scaling during resize */
285+
if (priv->current_pixbuf != NULL) {
286+
g_object_unref (priv->current_pixbuf);
287+
}
288+
priv->current_pixbuf = g_object_ref (icon_pixbuf);
289+
290+
surface = gdk_cairo_surface_create_from_pixbuf (icon_pixbuf, ui_scale, NULL);
291+
292+
if (surface != NULL) {
293+
/* Replace old surface with new one */
294+
if (priv->current_surface != NULL) {
295+
cairo_surface_destroy (priv->current_surface);
296+
}
297+
priv->current_surface = surface;
298+
gtk_widget_show (priv->drawing_area);
299+
gtk_widget_queue_draw (priv->drawing_area);
300+
}
301+
302+
g_object_unref (icon_pixbuf);
303+
gtk_widget_hide (priv->message_label);
304+
} else {
305+
/* Failed to load icon */
306+
if (error != NULL) {
307+
g_warning ("Failed to load icon '%s': %s", icon_name, error->message);
308+
g_error_free (error);
309+
}
310+
gtk_label_set_text (GTK_LABEL (priv->message_label),
311+
_("(Failed to load icon)"));
312+
gtk_widget_show (priv->message_label);
313+
gtk_widget_hide (priv->drawing_area);
314+
}
315+
316+
nemo_icon_info_unref (icon_info);
317+
} else {
318+
/* No icon info available */
319+
if (icon_info != NULL) {
320+
nemo_icon_info_unref (icon_info);
321+
}
322+
gtk_label_set_text (GTK_LABEL (priv->message_label),
323+
_("(No icon available)"));
324+
gtk_widget_show (priv->message_label);
325+
gtk_widget_hide (priv->drawing_area);
326+
}
327+
328+
priv->current_width = width;
329+
priv->current_height = height;
330+
}
331+
199332
static void
200333
load_image_at_size (NemoPreviewImage *widget,
201334
gint width,
@@ -342,7 +475,12 @@ on_resize_timeout (gpointer user_data)
342475
priv->resize_timeout_id = 0;
343476

344477
gtk_widget_get_allocation (GTK_WIDGET (widget), &allocation);
345-
load_image_at_size (widget, allocation.width, allocation.height);
478+
479+
if (priv->showing_icon) {
480+
load_icon_at_size (widget, allocation.width, allocation.height);
481+
} else {
482+
load_image_at_size (widget, allocation.width, allocation.height);
483+
}
346484

347485
return G_SOURCE_REMOVE;
348486
}
@@ -434,53 +572,14 @@ nemo_preview_image_set_file (NemoPreviewImage *widget,
434572

435573
if (is_image_file (file)) {
436574
/* Load the image at current widget size */
575+
priv->showing_icon = FALSE;
437576
gtk_widget_get_allocation (GTK_WIDGET (widget), &allocation);
438577
load_image_at_size (widget, allocation.width, allocation.height);
439-
} else if (nemo_file_is_directory (file)) {
440-
/* Show folder icon via nemo_file API */
441-
GdkPixbuf *icon_pixbuf;
442-
cairo_surface_t *surface;
443-
gint ui_scale = gtk_widget_get_scale_factor (GTK_WIDGET (widget));
444-
445-
icon_pixbuf = nemo_file_get_icon_pixbuf (file, 64, TRUE, ui_scale, 0);
446-
if (icon_pixbuf != NULL) {
447-
surface = gdk_cairo_surface_create_from_pixbuf (icon_pixbuf, ui_scale, NULL);
448-
if (surface != NULL) {
449-
if (priv->current_surface != NULL) {
450-
cairo_surface_destroy (priv->current_surface);
451-
}
452-
priv->current_surface = surface;
453-
}
454-
g_object_unref (icon_pixbuf);
455-
}
456-
457-
gtk_label_set_text (GTK_LABEL (priv->message_label), _("(Folder)"));
458-
gtk_widget_show (priv->drawing_area);
459-
gtk_widget_queue_draw (priv->drawing_area);
460-
gtk_widget_show (priv->message_label);
461578
} else {
462-
/* Non-image file: show file icon */
463-
GdkPixbuf *icon_pixbuf;
464-
cairo_surface_t *surface;
465-
gint ui_scale = gtk_widget_get_scale_factor (GTK_WIDGET (widget));
466-
467-
icon_pixbuf = nemo_file_get_icon_pixbuf (file, 64, TRUE, ui_scale, 0);
468-
if (icon_pixbuf != NULL) {
469-
surface = gdk_cairo_surface_create_from_pixbuf (icon_pixbuf, ui_scale, NULL);
470-
if (surface != NULL) {
471-
if (priv->current_surface != NULL) {
472-
cairo_surface_destroy (priv->current_surface);
473-
}
474-
priv->current_surface = surface;
475-
}
476-
g_object_unref (icon_pixbuf);
477-
}
478-
479-
gtk_label_set_text (GTK_LABEL (priv->message_label),
480-
_("(Not an image file)"));
481-
gtk_widget_show (priv->drawing_area);
482-
gtk_widget_queue_draw (priv->drawing_area);
483-
gtk_widget_show (priv->message_label);
579+
/* Load folder or file icon at current widget size */
580+
priv->showing_icon = TRUE;
581+
gtk_widget_get_allocation (GTK_WIDGET (widget), &allocation);
582+
load_icon_at_size (widget, allocation.width, allocation.height);
484583
}
485584
}
486585
}
@@ -519,4 +618,5 @@ nemo_preview_image_clear (NemoPreviewImage *widget)
519618
gtk_widget_hide (priv->message_label);
520619
priv->current_width = 0;
521620
priv->current_height = 0;
621+
priv->showing_icon = FALSE;
522622
}

src/nemo-window.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,8 @@ nemo_window_connect_content_view (NemoWindow *window,
15731573
NemoView *view)
15741574
{
15751575
NemoWindowSlot *slot;
1576+
NemoFile *directory_file;
1577+
gboolean show_preview;
15761578

15771579
g_assert (NEMO_IS_WINDOW (window));
15781580
g_assert (NEMO_IS_VIEW (view));
@@ -1587,6 +1589,21 @@ nemo_window_connect_content_view (NemoWindow *window,
15871589
G_CALLBACK (zoom_level_changed_callback),
15881590
window);
15891591

1592+
/* Check if this directory has a saved preview pane state */
1593+
directory_file = nemo_view_get_directory_as_file (view);
1594+
if (directory_file != NULL) {
1595+
show_preview = nemo_file_get_boolean_metadata (directory_file,
1596+
NEMO_METADATA_KEY_WINDOW_SHOW_PREVIEW_PANE,
1597+
FALSE);
1598+
1599+
/* Apply the saved state */
1600+
if (show_preview && !window->details->show_preview_pane) {
1601+
nemo_window_preview_pane_on (window);
1602+
} else if (!show_preview && window->details->show_preview_pane) {
1603+
nemo_window_preview_pane_off (window);
1604+
}
1605+
}
1606+
15901607
/* Connect preview pane selection updates if preview is showing */
15911608
if (window->details->preview_pane) {
15921609
g_signal_connect_object (view, "selection-changed",
@@ -2376,12 +2393,26 @@ nemo_window_preview_pane_on (NemoWindow *window)
23762393

23772394
window->details->show_preview_pane = TRUE;
23782395
nemo_window_update_show_hide_ui_elements (window);
2396+
2397+
/* Save preview pane state to directory metadata */
2398+
if (slot != NULL && slot->content_view != NULL) {
2399+
NemoFile *directory_file;
2400+
2401+
directory_file = nemo_view_get_directory_as_file (slot->content_view);
2402+
if (directory_file != NULL) {
2403+
nemo_file_set_boolean_metadata (directory_file,
2404+
NEMO_METADATA_KEY_WINDOW_SHOW_PREVIEW_PANE,
2405+
FALSE,
2406+
TRUE);
2407+
}
2408+
}
23792409
}
23802410

23812411
void
23822412
nemo_window_preview_pane_off (NemoWindow *window)
23832413
{
23842414
GtkPaned *paned;
2415+
NemoWindowSlot *slot;
23852416

23862417
if (window->details->preview_pane == NULL) {
23872418
return;
@@ -2407,6 +2438,20 @@ nemo_window_preview_pane_off (NemoWindow *window)
24072438
window->details->show_preview_pane = FALSE;
24082439

24092440
nemo_window_update_show_hide_ui_elements (window);
2441+
2442+
/* Save preview pane state to directory metadata */
2443+
slot = nemo_window_get_active_slot (window);
2444+
if (slot != NULL && slot->content_view != NULL) {
2445+
NemoFile *directory_file;
2446+
2447+
directory_file = nemo_view_get_directory_as_file (slot->content_view);
2448+
if (directory_file != NULL) {
2449+
nemo_file_set_boolean_metadata (directory_file,
2450+
NEMO_METADATA_KEY_WINDOW_SHOW_PREVIEW_PANE,
2451+
FALSE,
2452+
FALSE);
2453+
}
2454+
}
24102455
}
24112456

24122457
gboolean

0 commit comments

Comments
 (0)