# HG changeset patch # User Klaus Ethgen # Date 1549397898 -3600 # Node ID 5705ded05a19653b22beb6625ba457a92888924e # Parent 1c3289d4827350263f44978ce0eb0da40428cb22# Parent a9225aa1d93c2ef9ec309c555552c47efba28098 Merge merge requests 641, 638, 630 and 627 Just pro forma as they are already in the history. * github/merge-requests/641: Add export-jpg to POTFILES.in * github/merge-requests/638: Avoid non-portable == for the test command * github/merge-requests/630: add headline field * github/merge-requests/627: Add awk shebang to geocode-parameters.awk diff -r a9225aa1d93c -r 5705ded05a19 README.md --- a/README.md Tue Jul 31 18:34:40 2018 +0200 +++ b/README.md Tue Feb 05 21:18:18 2019 +0100 @@ -1,7 +1,7 @@ ################################################################### ## Geeqie x.x ## ## ## - ## Copyright (C) 2008 - 2017 The Geeqie Team ## + ## Copyright (C) 2008 - 2018 The Geeqie Team ## ## Copyright (C) 1999 - 2006 John Ellis. ## ## ## ## Use at your own risk! ## @@ -102,14 +102,13 @@ Geeqie is available as a package with some distributions. -The source tar of the latest formal release may be downloaded: - However Geeqie is stable, and you may download the latest version (if you have installed git) from here: Either: `git clone git://www.geeqie.org/geeqie.git` Or: `git clone http://www.geeqie.org/git/geeqie.git` +For Ubuntu and other Debian-based systems, [this script](http://www.geeqie.org/web/geeqie-install-debian.sh) will download Geeqie sources, all dependencies, and compile and install Geeqie. You may also select which optional libraries to install. ## Installation @@ -228,6 +227,10 @@ for thumbnailing camera video clips disable with configure option: --disable-ffmpegthumbnailer + libpoppler-glib-dev 0.62 + for displaying pdf files + disable with configure option: --disable-pdf + ### Code hackers: If you plan on making any major changes to the code that will be offered for diff -r a9225aa1d93c -r 5705ded05a19 configure.in --- a/configure.in Tue Jul 31 18:34:40 2018 +0200 +++ b/configure.in Tue Feb 05 21:18:18 2019 +0100 @@ -540,6 +540,35 @@ AC_SUBST(LUA_CFLAGS) AC_SUBST(LUA_LIBS) +# Pdf support +# ---------------------------------------------------------------------- + +if test "x${gtk3}" != "xno"; then + AC_ARG_ENABLE([pdf], + AC_HELP_STRING([--disable-pdf], [disable pdf support]), + [libpdf=$enableval], [libpdf=auto]) + + if test "x${libpdf}" != "xno"; then + PKG_CHECK_MODULES(PDF, poppler-glib >= 0.62, + [ + HAVE_PDF=yes + AC_DEFINE(HAVE_PDF, 1, [define to enable pdf support]) + ], + [ + HAVE_PDF=no + AC_MSG_WARN([$PDF_PKG_ERRORS]) + ]) + else + HAVE_PDF=disabled + fi +else + HAVE_PDF=disabled +fi + +AM_CONDITIONAL(HAVE_PDF, [test "x$HAVE_PDF" = xyes]) +AC_SUBST(PDF_CFLAGS) +AC_SUBST(PDF_LIBS) + # Markdown support # ---------------------------------------------------------------------- @@ -641,6 +670,7 @@ Libchamplain-gtk: $HAVE_LIBCHAMPLAIN_GTK Lua: $HAVE_LUA FFmpegthumbnailer: $HAVE_FFMPEGTHUMBNAILER + Pdf: $HAVE_PDF Documentation: Doxygen: $DX_DOXYGEN diff -r a9225aa1d93c -r 5705ded05a19 doc/docbook/GuideImageSearchSearch.xml --- a/doc/docbook/GuideImageSearchSearch.xml Tue Jul 31 18:34:40 2018 +0200 +++ b/doc/docbook/GuideImageSearchSearch.xml Tue Feb 05 21:18:18 2019 +0100 @@ -72,7 +72,13 @@ File name - The search will match if the entered text appears within the file name, or if the text exactly matches the file name, depending on the method selected from the drop down menu. The text comparison can be made to be case sensitive by enabling the Match case checkbox. + + The search will match if the entered text appears within the file name, or if the text exactly matches the file name, depending on the method selected from the drop down menu. The text comparison can be made to be case sensitive by enabling the Match case checkbox. + + If "contains" is selected, + Perl Compatible Regular Expressions + are used. + @@ -139,6 +145,16 @@ + Comment + + + The search will match if the file's Comments field contains the entered pattern. + Perl Compatible Regular Expressions + are used. + + + + Geocoded position diff -r a9225aa1d93c -r 5705ded05a19 doc/docbook/GuideOptionsBehavior.xml --- a/doc/docbook/GuideOptionsBehavior.xml Tue Jul 31 18:34:40 2018 +0200 +++ b/doc/docbook/GuideOptionsBehavior.xml Tue Feb 05 21:18:18 2019 +0100 @@ -134,6 +134,22 @@ + Use "With Rename" as default for Copy/Move dialogs + + + Move the "With Rename" button to the default position. + + + + + Open Collections on top + + + Open collection windows with "Always on Top" set. + + + + Recent folder list maximum size diff -r a9225aa1d93c -r 5705ded05a19 doc/docbook/GuideOptionsFiltering.xml --- a/doc/docbook/GuideOptionsFiltering.xml Tue Jul 31 18:34:40 2018 +0200 +++ b/doc/docbook/GuideOptionsFiltering.xml Tue Feb 05 21:18:18 2019 +0100 @@ -152,12 +152,14 @@ This may be used to define sets of file types, for use in the Grouping - function described above. The drop-down list has 4 entries: + function described above. The drop-down list has 6 entries: Unknown Image RAW Image Metadata + Video + Collection diff -r a9225aa1d93c -r 5705ded05a19 doc/docbook/GuideReference.xml --- a/doc/docbook/GuideReference.xml Tue Jul 31 18:34:40 2018 +0200 +++ b/doc/docbook/GuideReference.xml Tue Feb 05 21:18:18 2019 +0100 @@ -14,5 +14,6 @@ + diff -r a9225aa1d93c -r 5705ded05a19 doc/docbook/GuideReferencePCRE.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/docbook/GuideReferencePCRE.xml Tue Feb 05 21:18:18 2019 +0100 @@ -0,0 +1,14 @@ + +
+ Perl Compatible Regular Expressions + + The Filename and Comment sections on the search window use + Perl Compatible Regular Expressions + . In general use there are a number of differences to the wildcard expansion used on the command line: + + Use "." and not "?" for a single character. + Use "abc.*ghk" and not "abc*ghk" for multiple characters + Use "\." to represent the dot in a file extension + + +
diff -r a9225aa1d93c -r 5705ded05a19 doc/docbook/GuideSidebarsInfo.xml --- a/doc/docbook/GuideSidebarsInfo.xml Tue Jul 31 18:34:40 2018 +0200 +++ b/doc/docbook/GuideSidebarsInfo.xml Tue Feb 05 21:18:18 2019 +0100 @@ -292,6 +292,22 @@ file.ctime refer to operating system documentation for the meaning of ctime + + file.owner + the file's owner. Refer to operating system documentation for the meaning of file permissions + + + file.group + the file's group. Refer to operating system documentation for the meaning of file permissions + + + file.class + the file's class e.g. Image, RAW image etc. + + + file.link + if the file is a symbolic link, shows the path of the source file + diff -r a9225aa1d93c -r 5705ded05a19 geeqie-install-debian.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/geeqie-install-debian.sh Tue Feb 05 21:18:18 2019 +0100 @@ -0,0 +1,1 @@ +web/geeqie-install-debian.sh \ No newline at end of file diff -r a9225aa1d93c -r 5705ded05a19 po/en_GB.po --- a/po/en_GB.po Tue Jul 31 18:34:40 2018 +0200 +++ b/po/en_GB.po Tue Feb 05 21:18:18 2019 +0100 @@ -8,7 +8,7 @@ "Project-Id-Version: geeqie-1.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-06-24 10:14+0100\n" -"PO-Revision-Date: 2018-06-24 11:15+0100\n" +"PO-Revision-Date: 2018-07-14 14:54+0100\n" "Last-Translator: Colin Clark \n" "Language-Team: British English <>\n" "Language: en_GB\n" @@ -4088,7 +4088,7 @@ #: ../src/pan-view/pan-view.c:2022 msgid "Do not show this dialog again" -msgstr "" +msgstr "Do not show this dialogue again" #: ../src/pan-view/pan-view.c:2271 ../src/search.c:1091 msgid "_Play" @@ -4523,7 +4523,7 @@ #: ../src/preferences.c:2011 msgid "Remember dialog window positions" -msgstr "" +msgstr "Remember dialogue window positions" #: ../src/preferences.c:2014 msgid "Show window IDs" @@ -4857,7 +4857,7 @@ #: ../src/preferences.c:2604 msgid "Use \"With Rename\" as default for Copy/Move dialogs" -msgstr "" +msgstr "Use \"With Rename\" as default for Copy/Move dialogues" #: ../src/preferences.c:2608 msgid "Recent folder list maximum size" diff -r a9225aa1d93c -r 5705ded05a19 src/Makefile.am --- a/src/Makefile.am Tue Jul 31 18:34:40 2018 +0200 +++ b/src/Makefile.am Tue Feb 05 21:18:18 2019 +0100 @@ -11,6 +11,7 @@ $(CLUTTER_CFLAGS) \ $(CLUTTER_GTK_CFLAGS) \ $(FFMPEGTHUMBNAILER_CFLAGS) \ + $(PDF_CFLAGS) \ -I$(top_srcdir) \ -I$(top_builddir) @@ -25,6 +26,7 @@ $(CLUTTER_CFLAGS) \ $(CLUTTER_GTK_CFLAGS) \ $(FFMPEGTHUMBNAILER_CFLAGS) \ + $(PDF_CFLAGS) \ -I$(top_srcdir) \ -I$(top_builddir) @@ -181,6 +183,10 @@ image_load_tiff.h\ image_load_dds.c\ image_load_dds.h\ + image_load_collection.c\ + image_load_collection.h\ + image_load_pdf.c\ + image_load_pdf.h\ image_load_ffmpegthumbnailer.c\ image_load_ffmpegthumbnailer.h\ image-overlay.c \ @@ -268,7 +274,7 @@ 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) +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) EXTRA_DIST = \ $(extra_SLIK) diff -r a9225aa1d93c -r 5705ded05a19 src/bar.c --- a/src/bar.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/bar.c Tue Feb 05 21:18:18 2019 +0100 @@ -66,6 +66,15 @@ " " ""; +static const gchar default_config_headline[] = +"" +" " +" " +" " +" " +" " +""; + static const gchar default_config_keywords[] = "" " " @@ -128,6 +137,10 @@ " " " " " " +" " +" " +" " +" " " " " " " " @@ -188,6 +201,7 @@ {PANE_KEYWORDS, "keywords", N_("Keywords"), default_config_keywords}, {PANE_COMMENT, "comment", N_("Comment"), default_config_comment}, {PANE_COMMENT, "rating", N_("Rating"), default_config_rating}, + {PANE_COMMENT, "headline", N_("Headline"), default_config_headline}, {PANE_EXIF, "exif", N_("Exif"), default_config_exif}, /* other pre-configured panes */ {PANE_EXIF, "file_info", N_("File info"), default_config_file_info}, diff -r a9225aa1d93c -r 5705ded05a19 src/collect.c --- a/src/collect.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/collect.c Tue Feb 05 21:18:18 2019 +0100 @@ -1288,6 +1288,10 @@ gtk_window_set_geometry_hints(GTK_WINDOW(cw->window), NULL, &geometry, GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE); + if (options->collections_on_top) + { + gtk_window_set_keep_above(GTK_WINDOW(cw->window), TRUE); + } if (options->save_window_positions && path && collection_load_only_geometry(cw->cd, path)) { diff -r a9225aa1d93c -r 5705ded05a19 src/exif-common.c --- a/src/exif-common.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/exif-common.c Tue Feb 05 21:18:18 2019 +0100 @@ -812,8 +812,17 @@ text_latitude_ref = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLatitudeRef"); text_longitude_ref = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLongitudeRef"); - if (text_latitude && text_longitude && text_latitude_ref && - text_longitude_ref) + if ((text_latitude && g_strrstr(text_latitude, "deg")) && + (text_longitude && g_strrstr(text_longitude, "deg")) && + ( + (text_latitude_ref && g_strrstr(text_latitude_ref, "N")) || + (text_latitude_ref && g_strrstr(text_latitude_ref, "S")) + ) && + ( + (text_longitude_ref && g_strrstr(text_longitude_ref, "E")) || + (text_longitude_ref && g_strrstr(text_longitude_ref, "W")) + ) + ) { lat_deg = strtok(text_latitude, "deg'"); lat_min = strtok(NULL, "deg'"); @@ -888,6 +897,10 @@ {"file.date", N_("File date"), NULL}, {"file.mode", N_("File mode"), NULL}, {"file.ctime", N_("File ctime"), NULL}, + {"file.owner", N_("File owner"), NULL}, + {"file.group", N_("File group"), NULL}, + {"file.link", N_("File link"), NULL}, + {"file.class", N_("File class"), NULL}, { NULL, NULL, NULL } }; @@ -1152,6 +1165,22 @@ { return g_strdup(text_from_time(fd->cdate)); } + if (strcmp(key, "file.class") == 0) + { + return g_strdup(format_class_list[fd->format_class]); + } + if (strcmp(key, "file.owner") == 0) + { + return g_strdup(fd->owner); + } + if (strcmp(key, "file.group") == 0) + { + return g_strdup(fd->group); + } + if (strcmp(key, "file.link") == 0) + { + return g_strdup(fd->sym_link); + } return g_strdup(""); } diff -r a9225aa1d93c -r 5705ded05a19 src/filedata.c --- a/src/filedata.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/filedata.c Tue Feb 05 21:18:18 2019 +0100 @@ -32,8 +32,10 @@ #include "secure_save.h" #include "exif.h" +#include "misc.h" #include +#include #ifdef DEBUG_FILEDATA gint global_file_data_count = 0; @@ -370,6 +372,8 @@ static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean disable_sidecars) { FileData *fd; + struct passwd *user; + struct group *group; DEBUG_2("file_data_new: '%s' %d", path_utf8, disable_sidecars); @@ -432,6 +436,28 @@ fd->rating = STAR_RATING_NOT_READ; fd->format_class = filter_file_get_class(path_utf8); + user = getpwuid(st->st_uid); + if (!user) + { + fd->owner = g_strdup_printf("%u", st->st_uid); + } + else + { + fd->owner = g_strdup(user->pw_name); + } + + group = getgrgid(st->st_gid); + if (!group) + { + fd->group = g_strdup_printf("%u", st->st_gid); + } + else + { + fd->group = g_strdup(group->gr_name); + } + + fd->sym_link = get_symbolic_link(path_utf8); + if (disable_sidecars) fd->disable_grouping = TRUE; file_data_set_path(fd, path_utf8); /* set path, name, collate_key_*, original_path */ @@ -681,7 +707,9 @@ g_free(fd->extended_extension); if (fd->thumb_pixbuf) g_object_unref(fd->thumb_pixbuf); histmap_free(fd->histmap); - + g_free(fd->owner); + g_free(fd->group); + g_free(fd->sym_link); g_assert(fd->sidecar_files == NULL); /* sidecar files must be freed before calling this */ file_data_change_info_free(NULL, fd); diff -r a9225aa1d93c -r 5705ded05a19 src/filefilter.c --- a/src/filefilter.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/filefilter.c Tue Feb 05 21:18:18 2019 +0100 @@ -254,7 +254,7 @@ /* non-image files that might be desirable to show */ filter_add_if_missing("xmp", "XMP sidecar", ".xmp", FORMAT_CLASS_META, TRUE, FALSE, TRUE); filter_add_if_missing("meta", "GQview legacy metadata", GQ_CACHE_EXT_METADATA, FORMAT_CLASS_META, TRUE, FALSE, TRUE); - filter_add_if_missing("gqv", GQ_APPNAME " image collection", GQ_COLLECTION_EXT, FORMAT_CLASS_META, FALSE, FALSE, TRUE); + filter_add_if_missing("gqv", GQ_APPNAME " image collection", GQ_COLLECTION_EXT, FORMAT_CLASS_COLLECTION, FALSE, FALSE, TRUE); filter_add_if_missing("ufraw", "UFRaw ID file", ".ufraw", FORMAT_CLASS_META, FALSE, FALSE, TRUE); filter_add_if_missing("pto", "Panorama script file", ".pto", FORMAT_CLASS_META, FALSE, FALSE, TRUE); @@ -291,6 +291,7 @@ /* other supported formats */ filter_add_if_missing("dds", "DirectDraw Surface", ".dds", FORMAT_CLASS_IMAGE, FALSE, FALSE, TRUE); + filter_add_if_missing("pdf", "Portable Document Format", ".pdf", FORMAT_CLASS_PDF, FALSE, FALSE, TRUE); } GList *filter_to_list(const gchar *extensions) @@ -469,6 +470,8 @@ if (filter_file_class(name, FORMAT_CLASS_RAWIMAGE)) return FORMAT_CLASS_RAWIMAGE; if (filter_file_class(name, FORMAT_CLASS_META)) return FORMAT_CLASS_META; if (filter_file_class(name, FORMAT_CLASS_VIDEO)) return FORMAT_CLASS_VIDEO; + if (filter_file_class(name, FORMAT_CLASS_COLLECTION)) return FORMAT_CLASS_COLLECTION; + if (filter_file_class(name, FORMAT_CLASS_PDF)) return FORMAT_CLASS_PDF; return FORMAT_CLASS_UNKNOWN; } diff -r a9225aa1d93c -r 5705ded05a19 src/icons/Makefile.am --- a/src/icons/Makefile.am Tue Jul 31 18:34:40 2018 +0200 +++ b/src/icons/Makefile.am Tue Feb 05 21:18:18 2019 +0100 @@ -15,12 +15,32 @@ sheet_metadata.png \ sheet_unknown.png \ sheet_video.png \ + collection.png \ icon_float.png \ icon_thumb.png \ icon_book.png \ icon_config.png \ icon_tools.png \ - icon_view.png + icon_view.png \ + icon_guidelines.png \ + icon_panorama.png \ + icon_maintenance.png \ + icon_zoomfillhor.png \ + icon_zoomfillvert.png \ + icon_hidetools.png \ + icon_exif.png \ + icon_marks.png \ + icon_info.png \ + icon_sort.png \ + icon_pdf.png \ + icon_draw_rectangle.png \ + icon_move.png \ + icon_rename.png \ + icon_select_all.png \ + icon_select_none.png \ + icon_select_invert.png \ + icon_select_rectangle.png + ICONS_INLINE_PAIRS = \ folder_closed $(srcdir)/folder_closed.png \ @@ -36,10 +56,29 @@ icon_metadata $(srcdir)/sheet_metadata.png \ icon_unknown $(srcdir)/sheet_unknown.png \ icon_video $(srcdir)/sheet_video.png \ + icon_collection $(srcdir)/collection.png \ icon_book $(srcdir)/icon_book.png \ icon_config $(srcdir)/icon_config.png \ icon_tools $(srcdir)/icon_tools.png \ - icon_view $(srcdir)/icon_view.png + icon_view $(srcdir)/icon_view.png \ + icon_guidelines $(srcdir)/icon_guidelines.png \ + icon_panorama $(srcdir)/icon_panorama.png \ + icon_maintenance $(srcdir)/icon_maintenance.png \ + icon_zoomfillhor $(srcdir)/icon_zoomfillhor.png \ + icon_zoomfillvert $(srcdir)/icon_zoomfillvert.png \ + icon_hidetools $(srcdir)/icon_hidetools.png \ + icon_exif $(srcdir)/icon_exif.png \ + icon_marks $(srcdir)/icon_marks.png \ + icon_info $(srcdir)/icon_info.png \ + icon_sort $(srcdir)/icon_sort.png \ + icon_pdf $(srcdir)/icon_pdf.png \ + icon_draw_rectangle $(srcdir)/icon_draw_rectangle.png \ + icon_move $(srcdir)/icon_move.png \ + icon_rename $(srcdir)/icon_rename.png \ + icon_select_all $(srcdir)/icon_select_all.png \ + icon_select_none $(srcdir)/icon_select_none.png \ + icon_select_invert $(srcdir)/icon_select_invert.png \ + icon_select_rectangle $(srcdir)/icon_select_rectangle.png icons_inline.h: $(ICONS_INLINE) Makefile.in @sh -ec "echo '/* Auto generated file, do not edit */'; echo; \ @@ -57,4 +96,3 @@ EXTRA_DIST = \ $(ICONS_INLINE) \ marker.xpm - diff -r a9225aa1d93c -r 5705ded05a19 src/icons/collection.png Binary file src/icons/collection.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_draw_rectangle.png Binary file src/icons/icon_draw_rectangle.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_exif.png Binary file src/icons/icon_exif.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_guidelines.png Binary file src/icons/icon_guidelines.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_hidetools.png Binary file src/icons/icon_hidetools.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_info.png Binary file src/icons/icon_info.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_maintenance.png Binary file src/icons/icon_maintenance.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_marks.png Binary file src/icons/icon_marks.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_move.png Binary file src/icons/icon_move.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_panorama.png Binary file src/icons/icon_panorama.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_pdf.png Binary file src/icons/icon_pdf.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_rename.png Binary file src/icons/icon_rename.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_select_all.png Binary file src/icons/icon_select_all.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_select_invert.png Binary file src/icons/icon_select_invert.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_select_none.png Binary file src/icons/icon_select_none.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_select_rectangle.png Binary file src/icons/icon_select_rectangle.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_sort.png Binary file src/icons/icon_sort.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_zoomfillhor.png Binary file src/icons/icon_zoomfillhor.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/icons/icon_zoomfillvert.png Binary file src/icons/icon_zoomfillvert.png has changed diff -r a9225aa1d93c -r 5705ded05a19 src/image-load.c --- a/src/image-load.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/image-load.c Tue Feb 05 21:18:18 2019 +0100 @@ -25,7 +25,9 @@ #include "image_load_jpeg.h" #include "image_load_tiff.h" #include "image_load_dds.h" +#include "image_load_pdf.h" #include "image_load_ffmpegthumbnailer.h" +#include "image_load_collection.h" #include "exif.h" #include "filedata.h" @@ -617,6 +619,14 @@ } else #endif +#ifdef HAVE_PDF + if (il->fd->format_class == FORMAT_CLASS_PDF) + { + DEBUG_1("Using custom pdf loader"); + image_loader_backend_set_pdf(&il->backend); + } + else +#endif #ifdef HAVE_JPEG if (il->bytes_total >= 2 && il->mapped_file[0] == 0xff && il->mapped_file[1] == 0xd8) { @@ -643,6 +653,12 @@ image_loader_backend_set_dds(&il->backend); } else + if (il->fd->format_class == FORMAT_CLASS_COLLECTION) + { + DEBUG_1("Using custom collection loader"); + image_loader_backend_set_collection(&il->backend); + } + else image_loader_backend_set_default(&il->backend); il->loader = il->backend.loader_new(image_loader_area_updated_cb, image_loader_size_cb, image_loader_area_prepared_cb, il); diff -r a9225aa1d93c -r 5705ded05a19 src/image-overlay.c --- a/src/image-overlay.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/image-overlay.c Tue Feb 05 21:18:18 2019 +0100 @@ -52,6 +52,7 @@ Histogram *histogram; OsdShowFlags show; + OverlayRendererFlags origin; gint ovl_info; @@ -215,10 +216,15 @@ } else { - if (show & OSD_SHOW_HISTOGRAM) + if (show & OSD_SHOW_GUIDELINES) { image_osd_set(imd, OSD_SHOW_NOTHING); } + else if (show & OSD_SHOW_HISTOGRAM) + { + image_osd_set(imd, OSD_SHOW_GUIDELINES); + image_osd_set(imd, show | ~OSD_SHOW_HISTOGRAM); + } else { image_osd_set(imd, show | OSD_SHOW_HISTOGRAM); @@ -793,6 +799,40 @@ return icon; } +static GdkPixbuf *image_osd_guidelines_render(OverlayStateData *osd) +{ + gint width, height; + GdkPixbuf *rectangles; + ImageWindow *imd = osd->imd; + + pixbuf_renderer_get_scaled_size((PixbufRenderer *)imd->pr, &width, &height); + + if (width && height) + { + rectangles = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height); + if (rectangles) + { + pixbuf_set_rect_fill(rectangles, 0, 0, width, height, 255, 255, 255, 0); + pixbuf_set_rect(rectangles, 0, 0 + (height / 3), width, height / 3, + 0, 0, 0, 255, + 1, 1, 1, 1); + pixbuf_set_rect(rectangles, 0, 0 + (height / 3 + 1), width, height / 3 - 2, + 255, 255, 255, 255, + 1, 1, 1, 1); + + pixbuf_set_rect(rectangles, 0 + width / 3, 0 , width / 3, height, + 0, 0, 0, 255, + 1, 1, 1, 1); + pixbuf_set_rect(rectangles, 0 + width / 3 + 1, 0, width / 3 - 2, height, + 255, 255, 255, 255, + 1, 1, 1, 1); + return rectangles; + } + } + + return NULL; +} + static gint image_overlay_add(ImageWindow *imd, GdkPixbuf *pixbuf, gint x, gint y, OverlayRendererFlags flags) { @@ -876,7 +916,7 @@ { if (osd->ovl_info == 0) { - osd->ovl_info = image_overlay_add(osd->imd, pixbuf, osd->x, osd->y, OVL_RELATIVE); + osd->ovl_info = image_overlay_add(osd->imd, pixbuf, osd->x, osd->y, osd->origin); } else { @@ -902,19 +942,41 @@ with histogram we have to redraw also when loading is finished */ if (osd->changed_states & IMAGE_STATE_IMAGE || (osd->changed_states & IMAGE_STATE_LOADING && osd->show & OSD_SHOW_HISTOGRAM) || + (osd->changed_states & IMAGE_STATE_LOADING && osd->show & OSD_SHOW_GUIDELINES) || osd->notify & NOTIFY_HISTMAP) { GdkPixbuf *pixbuf; - pixbuf = image_osd_info_render(osd); - if (pixbuf) + if (osd->show & OSD_SHOW_GUIDELINES) { - image_osd_info_show(osd, pixbuf); - g_object_unref(pixbuf); + ImageWindow *imd = osd->imd; + osd->x = ((PixbufRenderer *)imd->pr)->x_offset; + osd->y = ((PixbufRenderer *)imd->pr)->y_offset; + osd->origin = OVL_NORMAL; + + pixbuf = image_osd_guidelines_render(osd); + if (pixbuf) + { + image_osd_info_show(osd, pixbuf); + g_object_unref(pixbuf); + } + + osd->x = options->image_overlay.x; + osd->y = options->image_overlay.y; + osd->origin = OVL_RELATIVE; } else { - image_osd_info_hide(osd); + pixbuf = image_osd_info_render(osd); + if (pixbuf) + { + image_osd_info_show(osd, pixbuf); + g_object_unref(pixbuf); + } + else + { + image_osd_info_hide(osd); + } } } } @@ -1088,6 +1150,7 @@ osd->show = OSD_SHOW_NOTHING; osd->x = options->image_overlay.x; osd->y = options->image_overlay.y; + osd->origin = OVL_RELATIVE; osd->histogram = histogram_new(); diff -r a9225aa1d93c -r 5705ded05a19 src/image-overlay.h --- a/src/image-overlay.h Tue Jul 31 18:34:40 2018 +0200 +++ b/src/image-overlay.h Tue Feb 05 21:18:18 2019 +0100 @@ -37,7 +37,8 @@ OSD_SHOW_NOTHING = 0, OSD_SHOW_INFO = 1 << 0, OSD_SHOW_STATUS = 1 << 1, - OSD_SHOW_HISTOGRAM = 1 << 2 + OSD_SHOW_HISTOGRAM = 1 << 2, + OSD_SHOW_GUIDELINES = 1 << 3 } OsdShowFlags; void set_image_overlay_template_string(gchar **template_string, const gchar *value); diff -r a9225aa1d93c -r 5705ded05a19 src/image.c --- a/src/image.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/image.c Tue Feb 05 21:18:18 2019 +0100 @@ -48,6 +48,14 @@ static void image_read_ahead_start(ImageWindow *imd); static void image_cache_set(ImageWindow *imd, FileData *fd); +// For draw rectangle function +static gint pixbuf_start_x; +static gint pixbuf_start_y; +static gint image_start_x; +static gint image_start_y; +static gint rect_x1, rect_x2, rect_y1, rect_y2; +static gint rect_id = 0; + /* *------------------------------------------------------------------- * 'signals' @@ -68,10 +76,92 @@ } } +static void switch_coords_orientation(ImageWindow *imd, gint x, gint y, gint width, gint height) +{ + switch (imd->orientation) + { + case EXIF_ORIENTATION_TOP_LEFT: + /* normal -- nothing to do */ + rect_x1 = image_start_x; + rect_y1 = image_start_y; + rect_x2 = x; + rect_y2 = y; + break; + case EXIF_ORIENTATION_TOP_RIGHT: + /* mirrored */ + rect_x1 = width - x; + rect_y1 = image_start_y; + rect_x2 = width - image_start_x; + rect_y2 = y; + break; + case EXIF_ORIENTATION_BOTTOM_RIGHT: + /* upside down */ + rect_x1 = width - x; + rect_y1 = height - y; + rect_x2 = width - image_start_x; + rect_y2 = height - image_start_y; + break; + case EXIF_ORIENTATION_BOTTOM_LEFT: + /* flipped */ + rect_x1 = image_start_x; + rect_y1 = height - y; + rect_x2 = x; + rect_y2 = height - image_start_y; + break; + case EXIF_ORIENTATION_LEFT_TOP: + /* left mirrored */ + rect_x1 = image_start_y; + rect_y1 = image_start_x; + rect_x2 = y; + rect_y2 = x; + break; + case EXIF_ORIENTATION_RIGHT_TOP: + /* rotated -90 (270) */ + rect_x1 = image_start_y; + rect_y1 = width - x; + rect_x2 = y; + rect_y2 = width - image_start_x; + break; + case EXIF_ORIENTATION_RIGHT_BOTTOM: + /* right mirrored */ + rect_x1 = height - y; + rect_y1 = width - x; + rect_x2 = height - image_start_y; + rect_y2 = width - image_start_x; + break; + case EXIF_ORIENTATION_LEFT_BOTTOM: + /* rotated 90 */ + rect_x1 = height - y; + rect_y1 = image_start_x; + rect_x2 = height - image_start_y; + rect_y2 = x; + break; + default: + /* The other values are out of range */ + break; + } +} + static void image_press_cb(PixbufRenderer *pr, GdkEventButton *event, gpointer data) { ImageWindow *imd = data; LayoutWindow *lw; + gint x_pixel, y_pixel; + + if(options->draw_rectangle) + { + pixbuf_renderer_get_mouse_position(pr, &x_pixel, &y_pixel); + + pixbuf_start_x = event->x; + pixbuf_start_y = event->y; + image_start_x = x_pixel; + image_start_y = y_pixel; + } + + if (rect_id) + { + pixbuf_renderer_overlay_remove((PixbufRenderer *)imd->pr, rect_id); + } lw = layout_find_by_image(imd); if (lw && event->button == MOUSE_BUTTON_LEFT && event->type == GDK_2BUTTON_PRESS @@ -86,6 +176,40 @@ { ImageWindow *imd = data; gint width, height; + gint rect_width; + gint rect_height; + GdkPixbuf *rect_pixbuf; + gint x_pixel, y_pixel; + + if (options->draw_rectangle) + { + pixbuf_renderer_get_image_size(pr, &width, &height); + pixbuf_renderer_get_mouse_position(pr, &x_pixel, &y_pixel); + switch_coords_orientation(imd, x_pixel, y_pixel, width, height); + + if (rect_id) + { + pixbuf_renderer_overlay_remove((PixbufRenderer *)imd->pr, rect_id); + } + + rect_width = pr->drag_last_x - pixbuf_start_x; + if (rect_width <= 0) + { + rect_width = 1; + } + rect_height = pr->drag_last_y - pixbuf_start_y; + if (rect_height <= 0) + { + rect_height = 1; + } + + rect_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, rect_width, rect_height); + pixbuf_set_rect_fill(rect_pixbuf, 0, 0, rect_width, rect_height, 255, 255, 255, 0); + pixbuf_set_rect(rect_pixbuf, 1, 1, rect_width-2, rect_height - 2, 0, 0, 0, 255, 1, 1, 1, 1); + pixbuf_set_rect(rect_pixbuf, 2, 2, rect_width-4, rect_height - 4, 255, 255, 255, 255, 1, 1, 1, 1); + + rect_id = pixbuf_renderer_overlay_add((PixbufRenderer *)imd->pr, rect_pixbuf, pixbuf_start_x, pixbuf_start_y, OVL_NORMAL); + } pixbuf_renderer_get_scaled_size(pr, &width, &height); @@ -697,6 +821,11 @@ break; case FORMAT_CLASS_VIDEO: pixbuf = pixbuf_inline(PIXBUF_INLINE_VIDEO); + case FORMAT_CLASS_COLLECTION: + pixbuf = pixbuf_inline(PIXBUF_INLINE_COLLECTION); + break; + case FORMAT_CLASS_PDF: + pixbuf = pixbuf_inline(PIXBUF_INLINE_ICON_PDF); break; default: pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN); @@ -2019,4 +2148,13 @@ return imd; } + +void image_get_rectangle(gint *x1, gint *y1, gint *x2, gint *y2) +{ + *x1 = rect_x1; + *y1 = rect_y1; + *x2 = rect_x2; + *y2 = rect_y2; +} + /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r a9225aa1d93c -r 5705ded05a19 src/image.h --- a/src/image.h Tue Jul 31 18:34:40 2018 +0200 +++ b/src/image.h Tue Feb 05 21:18:18 2019 +0100 @@ -150,6 +150,7 @@ /* reset default options */ void image_options_sync(void); +void image_get_rectangle(gint *x1, gint *y1, gint *x2, gint *y2); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r a9225aa1d93c -r 5705ded05a19 src/image_load_collection.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image_load_collection.c Tue Feb 05 21:18:18 2019 +0100 @@ -0,0 +1,182 @@ +/* + * Copyright (C) 20018 - The Geeqie Team + * + * Author: Colin Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "main.h" +#include "image-load.h" +#include "image_load_collection.h" + +#include "cache.h" +#include "misc.h" +#include "ui_fileops.h" + +typedef struct _ImageLoaderCOLLECTION ImageLoaderCOLLECTION; +struct _ImageLoaderCOLLECTION { + ImageLoaderBackendCbAreaUpdated area_updated_cb; + ImageLoaderBackendCbSize size_cb; + ImageLoaderBackendCbAreaPrepared area_prepared_cb; + gpointer data; + GdkPixbuf *pixbuf; + guint requested_width; + guint requested_height; + gboolean abort; +}; + +static gboolean image_loader_collection_load(gpointer loader, const guchar *buf, gsize count, GError **error) +{ + ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader; + ImageLoader *il = ld->data; + + #define LINE_LENGTH 1000 + + gboolean ret = FALSE; + gchar *randname; + gchar *cmd_line; + FILE *fp = NULL; + gint line_count = 0; + GString *file_names = g_string_new(NULL); + gchar line[LINE_LENGTH]; + gchar **split_line = NULL; + gchar *cache_found; + gchar *pathl; + + if (runcmd("which montage >/dev/null 2>&1") == 0) + { + pathl = path_from_utf8(il->fd->path); + fp = fopen(pathl, "r"); + g_free(pathl); + if (fp) + { + while(fgets(line, LINE_LENGTH, fp) && line_count < options->thumbnails.collection_preview) + { + if (line[0] && line[0] != '#') + { + split_line = g_strsplit(line, "\"", 4); + cache_found = cache_find_location(CACHE_TYPE_THUMB, split_line[1]); + if (cache_found) + { + file_names = g_string_append(file_names, g_strconcat("\"", cache_found,"\" ", NULL)); + line_count++; + } + g_free(cache_found); + } + if (split_line) + { + g_strfreev(split_line); + } + split_line = NULL; + } + fclose(fp); + + if (file_names->len > 0) + { + randname = g_strdup("/tmp/geeqie_collection_XXXXXX.png"); + g_mkstemp(randname); + + cmd_line = g_strdup_printf("montage %s -geometry %dx%d+1+1 %s >/dev/null 2>&1", file_names->str, options->thumbnails.max_width, options->thumbnails.max_height, randname); + + runcmd(cmd_line); + ld->pixbuf = gdk_pixbuf_new_from_file(randname, NULL); + if (ld->pixbuf) + { + ld->area_updated_cb(loader, 0, 0, gdk_pixbuf_get_width(ld->pixbuf), gdk_pixbuf_get_height(ld->pixbuf), ld->data); + } + + unlink(randname); + g_free(randname); + g_string_free(file_names, TRUE); + g_free(cmd_line); + + ret = TRUE; + } + else + { + g_string_free(file_names, TRUE); + } + } + } + return ret; +} + +static gpointer image_loader_collection_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +{ + ImageLoaderCOLLECTION *loader = g_new0(ImageLoaderCOLLECTION, 1); + loader->area_updated_cb = area_updated_cb; + loader->size_cb = size_cb; + loader->area_prepared_cb = area_prepared_cb; + loader->data = data; + return (gpointer) loader; +} + +static void image_loader_collection_set_size(gpointer loader, int width, int height) +{ + ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader; + ld->requested_width = width; + ld->requested_height = height; +} + +static GdkPixbuf* image_loader_collection_get_pixbuf(gpointer loader) +{ + ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader; + return ld->pixbuf; +} + +static gchar* image_loader_collection_get_format_name(gpointer loader) +{ + return g_strdup("collection"); +} +static gchar** image_loader_collection_get_format_mime_types(gpointer loader) +{ + static gchar *mime[] = {"image/png", NULL}; + return g_strdupv(mime); +} + +static gboolean image_loader_collection_close(gpointer loader, GError **error) +{ + return TRUE; +} + +static void image_loader_collection_abort(gpointer loader) +{ + ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader; + ld->abort = TRUE; +} + +static void image_loader_collection_free(gpointer loader) +{ + ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader; + if (ld->pixbuf) g_object_unref(ld->pixbuf); + g_free(ld); +} + +void image_loader_backend_set_collection(ImageLoaderBackend *funcs) +{ + funcs->loader_new = image_loader_collection_new; + funcs->set_size = image_loader_collection_set_size; + funcs->load = image_loader_collection_load; + funcs->write = NULL; + funcs->get_pixbuf = image_loader_collection_get_pixbuf; + funcs->close = image_loader_collection_close; + funcs->abort = image_loader_collection_abort; + funcs->free = image_loader_collection_free; + funcs->get_format_name = image_loader_collection_get_format_name; + funcs->get_format_mime_types = image_loader_collection_get_format_mime_types; +} + +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r a9225aa1d93c -r 5705ded05a19 src/image_load_collection.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image_load_collection.h Tue Feb 05 21:18:18 2019 +0100 @@ -0,0 +1,27 @@ +/* + * Copyright (C) 20018 - The Geeqie Team + * + * Author: Colin Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef IMAGE_LOAD_COLLECTION_H +#define IMAGE_LOAD_COLLECTION_H + +void image_loader_backend_set_collection(ImageLoaderBackend *funcs); + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r a9225aa1d93c -r 5705ded05a19 src/image_load_pdf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image_load_pdf.c Tue Feb 05 21:18:18 2019 +0100 @@ -0,0 +1,152 @@ +/* + * Copyright (C) 20018 - The Geeqie Team + * + * Author: Colin Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "main.h" + +#include "image-load.h" +#include "image_load_pdf.h" + +#ifdef HAVE_PDF +#include + +typedef struct _ImageLoaderPDF ImageLoaderPDF; +struct _ImageLoaderPDF { + ImageLoaderBackendCbAreaUpdated area_updated_cb; + ImageLoaderBackendCbSize size_cb; + ImageLoaderBackendCbAreaPrepared area_prepared_cb; + gpointer data; + GdkPixbuf *pixbuf; + guint requested_width; + guint requested_height; + gboolean abort; +}; + +static gboolean image_loader_pdf_load(gpointer loader, const guchar *buf, gsize count, GError **error) +{ + ImageLoaderPDF *ld = (ImageLoaderPDF *) loader; + ImageLoader *il = ld->data; + GError *poppler_error; + gchar *uri; + PopplerPage *page; + PopplerDocument *document; + gint page_num; + gdouble width, height; + cairo_surface_t *surface; + cairo_t *cr; + gboolean ret = FALSE; + + uri = g_filename_to_uri(il->fd->path, NULL, &poppler_error); + if (uri == NULL) + { + log_printf("warning: pdf reader error: %s\n", poppler_error->message); + } + else + { + page_num = 0; + document = poppler_document_new_from_file(uri, NULL, &poppler_error); + page = poppler_document_get_page(document, page_num); + poppler_page_get_size(page, &width, &height); + + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cr = cairo_create(surface); + poppler_page_render(page, cr); + + ld->pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, width, height); + ld->area_updated_cb(loader, 0, 0, width, height, ld->data); + + cairo_destroy (cr); + cairo_surface_destroy(surface); + g_free(uri); + g_object_unref(page); + g_object_unref(document); + ret = TRUE; + } + + return ret; +} + +static gpointer image_loader_pdf_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +{ + ImageLoaderPDF *loader = g_new0(ImageLoaderPDF, 1); + loader->area_updated_cb = area_updated_cb; + loader->size_cb = size_cb; + loader->area_prepared_cb = area_prepared_cb; + loader->data = data; + return (gpointer) loader; +} + +static void image_loader_pdf_set_size(gpointer loader, int width, int height) +{ + ImageLoaderPDF *ld = (ImageLoaderPDF *) loader; + ld->requested_width = width; + ld->requested_height = height; +} + +static GdkPixbuf* image_loader_pdf_get_pixbuf(gpointer loader) +{ + ImageLoaderPDF *ld = (ImageLoaderPDF *) loader; + return ld->pixbuf; +} + +static gchar* image_loader_pdf_get_format_name(gpointer loader) +{ + return g_strdup("pdf"); +} + +static gchar** image_loader_pdf_get_format_mime_types(gpointer loader) +{ + static gchar *mime[] = {"application/pdf", NULL}; + return g_strdupv(mime); +} + +static gboolean image_loader_pdf_close(gpointer loader, GError **error) +{ + return TRUE; +} + +static void image_loader_pdf_abort(gpointer loader) +{ + ImageLoaderPDF *ld = (ImageLoaderPDF *) loader; + ld->abort = TRUE; +} + +static void image_loader_pdf_free(gpointer loader) +{ + ImageLoaderPDF *ld = (ImageLoaderPDF *) loader; + if (ld->pixbuf) g_object_unref(ld->pixbuf); + g_free(ld); +} + +void image_loader_backend_set_pdf(ImageLoaderBackend *funcs) +{ + funcs->loader_new = image_loader_pdf_new; + funcs->set_size = image_loader_pdf_set_size; + funcs->load = image_loader_pdf_load; + funcs->write = NULL; + funcs->get_pixbuf = image_loader_pdf_get_pixbuf; + funcs->close = image_loader_pdf_close; + funcs->abort = image_loader_pdf_abort; + funcs->free = image_loader_pdf_free; + funcs->get_format_name = image_loader_pdf_get_format_name; + funcs->get_format_mime_types = image_loader_pdf_get_format_mime_types; +} + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r a9225aa1d93c -r 5705ded05a19 src/image_load_pdf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image_load_pdf.h Tue Feb 05 21:18:18 2019 +0100 @@ -0,0 +1,29 @@ +/* + * Copyright (C) 20018 - The Geeqie Team + * + * Author: Colin Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef IMAGE_LOAD_PDF_H +#define IMAGE_LOAD_PDF_H + +#ifdef HAVE_PDF +void image_loader_backend_set_pdf(ImageLoaderBackend *funcs); +#endif + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r a9225aa1d93c -r 5705ded05a19 src/layout.c --- a/src/layout.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/layout.c Tue Feb 05 21:18:18 2019 +0100 @@ -287,23 +287,38 @@ gtk_widget_set_sensitive(lw->back_button, (n > 1)); } +static gboolean path_entry_tooltip_cb(GtkWidget *widget, gpointer data) +{ + LayoutWindow *lw = data; + GList *box_child_list; + GtkComboBox *path_entry; + gchar *current_path; + + box_child_list = gtk_container_get_children(GTK_CONTAINER(widget)); + path_entry = box_child_list->data; + current_path = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(path_entry)); + gtk_widget_set_tooltip_text(GTK_WIDGET(widget), current_path); + + g_free(current_path); + g_list_free(box_child_list); + + return FALSE; +} + static GtkWidget *layout_tool_setup(LayoutWindow *lw) { GtkWidget *box; GtkWidget *box_folders; GtkWidget *scd; - GtkWidget *menu_bar; + GtkWidget *menu_tool_bar; GtkWidget *tabcomp; - GtkWidget *toolbar; box = gtk_vbox_new(FALSE, 0); - menu_bar = layout_actions_menu_bar(lw); - gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, FALSE, 0); - - toolbar = layout_actions_toolbar(lw, TOOLBAR_MAIN); - gtk_box_pack_start(GTK_BOX(box), toolbar, FALSE, FALSE, 0); - if (lw->options.toolbar_hidden) gtk_widget_hide(toolbar); + menu_tool_bar = layout_actions_menu_tool_bar(lw); + gtk_widget_show(menu_tool_bar); + gtk_box_pack_start(GTK_BOX(lw->main_box), lw->menu_tool_bar, FALSE, FALSE, 0); + if (lw->options.toolbar_hidden) gtk_widget_hide(lw->toolbar[TOOLBAR_MAIN]); tabcomp = tab_completion_new_with_history(&lw->path_entry, NULL, "path_list", -1, layout_path_entry_cb, lw); @@ -311,6 +326,8 @@ tab_completion_add_append_func(lw->path_entry, layout_path_entry_tab_append_cb, lw); gtk_box_pack_start(GTK_BOX(box), tabcomp, FALSE, FALSE, 0); gtk_widget_show(tabcomp); + gtk_widget_set_has_tooltip(GTK_WIDGET(tabcomp), TRUE); + g_signal_connect(G_OBJECT(tabcomp), "query_tooltip", G_CALLBACK(path_entry_tooltip_cb), lw); #if GTK_CHECK_VERSION(3,20,0) g_signal_connect(G_OBJECT(gtk_widget_get_parent(gtk_widget_get_parent(lw->path_entry))), "changed", @@ -1366,7 +1383,7 @@ *h = gdk_window_get_height(window); gtk_widget_get_allocation(gtk_paned_get_child1(GTK_PANED(lw->tools_pane)), &allocation); - if (GTK_IS_VPANED(lw->tools_pane)) + if (gtk_orientable_get_orientation(GTK_ORIENTABLE(lw->tools_pane)) == GTK_ORIENTATION_VERTICAL) { *divider_pos = allocation.height; } @@ -1479,6 +1496,7 @@ gtk_window_set_resizable(GTK_WINDOW(lw->tools), TRUE); gtk_container_set_border_width(GTK_CONTAINER(lw->tools), 0); + gtk_container_remove(GTK_CONTAINER(lw->main_box), lw->menu_tool_bar); new_window = TRUE; } @@ -1493,6 +1511,7 @@ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(lw->tools), vbox); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(lw->menu_tool_bar), FALSE, FALSE, 0); gtk_widget_show(vbox); layout_status_setup(lw, vbox, TRUE); @@ -1642,7 +1661,7 @@ layout_actions_setup(lw); lw->group_box = gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(lw->main_box), lw->group_box, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(lw->main_box), lw->group_box, TRUE, TRUE, 0); gtk_widget_show(lw->group_box); priority_location = layout_grid_compass(lw); @@ -1776,9 +1795,10 @@ /* preserve utility_box (image + sidebars), menu_bar and toolbars to be reused later in layout_grid_setup */ /* lw->image is preserved together with lw->utility_box */ if (lw->utility_box) gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(lw->utility_box)), lw->utility_box); - if (lw->menu_bar) gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(lw->menu_bar)), lw->menu_bar); - for (i = 0; i < TOOLBAR_COUNT; i++) - if (lw->toolbar[i]) gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(lw->toolbar[i])), lw->toolbar[i]); + + if (lw->toolbar[TOOLBAR_STATUS]) gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(lw->toolbar[TOOLBAR_STATUS])), lw->toolbar[TOOLBAR_STATUS]); + + if (lw->menu_tool_bar) gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(lw->menu_tool_bar)), lw->menu_tool_bar); /* clear it all */ diff -r a9225aa1d93c -r 5705ded05a19 src/layout_util.c --- a/src/layout_util.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/layout_util.c Tue Feb 05 21:18:18 2019 +0100 @@ -508,6 +508,13 @@ layout_image_reset_orientation(lw); } +static void layout_menu_select_rectangle_cb(GtkToggleAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + options->draw_rectangle = gtk_toggle_action_get_active(action); +} + static void layout_menu_write_rotate(GtkToggleAction *action, gpointer data, gboolean keep_date) { LayoutWindow *lw = data; @@ -928,6 +935,24 @@ } } +static void layout_menu_guidelines_cb(GtkToggleAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + if (gtk_toggle_action_get_active(action)) + { + OsdShowFlags flags = image_osd_get(lw->image); + image_osd_set(lw->image, OSD_SHOW_INFO | OSD_SHOW_STATUS | OSD_SHOW_GUIDELINES); + layout_util_sync_views(lw); + } + else + { + OsdShowFlags flags = image_osd_get(lw->image); + if (flags & OSD_SHOW_GUIDELINES) + image_osd_set(lw->image, OSD_SHOW_NOTHING); + } +} + static void layout_menu_animate_cb(GtkToggleAction *action, gpointer data) { LayoutWindow *lw = data; @@ -1810,12 +1835,12 @@ { "OpenRecent", NULL, N_("Open recen_t"), NULL, N_("Open recent"), NULL }, { "Search", GTK_STOCK_FIND, N_("_Search..."), "F3", N_("Search..."), CB(layout_menu_search_cb) }, { "FindDupes", GTK_STOCK_FIND, N_("_Find duplicates..."), "D", N_("Find duplicates..."), CB(layout_menu_dupes_cb) }, - { "PanView", GTK_STOCK_FILE, N_("Pa_n view"), "J", N_("Pan view"), CB(layout_menu_pan_cb) }, + { "PanView", PIXBUF_INLINE_ICON_PANORAMA, N_("Pa_n view"), "J", N_("Pan view"), CB(layout_menu_pan_cb) }, { "Print", GTK_STOCK_PRINT, N_("_Print..."), "P", N_("Print..."), CB(layout_menu_print_cb) }, { "NewFolder", GTK_STOCK_DIRECTORY, N_("N_ew folder..."), "F", N_("New folder..."), CB(layout_menu_dir_cb) }, { "Copy", GTK_STOCK_COPY, N_("_Copy..."), "C", N_("Copy..."), CB(layout_menu_copy_cb) }, - { "Move", NULL, N_("_Move..."), "M", N_("Move..."), CB(layout_menu_move_cb) }, - { "Rename", NULL, N_("_Rename..."), "R", N_("Rename..."), CB(layout_menu_rename_cb) }, + { "Move", PIXBUF_INLINE_ICON_MOVE, N_("_Move..."), "M", N_("Move..."), CB(layout_menu_move_cb) }, + { "Rename", PIXBUF_INLINE_ICON_RENAME, N_("_Rename..."), "R", N_("Rename..."), CB(layout_menu_rename_cb) }, { "Delete", GTK_STOCK_DELETE, N_("_Delete..."), "D", N_("Delete..."), CB(layout_menu_delete_cb) }, { "DeleteAlt1", GTK_STOCK_DELETE, N_("_Delete..."), "Delete", N_("Delete..."), CB(layout_menu_delete_key_cb) }, { "DeleteAlt2", GTK_STOCK_DELETE, N_("_Delete..."), "KP_Delete", N_("Delete..."), CB(layout_menu_delete_key_cb) }, @@ -1838,13 +1863,13 @@ { "Mirror", NULL, N_("_Mirror"), "M", N_("Mirror"), CB(layout_menu_alter_mirror_cb) }, { "Flip", NULL, N_("_Flip"), "F", N_("Flip"), CB(layout_menu_alter_flip_cb) }, { "AlterNone", NULL, N_("_Original state"), "O", N_("Original state"), CB(layout_menu_alter_none_cb) }, - { "SelectAll", NULL, N_("Select _all"), "A", N_("Select all"), CB(layout_menu_select_all_cb) }, - { "SelectNone", NULL, N_("Select _none"), "A", N_("Select none"), CB(layout_menu_unselect_all_cb) }, - { "SelectInvert", NULL, N_("_Invert Selection"), "I", N_("Invert Selection"), CB(layout_menu_invert_selection_cb) }, + { "SelectAll", PIXBUF_INLINE_ICON_SELECT_ALL, N_("Select _all"), "A", N_("Select all"), CB(layout_menu_select_all_cb) }, + { "SelectNone", PIXBUF_INLINE_ICON_SELECT_NONE, N_("Select _none"), "A", N_("Select none"), CB(layout_menu_unselect_all_cb) }, + { "SelectInvert", PIXBUF_INLINE_ICON_SELECT_INVERT, N_("_Invert Selection"), "I", N_("Invert Selection"), CB(layout_menu_invert_selection_cb) }, { "Preferences", GTK_STOCK_PREFERENCES, N_("P_references..."), "O", N_("Preferences..."), CB(layout_menu_config_cb) }, { "Plugins", GTK_STOCK_PREFERENCES, N_("Configure _Plugins..."), NULL, N_("Configure Plugins..."), CB(layout_menu_editors_cb) }, { "LayoutConfig", GTK_STOCK_PREFERENCES, N_("_Configure this window..."), NULL, N_("Configure this window..."), CB(layout_menu_layout_config_cb) }, - { "Maintenance", GTK_STOCK_FILE, N_("_Cache maintenance..."), NULL, N_("Cache maintenance..."), CB(layout_menu_remove_thumb_cb) }, + { "Maintenance", PIXBUF_INLINE_ICON_MAINTENANCE, N_("_Cache maintenance..."), NULL, N_("Cache maintenance..."), CB(layout_menu_remove_thumb_cb) }, { "Wallpaper", NULL, N_("Set as _wallpaper"), NULL, N_("Set as wallpaper"), CB(layout_menu_wallpaper_cb) }, { "SaveMetadata", GTK_STOCK_SAVE, N_("_Save metadata"), "S", N_("Save metadata"), CB(layout_menu_metadata_write_cb) }, { "ZoomIn", GTK_STOCK_ZOOM_IN, N_("Zoom _in"), "equal", N_("Zoom in"), CB(layout_menu_zoom_in_cb) }, @@ -1855,8 +1880,8 @@ { "Zoom100Alt1", GTK_STOCK_ZOOM_100, N_("Zoom _1:1"), "KP_Divide", N_("Zoom 1:1"), CB(layout_menu_zoom_1_1_cb) }, { "ZoomFit", GTK_STOCK_ZOOM_FIT, N_("_Zoom to fit"), "X", N_("Zoom to fit"), CB(layout_menu_zoom_fit_cb) }, { "ZoomFitAlt1", GTK_STOCK_ZOOM_FIT, N_("_Zoom to fit"), "KP_Multiply", N_("Zoom to fit"), CB(layout_menu_zoom_fit_cb) }, - { "ZoomFillHor", GTK_STOCK_FILE, N_("Fit _Horizontally"), "H", N_("Fit Horizontally"), CB(layout_menu_zoom_fit_hor_cb) }, - { "ZoomFillVert", GTK_STOCK_FILE, N_("Fit _Vertically"), "W", N_("Fit Vertically"), CB(layout_menu_zoom_fit_vert_cb) }, + { "ZoomFillHor", PIXBUF_INLINE_ICON_ZOOMFILLHOR, N_("Fit _Horizontally"), "H", N_("Fit Horizontally"), CB(layout_menu_zoom_fit_hor_cb) }, + { "ZoomFillVert", PIXBUF_INLINE_ICON_ZOOMFILLVERT, N_("Fit _Vertically"), "W", N_("Fit Vertically"), CB(layout_menu_zoom_fit_vert_cb) }, { "Zoom200", GTK_STOCK_FILE, N_("Zoom _2:1"), NULL, N_("Zoom 2:1"), CB(layout_menu_zoom_2_1_cb) }, { "Zoom300", GTK_STOCK_FILE, N_("Zoom _3:1"), NULL, N_("Zoom 3:1"), CB(layout_menu_zoom_3_1_cb) }, { "Zoom400", GTK_STOCK_FILE, N_("Zoom _4:1"), NULL, N_("Zoom 4:1"), CB(layout_menu_zoom_4_1_cb) }, @@ -1888,7 +1913,7 @@ { "ImageOverlayCycle",NULL, N_("_Cycle through overlay modes"), "I", N_("Cycle through Overlay modes"), CB(layout_menu_overlay_toggle_cb) }, { "HistogramChanCycle",NULL, N_("Cycle through histogram ch_annels"),"K", N_("Cycle through histogram channels"), CB(layout_menu_histogram_toggle_channel_cb) }, { "HistogramModeCycle",NULL, N_("Cycle through histogram mo_des"), "J", N_("Cycle through histogram modes"), CB(layout_menu_histogram_toggle_mode_cb) }, - { "HideTools", GTK_STOCK_FILE, N_("_Hide file list"), "H", N_("Hide file list"), CB(layout_menu_hide_cb) }, + { "HideTools", PIXBUF_INLINE_ICON_HIDETOOLS, N_("_Hide file list"), "H", N_("Hide file list"), CB(layout_menu_hide_cb) }, { "SlideShowPause", GTK_STOCK_MEDIA_PAUSE, N_("_Pause slideshow"), "P", N_("Pause slideshow"), CB(layout_menu_slideshow_pause_cb) }, { "SlideShowFaster", GTK_STOCK_FILE, N_("Faster"), "KP_Add", N_("Faster"), CB(layout_menu_slideshow_faster_cb) }, { "SlideShowSlower", GTK_STOCK_FILE, N_("Slower"), "KP_Subtract", N_("Slower"), CB(layout_menu_slideshow_slower_cb) }, @@ -1901,7 +1926,7 @@ { "HelpChangeLog", NULL, N_("_ChangeLog"), NULL, N_("ChangeLog notes"), CB(layout_menu_changelog_cb) }, { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, N_("About"), CB(layout_menu_about_cb) }, { "LogWindow", NULL, N_("_Log Window"), NULL, N_("Log Window"), CB(layout_menu_log_window_cb) }, - { "ExifWin", GTK_STOCK_FILE, N_("_Exif window"), "E", N_("Exif window"), CB(layout_menu_bar_exif_cb) }, + { "ExifWin", PIXBUF_INLINE_ICON_EXIF, N_("_Exif window"), "E", N_("Exif window"), CB(layout_menu_bar_exif_cb) }, { "StereoCycle", NULL, N_("_Cycle through stereo modes"), NULL, N_("Cycle through stereo modes"), CB(layout_menu_stereo_mode_next_cb) }, { "SplitNextPane", NULL, N_("_Next Pane"), "Right", N_("Next Pane"), CB(layout_menu_split_pane_next_cb) }, { "SplitPreviousPane", NULL, N_("_Previous Pane"), "Left", N_("Previous Pane"), CB(layout_menu_split_pane_prev_cb) }, @@ -1914,12 +1939,12 @@ static GtkToggleActionEntry menu_toggle_entries[] = { { "Thumbnails", PIXBUF_INLINE_ICON_THUMB,N_("Show _Thumbnails"), "T", N_("Show Thumbnails"), CB(layout_menu_thumb_cb), FALSE }, - { "ShowMarks", GTK_STOCK_FILE, N_("Show _Marks"), "M", N_("Show Marks"), CB(layout_menu_marks_cb), FALSE }, + { "ShowMarks", PIXBUF_INLINE_ICON_MARKS, N_("Show _Marks"), "M", N_("Show Marks"), CB(layout_menu_marks_cb), FALSE }, { "ShowInfoPixel", GTK_STOCK_COLOR_PICKER, N_("Pi_xel Info"), NULL, N_("Show Pixel Info"), CB(layout_menu_info_pixel_cb), FALSE }, { "FloatTools", PIXBUF_INLINE_ICON_FLOAT,N_("_Float file list"), "L", N_("Float file list"), CB(layout_menu_float_cb), FALSE }, { "HideToolbar", NULL, N_("Hide tool_bar"), NULL, N_("Hide toolbar"), CB(layout_menu_toolbar_cb), FALSE }, - { "SBar", GTK_STOCK_FILE, N_("_Info sidebar"), "K", N_("Info sidebar"), CB(layout_menu_bar_cb), FALSE }, - { "SBarSort", GTK_STOCK_FILE, N_("Sort _manager"), "S", N_("Sort manager"), CB(layout_menu_bar_sort_cb), FALSE }, + { "SBar", PIXBUF_INLINE_ICON_INFO, N_("_Info sidebar"), "K", N_("Info sidebar"), CB(layout_menu_bar_cb), FALSE }, + { "SBarSort", PIXBUF_INLINE_ICON_SORT, N_("Sort _manager"), "S", N_("Sort manager"), CB(layout_menu_bar_sort_cb), FALSE }, { "HideBars", NULL, N_("Hide Bars"), "grave", N_("Hide Bars"), CB(layout_menu_hide_bars_cb), FALSE }, { "SlideShow", GTK_STOCK_MEDIA_PLAY, N_("Toggle _slideshow"), "S", N_("Toggle slideshow"), CB(layout_menu_slideshow_cb), FALSE }, { "UseColorProfiles", GTK_STOCK_SELECT_COLOR, N_("Use _color profiles"), NULL, N_("Use color profiles"), CB(layout_color_menu_enable_cb), FALSE}, @@ -1927,9 +1952,11 @@ { "Grayscale", NULL, N_("Toggle _grayscale"), "G", N_("Toggle grayscale"), CB(layout_menu_alter_desaturate_cb), FALSE}, { "ImageOverlay", NULL, N_("Image _Overlay"), NULL, N_("Image Overlay"), CB(layout_menu_overlay_cb), FALSE }, { "ImageHistogram", NULL, N_("_Show Histogram"), NULL, N_("Show Histogram"), CB(layout_menu_histogram_cb), FALSE }, - { "RectangularSelection", NULL, N_("Rectangular Selection"), "R", N_("Rectangular Selection"), CB(layout_menu_rectangular_selection_cb), FALSE }, + { "ImageGuidelines", PIXBUF_INLINE_ICON_GUIDELINES, N_("_Show Guidelines"), NULL, N_("Show Guidelines"), CB(layout_menu_guidelines_cb), FALSE }, + { "RectangularSelection", PIXBUF_INLINE_ICON_SELECT_RECTANGLE, N_("Rectangular Selection"), "R", N_("Rectangular Selection"), CB(layout_menu_rectangular_selection_cb), FALSE }, { "Animate", NULL, N_("GIF _animation"), "A", N_("Toggle GIF animation"), CB(layout_menu_animate_cb), FALSE }, { "ExifRotate", GTK_STOCK_ORIENTATION_PORTRAIT, N_("_Exif rotate"), "X", N_("Exif rotate"), CB(layout_menu_exif_rotate_cb), FALSE }, + { "DrawRectangle", PIXBUF_INLINE_ICON_DRAW_RECTANGLE, N_("Draw Rectangle"), NULL, N_("Draw Rectangle"), CB(layout_menu_select_rectangle_cb), FALSE }, }; static GtkRadioActionEntry menu_radio_entries[] = { @@ -2067,6 +2094,8 @@ " " " " " " +" " +" " " " " " " " @@ -2162,6 +2191,7 @@ " " " " " " +" " " " " " " " @@ -2673,6 +2703,24 @@ return lw->toolbar[type]; } +GtkWidget *layout_actions_menu_tool_bar(LayoutWindow *lw) +{ + GtkWidget *menu_bar; + GtkWidget *toolbar; + + if (lw->menu_tool_bar) return lw->menu_tool_bar; + + menu_bar = layout_actions_menu_bar(lw); + toolbar = layout_actions_toolbar(lw, TOOLBAR_MAIN); + lw->menu_tool_bar = gtk_vbox_new(FALSE, 0); + + gtk_box_pack_start(GTK_BOX(lw->menu_tool_bar), menu_bar, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(lw->menu_tool_bar), toolbar, FALSE, FALSE, 0); + + g_object_ref(lw->menu_tool_bar); + return lw->menu_tool_bar; +} + void layout_toolbar_clear(LayoutWindow *lw, ToolbarType type) { if (lw->toolbar_merge_id[type]) @@ -3018,9 +3066,15 @@ action = gtk_action_group_get_action(lw->action_group, "ImageHistogram"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), osd_flags & OSD_SHOW_HISTOGRAM); + action = gtk_action_group_get_action(lw->action_group, "ImageGuidelines"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), osd_flags & OSD_SHOW_GUIDELINES); + action = gtk_action_group_get_action(lw->action_group, "ExifRotate"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->image.exif_rotate_enable); + action = gtk_action_group_get_action(lw->action_group, "DrawRectangle"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->draw_rectangle); + action = gtk_action_group_get_action(lw->action_group, "RectangularSelection"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->collections.rectangular_selection); diff -r a9225aa1d93c -r 5705ded05a19 src/layout_util.h --- a/src/layout_util.h Tue Jul 31 18:34:40 2018 +0200 +++ b/src/layout_util.h Tue Feb 05 21:18:18 2019 +0100 @@ -74,5 +74,6 @@ gboolean is_help_key(GdkEventKey *event); LayoutWindow *layout_menu_new_window(GtkAction *action, gpointer data); void layout_menu_close_cb(GtkAction *action, gpointer data); +GtkWidget *layout_actions_menu_tool_bar(LayoutWindow *lw); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r a9225aa1d93c -r 5705ded05a19 src/misc.c --- a/src/misc.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/misc.c Tue Feb 05 21:18:18 2019 +0100 @@ -323,4 +323,37 @@ return ret; } +gchar *get_symbolic_link(const gchar *path_utf8) +{ + gchar *sl; + struct stat st; + gchar *ret = g_strdup(""); + + sl = path_from_utf8(path_utf8); + + if (lstat(sl, &st) == 0 && S_ISLNK(st.st_mode)) + { + gchar *buf; + gint l; + + buf = g_malloc(st.st_size + 1); + l = readlink(sl, buf, st.st_size); + + if (l == st.st_size) + { + buf[l] = '\0'; + + ret = buf; + } + else + { + g_free(buf); + } + } + + g_free(sl); + + return ret; +} + /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r a9225aa1d93c -r 5705ded05a19 src/misc.h --- a/src/misc.h Tue Jul 31 18:34:40 2018 +0200 +++ b/src/misc.h Tue Feb 05 21:18:18 2019 +0100 @@ -30,5 +30,6 @@ gint date_get_first_day_of_week(); gchar *date_get_abbreviated_day_name(gint day); gchar *convert_rating_to_stars(gint rating); +gchar *get_symbolic_link(const gchar *path_utf8); #endif /* MISC_H */ /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r a9225aa1d93c -r 5705ded05a19 src/options.c --- a/src/options.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/options.c Tue Feb 05 21:18:18 2019 +0100 @@ -83,6 +83,7 @@ options->marks_save = TRUE; options->with_rename = FALSE; + options->collections_on_top = FALSE; memset(&options->image.border_color, 0, sizeof(options->image.border_color)); memset(&options->image.alpha_color_1, 0, sizeof(options->image.alpha_color_1)); @@ -170,6 +171,7 @@ options->thumbnails.use_exif = FALSE; options->thumbnails.use_ft_metadata = TRUE; // options->thumbnails.use_ft_metadata_small = TRUE; + options->thumbnails.collection_preview = 20; options->tree_descend_subdirs = FALSE; options->view_dir_list_single_click_enter = TRUE; diff -r a9225aa1d93c -r 5705ded05a19 src/options.h --- a/src/options.h Tue Jul 31 18:34:40 2018 +0200 +++ b/src/options.h Tue Feb 05 21:18:18 2019 +0100 @@ -35,6 +35,8 @@ gchar *image_l_click_video_editor; gboolean show_icon_names; gboolean show_star_rating; + gboolean show_guidelines; + gboolean draw_rectangle; /* various */ gboolean tree_descend_subdirs; @@ -66,6 +68,7 @@ gchar *marks_tooltips[FILEDATA_MARKS_SIZE]; gboolean with_rename; + gboolean collections_on_top; gchar *help_search_engine; @@ -138,6 +141,7 @@ guint quality; gboolean use_exif; gboolean use_ft_metadata; + gint collection_preview; // gboolean use_ft_metadata_small; } thumbnails; diff -r a9225aa1d93c -r 5705ded05a19 src/pan-view/pan-view.c --- a/src/pan-view/pan-view.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/pan-view/pan-view.c Tue Feb 05 21:18:18 2019 +0100 @@ -2003,9 +2003,7 @@ box = generic_dialog_add_message(gd, GTK_STOCK_DIALOG_INFO, _("Pan view performance may be poor."), - _("To improve performance of thumbnails in the pan view the" - " following options can be enabled. Note that both options" - " must be enabled to notice a change in performance."), TRUE); + _("To improve the performance of thumbnails in\npan view the following options can be enabled.\n\nNote that both options must be enabled to\nnotice a change in performance."), TRUE); group = pref_box_new(box, FALSE, GTK_ORIENTATION_HORIZONTAL, 0); pref_spacer(group, PREF_PAD_INDENT); diff -r a9225aa1d93c -r 5705ded05a19 src/pixbuf-renderer.c --- a/src/pixbuf-renderer.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/pixbuf-renderer.c Tue Feb 05 21:18:18 2019 +0100 @@ -2047,10 +2047,12 @@ accel = 1; } - /* do the scroll */ - pixbuf_renderer_scroll(pr, (pr->drag_last_x - event->x) * accel, - (pr->drag_last_y - event->y) * accel); - + /* do the scroll - not when drawing rectangle*/ + if (!options->draw_rectangle) + { + pixbuf_renderer_scroll(pr, (pr->drag_last_x - event->x) * accel, + (pr->drag_last_y - event->y) * accel); + } pr_drag_signal(pr, event); pr->drag_last_x = event->x; diff -r a9225aa1d93c -r 5705ded05a19 src/pixbuf_util.c --- a/src/pixbuf_util.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/pixbuf_util.c Tue Feb 05 21:18:18 2019 +0100 @@ -111,6 +111,7 @@ { PIXBUF_INLINE_METADATA, icon_metadata }, { PIXBUF_INLINE_UNKNOWN, icon_unknown }, { PIXBUF_INLINE_VIDEO, icon_video }, + { PIXBUF_INLINE_COLLECTION, icon_collection }, { PIXBUF_INLINE_ICON, gqview_icon }, { PIXBUF_INLINE_LOGO, geeqie_logo }, { PIXBUF_INLINE_ICON_FLOAT, icon_float }, @@ -119,6 +120,24 @@ { PIXBUF_INLINE_ICON_CONFIG, icon_config }, { PIXBUF_INLINE_ICON_TOOLS, icon_tools }, { PIXBUF_INLINE_ICON_VIEW, icon_view }, + { PIXBUF_INLINE_ICON_GUIDELINES, icon_guidelines }, + { PIXBUF_INLINE_ICON_PANORAMA, icon_panorama }, + { PIXBUF_INLINE_ICON_MAINTENANCE, icon_maintenance }, + { PIXBUF_INLINE_ICON_ZOOMFILLHOR, icon_zoomfillhor }, + { PIXBUF_INLINE_ICON_ZOOMFILLVERT, icon_zoomfillvert }, + { PIXBUF_INLINE_ICON_HIDETOOLS, icon_hidetools }, + { PIXBUF_INLINE_ICON_EXIF, icon_exif }, + { PIXBUF_INLINE_ICON_MARKS, icon_marks }, + { PIXBUF_INLINE_ICON_INFO, icon_info }, + { PIXBUF_INLINE_ICON_SORT, icon_sort }, + { PIXBUF_INLINE_ICON_PDF, icon_pdf }, + { PIXBUF_INLINE_ICON_DRAW_RECTANGLE, icon_draw_rectangle }, + { PIXBUF_INLINE_ICON_MOVE, icon_move }, + { PIXBUF_INLINE_ICON_RENAME, icon_rename }, + { PIXBUF_INLINE_ICON_SELECT_ALL, icon_select_all }, + { PIXBUF_INLINE_ICON_SELECT_NONE, icon_select_none }, + { PIXBUF_INLINE_ICON_SELECT_INVERT, icon_select_invert }, + { PIXBUF_INLINE_ICON_SELECT_RECTANGLE, icon_select_rectangle }, { NULL, NULL } }; @@ -254,6 +273,12 @@ case FORMAT_CLASS_VIDEO: pixbuf = pixbuf_inline(PIXBUF_INLINE_VIDEO); break; + case FORMAT_CLASS_COLLECTION: + pixbuf = pixbuf_inline(PIXBUF_INLINE_COLLECTION); + break; + case FORMAT_CLASS_PDF: + pixbuf = pixbuf_inline(PIXBUF_INLINE_ICON_PDF); + break; default: pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN); } diff -r a9225aa1d93c -r 5705ded05a19 src/pixbuf_util.h --- a/src/pixbuf_util.h Tue Jul 31 18:34:40 2018 +0200 +++ b/src/pixbuf_util.h Tue Feb 05 21:18:18 2019 +0100 @@ -43,6 +43,7 @@ #define PIXBUF_INLINE_METADATA "metadata" #define PIXBUF_INLINE_UNKNOWN "unknown" #define PIXBUF_INLINE_VIDEO "video" +#define PIXBUF_INLINE_COLLECTION "collection" #define PIXBUF_INLINE_ICON "icon" #define PIXBUF_INLINE_LOGO "logo" @@ -53,7 +54,24 @@ #define PIXBUF_INLINE_ICON_CONFIG "icon_config" #define PIXBUF_INLINE_ICON_TOOLS "icon_tools" #define PIXBUF_INLINE_ICON_VIEW "icon_view" - +#define PIXBUF_INLINE_ICON_GUIDELINES "icon_guidelines" +#define PIXBUF_INLINE_ICON_PANORAMA "icon_panorama" +#define PIXBUF_INLINE_ICON_MAINTENANCE "icon_maintenance" +#define PIXBUF_INLINE_ICON_ZOOMFILLHOR "icon_zoomfillhor" +#define PIXBUF_INLINE_ICON_ZOOMFILLVERT "icon_zoomfillvert" +#define PIXBUF_INLINE_ICON_HIDETOOLS "icon_hidetools" +#define PIXBUF_INLINE_ICON_EXIF "icon_exif" +#define PIXBUF_INLINE_ICON_MARKS "icon_marks" +#define PIXBUF_INLINE_ICON_INFO "icon_info" +#define PIXBUF_INLINE_ICON_SORT "icon_sort" +#define PIXBUF_INLINE_ICON_PDF "icon_pdf" +#define PIXBUF_INLINE_ICON_DRAW_RECTANGLE "icon_draw_rectangle" +#define PIXBUF_INLINE_ICON_MOVE "icon_move" +#define PIXBUF_INLINE_ICON_RENAME "icon_rename" +#define PIXBUF_INLINE_ICON_SELECT_ALL "icon_select_all" +#define PIXBUF_INLINE_ICON_SELECT_NONE "icon_select_none" +#define PIXBUF_INLINE_ICON_SELECT_INVERT "icon_select_invert" +#define PIXBUF_INLINE_ICON_SELECT_RECTANGLE "icon_select_rectangle" GdkPixbuf *pixbuf_copy_rotate_90(GdkPixbuf *src, gboolean counter_clockwise); GdkPixbuf *pixbuf_copy_mirror(GdkPixbuf *src, gboolean mirror, gboolean flip); diff -r a9225aa1d93c -r 5705ded05a19 src/preferences.c --- a/src/preferences.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/preferences.c Tue Feb 05 21:18:18 2019 +0100 @@ -109,7 +109,9 @@ N_("Image"), N_("RAW Image"), N_("Metadata"), - N_("Video") + N_("Video"), + N_("Collection"), + N_("Pdf") }; /* config memory values */ @@ -285,6 +287,7 @@ options->thumbnails.enable_caching = c_options->thumbnails.enable_caching; options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs; options->thumbnails.use_exif = c_options->thumbnails.use_exif; + options->thumbnails.collection_preview = c_options->thumbnails.collection_preview; options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata; // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small; options->thumbnails.spec_standard = c_options->thumbnails.spec_standard; @@ -410,6 +413,7 @@ options->marks_save = c_options->marks_save; options->with_rename = c_options->with_rename; + options->collections_on_top = c_options->collections_on_top; config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL); options->read_metadata_in_idle = c_options->read_metadata_in_idle; @@ -1558,22 +1562,14 @@ c_options->thumbnails.spec_standard =TRUE; c_options->thumbnails.cache_into_dirs = FALSE; } - else - { - c_options->thumbnails.spec_standard =FALSE; - } } static void cache_geeqie_cb(GtkWidget *widget, gpointer data) { - if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) - { - c_options->thumbnails.spec_standard =TRUE; - c_options->thumbnails.cache_into_dirs = FALSE; - } - else + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { c_options->thumbnails.spec_standard =FALSE; + c_options->thumbnails.cache_into_dirs = FALSE; } } @@ -1584,10 +1580,6 @@ c_options->thumbnails.cache_into_dirs = TRUE; c_options->thumbnails.spec_standard =FALSE; } - else - { - c_options->thumbnails.cache_into_dirs = FALSE; - } } static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos, @@ -1723,29 +1715,36 @@ subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP); pref_checkbox_link_sensitivity(ct_button, subgroup); + c_options->thumbnails.spec_standard = options->thumbnails.spec_standard; + c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs; group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"), GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP); button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(), - !options->thumbnails.spec_standard, + !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs, G_CALLBACK(cache_geeqie_cb), NULL); group_frame = pref_frame_new(subgroup, TRUE, _("Store thumbnails local to image folder (non-standard)"), GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP); pref_radiobutton_new(group_frame, button, "*/.thumbnails", - options->thumbnails.cache_into_dirs, + !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs, G_CALLBACK(cache_local_cb), NULL); group_frame = pref_frame_new(subgroup, TRUE, _("Use standard thumbnail style and cache, shared with other applications"), GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP); pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(), - options->thumbnails.spec_standard, + options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs, G_CALLBACK(cache_standard_cb), NULL); pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"), options->thumbnails.use_exif, &c_options->thumbnails.use_exif); + spin = pref_spin_new_int(group, _("Collection preview:"), NULL, + 1, 999, 1, + options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview); + gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage")); + #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"), options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata); @@ -2544,6 +2543,7 @@ GtkWidget *table; GtkWidget *marks; GtkWidget *with_rename; + GtkWidget *collections_on_top; vbox = scrolled_notebook_page(notebook, _("Behavior")); @@ -2605,6 +2605,10 @@ options->with_rename, &c_options->with_rename); gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs"); + collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"), + options->collections_on_top, &c_options->collections_on_top); + gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top"); + pref_spin_new_int(group, _("Recent folder list maximum size"), NULL, 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize); diff -r a9225aa1d93c -r 5705ded05a19 src/rcfile.c --- a/src/rcfile.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/rcfile.c Tue Feb 05 21:18:18 2019 +0100 @@ -307,6 +307,7 @@ /* General Options */ WRITE_NL(); WRITE_BOOL(*options, show_icon_names); WRITE_NL(); WRITE_BOOL(*options, show_star_rating); + WRITE_NL(); WRITE_BOOL(*options, show_guidelines); WRITE_SEPARATOR(); WRITE_NL(); WRITE_BOOL(*options, tree_descend_subdirs); @@ -348,6 +349,7 @@ WRITE_NL(); WRITE_CHAR(*options, help_search_engine); WRITE_NL(); WRITE_BOOL(*options, with_rename); + WRITE_NL(); WRITE_BOOL(*options, collections_on_top); /* File operations Options */ WRITE_NL(); WRITE_BOOL(*options, file_ops.enable_in_place_rename); @@ -396,6 +398,7 @@ WRITE_NL(); WRITE_UINT(*options, thumbnails.quality); WRITE_NL(); WRITE_BOOL(*options, thumbnails.use_exif); WRITE_NL(); WRITE_BOOL(*options, thumbnails.use_ft_metadata); + WRITE_NL(); WRITE_INT(*options, thumbnails.collection_preview); // WRITE_NL(); WRITE_BOOL(*options, thumbnails.use_ft_metadata_small); /* File sorting Options */ @@ -643,6 +646,7 @@ /* General options */ if (READ_BOOL(*options, show_icon_names)) continue; if (READ_BOOL(*options, show_star_rating)) continue; + if (READ_BOOL(*options, show_guidelines)) continue; if (READ_BOOL(*options, tree_descend_subdirs)) continue; if (READ_BOOL(*options, view_dir_list_single_click_enter)) continue; @@ -681,6 +685,8 @@ if (READ_BOOL(*options, marks_save)) continue; if (READ_CHAR(*options, help_search_engine)) continue; + if (READ_BOOL(*options, collections_on_top)) continue; + /* Properties dialog options */ if (READ_CHAR(*options, properties.tabs_order)) continue; @@ -720,6 +726,7 @@ if (READ_BOOL(*options, thumbnails.spec_standard)) continue; if (READ_UINT_CLAMP(*options, thumbnails.quality, GDK_INTERP_NEAREST, GDK_INTERP_HYPER)) continue; if (READ_BOOL(*options, thumbnails.use_exif)) continue; + if (READ_INT(*options, thumbnails.collection_preview)) continue; if (READ_BOOL(*options, thumbnails.use_ft_metadata)) continue; // if (READ_BOOL(*options, thumbnails.use_ft_metadata_small)) continue; @@ -878,7 +885,7 @@ const gchar *value = *attribute_values++; if (READ_CHAR_FULL("text", options->marks_tooltips[i])) continue; - log_printf("unkown attribute %s = %s\n", option, value); + log_printf("unknown attribute %s = %s\n", option, value); } i++; options_parse_func_set_data(parser_data, GINT_TO_POINTER(i)); diff -r a9225aa1d93c -r 5705ded05a19 src/remote.c --- a/src/remote.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/remote.c Tue Feb 05 21:18:18 2019 +0100 @@ -690,6 +690,33 @@ } } +static void gr_rectangle(const gchar *text, GIOChannel *channel, gpointer data) +{ + gchar *rectangle_info; + PixbufRenderer *pr; + LayoutWindow *lw = NULL; + gint x1, y1, x2, y2; + + if (!layout_valid(&lw_id)) return; + + pr = (PixbufRenderer*)lw_id->image->pr; + + if (pr) + { + image_get_rectangle(&x1, &y1, &x2, &y2); + rectangle_info = g_strdup_printf(_("%dx%d+%d+%d"), + (x2 > x1) ? x2 - x1 : x1 - x2, + (y2 > y1) ? y2 - y1 : y1 - y2, + (x2 > x1) ? x1 : x2, + (y2 > y1) ? y1 : y2); + + g_io_channel_write_chars(channel, rectangle_info, -1, NULL, NULL); + g_io_channel_write_chars(channel, "\n", -1, NULL, NULL); + + g_free(rectangle_info); + } +} + static void gr_file_tell(const gchar *text, GIOChannel *channel, gpointer data) { if (!layout_valid(&lw_id)) return; @@ -881,6 +908,7 @@ { NULL, "File:", gr_file_load_no_raise, TRUE, FALSE, N_(""), N_("open FILE, do not bring Geeqie window to the top") }, { NULL, "--tell", gr_file_tell, FALSE, FALSE, NULL, N_("print filename of current image") }, { NULL, "--pixel-info", gr_pixel_info, FALSE, FALSE, NULL, N_("print pixel info of mouse pointer on current image") }, + { NULL, "--get-rectangle", gr_rectangle, FALSE, FALSE, NULL, N_("get rectangle co-ordinates") }, { NULL, "view:", gr_file_view, TRUE, FALSE, N_(""), N_("open FILE in new window") }, { NULL, "--list-clear", gr_list_clear, FALSE, FALSE, NULL, N_("clear command line collection list") }, { NULL, "--list-add:", gr_list_add, TRUE, FALSE, N_(""), N_("add FILE to command line collection list") }, diff -r a9225aa1d93c -r 5705ded05a19 src/search.c --- a/src/search.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/search.c Tue Feb 05 21:18:18 2019 +0100 @@ -154,6 +154,7 @@ FileData *search_dir_fd; gboolean search_path_recurse; gchar *search_name; + GRegex *search_name_regex; gboolean search_name_match_case; gint64 search_size; gint64 search_size_end; @@ -172,6 +173,7 @@ CacheData *search_similarity_cd; GList *search_keyword_list; gchar *search_comment; + GRegex *search_comment_regex; gint search_rating; gint search_rating_end; gboolean search_comment_match_case; @@ -1544,6 +1546,64 @@ } } +static void search_path_entry_dnd_received_cb(GtkWidget *pane, GdkDragContext *context, + gint x, gint y, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data) +{ + SearchData *sd = data; + GList *list; + FileData *fd; + + if (info == TARGET_URI_LIST) + { + list = uri_filelist_from_gtk_selection_data(selection_data); + /* If more than one file, use only the first file in a list. + */ + if (list != NULL) + { + fd = list->data; + gtk_entry_set_text(GTK_ENTRY(sd->path_entry), + g_strdup_printf("%s", fd->path)); + gtk_widget_set_tooltip_text(GTK_WIDGET(sd->path_entry),g_strdup_printf("%s", fd->path)); + } + } + + if (info == TARGET_TEXT_PLAIN) + { + gtk_entry_set_text(GTK_ENTRY(sd->path_entry),""); + } +} + +static void search_image_content_dnd_received_cb(GtkWidget *pane, GdkDragContext *context, + gint x, gint y, + GtkSelectionData *selection_data, guint info, + guint time, gpointer data) +{ + SearchData *sd = data; + GList *list; + FileData *fd; + + if (info == TARGET_URI_LIST) + { + list = uri_filelist_from_gtk_selection_data(selection_data); + /* If more than one file, use only the first file in a list. + */ + if (list != NULL) + { + fd = list->data; + gtk_entry_set_text(GTK_ENTRY(sd->entry_similarity), + g_strdup_printf("%s", fd->path)); + gtk_widget_set_tooltip_text(GTK_WIDGET(sd->entry_similarity),g_strdup_printf("%s", fd->path)); + } + } + + if (info == TARGET_TEXT_PLAIN) + { + gtk_entry_set_text(GTK_ENTRY(sd->entry_similarity),""); + } +} + static void search_dnd_init(SearchData *sd) { gtk_drag_source_set(sd->result_view, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, @@ -1561,6 +1621,22 @@ g_signal_connect(G_OBJECT(sd->entry_gps_coord), "drag_data_received", G_CALLBACK(search_gps_dnd_received_cb), sd); + + gtk_drag_dest_set(GTK_WIDGET(sd->path_entry), + GTK_DEST_DEFAULT_ALL, + result_drop_types, n_result_drop_types, + GDK_ACTION_COPY); + + g_signal_connect(G_OBJECT(sd->path_entry), "drag_data_received", + G_CALLBACK(search_path_entry_dnd_received_cb), sd); + + gtk_drag_dest_set(GTK_WIDGET(sd->entry_similarity), + GTK_DEST_DEFAULT_ALL, + result_drop_types, n_result_drop_types, + GDK_ACTION_COPY); + + g_signal_connect(G_OBJECT(sd->entry_similarity), "drag_data_received", + G_CALLBACK(search_image_content_dnd_received_cb), sd); } /* @@ -1841,13 +1917,13 @@ { if (sd->search_name_match_case) { - match = (strstr(fd->name, sd->search_name) != NULL); + match = g_regex_match(sd->search_name_regex, fd->name, 0, NULL); } else { /* sd->search_name is converted in search_start() */ gchar *haystack = g_utf8_strdown(fd->name, -1); - match = (strstr(haystack, sd->search_name) != NULL); + match = g_regex_match(sd->search_name_regex, haystack, 0, NULL); g_free(haystack); } } @@ -2038,11 +2114,11 @@ if (sd->match_comment == SEARCH_MATCH_CONTAINS) { - match = (strstr(comment, sd->search_comment) != NULL); + match = g_regex_match(sd->search_comment_regex, comment, 0, NULL); } else if (sd->match_comment == SEARCH_MATCH_NONE) { - match = (strstr(comment, sd->search_comment) == NULL); + match = !g_regex_match(sd->search_comment_regex, comment, 0, NULL); } g_free(comment); } @@ -2385,6 +2461,8 @@ static void search_start(SearchData *sd) { + GError *error = NULL; + search_stop(sd); search_result_clear(sd); @@ -2401,6 +2479,20 @@ sd->search_name = tmp; } + if(sd->search_name_regex) + { + g_regex_unref(sd->search_name_regex); + } + + sd->search_name_regex = g_regex_new(sd->search_name, 0, 0, &error); + if (error) + { + log_printf("Error: could not compile regular expression %s\n%s\n", sd->search_name, error->message); + g_error_free(error); + error = NULL; + sd->search_name_regex = g_regex_new("", 0, 0, NULL); + } + if (!sd->search_comment_match_case) { /* convert to lowercase here, so that this is only done once per search */ @@ -2409,6 +2501,20 @@ sd->search_comment = tmp; } + if(sd->search_comment_regex) + { + g_regex_unref(sd->search_comment_regex); + } + + sd->search_comment_regex = g_regex_new(sd->search_comment, 0, 0, &error); + if (error) + { + log_printf("Error: could not compile regular expression %s\n%s\n", sd->search_comment, error->message); + g_error_free(error); + error = NULL; + sd->search_comment_regex = g_regex_new("", 0, 0, NULL); + } + sd->search_count = 0; sd->search_total = 0; @@ -2958,7 +3064,9 @@ file_data_unref(sd->search_dir_fd); g_free(sd->search_name); + g_regex_unref(sd->search_name_regex); g_free(sd->search_comment); + g_regex_unref(sd->search_comment_regex); g_free(sd->search_similarity_path); string_list_free(sd->search_keyword_list); @@ -3075,6 +3183,7 @@ gtk_widget_show(combo); pref_checkbox_new_int(hbox, _("Match case"), sd->search_name_match_case, &sd->search_name_match_case); + gtk_widget_set_tooltip_text(GTK_WIDGET(combo), "When set to \"contains\", this field uses Perl Compatible Regular Expressions.\ne.g. use \n.*\\.jpg\n and not \n*.jpg\n\nSee the Help file."); /* Search for file size */ hbox = menu_choice(sd->box_search, &sd->check_size, &sd->menu_size, @@ -3183,6 +3292,7 @@ gtk_widget_show(sd->entry_comment); pref_checkbox_new_int(hbox, _("Match case"), sd->search_comment_match_case, &sd->search_comment_match_case); + gtk_widget_set_tooltip_text(GTK_WIDGET(sd->entry_comment), "This field uses Perl Compatible Regular Expressions.\ne.g. use \nabc.*ghk\n and not \nabc*ghk\n\nSee the Help file."); /* Search for image rating */ hbox = menu_choice(sd->box_search, &sd->check_rating, &sd->menu_rating, diff -r a9225aa1d93c -r 5705ded05a19 src/thumb.c --- a/src/thumb.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/thumb.c Tue Feb 05 21:18:18 2019 +0100 @@ -337,7 +337,7 @@ if (!tl->fd) tl->fd = file_data_ref(fd); - if (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_VIDEO && !options->file_filter.disable) + if (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_COLLECTION && tl->fd->format_class != FORMAT_CLASS_VIDEO && tl->fd->format_class != FORMAT_CLASS_PDF && !options->file_filter.disable) { thumb_loader_set_fallback(tl); return FALSE; diff -r a9225aa1d93c -r 5705ded05a19 src/thumb_standard.c --- a/src/thumb_standard.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/thumb_standard.c Tue Feb 05 21:18:18 2019 +0100 @@ -667,7 +667,7 @@ tl->fd = file_data_ref(fd); - if (!stat_utf8(fd->path, &st) || (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_VIDEO && !options->file_filter.disable)) + if (!stat_utf8(fd->path, &st) || (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_VIDEO && tl->fd->format_class != FORMAT_CLASS_COLLECTION && tl->fd->format_class != FORMAT_CLASS_PDF && !options->file_filter.disable)) { thumb_loader_std_set_fallback(tl); return FALSE; diff -r a9225aa1d93c -r 5705ded05a19 src/toolbar.c --- a/src/toolbar.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/toolbar.c Tue Feb 05 21:18:18 2019 +0100 @@ -84,17 +84,27 @@ {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN}, {"Search", N_("Search"), GTK_STOCK_FIND}, {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND}, - {"PanView", N_("Pan view"), GTK_STOCK_FILE}, + {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY}, + {"Copy", N_("Copy"), GTK_STOCK_COPY}, + {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE}, + {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME}, + {"Delete", N_("Delete"), GTK_STOCK_DELETE}, + {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE}, + {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA}, + {"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}, + {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE}, {"Print", N_("Print"), GTK_STOCK_PRINT}, {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES}, {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES}, - {"Maintenance", N_("Cache maintenance"), GTK_STOCK_FILE}, + {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE}, {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN}, {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT}, {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100}, {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT}, - {"ZoomFillHor", N_("Fit Horizontaly"), GTK_STOCK_FILE}, - {"ZoomFillVert", N_("Fit vertically"), GTK_STOCK_FILE}, + {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR}, + {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT}, {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE}, {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE}, {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE}, @@ -102,18 +112,20 @@ {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE}, {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE}, {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN}, - {"HideTools", N_("Hide file list"), GTK_STOCK_FILE}, + {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS}, {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE}, {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE}, {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE}, {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH}, {"HelpContents", N_("Help"), GTK_STOCK_HELP}, - {"ExifWin", N_("Exif window"), GTK_STOCK_FILE}, + {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF}, {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB}, - {"ShowMarks", N_("Show marks"), GTK_STOCK_FILE}, + {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS}, + {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES}, + {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE}, {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT}, - {"SBar", N_("Info sidebar"), GTK_STOCK_FILE}, - {"SBarSort", N_("Sort manager"), GTK_STOCK_FILE}, + {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO}, + {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT}, {"Quit", N_("Quit"), GTK_STOCK_QUIT}, {NULL, NULL, NULL} }; diff -r a9225aa1d93c -r 5705ded05a19 src/typedefs.h --- a/src/typedefs.h Tue Jul 31 18:34:40 2018 +0200 +++ b/src/typedefs.h Tue Feb 05 21:18:18 2019 +0100 @@ -143,6 +143,8 @@ FORMAT_CLASS_RAWIMAGE, FORMAT_CLASS_META, FORMAT_CLASS_VIDEO, + FORMAT_CLASS_COLLECTION, + FORMAT_CLASS_PDF, FILE_FORMAT_CLASSES } FileFormatClass; @@ -598,6 +600,10 @@ gint rating; gboolean metadata_in_idle_loaded; + gchar *owner; + gchar *group; + gchar *sym_link; + SelectionType selected; // Used by view_file_icon. }; @@ -725,7 +731,7 @@ // gint tools_float; // gint tools_hidden; - + GtkWidget *menu_tool_bar; /*Combined menu and toolbar box */ GtkWidget *menu_bar; /* referenced by lw, exist during whole lw lifetime */ /* toolbar */ diff -r a9225aa1d93c -r 5705ded05a19 src/ui_bookmark.c --- a/src/ui_bookmark.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/ui_bookmark.c Tue Feb 05 21:18:18 2019 +0100 @@ -541,6 +541,17 @@ g_object_unref(pixbuf); } +static gboolean bookmark_path_tooltip_cb(GtkWidget *button, gpointer data) +{ + BookMarkData *bm = data; + BookButtonData *b; + + b = g_object_get_data(G_OBJECT(button), "bookbuttondata"); + gtk_widget_set_tooltip_text(GTK_WIDGET(button), b->path); + + return FALSE; +} + static void bookmark_populate(BookMarkData *bm) { GtkBox *box; @@ -691,6 +702,9 @@ G_CALLBACK(bookmark_drag_set_data), bm); g_signal_connect(G_OBJECT(b->button), "drag_begin", G_CALLBACK(bookmark_drag_begin), bm); + + gtk_widget_set_has_tooltip(GTK_WIDGET(b->button), TRUE); + g_signal_connect(G_OBJECT(b->button), "query_tooltip", G_CALLBACK(bookmark_path_tooltip_cb), bm); } work = work->prev; diff -r a9225aa1d93c -r 5705ded05a19 src/view_file/view_file_icon.c --- a/src/view_file/view_file_icon.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/view_file/view_file_icon.c Tue Feb 05 21:18:18 2019 +0100 @@ -1367,8 +1367,15 @@ if (bevent->type == GDK_2BUTTON_PRESS && vf->layout) { - vficon_selection_remove(vf, VFICON(vf)->click_fd, SELECTION_PRELIGHT, &iter); - layout_image_full_screen_start(vf->layout); + if (VFICON(vf)->click_fd->format_class == FORMAT_CLASS_COLLECTION) + { + collection_window_new(VFICON(vf)->click_fd->path); + } + else + { + vficon_selection_remove(vf, VFICON(vf)->click_fd, SELECTION_PRELIGHT, &iter); + layout_image_full_screen_start(vf->layout); + } } break; case MOUSE_BUTTON_RIGHT: diff -r a9225aa1d93c -r 5705ded05a19 src/view_file/view_file_list.c --- a/src/view_file/view_file_list.c Tue Jul 31 18:34:40 2018 +0200 +++ b/src/view_file/view_file_list.c Tue Feb 05 21:18:18 2019 +0100 @@ -24,6 +24,7 @@ #include "bar.h" #include "cache_maint.h" +#include "collect.h" #include "dnd.h" #include "editors.h" #include "img-view.h" @@ -39,6 +40,7 @@ #include "uri_utils.h" #include "view_file.h" + #include /* for keyboard values */ /* Index to tree store */ @@ -644,7 +646,14 @@ if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_2BUTTON_PRESS) { - if (vf->layout) layout_image_full_screen_start(vf->layout); + if (VFLIST(vf)->click_fd->format_class == FORMAT_CLASS_COLLECTION) + { + collection_window_new(VFLIST(vf)->click_fd->path); + } + else + { + if (vf->layout) layout_image_full_screen_start(vf->layout); + } } return FALSE; diff -r a9225aa1d93c -r 5705ded05a19 web/geeqie-install-debian.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/geeqie-install-debian.sh Tue Feb 05 21:18:18 2019 +0100 @@ -0,0 +1,708 @@ +#!/bin/bash +version="2018-08-06" +description=$' +Geeqie is an image viewer. +This script will download, compile, and install Geeqie on Debian-based systems. +If run from a folder that already contains the Geeqie sources, the source +code will be updated from the repository. +Dialogs allow the user to install additional features, including +additional pixbuf loaders. + +Command line options are: +-v --version The version of this file +-h --help Output this text +-c --commit=ID Checkout and compile commit ID +-t --tag=TAG Checkout and compile TAG (e.g. v1.4 or v1.3) +-b --back=N Checkout commit -N (e.g. "-b 1" for last-but-one commit) +' + +# Essential for compiling +essential_array=( +"git" +"build-essential" +"autoconf" +"libglib2.0-0" +"intltool" +) + +# Optional for both GTK2 and GTK3 +optional_array=( +"LCMS (for color management)" +"liblcms2-dev" +"exiv2 (for exif handling)" +"libgexiv2-dev" +"lua (for --remote commands)" +"liblua5.1-0-dev" +"libffmpegthumbnailer (for mpeg thumbnails)" +"libffmpegthumbnailer-dev" +"libtiff (for tiff support)" +"libtiff-dev" +"libjpeg (for jpeg support" +"libjpeg-dev" +"librsvg2 (for viewing .svg images" +"librsvg2-common" +"libwmf (for viewing .wmf images)" +"libwmf0.2-7-gtk" +"exiftran (for image rotation)" +"exiftran" +"imagemagick (for image rotation)" +"imagemagick" +"ufraw (for RAW file handling)" +"ufraw" +"markdown (for generating README help file)" +"markdown" +) + +# Optional for GTK3 only +optional_gtk3_array=( +"libchamplain gtk (for GPS maps)" +"libchamplain-gtk-0.12-dev" +"libchamplain (for GPS maps)" +"libchamplain-0.12-dev" +"libpoppler (for pdf file preview)" +"libpoppler-glib-dev" +) + +# Optional pixbuf loaders +optional_loaders_array=( +".webp WebP images" +"webp" +".psd Photoshop images" +"psd" +".xcf Gimp files" +"xcf" +) + +#################################################################### +# Get System Info +# Derived from: https://github.com/coto/server-easy-install (GPL) +#################################################################### +lowercase() +{ + echo "$1" | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/" +} + +systemProfile() +{ + OS=`lowercase \`uname\`` + KERNEL=`uname -r` + MACH=`uname -m` + + if [ "${OS}" == "windowsnt" ] + then + OS=windows + elif [ "${OS}" == "darwin" ] + then + OS=mac + else + OS=`uname` + if [ "${OS}" = "SunOS" ] + then + OS=Solaris + ARCH=`uname -p` + OSSTR="${OS} ${REV}(${ARCH} `uname -v`)" + elif [ "${OS}" = "AIX" ] + then + OSSTR="${OS} `oslevel` (`oslevel -r`)" + elif [ "${OS}" = "Linux" ] + then + if [ -f /etc/redhat-release ] + then + DistroBasedOn='RedHat' + DIST=`cat /etc/redhat-release |sed s/\ release.*//` + PSUEDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//` + REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//` + elif [ -f /etc/SuSE-release ] + then + DistroBasedOn='SuSe' + PSUEDONAME=`cat /etc/SuSE-release | tr "\n" ' '| sed s/VERSION.*//` + REV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //` + elif [ -f /etc/mandrake-release ] + then + DistroBasedOn='Mandrake' + PSUEDONAME=`cat /etc/mandrake-release | sed s/.*\(// | sed s/\)//` + REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//` + elif [ -f /etc/debian_version ] + then + DistroBasedOn='Debian' + if [ -f /etc/lsb-release ] + then + DIST=`cat /etc/lsb-release | grep '^DISTRIB_ID' | awk -F= '{ print $2 }'` + PSUEDONAME=`cat /etc/lsb-release | grep '^DISTRIB_CODENAME' | awk -F= '{ print $2 }'` + REV=`cat /etc/lsb-release | grep '^DISTRIB_RELEASE' | awk -F= '{ print $2 }'` + fi + fi + if [ -f /etc/UnitedLinux-release ] + then + DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]" + fi + OS=`lowercase $OS` + DistroBasedOn=`lowercase $DistroBasedOn` + readonly OS + readonly DIST + readonly DistroBasedOn + readonly PSUEDONAME + readonly REV + readonly KERNEL + readonly MACH + fi + fi +} + +install_essential() +{ +arraylength=${#essential_array[@]} +for (( i=0; i<${arraylength}; i=i+1 )); +do + package_query ${essential_array[$i]} + if [ $? != 0 ] + then + package_install ${essential_array[$i]} + fi +done + +if [[ $1 == "GTK3" ]] +then + package_query "libgtk-3-dev" + if [ $? != 0 ] + then + package_install libgtk-3-dev + fi +else + package_query "libgtk2.0-dev" + if [ $? != 0 ] + then + package_install libgtk2.0-dev + fi +fi +} + +install_options() +{ +if [ -n "$options" ] +then + OLDIFS=$IFS + IFS='|' + set $options + while [ $# -gt 0 ]; + do + package_install $1 + shift + done + IFS=$OLDIFS +fi +} + +install_webp() +{ +rm -rf webp-pixbuf-loader-master +package_install libglib2.0-dev libgdk-pixbuf2.0-dev libwebp-dev python-minimal +wget https://github.com/aruiz/webp-pixbuf-loader/archive/master.zip +unzip master.zip +cd webp-pixbuf-loader-master +./waf configure +./waf build +sudo --askpass ./waf install +sudo --askpass gdk-pixbuf-query-loaders --update-cache +cd - +rm -rf webp-pixbuf-loader-master +rm master.zip +} + +install_psd() +{ +rm -rf gdk-pixbuf-psd +git clone https://github.com/and-rom/gdk-pixbuf-psd.git +cd gdk-pixbuf-psd +./autogen.sh +make +sudo --askpass make install +sudo --askpass gdk-pixbuf-query-loaders --update-cache +cd - +rm -rf gdk-pixbuf-psd +} + +install_xcf() +{ +rm -rf xcf-pixbuf-loader +package_install libbz2-dev +git clone https://github.com/StephaneDelcroix/xcf-pixbuf-loader.git +cd xcf-pixbuf-loader +./autogen.sh +make + +# There must be a better way... +loader_locn=$(gdk-pixbuf-query-loaders | grep "LoaderDir" | tr -d '#[:space:]') + +OLDIFS=$IFS +IFS='=' +set $loader_locn +OLDIFS=$IFS + +if [ -d $2 ] +then + sudo --askpass cp .libs/libioxcf.so $2 + sudo --askpass gdk-pixbuf-query-loaders --update-cache +fi +cd - +rm -rf xcf-pixbuf-loader +} + +install_extra_loaders() +{ +if [ -n "$extra_loaders" ] +then + OLDIFS=$IFS + IFS='|' + set $extra_loaders + while [ $# -gt 0 ]; + do + case $1 in + "webp" ) + install_webp + ;; + "psd" ) + install_psd + ;; + "xcf" ) + install_xcf + ;; + esac + + shift + done + IFS=$OLDIFS +fi +return +} + +uninstall() +{ +current_dir=$(basename $PWD) +if [[ $current_dir == "geeqie" ]] +then + sudo --askpass make uninstall + zenity --title="Uninstall Geeqie" --width=370 --text="WARNING.\nThis will delete folder:\n\n$PWD\n\nand all sub-folders!" --question --ok-label="Cancel" --cancel-label="OK" 2>/dev/null + + if [[ $? == 1 ]] + then + cd .. + sudo --askpass rm -rf geeqie + fi +else + zenity --title="Uninstall Geeqie" --width=370 --text="This is not a geeqie installation folder!\n\n$PWD" --warning 2>/dev/null +fi + +exit_install +} + +package_query() +{ +if [[ $DistroBasedOn == "debian" ]] +then + res=$(dpkg-query --show --showformat='${Status}' $1 2>>$install_log) + if [[ "$res" == "install ok installed"* ]] + then + status=0 + else + status=1 + fi +fi +return $status +} + +package_install() +{ +if [[ $DistroBasedOn == "debian" ]] +then + sudo --askpass apt-get --assume-yes install $@ >>$install_log 2>&1 +fi +} + +exit_install() +{ +rm $install_pass_script >/dev/null 2>&1 +#~ rm $install_log >/dev/null 2>&1 + +if [[ -p $zen_pipe ]] +then + echo "100" > $zen_pipe + echo "#End" > $zen_pipe +fi + +zenity --title="$title" --width=370 --text=$'Geeqie is not installed\nLog file: '$install_log --info 2>/dev/null + +rm $zen_pipe >/dev/null 2>&1 + +exit 1 +} + +# Entry point + +# If uninstall has been run, maybe the current directory no longer exists +ls $PWD >/dev/null +if [[ $? != 0 ]] +then + zenity --error --title="Install Geeqie and dependencies" --width=370 --text="Folder $PWD does not exist!" 2>/dev/null + + exit +fi + +# Check system type +systemProfile +if [[ $DistroBasedOn != "debian" ]] +then + zenity --error --title="Install Geeqie and dependencies" --width=370 --text="Unknown operating system:\n +Operating System: $OS +Distribution: $DIST +Psuedoname: $PSUEDONAME +Revision: $REV +DistroBasedOn: $DistroBasedOn +Kernel: $KERNEL +Machine: $MACH" 2>/dev/null + + exit +fi + +# Parse the comand line +OPTS=$(getopt -o vhc:t:b: --long version,help,commit:,tag:,back: -- "$@") +eval set -- "$OPTS" + +while true; +do + case "$1" in + -v | --version ) + echo "$version" + exit + ;; + -h | --help ) + echo "$description" + exit + ;; + -c | --commit ) + COMMIT="$2" + shift + shift + ;; + -t | --tag ) + TAG="$2" + shift; + shift + ;; + -b | --back ) + BACK="$2" + shift; + shift + ;; + * ) break + ;; + esac +done + +# If a Geeqie folder already exists here, warn the user +if [ -d "geeqie" ] +then + zenity --info --title="Install Geeqie and dependencies" --width=370 --text="This script is for use on Ubuntu and other\nDebian-based installations.\nIt will download, compile, and install Geeqie source\ncode and its dependencies.\n\nA sub-folder named \"geeqie\" will be created in the\nfolder this script is run from, and the source code\nwill be downloaded to that sub-folder.\n\nA sub-folder of that name already exists.\nPlease try another folder." 2>/dev/null + + exit +fi + +# If it looks like a Geeqie download folder, assume an update +if [ -d ".git" ] && [ -d "src" ] && [ -f "geeqie.1" ] +then + mode="update" +else + # If it looks like something else is already installed here, warn the user + if [ -d ".git" ] || [ -d "src" ] + then + zenity --info --title="Install Geeqie and dependencies" --width=370 --text="This script is for use on Ubuntu and other\nDebian-based installations.\nIt will download, compile, and install Geeqie source\ncode and its dependencies.\n\nIt looks like you are running this script from a folder which already has software installed.\n\nPlease try another folder." 2>/dev/null + + exit + else + mode="install" + fi +fi + +# Use GTK3 as default +gk2_installed=FALSE +gtk3_installed=TRUE + +if [[ $mode == "install" ]] +then + message="This script is for use on Ubuntu and other\nDebian-based installations.\nIt will download, compile, and install Geeqie source\ncode and its dependencies.\n\nA sub-folder named \"geeqie\" will be created in the\nfolder this script is run from, and the source code\nwill be downloaded to that sub-folder.\n\nIn this dialog you must select whether to compile\nfor GTK2 or GTK3.\nIf you want to use GPS maps or pdf preview,\nyou must choose GTK3.\nThe GTK2 version has a slightly different\nlook-and-feel compared to the GTK3 version,\nbut otherwise has the same features.\nYou may easily switch between the two after\ninstallation.\n\nIn subsequent dialogs you may choose which\noptional features to install." + + title="Install Geeqie and dependencies" + install_option=TRUE +else + message="This script is for use on Ubuntu and other\nDebian-based installations.\nIt will update the Geeqie source code and its\ndependencies, and will compile and install Geeqie.\n\nYou may also switch the installed version from\nGTK2 to GTK3 and vice versa.\n\nIn this dialog you must select whether to compile\nfor GTK2 or GTK3.\nIf you want to use GPS maps or pdf preview,\nyou must choose GTK3.\nThe GTK2 version has a slightly different\nlook-and-feel compared to the GTK3 version,\nbut otherwise has the same features.\n\nIn subsequent dialogs you may choose which\noptional features to install." + + title="Update Geeqie and re-install" + install_option=FALSE + + # When updating, use previous installation as default + if [[ -f config.log ]] + then + grep gtk-2.0 config.log >/dev/null + if [[ $? != 0 ]] + then + gtk2_installed=FALSE + gtk3_installed=TRUE + else + gtk2_installed=TRUE + gtk3_installed=FALSE + fi + fi +fi + +# Ask whether to install GTK2 or GTK3 or uninstall + +gtk_version=$(zenity --title="$title" --width=370 --text="$message" --list --radiolist --column "" --column "" "$gtk3_installed" "GTK3 (required for GPS maps and pdf preview)" "$gtk2_installed" "GTK2" FALSE "Uninstall" --cancel-label="Cancel" --ok-label="OK" --hide-header 2>/dev/null) + +if [[ $? == 1 ]] +then + exit +fi + +# Environment variable SUDO_ASKPASS cannot be "zenity --password", +# so create a temporary script containing the command +install_pass_script=$(mktemp --tmpdir geeqie_install_XXXXXX.sh) +echo $'#!/bin/bash +zenity --password --title=\"'$title$'\" --width=370 2>/dev/null +if [[ $? > 0 ]] +then + exit 1 +fi +\n' > $install_pass_script +chmod +x $install_pass_script +export SUDO_ASKPASS=$install_pass_script + +if [[ $gtk_version == "Uninstall" ]] +then + uninstall + exit +fi + +# Put the install log in tmp, to avoid writing to PWD during a new install +rm install.log 2>/dev/null +install_log=$(mktemp --tmpdir geeqie_install_XXXXXX.log) + +sleep 100 | zenity --title="$title" --text="Checking for installed files" --width=370 --progress --pulsate 2>/dev/null & +zen_pid=$! + +# Get the standard options that are not yet installed +arraylength=${#optional_array[@]} +for (( i=0; i<${arraylength}; i=i+2 )); +do + package_query ${optional_array[$i+1]} + if [ $? != 0 ] + then + if [ -z "$option_string" ] + then + option_string="$install_option"$'\n'"${optional_array[$i]}"$'\n'"${optional_array[$i+1]}" + else + option_string="$option_string"$'\n'"$install_option"$'\n'"${optional_array[$i]}"$'\n'"${optional_array[$i+1]}" + fi + fi +done + +# If GTK3 required, get the GTK3 options not yet installed +if [[ "$gtk_version" == "GTK3"* ]] +then + arraylength=${#optional_gtk3_array[@]} + for (( i=0; i<${arraylength}; i=i+2 )); + do + package_query ${optional_gtk3_array[$i+1]} + if [ $? != 0 ] + then + if [ -z "$option_string" ] + then + option_string="$install_option"$'\n'"${optional_gtk3_array[$i]}"$'\n'"${optional_gtk3_array[$i+1]}" + else + option_string="$option_string"$'\n'"$install_option"$'\n'"${optional_gtk3_array[$i]}"$'\n'"${optional_gtk3_array[$i+1]}" + fi + fi + done +fi + +# Get the optional loaders not yet installed +((i=0)) +gdk-pixbuf-query-loaders | grep WebP >/dev/null +if [[ $? == 1 ]] +then + if [ -z "$loaders_string" ] + then + loaders_string=$'FALSE\n'"${optional_loaders_array[$i]}"$'\n'"${optional_loaders_array[$i+1]}" + else + loaders_string="$loaders_string"$'\nFALSE\n'"${optional_loaders_array[$i]}"$'\n'"${optional_loaders_array[$i+1]}" + + fi +fi + +((i=i+2)) +gdk-pixbuf-query-loaders | grep psd >/dev/null +if [[ $? == 1 ]] +then + if [ -z "$loaders_string" ] + then + loaders_string=$'FALSE\n'"${optional_loaders_array[$i]}"$'\n'"${optional_loaders_array[$i+1]}" + else + loaders_string="$loaders_string"$'\nFALSE\n'"${optional_loaders_array[$i]}"$'\n'"${optional_loaders_array[$i+1]}" + fi +fi + +((i=i+2)) +gdk-pixbuf-query-loaders | grep xcf >/dev/null +if [[ $? == 1 ]] +then + if [ -z "$loaders_string" ] + then + loaders_string=$'FALSE\n'"${optional_loaders_array[$i]}"$'\n'"${optional_loaders_array[$i+1]}" + else + loaders_string="$loaders_string"$'\nFALSE\n'"${optional_loaders_array[$i]}"$'\n'"${optional_loaders_array[$i+1]}" + fi +fi + +kill $zen_pid 2>/dev/null + +# Ask the user which options to install +if [ -n "$option_string" ] +then + options=$(echo "$option_string" | zenity --title="$title" --width=400 --height=500 --list --checklist --text 'Select which library files to install:' --column='Select' --column='Library files' --column='Library' --hide-column=3 --print-column=3 2>/dev/null) + + if [[ $? == 1 ]] + then + exit_install + fi +fi + +# Ask the user which extra loaders to install +if [ -n "$loaders_string" ] +then + extra_loaders=$(echo "$loaders_string" | zenity --title="$title" --width=370 --height=400 --list --checklist --text 'These loaders are not part of the main repository,\nbut are known to work to some extent.' --column='Select' --column='Library files' --column='Library' --hide-column=3 --print-column=3 2>/dev/null) + + if [[ $? == 1 ]] + then + exit_install + fi +fi + +# Start of Zenity progress section +zen_pipe=$(mktemp --dry-run --tmpdir geeqie_install_pipe_XXXXXX) +mkfifo $zen_pipe +(tail -f $zen_pipe 2>/dev/null) | zenity --progress --title="$title" --width=370 --text="Installing options..." --auto-close --auto-kill --percentage=0 2>/dev/null & + +echo "2" > $zen_pipe +echo "#Installing essential libraries..." > $zen_pipe + +install_essential $gtk_version + +echo "4" > $zen_pipe +echo "#Installing options..." > $zen_pipe + +install_options + +echo "6" > $zen_pipe +echo "#Installing extra loaders..." > $zen_pipe + +install_extra_loaders + +echo "10" > $zen_pipe +echo "#Getting new sources from server..." > $zen_pipe + +if [[ $mode == "install" ]] +then + ret=$(git clone git://www.geeqie.org/geeqie.git >>$install_log 2>&1) +else + git checkout master >>$install_log 2>&1 + if [[ $? != 0 ]] + then + git_error=$(tail -n5 $install_log 2>&1) + zenity --title="$title" --width=370 --height=400 --error --text=$'Git error:\n\n'"$git_error" 2>/dev/null + exit_install + fi + ret=$(git pull >>$install_log 2>&1) +fi + +if [[ $? != 0 ]] +then + git_error=$(tail -n5 $install_log 2>&1) + zenity --title="$title" --width=370 --height=400 --error --text=$'Git error:\n\n'"$git_error" 2>/dev/null + exit_install +fi + +echo "20" > $zen_pipe +echo "#Cleaning installed version..." > $zen_pipe + +if [[ $mode == "install" ]] +then + cd geeqie +else + sudo --askpass make uninstall >>$install_log 2>&1 + sudo --askpass make maintainer-clean >>$install_log 2>&1 +fi + +echo "30" > $zen_pipe +echo "#Checkout required version..." > $zen_pipe + +if [[ "$BACK" ]] +then + ret=$(git checkout master~"$BACK" >>$install_log 2>&1) + if [[ $? != 0 ]] + then + git_error=$(tail -n5 $install_log 2>&1) + zenity --title="$title" --width=370 --height=400 --error --text=$'Git error:\n\n'"$git_error" 2>/dev/null + exit_install + fi +elif [[ "$COMMIT" ]] +then + ret=$(git checkout "$COMMIT" >>$install_log 2>&1) + if [[ $? != 0 ]] + then + git_error=$(tail -n5 $install_log 2>&1) + zenity --title="$title" --width=370 --height=400 --error --text=$'Git error:\n\n'"$git_error" 2>/dev/null + exit_install + fi +elif [[ "$TAG" ]] +then + ret=$(git checkout "$TAG" >>$install_log 2>&1) + if [[ $? != 0 ]] + then + echo "error" + git_error=$(tail -n5 $install_log 2>&1) + zenity --title="$title" --width=370 --height=400 --error --text=$'Git error:\n\n'"$git_error" 2>/dev/null + exit_install + exit + fi +fi + +echo "40" > $zen_pipe +echo "#Creating configuration files..." > $zen_pipe + +if [[ $gtk_version == "GTK3"* ]] +then + ./autogen.sh >>$install_log 2>&1 +else + ./autogen.sh --disable-gtk3 >>$install_log 2>&1 +fi + +echo "60" > $zen_pipe +echo "#Compiling..." > $zen_pipe + +export CFLAGS=$CFLAGS" -Wno-deprecated-declarations" +export CXXFLAGS=$CXXFLAGS" -Wno-deprecated-declarations" +make -j >>$install_log 2>&1 + +echo "90 " > $zen_pipe +echo "#Installing Geeqie..." > $zen_pipe + +sudo --askpass make install >>$install_log 2>&1 + +rm $install_pass_script +mv -f $install_log install.log; + +echo "100 " > $zen_pipe +rm $zen_pipe + +(for i in $(seq 0 4 100); do echo "$i"; sleep 0.1; done) | zenity --progress --title="$title" --width=370 --text="Geeqie installation complete...\n" --auto-close 2>/dev/null + +exit diff -r a9225aa1d93c -r 5705ded05a19 web/help/GuideFaq.html --- a/web/help/GuideFaq.html Tue Jul 31 18:34:40 2018 +0200 +++ b/web/help/GuideFaq.html Tue Feb 05 21:18:18 2019 +0100 @@ -3,7 +3,7 @@ Frequently Asked Questions - + + + + + +
+

