* Viewing raster and vector images, in the following formats:
3FR, ANI, APM, ARW, AVIF, BMP, CR2, CR3, CRW, CUR, DDS, DjVu, DNG, ERF, GIF, HEIC, HEIF, ICNS, ICO, JP2. JPE/JPEG/JPG, JPEG XL, JPS, KDC, MEF, MOS, MPO, MRW, NEF, ORF, PBM/PGM/PNM/PPM, PEF, PNG, PSD, PTX, QIF/QTIF (QuickTime Image Format), RAF, RAW, RW2, SR2, SRF, SVG/SVGZ, TGA/TARGA, TIF/TIFF, WEBP, WMF, XBM, XPM.
-Animated GIFs are supported.
+ * Display images in archive files (.ZIP, .RAR etc.).
+ * Animated GIFs are supported.
* Preview and thumbnails of video clips can be displayed. Clips can be run via a defined external program.
libraw 0.20
For displaying CR3 images
+ libarchive 3.4.3
+ For opening archive files (.ZIP, .RAR etc.)
+
yelp-tools
For creating the Help files
AC_SUBST(WEBP_CFLAGS)
AC_SUBST(WEBP_LIBS)
+# Libarchive support
+# ----------------------------------------------------------------------
+
+AC_ARG_ENABLE([archive],
+ AC_HELP_STRING([--disable-archive], [disable archive support]),
+ [libarchive=$enableval], [libarchive=auto])
+
+if test "x${libarchive}" != "xno"; then
+ PKG_CHECK_MODULES(ARCHIVE, libarchive >= 3.4.3,
+ [
+ HAVE_ARCHIVE=yes
+ AC_DEFINE(HAVE_ARCHIVE, 1, [define to enable archive support])
+ ],
+ [
+ HAVE_ARCHIVE=no
+ AC_MSG_WARN([$ARCHIVE_PKG_ERRORS])
+ ])
+else
+ HAVE_ARCHIVE=disabled
+fi
+
+AM_CONDITIONAL(HAVE_ARCHIVE, [test "x$HAVE_ARCHIVE" = xyes])
+AC_SUBST(ARCHIVE_CFLAGS)
+AC_SUBST(ARCHIVE_LIBS)
+
# J2K support
# ----------------------------------------------------------------------
plugins/image-crop/Makefile
plugins/random-image/Makefile
plugins/lens/Makefile
- plugins/open-archive/Makefile
geeqie.spec
])
J2K: $HAVE_J2K
LibRaw: $HAVE_RAW
Libjxl: $HAVE_JPEGXL
+ Libarchive: $HAVE_ARCHIVE
Documentation:
Doxygen: $DX_DOXYGEN
<para>If selected, mouse left-click will select the next image; mouse middle-click will select the previous image.</para>\r
</listitem>\r
</varlistentry>\r
+ <varlistentry>\r
+ <term>\r
+ <guilabel>Open archive by left click on image</guilabel>\r
+ </term>\r
+ <listitem>\r
+ <para>If selected, mouse left-click on an image belonging to the archive class will decompress the file contents and display them in a new Geeqie window.</para>\r
+ </listitem>\r
+ </varlistentry>\r
<varlistentry>\r
<term>\r
<guilabel>Play video by left click on image</guilabel>\r
<listitem>Video</listitem>\r
<listitem>Collection</listitem>\r
<listitem>Document</listitem>\r
+ <listitem>Archive (.zip, .rar etc.)</listitem>\r
</itemizedlist>\r
</listitem>\r
</varlistentry>\r
<title id="titleGuideReferencePixbufLoaders">Additional pixbuf loaders</title>\r
<para>Geeqie can display files for which there are existing pixbuf loaders. In addition to the standard ones included with most distributions, the following loaders may also be available to you.</para>\r
<para>However, in some cases you are required to compile and install them yourself.</para>\r
- <section id="svg">\r
- <title>svg</title>\r
- <para>librsvg2-common</para>\r
- </section>\r
- <section id="wmf">\r
- <title>wmf</title>\r
- <para>libwmf0.2-7-gtk</para>\r
- </section>\r
<section id="jp2">\r
<title>JP2/JPC/JPX/J2K/JPF</title>\r
<para>If your distribution has the libpixbufloader-jasper.so loader, these file formats will also be displayed.</para>\r
menu.\r
</para>\r
</section>\r
- <section id="OpenArchive">\r
- <title>Open archive file</title>\r
- <para>\r
- Opens an archive file (of the type .zip, .rar, .cbr, .tar.gz) and extracts the contents into a folder in <code>/tmp</code>. A new Geeqie window is opened in that folder.\r
- </para>\r
- <para>\r
- This item is displayed in the\r
- <emphasis role="strong">Plugins</emphasis>\r
- menu.\r
- </para>\r
- </section>\r
</section>\r
<?xml version="1.0" encoding="utf-8"?>\r
<section id="GuideReferenceSupportedFormats">\r
<title id="titleGuideReferenceSupportedFormats">Supported File Formats</title>\r
- <para>3FR, ANI, APM, ARW, BMP, CR2, CRW, CUR, DDS, DNG, ERF, GIF, ICNS, ICO, JPE/JPEG/JPG, JPS, KDC, MEF, MPO, MOS, MRW, NEF, ORF, PEF, PTX, PBM/PGM/PNM/PPM, PNG, QIF/QTIF (QuickTime Image Format), RAF, RAW, RW2, SR2, SRF, SVG/SVGZ, TGA/TARGA, TIF/TIFF, WMF, XBM, XPM, HEIF (primary image only), WebP, DjVu. Animated GIFs are supported.</para>\r
+ <para>3FR, ANI, APM, ARW, BMP, CR2, CRW, CUR, DDS, DNG, ERF, GIF, ICNS, ICO, JPE/JPEG/JPG, JPS, KDC, MEF, MPO, MOS, MRW, NEF, ORF, PEF, PTX, PBM/PGM/PNM/PPM, PNG, QIF/QTIF (QuickTime Image Format), RAF, RAW, RW2, SR2, SRF, SVG/SVGZ, TGA/TARGA, TIF/TIFF, WMF, XBM, XPM, HEIF (primary image only), WebP, DjVu.</para>\r
+ <para>Images in archive files (.zip, .tar etc) can be displayed.\r
+ </para>\r
+ <para>Animated GIFs are supported.\r
+ </para>\r
<para>\r
Refer to\r
<link linkend="GuideReferencePixbufLoaders" endterm="titleGuideReferencePixbufLoaders" />\r
-SUBDIRS = rotate symlink ufraw geocode-parameters export-jpeg tethered-photography camera-import image-crop random-image lens open-archive
+SUBDIRS = rotate symlink ufraw geocode-parameters export-jpeg tethered-photography camera-import image-crop random-image lens
qq_desktoptemplatedir = $(appdir)
qq_desktoptemplate_in_files = template.desktop.in
qq_desktoptemplate_DATA = $(qq_desktoptemplate_in_files:.desktop.in=.desktop)
+++ /dev/null
-dist_gq_bin_SCRIPTS = geeqie-open-archive
-
-gq_desktopdir = $(appdir)/applications
-gq_desktop_in_files = open-archive.desktop.in
-gq_desktop_DATA = $(gq_desktop_in_files:.desktop.in=.desktop)
-@INTLTOOL_DESKTOP_RULE@
-
-EXTRA_DIST = $(gq_desktop_in_files)
-CLEANFILES = $(gq_desktop_DATA)
-
+++ /dev/null
-#!/bin/bash
-
-# Extract the contents of an archive file to a
-# temporary folder under /tmp.
-#
-# Open a new Geeqie window pointing to that folder.
-
-full_path=$(realpath "$1")
-filename=$(basename -- "$1")
-extension="${filename#*.}"
-
-case $extension in
-
- zip)
- if [ $(which unzip > /dev/null; echo $? ) = 0 ]
- then
- rm --recursive --force "/tmp/geeqie-archive/$full_path"
- mkdir --parents "/tmp/geeqie-archive/$full_path"
- unzip "$full_path" -d "/tmp/geeqie-archive/$full_path" > /dev/null
- geeqie --remote --new-window "/tmp/geeqie-archive/$full_path"
- else
- zenity --title="Geeqie Open Archive" --info --width=300 --text="Utility unzip is not installed"
- fi
- ;;
-
- tar.gz)
- if [ $(which tar > /dev/null; echo $? ) = 0 ]
- then
- rm --recursive --force "/tmp/geeqie-archive/$full_path"
- mkdir --parents "/tmp/geeqie-archive/$full_path"
- tar --extract --gunzip --directory "/tmp/geeqie-archive/$full_path" --file="$full_path" > /dev/null
- geeqie --remote --new-window "/tmp/geeqie-archive/$full_path"
- else
- zenity --title="Geeqie Open Archive" --info --width=300 --text="Utility tar is not installed"
- fi
- ;;
-
- cbr | rar)
- if [ $(which unrar > /dev/null; echo $? ) = 0 ]
- then
- rm --recursive --force rf "/tmp/geeqie-archive/$full_path"
- mkdir --parents "/tmp/geeqie-archive/$full_path"
- unrar "$full_path" "/tmp/geeqie-archive/$full_path" > /dev/null
- geeqie --remote --new-window "/tmp/geeqie-archive/$full_path"
- else
- zenity --title="Geeqie Open Archive" --info --width=300 --text="Utility unrar is not installed"
- fi
- ;;
-
- *)
- zenity --title="Geeqie Open Archive" --info --width=300 --text="This is not a known archive file type"
- ;;
-esac
-
+++ /dev/null
-[Desktop Entry]
-Version=1.0
-Type=Application
-_Name=Open archive file
-
-# call the helper script
-Exec=geeqie-open-archive %f
-
-# Desktop files that are usable only in Geeqie should be marked like this:
-Categories=X-Geeqie;
-OnlyShowIn=X-Geeqie;
-
-# It can be made verbose
-# X-Geeqie-Verbose=true
-
-Icon=package-x-generic
zonedetect.c \
zonedetect.h
-geeqie_LDADD = $(GTK_LIBS) $(GLIB_LIBS) $(INTLLIBS) $(JPEG_LIBS) $(TIFF_LIBS) $(LCMS_LIBS) $(EXIV2_LIBS) $(LIBCHAMPLAIN_LIBS) $(LIBCHAMPLAIN_GTK_LIBS) $(LUA_LIBS) $(CLUTTER_LIBS) $(CLUTTER_GTK_LIBS) $(FFMPEGTHUMBNAILER_LIBS) $(PDF_LIBS) $(HEIF_LIBS) $(WEBP_LIBS) $(DJVU_LIBS) $(J2K_LIBS) $(RAW_LIBS) $(JPEGXL_LIBS)
+geeqie_LDADD = $(GTK_LIBS) $(GLIB_LIBS) $(INTLLIBS) $(JPEG_LIBS) $(TIFF_LIBS) $(LCMS_LIBS) $(EXIV2_LIBS) $(LIBCHAMPLAIN_LIBS) $(LIBCHAMPLAIN_GTK_LIBS) $(LUA_LIBS) $(CLUTTER_LIBS) $(CLUTTER_GTK_LIBS) $(FFMPEGTHUMBNAILER_LIBS) $(PDF_LIBS) $(HEIF_LIBS) $(WEBP_LIBS) $(DJVU_LIBS) $(J2K_LIBS) $(RAW_LIBS) $(JPEGXL_LIBS) $(ARCHIVE_LIBS)
EXTRA_DIST = \
$(extra_SLIK)
#endif
#ifdef HAVE_J2K
filter_add_if_missing("jp2", "JPEG 2000", ".jp2", FORMAT_CLASS_IMAGE, FALSE, FALSE, TRUE);
+#endif
+#ifdef HAVE_ARCHIVE
+ filter_add_if_missing("zip", "Archive files", ".zip;.rar;.tar;.tar.gz;.cbr;.cbz;.bz2;.lzh;.lza;.7z", FORMAT_CLASS_ARCHIVE, FALSE, FALSE, TRUE);
#endif
filter_add_if_missing("psd", "Adobe Photoshop Document", ".psd", FORMAT_CLASS_IMAGE, FALSE, FALSE, TRUE);
filter_add_if_missing("apng", "Animated Portable Network Graphic", ".apng", FORMAT_CLASS_IMAGE, FALSE, FALSE, TRUE);
- filter_add_if_missing("zip", "Archive files", ".zip;.rar;.cbr;tar.gz", FORMAT_CLASS_ARCHIVE, FALSE, FALSE, TRUE);
}
GList *filter_to_list(const gchar *extensions)
{
ViewWindow *vw = data;
GtkWidget *menu;
+ gchar *dest_dir;
+ LayoutWindow *lw_new;
switch (event->button)
{
case MOUSE_BUTTON_LEFT:
- if (options->image_l_click_video && options->image_l_click_video_editor && imd->image_fd->format_class == FORMAT_CLASS_VIDEO)
+ if (options->image_l_click_archive && imd->image_fd->format_class == FORMAT_CLASS_ARCHIVE)
+ {
+ dest_dir = open_archive(imd->image_fd);
+ if (dest_dir)
+ {
+ lw_new = layout_new_from_default();
+ layout_set_path(lw_new, dest_dir);
+ g_free(dest_dir);
+ }
+ else
+ {
+ warning_dialog(_("Cannot open archive file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
+ }
+ }
+ else if (options->image_l_click_video && options->image_l_click_video_editor && imd->image_fd->format_class == FORMAT_CLASS_VIDEO)
{
start_editor_from_file(options->image_l_click_video_editor, imd->image_fd);
}
{
LayoutWindow *lw = data;
GtkWidget *menu;
+ LayoutWindow *lw_new;
+ gchar *dest_dir;
switch (event->button)
{
case MOUSE_BUTTON_LEFT:
- if (options->image_l_click_video && options->image_l_click_video_editor && imd->image_fd && imd->image_fd->format_class == FORMAT_CLASS_VIDEO)
+ if (options->image_l_click_archive && imd-> image_fd && imd->image_fd->format_class == FORMAT_CLASS_ARCHIVE)
+ {
+ dest_dir = open_archive(imd->image_fd);
+ if (dest_dir)
+ {
+ lw_new = layout_new_from_default();
+ layout_set_path(lw_new, dest_dir);
+ g_free(dest_dir);
+ }
+ else
+ {
+ warning_dialog(_("Cannot open archive file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
+ }
+ }
+ else if (options->image_l_click_video && options->image_l_click_video_editor && imd-> image_fd && imd->image_fd->format_class == FORMAT_CLASS_VIDEO)
{
start_editor_from_file(options->image_l_click_video_editor, imd->image_fd);
}
view_window_new(layout_image_get_fd(lw));
}
+static void layout_menu_open_archive_cb(GtkAction *action, gpointer data)
+{
+ LayoutWindow *lw = data;
+ LayoutWindow *lw_new;
+ gchar *dest_dir;
+ FileData *fd;
+
+ layout_exit_fullscreen(lw);
+ fd = layout_image_get_fd(lw);
+
+ if (fd->format_class == FORMAT_CLASS_ARCHIVE)
+ {
+ dest_dir = open_archive(layout_image_get_fd(lw));
+ lw_new = layout_new_from_default();
+ layout_set_path(lw_new, dest_dir);
+ g_free(dest_dir);
+ }
+}
+
static void layout_menu_fullscreen_cb(GtkAction *action, gpointer data)
{
LayoutWindow *lw = data;
}
}
+static void layout_menu_view_menu_cb(GtkWidget *widget, gpointer data)
+{
+ LayoutWindow *lw = data;
+ GtkWidget *menu;
+ GtkWidget *sub_menu;
+ gchar *menu_label;
+ GList *children, *iter;
+ gint i;
+ FileData *fd;
+
+ menu = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu/ViewMenu/");
+ sub_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
+
+ fd = layout_image_get_fd(lw);
+
+ i = 0;
+ children = gtk_container_get_children(GTK_CONTAINER(sub_menu));
+ for (iter = children; iter != NULL; iter = g_list_next(iter), i++)
+ {
+ menu_label = g_strdup(gtk_menu_item_get_label(GTK_MENU_ITEM(iter->data)));
+ if (g_strcmp0(menu_label, _("Open archive")) == 0)
+ {
+ if (fd->format_class == FORMAT_CLASS_ARCHIVE)
+ {
+ gtk_widget_set_sensitive(GTK_WIDGET(iter->data), TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive(GTK_WIDGET(iter->data), FALSE);
+ }
+ }
+ g_free(menu_label);
+ }
+ g_list_free(children);
+}
+
static void change_window_id(const gchar *infile, const gchar *outfile)
{
GFile *in_file;
{ "OrientationMenu", NULL, N_("_Orientation"), NULL, NULL, NULL },
{ "RatingMenu", NULL, N_("_Rating"), NULL, NULL, NULL },
{ "PreferencesMenu", NULL, N_("P_references"), NULL, NULL, NULL },
- { "ViewMenu", NULL, N_("_View"), NULL, NULL, NULL },
+ { "ViewMenu", NULL, N_("_View"), NULL, NULL, CB(layout_menu_view_menu_cb) },
{ "FileDirMenu", NULL, N_("_Files and Folders"), NULL, NULL, NULL },
{ "ZoomMenu", NULL, N_("_Zoom"), NULL, NULL, NULL },
{ "ColorMenu", NULL, N_("_Color Management"), NULL, NULL, NULL },
{ "ConnectZoom33", NULL, N_("Zoom 1:3"), NULL, N_("Connected Zoom 1:3"), CB(layout_menu_connect_zoom_1_3_cb) },
{ "ConnectZoom25", NULL, N_("Zoom 1:4"), NULL, N_("Connected Zoom 1:4"), CB(layout_menu_connect_zoom_1_4_cb) },
{ "ViewInNewWindow", NULL, N_("_View in new window"), "<control>V", N_("View in new window"), CB(layout_menu_view_in_new_window_cb) },
+ { "OpenArchive", GTK_STOCK_OPEN, N_("Open archive"), NULL, N_("Open archive"), CB(layout_menu_open_archive_cb) },
{ "FullScreen", GTK_STOCK_FULLSCREEN, N_("F_ull screen"), "F", N_("Full screen"), CB(layout_menu_fullscreen_cb) },
{ "FullScreenAlt1", GTK_STOCK_FULLSCREEN, N_("F_ull screen"), "V", N_("Full screen"), CB(layout_menu_fullscreen_cb) },
{ "FullScreenAlt2", GTK_STOCK_FULLSCREEN, N_("F_ull screen"), "F11", N_("Full screen"), CB(layout_menu_fullscreen_cb) },
" <menuitem action='ViewInNewWindow'/>"
" <menuitem action='PanView'/>"
" <menuitem action='ExifWin'/>"
+" <menuitem action='OpenArchive'/>"
" <placeholder name='WindowSection'/>"
" <separator/>"
" <menu action='FileDirMenu'>"
gchar *gq_bin_dir;
gchar *gq_executable_path;
gchar *desktop_file_template;
+gchar *instance_identifier;
/*
*-----------------------------------------------------------------------------
LayoutWindow *lw = NULL;
GList *list;
LayoutWindow *tmp_lw;
+ gchar *archive_dir;
+ GFile *archive_file;
/* make sure that external editors are loaded, we would save incomplete configuration otherwise */
layout_editors_reload_finish();
layout_free(lw);
}
+ /* Delete any files/folders in /tmp that have been created by the open archive function */
+ archive_dir = g_build_filename(g_get_tmp_dir(), GQ_ARCHIVE_DIR, instance_identifier, NULL);
+ if (isdir(archive_dir))
+ {
+ archive_file = g_file_new_for_path(archive_dir);
+ rmdir_recursive(archive_file, NULL, NULL);
+ g_free(archive_dir);
+ g_object_unref(archive_file);
+ }
+
+ /* If there are still sub-dirs created by another instance, this will fail
+ * but that does not matter */
+ archive_dir = g_build_filename(g_get_tmp_dir(), GQ_ARCHIVE_DIR, NULL);
+ if (isdir(archive_dir))
+ {
+ archive_file = g_file_new_for_path(archive_dir);
+ g_file_delete(archive_file, NULL, NULL);
+ g_free(archive_dir);
+ g_object_unref(archive_file);
+ }
+
secure_close(command_line->ssi);
gtk_main_quit();
options->disable_gpu = TRUE;
}
+ /* Generate a unique identifier used by the open archive function */
+ instance_identifier = g_strdup_printf("%x", g_random_int());
+
DEBUG_1("%s main: mkdir_if_not_exists", get_exec_time());
/* these functions don't depend on config file */
mkdir_if_not_exists(get_rc_dir());
#define GQ_COLLECTIONS_DIR "collections"
#define GQ_TRASH_DIR "trash"
#define GQ_WINDOW_LAYOUTS_DIR "layouts"
+#define GQ_ARCHIVE_DIR "geeqie-archive"
#define GQ_SYSTEM_WIDE_DIR "/etc/" GQ_APPNAME_LC
extern gchar *gq_bin_dir;
extern gchar *gq_executable_path;
extern gchar *desktop_file_template;
+extern gchar *instance_identifier;
void keyboard_scroll_calc(gint *x, gint *y, GdkEventKey *event);
gint key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer data);
#include "misc.h"
#include "ui_fileops.h"
+#include <archive.h>
+#include <archive_entry.h>
#include <langinfo.h>
#include <locale.h>
gtk_tree_path_free(data);
}
+/* Copied from the libarchive .repo. examples */
+
+static void errmsg(const char *);
+static gboolean extract(const char *filename, int do_extract, int flags);
+static int copy_data(struct archive *, struct archive *);
+static void msg(const char *);
+static int verbose = 0;
+
+gchar *open_archive(FileData *fd)
+{
+ int flags;
+ gchar *current_dir;
+ gchar *destination_dir;
+ gboolean success;
+
+ destination_dir = g_build_filename(g_get_tmp_dir(), GQ_ARCHIVE_DIR, instance_identifier, fd->path, NULL);
+
+ recursive_mkdir_if_not_exists(destination_dir, 0755);
+
+ current_dir = g_get_current_dir();
+ chdir(destination_dir);
+
+ flags = ARCHIVE_EXTRACT_TIME;
+ success = extract(fd->path, 1, flags);
+
+ chdir(current_dir);
+ g_free(current_dir);
+
+ if (!success)
+ {
+ g_free(destination_dir);
+ destination_dir = NULL;
+ }
+
+ return destination_dir;
+}
+
+static gboolean extract(const char *filename, int do_extract, int flags)
+{
+ struct archive *a;
+ struct archive *ext;
+ struct archive_entry *entry;
+ int r;
+
+ a = archive_read_new();
+ ext = archive_write_disk_new();
+ archive_write_disk_set_options(ext, flags);
+ archive_write_disk_set_standard_lookup(ext);
+ archive_read_support_filter_all(a);
+ archive_read_support_format_all(a);
+
+ if (filename != NULL && strcmp(filename, "-") == 0)
+ {
+ filename = NULL;
+ }
+ if ((r = archive_read_open_filename(a, filename, 10240)))
+ {
+ errmsg(archive_error_string(a));
+ errmsg("\n");
+ return(FALSE);
+ }
+ for (;;)
+ {
+ int needcr = 0;
+
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_EOF)
+ {
+ break;
+ }
+ if (r != ARCHIVE_OK)
+ {
+ errmsg(archive_error_string(a));
+ errmsg("\n");
+ return(FALSE);
+ }
+ if (verbose && do_extract)
+ {
+ msg("x ");
+ }
+ if (verbose || !do_extract)
+ {
+ msg(archive_entry_pathname(entry));
+ msg(" ");
+ needcr = 1;
+ }
+ if (do_extract)
+ {
+ r = archive_write_header(ext, entry);
+ if (r != ARCHIVE_OK)
+ {
+ errmsg(archive_error_string(a));
+ needcr = 1;
+ }
+ else
+ {
+ r = copy_data(a, ext);
+ if (r != ARCHIVE_OK)
+ {
+ needcr = 1;
+ }
+ }
+ }
+ if (needcr)
+ {
+ msg("\n");
+ }
+ }
+ archive_read_close(a);
+ archive_read_free(a);
+
+ archive_write_close(ext);
+ archive_write_free(ext);
+ return(TRUE);
+}
+
+static int
+copy_data(struct archive *ar, struct archive *aw)
+{
+ int r;
+ const void *buff;
+ size_t size;
+ int64_t offset;
+
+ for (;;)
+ {
+ r = archive_read_data_block(ar, &buff, &size, &offset);
+ if (r == ARCHIVE_EOF)
+ return (ARCHIVE_OK);
+ if (r != ARCHIVE_OK)
+ {
+ errmsg(archive_error_string(ar));
+ return (r);
+ }
+ r = archive_write_data_block(aw, buff, size, offset);
+ if (r != ARCHIVE_OK)
+ {
+ errmsg(archive_error_string(ar));
+ return (r);
+ }
+ }
+}
+
+static void msg(const char *m)
+{
+ log_printf("%s \n", m);
+}
+
+static void errmsg(const char *m)
+{
+ if (m == NULL)
+ {
+ m = "Error: No error description provided.\n";
+ }
+ log_printf("%s \n", m);
+}
+
/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
gchar *get_symbolic_link(const gchar *path_utf8);
gint get_cpu_cores(void);
void tree_path_free_wrapper(void *data, void *useradata);
+gchar *open_archive(FileData *fd);
#endif /* MISC_H */
/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
options->lazy_image_sync = FALSE;
options->mousewheel_scrolls = FALSE;
options->image_lm_click_nav = TRUE;
+ options->image_l_click_archive = FALSE;
options->image_l_click_video = FALSE;
options->image_l_click_video_editor = NULL;
options->open_recent_list_maxsize = 10;
gboolean place_dialogs_under_mouse;
gboolean mousewheel_scrolls;
gboolean image_lm_click_nav;
+ gboolean image_l_click_archive;
gboolean image_l_click_video;
gchar *image_l_click_video_editor;
gboolean show_icon_names;
options->mousewheel_scrolls = c_options->mousewheel_scrolls;
options->image_lm_click_nav = c_options->image_lm_click_nav;
+ options->image_l_click_archive = c_options->image_l_click_archive;
options->image_l_click_video = c_options->image_l_click_video;
options->image_l_click_video_editor = c_options->image_l_click_video_editor;
options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
options->image_lm_click_nav, &c_options->image_lm_click_nav);
+ pref_checkbox_new_int(group, _("Open archive by left click on image"),
+ options->image_l_click_archive, &c_options->image_l_click_archive);
pref_checkbox_new_int(group, _("Play video by left click on image"),
options->image_l_click_video, &c_options->image_l_click_video);
table = pref_table_new(group, 2, 1, FALSE, FALSE);
WRITE_NL(); WRITE_BOOL(*options, mousewheel_scrolls);
WRITE_NL(); WRITE_BOOL(*options, image_lm_click_nav);
+ WRITE_NL(); WRITE_BOOL(*options, image_l_click_archive);
WRITE_NL(); WRITE_BOOL(*options, image_l_click_video);
WRITE_NL(); WRITE_CHAR(*options, image_l_click_video_editor);
WRITE_NL(); WRITE_INT(*options, open_recent_list_maxsize);
if (READ_BOOL(*options, mousewheel_scrolls)) continue;
if (READ_BOOL(*options, image_lm_click_nav)) continue;
+ if (READ_BOOL(*options, image_l_click_archive)) continue;
if (READ_BOOL(*options, image_l_click_video)) continue;
if (READ_CHAR(*options, image_l_click_video_editor)) continue;
{"Delete", N_("Delete"), GTK_STOCK_DELETE},
{"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
{"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
+ {"OpenArchive", N_("Open Archive"), PIXBUF_INLINE_ARCHIVE},
{"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
{"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
{"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
return ret;
}
+
+gboolean rmdir_recursive(GFile *file, GCancellable *cancellable, GError **error)
+{
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+
+ enumerator = g_file_enumerate_children(file, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, NULL);
+
+ while (enumerator != NULL)
+ {
+ GFile *child;
+
+ if (!g_file_enumerator_iterate(enumerator, NULL, &child, cancellable, error))
+ return FALSE;
+ if (child == NULL)
+ break;
+ if (!rmdir_recursive(child, cancellable, error))
+ return FALSE;
+ }
+
+ return g_file_delete(file, cancellable, error);
+}
+
/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
gboolean md5_get_digest_from_file_utf8(const gchar *path, guchar digest[16]);
gboolean download_web_file(const gchar *text, gboolean minimized, gpointer data);
+gboolean rmdir_recursive(GFile *file, GCancellable *cancellable, GError **error);
#endif
/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */