Compare commits
No commits in common. "usagebars" and "usagebars-4.20.7" have entirely different histories.
usagebars
...
usagebars-
80 changed files with 35245 additions and 22962 deletions
96
NEWS
96
NEWS
|
|
@ -1,3 +1,99 @@
|
||||||
|
4.20.7 (2026-01-23)
|
||||||
|
======
|
||||||
|
- Prevent crash on unmount (#1778)
|
||||||
|
- Show 'queued' message only for queued jobs (#1755)
|
||||||
|
- Prevent crash on non-local symlinks (#1757)
|
||||||
|
- Fix g_object_unref warning
|
||||||
|
- Fix symlink resolve for desktop files (#1757)
|
||||||
|
- Translation Updates:
|
||||||
|
Albanian, Arabic, Asturian, Basque, Belarusian, Bulgarian, Catalan,
|
||||||
|
Chinese (China), Chinese (Taiwan), Czech, Danish, Dutch, English
|
||||||
|
(United Kingdom), Estonian, Finnish, French, Galician, Georgian,
|
||||||
|
German, Greek, Hungarian, Indonesian, Interlingue, Japanese, Kazakh,
|
||||||
|
Malay, Norwegian Bokmål, Occitan (post 1500), Polish, Portuguese
|
||||||
|
(Brazil), Romanian, Serbian, Slovenian, Spanish, Swedish, Thai,
|
||||||
|
Turkish, Venetian, Vietnamese
|
||||||
|
|
||||||
|
4.20.6 (2025-10-16)
|
||||||
|
======
|
||||||
|
- Prevent GFileMonitor leak for folders (#1724)
|
||||||
|
- Don't use variables for strings in ngettext (#1683)
|
||||||
|
- Fix 'MOUNTED' state on file reload when unmounted
|
||||||
|
- Translation Updates:
|
||||||
|
Albanian, Arabic, Armenian, Armenian (Armenia), Asturian, Basque,
|
||||||
|
Belarusian, Bengali, Bulgarian, Catalan, Chinese (China), Chinese
|
||||||
|
(Hong Kong), Chinese (Taiwan), Czech, Danish, Dutch, Eastern
|
||||||
|
Armenian, English (Australia), English (United Kingdom), Esperanto,
|
||||||
|
Estonian, Finnish, French, Galician, Georgian, German, Greek,
|
||||||
|
Hungarian, Icelandic, Indonesian, Interlingue, Japanese, Kazakh,
|
||||||
|
Latvian, Malay, Norwegian Bokmål, Norwegian Nynorsk, Occitan (post
|
||||||
|
1500), Persian (Iran), Polish, Portuguese (Brazil), Romanian,
|
||||||
|
Serbian, Slovenian, Spanish, Swedish, Thai, Turkish, Venetian,
|
||||||
|
Vietnamese
|
||||||
|
|
||||||
|
4.20.5 (2025-09-14)
|
||||||
|
======
|
||||||
|
- Update shortcut model asynchronously (#1022)
|
||||||
|
- Clear selection before updating selection (#1672)
|
||||||
|
- Translation Updates:
|
||||||
|
Chinese (China), English (United Kingdom), Finnish, Greek, Occitan
|
||||||
|
(post 1500), Polish
|
||||||
|
|
||||||
|
4.20.4 (2025-07-18)
|
||||||
|
======
|
||||||
|
- Improve file add/remove checks for ThunarFolder (#1649)
|
||||||
|
- Properly update view after hidden file rename
|
||||||
|
- Always reload ThunarFiles on change notice (#1650)
|
||||||
|
- Directly notify after file reload (#1650)
|
||||||
|
- Set initial state of "Restore" button (#1663)
|
||||||
|
- Fix quoting when running shell scripts in a terminal (#1661)
|
||||||
|
- Avoid use-after-free in rename dialog when file is changed
|
||||||
|
- Fix a GFile leak in _thunar_io_jobs_rename
|
||||||
|
- Fix use-after-free in thunar_renamer_dialog_response (#1458)
|
||||||
|
- Fix use-after-free on exit with search tabs open (#1593)
|
||||||
|
- Translation Updates:
|
||||||
|
Arabic, Chinese (China), Danish, Esperanto, Galician, Georgian,
|
||||||
|
Greek, Norwegian Bokmål, Polish, Portuguese (Brazil), Spanish,
|
||||||
|
Turkish, Vietnamese
|
||||||
|
|
||||||
|
4.20.3 (2025-05-16)
|
||||||
|
======
|
||||||
|
- Always warn user before permanent deleting files
|
||||||
|
- Fix string leaks when UCAs use a submenu
|
||||||
|
- Fix a potential leak in thunar_action_manager_append_custom_actions
|
||||||
|
- Fix leaks with ThunarMenuX objects
|
||||||
|
- Fix thunarx_menu_get_items leak when multiple UCAs share a submenu
|
||||||
|
- Fix refresh on row-changed in list view (#1584)
|
||||||
|
- Add missing NULL check before unref call
|
||||||
|
- Fix popup position of DnD menu
|
||||||
|
- UCA: Correct PWD for submenu folder items (#1615)
|
||||||
|
- wayland: Fix popup menu not closing (#1592)
|
||||||
|
- Check if file exists before opening its location (#1257)
|
||||||
|
- Prevent popups on wrong window (#1591)
|
||||||
|
- thunar-tpa: Fix libxfce4panel include
|
||||||
|
- Prevent criticals when switching current view (#1344)
|
||||||
|
- Fix crash when destroying folder in list view (#1330) (#1568)
|
||||||
|
- Fix crash in properties dialog (#1585)
|
||||||
|
- Fix invalid filenames when copying to exFAT FS (#1570)
|
||||||
|
- Fix typo in preferences dialog
|
||||||
|
- Hide shortcuts editor when accel map uninitialized (#1488)
|
||||||
|
- Update statusbar when searching (#1560)
|
||||||
|
- Always update statusbar on file changes in list view (#1560)
|
||||||
|
- Fix item activation on double-click in list view (#1567)
|
||||||
|
- Use 'malloc_trim' after search (#1552)
|
||||||
|
- Fix missing dialog for folder errors in list view (#1538)
|
||||||
|
- Fix leak on search update
|
||||||
|
- Fix missing dialog window icon (#1506)
|
||||||
|
- Fix leaks on "cancel search"
|
||||||
|
- Properly check if a file can be trashed (#1554)
|
||||||
|
- Translation Updates:
|
||||||
|
Albanian, Bulgarian, Catalan, Chinese (China), Chinese (Taiwan),
|
||||||
|
Czech, Danish, Dutch, English (United Kingdom), Estonian, Finnish,
|
||||||
|
French, Georgian, German, Greek, Hebrew, Hungarian, Italian,
|
||||||
|
Japanese, Norwegian Bokmål, Occitan (post 1500), Polish, Portuguese,
|
||||||
|
Portuguese (Brazil), Romanian, Serbian, Slovenian, Swedish, Turkish,
|
||||||
|
Venetian, Vietnamese
|
||||||
|
|
||||||
4.20.2 (2025-02-10)
|
4.20.2 (2025-02-10)
|
||||||
======
|
======
|
||||||
- Fix wrong selection after rename in list view (#1415)
|
- Fix wrong selection after rename in list view (#1415)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ dnl ***************************
|
||||||
m4_define([thunarx_verinfo], [0:0:0])
|
m4_define([thunarx_verinfo], [0:0:0])
|
||||||
m4_define([thunarx_version_api], [3])
|
m4_define([thunarx_version_api], [3])
|
||||||
|
|
||||||
XDT_VERSION_INIT([4.20.2])
|
XDT_VERSION_INIT([4.20.7])
|
||||||
|
|
||||||
dnl ***************************
|
dnl ***************************
|
||||||
dnl *** Initialize autoconf ***
|
dnl *** Initialize autoconf ***
|
||||||
|
|
@ -123,7 +123,7 @@ AC_SYS_LARGEFILE()
|
||||||
dnl **********************************
|
dnl **********************************
|
||||||
dnl *** Check for standard headers ***
|
dnl *** Check for standard headers ***
|
||||||
dnl **********************************
|
dnl **********************************
|
||||||
AC_CHECK_HEADERS([ctype.h errno.h fcntl.h grp.h limits.h locale.h memory.h \
|
AC_CHECK_HEADERS([ctype.h errno.h fcntl.h grp.h limits.h locale.h malloc.h memory.h \
|
||||||
paths.h pwd.h sched.h signal.h stdarg.h stdlib.h string.h \
|
paths.h pwd.h sched.h signal.h stdarg.h stdlib.h string.h \
|
||||||
sys/mman.h sys/param.h sys/stat.h sys/time.h sys/types.h \
|
sys/mman.h sys/param.h sys/stat.h sys/time.h sys/types.h \
|
||||||
sys/uio.h sys/wait.h time.h])
|
sys/uio.h sys/wait.h time.h])
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <libxfce4panel/libxfce4panel.h>
|
#include <libxfce4panel/libxfce4panel.h>
|
||||||
#include <libxfce4panel/xfce-panel-macros.h>
|
|
||||||
#include <libxfce4ui/libxfce4ui.h>
|
#include <libxfce4ui/libxfce4ui.h>
|
||||||
#include <libxfce4util/libxfce4util.h>
|
#include <libxfce4util/libxfce4util.h>
|
||||||
#include <thunar-tpa/thunar-tpa-bindings.h>
|
#include <thunar-tpa/thunar-tpa-bindings.h>
|
||||||
|
|
|
||||||
|
|
@ -222,12 +222,13 @@ find_submenu_by_name (gchar *name, GList *items)
|
||||||
if (thunarx_menu_items != NULL)
|
if (thunarx_menu_items != NULL)
|
||||||
{
|
{
|
||||||
ThunarxMenu *submenu = find_submenu_by_name (name, thunarx_menu_items);
|
ThunarxMenu *submenu = find_submenu_by_name (name, thunarx_menu_items);
|
||||||
|
thunarx_menu_item_list_free (thunarx_menu_items);
|
||||||
|
|
||||||
if (submenu != NULL)
|
if (submenu != NULL)
|
||||||
{
|
{
|
||||||
g_free (item_name);
|
g_free (item_name);
|
||||||
return submenu;
|
return submenu;
|
||||||
}
|
}
|
||||||
thunarx_menu_item_list_free (thunarx_menu_items);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_free (item_name);
|
g_free (item_name);
|
||||||
|
|
@ -297,7 +298,11 @@ thunar_uca_provider_get_file_menu_items (ThunarxMenuProvider *menu_provider,
|
||||||
gchar *sub_menu_path = g_strdup (sub_menus_as_array[0]);
|
gchar *sub_menu_path = g_strdup (sub_menus_as_array[0]);
|
||||||
|
|
||||||
for (int j = 1; j <= i; j++)
|
for (int j = 1; j <= i; j++)
|
||||||
sub_menu_path = g_strconcat (sub_menu_path, "/", sub_menus_as_array[j], NULL);
|
{
|
||||||
|
gchar *prev_path = sub_menu_path;
|
||||||
|
sub_menu_path = g_strconcat (prev_path, "/", sub_menus_as_array[j], NULL);
|
||||||
|
g_free (prev_path);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if the full path already exists */
|
/* Check if the full path already exists */
|
||||||
submenu = find_submenu_by_name (sub_menu_path, items);
|
submenu = find_submenu_by_name (sub_menu_path, items);
|
||||||
|
|
@ -381,6 +386,36 @@ thunar_uca_provider_get_file_menu_items (ThunarxMenuProvider *menu_provider,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_folder_quarks_recursive (GList *items)
|
||||||
|
{
|
||||||
|
GList *lp;
|
||||||
|
GList *thunarx_menu_items;
|
||||||
|
|
||||||
|
for (lp = g_list_first (items); lp != NULL; lp = lp->next)
|
||||||
|
{
|
||||||
|
ThunarxMenu *item_menu = NULL;
|
||||||
|
g_object_get (G_OBJECT (lp->data), "menu", &item_menu, NULL);
|
||||||
|
|
||||||
|
if (item_menu != NULL)
|
||||||
|
{
|
||||||
|
/* Some submenu found .. lets walk through it recursively */
|
||||||
|
thunarx_menu_items = thunarx_menu_get_items (item_menu);
|
||||||
|
g_object_unref (item_menu);
|
||||||
|
|
||||||
|
if (thunarx_menu_items != NULL)
|
||||||
|
{
|
||||||
|
set_folder_quarks_recursive (thunarx_menu_items);
|
||||||
|
thunarx_menu_item_list_free (thunarx_menu_items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_object_set_qdata (G_OBJECT (lp->data), thunar_uca_folder_quark, GUINT_TO_POINTER (TRUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
thunar_uca_provider_get_folder_menu_items (ThunarxMenuProvider *menu_provider,
|
thunar_uca_provider_get_folder_menu_items (ThunarxMenuProvider *menu_provider,
|
||||||
GtkWidget *window,
|
GtkWidget *window,
|
||||||
|
|
@ -388,7 +423,6 @@ thunar_uca_provider_get_folder_menu_items (ThunarxMenuProvider *menu_provider,
|
||||||
{
|
{
|
||||||
GList *items;
|
GList *items;
|
||||||
GList files;
|
GList files;
|
||||||
GList *lp;
|
|
||||||
|
|
||||||
/* fake a file list... */
|
/* fake a file list... */
|
||||||
files.data = folder;
|
files.data = folder;
|
||||||
|
|
@ -398,9 +432,8 @@ thunar_uca_provider_get_folder_menu_items (ThunarxMenuProvider *menu_provider,
|
||||||
/* ...and use the get_file_menu_items() method */
|
/* ...and use the get_file_menu_items() method */
|
||||||
items = thunarx_menu_provider_get_file_menu_items (menu_provider, window, &files);
|
items = thunarx_menu_provider_get_file_menu_items (menu_provider, window, &files);
|
||||||
|
|
||||||
/* mark the menu items, so we can properly detect the working directory */
|
/* mark the menu items as folder menu items, so we can properly detect the working directory */
|
||||||
for (lp = items; lp != NULL; lp = lp->next)
|
set_folder_quarks_recursive (items);
|
||||||
g_object_set_qdata (G_OBJECT (lp->data), thunar_uca_folder_quark, GUINT_TO_POINTER (TRUE));
|
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ ie
|
||||||
is
|
is
|
||||||
it
|
it
|
||||||
ja
|
ja
|
||||||
|
ka
|
||||||
kk
|
kk
|
||||||
ko
|
ko
|
||||||
lt
|
lt
|
||||||
|
|
@ -59,6 +60,7 @@ ug
|
||||||
uk
|
uk
|
||||||
ur_PK
|
ur_PK
|
||||||
ur
|
ur
|
||||||
|
vec
|
||||||
vi
|
vi
|
||||||
zh_CN
|
zh_CN
|
||||||
zh_HK
|
zh_HK
|
||||||
|
|
|
||||||
880
po/en_AU.po
880
po/en_AU.po
File diff suppressed because it is too large
Load diff
884
po/en_GB.po
884
po/en_GB.po
File diff suppressed because it is too large
Load diff
862
po/fa_IR.po
862
po/fa_IR.po
File diff suppressed because it is too large
Load diff
879
po/hy_AM.po
879
po/hy_AM.po
File diff suppressed because it is too large
Load diff
1436
po/pt_BR.po
1436
po/pt_BR.po
File diff suppressed because it is too large
Load diff
891
po/zh_CN.po
891
po/zh_CN.po
File diff suppressed because it is too large
Load diff
858
po/zh_HK.po
858
po/zh_HK.po
File diff suppressed because it is too large
Load diff
884
po/zh_TW.po
884
po/zh_TW.po
File diff suppressed because it is too large
Load diff
|
|
@ -80,7 +80,7 @@ main (int argc, char **argv)
|
||||||
application = thunar_application_get ();
|
application = thunar_application_get ();
|
||||||
|
|
||||||
/* use the Thunar icon as default for new windows */
|
/* use the Thunar icon as default for new windows */
|
||||||
gtk_window_set_default_icon_name ("Thunar");
|
gtk_window_set_default_icon_name ("org.xfce.thunar");
|
||||||
|
|
||||||
/* do further processing inside gapplication */
|
/* do further processing inside gapplication */
|
||||||
g_application_run (G_APPLICATION (application), argc, argv);
|
g_application_run (G_APPLICATION (application), argc, argv);
|
||||||
|
|
|
||||||
|
|
@ -1525,7 +1525,17 @@ thunar_action_manager_action_open_location (ThunarActionManager *action_mgr)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
for (lp = action_mgr->files_to_process; lp != NULL; lp = lp->next)
|
for (lp = action_mgr->files_to_process; lp != NULL; lp = lp->next)
|
||||||
gfiles = g_list_prepend (gfiles, thunar_file_get_file (THUNAR_FILE (lp->data)));
|
{
|
||||||
|
ThunarFile *file = lp->data;
|
||||||
|
if (thunar_file_exists (file))
|
||||||
|
gfiles = g_list_prepend (gfiles, thunar_file_get_file (file));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GError *error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_NOENT, _("File does not exist anymore"));
|
||||||
|
thunar_dialogs_show_error (action_mgr->widget, error, _("Failed to open location for \"%s\""), thunar_file_get_display_name (file));
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
thunar_window_open_files_in_location (THUNAR_WINDOW (action_mgr->widget), gfiles);
|
thunar_window_open_files_in_location (THUNAR_WINDOW (action_mgr->widget), gfiles);
|
||||||
|
|
||||||
|
|
@ -1658,7 +1668,7 @@ thunar_action_manager_append_menu_item (ThunarActionManager *action_mgr,
|
||||||
|
|
||||||
case THUNAR_ACTION_MANAGER_ACTION_OPEN_IN_TAB:
|
case THUNAR_ACTION_MANAGER_ACTION_OPEN_IN_TAB:
|
||||||
n = action_mgr->n_files_to_process > 0 ? action_mgr->n_files_to_process : 1;
|
n = action_mgr->n_files_to_process > 0 ? action_mgr->n_files_to_process : 1;
|
||||||
label_text = g_strdup_printf (ngettext (action_entry->menu_item_label_text, "Open in %d New _Tabs", n), n);
|
label_text = g_strdup_printf (ngettext ("Open in new _Tab", "Open in %d New _Tabs", n), n);
|
||||||
tooltip_text = g_strdup_printf (ngettext ("Open the selected directory in new tab",
|
tooltip_text = g_strdup_printf (ngettext ("Open the selected directory in new tab",
|
||||||
"Open the selected directories in %d new tabs", n),
|
"Open the selected directories in %d new tabs", n),
|
||||||
n);
|
n);
|
||||||
|
|
@ -1669,7 +1679,7 @@ thunar_action_manager_append_menu_item (ThunarActionManager *action_mgr,
|
||||||
|
|
||||||
case THUNAR_ACTION_MANAGER_ACTION_OPEN_IN_WINDOW:
|
case THUNAR_ACTION_MANAGER_ACTION_OPEN_IN_WINDOW:
|
||||||
n = action_mgr->n_files_to_process > 0 ? action_mgr->n_files_to_process : 1;
|
n = action_mgr->n_files_to_process > 0 ? action_mgr->n_files_to_process : 1;
|
||||||
label_text = g_strdup_printf (ngettext (action_entry->menu_item_label_text, "Open in %d New _Windows", n), n);
|
label_text = g_strdup_printf (ngettext ("Open in new _Window", "Open in %d New _Windows", n), n);
|
||||||
tooltip_text = g_strdup_printf (ngettext ("Open the selected directory in new window",
|
tooltip_text = g_strdup_printf (ngettext ("Open the selected directory in new window",
|
||||||
"Open the selected directories in %d new windows", n),
|
"Open the selected directories in %d new windows", n),
|
||||||
n);
|
n);
|
||||||
|
|
@ -1707,7 +1717,7 @@ thunar_action_manager_append_menu_item (ThunarActionManager *action_mgr,
|
||||||
if (!show_item && !force)
|
if (!show_item && !force)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
label_text = ngettext (action_entry->menu_item_label_text, "Ma_ke Links", action_mgr->n_files_to_process);
|
label_text = ngettext ("Ma_ke Link", "Ma_ke Links", action_mgr->n_files_to_process);
|
||||||
tooltip_text = ngettext ("Create a symbolic link for the selected file",
|
tooltip_text = ngettext ("Create a symbolic link for the selected file",
|
||||||
"Create a symbolic link for each selected file", action_mgr->n_files_to_process);
|
"Create a symbolic link for each selected file", action_mgr->n_files_to_process);
|
||||||
item = xfce_gtk_menu_item_new (label_text, tooltip_text, action_entry->accel_path, action_entry->callback,
|
item = xfce_gtk_menu_item_new (label_text, tooltip_text, action_entry->accel_path, action_entry->callback,
|
||||||
|
|
@ -2391,6 +2401,10 @@ thunar_action_manager_append_custom_actions (ThunarActionManager *action_mgr,
|
||||||
_thunar_return_val_if_fail (THUNAR_IS_ACTION_MANAGER (action_mgr), FALSE);
|
_thunar_return_val_if_fail (THUNAR_IS_ACTION_MANAGER (action_mgr), FALSE);
|
||||||
_thunar_return_val_if_fail (GTK_IS_MENU (menu), FALSE);
|
_thunar_return_val_if_fail (GTK_IS_MENU (menu), FALSE);
|
||||||
|
|
||||||
|
/* This may occur when the thunar-window is build */
|
||||||
|
if (G_UNLIKELY (action_mgr->files_to_process == NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* determine the toplevel window we belong to */
|
/* determine the toplevel window we belong to */
|
||||||
window = gtk_widget_get_toplevel (action_mgr->widget);
|
window = gtk_widget_get_toplevel (action_mgr->widget);
|
||||||
|
|
||||||
|
|
@ -2402,10 +2416,6 @@ thunar_action_manager_append_custom_actions (ThunarActionManager *action_mgr,
|
||||||
if (G_UNLIKELY (providers == NULL))
|
if (G_UNLIKELY (providers == NULL))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* This may occur when the thunar-window is build */
|
|
||||||
if (G_UNLIKELY (action_mgr->files_to_process == NULL))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* load the menu items offered by the menu providers */
|
/* load the menu items offered by the menu providers */
|
||||||
for (lp_provider = providers; lp_provider != NULL; lp_provider = lp_provider->next)
|
for (lp_provider = providers; lp_provider != NULL; lp_provider = lp_provider->next)
|
||||||
{
|
{
|
||||||
|
|
@ -2666,7 +2676,7 @@ thunar_action_manager_action_trash_delete (ThunarActionManager *action_mgr)
|
||||||
/* when shift modifier is pressed, we delete (as well via context menu) */
|
/* when shift modifier is pressed, we delete (as well via context menu) */
|
||||||
if (gtk_get_current_event_state (&event_state) && (event_state & GDK_SHIFT_MASK) != 0)
|
if (gtk_get_current_event_state (&event_state) && (event_state & GDK_SHIFT_MASK) != 0)
|
||||||
thunar_action_manager_action_delete (action_mgr);
|
thunar_action_manager_action_delete (action_mgr);
|
||||||
else if (thunar_g_vfs_is_uri_scheme_supported ("trash") && !thunar_file_is_trashed (action_mgr->current_directory))
|
else if (thunar_action_manager_show_trash (action_mgr))
|
||||||
thunar_action_manager_action_move_to_trash (action_mgr);
|
thunar_action_manager_action_move_to_trash (action_mgr);
|
||||||
else
|
else
|
||||||
thunar_action_manager_action_delete (action_mgr);
|
thunar_action_manager_action_delete (action_mgr);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@
|
||||||
#ifdef HAVE_ERRNO_H
|
#ifdef HAVE_ERRNO_H
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_MALLOC_H
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_MEMORY_H
|
#ifdef HAVE_MEMORY_H
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2438,7 +2441,7 @@ unlink_stub (GList *source_path_list,
|
||||||
* @parent : a #GdkScreen, a #GtkWidget or %NULL.
|
* @parent : a #GdkScreen, a #GtkWidget or %NULL.
|
||||||
* @file_list : the list of #ThunarFile<!---->s that should be deleted.
|
* @file_list : the list of #ThunarFile<!---->s that should be deleted.
|
||||||
* @permanently : whether to unlink the files permanently.
|
* @permanently : whether to unlink the files permanently.
|
||||||
* @warn : whether to warn the user if deleting permanently.
|
* @warn : whether to warn the user if moving files to trash.
|
||||||
* @log_mode : log mode
|
* @log_mode : log mode
|
||||||
*
|
*
|
||||||
* Deletes all files in the @file_list and takes care of all user interaction.
|
* Deletes all files in the @file_list and takes care of all user interaction.
|
||||||
|
|
@ -2459,7 +2462,7 @@ thunar_application_unlink_files (ThunarApplication *application,
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GtkWidget *message_area;
|
GtkWidget *message_area;
|
||||||
GtkWindow *window;
|
GtkWindow *window = NULL;
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
GList *path_list = NULL;
|
GList *path_list = NULL;
|
||||||
GList *lp;
|
GList *lp;
|
||||||
|
|
@ -2489,7 +2492,7 @@ thunar_application_unlink_files (ThunarApplication *application,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* ask the user to confirm if deleting permanently */
|
/* ask the user to confirm if deleting permanently */
|
||||||
if (G_UNLIKELY (permanently) && warn)
|
if (G_UNLIKELY (permanently))
|
||||||
{
|
{
|
||||||
/* parse the parent pointer */
|
/* parse the parent pointer */
|
||||||
screen = thunar_util_parse_parent (parent, &window);
|
screen = thunar_util_parse_parent (parent, &window);
|
||||||
|
|
@ -2555,12 +2558,6 @@ thunar_application_unlink_files (ThunarApplication *application,
|
||||||
else
|
else
|
||||||
operation_canceled = TRUE;
|
operation_canceled = TRUE;
|
||||||
}
|
}
|
||||||
else if (G_UNLIKELY (permanently))
|
|
||||||
{
|
|
||||||
thunar_application_launch (application, parent, "edit-delete",
|
|
||||||
_("Deleting files..."), unlink_stub,
|
|
||||||
path_list, path_list, TRUE, FALSE, log_mode, NULL);
|
|
||||||
}
|
|
||||||
else if (G_LIKELY (!permanently) && warn)
|
else if (G_LIKELY (!permanently) && warn)
|
||||||
{
|
{
|
||||||
/* parse the parent pointer */
|
/* parse the parent pointer */
|
||||||
|
|
@ -2760,7 +2757,7 @@ thunar_application_empty_trash (ThunarApplication *application,
|
||||||
const gchar *startup_id)
|
const gchar *startup_id)
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GtkWindow *window;
|
GtkWindow *window = NULL;
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
GList file_list;
|
GList file_list;
|
||||||
gint response;
|
gint response;
|
||||||
|
|
@ -2908,3 +2905,28 @@ thunar_application_get_thumbnail_cache (ThunarApplication *application)
|
||||||
|
|
||||||
return g_object_ref (application->thumbnail_cache);
|
return g_object_ref (application->thumbnail_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
thunar_application_malloc_trim_idle (gpointer application_ptr)
|
||||||
|
{
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
/* Workaround to make the kernel reclaim memory which is not used by Thunar anymore. */
|
||||||
|
/* When using glibc, after releasing bigger memory chunks it seems to be required to call that 'garbage collector'. */
|
||||||
|
/* More information here: https://gitlab.xfce.org/xfce/thunar/-/issues/1552#note_101990 */
|
||||||
|
malloc_trim (0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
thunar_application_malloc_trim_on_idle (ThunarApplication *application)
|
||||||
|
{
|
||||||
|
_thunar_return_if_fail (THUNAR_IS_APPLICATION (application));
|
||||||
|
|
||||||
|
g_idle_add (thunar_application_malloc_trim_idle, application);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,9 @@ thunar_application_get_thumbnail_cache (ThunarApplication *application);
|
||||||
gboolean
|
gboolean
|
||||||
thunar_application_accel_map_init (ThunarApplication *application);
|
thunar_application_accel_map_init (ThunarApplication *application);
|
||||||
|
|
||||||
|
void
|
||||||
|
thunar_application_malloc_trim_on_idle (ThunarApplication *application);
|
||||||
|
|
||||||
G_END_DECLS;
|
G_END_DECLS;
|
||||||
|
|
||||||
#endif /* !__THUNAR_APPLICATION_H__ */
|
#endif /* !__THUNAR_APPLICATION_H__ */
|
||||||
|
|
|
||||||
|
|
@ -1238,6 +1238,9 @@ thunar_details_view_row_activated (GtkTreeView *tree_view,
|
||||||
|
|
||||||
_thunar_return_if_fail (THUNAR_IS_DETAILS_VIEW (details_view));
|
_thunar_return_if_fail (THUNAR_IS_DETAILS_VIEW (details_view));
|
||||||
|
|
||||||
|
/* ensure that the path is selected on double-click events */
|
||||||
|
thunar_details_view_select_path (THUNAR_STANDARD_VIEW (details_view), path);
|
||||||
|
|
||||||
window = gtk_widget_get_toplevel (GTK_WIDGET (details_view));
|
window = gtk_widget_get_toplevel (GTK_WIDGET (details_view));
|
||||||
action_mgr = thunar_window_get_action_manager (THUNAR_WINDOW (window));
|
action_mgr = thunar_window_get_action_manager (THUNAR_WINDOW (window));
|
||||||
thunar_action_manager_activate_selected_files (action_mgr, THUNAR_ACTION_MANAGER_CHANGE_DIRECTORY, NULL);
|
thunar_action_manager_activate_selected_files (action_mgr, THUNAR_ACTION_MANAGER_CHANGE_DIRECTORY, NULL);
|
||||||
|
|
@ -1309,7 +1312,7 @@ thunar_details_view_row_changed (GtkTreeView *tree_view,
|
||||||
{
|
{
|
||||||
_thunar_return_if_fail (THUNAR_IS_DETAILS_VIEW (details_view));
|
_thunar_return_if_fail (THUNAR_IS_DETAILS_VIEW (details_view));
|
||||||
|
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (details_view));
|
gtk_widget_queue_draw (GTK_WIDGET (details_view->tree_view));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ thunar_dialogs_show_create (gpointer parent,
|
||||||
const gchar *title)
|
const gchar *title)
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GtkWindow *window;
|
GtkWindow *window = NULL;
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
gchar *name = NULL;
|
gchar *name = NULL;
|
||||||
|
|
@ -225,7 +225,7 @@ thunar_dialogs_show_rename_file (gpointer parent,
|
||||||
ThunarIconFactory *icon_factory;
|
ThunarIconFactory *icon_factory;
|
||||||
GtkIconTheme *icon_theme;
|
GtkIconTheme *icon_theme;
|
||||||
gint scale_factor;
|
gint scale_factor;
|
||||||
const gchar *filename;
|
gchar *filename;
|
||||||
const gchar *text;
|
const gchar *text;
|
||||||
ThunarJob *job = NULL;
|
ThunarJob *job = NULL;
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
|
|
@ -234,7 +234,7 @@ thunar_dialogs_show_rename_file (gpointer parent,
|
||||||
GtkWidget *grid;
|
GtkWidget *grid;
|
||||||
XfceFilenameInput *filename_input;
|
XfceFilenameInput *filename_input;
|
||||||
GtkEntry *filename_input_entry;
|
GtkEntry *filename_input_entry;
|
||||||
GtkWindow *window;
|
GtkWindow *window = NULL;
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
GdkPixbuf *icon;
|
GdkPixbuf *icon;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
|
|
@ -250,8 +250,9 @@ thunar_dialogs_show_rename_file (gpointer parent,
|
||||||
/* parse the parent window and screen */
|
/* parse the parent window and screen */
|
||||||
screen = thunar_util_parse_parent (parent, &window);
|
screen = thunar_util_parse_parent (parent, &window);
|
||||||
|
|
||||||
/* get the filename of the file */
|
/* Get the filename of the file. We create our own copy of the string because the file
|
||||||
filename = thunar_file_get_basename (file);
|
* can be modified by another process while the rename is in progress (issue #1639). */
|
||||||
|
filename = g_strdup (thunar_file_get_basename (file));
|
||||||
|
|
||||||
/* create a new dialog window */
|
/* create a new dialog window */
|
||||||
title = g_strdup_printf (_("Rename \"%s\""), filename);
|
title = g_strdup_printf (_("Rename \"%s\""), filename);
|
||||||
|
|
@ -385,6 +386,8 @@ thunar_dialogs_show_rename_file (gpointer parent,
|
||||||
gtk_widget_destroy (dialog);
|
gtk_widget_destroy (dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (filename);
|
||||||
|
|
||||||
return job;
|
return job;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -482,7 +485,7 @@ thunar_dialogs_show_error (gpointer parent,
|
||||||
...)
|
...)
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GtkWindow *window;
|
GtkWindow *window = NULL;
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
va_list args;
|
va_list args;
|
||||||
gchar *primary_text;
|
gchar *primary_text;
|
||||||
|
|
@ -1041,7 +1044,7 @@ thunar_dialogs_show_insecure_program (gpointer parent,
|
||||||
const gchar *command)
|
const gchar *command)
|
||||||
{
|
{
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
GtkWindow *window;
|
GtkWindow *window = NULL;
|
||||||
gint response;
|
gint response;
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GString *secondary;
|
GString *secondary;
|
||||||
|
|
@ -1236,7 +1239,7 @@ thunar_dialog_ask_execute (const ThunarFile *file,
|
||||||
gboolean single_file)
|
gboolean single_file)
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GtkWindow *window;
|
GtkWindow *window = NULL;
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
gint response;
|
gint response;
|
||||||
gchar *dialog_text;
|
gchar *dialog_text;
|
||||||
|
|
|
||||||
|
|
@ -230,8 +230,9 @@ struct _ThunarFile
|
||||||
/* flags for thumbnail state etc */
|
/* flags for thumbnail state etc */
|
||||||
ThunarFileFlags flags;
|
ThunarFileFlags flags;
|
||||||
|
|
||||||
/* event source id used to rate-limit file-changed signals */
|
/* event source id and variable to rate-limit file-changed signals */
|
||||||
guint signal_changed_source_id;
|
guint signal_changed_source_id;
|
||||||
|
gboolean signal_change_requested;
|
||||||
|
|
||||||
/* Number of files in this directory (only used if this #Thunarfile is a directory) */
|
/* Number of files in this directory (only used if this #Thunarfile is a directory) */
|
||||||
/* Note that this feature was added into #ThunarFile on purpose, because having inside #ThunarFolder caused lag when
|
/* Note that this feature was added into #ThunarFile on purpose, because having inside #ThunarFolder caused lag when
|
||||||
|
|
@ -1204,6 +1205,7 @@ thunar_file_load (ThunarFile *file,
|
||||||
{
|
{
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
GFileInfo *info = NULL;
|
GFileInfo *info = NULL;
|
||||||
|
gboolean mounted = TRUE;
|
||||||
|
|
||||||
_thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
|
_thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
|
||||||
_thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
_thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
@ -1221,12 +1223,12 @@ thunar_file_load (ThunarFile *file,
|
||||||
G_FILE_QUERY_INFO_NONE,
|
G_FILE_QUERY_INFO_NONE,
|
||||||
cancellable, &err);
|
cancellable, &err);
|
||||||
|
|
||||||
/* update the mounted info */
|
/* check if mounted (but do not update the file until after it has been cleared) */
|
||||||
if (err != NULL
|
if (err != NULL
|
||||||
&& err->domain == G_IO_ERROR
|
&& err->domain == G_IO_ERROR
|
||||||
&& err->code == G_IO_ERROR_NOT_MOUNTED)
|
&& err->code == G_IO_ERROR_NOT_MOUNTED)
|
||||||
{
|
{
|
||||||
FLAG_UNSET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
|
mounted = FALSE;
|
||||||
g_clear_error (&err);
|
g_clear_error (&err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1254,6 +1256,10 @@ thunar_file_load (ThunarFile *file,
|
||||||
/* update the file from the information */
|
/* update the file from the information */
|
||||||
thunar_file_info_reload (file, cancellable);
|
thunar_file_info_reload (file, cancellable);
|
||||||
|
|
||||||
|
/* update the mounted info */
|
||||||
|
if (mounted == FALSE)
|
||||||
|
FLAG_UNSET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
|
||||||
|
|
||||||
/* (re)insert the file into the cache */
|
/* (re)insert the file into the cache */
|
||||||
if (file->kind != G_FILE_TYPE_UNKNOWN)
|
if (file->kind != G_FILE_TYPE_UNKNOWN)
|
||||||
{
|
{
|
||||||
|
|
@ -1741,11 +1747,15 @@ thunar_file_execute (ThunarFile *file,
|
||||||
{
|
{
|
||||||
/* fake the Exec line */
|
/* fake the Exec line */
|
||||||
escaped_location = g_shell_quote (location);
|
escaped_location = g_shell_quote (location);
|
||||||
if (in_terminal)
|
|
||||||
exec = g_strconcat ("exo-open --launch TerminalEmulator ", escaped_location, " %F", NULL);
|
|
||||||
else
|
|
||||||
exec = g_strconcat (escaped_location, " %F", NULL);
|
exec = g_strconcat (escaped_location, " %F", NULL);
|
||||||
command = xfce_expand_desktop_entry_field_codes (exec, uri_list, NULL, NULL, NULL, FALSE);
|
command = xfce_expand_desktop_entry_field_codes (exec, uri_list, NULL, NULL, NULL, FALSE);
|
||||||
|
if (in_terminal)
|
||||||
|
{
|
||||||
|
gchar *escaped = g_shell_quote (command);
|
||||||
|
g_free (command);
|
||||||
|
command = g_strconcat ("exo-open --launch TerminalEmulator ", escaped, NULL);
|
||||||
|
g_free (escaped);
|
||||||
|
}
|
||||||
result = g_shell_parse_argv (command, NULL, &argv, error);
|
result = g_shell_parse_argv (command, NULL, &argv, error);
|
||||||
g_free (escaped_location);
|
g_free (escaped_location);
|
||||||
g_free (exec);
|
g_free (exec);
|
||||||
|
|
@ -2107,6 +2117,7 @@ thunar_file_accepts_drop (ThunarFile *file,
|
||||||
{
|
{
|
||||||
/* default to copy and get outta here */
|
/* default to copy and get outta here */
|
||||||
suggested_action = GDK_ACTION_COPY;
|
suggested_action = GDK_ACTION_COPY;
|
||||||
|
if (parent_thunar_file != NULL)
|
||||||
g_object_unref (parent_thunar_file);
|
g_object_unref (parent_thunar_file);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -5413,24 +5424,23 @@ thunar_file_reset_thumbnail (ThunarFile *file,
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
thunar_file_changed_signal_emit (gpointer data)
|
thunar_file_changed_signal_timeout (gpointer data)
|
||||||
{
|
{
|
||||||
/* emit the changed signal on thunarx level */
|
ThunarFile *file = THUNAR_FILE (data);
|
||||||
thunarx_file_info_changed (THUNARX_FILE_INFO (data));
|
_thunar_return_val_if_fail (THUNAR_IS_FILE (file), G_SOURCE_REMOVE);
|
||||||
|
|
||||||
|
/* emit the changed signal on thunarx level, if required */
|
||||||
|
if (file->signal_change_requested)
|
||||||
|
thunarx_file_info_changed (THUNARX_FILE_INFO (file));
|
||||||
|
|
||||||
|
file->signal_change_requested = FALSE;
|
||||||
|
file->signal_changed_source_id = 0;
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
thunar_file_changed_signal_destroy (gpointer data)
|
|
||||||
{
|
|
||||||
THUNAR_FILE (data)->signal_changed_source_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* thunar_file_changed:
|
* thunar_file_changed:
|
||||||
* @file : a #ThunarFile instance.
|
* @file : a #ThunarFile instance.
|
||||||
|
|
@ -5441,10 +5451,17 @@ thunar_file_changed_signal_destroy (gpointer data)
|
||||||
void
|
void
|
||||||
thunar_file_changed (ThunarFile *file)
|
thunar_file_changed (ThunarFile *file)
|
||||||
{
|
{
|
||||||
if (file->signal_changed_source_id == 0)
|
/* in case a timeout is running, the change-signal will be delayed (performance) */
|
||||||
|
if (file->signal_changed_source_id != 0)
|
||||||
{
|
{
|
||||||
file->signal_changed_source_id = g_timeout_add_full (G_PRIORITY_DEFAULT, FILE_CHANGED_SIGNAL_RATE_LIMIT,
|
file->signal_change_requested = TRUE;
|
||||||
thunar_file_changed_signal_emit,
|
return;
|
||||||
file, thunar_file_changed_signal_destroy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* handle the first request directly */
|
||||||
|
thunarx_file_info_changed (THUNARX_FILE_INFO (file));
|
||||||
|
|
||||||
|
/* start a timer to throttle consecutive calls */
|
||||||
|
file->signal_changed_source_id = g_timeout_add (FILE_CHANGED_SIGNAL_RATE_LIMIT,
|
||||||
|
thunar_file_changed_signal_timeout, file);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,10 +149,10 @@ struct _ThunarFolder
|
||||||
/* Files which were changed recently. The key is a ThunarFile; value is NULL (unimportant)*/
|
/* Files which were changed recently. The key is a ThunarFile; value is NULL (unimportant)*/
|
||||||
GHashTable *changed_files_map;
|
GHashTable *changed_files_map;
|
||||||
|
|
||||||
/* Files which were changed recently. The key is a ThunarFile; value is NULL (unimportant)*/
|
/* Files which were added recently. The key is a ThunarFile; value is NULL (unimportant)*/
|
||||||
GHashTable *added_files_map;
|
GHashTable *added_files_map;
|
||||||
|
|
||||||
/* Files which were changed recently. The key is a ThunarFile; value is NULL (unimportant)*/
|
/* Files which were removed recently. The key is a ThunarFile; value is NULL (unimportant)*/
|
||||||
GHashTable *removed_files_map;
|
GHashTable *removed_files_map;
|
||||||
|
|
||||||
/* Files inside this folder. The key is a ThunarFile; value is NULL (unimportant)*/
|
/* Files inside this folder. The key is a ThunarFile; value is NULL (unimportant)*/
|
||||||
|
|
@ -409,7 +409,10 @@ thunar_folder_finalize (GObject *object)
|
||||||
g_source_remove (folder->files_update_timeout_source_id);
|
g_source_remove (folder->files_update_timeout_source_id);
|
||||||
|
|
||||||
if (folder->monitor != NULL)
|
if (folder->monitor != NULL)
|
||||||
|
{
|
||||||
g_signal_handlers_disconnect_by_data (folder->monitor, folder);
|
g_signal_handlers_disconnect_by_data (folder->monitor, folder);
|
||||||
|
g_object_unref (folder->monitor);
|
||||||
|
}
|
||||||
|
|
||||||
if (folder->corresponding_file)
|
if (folder->corresponding_file)
|
||||||
{
|
{
|
||||||
|
|
@ -594,17 +597,25 @@ _thunar_folder_files_update_timeout (gpointer data)
|
||||||
g_hash_table_remove_all (files);
|
g_hash_table_remove_all (files);
|
||||||
g_hash_table_remove_all (folder->added_files_map);
|
g_hash_table_remove_all (folder->added_files_map);
|
||||||
|
|
||||||
/* send a 'changed' signal for all files which changed */
|
/* reload files which were changed and send a 'changed' signal for them, if required */
|
||||||
g_hash_table_iter_init (&iter, folder->changed_files_map);
|
g_hash_table_iter_init (&iter, folder->changed_files_map);
|
||||||
while (g_hash_table_iter_next (&iter, &key, NULL))
|
while (g_hash_table_iter_next (&iter, &key, NULL))
|
||||||
{
|
{
|
||||||
|
/* block 'changed' signals for this file until reload is done, in order to prevent recursion */
|
||||||
|
g_signal_handlers_block_by_func (G_OBJECT (key), G_CALLBACK (thunar_folder_file_changed), folder);
|
||||||
|
thunar_file_reload (THUNAR_FILE (key));
|
||||||
|
g_signal_handlers_unblock_by_func (G_OBJECT (key), G_CALLBACK (thunar_folder_file_changed), folder);
|
||||||
|
|
||||||
|
/* only send the 'changed' signal for files which are already part of this folder */
|
||||||
if (!g_hash_table_contains (folder->files_map, key))
|
if (!g_hash_table_contains (folder->files_map, key))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
g_hash_table_add (files, g_object_ref (key));
|
g_hash_table_add (files, g_object_ref (key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_hash_table_size (files) > 0)
|
||||||
g_signal_emit (G_OBJECT (folder), folder_signals[FILES_CHANGED], 0, files);
|
g_signal_emit (G_OBJECT (folder), folder_signals[FILES_CHANGED], 0, files);
|
||||||
|
|
||||||
g_hash_table_destroy (files);
|
g_hash_table_destroy (files);
|
||||||
g_hash_table_remove_all (folder->changed_files_map);
|
g_hash_table_remove_all (folder->changed_files_map);
|
||||||
|
|
||||||
|
|
@ -645,6 +656,10 @@ thunar_folder_add_file (ThunarFolder *folder,
|
||||||
if (g_hash_table_remove (folder->removed_files_map, file))
|
if (g_hash_table_remove (folder->removed_files_map, file))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Do nothing if we already have the file in our internal map */
|
||||||
|
if (g_hash_table_lookup (folder->files_map, file) != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
g_hash_table_add (folder->added_files_map, g_object_ref (file));
|
g_hash_table_add (folder->added_files_map, g_object_ref (file));
|
||||||
|
|
||||||
if (folder->files_update_timeout_source_id == 0)
|
if (folder->files_update_timeout_source_id == 0)
|
||||||
|
|
@ -661,6 +676,10 @@ thunar_folder_remove_file (ThunarFolder *folder,
|
||||||
if (g_hash_table_remove (folder->added_files_map, file))
|
if (g_hash_table_remove (folder->added_files_map, file))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Do nothing if we dont have the file yet in our internal map */
|
||||||
|
if (g_hash_table_lookup (folder->files_map, file) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
g_hash_table_add (folder->removed_files_map, g_object_ref (file));
|
g_hash_table_add (folder->removed_files_map, g_object_ref (file));
|
||||||
|
|
||||||
if (folder->files_update_timeout_source_id == 0)
|
if (folder->files_update_timeout_source_id == 0)
|
||||||
|
|
@ -1068,16 +1087,12 @@ thunar_folder_monitor (GFileMonitor *monitor,
|
||||||
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
|
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
|
||||||
if (event_file_thunar != NULL)
|
if (event_file_thunar != NULL)
|
||||||
{
|
{
|
||||||
/* If we have that file in our internal map, reload it and send a file-changed signal */
|
/* this will trigger a reload if the file and send a 'file-changed' signal */
|
||||||
if (g_hash_table_lookup (folder->files_map, event_file_thunar) != NULL)
|
|
||||||
{
|
|
||||||
thunar_folder_file_changed (folder, event_file_thunar);
|
thunar_folder_file_changed (folder, event_file_thunar);
|
||||||
|
|
||||||
#if DEBUG_FILE_CHANGES
|
#if DEBUG_FILE_CHANGES
|
||||||
thunar_file_infos_equal (event_file_thunar, event_file);
|
thunar_file_infos_equal (event_file_thunar, event_file);
|
||||||
#endif
|
#endif
|
||||||
thunar_file_reload (event_file_thunar);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -194,9 +194,91 @@ thunar_g_file_new_for_bookmarks (void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* internal version, for recursive execution. Uses a lookup table to detect loops */
|
||||||
|
static GFile *
|
||||||
|
_thunar_g_file_resolve_symlink_internal (GFile *file, GHashTable *lookup_table)
|
||||||
|
{
|
||||||
|
g_autoptr (GHashTable) lookup_history = NULL;
|
||||||
|
g_autoptr (GFileInfo) info = NULL;
|
||||||
|
|
||||||
|
_thunar_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||||
|
|
||||||
|
if (lookup_table == NULL)
|
||||||
|
lookup_history = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||||
|
else
|
||||||
|
lookup_history = g_hash_table_ref (lookup_table);
|
||||||
|
|
||||||
|
/* Resolve the link target recursively, until the target we found is not a symlink */
|
||||||
|
char *file_uri = g_file_get_uri (file);
|
||||||
|
|
||||||
|
if (file_uri == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Detect loops: if the file already was seen, return NULL */
|
||||||
|
if (g_hash_table_contains (lookup_history, file_uri))
|
||||||
|
{
|
||||||
|
g_info ("Symlink loop detected - resolve symlink aborted");
|
||||||
|
g_free (file_uri);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
g_hash_table_add (lookup_history, file_uri);
|
||||||
|
|
||||||
|
info = g_file_query_info (file,
|
||||||
|
G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET "," G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK,
|
||||||
|
G_FILE_QUERY_INFO_NONE, NULL, NULL);
|
||||||
|
if (info == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Not a symlink: return that file */
|
||||||
|
if (!g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK))
|
||||||
|
return g_object_ref (file);
|
||||||
|
|
||||||
|
/* It's a symlink, get the target */
|
||||||
|
const char *target_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
|
||||||
|
if (target_path == NULL)
|
||||||
|
{
|
||||||
|
g_info ("Failed to read target path from symlink: %s", g_file_get_path (file));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The target is as well a symlink ... so lets use recursion */
|
||||||
|
if (g_path_is_absolute (target_path))
|
||||||
|
{
|
||||||
|
g_autoptr (GFile) target = g_file_new_for_path (target_path);
|
||||||
|
return _thunar_g_file_resolve_symlink_internal (target, lookup_history);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Resolve a possible relative path */
|
||||||
|
g_autoptr (GFile) target = NULL;
|
||||||
|
g_autoptr (GFile) parent = NULL;
|
||||||
|
g_autoptr (GFile) parent_resolved = NULL;
|
||||||
|
|
||||||
|
parent = g_file_get_parent (file);
|
||||||
|
if (parent == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Resolve parent, if required */
|
||||||
|
parent_resolved = _thunar_g_file_resolve_symlink_internal (parent, lookup_history);
|
||||||
|
|
||||||
|
if (parent_resolved == NULL)
|
||||||
|
{
|
||||||
|
g_info ("Failed to resolve parent of symlink");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = g_file_resolve_relative_path (parent_resolved, target_path);
|
||||||
|
|
||||||
|
/* Sicne as well that file might be a symlink, we need to use recursion */
|
||||||
|
return _thunar_g_file_resolve_symlink_internal (target, lookup_history);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* thunar_g_file_resolve_symlink:
|
* thunar_g_file_resolve_symlink:
|
||||||
* @file : a #GFile.
|
* @file : a #GFile
|
||||||
*
|
*
|
||||||
* Returns the resolved symlink target of @file as a new #GFile.
|
* Returns the resolved symlink target of @file as a new #GFile.
|
||||||
* If @file is not a symlink, @file will just be returned
|
* If @file is not a symlink, @file will just be returned
|
||||||
|
|
@ -206,27 +288,7 @@ thunar_g_file_new_for_bookmarks (void)
|
||||||
GFile *
|
GFile *
|
||||||
thunar_g_file_resolve_symlink (GFile *file)
|
thunar_g_file_resolve_symlink (GFile *file)
|
||||||
{
|
{
|
||||||
gchar *basename;
|
return _thunar_g_file_resolve_symlink_internal (file, NULL);
|
||||||
GFile *parent = NULL;
|
|
||||||
GFile *target = NULL;
|
|
||||||
|
|
||||||
_thunar_return_val_if_fail (G_IS_FILE (file), NULL);
|
|
||||||
|
|
||||||
parent = g_file_get_parent (file);
|
|
||||||
if (parent == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
basename = g_file_get_basename (file);
|
|
||||||
if (basename == NULL)
|
|
||||||
{
|
|
||||||
g_object_unref (parent);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
target = g_file_resolve_relative_path (parent, basename);
|
|
||||||
g_object_unref (parent);
|
|
||||||
g_free (basename);
|
|
||||||
return target;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1760,10 +1822,12 @@ thunar_g_file_get_content_type (GFile *gfile)
|
||||||
g_object_unref (info);
|
g_object_unref (info);
|
||||||
info = NULL;
|
info = NULL;
|
||||||
if (link_target != NULL)
|
if (link_target != NULL)
|
||||||
|
{
|
||||||
info = thunar_g_file_get_content_type_querry_info (link_target, err);
|
info = thunar_g_file_get_content_type_querry_info (link_target, err);
|
||||||
g_object_unref (link_target);
|
g_object_unref (link_target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (G_LIKELY (info != NULL))
|
if (G_LIKELY (info != NULL))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,8 @@ thunar_gtk_menu_thunarx_menu_item_new (GObject *thunarx_menu_item,
|
||||||
g_free (icon_name);
|
g_free (icon_name);
|
||||||
if (icon != NULL)
|
if (icon != NULL)
|
||||||
g_object_unref (icon);
|
g_object_unref (icon);
|
||||||
|
if (thunarx_menu != NULL)
|
||||||
|
g_object_unref (thunarx_menu);
|
||||||
|
|
||||||
return gtk_menu_item;
|
return gtk_menu_item;
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +189,7 @@ thunar_gtk_menu_clean (GtkMenu *menu)
|
||||||
* thunar_gtk_menu_run:
|
* thunar_gtk_menu_run:
|
||||||
* @menu : a #GtkMenu.
|
* @menu : a #GtkMenu.
|
||||||
*
|
*
|
||||||
* Conveniance wrapper for thunar_gtk_menu_run_at_event_pointer, to run a menu for the current event
|
* Convenience wrapper for thunar_gtk_menu_run_at_event() to run a menu for the current event
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
thunar_gtk_menu_run (GtkMenu *menu)
|
thunar_gtk_menu_run (GtkMenu *menu)
|
||||||
|
|
@ -207,6 +209,51 @@ thunar_gtk_menu_run (GtkMenu *menu)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
thunar_gtk_menu_popup_at_pointer (GtkMenu *menu,
|
||||||
|
GdkEvent *event)
|
||||||
|
{
|
||||||
|
GdkWindow *window;
|
||||||
|
GdkWindow *toplevel = NULL;
|
||||||
|
GdkDevice *device;
|
||||||
|
GdkRectangle rect = { 0, 0, 1, 1 };
|
||||||
|
|
||||||
|
/* fallback if event not set or event not holding a GdkSeat */
|
||||||
|
if (event == NULL || gdk_event_get_seat (event) == NULL)
|
||||||
|
{
|
||||||
|
gtk_menu_popup_at_pointer (menu, event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create popup rect */
|
||||||
|
window = gdk_event_get_window (event);
|
||||||
|
if (window != NULL)
|
||||||
|
{
|
||||||
|
/* Ensure that we have the toplevel window to work around a GTK3 Wayland bug
|
||||||
|
* that prevents the user from dismissing the menu via click in some cases.
|
||||||
|
* See: https://gitlab.xfce.org/xfce/thunar/-/issues/1592 */
|
||||||
|
toplevel = gdk_window_get_toplevel (window);
|
||||||
|
|
||||||
|
device = gdk_event_get_device (event);
|
||||||
|
|
||||||
|
if (device != NULL && gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
|
||||||
|
device = gdk_device_get_associated_device (device);
|
||||||
|
|
||||||
|
if (device != NULL)
|
||||||
|
gdk_window_get_device_position (toplevel, device, &rect.x, &rect.y, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pop up the menu at the rectangle below the mouse cursor */
|
||||||
|
gtk_menu_popup_at_rect (menu,
|
||||||
|
toplevel,
|
||||||
|
&rect,
|
||||||
|
GDK_GRAVITY_NORTH_WEST,
|
||||||
|
GDK_GRAVITY_NORTH_WEST,
|
||||||
|
event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* thunar_gtk_menu_run_at_event:
|
* thunar_gtk_menu_run_at_event:
|
||||||
* @menu : a #GtkMenu.
|
* @menu : a #GtkMenu.
|
||||||
|
|
@ -221,7 +268,8 @@ thunar_gtk_menu_run (GtkMenu *menu)
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
thunar_gtk_menu_run_at_event (GtkMenu *menu, GdkEvent *event)
|
thunar_gtk_menu_run_at_event (GtkMenu *menu,
|
||||||
|
GdkEvent *event)
|
||||||
{
|
{
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
gulong signal_id;
|
gulong signal_id;
|
||||||
|
|
@ -234,7 +282,7 @@ thunar_gtk_menu_run_at_event (GtkMenu *menu, GdkEvent *event)
|
||||||
/* run an internal main loop */
|
/* run an internal main loop */
|
||||||
loop = g_main_loop_new (NULL, FALSE);
|
loop = g_main_loop_new (NULL, FALSE);
|
||||||
signal_id = g_signal_connect_swapped (G_OBJECT (menu), "deactivate", G_CALLBACK (g_main_loop_quit), loop);
|
signal_id = g_signal_connect_swapped (G_OBJECT (menu), "deactivate", G_CALLBACK (g_main_loop_quit), loop);
|
||||||
gtk_menu_popup_at_pointer (menu, event);
|
thunar_gtk_menu_popup_at_pointer (menu, event);
|
||||||
gtk_menu_reposition (menu);
|
gtk_menu_reposition (menu);
|
||||||
gtk_grab_add (GTK_WIDGET (menu));
|
gtk_grab_add (GTK_WIDGET (menu));
|
||||||
g_main_loop_run (loop);
|
g_main_loop_run (loop);
|
||||||
|
|
|
||||||
|
|
@ -1371,6 +1371,7 @@ _thunar_io_jobs_rename (ThunarJob *job,
|
||||||
const gchar *display_name;
|
const gchar *display_name;
|
||||||
ThunarFile *file;
|
ThunarFile *file;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
|
GFile *old_file;
|
||||||
gchar *old_file_uri;
|
gchar *old_file_uri;
|
||||||
ThunarOperationLogMode log_mode;
|
ThunarOperationLogMode log_mode;
|
||||||
ThunarJobOperation *operation;
|
ThunarJobOperation *operation;
|
||||||
|
|
@ -1403,8 +1404,10 @@ _thunar_io_jobs_rename (ThunarJob *job,
|
||||||
if (log_mode == THUNAR_OPERATION_LOG_OPERATIONS)
|
if (log_mode == THUNAR_OPERATION_LOG_OPERATIONS)
|
||||||
{
|
{
|
||||||
operation = thunar_job_operation_new (THUNAR_JOB_OPERATION_KIND_RENAME);
|
operation = thunar_job_operation_new (THUNAR_JOB_OPERATION_KIND_RENAME);
|
||||||
thunar_job_operation_add (operation, g_file_new_for_uri (old_file_uri), thunar_file_get_file (file));
|
old_file = g_file_new_for_uri (old_file_uri);
|
||||||
|
thunar_job_operation_add (operation, old_file, thunar_file_get_file (file));
|
||||||
thunar_job_operation_history_commit (operation);
|
thunar_job_operation_history_commit (operation);
|
||||||
|
g_object_unref (old_file);
|
||||||
g_object_unref (operation);
|
g_object_unref (operation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1605,7 +1608,7 @@ _thunar_search_folder (ThunarStandardViewModel *model,
|
||||||
|
|
||||||
if (exo_job_is_cancelled (EXO_JOB (job)))
|
if (exo_job_is_cancelled (EXO_JOB (job)))
|
||||||
{
|
{
|
||||||
g_list_free (files_found);
|
thunar_g_list_free_full (files_found);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,7 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
|
||||||
GtkWidget *vbox;
|
GtkWidget *vbox;
|
||||||
GtkWidget *infobar;
|
GtkWidget *infobar;
|
||||||
GEnumClass *type;
|
GEnumClass *type;
|
||||||
|
GList *windows;
|
||||||
gchar *date;
|
gchar *date;
|
||||||
gint row = 0;
|
gint row = 0;
|
||||||
|
|
||||||
|
|
@ -1420,9 +1421,13 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
|
||||||
gtk_widget_show (vbox);
|
gtk_widget_show (vbox);
|
||||||
|
|
||||||
frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_IN, NULL);
|
frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_IN, NULL);
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
|
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
|
||||||
gtk_widget_show (frame);
|
gtk_widget_show (frame);
|
||||||
|
|
||||||
|
/* check if the accel map has been initialized which is done in thunar-window.c */
|
||||||
|
windows = thunar_application_get_windows (thunar_application_get ());
|
||||||
|
if (windows != NULL)
|
||||||
|
{
|
||||||
grid = xfce_shortcuts_editor_new (13,
|
grid = xfce_shortcuts_editor_new (13,
|
||||||
_("Window"), thunar_window_get_action_entries (), (size_t) THUNAR_WINDOW_N_ACTIONS,
|
_("Window"), thunar_window_get_action_entries (), (size_t) THUNAR_WINDOW_N_ACTIONS,
|
||||||
_("View"), thunar_standard_view_get_action_entries (), (size_t) THUNAR_STANDARD_VIEW_N_ACTIONS,
|
_("View"), thunar_standard_view_get_action_entries (), (size_t) THUNAR_STANDARD_VIEW_N_ACTIONS,
|
||||||
|
|
@ -1430,6 +1435,15 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
|
||||||
_("Status Bar"), thunar_statusbar_get_action_entries (), (size_t) THUNAR_STATUS_BAR_N_ACTIONS);
|
_("Status Bar"), thunar_statusbar_get_action_entries (), (size_t) THUNAR_STATUS_BAR_N_ACTIONS);
|
||||||
gtk_container_add (GTK_CONTAINER (frame), grid);
|
gtk_container_add (GTK_CONTAINER (frame), grid);
|
||||||
gtk_widget_show (grid);
|
gtk_widget_show (grid);
|
||||||
|
|
||||||
|
g_list_free (windows);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label = gtk_label_new (_("The Shortcuts Editor requires a Thunar window to be present."));
|
||||||
|
gtk_container_add (GTK_CONTAINER (frame), label);
|
||||||
|
gtk_widget_show (label);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -381,6 +381,7 @@ thunar_progress_dialog_add_job (ThunarProgressDialog *dialog,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dialog->views_waiting = g_list_append (dialog->views_waiting, view);
|
dialog->views_waiting = g_list_append (dialog->views_waiting, view);
|
||||||
|
thunar_job_freeze (job);
|
||||||
}
|
}
|
||||||
g_list_free (job_list);
|
g_list_free (job_list);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -658,7 +658,10 @@ thunar_progress_view_new_with_job (ThunarJob *job)
|
||||||
_thunar_return_val_if_fail (job == NULL || THUNAR_IS_JOB (job), NULL);
|
_thunar_return_val_if_fail (job == NULL || THUNAR_IS_JOB (job), NULL);
|
||||||
|
|
||||||
view = g_object_new (THUNAR_TYPE_PROGRESS_VIEW, "job", job, NULL);
|
view = g_object_new (THUNAR_TYPE_PROGRESS_VIEW, "job", job, NULL);
|
||||||
gtk_label_set_text (GTK_LABEL (view->progress_label), _("Queued"));
|
|
||||||
|
/* 'thunar_progress_dialog_add_job' will instantly overwrite with "queued", if required */
|
||||||
|
thunar_progress_view_percent (view, 0.0, EXO_JOB (job));
|
||||||
|
|
||||||
return GTK_WIDGET (view);
|
return GTK_WIDGET (view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1704,14 +1704,16 @@ thunar_properties_dialog_update_multiple (ThunarPropertiesDialog *dialog)
|
||||||
parent_file = tmp_parent;
|
parent_file = tmp_parent;
|
||||||
}
|
}
|
||||||
else if (tmp_parent != NULL)
|
else if (tmp_parent != NULL)
|
||||||
|
{
|
||||||
|
if (parent_file != NULL)
|
||||||
{
|
{
|
||||||
/* we only display the location if they are all equal */
|
/* we only display the location if they are all equal */
|
||||||
if (!g_file_equal (thunar_file_get_file (parent_file), thunar_file_get_file (tmp_parent)))
|
if (!g_file_equal (thunar_file_get_file (parent_file), thunar_file_get_file (tmp_parent)))
|
||||||
{
|
{
|
||||||
if (parent_file != NULL)
|
|
||||||
g_object_unref (G_OBJECT (parent_file));
|
g_object_unref (G_OBJECT (parent_file));
|
||||||
parent_file = NULL;
|
parent_file = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_object_unref (G_OBJECT (tmp_parent));
|
g_object_unref (G_OBJECT (tmp_parent));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -853,7 +853,8 @@ thunar_renamer_dialog_response (GtkDialog *dialog,
|
||||||
/* perform the rename (returns when done) */
|
/* perform the rename (returns when done) */
|
||||||
thunar_renamer_progress_run (THUNAR_RENAMER_PROGRESS (renamer_dialog->progress), pair_list);
|
thunar_renamer_progress_run (THUNAR_RENAMER_PROGRESS (renamer_dialog->progress), pair_list);
|
||||||
|
|
||||||
/* hide the rename progress bar */
|
/* hide the rename progress bar (unless the dialog has been destroyed) */
|
||||||
|
if (gtk_widget_get_realized (GTK_WIDGET (renamer_dialog)))
|
||||||
gtk_widget_hide (renamer_dialog->progress);
|
gtk_widget_hide (renamer_dialog->progress);
|
||||||
|
|
||||||
/* release the pairs */
|
/* release the pairs */
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,13 @@ struct _ThunarShortcut
|
||||||
guint is_separator : 1;
|
guint is_separator : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ThunarShortcutsModel *model;
|
||||||
|
ThunarShortcut *shortcut;
|
||||||
|
gboolean update_visibility;
|
||||||
|
} ThunarShortcutFileGetData;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (ThunarShortcutsModel, thunar_shortcuts_model, G_TYPE_OBJECT,
|
G_DEFINE_TYPE_WITH_CODE (ThunarShortcutsModel, thunar_shortcuts_model, G_TYPE_OBJECT,
|
||||||
|
|
@ -1610,12 +1617,39 @@ thunar_shortcuts_model_save_bookmarks (ThunarShortcutsModel *model)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
thunar_shortcuts_model_device_added_callback (GFile *location,
|
||||||
|
ThunarFile *file,
|
||||||
|
GError *error,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ThunarShortcutFileGetData *data = user_data;
|
||||||
|
ThunarShortcut *shortcut = data->shortcut;
|
||||||
|
ThunarShortcutsModel *model = data->model;
|
||||||
|
|
||||||
|
if (error == NULL)
|
||||||
|
{
|
||||||
|
shortcut->file = g_object_ref (file);
|
||||||
|
|
||||||
|
/* insert in the model */
|
||||||
|
thunar_shortcuts_model_add_shortcut (model, shortcut);
|
||||||
|
|
||||||
|
if (data->update_visibility)
|
||||||
|
thunar_shortcuts_model_header_visibility (model);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (location);
|
||||||
|
g_object_unref (model);
|
||||||
|
g_slice_free (ThunarShortcutFileGetData, data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
thunar_shortcuts_model_device_added (ThunarDeviceMonitor *device_monitor,
|
thunar_shortcuts_model_device_added (ThunarDeviceMonitor *device_monitor,
|
||||||
ThunarDevice *device,
|
ThunarDevice *device,
|
||||||
ThunarShortcutsModel *model)
|
ThunarShortcutsModel *model)
|
||||||
{
|
{
|
||||||
ThunarShortcut *shortcut;
|
ThunarShortcut *shortcut;
|
||||||
|
ThunarShortcutFileGetData *data;
|
||||||
GFile *mount_point;
|
GFile *mount_point;
|
||||||
|
|
||||||
_thunar_return_if_fail (device_monitor == NULL || THUNAR_DEVICE_MONITOR (device_monitor));
|
_thunar_return_if_fail (device_monitor == NULL || THUNAR_DEVICE_MONITOR (device_monitor));
|
||||||
|
|
@ -1628,13 +1662,6 @@ thunar_shortcuts_model_device_added (ThunarDeviceMonitor *device_monitor,
|
||||||
shortcut->device = g_object_ref (device);
|
shortcut->device = g_object_ref (device);
|
||||||
shortcut->hidden = thunar_device_get_hidden (device);
|
shortcut->hidden = thunar_device_get_hidden (device);
|
||||||
|
|
||||||
mount_point = thunar_device_get_root (device);
|
|
||||||
if (mount_point != NULL)
|
|
||||||
{
|
|
||||||
shortcut->file = thunar_file_get (mount_point, NULL);
|
|
||||||
g_object_unref (mount_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (thunar_device_get_kind (device))
|
switch (thunar_device_get_kind (device))
|
||||||
{
|
{
|
||||||
case THUNAR_DEVICE_KIND_VOLUME:
|
case THUNAR_DEVICE_KIND_VOLUME:
|
||||||
|
|
@ -1650,14 +1677,28 @@ thunar_shortcuts_model_device_added (ThunarDeviceMonitor *device_monitor,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* header visibility if call is from monitor */
|
||||||
|
gboolean update_visibility = (device_monitor != NULL && !shortcut->hidden);
|
||||||
|
|
||||||
|
mount_point = thunar_device_get_root (device);
|
||||||
|
if (mount_point != NULL)
|
||||||
|
{
|
||||||
|
data = g_slice_new0 (ThunarShortcutFileGetData);
|
||||||
|
data->shortcut = shortcut;
|
||||||
|
data->model = g_object_ref (model);
|
||||||
|
data->update_visibility = update_visibility;
|
||||||
|
|
||||||
|
thunar_file_get_async (mount_point, NULL, &thunar_shortcuts_model_device_added_callback, data);
|
||||||
|
}
|
||||||
|
else /* some devices (e.g. usb flashdrives) do not have a mountpoint */
|
||||||
|
{
|
||||||
/* insert in the model */
|
/* insert in the model */
|
||||||
thunar_shortcuts_model_add_shortcut (model, shortcut);
|
thunar_shortcuts_model_add_shortcut (model, shortcut);
|
||||||
|
|
||||||
/* header visibility if call is from monitor */
|
if (update_visibility)
|
||||||
if (device_monitor != NULL
|
|
||||||
&& !shortcut->hidden)
|
|
||||||
thunar_shortcuts_model_header_visibility (model);
|
thunar_shortcuts_model_header_visibility (model);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1679,7 +1720,12 @@ thunar_shortcuts_model_device_removed (ThunarDeviceMonitor *device_monitor,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* something is broken if we don't have a shortcut here */
|
/* something is broken if we don't have a shortcut here */
|
||||||
_thunar_assert (lp != NULL);
|
if (lp == NULL)
|
||||||
|
{
|
||||||
|
g_warning ("No shortcut found for device '%s'", thunar_device_get_name (device));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_thunar_assert (THUNAR_SHORTCUT (lp->data)->device == device);
|
_thunar_assert (THUNAR_SHORTCUT (lp->data)->device == device);
|
||||||
|
|
||||||
/* drop the shortcut from the model */
|
/* drop the shortcut from the model */
|
||||||
|
|
@ -1713,7 +1759,12 @@ thunar_shortcuts_model_device_changed (ThunarDeviceMonitor *device_monitor,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* something is broken if we don't have a shortcut here */
|
/* something is broken if we don't have a shortcut here */
|
||||||
_thunar_assert (lp != NULL);
|
if (lp == NULL)
|
||||||
|
{
|
||||||
|
g_warning ("No shortcut found for device '%s'", thunar_device_get_name (device));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_thunar_assert (THUNAR_SHORTCUT (lp->data)->device == device);
|
_thunar_assert (THUNAR_SHORTCUT (lp->data)->device == device);
|
||||||
|
|
||||||
if (G_LIKELY (lp != NULL))
|
if (G_LIKELY (lp != NULL))
|
||||||
|
|
@ -1786,8 +1837,7 @@ thunar_shortcuts_model_file_destroyed (ThunarFile *file,
|
||||||
/* remove the thunar file from the list and set the g_file instead */
|
/* remove the thunar file from the list and set the g_file instead */
|
||||||
if (shortcut->location == NULL)
|
if (shortcut->location == NULL)
|
||||||
{
|
{
|
||||||
GFile *g_file = thunar_file_get_file (file);
|
shortcut->location = g_object_ref (thunar_file_get_file (file)) ;
|
||||||
shortcut->location = g_file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shortcut->gicon == NULL)
|
if (shortcut->gicon == NULL)
|
||||||
|
|
|
||||||
|
|
@ -1500,6 +1500,10 @@ thunar_standard_view_update_selected_files (ThunarStandardView *standard_view,
|
||||||
|
|
||||||
/* determine the tree paths for the given files */
|
/* determine the tree paths for the given files */
|
||||||
paths = thunar_standard_view_model_get_paths_for_files (standard_view->model, files_to_select);
|
paths = thunar_standard_view_model_get_paths_for_files (standard_view->model, files_to_select);
|
||||||
|
|
||||||
|
/* unselect all previously selected files - this may free the "files_to_select" list */
|
||||||
|
(*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->unselect_all) (standard_view);
|
||||||
|
|
||||||
if (G_LIKELY (paths != NULL))
|
if (G_LIKELY (paths != NULL))
|
||||||
{
|
{
|
||||||
/* determine the first path */
|
/* determine the first path */
|
||||||
|
|
@ -2456,6 +2460,7 @@ thunar_standard_view_update_statusbar_text_idle (gpointer data)
|
||||||
GList *selected_items_tree_path_list;
|
GList *selected_items_tree_path_list;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
ThunarFile *file;
|
ThunarFile *file;
|
||||||
|
gchar *statusbar_text;
|
||||||
|
|
||||||
_thunar_return_val_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view), FALSE);
|
_thunar_return_val_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view), FALSE);
|
||||||
|
|
||||||
|
|
@ -2478,6 +2483,22 @@ thunar_standard_view_update_statusbar_text_idle (gpointer data)
|
||||||
if (thunar_standard_view_model_get_folder (standard_view->model) == NULL)
|
if (thunar_standard_view_model_get_folder (standard_view->model) == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
/* search mode active */
|
||||||
|
if (standard_view->priv->search_query != NULL)
|
||||||
|
{
|
||||||
|
gint num_files;
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (standard_view->model), "num-files", &num_files, NULL);
|
||||||
|
|
||||||
|
statusbar_text = g_strdup_printf (ngettext ("%d file found", "%d files found", num_files), num_files);
|
||||||
|
thunar_standard_view_set_statusbar_text (standard_view, statusbar_text);
|
||||||
|
g_free (statusbar_text);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (standard_view), standard_view_props[PROP_STATUSBAR_TEXT]);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
standard_view->priv->statusbar_job = thunar_io_jobs_load_statusbar_text_for_folder (standard_view, thunar_standard_view_model_get_folder (standard_view->model));
|
standard_view->priv->statusbar_job = thunar_io_jobs_load_statusbar_text_for_folder (standard_view, thunar_standard_view_model_get_folder (standard_view->model));
|
||||||
|
|
||||||
g_signal_connect (standard_view->priv->statusbar_job, "error", G_CALLBACK (thunar_standard_view_update_statusbar_text_error), standard_view);
|
g_signal_connect (standard_view->priv->statusbar_job, "error", G_CALLBACK (thunar_standard_view_update_statusbar_text_error), standard_view);
|
||||||
|
|
@ -2487,8 +2508,6 @@ thunar_standard_view_update_statusbar_text_idle (gpointer data)
|
||||||
}
|
}
|
||||||
else if (selected_items_tree_path_list->next == NULL) /* only one item selected */
|
else if (selected_items_tree_path_list->next == NULL) /* only one item selected */
|
||||||
{
|
{
|
||||||
gchar *statusbar_text;
|
|
||||||
|
|
||||||
/* resolve the iter for the single path */
|
/* resolve the iter for the single path */
|
||||||
gtk_tree_model_get_iter (GTK_TREE_MODEL (standard_view->model), &iter, selected_items_tree_path_list->data);
|
gtk_tree_model_get_iter (GTK_TREE_MODEL (standard_view->model), &iter, selected_items_tree_path_list->data);
|
||||||
|
|
||||||
|
|
@ -2549,7 +2568,7 @@ thunar_standard_view_update_statusbar_text (ThunarStandardView *standard_view)
|
||||||
/* restart a new one, this way we avoid multiple update when
|
/* restart a new one, this way we avoid multiple update when
|
||||||
* the user is pressing a key to scroll */
|
* the user is pressing a key to scroll */
|
||||||
standard_view->priv->statusbar_text_idle_id =
|
standard_view->priv->statusbar_text_idle_id =
|
||||||
g_timeout_add_full (G_PRIORITY_LOW, 50, thunar_standard_view_update_statusbar_text_idle,
|
g_timeout_add_full (G_PRIORITY_DEFAULT, 50, thunar_standard_view_update_statusbar_text_idle,
|
||||||
standard_view, NULL);
|
standard_view, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -868,6 +868,7 @@ thunar_transfer_job_copy_node (ThunarTransferJob *job,
|
||||||
use_fat_name_scheme =
|
use_fat_name_scheme =
|
||||||
!g_strcmp0 (fs_type, "fat") ||
|
!g_strcmp0 (fs_type, "fat") ||
|
||||||
!g_strcmp0 (fs_type, "vfat") ||
|
!g_strcmp0 (fs_type, "vfat") ||
|
||||||
|
!g_strcmp0 (fs_type, "exfat") ||
|
||||||
!g_strcmp0 (fs_type, "fuse") ||
|
!g_strcmp0 (fs_type, "fuse") ||
|
||||||
!g_strcmp0 (fs_type, "ntfs") ||
|
!g_strcmp0 (fs_type, "ntfs") ||
|
||||||
!g_strcmp0 (fs_type, "msdos") ||
|
!g_strcmp0 (fs_type, "msdos") ||
|
||||||
|
|
|
||||||
|
|
@ -1717,6 +1717,9 @@ _thunar_tree_view_model_cancel_search_job (ThunarTreeViewModel *model)
|
||||||
g_object_unref (model->search_job);
|
g_object_unref (model->search_job);
|
||||||
model->search_job = NULL;
|
model->search_job = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thunar_g_list_free_full (model->search_files);
|
||||||
|
model->search_files = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2516,11 +2519,27 @@ thunar_tree_view_model_sort (ThunarTreeViewModel *model)
|
||||||
static void
|
static void
|
||||||
_thunar_tree_view_model_folder_destroy (Node *node)
|
_thunar_tree_view_model_folder_destroy (Node *node)
|
||||||
{
|
{
|
||||||
/* if a subdir get's destroyed it's handled internally but if the current_folder
|
/* if a subdir gets destroyed, it's handled internally, but if the current_folder
|
||||||
* get's destroyed then we simply set_folder to NULL & cleanup things */
|
* gets destroyed, then we simply set_folder to NULL & cleanup things */
|
||||||
if (node->parent == NULL)
|
if (node->parent == NULL)
|
||||||
|
{
|
||||||
|
if (node->n_children > 0)
|
||||||
|
{
|
||||||
|
/* set_folder func does not emit row-deleted signal, but instead relies on
|
||||||
|
* ThunarStandardView to disconnect & reconnect the view to quickly update
|
||||||
|
* changes in current_directory. */
|
||||||
|
GList *keys = g_hash_table_get_keys (node->set);
|
||||||
|
|
||||||
|
for (GList *lp = keys; lp != NULL; lp = lp->next)
|
||||||
|
thunar_tree_view_model_dir_remove_file (node, THUNAR_FILE (lp->data));
|
||||||
|
|
||||||
|
g_list_free (keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset the model */
|
||||||
thunar_tree_view_model_set_folder (THUNAR_STANDARD_VIEW_MODEL (node->model), NULL, NULL);
|
thunar_tree_view_model_set_folder (THUNAR_STANDARD_VIEW_MODEL (node->model), NULL, NULL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2530,26 +2549,13 @@ _thunar_tree_view_model_folder_error (Node *node,
|
||||||
{
|
{
|
||||||
_thunar_return_if_fail (error != NULL);
|
_thunar_return_if_fail (error != NULL);
|
||||||
|
|
||||||
if (node->n_children > 0)
|
|
||||||
{
|
|
||||||
if (node->parent == NULL)
|
if (node->parent == NULL)
|
||||||
{
|
_thunar_tree_view_model_folder_destroy (node);
|
||||||
/* set_folder func does not emit row-deleted signal instead relies
|
|
||||||
* on ThunarStandardView to disconnect & reconnect the view quickly update
|
|
||||||
* changes in current_directory. */
|
|
||||||
GList *keys = g_hash_table_get_keys (node->set);
|
|
||||||
|
|
||||||
for (GList *lp = keys; lp != NULL; lp = lp->next)
|
|
||||||
thunar_tree_view_model_dir_remove_file (node, THUNAR_FILE (lp->data));
|
|
||||||
|
|
||||||
g_list_free (keys);
|
|
||||||
|
|
||||||
/* reset the model if error is with the current directory */
|
|
||||||
thunar_tree_view_model_set_folder (THUNAR_STANDARD_VIEW_MODEL (node->model), NULL, NULL);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
thunar_tree_view_model_dir_remove_file (node->parent, node->file);
|
thunar_tree_view_model_dir_remove_file (node->parent, node->file);
|
||||||
}
|
|
||||||
|
/* forward the error signal */
|
||||||
|
g_signal_emit_by_name (G_OBJECT (node->model), "error", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2578,6 +2584,8 @@ _thunar_tree_view_model_dir_files_added (Node *node,
|
||||||
if (!g_hash_table_contains (node->set, file))
|
if (!g_hash_table_contains (node->set, file))
|
||||||
thunar_tree_view_model_dir_add_file (node, file);
|
thunar_tree_view_model_dir_add_file (node, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (node->model), tree_model_props[PROP_NUM_FILES]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2607,6 +2615,8 @@ _thunar_tree_view_model_dir_files_removed (Node *node,
|
||||||
|
|
||||||
thunar_tree_view_model_dir_remove_file (node, file);
|
thunar_tree_view_model_dir_remove_file (node, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (node->model), tree_model_props[PROP_NUM_FILES]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2841,8 +2851,8 @@ thunar_tree_view_model_dir_files_changed (Node *node_parent,
|
||||||
{
|
{
|
||||||
if (!model->show_hidden)
|
if (!model->show_hidden)
|
||||||
thunar_tree_view_model_dir_remove_file (node_parent, file);
|
thunar_tree_view_model_dir_remove_file (node_parent, file);
|
||||||
|
|
||||||
g_hash_table_add (node_parent->hidden_files, g_object_ref (file));
|
g_hash_table_add (node_parent->hidden_files, g_object_ref (file));
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node = thunar_tree_view_model_locate_file (model, file);
|
node = thunar_tree_view_model_locate_file (model, file);
|
||||||
|
|
@ -3114,9 +3124,12 @@ thunar_tree_view_model_update_search_files (ThunarTreeViewModel *model)
|
||||||
g_object_unref (file);
|
g_object_unref (file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (model), tree_model_props[PROP_NUM_FILES]);
|
||||||
|
|
||||||
if (model->search_files != NULL)
|
if (model->search_files != NULL)
|
||||||
g_list_free (model->search_files);
|
thunar_g_list_free_full (model->search_files);
|
||||||
model->search_files = NULL;
|
model->search_files = NULL;
|
||||||
|
|
||||||
g_mutex_unlock (&model->mutex_add_search_files);
|
g_mutex_unlock (&model->mutex_add_search_files);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
||||||
|
|
@ -560,8 +560,8 @@ thunar_util_parse_parent (gpointer parent,
|
||||||
}
|
}
|
||||||
else if (GDK_IS_SCREEN (parent))
|
else if (GDK_IS_SCREEN (parent))
|
||||||
{
|
{
|
||||||
/* yep, that's a screen */
|
/* A specific screen was requested. Just return it, without filling 'window_return' */
|
||||||
screen = GDK_SCREEN (parent);
|
return GDK_SCREEN (parent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1256,6 +1256,7 @@ thunar_window_init (ThunarWindow *window)
|
||||||
window->trash_infobar = gtk_info_bar_new ();
|
window->trash_infobar = gtk_info_bar_new ();
|
||||||
gtk_grid_attach (GTK_GRID (window->view_box), window->trash_infobar, 0, 2, 1, 1);
|
gtk_grid_attach (GTK_GRID (window->view_box), window->trash_infobar, 0, 2, 1, 1);
|
||||||
window->trash_infobar_restore_button = gtk_info_bar_add_button (GTK_INFO_BAR (window->trash_infobar), _("Restore Selected Items"), RESTORE);
|
window->trash_infobar_restore_button = gtk_info_bar_add_button (GTK_INFO_BAR (window->trash_infobar), _("Restore Selected Items"), RESTORE);
|
||||||
|
gtk_widget_set_sensitive (window->trash_infobar_restore_button, FALSE);
|
||||||
window->trash_infobar_empty_button = gtk_info_bar_add_button (GTK_INFO_BAR (window->trash_infobar), _("Empty Trash"), EMPTY);
|
window->trash_infobar_empty_button = gtk_info_bar_add_button (GTK_INFO_BAR (window->trash_infobar), _("Empty Trash"), EMPTY);
|
||||||
g_signal_connect (window->trash_infobar,
|
g_signal_connect (window->trash_infobar,
|
||||||
"response",
|
"response",
|
||||||
|
|
@ -2405,6 +2406,7 @@ thunar_window_switch_current_view (ThunarWindow *window,
|
||||||
GSList *view_bindings;
|
GSList *view_bindings;
|
||||||
ThunarFile *current_directory;
|
ThunarFile *current_directory;
|
||||||
ThunarHistory *history;
|
ThunarHistory *history;
|
||||||
|
gchar *search_query;
|
||||||
|
|
||||||
_thunar_return_if_fail (THUNAR_IS_WINDOW (window));
|
_thunar_return_if_fail (THUNAR_IS_WINDOW (window));
|
||||||
_thunar_return_if_fail (THUNAR_IS_VIEW (new_view));
|
_thunar_return_if_fail (THUNAR_IS_VIEW (new_view));
|
||||||
|
|
@ -2436,6 +2438,11 @@ thunar_window_switch_current_view (ThunarWindow *window,
|
||||||
window->view_bindings = NULL;
|
window->view_bindings = NULL;
|
||||||
g_slist_free_full (view_bindings, g_object_unref);
|
g_slist_free_full (view_bindings, g_object_unref);
|
||||||
|
|
||||||
|
/* exit search mode (if the view has no ongoing search operation) */
|
||||||
|
search_query = thunar_standard_view_get_search_query (THUNAR_STANDARD_VIEW (new_view));
|
||||||
|
if (search_query == NULL && window->search_query != NULL)
|
||||||
|
thunar_window_action_cancel_search (window);
|
||||||
|
|
||||||
/* update the directory of the current window */
|
/* update the directory of the current window */
|
||||||
current_directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (new_view));
|
current_directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (new_view));
|
||||||
thunar_window_set_current_directory (window, current_directory);
|
thunar_window_set_current_directory (window, current_directory);
|
||||||
|
|
@ -2511,15 +2518,13 @@ thunar_window_switch_current_view (ThunarWindow *window,
|
||||||
if (thunar_file_is_trash (window->current_directory))
|
if (thunar_file_is_trash (window->current_directory))
|
||||||
gtk_widget_set_sensitive (window->trash_infobar_empty_button, thunar_file_get_item_count (window->current_directory) > 0);
|
gtk_widget_set_sensitive (window->trash_infobar_empty_button, thunar_file_get_item_count (window->current_directory) > 0);
|
||||||
|
|
||||||
/* if the view has an ongoing search operation take that into account, otherwise cancel the current search (if there is one) */
|
/* if the view has an ongoing search operation, take that into account */
|
||||||
if (thunar_standard_view_get_search_query (THUNAR_STANDARD_VIEW (window->view)) != NULL)
|
if (search_query != NULL)
|
||||||
{
|
{
|
||||||
gchar *str = g_strjoin (NULL, thunar_util_get_search_prefix (), thunar_standard_view_get_search_query (THUNAR_STANDARD_VIEW (window->view)), NULL);
|
gchar *str = g_strjoin (NULL, thunar_util_get_search_prefix (), search_query, NULL);
|
||||||
thunar_window_resume_search (window, str);
|
thunar_window_resume_search (window, str);
|
||||||
g_free (str);
|
g_free (str);
|
||||||
}
|
}
|
||||||
else if (window->search_query != NULL)
|
|
||||||
thunar_window_action_cancel_search (window);
|
|
||||||
|
|
||||||
/* switch to the new view */
|
/* switch to the new view */
|
||||||
thunar_window_notebook_set_current_tab (window, gtk_notebook_page_num (GTK_NOTEBOOK (window->notebook_selected), window->view));
|
thunar_window_notebook_set_current_tab (window, gtk_notebook_page_num (GTK_NOTEBOOK (window->notebook_selected), window->view));
|
||||||
|
|
@ -2643,6 +2648,10 @@ thunar_window_notebook_page_removed (GtkWidget *notebook,
|
||||||
/* drop connected signals */
|
/* drop connected signals */
|
||||||
g_signal_handlers_disconnect_by_data (page, window);
|
g_signal_handlers_disconnect_by_data (page, window);
|
||||||
|
|
||||||
|
/* skip selecting another page when the window is being destroyed */
|
||||||
|
if (gtk_widget_in_destruction (GTK_WIDGET (window)))
|
||||||
|
return;
|
||||||
|
|
||||||
n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
|
n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
|
||||||
if (n_pages == 0)
|
if (n_pages == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -2665,8 +2674,7 @@ thunar_window_notebook_page_removed (GtkWidget *notebook,
|
||||||
/* page from the other notebook was removed */
|
/* page from the other notebook was removed */
|
||||||
if (notebook != window->notebook_selected)
|
if (notebook != window->notebook_selected)
|
||||||
thunar_window_paned_notebooks_switch (window);
|
thunar_window_paned_notebooks_switch (window);
|
||||||
else
|
else /* this page removed -> select next page */
|
||||||
/* this page removed -> select next page */
|
|
||||||
thunar_window_notebook_select_current_page (window);
|
thunar_window_notebook_select_current_page (window);
|
||||||
|
|
||||||
/* update tab visibility */
|
/* update tab visibility */
|
||||||
|
|
@ -3670,6 +3678,8 @@ thunar_window_reset_view_type_idle_destroyed (gpointer data)
|
||||||
gboolean
|
gboolean
|
||||||
thunar_window_action_cancel_search (ThunarWindow *window)
|
thunar_window_action_cancel_search (ThunarWindow *window)
|
||||||
{
|
{
|
||||||
|
ThunarApplication *application;
|
||||||
|
|
||||||
_thunar_return_val_if_fail (THUNAR_IS_LOCATION_BAR (window->location_bar), FALSE);
|
_thunar_return_val_if_fail (THUNAR_IS_LOCATION_BAR (window->location_bar), FALSE);
|
||||||
_thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
|
_thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
|
||||||
|
|
||||||
|
|
@ -3708,6 +3718,11 @@ thunar_window_action_cancel_search (ThunarWindow *window)
|
||||||
/* bring back the original location bar style (relevant if the bar is hidden) */
|
/* bring back the original location bar style (relevant if the bar is hidden) */
|
||||||
thunar_window_update_location_bar_visible (window);
|
thunar_window_update_location_bar_visible (window);
|
||||||
|
|
||||||
|
/* tidy up memory after a search */
|
||||||
|
application = thunar_application_get ();
|
||||||
|
thunar_application_malloc_trim_on_idle (application);
|
||||||
|
g_object_unref (application);
|
||||||
|
|
||||||
/* required in case of shortcut activation, in order to signal that the accel key got handled */
|
/* required in case of shortcut activation, in order to signal that the accel key got handled */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue