Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions gresources/nemo-file-management-properties.glade
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,22 @@ along with . If not, see <http://www.gnu.org/licenses/>.
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="show_selection_checkboxes_checkbutton">
<property name="label" translatable="yes">Enable item selection checkboxes</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="use-underline">True</property>
<property name="xalign">0</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="ignore_view_metadata_checkbutton">
<property name="label" translatable="yes">Ignore per-folder view preferences</property>
Expand All @@ -1220,7 +1236,7 @@ along with . If not, see <http://www.gnu.org/licenses/>.
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
Expand All @@ -1236,7 +1252,7 @@ along with . If not, see <http://www.gnu.org/licenses/>.
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
<child>
Expand All @@ -1253,7 +1269,7 @@ along with . If not, see <http://www.gnu.org/licenses/>.
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">3</property>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
<child>
Expand All @@ -1270,7 +1286,7 @@ along with . If not, see <http://www.gnu.org/licenses/>.
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">3</property>
<property name="position">4</property>
<property name="position">5</property>
</packing>
</child>
<child>
Expand All @@ -1286,7 +1302,7 @@ along with . If not, see <http://www.gnu.org/licenses/>.
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
<property name="position">6</property>
</packing>
</child>
</object>
Expand Down
1 change: 1 addition & 0 deletions libnemo-private/nemo-global-preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ typedef enum

#define NEMO_PREFERENCES_START_WITH_DUAL_PANE "start-with-dual-pane"
#define NEMO_PREFERENCES_RESTORE_TABS_ON_STARTUP "restore-tabs-on-startup"
#define NEMO_PREFERENCES_SHOW_SELECTION_CHECKBOXES "show-selection-checkboxes"
#define NEMO_PREFERENCES_IGNORE_VIEW_METADATA "ignore-view-metadata"
#define NEMO_PREFERENCES_SHOW_BOOKMARKS_IN_TO_MENUS "show-bookmarks-in-to-menus"
#define NEMO_PREFERENCES_SHOW_PLACES_IN_TO_MENUS "show-places-in-to-menus"
Expand Down
135 changes: 135 additions & 0 deletions libnemo-private/nemo-icon-canvas-item.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
/* gap between bottom of icon and start of text box */
#define LABEL_OFFSET_BESIDES 3
#define LABEL_LINE_SPACING 0
#define SELECTION_CHECKBOX_MARGIN 2


/* special text height handling
Expand Down Expand Up @@ -174,6 +175,12 @@ static void draw_pixbuf (GdkPixbuf
cairo_t *cr,
int x,
int y);
static void draw_selection_checkbox (NemoIconCanvasItem *item,
cairo_t *cr,
EelIRect icon_rect);
static double get_selection_checkbox_size (GtkWidget *widget);
static GdkPixbuf *get_selection_checkbox_pixbuf (GtkWidget *widget,
gboolean selected);
static PangoLayout *get_label_layout (PangoLayout **layout,
NemoIconCanvasItem *item,
const char *text);
Expand Down Expand Up @@ -1288,6 +1295,100 @@ draw_pixbuf (GdkPixbuf *pixbuf,
cairo_restore (cr);
}

static double
get_selection_checkbox_size (GtkWidget *widget)
{
int width = 0;
int height = 0;

if (gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (widget),
GTK_ICON_SIZE_MENU,
&width,
&height)) {
return MAX (width, height);
}

return 16.0;
}

static GdkPixbuf *
get_selection_checkbox_pixbuf (GtkWidget *widget,
gboolean selected)
{
GtkIconTheme *icon_theme;
GtkStyleContext *context;
GtkIconInfo *icon_info;
GdkRGBA fg_color;
GdkPixbuf *pixbuf;
int icon_size;
const char *icon_name;
GError *error = NULL;
gboolean was_symbolic = FALSE;

context = gtk_widget_get_style_context (widget);
icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
icon_size = (int) get_selection_checkbox_size (widget);
icon_name = selected ? "checkbox-checked-symbolic" : "checkbox-symbolic";

icon_info = gtk_icon_theme_lookup_icon (icon_theme,
icon_name,
icon_size,
GTK_ICON_LOOKUP_FORCE_SIZE);
if (icon_info == NULL) {
return NULL;
}

gtk_style_context_get_color (context, GTK_STATE_FLAG_SELECTED, &fg_color);
pixbuf = gtk_icon_info_load_symbolic_for_context (icon_info,
context,
&was_symbolic,
&error);
g_object_unref (icon_info);

if (pixbuf == NULL) {
g_clear_error (&error);
}

return pixbuf;
}

static void
draw_selection_checkbox (NemoIconCanvasItem *icon_item,
cairo_t *cr,
EelIRect icon_rect)
{
GtkWidget *widget;
double pixels_per_unit;
gboolean selected;
gboolean show_selection_checkboxes;
GdkPixbuf *checkbox_pixbuf;

show_selection_checkboxes = g_settings_get_boolean (nemo_preferences,
NEMO_PREFERENCES_SHOW_SELECTION_CHECKBOXES);
if (!show_selection_checkboxes) {
return;
}

selected = icon_item->details->is_highlighted_for_selection;
if (!icon_item->details->is_prelit && !selected) {
return;
}

widget = GTK_WIDGET (EEL_CANVAS_ITEM (icon_item)->canvas);
pixels_per_unit = EEL_CANVAS_ITEM (icon_item)->canvas->pixels_per_unit;
checkbox_pixbuf = get_selection_checkbox_pixbuf (widget, selected);
if (checkbox_pixbuf == NULL) {
return;
}

draw_pixbuf (checkbox_pixbuf,
cr,
icon_rect.x0 + (SELECTION_CHECKBOX_MARGIN / pixels_per_unit),
icon_rect.y0 + (SELECTION_CHECKBOX_MARGIN / pixels_per_unit));
g_object_unref (checkbox_pixbuf);

}

/* shared code to highlight or dim the passed-in pixbuf */
static cairo_surface_t *
real_map_surface (NemoIconCanvasItem *icon_item)
Expand Down Expand Up @@ -1387,6 +1488,8 @@ nemo_icon_canvas_item_draw (EelCanvasItem *item,
icon_rect.x0, icon_rect.y0);
cairo_surface_destroy (temp_surface);