Caching Data For Searches

+ +

+ Searching large numbers of files for similarity can take significant cpu time. Part of this is the time to compute the similarity matrix for each file. +

+ If the + Cache Thumbnails + option is selected in Preferences/General, the similarity matrix and the checksum will also be cached. This will reduce the time needed for future searches. +
If you frequently search on similarity and your images are in a tree arrangement under a single point, initiating a one-time search on similarity from the top of the tree will generate the similarity data for all images.
+

Similarity data are stored in a folder hierachy that mirrors the location of the source images. The data have the same name as the original appended by the file extension .sim.

+

+ The root of the hierachy is: +

+

$XDG_CACHE_HOME/geeqie/thumbnails/
+ or, if $XDG_CACHE_HOME is not defined: +
$HOME/.cache/geeqie/thumbnails/
+

+

+

+

+
+ + + diff -r a9225aa1d93c -r 5705ded05a19 web/help/GuideImageSearchSearch.html --- a/web/help/GuideImageSearchSearch.html Tue Jul 31 18:34:40 2018 +0200 +++ b/web/help/GuideImageSearchSearch.html Tue Feb 05 21:18:18 2019 +0100 @@ -531,7 +531,13 @@
File name
-
The search will match if the entered text appears within the file name, or if the text exactly matches the file name, depending on the method selected from the drop down menu. The text comparison can be made to be case sensitive by enabling the Match case checkbox.
+
+ The search will match if the entered text appears within the file name, or if the text exactly matches the file name, depending on the method selected from the drop down menu. The text comparison can be made to be case sensitive by enabling the Match case checkbox. +

