*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
+#include <config.h>
+
#include "ev-utils.h"
+#include "ev-file-helpers.h"
+
+#include <string.h>
#include <math.h>
+#include <glib/gi18n.h>
typedef struct
{
}
-#ifndef HAVE_G_FILE_SET_CONTENTS
+/* Simple function to output the contents of a region. Used solely for testing
+ * the region code.
+ */
+void
+ev_print_region_contents (cairo_region_t *region)
+{
+ gint n_rectangles, i;
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <string.h>
+ if (region == NULL) {
+ g_print ("<empty region>\n");
+ return;
+ }
-static gboolean
-rename_file (const char *old_name,
- const char *new_name,
- GError **err)
-{
- errno = 0;
- if (g_rename (old_name, new_name) == -1)
- {
- return FALSE;
- }
-
- return TRUE;
+ g_print ("<region %p>\n", region);
+ n_rectangles = cairo_region_num_rectangles (region);
+ for (i = 0; i < n_rectangles; i++) {
+ GdkRectangle rect;
+
+ cairo_region_get_rectangle (region, i, &rect);
+ g_print ("\t(%d %d, %d %d) [%dx%d]\n",
+ rect.x,
+ rect.y,
+ rect.x + rect.width,
+ rect.y + rect.height,
+ rect.width,
+ rect.height);
+ }
}
-static gboolean
-set_umask_permissions (int fd,
- GError **err)
+static void
+ev_gui_sanitise_popup_position (GtkMenu *menu,
+ GtkWidget *widget,
+ gint *x,
+ gint *y)
{
- /* All of this function is just to work around the fact that
- * there is no way to get the umask without changing it.
- *
- * We can't just change-and-reset the umask because that would
- * lead to a race condition if another thread tried to change
- * the umask in between the getting and the setting of the umask.
- * So we have to do the whole thing in a child process.
- */
-
- int save_errno;
- pid_t pid;
-
- pid = fork ();
-
- if (pid == -1)
- {
- return FALSE;
- }
- else if (pid == 0)
- {
- /* child */
- mode_t mask = umask (0666);
+ GdkScreen *screen = gtk_widget_get_screen (widget);
+ gint monitor_num;
+ GdkRectangle monitor;
+ GtkRequisition req;
- errno = 0;
- if (fchmod (fd, 0666 & ~mask) == -1)
- _exit (errno);
- else
- _exit (0);
+ g_return_if_fail (widget != NULL);
- return TRUE; /* To quiet gcc */
- }
- else
- {
- /* parent */
- int status;
+ gtk_widget_size_request (GTK_WIDGET (menu), &req);
- errno = 0;
- if (waitpid (pid, &status, 0) == -1)
- {
- return FALSE;
- }
-
- if (WIFEXITED (status))
- {
- save_errno = WEXITSTATUS (status);
+ monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
+ gtk_menu_set_monitor (menu, monitor_num);
+ gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
- if (save_errno == 0)
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- else if (WIFSIGNALED (status))
- {
- return FALSE;
- }
- else
- {
- return FALSE;
- }
- }
+ *x = CLAMP (*x, monitor.x, monitor.x + MAX (0, monitor.width - req.width));
+ *y = CLAMP (*y, monitor.y, monitor.y + MAX (0, monitor.height - req.height));
}
-static gchar *
-write_to_temp_file (const gchar *contents,
- gssize length,
- const gchar *template,
- GError **err)
+void
+ev_gui_menu_position_tree_selection (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data)
{
- gchar *tmp_name;
- gchar *display_name;
- gchar *retval;
- FILE *file;
- gint fd;
- int save_errno;
-
- retval = NULL;
-
- tmp_name = g_strdup_printf ("%s.XXXXXX", template);
-
- errno = 0;
- fd = g_mkstemp (tmp_name);
- display_name = g_filename_display_name (tmp_name);
-
- if (fd == -1)
- {
- goto out;
- }
-
- if (!set_umask_permissions (fd, err))
- {
- close (fd);
- g_unlink (tmp_name);
-
- goto out;
- }
-
- errno = 0;
- file = fdopen (fd, "wb");
- if (!file)
- {
- close (fd);
- g_unlink (tmp_name);
-
- goto out;
- }
+ GtkTreeSelection *selection;
+ GList *selected_rows;
+ GtkTreeModel *model;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (user_data);
+ GtkWidget *widget = GTK_WIDGET (user_data);
+ GtkRequisition req;
+ GtkAllocation allocation;
+ GdkRectangle visible;
+
+ gtk_widget_size_request (GTK_WIDGET (menu), &req);
+ gdk_window_get_origin (gtk_widget_get_window (widget), x, y);
+ gtk_widget_get_allocation (widget, &allocation);
+
+ *x += (allocation.width - req.width) / 2;
+
+ /* Add on height for the treeview title */
+ gtk_tree_view_get_visible_rect (tree_view, &visible);
+ *y += allocation.height - visible.height;
+
+ selection = gtk_tree_view_get_selection (tree_view);
+ selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
+ if (selected_rows)
+ {
+ GdkRectangle cell_rect;
- if (length > 0)
- {
- size_t n_written;
-
- errno = 0;
+ gtk_tree_view_get_cell_area (tree_view, selected_rows->data,
+ NULL, &cell_rect);
- n_written = fwrite (contents, 1, length, file);
+ *y += CLAMP (cell_rect.y + cell_rect.height, 0, visible.height);
- if (n_written < length)
- {
- fclose (file);
- g_unlink (tmp_name);
-
- goto out;
+ g_list_foreach (selected_rows, (GFunc)gtk_tree_path_free, NULL);
+ g_list_free (selected_rows);
}
- }
-
- errno = 0;
- if (fclose (file) == EOF)
- {
- g_unlink (tmp_name);
-
- goto out;
- }
- retval = g_strdup (tmp_name);
-
- out:
- g_free (tmp_name);
- g_free (display_name);
-
- return retval;
+ ev_gui_sanitise_popup_position (menu, widget, x, y);
}
-gboolean
-ev_file_set_contents (const gchar *filename,
- const gchar *contents,
- gssize length,
- GError **error)
+/**
+ * get_num_monitors: Get the number of user monitors.
+ * @window: optional GtkWindow to look at.
+ *
+ * Returns: Number of monitors, -1 if uncertain situation (like multiple screens)
+ */
+gint
+get_num_monitors (GtkWindow *window)
{
- gchar *tmp_filename;
- gboolean retval;
- GError *rename_error = NULL;
-
- g_return_val_if_fail (filename != NULL, FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- g_return_val_if_fail (contents != NULL || length == 0, FALSE);
- g_return_val_if_fail (length >= -1, FALSE);
-
- if (length == -1)
- length = strlen (contents);
+ GdkDisplay *display;
+ GdkScreen *screen;
+ gint num_screen;
+
+ display = gdk_display_get_default ();
+ num_screen = gdk_display_get_n_screens (display);
+
+ if (num_screen != 1)
+ return -1;
+
+ if (window)
+ screen = gtk_window_get_screen (window);
+ else
+ screen = gdk_display_get_screen (display, 0);
+
+ return gdk_screen_get_n_monitors (screen);
+}
- tmp_filename = write_to_temp_file (contents, length, filename, error);
+void
+file_chooser_dialog_add_writable_pixbuf_formats (GtkFileChooser *chooser)
+{
+ GSList *pixbuf_formats = NULL;
+ GSList *iter;
+ GtkFileFilter *filter;
+ int i;
- if (!tmp_filename)
- {
- retval = FALSE;
- goto out;
- }
-
- if (!rename_file (tmp_filename, filename, &rename_error))
- {
- g_unlink (tmp_filename);
- g_propagate_error (error, rename_error);
- retval = FALSE;
- goto out;
- }
+ filter = gtk_file_filter_new();
+ gtk_file_filter_set_name (filter, _("By extension"));
+ g_object_set_data (G_OBJECT(filter), "pixbuf-format", NULL);
+ gtk_file_chooser_add_filter (chooser, filter);
+
+ pixbuf_formats = gdk_pixbuf_get_formats ();
+
+ for (iter = pixbuf_formats; iter; iter = iter->next) {
+ GdkPixbufFormat *format = iter->data;
+
+ gchar *description, *name, *extensions;
+ gchar **extension_list, **mime_types;
+
+ if (gdk_pixbuf_format_is_disabled (format) ||
+ !gdk_pixbuf_format_is_writable (format))
+ continue;
+
+ name = gdk_pixbuf_format_get_description (format);
+ extension_list = gdk_pixbuf_format_get_extensions (format);
+ extensions = g_strjoinv (", ", extension_list);
+ g_strfreev (extension_list);
+ description = g_strdup_printf ("%s (%s)", name, extensions);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, description);
+ g_object_set_data (G_OBJECT (filter), "pixbuf-format", format);
+ gtk_file_chooser_add_filter (chooser, filter);
+
+ g_free (description);
+ g_free (extensions);
+ g_free (name);
+
+ mime_types = gdk_pixbuf_format_get_mime_types (format);
+ for (i = 0; mime_types[i] != 0; i++)
+ gtk_file_filter_add_mime_type (filter, mime_types[i]);
+ g_strfreev (mime_types);
+ }
- retval = TRUE;
-
- out:
- g_free (tmp_filename);
- return retval;
+ g_slist_free (pixbuf_formats);
}
-#endif /* HAVE_G_FILE_SET_CONTENTS */
+GdkPixbufFormat*
+get_gdk_pixbuf_format_by_extension (gchar *uri)
+{
+ GSList *pixbuf_formats = NULL;
+ GSList *iter;
+ int i;
+
+ pixbuf_formats = gdk_pixbuf_get_formats ();
+
+ for (iter = pixbuf_formats; iter; iter = iter->next) {
+ gchar **extension_list;
+ GdkPixbufFormat *format = iter->data;
+
+ if (gdk_pixbuf_format_is_disabled (format) ||
+ !gdk_pixbuf_format_is_writable (format))
+ continue;
+
+ extension_list = gdk_pixbuf_format_get_extensions (format);
+
+ for (i = 0; extension_list[i] != 0; i++) {
+ if (g_str_has_suffix (uri, extension_list[i])) {
+ g_slist_free (pixbuf_formats);
+ g_strfreev (extension_list);
+ return format;
+ }
+ }
+ g_strfreev (extension_list);
+ }
+ g_slist_free (pixbuf_formats);
+ return NULL;
+}