draw_selection_checkbox (icon_item, cr, icon_rect);

/* Draw stretching handles (if necessary). */
draw_stretch_handles (icon_item, cr, &icon_rect);

Expand Down Expand Up @@ -1988,6 +2091,38 @@ nemo_icon_canvas_item_hit_test_rectangle (NemoIconCanvasItem *item, EelIRect can
return hit_test (item, canvas_rect);
}

gboolean
nemo_icon_canvas_item_hit_test_selection_checkbox (NemoIconCanvasItem *item,
gdouble world_x,
gdouble world_y)
{
EelDRect icon_rect;
double pixels_per_unit;
double checkbox_size;
double checkbox_x;
double checkbox_y;
gboolean show_selection_checkboxes;

g_return_val_if_fail (NEMO_IS_ICON_CANVAS_ITEM (item), FALSE);

show_selection_checkboxes = g_settings_get_boolean (nemo_preferences,
NEMO_PREFERENCES_SHOW_SELECTION_CHECKBOXES);
if (!show_selection_checkboxes) {
return FALSE;
}

icon_rect = nemo_icon_canvas_item_get_icon_rectangle (item);
pixels_per_unit = EEL_CANVAS_ITEM (item)->canvas->pixels_per_unit;
checkbox_size = get_selection_checkbox_size (GTK_WIDGET (EEL_CANVAS_ITEM (item)->canvas)) / pixels_per_unit;
checkbox_x = icon_rect.x0 + (SELECTION_CHECKBOX_MARGIN / pixels_per_unit);
checkbox_y = icon_rect.y0 + (SELECTION_CHECKBOX_MARGIN / pixels_per_unit);

return world_x >= checkbox_x &&
world_x <= checkbox_x + checkbox_size &&
world_y >= checkbox_y &&
world_y <= checkbox_y + checkbox_size;
}