+ If "contains" is selected, + Perl Compatible Regular Expressions + are used. +
File size
@@ -586,6 +592,14 @@
The search will match if the file's associated keywords match all, match any, or exclude the entered keywords, depending on the method selected from the drop down menu. Keywords can be separated with a space, comma, or tab character.
+ Comment +
+
+ The search will match if the file's Comments field contains the entered pattern. + Perl Compatible Regular Expressions + are used. +
+
Geocoded position
diff -r a9225aa1d93c -r 5705ded05a19 web/help/GuideIndex.html --- a/web/help/GuideIndex.html Tue Jul 31 18:34:40 2018 +0200 +++ b/web/help/GuideIndex.html Tue Feb 05 21:18:18 2019 +0100 @@ -659,6 +659,9 @@
  • 13.13. Standards
  • +
  • +13.14. Perl Compatible Regular Expressions +
  • diff -r a9225aa1d93c -r 5705ded05a19 web/help/GuideOptionsBehavior.html --- a/web/help/GuideOptionsBehavior.html Tue Jul 31 18:34:40 2018 +0200 +++ b/web/help/GuideOptionsBehavior.html Tue Feb 05 21:18:18 2019 +0100 @@ -580,6 +580,18 @@

    Save all marks that have been set. Note that marks that are linked to a keyword will always be saved irrespective of this setting.

  • + Use "With Rename" as default for Copy/Move dialogs +
    +
    +

    Move the "With Rename" button to the default position.

    +
    +
    + Open Collections on top +
    +
    +

    Open collection windows with "Always on Top" set.

    +
    +
    Recent folder list maximum size
    diff -r a9225aa1d93c -r 5705ded05a19 web/help/GuideOptionsFiltering.html --- a/web/help/GuideOptionsFiltering.html Tue Jul 31 18:34:40 2018 +0200 +++ b/web/help/GuideOptionsFiltering.html Tue Feb 05 21:18:18 2019 +0100 @@ -593,12 +593,14 @@
    This may be used to define sets of file types, for use in the Grouping - function described above. The drop-down list has 4 entries: + function described above. The drop-down list has 6 entries:
    • Unknown
    • Image
    • RAW Image
    • Metadata
    • +
    • Video
    • +
    • Collection
    diff -r a9225aa1d93c -r 5705ded05a19 web/help/GuideReference.html --- a/web/help/GuideReference.html Tue Jul 31 18:34:40 2018 +0200 +++ b/web/help/GuideReference.html Tue Feb 05 21:18:18 2019 +0100 @@ -443,6 +443,7 @@
  • UTC and Daylight Saving Time (DST)
  • Decoding Latitude and Longitude
  • Standards
  • +
  • Perl Compatible Regular Expressions
  • Frequently Asked Questions
  • @@ -496,6 +497,9 @@
  • 13.13. Standards
  • +
  • +13.14. Perl Compatible Regular Expressions +
  • + +
    +

    Perl Compatible Regular Expressions

    + +

    + The Filename and Comment sections on the search window use + Perl Compatible Regular Expressions + . In general use there are a number of differences to the wildcard expansion used on the command line: +

      +
    • Use "." and not "?" for a single character.
    • +
    • Use "abc.*ghk" and not "abc*ghk" for multiple characters
    • +
    • Use "\." to represent the dot in a file extension
    • +
    +

    +
    + + + diff -r a9225aa1d93c -r 5705ded05a19 web/help/GuideReferencePixbufLoaders.html --- a/web/help/GuideReferencePixbufLoaders.html Tue Jul 31 18:34:40 2018 +0200 +++ b/web/help/GuideReferencePixbufLoaders.html Tue Feb 05 21:18:18 2019 +0100 @@ -444,6 +444,7 @@
  • UTC and Daylight Saving Time (DST)
  • Decoding Latitude and Longitude
  • Standards
  • +
  • Perl Compatible Regular Expressions
  • Frequently Asked Questions
  • diff -r a9225aa1d93c -r 5705ded05a19 web/help/GuideReferenceStandards.html --- a/web/help/GuideReferenceStandards.html Tue Jul 31 18:34:40 2018 +0200 +++ b/web/help/GuideReferenceStandards.html Tue Feb 05 21:18:18 2019 +0100 @@ -4,7 +4,7 @@ Standards - +