/** * thunar_column_model_get_column_name: * @column_model : a #ThunarColumnModel. * @column : a #ThunarColumn. * * Returns the user visible name for the @column in * the @column_model. * * Return value: the user visible name for @column. **/ const gchar* thunar_column_model_get_column_name (ThunarColumnModel *column_model, ThunarColumn column) { const gchar *column_name = _("Unknown"); GEnumClass *klass; gint n; _thunar_return_val_if_fail (THUNAR_IS_COLUMN_MODEL (column_model), NULL); _thunar_return_val_if_fail (column < THUNAR_N_VISIBLE_COLUMNS, NULL); _thunar_return_val_if_fail (column >= 0, NULL); /* determine the column name from the ThunarColumn enum type */ klass = g_type_class_ref (THUNAR_TYPE_COLUMN); for (n = 0; n < klass->n_values; ++n) if (klass->values[n].value == column) column_name = _(klass->values[n].value_nick); g_type_class_unref (klass); return column_name; }
static gboolean thunar_progress_dialog_closed (ThunarProgressDialog *dialog) { _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), FALSE); /* remember the position of the dialog */ gtk_window_get_position (GTK_WINDOW (dialog), &dialog->x, &dialog->y); /* hide the progress dialog */ gtk_widget_hide (GTK_WIDGET (dialog)); /* don't destroy the dialog */ return TRUE; }
/** * thunar_folder_get_for_file: * @file : a #ThunarFile. * * Opens the specified @file as #ThunarFolder and * returns a reference to the folder. * * The caller is responsible to free the returned * object using g_object_unref() when no longer * needed. * * Return value: the #ThunarFolder which corresponds * to @file. **/ ThunarFolder* thunar_folder_get_for_file (ThunarFile *file) { ThunarFolder *folder; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); _thunar_return_val_if_fail (thunar_file_is_directory (file), NULL); /* determine the "thunar-folder" quark on-demand */ if (G_UNLIKELY (thunar_folder_quark == 0)) thunar_folder_quark = g_quark_from_static_string ("thunar-folder"); /* check if we already know that folder */ folder = g_object_get_qdata (G_OBJECT (file), thunar_folder_quark); if (G_UNLIKELY (folder != NULL)) { g_object_ref (G_OBJECT (folder)); } else { /* allocate the new instance */ folder = g_object_new (THUNAR_TYPE_FOLDER, NULL); folder->corresponding_file = file; g_object_ref (G_OBJECT (file)); /* drop the floating reference */ exo_gtk_object_ref_sink (GTK_OBJECT (folder)); /* connect the folder to the file */ g_object_set_qdata (G_OBJECT (file), thunar_folder_quark, folder); /* schedule the loading of the folder */ thunar_folder_reload (folder); } return folder; }
/** * thunar_util_parse_parent: * @parent : a #GtkWidget, a #GdkScreen or %NULL. * @window_return : return location for the toplevel #GtkWindow or * %NULL. * * Determines the screen for the @parent and returns that #GdkScreen. * If @window_return is not %NULL, the pointer to the #GtkWindow is * placed into it, or %NULL if the window could not be determined. * * Return value: the #GdkScreen for the @parent. **/ GdkScreen* thunar_util_parse_parent (gpointer parent, GtkWindow **window_return) { GdkScreen *screen; GtkWidget *window = NULL; _thunar_return_val_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent), NULL); /* determine the proper parent */ if (parent == NULL) { /* just use the default screen then */ screen = gdk_screen_get_default (); } else if (GDK_IS_SCREEN (parent)) { /* yep, that's a screen */ screen = GDK_SCREEN (parent); } else { /* parent is a widget, so let's determine the toplevel window */ window = gtk_widget_get_toplevel (GTK_WIDGET (parent)); if (window != NULL && gtk_widget_is_toplevel (window)) { /* make sure the toplevel window is shown */ gtk_widget_show_now (window); } else { /* no toplevel, not usable then */ window = NULL; } /* determine the screen for the widget */ screen = gtk_widget_get_screen (GTK_WIDGET (parent)); } /* check if we should return the window */ if (G_LIKELY (window_return != NULL)) *window_return = (GtkWindow *) window; return screen; }
static gboolean thunar_column_model_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) { ThunarColumnModel *column_model = THUNAR_COLUMN_MODEL (tree_model); _thunar_return_val_if_fail (THUNAR_IS_COLUMN_MODEL (column_model), FALSE); if (G_LIKELY (parent == NULL)) { GTK_TREE_ITER_INIT (*iter, column_model->stamp, GINT_TO_POINTER (0)); return TRUE; } return FALSE; }
gchar * thunar_util_change_working_directory (const gchar *new_directory) { gchar *old_directory; _thunar_return_val_if_fail (new_directory != NULL && *new_directory != '\0', NULL); /* try to determine the current working directory */ old_directory = g_get_current_dir(); /* try switching to the new working directory */ if (g_chdir (new_directory) != 0) { /* switching failed, we don't need to return the old directory */ g_free (old_directory); old_directory = NULL; } return old_directory; }
/** * thunar_dbus_client_bulk_rename: * @working_directory : the default working directory for the bulk rename dialog. * @filenames : the list of files that should be displayed by default or * the empty list to start with an empty bulk rename dialog. * @standalone : whether to run the bulk renamer in standalone mode. * @screen : the #GdkScreen on which to display the dialog or %NULL to * use the default #GdkScreen. * @error : return location for errors or %NULL. * * Tries to invoke the BulkRename() method on a running Thunar instance, that is * registered with the current D-BUS session bus. Returns %TRUE if the method was * successfully invoked, else %FALSE. * * If %TRUE is returned, the current process may afterwards just terminate, as * all @filenames will be handled by the remote instance. * * Return value: %TRUE on success, else %FALSE. **/ gboolean thunar_dbus_client_bulk_rename (const gchar *working_directory, gchar **filenames, gboolean standalone, GdkScreen *screen, GError **error) { DBusConnection *connection; DBusMessage *message; DBusMessage *result; DBusError derror; gchar *display_name; _thunar_return_val_if_fail (screen == NULL || GDK_IS_SCREEN (screen), FALSE); _thunar_return_val_if_fail (g_path_is_absolute (working_directory), FALSE); _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); _thunar_return_val_if_fail (filenames != NULL, FALSE); /* initialize the DBusError struct */ dbus_error_init (&derror); /* fallback to default screen if no other is specified */ if (G_LIKELY (screen == NULL)) screen = gdk_screen_get_default (); /* try to connect to the session bus */ connection = dbus_bus_get (DBUS_BUS_SESSION, &derror); if (G_UNLIKELY (connection == NULL)) { dbus_set_g_error (error, &derror); dbus_error_free (&derror); return FALSE; } /* determine the display name for the screen */ display_name = gdk_screen_make_display_name (screen); /* generate the BulkRename() method (disable activation!) */ message = dbus_message_new_method_call ("org.xfce.Thunar", "/org/xfce/FileManager", "org.xfce.Thunar", "BulkRename"); dbus_message_set_auto_start (message, FALSE); dbus_message_append_args (message, DBUS_TYPE_STRING, &working_directory, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &filenames, g_strv_length (filenames), DBUS_TYPE_BOOLEAN, &standalone, DBUS_TYPE_STRING, &display_name, DBUS_TYPE_INVALID); /* release the display name */ g_free (display_name); /* send the message and release our references on connection and message */ result = dbus_connection_send_with_reply_and_block (connection, message, -1, &derror); dbus_message_unref (message); /* check if no reply was received */ if (G_UNLIKELY (result == NULL)) { dbus_set_g_error (error, &derror); dbus_error_free (&derror); return FALSE; } /* but maybe we received an error */ if (dbus_message_get_type (result) == DBUS_MESSAGE_TYPE_ERROR) { dbus_set_error_from_message (&derror, result); dbus_set_g_error (error, &derror); dbus_message_unref (result); dbus_error_free (&derror); return FALSE; } /* let's asume that it worked */ dbus_message_unref (result); return TRUE; }
/** * thunar_dialogs_show_job_ask: * @parent : the parent #GtkWindow or %NULL. * @question : the question text. * @choices : possible responses. * * Utility function to display a question dialog for the ThunarJob::ask * signal. * * Return value: the #ThunarJobResponse. **/ ThunarJobResponse thunar_dialogs_show_job_ask (GtkWindow *parent, const gchar *question, ThunarJobResponse choices) { const gchar *separator; const gchar *mnemonic; GtkWidget *message; GtkWidget *button; GString *secondary = g_string_sized_new (256); GString *primary = g_string_sized_new (256); gint response; gint n; gboolean has_cancel = FALSE; _thunar_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), THUNAR_JOB_RESPONSE_CANCEL); _thunar_return_val_if_fail (g_utf8_validate (question, -1, NULL), THUNAR_JOB_RESPONSE_CANCEL); /* try to separate the question into primary and secondary parts */ separator = strstr (question, ": "); if (G_LIKELY (separator != NULL)) { /* primary is everything before the colon, plus a dot */ g_string_append_len (primary, question, separator - question); g_string_append_c (primary, '.'); /* secondary is everything after the colon (skipping whitespace) */ do ++separator; while (g_ascii_isspace (*separator)); g_string_append (secondary, separator); } else { /* otherwise separate based on the \n\n */ separator = strstr (question, "\n\n"); if (G_LIKELY (separator != NULL)) { /* primary is everything before the newlines */ g_string_append_len (primary, question, separator - question); /* secondary is everything after the newlines (skipping whitespace) */ while (g_ascii_isspace (*separator)) ++separator; g_string_append (secondary, separator); } else { /* everything is primary */ g_string_append (primary, question); } } /* allocate the question message dialog */ message = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", primary->str); if (G_LIKELY (*secondary->str != '\0')) gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message), "%s", secondary->str); /* add the buttons based on the possible choices */ for (n = 6; n >= 0; --n) { /* check if the response is set */ response = choices & (1 << n); if (response == 0) continue; switch (response) { case THUNAR_JOB_RESPONSE_YES: mnemonic = _("_Yes"); break; case THUNAR_JOB_RESPONSE_YES_ALL: mnemonic = _("Yes to _all"); break; case THUNAR_JOB_RESPONSE_NO: mnemonic = _("_No"); break; case THUNAR_JOB_RESPONSE_NO_ALL: mnemonic = _("N_o to all"); break; case THUNAR_JOB_RESPONSE_RETRY: mnemonic = _("_Retry"); break; case THUNAR_JOB_RESPONSE_FORCE: mnemonic = _("Copy _Anyway"); break; case THUNAR_JOB_RESPONSE_CANCEL: /* cancel is always the last option */ has_cancel = TRUE; continue; default: g_assert_not_reached (); break; } button = gtk_button_new_with_mnemonic (mnemonic); gtk_widget_set_can_default (button, TRUE); gtk_dialog_add_action_widget (GTK_DIALOG (message), button, response); gtk_widget_show (button); gtk_dialog_set_default_response (GTK_DIALOG (message), response); } if (has_cancel) { button = gtk_button_new_with_mnemonic (_("_Cancel")); gtk_widget_set_can_default (button, TRUE); gtk_dialog_add_action_widget (GTK_DIALOG (message), button, GTK_RESPONSE_CANCEL); gtk_widget_show (button); gtk_dialog_set_default_response (GTK_DIALOG (message), GTK_RESPONSE_CANCEL); } /* run the question dialog */ response = gtk_dialog_run (GTK_DIALOG (message)); gtk_widget_destroy (message); /* transform the result as required */ if (G_UNLIKELY (response <= 0)) response = THUNAR_JOB_RESPONSE_CANCEL; /* cleanup */ g_string_free (secondary, TRUE); g_string_free (primary, TRUE); return response; }
/** * thunar_renamer_pair_copy: * @renamer_pair : a #ThunarRenamerPair. * * Allocates a copy of the specified @renamer_pair. * * The caller is responsible to free the returned pair * using thunar_renamer_pair_free() when no longer * needed. * * Return value: the newly allocated copy of @renamer_pair. **/ static ThunarRenamerPair* thunar_renamer_pair_copy (ThunarRenamerPair *renamer_pair) { _thunar_return_val_if_fail (renamer_pair != NULL, NULL); return thunar_renamer_pair_new (renamer_pair->file, renamer_pair->name); }
/** * thunar_chooser_button_get_file: * @chooser_button : a #ThunarChooserButton instance. * * Returns the #ThunarFile associated with @chooser_button. * * Return value: the file associated with @chooser_button. **/ ThunarFile* thunar_chooser_button_get_file (ThunarChooserButton *chooser_button) { _thunar_return_val_if_fail (THUNAR_IS_CHOOSER_BUTTON (chooser_button), NULL); return chooser_button->file; }
/** * thunar_folder_get_files: * @folder : a #ThunarFolder instance. * * Returns the list of files currently known for @folder. * The returned list is owned by @folder and may not be freed! * * Return value: the list of #ThunarFiles for @folder. **/ GList* thunar_folder_get_files (const ThunarFolder *folder) { _thunar_return_val_if_fail (THUNAR_IS_FOLDER (folder), NULL); return folder->files; }
/** * thunar_folder_get_loading: * @folder : a #ThunarFolder instance. * * Tells whether the contents of the @folder are currently * being loaded. * * Return value: %TRUE if @folder is loading, else %FALSE. **/ gboolean thunar_folder_get_loading (const ThunarFolder *folder) { _thunar_return_val_if_fail (THUNAR_IS_FOLDER (folder), FALSE); return (folder->job != NULL); }
/** * thunar_side_pane_get_show_hidden: * @side_pane : a #ThunarSidePane. * * Returns %TRUE if hidden folders are shown * in the @side_pane. * * Return value: %TRUE if hidden folders are * shown in the @side_pane. **/ gboolean thunar_side_pane_get_show_hidden (ThunarSidePane *side_pane) { _thunar_return_val_if_fail (THUNAR_IS_SIDE_PANE (side_pane), FALSE); return (*THUNAR_SIDE_PANE_GET_IFACE (side_pane)->get_show_hidden) (side_pane); }
/** * thunar_dbus_client_terminate: * @error : Return location for errors or %NULL. * * Tells a running Thunar instance, connected to the D-BUS * session bus, to terminate immediately. * * Return value: %TRUE if any instance was terminated, else * %FALSE and @error is set. **/ gboolean thunar_dbus_client_terminate (GError **error) { DBusConnection *connection; DBusMessage *message; DBusMessage *result; DBusError derror; _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* initialize the DBusError struct */ dbus_error_init (&derror); /* try to connect to the session bus */ connection = dbus_bus_get (DBUS_BUS_SESSION, &derror); if (G_UNLIKELY (connection == NULL)) { dbus_set_g_error (error, &derror); dbus_error_free (&derror); return FALSE; } /* generate the LaunchFiles() method (disable activation!) */ message = dbus_message_new_method_call ("org.xfce.Thunar", "/org/xfce/FileManager", "org.xfce.Thunar", "Terminate"); dbus_message_set_auto_start (message, FALSE); /* send the message and release our references on connection and message */ dbus_error_init (&derror); result = dbus_connection_send_with_reply_and_block (connection, message, -1, &derror); dbus_message_unref (message); /* check if no reply was received */ if (G_UNLIKELY (result == NULL)) { /* check if there was nothing to terminate */ if (dbus_error_has_name (&derror, DBUS_ERROR_NAME_HAS_NO_OWNER)) { dbus_error_free (&derror); return TRUE; } /* Looks like there was a real error */ dbus_set_g_error (error, &derror); dbus_error_free (&derror); return FALSE; } /* but maybe we received an error */ if (dbus_message_get_type (result) == DBUS_MESSAGE_TYPE_ERROR) { dbus_set_error_from_message (&derror, result); dbus_set_g_error (error, &derror); dbus_message_unref (result); dbus_error_free (&derror); return FALSE; } /* let's asume that it worked */ dbus_message_unref (result); return TRUE; }
gboolean thunar_dialogs_show_insecure_program (gpointer parent, const gchar *primary, ThunarFile *file, const gchar *command) { GdkScreen *screen; GtkWindow *window; gint response; GtkWidget *dialog; GString *secondary; ThunarFileMode old_mode; ThunarFileMode new_mode; GFileInfo *info; GError *err = NULL; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); _thunar_return_val_if_fail (g_utf8_validate (command, -1, NULL), FALSE); /* parse the parent window and screen */ screen = thunar_util_parse_parent (parent, &window); /* secondary text */ secondary = g_string_new (NULL); g_string_append_printf (secondary, _("The desktop file \"%s\" is in an insecure location " "and not marked as executable. If you do not trust " "this program, click Cancel."), thunar_file_get_display_name (file)); g_string_append (secondary, "\n\n"); if (exo_str_looks_like_an_uri (command)) g_string_append_printf (secondary, G_KEY_FILE_DESKTOP_KEY_URL"=%s", command); else g_string_append_printf (secondary, G_KEY_FILE_DESKTOP_KEY_EXEC"=%s", command); /* allocate and display the error message dialog */ dialog = gtk_message_dialog_new (window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, "%s", primary); gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Launch Anyway"), GTK_RESPONSE_OK); if (thunar_file_is_chmodable (file)) gtk_dialog_add_button (GTK_DIALOG (dialog), _("Mark _Executable"), GTK_RESPONSE_APPLY); gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL); if (screen != NULL && window == NULL) gtk_window_set_screen (GTK_WINDOW (dialog), screen); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", secondary->str); g_string_free (secondary, TRUE); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); /* check if we should make the file executable */ if (response == GTK_RESPONSE_APPLY) { /* try to query information about the file */ info = g_file_query_info (thunar_file_get_file (file), G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &err); if (G_LIKELY (info != NULL)) { if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE)) { /* determine the current mode */ old_mode = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE); /* generate the new mode */ new_mode = old_mode | THUNAR_FILE_MODE_USR_EXEC | THUNAR_FILE_MODE_GRP_EXEC | THUNAR_FILE_MODE_OTH_EXEC; if (old_mode != new_mode) { g_file_set_attribute_uint32 (thunar_file_get_file (file), G_FILE_ATTRIBUTE_UNIX_MODE, new_mode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &err); } } else { g_warning ("No %s attribute found", G_FILE_ATTRIBUTE_UNIX_MODE); } g_object_unref (info); } if (err != NULL) { thunar_dialogs_show_error (parent, err, ("Unable to mark launcher executable")); g_error_free (err); } /* just launch */ response = GTK_RESPONSE_OK; } return (response == GTK_RESPONSE_OK); }
/** * thunar_component_get_selected_files: * @component : a #ThunarComponent instance. * * Returns the set of selected files. Check the description * of the :selected-files property for details. * * Return value: the set of selected files. **/ GList* thunar_component_get_selected_files (ThunarComponent *component) { _thunar_return_val_if_fail (THUNAR_IS_COMPONENT (component), NULL); return (*THUNAR_COMPONENT_GET_IFACE (component)->get_selected_files) (component); }
/** * thunar_dialogs_show_job_ask_replace: * @parent : the parent #GtkWindow or %NULL. * @src_file : the #ThunarFile of the source file. * @dst_file : the #ThunarFile of the destination file that * may be replaced with the source file. * * Asks the user whether to replace the destination file with the * source file identified by @src_file. * * Return value: the selected #ThunarJobResponse. **/ ThunarJobResponse thunar_dialogs_show_job_ask_replace (GtkWindow *parent, ThunarFile *src_file, ThunarFile *dst_file) { ThunarIconFactory *icon_factory; ThunarPreferences *preferences; ThunarDateStyle date_style; GtkIconTheme *icon_theme; GtkWidget *dialog; GtkWidget *table; GtkWidget *image; GtkWidget *label; GdkPixbuf *icon; gchar *date_string; gchar *size_string; gchar *text; gint response; gboolean file_size_binary; _thunar_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), THUNAR_JOB_RESPONSE_CANCEL); _thunar_return_val_if_fail (THUNAR_IS_FILE (src_file), THUNAR_JOB_RESPONSE_CANCEL); _thunar_return_val_if_fail (THUNAR_IS_FILE (dst_file), THUNAR_JOB_RESPONSE_CANCEL); /* determine the style used to format dates */ preferences = thunar_preferences_get (); g_object_get (G_OBJECT (preferences), "misc-date-style", &date_style, NULL); g_object_get (G_OBJECT (preferences), "misc-file-size-binary", &file_size_binary, NULL); g_object_unref (G_OBJECT (preferences)); /* setup the confirmation dialog */ dialog = gtk_dialog_new_with_buttons (_("Confirm to replace files"), parent, GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("S_kip All"), THUNAR_JOB_RESPONSE_NO_ALL, _("_Skip"), THUNAR_JOB_RESPONSE_NO, _("Replace _All"), THUNAR_JOB_RESPONSE_YES_ALL, _("_Replace"), THUNAR_JOB_RESPONSE_YES, NULL); gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), THUNAR_JOB_RESPONSE_YES, THUNAR_JOB_RESPONSE_YES_ALL, THUNAR_JOB_RESPONSE_NO, THUNAR_JOB_RESPONSE_NO_ALL, GTK_RESPONSE_CANCEL, -1); gtk_dialog_set_default_response (GTK_DIALOG (dialog), THUNAR_JOB_RESPONSE_YES); /* determine the icon factory to use */ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (dialog)); icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); table = g_object_new (GTK_TYPE_TABLE, "border-width", 10, "n-columns", 3, "n-rows", 5, "row-spacing", 6, "column-spacing", 5, NULL); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, TRUE, TRUE, 0); gtk_widget_show (table); image = gtk_image_new_from_icon_name ("stock_folder-copy", GTK_ICON_SIZE_BUTTON); gtk_misc_set_alignment (GTK_MISC (image), 0.5f, 0.0f); gtk_misc_set_padding (GTK_MISC (image), 6, 6); gtk_table_attach (GTK_TABLE (table), image, 0, 1, 0, 1, GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show (image); if (thunar_file_is_symlink (dst_file)) { text = g_strdup_printf (_("This folder already contains a symbolic link \"%s\"."), thunar_file_get_display_name (dst_file)); } else if (thunar_file_is_directory (dst_file)) { text = g_strdup_printf (_("This folder already contains a folder \"%s\"."), thunar_file_get_display_name (dst_file)); } else { text = g_strdup_printf (_("This folder already contains a file \"%s\"."), thunar_file_get_display_name (dst_file)); } label = gtk_label_new (text); gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_big ()); gtk_table_attach (GTK_TABLE (table), label, 1, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (label); g_free (text); if (thunar_file_is_symlink (dst_file)) text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the link")); else if (thunar_file_is_directory (dst_file)) text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the existing folder")); else text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the existing file")); label = gtk_label_new (text); gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); gtk_table_attach (GTK_TABLE (table), label, 1, 3, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (label); g_free (text); icon = thunar_icon_factory_load_file_icon (icon_factory, dst_file, THUNAR_FILE_ICON_STATE_DEFAULT, 48); image = gtk_image_new_from_pixbuf (icon); gtk_misc_set_padding (GTK_MISC (image), 6, 6); gtk_table_attach (GTK_TABLE (table), image, 1, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0); g_object_unref (G_OBJECT (icon)); gtk_widget_show (image); size_string = thunar_file_get_size_string_formatted (dst_file, file_size_binary); date_string = thunar_file_get_date_string (dst_file, THUNAR_FILE_DATE_MODIFIED, date_style); text = g_strdup_printf ("%s %s\n%s %s", _("Size:"), size_string, _("Modified:"), date_string); label = gtk_label_new (text); gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); gtk_table_attach (GTK_TABLE (table), label, 2, 3, 2, 3, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (label); g_free (size_string); g_free (date_string); g_free (text); if (thunar_file_is_symlink (src_file)) text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following link?")); else if (thunar_file_is_directory (src_file)) text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following folder?")); else text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following file?")); label = gtk_label_new (text); gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); gtk_table_attach (GTK_TABLE (table), label, 1, 3, 3, 4, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (label); g_free (text); icon = thunar_icon_factory_load_file_icon (icon_factory, src_file, THUNAR_FILE_ICON_STATE_DEFAULT, 48); image = gtk_image_new_from_pixbuf (icon); gtk_misc_set_padding (GTK_MISC (image), 6, 6); gtk_table_attach (GTK_TABLE (table), image, 1, 2, 4, 5, GTK_FILL, GTK_FILL, 0, 0); g_object_unref (G_OBJECT (icon)); gtk_widget_show (image); size_string = thunar_file_get_size_string_formatted (src_file, file_size_binary); date_string = thunar_file_get_date_string (src_file, THUNAR_FILE_DATE_MODIFIED, date_style); text = g_strdup_printf ("%s %s\n%s %s", _("Size:"), size_string, _("Modified:"), date_string); label = gtk_label_new (text); gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); gtk_table_attach (GTK_TABLE (table), label, 2, 3, 4, 5, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (label); g_free (size_string); g_free (date_string); g_free (text); /* run the dialog */ response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); /* cleanup */ g_object_unref (G_OBJECT (icon_factory)); /* translate GTK responses */ if (G_UNLIKELY (response < 0)) response = THUNAR_JOB_RESPONSE_CANCEL; return response; }
/** * thunar_component_get_ui_manager: * @component : a #ThunarComponent instance. * * Returns the #GtkUIManager associated with @component or * %NULL if @component has no #GtkUIManager associated with * it. * * Return value: the #GtkUIManager associated with @component * or %NULL. **/ GtkUIManager* thunar_component_get_ui_manager (ThunarComponent *component) { _thunar_return_val_if_fail (THUNAR_IS_COMPONENT (component), NULL); return (*THUNAR_COMPONENT_GET_IFACE (component)->get_ui_manager) (component); }
/** * thunar_dnd_perform: * @widget : the #GtkWidget on which the drop was done. * @file : the #ThunarFile on which the @file_list was dropped. * @file_list : the list of #GFile<!---->s that was dropped. * @action : the #GdkDragAction that was performed. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * * Performs the drop of @file_list on @file in @widget, as given in * @action and returns %TRUE if the drop was started successfully * (or even completed successfully), else %FALSE. * * Return value: %TRUE if the DnD operation was started * successfully, else %FALSE. **/ gboolean thunar_dnd_perform (GtkWidget *widget, ThunarFile *file, GList *file_list, GdkDragAction action, GClosure *new_files_closure) { ThunarApplication *application; gboolean succeed = TRUE; GError *error = NULL; _thunar_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); _thunar_return_val_if_fail (gtk_widget_get_realized (widget), FALSE); /* query a reference on the application object */ application = thunar_application_get (); /* check if the file is a directory */ if (thunar_file_is_directory (file)) { /* perform the given directory operation */ switch (action) { case GDK_ACTION_COPY: thunar_application_copy_into (application, widget, file_list, thunar_file_get_file (file), new_files_closure); break; case GDK_ACTION_MOVE: thunar_application_move_into (application, widget, file_list, thunar_file_get_file (file), new_files_closure); break; case GDK_ACTION_LINK: thunar_application_link_into (application, widget, file_list, thunar_file_get_file (file), new_files_closure); break; default: succeed = FALSE; } } else if (thunar_file_is_executable (file)) { /* TODO any chance to determine the working dir here? */ succeed = thunar_file_execute (file, NULL, widget, file_list, &error); if (G_UNLIKELY (!succeed)) { /* display an error to the user */ thunar_dialogs_show_error (widget, error, _("Failed to execute file \"%s\""), thunar_file_get_display_name (file)); /* release the error */ g_error_free (error); } } else { succeed = FALSE; } /* release the application reference */ g_object_unref (G_OBJECT (application)); return succeed; }
/** * thunar_column_model_get_column_order: * @column_model : a #ThunarColumnModel. * * Returns the current #ThunarColumn order for @column_model. * * Return value: the current #ThunarColumn order for the given * @column_model instance. **/ const ThunarColumn* thunar_column_model_get_column_order (ThunarColumnModel *column_model) { _thunar_return_val_if_fail (THUNAR_IS_COLUMN_MODEL (column_model), NULL); return column_model->order; }
/** * thunar_dnd_ask: * @widget : the widget on which the drop was performed. * @folder : the #ThunarFile to which the @path_list is being dropped. * @path_list : the #GFile<!---->s of the files being dropped to @file. * @timestamp : the time of the drop event. * @actions : the list of actions supported for the drop. * * Pops up a menu that asks the user to choose one of the * @actions or to cancel the drop. If the user chooses a * valid #GdkDragAction from @actions, then this action is * returned. Else if the user cancels the drop, 0 will be * returned. * * This method can be used to implement a response to the * #GDK_ACTION_ASK action on drops. * * Return value: the selected #GdkDragAction or 0 to cancel. **/ GdkDragAction thunar_dnd_ask (GtkWidget *widget, ThunarFile *folder, GList *path_list, guint timestamp, GdkDragAction dnd_actions) { static const GdkDragAction dnd_action_items[] = { GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK }; static const gchar *dnd_action_names[] = { N_ ("_Copy here"), N_ ("_Move here"), N_ ("_Link here") }; static const gchar *dnd_action_icons[] = { "stock_folder-copy", "stock_folder-move", NULL }; ThunarxProviderFactory *factory; GdkDragAction dnd_action = 0; ThunarFile *file; GtkWidget *window; GtkWidget *image; GtkWidget *menu; GtkWidget *item; GList *file_list = NULL; GList *providers = NULL; GList *actions = NULL; GList *lp; guint n; _thunar_return_val_if_fail (thunar_file_is_directory (folder), 0); _thunar_return_val_if_fail (GTK_IS_WIDGET (widget), 0); /* connect to the provider factory */ factory = thunarx_provider_factory_get_default (); /* prepare the popup menu */ menu = gtk_menu_new (); /* append the various items */ for (n = 0; n < G_N_ELEMENTS (dnd_action_items); ++n) if (G_LIKELY ((dnd_actions & dnd_action_items[n]) != 0)) { item = gtk_image_menu_item_new_with_mnemonic (_(dnd_action_names[n])); g_object_set_data (G_OBJECT (item), I_("dnd-action"), GUINT_TO_POINTER (dnd_action_items[n])); g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (dnd_action_selected), &dnd_action); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* add image to the menu item */ if (G_LIKELY (dnd_action_icons[n] != NULL)) { image = gtk_image_new_from_icon_name (dnd_action_icons[n], GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); } } /* append the separator */ item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* determine the toplevel window the widget belongs to */ window = gtk_widget_get_toplevel (widget); if (G_LIKELY (window != NULL && gtk_widget_get_toplevel (window))) { /* check if we can resolve all paths */ for (lp = path_list; lp != NULL; lp = lp->next) { /* try to resolve this path */ file = thunar_file_cache_lookup (lp->data); if (G_LIKELY (file != NULL)) file_list = g_list_prepend (file_list, file); else break; } /* check if we resolved all paths (and have atleast one file) */ if (G_LIKELY (file_list != NULL && lp == NULL)) { /* load the menu providers from the provider factory */ providers = thunarx_provider_factory_list_providers (factory, THUNARX_TYPE_MENU_PROVIDER); /* load the dnd actions offered by the menu providers */ for (lp = providers; lp != NULL; lp = lp->next) { /* merge the actions from this provider */ actions = g_list_concat (actions, thunarx_menu_provider_get_dnd_actions (lp->data, window, THUNARX_FILE_INFO (folder), file_list)); g_object_unref (G_OBJECT (lp->data)); } g_list_free (providers); /* check if we have atleast one action */ if (G_UNLIKELY (actions != NULL)) { /* add menu items for all actions */ for (lp = actions; lp != NULL; lp = lp->next) { /* add a menu item for the action */ item = gtk_action_create_menu_item (lp->data); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); g_object_unref (G_OBJECT (lp->data)); gtk_widget_show (item); } g_list_free (actions); /* append another separator */ item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); } } } /* append the cancel item */ item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CANCEL, NULL); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* run the menu on the widget's screen (takes over the floating reference of menu) */ thunar_gtk_menu_run (GTK_MENU (menu), widget, NULL, NULL, 3, timestamp); /* cleanup */ g_object_unref (G_OBJECT (factory)); g_list_free_full (file_list, g_object_unref); return dnd_action; }
/** * thunar_dialogs_show_rename_file: * @parent : a #GtkWidget on which the error dialog should be shown, or a #GdkScreen * if no #GtkWidget is known. May also be %NULL, in which case the default * #GdkScreen will be used. * @file : the #ThunarFile we're going to rename. * * Displays the Thunar rename dialog for a single file rename. * * Return value: The #ThunarJob responsible for renaming the file or * %NULL if there was no renaming required. **/ ThunarJob * thunar_dialogs_show_rename_file (gpointer parent, ThunarFile *file) { ThunarIconFactory *icon_factory; GtkIconTheme *icon_theme; const gchar *filename; const gchar *text; ThunarJob *job = NULL; GtkWidget *dialog; GtkWidget *entry; GtkWidget *label; GtkWidget *image; GtkWidget *table; GtkWindow *window; GdkPixbuf *icon; GdkScreen *screen; glong offset; gchar *title; gint response; PangoLayout *layout; gint layout_width; gint layout_offset; gint parent_width = 500; _thunar_return_val_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WINDOW (parent), FALSE); _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); /* parse the parent window and screen */ screen = thunar_util_parse_parent (parent, &window); /* get the filename of the file */ filename = thunar_file_get_display_name (file); /* create a new dialog window */ title = g_strdup_printf (_("Rename \"%s\""), filename); dialog = gtk_dialog_new_with_buttons (title, window, GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("_Rename"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); g_free (title); /* move the dialog to the appropriate screen */ if (G_UNLIKELY (window == NULL && screen != NULL)) gtk_window_set_screen (GTK_WINDOW (dialog), screen); table = g_object_new (GTK_TYPE_TABLE, "border-width", 6, "column-spacing", 6, "row-spacing", 3, NULL); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, TRUE, TRUE, 0); gtk_widget_show (table); icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (dialog)); icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); icon = thunar_icon_factory_load_file_icon (icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, 48); g_object_unref (G_OBJECT (icon_factory)); image = gtk_image_new_from_pixbuf (icon); gtk_misc_set_padding (GTK_MISC (image), 6, 6); gtk_table_attach (GTK_TABLE (table), image, 0, 1, 0, 2, GTK_FILL, GTK_FILL, 0, 0); g_object_unref (G_OBJECT (icon)); gtk_widget_show (image); label = gtk_label_new (_("Enter the new name:")); gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (label); entry = gtk_entry_new (); gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (entry); /* setup the old filename */ gtk_entry_set_text (GTK_ENTRY (entry), filename); /* check if we don't have a directory here */ if (!thunar_file_is_directory (file)) { /* check if the filename contains an extension */ text = thunar_util_str_get_extension (filename); if (G_LIKELY (text != NULL)) { /* grab focus to the entry first, else the selection will be altered later */ gtk_widget_grab_focus (entry); /* determine the UTF-8 char offset */ offset = g_utf8_pointer_to_offset (filename, text); /* select the text prior to the dot */ if (G_LIKELY (offset > 0)) gtk_editable_select_region (GTK_EDITABLE (entry), 0, offset); } } /* get the size the entry requires to render the full text */ layout = gtk_entry_get_layout (GTK_ENTRY (entry)); pango_layout_get_pixel_size (layout, &layout_width, NULL); gtk_entry_get_layout_offsets (GTK_ENTRY (entry), &layout_offset, NULL); layout_width += (layout_offset * 2) + (12 * 4) + 48; /* 12px free space in entry */ /* parent window width */ if (G_LIKELY (window != NULL)) { /* keep below 90% of the parent window width */ gtk_window_get_size (GTK_WINDOW (window), &parent_width, NULL); parent_width *= 0.90f; } /* resize the dialog to make long names fit as much as possible */ gtk_window_set_default_size (GTK_WINDOW (dialog), CLAMP (layout_width, 300, parent_width), -1); /* run the dialog */ response = gtk_dialog_run (GTK_DIALOG (dialog)); if (G_LIKELY (response == GTK_RESPONSE_OK)) { /* hide the dialog */ gtk_widget_hide (dialog); /* determine the new filename */ text = gtk_entry_get_text (GTK_ENTRY (entry)); /* check if we have a new name here */ if (G_LIKELY (!exo_str_is_equal (filename, text))) { /* try to rename the file */ job = thunar_io_jobs_rename_file (file, text); } } /* cleanup */ gtk_widget_destroy (dialog); return job; }
GList * thunar_io_scan_directory (ThunarJob *job, GFile *file, GFileQueryInfoFlags flags, gboolean recursively, gboolean unlinking, GError **error) { GFileEnumerator *enumerator; GFileInfo *info; GFileType type; GError *err = NULL; GFile *child_file; GList *child_files = NULL; GList *files = NULL; _thunar_return_val_if_fail (THUNAR_IS_JOB (job), NULL); _thunar_return_val_if_fail (G_IS_FILE (file), NULL); _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL); /* abort if the job was cancelled */ if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) return NULL; /* don't recurse when we are scanning prior to unlinking and the current * file/dir is in the trash. In GVfs, only the top-level directories in * the trash can be modified and deleted directly. See * http://bugzilla.xfce.org/show_bug.cgi?id=7147 * for more information */ if (unlinking && thunar_g_file_is_trashed (file) && !thunar_g_file_is_root (file)) { return NULL; } /* query the file type */ type = g_file_query_file_type (file, flags, exo_job_get_cancellable (EXO_JOB (job))); /* abort if the job was cancelled */ if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) return NULL; /* ignore non-directory nodes */ if (type != G_FILE_TYPE_DIRECTORY) return NULL; /* try to read from the direectory */ enumerator = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_NAME, flags, exo_job_get_cancellable (EXO_JOB (job)), &err); /* abort if there was an error or the job was cancelled */ if (err != NULL) { g_propagate_error (error, err); return NULL; } /* query info of the first child */ info = g_file_enumerator_next_file (enumerator, exo_job_get_cancellable (EXO_JOB (job)), &err); /* iterate over children one by one as long as there's no error */ while (info != NULL && err == NULL && !exo_job_is_cancelled (EXO_JOB (job))) { /* create GFile for the child and prepend it to the file list */ child_file = g_file_get_child (file, g_file_info_get_name (info)); files = thunar_g_file_list_prepend (files, child_file); /* if the child is a directory and we need to recurse ... just do so */ if (recursively && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { child_files = thunar_io_scan_directory (job, child_file, flags, recursively, unlinking, &err); /* prepend children to the file list to make sure they're * processed first (required for unlinking) */ files = g_list_concat (child_files, files); } g_object_unref (child_file); g_object_unref (info); info = g_file_enumerator_next_file (enumerator, exo_job_get_cancellable (EXO_JOB (job)), &err); } /* release the enumerator */ g_object_unref (enumerator); if (G_UNLIKELY (err != NULL)) { g_propagate_error (error, err); thunar_g_file_list_free (files); return NULL; } else if (exo_job_set_error_if_cancelled (EXO_JOB (job), &err)) { g_propagate_error (error, err); thunar_g_file_list_free (files); return NULL; } return files; }
/** * thunar_history_get_action_group: * @history : a #ThunarHistory. * * Returns the #GtkActionGroup to which @history * is currently attached, or %NULL if @history is * not attached to any #GtkActionGroup right now. * * Return value: the #GtkActionGroup to which * @history is currently attached. **/ GtkActionGroup* thunar_history_get_action_group (const ThunarHistory *history) { _thunar_return_val_if_fail (THUNAR_IS_HISTORY (history), NULL); return history->action_group; }
/** * thunar_location_dialog_get_selected_file: * @location_dialog : a #ThunarLocationDialog. * * Returns the file selected for the @dialog or * %NULL if the file entered is not valid. * * Return value: the selected #ThunarFile or %NULL. **/ ThunarFile* thunar_location_dialog_get_selected_file (ThunarLocationDialog *location_dialog) { _thunar_return_val_if_fail (THUNAR_IS_LOCATION_DIALOG (location_dialog), NULL); return thunar_path_entry_get_current_file (THUNAR_PATH_ENTRY (location_dialog->entry)); }
gboolean thunar_progress_dialog_has_jobs (ThunarProgressDialog *dialog) { _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), FALSE); return dialog->views != NULL; }
/** * thunar_folder_get_corresponding_file: * @folder : a #ThunarFolder instance. * * Returns the #ThunarFile corresponding to this @folder. * * No reference is taken on the returned #ThunarFile for * the caller, so if you need a persistent reference to * the file, you'll have to call g_object_ref() yourself. * * Return value: the #ThunarFile corresponding to @folder. **/ ThunarFile* thunar_folder_get_corresponding_file (const ThunarFolder *folder) { _thunar_return_val_if_fail (THUNAR_IS_FOLDER (folder), NULL); return folder->corresponding_file; }
/** * thunar_navigator_get_current_directory: * @navigator : a #ThunarNavigator instance. * * Returns the directory currently displayed by @navigator * or %NULL, if @navigator does not currently display and * directory. * * Return value: the current directory of @navigator or %NULL. **/ ThunarFile* thunar_navigator_get_current_directory (ThunarNavigator *navigator) { _thunar_return_val_if_fail (THUNAR_IS_NAVIGATOR (navigator), NULL); return THUNAR_NAVIGATOR_GET_IFACE (navigator)->get_current_directory (navigator); }
/** * thunar_dialogs_show_job_ask_replace: * @parent : the parent #GtkWindow or %NULL. * @src_file : the #ThunarFile of the source file. * @dst_file : the #ThunarFile of the destination file that * may be replaced with the source file. * * Asks the user whether to replace the destination file with the * source file identified by @src_file. * * Return value: the selected #ThunarJobResponse. **/ ThunarJobResponse thunar_dialogs_show_job_ask_replace (GtkWindow *parent, ThunarFile *src_file, ThunarFile *dst_file) { ThunarIconFactory *icon_factory; ThunarPreferences *preferences; ThunarDateStyle date_style; GtkIconTheme *icon_theme; GtkWidget *dialog; GtkWidget *grid; GtkWidget *image; GtkWidget *label; GdkPixbuf *icon; gchar *date_custom_style; gchar *date_string; gchar *size_string; gchar *text; gint response; gboolean file_size_binary; _thunar_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), THUNAR_JOB_RESPONSE_CANCEL); _thunar_return_val_if_fail (THUNAR_IS_FILE (src_file), THUNAR_JOB_RESPONSE_CANCEL); _thunar_return_val_if_fail (THUNAR_IS_FILE (dst_file), THUNAR_JOB_RESPONSE_CANCEL); /* determine the style used to format dates */ preferences = thunar_preferences_get (); g_object_get (G_OBJECT (preferences), "misc-date-style", &date_style, NULL); g_object_get (G_OBJECT (preferences), "misc-date-custom-style", &date_custom_style, NULL); g_object_get (G_OBJECT (preferences), "misc-file-size-binary", &file_size_binary, NULL); g_object_unref (G_OBJECT (preferences)); /* setup the confirmation dialog */ dialog = gtk_dialog_new_with_buttons (_("Confirm to replace files"), parent, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, _("_Cancel"), GTK_RESPONSE_CANCEL, _("S_kip All"), THUNAR_JOB_RESPONSE_NO_ALL, _("_Skip"), THUNAR_JOB_RESPONSE_NO, _("Replace _All"), THUNAR_JOB_RESPONSE_YES_ALL, _("_Replace"), THUNAR_JOB_RESPONSE_YES, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), THUNAR_JOB_RESPONSE_YES); /* determine the icon factory to use */ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (dialog)); icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); grid = gtk_grid_new (); gtk_grid_set_column_spacing (GTK_GRID (grid), 5); gtk_grid_set_row_spacing (GTK_GRID (grid), 6); gtk_container_set_border_width (GTK_CONTAINER (grid), 10); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), grid, TRUE, TRUE, 0); gtk_widget_show (grid); image = gtk_image_new_from_icon_name ("stock_folder-copy", GTK_ICON_SIZE_BUTTON); gtk_widget_set_halign (image, GTK_ALIGN_CENTER); gtk_widget_set_valign (image, GTK_ALIGN_START); gtk_widget_set_margin_start (GTK_WIDGET(image), 6); gtk_widget_set_margin_end (GTK_WIDGET(image), 6); gtk_widget_set_margin_top (GTK_WIDGET(image), 6); gtk_widget_set_margin_bottom (GTK_WIDGET(image), 6); gtk_widget_set_vexpand (image, TRUE); gtk_grid_attach (GTK_GRID (grid), image, 0, 0, 1, 1); gtk_widget_show (image); if (thunar_file_is_symlink (dst_file)) { text = g_strdup_printf (_("This folder already contains a symbolic link \"%s\"."), thunar_file_get_display_name (dst_file)); } else if (thunar_file_is_directory (dst_file)) { text = g_strdup_printf (_("This folder already contains a folder \"%s\"."), thunar_file_get_display_name (dst_file)); } else { text = g_strdup_printf (_("This folder already contains a file \"%s\"."), thunar_file_get_display_name (dst_file)); } label = gtk_label_new (text); gtk_label_set_xalign (GTK_LABEL (label), 0.0f); gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_big ()); gtk_widget_set_hexpand (label, TRUE); gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 2, 1); gtk_widget_show (label); g_free (text); if (thunar_file_is_symlink (dst_file)) text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the link")); else if (thunar_file_is_directory (dst_file)) text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the existing folder")); else text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the existing file")); label = gtk_label_new (text); gtk_label_set_xalign (GTK_LABEL (label), 0.0f); gtk_widget_set_hexpand (label, TRUE); gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 2, 1); gtk_widget_show (label); g_free (text); icon = thunar_icon_factory_load_file_icon (icon_factory, dst_file, THUNAR_FILE_ICON_STATE_DEFAULT, 48); image = gtk_image_new_from_pixbuf (icon); gtk_widget_set_margin_start (GTK_WIDGET(image), 6); gtk_widget_set_margin_end (GTK_WIDGET(image), 6); gtk_widget_set_margin_top (GTK_WIDGET(image), 6); gtk_widget_set_margin_bottom (GTK_WIDGET(image), 6); gtk_grid_attach (GTK_GRID (grid), image, 1, 2, 1, 1); g_object_unref (G_OBJECT (icon)); gtk_widget_show (image); size_string = thunar_file_get_size_string_long (dst_file, file_size_binary); date_string = thunar_file_get_date_string (dst_file, THUNAR_FILE_DATE_MODIFIED, date_style, date_custom_style); text = g_strdup_printf ("%s %s\n%s %s", _("Size:"), size_string, _("Modified:"), date_string); label = gtk_label_new (text); gtk_label_set_xalign (GTK_LABEL (label), 0.0f); gtk_widget_set_hexpand (label, TRUE); gtk_grid_attach (GTK_GRID (grid), label, 2, 2, 1, 1); gtk_widget_show (label); g_free (size_string); g_free (date_string); g_free (text); if (thunar_file_is_symlink (src_file)) text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following link?")); else if (thunar_file_is_directory (src_file)) text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following folder?")); else text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following file?")); label = gtk_label_new (text); gtk_label_set_xalign (GTK_LABEL (label), 0.0f); gtk_widget_set_hexpand (label, TRUE); gtk_grid_attach (GTK_GRID (grid), label, 1, 3, 2, 1); gtk_widget_show (label); g_free (text); icon = thunar_icon_factory_load_file_icon (icon_factory, src_file, THUNAR_FILE_ICON_STATE_DEFAULT, 48); image = gtk_image_new_from_pixbuf (icon); gtk_widget_set_margin_start (GTK_WIDGET(image), 6); gtk_widget_set_margin_end (GTK_WIDGET(image), 6); gtk_widget_set_margin_top (GTK_WIDGET(image), 6); gtk_widget_set_margin_bottom (GTK_WIDGET(image), 6); gtk_grid_attach (GTK_GRID (grid), image, 1, 4, 1, 1); g_object_unref (G_OBJECT (icon)); gtk_widget_show (image); size_string = thunar_file_get_size_string_long (src_file, file_size_binary); date_string = thunar_file_get_date_string (src_file, THUNAR_FILE_DATE_MODIFIED, date_style, date_custom_style); text = g_strdup_printf ("%s %s\n%s %s", _("Size:"), size_string, _("Modified:"), date_string); label = gtk_label_new (text); gtk_label_set_xalign (GTK_LABEL (label), 0.0f); gtk_widget_set_hexpand (label, TRUE); gtk_grid_attach (GTK_GRID (grid), label, 2, 4, 1, 1); gtk_widget_show (label); g_free (size_string); g_free (date_string); g_free (text); /* run the dialog */ response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); /* cleanup */ g_object_unref (G_OBJECT (icon_factory)); /* translate GTK responses */ if (G_UNLIKELY (response < 0)) response = THUNAR_JOB_RESPONSE_CANCEL; return response; }