const char *
nemo_icon_canvas_item_get_editable_text (NemoIconCanvasItem *icon_item)
{
Expand Down
3 changes: 3 additions & 0 deletions libnemo-private/nemo-icon-canvas-item.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ void nemo_icon_canvas_item_set_emblems (NemoIconCanvasItem
GList *emblem_pixbufs);
void nemo_icon_canvas_item_set_show_stretch_handles (NemoIconCanvasItem *item,
gboolean show_stretch_handles);
gboolean nemo_icon_canvas_item_hit_test_selection_checkbox (NemoIconCanvasItem *item,
gdouble world_x,
gdouble world_y);
double nemo_icon_canvas_item_get_max_text_width (NemoIconCanvasItem *item);
const char *nemo_icon_canvas_item_get_editable_text (NemoIconCanvasItem *icon_item);
void nemo_icon_canvas_item_set_renaming (NemoIconCanvasItem *icon_item,
Expand Down
52 changes: 52 additions & 0 deletions libnemo-private/nemo-icon-container.c
Original file line number Diff line number Diff line change
Expand Up @@ -5220,6 +5220,51 @@ handle_icon_button_press (NemoIconContainer *container,
return TRUE;
}

static gboolean
clicked_on_selection_checkbox (NemoIconContainer *container,
NemoIcon *icon,
GdkEventButton *event)
{
gboolean show_selection_checkboxes;
double raw_x;
double raw_y;
double world_x;
double world_y;
EelDRect icon_rect;
double pixels_per_unit;
double checkbox_size;
double checkbox_x;
double checkbox_y;

g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE);
g_return_val_if_fail (icon != NULL, FALSE);

show_selection_checkboxes = g_settings_get_boolean (nemo_preferences,
NEMO_PREFERENCES_SHOW_SELECTION_CHECKBOXES);
if (!show_selection_checkboxes) {
return FALSE;
}

raw_x = event->x;
raw_y = event->y;
eel_canvas_window_to_world (EEL_CANVAS (container), event->x, event->y,
&world_x, &world_y);
if (nemo_icon_canvas_item_hit_test_selection_checkbox (icon->item, world_x, world_y)) {
return TRUE;
}

icon_rect = nemo_icon_canvas_item_get_icon_rectangle (icon->item);
pixels_per_unit = EEL_CANVAS (container)->pixels_per_unit;
checkbox_size = 12 / pixels_per_unit;
checkbox_x = icon_rect.x0 + (2 / pixels_per_unit);
checkbox_y = icon_rect.y0 + (2 / pixels_per_unit);

return raw_x >= checkbox_x &&
raw_x <= checkbox_x + checkbox_size &&
raw_y >= checkbox_y &&
raw_y <= checkbox_y + checkbox_size;
}

static int
item_event_callback (EelCanvasItem *item,
GdkEvent *event,
Expand All @@ -5234,6 +5279,13 @@ item_event_callback (EelCanvasItem *item,
g_assert (icon != NULL);

if (event->type == GDK_BUTTON_PRESS) {
if (clicked_on_selection_checkbox (container, icon, &event->button)) {
icon_toggle_selected (container, icon);
g_signal_emit (container,
signals[SELECTION_CHANGED], 0);
return TRUE;
}

if (handle_icon_button_press (container, icon, &event->button)) {
/* Stop the event from being passed along further. Returning
* TRUE ain't enough.
Expand Down
5 changes: 5 additions & 0 deletions libnemo-private/org.nemo.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@
<summary>Restore the previous window tabs on startup</summary>
<description>If set to true, Nemo will restore the last saved window tab state when launched without explicit locations.</description>
</key>
<key name="show-selection-checkboxes" type="b">
<default>false</default>
<summary>Enable item selection checkboxes</summary>
<description>If set to true, Nemo will show clickable checkboxes on hovered items in icon and compact views, and beside all items in list view to make mouse-only multi-selection easier.</description>
</key>
<key name="ignore-view-metadata" type="b">
<default>false</default>
<summary>Whether to ignore folder metadata for view zoom levels and layouts</summary>
Expand Down
5 changes: 5 additions & 0 deletions src/nemo-file-management-properties.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
#define NEMO_FILE_MANAGEMENT_PROPERTIES_START_WITH_DUAL_PANE_WIDGET "start_with_dual_pane_checkbutton"
#define NEMO_FILE_MANAGEMENT_PROPERTIES_RESTORE_TABS_ON_STARTUP_WIDGET "restore_tabs_on_startup_checkbutton"
#define NEMO_FILE_MANAGEMENT_PROPERTIES_IGNORE_VIEW_METADATA_WIDGET "ignore_view_metadata_checkbutton"
#define NEMO_FILE_MANAGEMENT_PROPERTIES_SHOW_SELECTION_CHECKBOXES_WIDGET "show_selection_checkboxes_checkbutton"
#define NEMO_FILE_MANAGEMENT_PROPERTIES_BOOKMARKS_IN_TO_MENUS_WIDGET "bookmarks_in_to_checkbutton"
#define NEMO_FILE_MANAGEMENT_PROPERTIES_PLACES_IN_TO_MENUS_WIDGET "places_in_to_checkbutton"
#define NEMO_FILE_MANAGEMENT_PROPERTIES_INHERIT_SHOW_THUMBNAILS_WIDGET "inherit_show_thumbnails_checkbutton"
Expand Down Expand Up @@ -1076,6 +1077,10 @@ nemo_file_management_properties_dialog_setup (GtkBuilder *builder,
NEMO_FILE_MANAGEMENT_PROPERTIES_IGNORE_VIEW_METADATA_WIDGET,
NEMO_PREFERENCES_IGNORE_VIEW_METADATA);

bind_builder_bool (builder, nemo_preferences,
NEMO_FILE_MANAGEMENT_PROPERTIES_SHOW_SELECTION_CHECKBOXES_WIDGET,
NEMO_PREFERENCES_SHOW_SELECTION_CHECKBOXES);

bind_builder_bool (builder, nemo_preferences,
NEMO_FILE_MANAGEMENT_PROPERTIES_BOOKMARKS_IN_TO_MENUS_WIDGET,
NEMO_PREFERENCES_SHOW_BOOKMARKS_IN_TO_MENUS);
Expand Down
Loading