--- /dev/null
+## A checklist to be used after Geeqie has been updated
+
+Before compiling the sources, carry out the following actions when necessary:
+
+* Update ```org.geeqie.Geeqie.appdata.xml.in``` with the latest released version and date
+* If source files have been added or removed from ```.src/``` directory, resync ```./po/POTFILES.in```
+```
+cd ./po
+./regen_potfiles.sh | patch -p0
+```
+* Keep translations in sync with the code
+```
+cd ./po
+make update-po
+```
+* Update the the timezone database
+```
+./scripts/zonedetect/create_timezone_database
+```
+
+After compiling the sources, carry out the following actions when necessary:
+
+* Generate a new AppImage (note that this should be run on a **20.04 system**)
+```
+./scripts/generate-appimage.sh <location of GeeqieWeb/appimages folder>
+```
+* Copy Help html files to ```<location of GeeqieWeb/help folder>```
+* Copy ```geeqie.desktop``` to ```<location of GeeqieWeb/ folder>```
+* Copy ```org.geeqie.Geeqie.appdata.xml``` to ```<location of GeeqieWeb/ folder>```
+* Upload to GeeqieWeb
+
+++ /dev/null
-Log Window:
-
-DEBUG_0()
-Use DEBUG_0() only for temporary debugging i.e. not in code in the repository.
-The user will then not see irrelevant debug output when the default
-debug level = 0 is used.
-
-log_printf()
-If the first word of the message is "error" or "warning" (case insensitive)
-the message will be color-coded appropriately.
-
-
-GTKInspector:
-
-DEBUG_NAME(widget)
-For use with the GTKInspector to provide a visual indication of where objects are declared.
-
-Sample command line call:
-GTK_DEBUG=interactive src/geeqie
-
---------------------------------------------------------------------------------
-
-GPL header, in every file, like this:
-
-/** \file
- * \short Short description of this file.
- * \author Author1
- * \author Author2
- *
- * Optionally detailed description of this file
- * on more lines.
- */
-
-/*
- * This file is a part of Geeqie project (http://www.geeqie.org/).
- * Copyright (C) 2008 - 2016 The Geeqie Team
- *
- * 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.
- */
-
---------------------------------------------------------------------------------
-
-git change-log:
-
-If referencing a Geeqie GitHub issue, include the issue number in the summary line.
-Start with a short summary in the first line (without a dot at the end) followed
-by a empty line.
-
-If referencing a Geeqie GitHub issue, include a hyperlink to the GitHub issue page
-in the message body.
-Use whole sentences begins with Capital letter. For each
-modification use new line. Or you can write the theme, colon and then every
-change on new line, begin with "- ".
-
-See also: http://www.tpope.net/node/106
-
-Example:
-
- I did some bugfixes
-
- There was the bug that something was wrong. I fixed it.
-
- Library:
- - the interface was modified
- - new functions were added
-
-Also please use your full name and a working e-mail address as author for any contribution.
-
---------------------------------------------------------------------------------
-
-sources:
-
-Indentation: tabs
-Names of variables & functions: small_letters
- of defines: CAPITAL_LETTERS
-
-Try to use explicit variable and function names.
-
-Try not to use macros.
-Use EITHER "struct foo" OR "foo"; never both
-
-
-Conditions, cycles:
-
-if (<cond>)
- {
- <command>;
- ...
- <command>;
- }
-else
- {
- <command>;
- ...
- <command>;
- }
-
-if (<cond_very_very_very_very_very_very_very_very_very_long> &&
- <cond2very_very_very_very_very_very_very_very_very_long>)
- <the_only_command>;
-
-switch (<var>)
- {
- case 0:
- <command>;
- <command>;
- break;
- case 1:
- <command>; break;
- }
-
-for (i = 0; i <= 10; i++)
- {
- <command>;
- ...
- <command>;
- }
-
-
-Functions:
-
-gint bar(<var_def>, <var_def>, <var_def>)
-{
- <command>;
- ...
- <command>;
-
- return 0; // i.e. SUCCESS; if error, you must return minus <err_no>
-}
-
-void bar2(void)
-{
- <command>;
- ...
- <command>;
-}
-
-Pragma: (Indentation 2 spaces)
-
-#ifdef ENABLE_NLS
-# undef _
-# define _(String) (String)
-#endif /* ENABLE_NLS */
-
-Headers:
-
-#ifndef _FILENAME_H
-
---------------------------------------------------------------------------------
-
-Use spaces around every operator (except ".", "->", "++" and "--");
- unary operator '*' and '&' are missing the space from right;
- (and also unary '-').
-As you can see above, parentheses are closed to inside, i.e. " (blah blah) "
- In "function(<var>)" there are no space before '('.
-You MAY use more tabs/spaces than you OUGHT TO (according to this CodingStyle), if
- it makes your code nicer in being vertically indented.
-Variables declarations should be followed by a blank line and should always be
-at the start of the block.
-
---------------------------------------------------------------------------------
-
-Use glib types when possible (ie. gint and gchar instead of int and char).
-Use glib functions when possible (ie. g_ascii_isspace() instead of isspace()).
-Check if used functions are not deprecated.
-
---------------------------------------------------------------------------------
-
-Documentation:
-
-Use American, rather than British English, spelling. This will facilitate consistent
-text searches. User text may be translated via the en_GB.po file.
-
-To document the code use the following rules to allow extraction with doxygen.
-Do not save with comments. Not all comments have to be doxygen comments.
-
-- Use C comments in plain C files and use C++ comments in C++ files for one line
- comments.
-- Use '/**' (note the two asterisks) to start comments to be extracted by
- doxygen and start every following line with " *".
-- Use '@' to indicate doxygen keywords/commands (see below).
-- Use the '@deprecated' command to tell if the function is subject to be deleted
- or to a complete rewrite.
-
-Example:
-
-To document functions or big structures:
- /**
- * @brief This is a short description of the function.
- *
- * This function does ...
- *
- * @param x1 This is the first parameter named x1
- * @param y1 This is the second parameter named y1
- * @return What the function returns
- * You can extend that return description (or anything else) by indenting the
- * following lines until the next empty line or the next keyword/command.
- * @see Cross reference
- */
-
-To document members of a structure that have to be documented (use it at least
-for big structures) use the '/**<' format:
- int counter; /**< This counter counts images */
-
-Document TODO or FIXME comments as:
- /**
- * @todo
-or
- /**
- * @FIXME
-
-For further documentation about doxygen see
-http://www.stack.nl/~dimitri/doxygen/manual.html. For the possible commands you
-can use see http://www.stack.nl/~dimitri/doxygen/commands.html.
-
-But in case just think about that the documentation is for other developers not
-for the end user. So keep the focus.
-
-The file ./scripts/doxygen-help.sh may be used to integrate access to the
-Doxygen files into a code editor.
--- /dev/null
+[Log Window](#log-window)
+[GPL header](#gpl-header)
+[Git change log](#git-change-log)
+[Sources](#sources)
+[Documentation](#documentation)
+
+-----------
+
+
+# <a name='log-window'>
+# Log Window
+
+`DEBUG_0()`
+Use `DEBUG_0()` only for temporary debugging i.e. not in code in the repository.
+The user will then not see irrelevant debug output when the default
+`debug level = 0` is used.
+
+`log_printf()`
+If the first word of the message is "error" or "warning" (case insensitive) the message will be color-coded appropriately.
+
+
+`DEBUG_NAME(widget)`
+For use with the [GTKInspector](https://wiki.gnome.org/action/show/Projects/GTK/Inspector?action=show&redirect=Projects%2FGTK%2B%2FInspector) to provide a visual indication of where objects are declared.
+
+Sample command line call:
+`GTK_DEBUG=interactive src/geeqie`
+
+--------------------------------------------------------------------------------
+
+# <a name='gpl-header'>
+# GPL header
+
+Include a header in every file, like this:
+
+ /** @file
+ * @brief Short description of this file.
+ * @author Author1
+ * @author Author2
+ *
+ * Optionally detailed description of this file
+ * on more lines.
+ */
+
+ /*
+ * This file is a part of Geeqie project (http://www.geeqie.org/).
+ * Copyright (C) 2008 - 2021 The Geeqie Team
+ *
+ * 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.
+ */
+
+-------------
+
+# <a name='git-change-log'>
+# git change-log
+
+If referencing a Geeqie GitHub issue, include the issue number in the summary line. Start with a short summary in the first line (without a dot at the end) followed by a empty line.
+
+If referencing a Geeqie GitHub issue, include a hyperlink to the GitHub issue webpage in the message body. Use whole sentences beginning with Capital letter. For each modification use a new line. Or you can write the theme, colon and then every change on new line, begin with "- ".
+
+See also [A Note About Git Commit Messages](http://www.tpope.net/node/106)
+
+Example:
+
+ `I did some bugfixes`
+
+ `There was the bug that something was wrong. I fixed it.`
+
+ ` Library:`
+ `- the interface was modified`
+ `- new functions were added`
+
+Also please use your full name and a working e-mail address as author for any contribution.
+
+--------------------------------------------------------------------------------
+
+# <a name='sources'>
+# Sources
+
+Indentation: tabs at 4 spaces
+
+
+Names:
+
+- of variables & functions: small\_letters
+- of defines: CAPITAL\_LETTERS
+
+Try to use explicit variable and function names.
+Try not to use macros.
+Use EITHER "struct foo" OR "foo"; never both
+
+
+Conditions, cycles:
+
+ if (<cond>)
+ {
+ <command>;
+ ...
+ <command>;
+ }
+ else
+ {
+ <command>;
+ ...
+ <command>;
+ }
+
+ if (<cond_very_very_very_very_very_very_very_very_very_long> &&
+ <cond2very_very_very_very_very_very_very_very_very_long>)
+ <the_only_command>;
+
+ switch (<var>)
+ {
+ case 0:
+ <command>;
+ <command>;
+ break;
+ case 1:
+ <command>; break;
+ }
+
+ for (i = 0; i <= 10; i++)
+ {
+ <command>;
+ ...
+ <command>;
+ }
+
+Functions:
+
+ gint bar(<var_def>, <var_def>, <var_def>)
+ {
+ <command>;
+ ...
+ <command>;
+
+ return 0; // i.e. SUCCESS; if error, you must return minus <err_no>
+ }
+
+ void bar2(void)
+ {
+ <command>;
+ ...
+ <command>;
+ }
+
+Pragma: (Indentation 2 spaces)
+
+ #ifdef ENABLE_NLS
+ # undef _
+ # define _(String) (String)
+ #endif /* ENABLE_NLS */
+
+Headers:
+
+ #ifndef _FILENAME_H
+
+
+Use spaces around every operator (except ".", "->", "++" and "--").
+Unary operator '*' and '&' are missing the space from right, (and also unary '-').
+
+As you can see above, parentheses are closed to inside, i.e. " (blah blah) "
+In "`function(<var>)`" there is no space before the '('.
+You MAY use more tabs/spaces than you OUGHT TO (according to this CodingStyle), if it makes your code nicer in being vertically indented.
+Variables declarations should be followed by a blank line and should always be at the start of the block.
+
+
+Use glib types when possible (ie. gint and gchar instead of int and char).
+Use glib functions when possible (ie. `g_ascii_isspace()` instead of `isspace()`).
+Check if used functions are not deprecated.
+
+--------------------------------------------------------------------------------
+
+# <a name='documentation'>
+# Documentation
+
+Use American, rather than British English, spelling. This will facilitate consistent
+text searches. User text may be translated via the en_GB.po file.
+
+To document the code use the following rules to allow extraction with doxygen.
+Do not save with comments. Not all comments have to be doxygen comments.
+
+- Use C comments in plain C files and use C++ comments in C++ files for one line
+ comments.
+- Use '/**' (note the two asterisks) to start comments to be extracted by
+ doxygen and start every following line with " *".
+- Use '@' to indicate doxygen keywords/commands (see below).
+- Use the '@deprecated' command to tell if the function is subject to be deleted
+ or to a complete rewrite.
+
+Example:
+
+To document functions or big structures:
+
+ /**
+ * @brief This is a short description of the function.
+ *
+ * This function does ...
+ *
+ * @param x1 This is the first parameter named x1
+ * @param y1 This is the second parameter named y1
+ * @return What the function returns
+ * You can extend that return description (or anything else) by indenting the
+ * following lines until the next empty line or the next keyword/command.
+ * @see Cross reference
+ */
+
+To document members of a structure that have to be documented (use it at least
+for big structures) use the `/**<` format:
+`int counter; /**< This counter counts images */`
+
+Document TODO or FIXME comments as:
+
+ /**
+ * @todo
+
+or
+
+ /**
+ * @FIXME
+
+For further documentation about doxygen see the [Doxygen Manual](https://www.doxygen.nl/index.html).
+For the possible commands you may use, see [Doxygen Special Commands](https://www.doxygen.nl/manual/commands.html).
+
+The file `./scripts/doxygen-help.sh` may be used to integrate access to the Doxygen files into a code editor.
+
+The following environment variables may be set to personalize the Doxygen output:
+`DOCDIR=<output folder>`
+`SRCDIR=<the folder above ./src>`
+`PROJECT=`
+`VERSION=`
+`PLANTUML_JAR_PATH=`
+`INLINE_SOURCES=<YES|NO>`
+`STRIP_CODE_COMMENTS=<YES|NO>`
+
+Ref: [INLINE\_SOURCES](https://www.doxygen.nl/manual/config.html#cfg_inline_sources)
+Ref: [STRIP\_CODE\_COMMENTS](https://www.doxygen.nl/manual/config.html#cfg_strip_code_comments)
+
+To include diagrams (if any) in the Doxygen output, the following are required to be installed. The installation process will vary between distributions:
+[The PlantUML jar](https://plantuml.com/download)
+`sudo apt install default-jre`
+`sudo apt install texlive-font-utils`
+
+-------------
+
+But in case just think about that the documentation is for other developers not
+for the end user. So keep the focus.
+++ /dev/null
-A brief overview for those that wish to work with the source.
-
-The Makefiles and configure script are generated by the autogen.sh script,
-usually only distributed with snapshot releases. Running autogen.sh requires
-automake and autoconf. GNU gettext may also be needed by autogen.sh.
-
-Git commits _require_ an explicit log message. Think it will be used in the
-release Changelog.
-
-Coders should respect general coding style (see CODING).
-
-Coders, please resync po/POTFILES.in if you add or remove source files from src/
-directory (using regen_potfiles.sh script in po/) and re-run make update-po when
-appropriate to keep translations in sync with the code.
-
-Maintainers, don't forget to run make update-po before releases.
-
-The scripts folder contains a script for generating the timezone database.
-The database will need updating occasionally.
-
-Translators, please have a look at po/README.
# <a name="downloading"></a>
## Downloading
-Geeqie is available as a package with some distributions, however Geeqie is stable and you may compile the latest version from sources.
+Geeqie is available:
+
+* as a package with some distributions.
+
+* as a [flatpak](https://flathub.org/apps/details/org.geeqie.Geeqie) from the [Flathub site](https://flathub.org/home).
+
+* as an [AppImage](https://cclark.uk/Geeqie).
+
+However Geeqie is stable and you may compile the latest version from sources.
There are two scripts which will download and compile the sources for you.
Or: `git clone http://www.geeqie.org/git/geeqie.git`
-Also [Geeqie is available as a flatpak](https://flathub.org/apps/details/org.geeqie.Geeqie) from the [Flathub site](https://flathub.org/home).
-
## Manual Installation
List compile options: `./autogen.sh --help`
--- /dev/null
+# How to create AppImages for Geeqie
+
+## Download the required tools:
+
+Download the `linuxdeploy` tool. At the time of writing, this is:
+
+`wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage`
+
+
+Move this file to `$HOME/bin` or somewhere else in your `$PATH` and make executable.
+
+
+## Generate the executable
+
+`cd <your working area>`
+
+Download Geeqie sources:
+`git clone git://www.geeqie.org/geeqie.git`
+`cd geeqie`
+
+If a run has already been made, remove any existing targets:
+`rm -r <target dir>/AppDir`
+`sudo rm -rf doc/html`
+
+Create a fresh target directory:
+`mkdir <target dir>/AppDir`
+
+Generate the Geeqie executable:
+`sudo make maintainer-clean`
+`./autogen.sh --prefix="/usr/"`
+`make -j`
+`make install DESTDIR=<full path to target dir>/AppDir`
+
+## Generate the AppImage
+
+`cd <target dir>`
+`linuxdeploy-x86_64.AppImage \`
+`--appdir ./AppDir --output appimage \`
+`--desktop-file ./AppDir/usr/share/applications/geeqie.desktop \`
+`--icon-file ./AppDir/usr/share/pixmaps/geeqie.png \`
+`--executable ./AppDir/usr/bin/geeqie`
+
+## Rename AppImage
+If required, rename the AppImage executable - e.g.:
+`mv ./Geeqie-v1.6-x86_64.AppImage $(./Geeqie-v1.6-x86_64.AppImage -v | sed 's/git//' | sed 's/-.* /-/' | sed 's/ /-v/' | sed 's/-GTK3//').AppImage`
+
+The script `./scripts/generate-appimage.sh` automates this process.
EXTRA_DIST = docbook2html.sh docbook icons
html/GuideIndex.html: docbook/GuideIndex.xml
- rm -rf html; mkdir html; cp $(srcdir)/icons/* html/
+ rm -rf html; mkdir html; cp $(srcdir)/icons/* html/; ./create-doxygen-lua-api.sh
if [ -x "$(GNOME_DOC_TOOL)" ]; then \
"$(GNOME_DOC_TOOL)" html -i -o html/ $(srcdir)/docbook/GuideIndex.xml ; \
else \
$(MKDIR_P) "$(DESTDIR)$(helpdir)" || exit 1; \
cd $(srcdir)/html; for f in * ; do $(INSTALL_DATA) "$$f" "$(DESTDIR)$(helpdir)/$$f" ; done; \
ln -s -f GuideIndex.html "$(DESTDIR)$(helpdir)/index.html" ; \
+ $(MKDIR_P) "$(DESTDIR)$(helpdir)/lua-api" || exit 1; \
+ cd ./lua-api/html; for f in * ; do $(INSTALL_DATA) "$$f" "$(DESTDIR)$(helpdir)/lua-api/$$f" ; done; \
fi
uninstall-hook:
- rm "$(DESTDIR)$(helpdir)/"*
+ rm -r "$(DESTDIR)$(helpdir)/"*
clean-local:
rm -rf html
--- /dev/null
+#!/bin/bash
+
+#**********************************************************************
+# Copyright (C) 2021 - 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.
+#**********************************************************************
+#
+# This script will create the Lua API html document, which is part of
+# the Geeqie Help file.
+#
+# It is run during the generation of the help files.
+#
+# The generated Lua html files are placed in doc/html/lua-api
+#
+# The doxygen.conf file is modified to extract only those comments
+# that are useful as part of an API description.
+#
+#**********************************************************************
+
+export PROJECT="Geeqie"
+export VERSION=$(git tag --list v[1-9]* | tail -1)
+export SRCDIR="$PWD/.."
+export DOCDIR="$PWD/html/lua-api"
+
+TMPFILE=$(mktemp) || exit 1
+
+# Modify the Geeqie doxygen.conf file to produce
+# only the data needed for the lua API document
+awk '
+BEGIN {
+ FILE_PATTERNS_found = "FALSE"
+}
+{
+ if (FILE_PATTERNS_found == "TRUE")
+ {
+ if ($0 ~ /\\/)
+ {
+ next
+ }
+ else
+ {
+ FILE_PATTERNS_found = "FALSE"
+ }
+ }
+ if ($1 == SHOW_INCLUDE_FILES)
+ {
+ {print "SHOW_INCLUDE_FILES = NO"}
+ }
+ else if ($1 == "FILE_PATTERNS")
+ {
+ print "FILE_PATTERNS = lua.c"
+ FILE_PATTERNS_found = "TRUE"
+ next
+ }
+ else if ($1 == "EXCLUDE_SYMBOLS")
+ {
+ print "EXCLUDE_SYMBOLS = L \\"
+ print "lua_callvalue \\"
+ print "lua_check_exif \\"
+ print "lua_check_image \\"
+ print "lua_init \\"
+ print "_XOPEN_SOURCE \\"
+ print "LUA_register_global \\"
+ print "LUA_register_meta"
+ }
+ else if ($1 == "SOURCE_BROWSER")
+ {
+ print "SOURCE_BROWSER = NO"
+ }
+ else if ($1 == "HAVE_DOT")
+ {
+ {print "HAVE_DOT = NO"}
+ }
+ else
+ {
+ {print}
+ }
+}
+' ../doxygen.conf > $TMPFILE
+
+doxygen $TMPFILE
+
+rm $TMPFILE
+
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideOptionsMain.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideOptionsAdditional.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReference.xml" />\r
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideOtherSoftware.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideFaq.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideLicence.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideCredits.xml" />\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<section id="GuideOptionsAdvanced">\r
+ <title>External preview extraction</title>\r
+ <para>\r
+ The intention of this feature is to give the user the possibility to display image previews of files\r
+ that the standard libraries cannot decode.\r
+ <para />\r
+ An example is the .dng files produced by LG V30 cameras. Neither\r
+ <code>exiv2</code>\r
+ nor\r
+ <code>libraw</code>\r
+ can\r
+ extract a preview, but the command line program\r
+ <code>dcraw</code>\r
+ can.\r
+ <para />\r
+ This feature allows a work-around until the standard libraries provide a solution.\r
+ <para />\r
+ Two command files are required: one to identify which files to process, and one to extract or decode the preview image.\r
+ <para />\r
+ The format for the identification tool is:\r
+ <para />\r
+ <pre>\r
+ <programlisting xml:space="preserve">\r
+ Parameter 1: (input) full path name to the current image.\r
+ <para />\r
+ Returns: 0 for file match, any other value for no match.\r
+ </programlisting>\r
+ </pre>\r
+ <para />\r
+ The format for the extraction tool is:\r
+ <para />\r
+ <pre>\r
+ <programlisting xml:space="preserve">\r
+ Parameter 1: (input) full path name to the current image.\r
+ <para />\r
+ Parameter 2: (output) a temporary file name generated by Geeqie. The tool should load this file with the decoded image.\r
+ <para />\r
+ Returns: not used.\r
+ </programlisting>\r
+ </pre>\r
+ <para />\r
+ This is an example of an identification tool using a shell script:\r
+ <para />\r
+ <pre>\r
+ <programlisting xml:space="preserve">#! /bin/bash\r
+\r
+ filename=$(basename -- "$1")\r
+ extension="${filename##*.}"\r
+\r
+ shopt -s nocasematch\r
+ if [[ $extension == "DNG" ]]\r
+ then\r
+ cameramodel=$(exiv2 -K Exif.Image.UniqueCameraModel -Pt "$1" )\r
+ if [[ $cameramodel == "LG-H930" ]]\r
+ then\r
+ exit 0\r
+ else\r
+ exit 1\r
+ fi\r
+ else\r
+ exit 1\r
+ fi</programlisting>\r
+ </pre>\r
+ </para>\r
+ <para>\r
+ This is an example of an extraction/decode tool using a shell script:\r
+ <pre>\r
+ <programlisting xml:space="preserve">#! /bin/bash\r
+ dcraw -e -c "$1" > "$2"</programlisting>\r
+ </pre>\r
+ <para />\r
+ Alternatively:\r
+ <pre>\r
+ <programlisting xml:space="preserve">#! /bin/bash\r
+ gm convert "$1" "$2"</programlisting>\r
+ </pre>\r
+ </para>\r
+ <para>\r
+ If the decode tool requires an output file with a particular extension, use this method:\r
+ <pre>\r
+ <programlisting xml:space="preserve">#! /bin/bash\r
+ tmpfile=$(mktemp --tmpdir=$tempdir geeqie_tmp_XXXXXX.jpg)\r
+ gm convert "$1" $tmpfile\r
+ mv $tmpfile "$2"</programlisting>\r
+ </pre>\r
+ </para>\r
+</section>\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideOptionsStereo.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideOptionsBehavior.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideOptionsToolbar.xml" />\r
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideOptionsAdvanced.xml" />\r
<para />\r
\r
</chapter>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<chapter id="GuideOtherSoftware">\r
+ <title id="titleGuideOtherSoftware">Other Software</title>\r
+ <para>This is a list of other software that users might find useful in conjunction with Geeqie.</para>\r
+ <section id="Entangle">\r
+ <title>Entangle</title>\r
+ <para>\r
+ Tethered photography:\r
+ <ulink url="https://entangle-photo.org/">https://entangle-photo.org/</ulink>\r
+ </para>\r
+ </section>\r
+ <section id="Photini">\r
+ <title>Photini</title>\r
+ <para>\r
+ Digital photograph metadata editor:\r
+ <ulink url="https://photini.readthedocs.io/en/latest/">https://photini.readthedocs.io/en/latest/</ulink>\r
+ </para>\r
+ </section>\r
+</chapter>\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceThumbnails.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceMetadata.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceLua.xml" />\r
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceLuaAPI.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceConfig.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceFileDates.xml" />\r
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceLIRC.xml" />\r
<entry>\r
<code>\r
Ctrl +\r
- <keycap>Keypad +</keycap>\r
+ <keycap>=</keycap>\r
</code>\r
</entry>\r
<entry />\r
<entry>\r
<code>\r
Ctrl +\r
- <keycap>Keypad -</keycap>\r
+ <keycap>-</keycap>\r
</code>\r
</entry>\r
<entry />\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<section id="GuideReferenceLuaAPI">\r
+ <title>Lua API</title>\r
+ <para>\r
+ <ulink url="./lua-api/lua_8c.html">The Lua API document</ulink>\r
+ </para>\r
+</section>\r
</para>\r
<para>\r
XMP:\r
- <ulink url="http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf" />\r
+ <ulink url="https://wwwimages2.adobe.com/content/dam/acom/en/devnet/xmp/pdfs/XMP%20SDK%20Release%20cc-2016-08/XMPSpecificationPart3.pdf" />\r
</para>\r
<para>\r
IPTC4XMP:\r
</para>\r
<para>\r
Pango mark up:\r
- <ulink url="https://developer.gnome.org/pango/stable/PangoMarkupFormat.html" />\r
+ <ulink url="https://developer.gnome.org/pygtk/stable/pango-markup-language.html" />\r
</para>\r
<para>\r
Thumbnails:\r
# classes and enums directly into the documentation.
# The default value is: NO.
-INLINE_SOURCES = NO
+INLINE_SOURCES = $(INLINE_SOURCES)
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
-STRIP_CODE_COMMENTS = YES
+STRIP_CODE_COMMENTS = $(STRIP_CODE_COMMENTS)
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
# function all documented functions referencing it will be listed.
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
-PLANTUML_JAR_PATH =
+PLANTUML_JAR_PATH = $(PLANTUML_JAR_PATH)
# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
# configuration file for plantuml.
</screenshot>
</screenshots>
<releases>
- <release version="v1.5.1" date="2019-08-20"></release>
+ <release version="v1.6" date="2020-12-02"></release>
</releases>
<keywords>
<keyword>image</keyword>
"Project-Id-Version: geeqie-1.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-01 10:24+0100\n"
-"PO-Revision-Date: 2021-05-16 09:37+0200\n"
+"PO-Revision-Date: 2021-06-26 22:12+0200\n"
"Last-Translator: Jose Riha <jose1711@gmail.com>\n"
"Language-Team: Peter Tuhársky <tuharsky@misbb.sk>\n"
"Language: sk_SK\n"
# src/collect-table.c:1818 src/dupe.c:2170
#: ../src/collect-table.c:2236 ../src/dupe.c:4894 ../src/img-view.c:1521
msgid "Dropped list includes folders."
-msgstr "Odstraňovaný zoznam obsahuje priečinky."
+msgstr "Umiestnený zoznam obsahuje priečinky."
# src/collect-table.c:1820 src/dupe.c:2172
#: ../src/collect-table.c:2238 ../src/dupe.c:4896 ../src/img-view.c:1523
# src/preferences.c:782
#: ../src/preferences.c:2307
-#, fuzzy
msgid "Remember window workspace"
-msgstr "Pamätať si pozície okien"
+msgstr "Pamätať si plochu"
# src/preferences.c:784
#: ../src/preferences.c:2311
# src/collect-dlg.c:206
#: ../src/preferences.c:3355
-#, fuzzy
msgid "Circular selection lists"
-msgstr "Zbierka už existuje"
+msgstr "Výbery v nekonečnej slučke"
#: ../src/preferences.c:3357
msgid "Traverse selection lists in a circular manner"
-msgstr ""
+msgstr "Prechádzať zoznamy s výberom v nekonečnej slučke"
#: ../src/preferences.c:3359
msgid "Save marks on exit"
--- /dev/null
+#! /bin/bash
+#**********************************************************************
+# Copyright (C) 2021 - 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.
+#**********************************************************************
+#
+# This script will generate a Geeqie AppImage.
+#
+# It must be run from the base Geeqie folder.
+# The single parameter is the directory where the AppDir
+# will be created.
+#
+#**********************************************************************
+
+
+if [[ ! -f geeqie.spec.in ]] || [[ ! -d .git ]]
+then
+ echo "This is not a Geeqie folder"
+ exit 1
+fi
+
+target_dir=$(realpath $1)
+
+if [[ $? -ne 0 ]]
+then
+ echo "No target dir specified"
+ exit 1
+fi
+
+rm -rf "$target_dir"/AppDir
+mkdir "$target_dir"/AppDir
+
+sudo rm -rf doc/html
+
+sudo make maintainer-clean
+./autogen.sh --prefix="/usr/"
+make -j
+make install DESTDIR="$target_dir"/AppDir
+
+export VERSION=$(git tag | tail -1)
+
+cd $target_dir
+
+linuxdeploy-x86_64.AppImage \
+--appdir ./AppDir --output appimage \
+--desktop-file ./AppDir/usr/share/applications/geeqie.desktop \
+--icon-file ./AppDir/usr/share/pixmaps/geeqie.png \
+--executable ./AppDir/usr/bin/geeqie
+
+mv ./Geeqie-$VERSION-x86_64.AppImage $(./Geeqie-$VERSION-x86_64.AppImage -v | sed 's/git//' | sed 's/-.* /-/' | sed 's/ /-v/' | sed 's/-GTK3//').AppImage
image_load_tiff.h\
image_load_dds.c\
image_load_dds.h\
+ image_load_external.c\
+ image_load_external.h\
image_load_collection.c\
image_load_collection.h\
image_load_pdf.c\
static void editor_list_window_new_cb(GtkWidget *widget, gpointer data)
{
- editor_window_new(DESKTOP_FILE_TEMPLATE, _("new.desktop"));
+ editor_window_new(desktop_file_template, _("new.desktop"));
}
static void editor_list_window_help_cb(GtkWidget *widget, gpointer data)
static void dupe_dnd_init(DupeWindow *dw);
static void dupe_notify_cb(FileData *fd, NotifyType type, gpointer data);
+static void delete_finished_cb(gboolean success, const gchar *dest_path, gpointer data);
static GtkWidget *submenu_add_export(GtkWidget *menu, GtkWidget **menu_item, GCallback func, gpointer data);
static void dupe_pop_menu_export_cb(GtkWidget *widget, gpointer data);
DupeMatchType mask = dw->match_mask;
param_match_mask = dw->match_mask;
guint out_match_index;
+ gboolean match_found = FALSE;;
if (!dw->list) return;
continue;
}
}
- if (g_array_binary_search(array_set2, di1, dupe_match_binary_search_cb, &out_match_index))
+
+#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION >= 62))
+ match_found = g_array_binary_search(array_set2, di1, dupe_match_binary_search_cb, &out_match_index);
+#else
+ gint i;
+
+ match_found = FALSE;
+ for(i=0; i < array_set2->len; i++)
+ {
+ di2 = g_array_index(array_set2, gpointer, i);
+ check_result = dupe_match_check(di1, di2, dw);
+ if (check_result == DUPE_MATCH)
+ {
+ match_found = TRUE;
+ out_match_index = i;
+ break;
+ }
+ }
+#endif
+
+ if (match_found)
{
di2 = g_array_index(array_set2, gpointer, out_match_index);
DupeWindow *dw = data;
options->file_ops.safe_delete_enable = FALSE;
- file_util_delete(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window);
+ file_util_delete_notify_done(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window, delete_finished_cb, dw);
}
static void dupe_menu_move_to_trash_cb(GtkWidget *widget, gpointer data)
DupeWindow *dw = data;
options->file_ops.safe_delete_enable = TRUE;
- file_util_delete(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window);
+ file_util_delete_notify_done(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window, delete_finished_cb, dw);
}
static void dupe_menu_copy_path_cb(GtkWidget *widget, gpointer data)
case FILEDATA_CHANGE_COPY:
break;
case FILEDATA_CHANGE_DELETE:
- while (dupe_item_remove_by_path(dw, fd->path));
+ /* Update the UI only once, after the operation finishes */
break;
case FILEDATA_CHANGE_UNSPECIFIED:
case FILEDATA_CHANGE_WRITE_METADATA:
}
+/**
+ * @brief Refresh window after a file delete operation
+ * @param success (ud->phase != UTILITY_PHASE_CANCEL) #file_util_dialog_run
+ * @param dest_path Not used
+ * @param data #DupeWindow
+ *
+ * If the window is refreshed after each file of a large set is deleted,
+ * the UI slows to an unacceptable level. The #FileUtilDoneFunc is used
+ * to call this function once, when the entire delete operation is completed.
+ */
+static void delete_finished_cb(gboolean success, const gchar *dest_path, gpointer data)
+{
+ DupeWindow *dw = data;
+ GList *work;
+
+ if (!success)
+ {
+ return;
+ }
+
+ dupe_window_remove_selection(dw, dw->listview);
+}
+
/*
*-------------------------------------------------------------------
* Export duplicates data
else
xdg_data_dirs = g_strdup("/usr/share");
- all_dirs = g_strconcat(get_rc_dir(), ":", GQ_APP_DIR, ":", xdg_data_home_get(), ":", xdg_data_dirs, NULL);
+ all_dirs = g_strconcat(get_rc_dir(), ":", gq_app_dir, ":", xdg_data_home_get(), ":", xdg_data_dirs, NULL);
g_free(xdg_data_dirs);
bind_textdomain_codeset (EXV_PACKAGE, "UTF-8");
#endif
-#if EXIV2_TEST_VERSION(0,27,4)
+#ifdef EXV_ENABLE_BMFF
Exiv2::enableBMFF(TRUE);
#endif
}
#include "image_load_tiff.h"
#include "image_load_dds.h"
#include "image_load_djvu.h"
+#include "image_load_external.h"
#include "image_load_pdf.h"
#include "image_load_psd.h"
#include "image_load_heif.h"
#include "image_load_j2k.h"
#include "image_load_libraw.h"
#include "image_load_svgz.h"
+#include "misc.h"
#include "exif.h"
#include "filedata.h"
#define IMAGE_LOADER_READ_BUFFER_SIZE_DEFAULT 4096
#define IMAGE_LOADER_IDLE_READ_LOOP_COUNT_DEFAULT 1
-
+/**
+ * @page diagrams Diagrams
+ * @section image_load_overview Image Load Overview
+ * @startuml
+ * object image_change
+ * object image_change_complete
+ * object image_load_begin
+ * object image_loader_start
+ * object image_loader_start_thread
+ * object image_loader_start_idle
+ * object image_loader_setup_source
+ * object image_loader_thread_run
+ * object image_loader_begin
+ * object image_loader_setuploader
+ * circle "il->memory_mapped"
+ * object exif_get_preview_
+ * object exif_get_preview
+ * object libraw_get_preview
+ *
+ * image_change : image.c
+ * image_change_complete : image.c
+ * image_load_begin : image.c
+ * image_loader_start : image_load.c
+ * image_loader_start_thread : image_load.c
+ * image_loader_start_idle : image_load.c
+ * image_loader_thread_run : image_load.c
+ * image_loader_begin : image_load.c
+ * image_loader_setuploader : image_load.c
+ * image_loader_setuploader : -
+ * image_loader_setuploader : Select backend using magic
+ * image_loader_setup_source : image_load.c
+ * exif_get_preview : exiv2.cc
+ * exif_get_preview : EXIV2_TEST_VERSION(0,17,90)
+ * exif_get_preview_ : exif.c
+ * exif_get_preview_ : -
+ * exif_get_preview_ : If exiv2 not installed
+ * libraw_get_preview : image_load_libraw.c
+ *
+ * image_change --> image_change_complete
+ * image_change_complete --> image_load_begin
+ * image_load_begin --> image_loader_start
+ * image_loader_start --> image_loader_start_thread
+ * image_loader_start --> image_loader_start_idle : Obsolete - no threads version
+ * image_loader_start_thread --> image_loader_thread_run
+ * image_loader_start_thread --> image_loader_setup_source
+ * image_loader_setup_source --> exif_get_preview_
+ * image_loader_setup_source --> exif_get_preview
+ * image_loader_setup_source --> libraw_get_preview : Try libraw if exiv2 fails
+ * exif_get_preview_ ..> "il->memory_mapped"
+ * exif_get_preview ..> "il->memory_mapped"
+ * libraw_get_preview ..> "il->memory_mapped"
+ * image_loader_thread_run --> image_loader_begin
+ * image_loader_begin --> image_loader_setuploader
+ * "il->memory_mapped" ..> image_loader_setuploader
+ * note left of "il->memory_mapped" : Points to first byte of embedded jpeg (#FFD8)\n if preview found, otherwise to first byte of file
+ * @enduml
+ */
+ /**
+ * @file
+ * @ref image_load_overview "Image Load Overview"
+ */
+
/**************************************************************************************/
/* image loader class */
gchar *format;
#endif
+ gint external_preview = 1;
+
g_mutex_lock(il->data_mutex);
+
+ if (options->external_preview.enable)
+ {
+ gchar *cmd_line;
+ gchar *tilde_filename;
+
+ tilde_filename = expand_tilde(options->external_preview.select);
+
+ cmd_line = g_strdup_printf("\"%s\" \"%s\"" , tilde_filename, il->fd->path);
+
+ external_preview = runcmd(cmd_line);
+ g_free(cmd_line);
+ g_free(tilde_filename);
+ }
+
+ if (external_preview == 0)
+ {
+ DEBUG_1("Using custom external loader");
+ image_loader_backend_set_external(&il->backend);
+ }
+ else
+
#ifdef HAVE_FFMPEGTHUMBNAILER
if (il->fd->format_class == FORMAT_CLASS_VIDEO)
{
if (il->bytes_total >= 12 &&
((memcmp(il->mapped_file + 4, "ftypheic", 8) == 0) ||
(memcmp(il->mapped_file + 4, "ftypmsf1", 8) == 0) ||
- (memcmp(il->mapped_file + 4, "ftypmif1", 8) == 0)))
+ (memcmp(il->mapped_file + 4, "ftypmif1", 8) == 0) ||
+ (memcmp(il->mapped_file + 4, "ftypavif", 8) == 0)))
{
DEBUG_1("Using custom heif loader");
image_loader_backend_set_heif(&il->backend);
if (il->mapped_file)
{
- il->preview = IMAGE_LOADER_PREVIEW_EXIF;
+ /* Both exiv2 and libraw sometimes return a pointer to a file
+ * section that is not a jpeg */
+ if (!(il->mapped_file[0] == 0xFF && il->mapped_file[1] == 0xD8))
+ {
+ il->mapped_file = NULL;
+ }
+ else
+ {
+ il->preview = IMAGE_LOADER_PREVIEW_EXIF;
+ }
}
}
if (il->mapped_file)
{
- il->preview = IMAGE_LOADER_PREVIEW_LIBRAW;
+ if (!(il->mapped_file[0] == 0xFF && il->mapped_file[1] == 0xD8))
+ {
+ il->mapped_file = NULL;
+ }
+ else
+ {
+ il->preview = IMAGE_LOADER_PREVIEW_LIBRAW;
+ }
}
}
--- /dev/null
+/*
+ * Copyright (C) 2021 - 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_external.h"
+
+#include "misc.h"
+#include "ui_fileops.h"
+
+typedef struct _ImageLoaderExternal ImageLoaderExternal;
+struct _ImageLoaderExternal {
+ 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_external_load(gpointer loader, const guchar *buf, gsize count, GError **error)
+{
+ ImageLoaderExternal *ld = (ImageLoaderExternal *) loader;
+ ImageLoader *il = ld->data;
+ gchar *cmd_line;
+ gchar *randname;
+ gchar *tilde_filename;
+
+ tilde_filename = expand_tilde(options->external_preview.extract);
+
+ randname = g_strdup("/tmp/geeqie_external_preview_XXXXXX");
+ g_mkstemp(randname);
+
+ cmd_line = g_strdup_printf("\"%s\" \"%s\" \"%s\"" , tilde_filename, il->fd->path, randname);
+
+ runcmd(cmd_line);
+
+ ld->pixbuf = gdk_pixbuf_new_from_file(randname, NULL);
+
+ ld->area_updated_cb(loader, 0, 0, gdk_pixbuf_get_width(ld->pixbuf), gdk_pixbuf_get_height(ld->pixbuf), ld->data);
+
+ g_free(cmd_line);
+ unlink_file(randname);
+ g_free(randname);
+ g_free(tilde_filename);
+
+ return TRUE;
+}
+
+static gpointer image_loader_external_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data)
+{
+ ImageLoaderExternal *loader = g_new0(ImageLoaderExternal, 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_external_set_size(gpointer loader, int width, int height)
+{
+ ImageLoaderExternal *ld = (ImageLoaderExternal *) loader;
+ ld->requested_width = width;
+ ld->requested_height = height;
+}
+
+static GdkPixbuf* image_loader_external_get_pixbuf(gpointer loader)
+{
+ ImageLoaderExternal *ld = (ImageLoaderExternal *) loader;
+ return ld->pixbuf;
+}
+
+static gchar* image_loader_external_get_format_name(gpointer loader)
+{
+ return g_strdup("external");
+}
+
+static gchar** image_loader_external_get_format_mime_types(gpointer loader)
+{
+ static gchar *mime[] = {"application/octet-stream", NULL};
+ return g_strdupv(mime);
+}
+
+static gboolean image_loader_external_close(gpointer loader, GError **error)
+{
+ return TRUE;
+}
+
+static void image_loader_external_abort(gpointer loader)
+{
+ ImageLoaderExternal *ld = (ImageLoaderExternal *) loader;
+ ld->abort = TRUE;
+}
+
+static void image_loader_external_free(gpointer loader)
+{
+ ImageLoaderExternal *ld = (ImageLoaderExternal *) loader;
+ if (ld->pixbuf) g_object_unref(ld->pixbuf);
+ g_free(ld);
+}
+
+void image_loader_backend_set_external(ImageLoaderBackend *funcs)
+{
+ funcs->loader_new = image_loader_external_new;
+ funcs->set_size = image_loader_external_set_size;
+ funcs->load = image_loader_external_load;
+ funcs->write = NULL;
+ funcs->get_pixbuf = image_loader_external_get_pixbuf;
+ funcs->close = image_loader_external_close;
+ funcs->abort = image_loader_external_abort;
+ funcs->free = image_loader_external_free;
+ funcs->get_format_name = image_loader_external_get_format_name;
+ funcs->get_format_mime_types = image_loader_external_get_format_mime_types;
+}
+
+
+/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- /dev/null
+/*
+ * Copyright (C) 2021 - 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_EXTERNAL_H
+#define IMAGE_LOAD_EXTERNAL_H
+
+void image_loader_backend_set_external(ImageLoaderBackend *funcs);
+
+#endif
+/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
void layout_status_update_info(LayoutWindow *lw, const gchar *text)
{
gchar *buf = NULL;
+ gint hrs;
+ gint min;
+ gdouble sec;
+ GString *delay;
if (!layout_valid(&lw)) return;
{
guint s;
gint64 s_bytes = 0;
- const gchar *ss;
+ gchar *ss;
if (layout_image_slideshow_active(lw))
{
+
if (!layout_image_slideshow_paused(lw))
{
- ss = _(" Slideshow");
+ delay = g_string_new(_(" Slideshow ["));
}
else
{
- ss = _(" Paused");
+ delay = g_string_new(_(" Paused ["));
+ }
+ hrs = options->slideshow.delay / (36000);
+ min = (options->slideshow.delay -(36000 * hrs))/600;
+ sec = (gdouble)(options->slideshow.delay -(36000 * hrs)-(min * 600)) / 10;
+
+ if (hrs > 0)
+ {
+ g_string_append_printf(delay, "%dh ", hrs);
+ }
+ if (min > 0)
+ {
+ g_string_append_printf(delay, "%dm ", min);
}
+ g_string_append_printf(delay, "%.1fs]", sec);
+
+ ss = g_strdup(delay->str);
+
+ g_string_free(delay, TRUE);
}
else
{
- ss = "";
+ ss = g_strdup("");
}
s = layout_selection_count(lw, &s_bytes);
buf = g_strdup_printf(_("%s, %d files (%s, %d)%s"), b, n, sb, s, ss);
g_free(b);
g_free(sb);
+ g_free(ss);
}
else if (n > 0)
{
gchar *b = text_from_size_abrev(n_bytes);
buf = g_strdup_printf(_("%s, %d files%s"), b, n, ss);
g_free(b);
+ g_free(ss);
}
else
{
buf = g_strdup_printf(_("%d files%s"), n, ss);
+ g_free(ss);
}
text = buf;
lw->info_status = layout_status_label(NULL, lw->info_box, TRUE, 0, (!small_format));
DEBUG_NAME(lw->info_status);
- gtk_widget_set_tooltip_text(GTK_WIDGET(lw->info_status), _("Folder contents (files selected)"));
+ gtk_widget_set_tooltip_text(GTK_WIDGET(lw->info_status), _("Folder contents (files selected)\nSlideshow [time interval]"));
if (small_format)
{
WRITE_NL(); WRITE_INT(*layout, log_window.w);
WRITE_NL(); WRITE_INT(*layout, log_window.h);
+ WRITE_NL(); WRITE_INT(*layout, preferences_window.x);
+ WRITE_NL(); WRITE_INT(*layout, preferences_window.y);
+ WRITE_NL(); WRITE_INT(*layout, preferences_window.w);
+ WRITE_NL(); WRITE_INT(*layout, preferences_window.h);
+ WRITE_NL(); WRITE_INT(*layout, preferences_window.page_number);
+
WRITE_NL(); WRITE_INT(*layout, search_window.x);
WRITE_NL(); WRITE_INT(*layout, search_window.y);
WRITE_NL(); WRITE_INT(*layout, search_window.w);
if (READ_INT(*layout, log_window.w)) continue;
if (READ_INT(*layout, log_window.h)) continue;
+ if (READ_INT(*layout, preferences_window.x)) continue;
+ if (READ_INT(*layout, preferences_window.y)) continue;
+ if (READ_INT(*layout, preferences_window.w)) continue;
+ if (READ_INT(*layout, preferences_window.h)) continue;
+ if (READ_INT(*layout, preferences_window.page_number)) continue;
+
if (READ_INT(*layout, search_window.x)) continue;
if (READ_INT(*layout, search_window.y)) continue;
if (READ_INT(*layout, search_window.w)) continue;
}
rotation = g_strdup_printf("%d", fd_n->user_orientation);
- command = g_strconcat(GQ_BIN_DIR, "/geeqie-rotate -r ", rotation,
+ command = g_strconcat(gq_bin_dir, "/geeqie-rotate -r ", rotation,
keep_date ? " -t \"" : " \"", fd_n->path, "\"", NULL);
cmdstatus = runcmd(command);
run_result = WEXITSTATUS(cmdstatus);
LayoutWindow *lw = data;
layout_exit_fullscreen(lw);
- show_config_window();
+ show_config_window(lw);
}
static void layout_menu_editors_cb(GtkAction *action, gpointer data)
{ "HistogramModeCycle",NULL, N_("Cycle through histogram mo_des"), "J", N_("Cycle through histogram modes"), CB(layout_menu_histogram_toggle_mode_cb) },
{ "HideTools", PIXBUF_INLINE_ICON_HIDETOOLS, N_("_Hide file list"), "<control>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"), "<control>KP_Add", N_("Slideshow Faster"), CB(layout_menu_slideshow_faster_cb) },
- { "SlideShowSlower", GTK_STOCK_FILE, N_("Slower"), "<control>KP_Subtract", N_("Slideshow Slower"), CB(layout_menu_slideshow_slower_cb) },
+ { "SlideShowFaster", GTK_STOCK_FILE, N_("Faster"), "<control>equal", N_("Slideshow Faster"), CB(layout_menu_slideshow_faster_cb) },
+ { "SlideShowSlower", GTK_STOCK_FILE, N_("Slower"), "<control>minus", N_("Slideshow Slower"), CB(layout_menu_slideshow_slower_cb) },
{ "Refresh", GTK_STOCK_REFRESH, N_("_Refresh"), "R", N_("Refresh"), CB(layout_menu_refresh_cb) },
{ "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", N_("Contents"), CB(layout_menu_help_cb) },
{ "HelpSearch", NULL, N_("On-line help search"), NULL, N_("On-line help search"), CB(layout_menu_help_search_cb) },
#include "ui_fileops.h"
#include "exif.h"
+/**
+ * @file
+ * User API consists of the following namespaces:
+ *
+ * @link image_methods Image:@endlink basic image information
+ *
+ * <b>Collection</b>: not implemented
+ *
+ * @link exif_methods <exif-structure>:get_datum() @endlink get single exif parameter
+ *
+ */
+
static lua_State *L; /** The LUA object needed for all operations (NOTE: That is
* a upper-case variable to match the documentation!) */
return *fd;
}
+/**
+ * @brief Get exif structure of selected image
+ * @param L
+ * @returns An @ref ExifData data structure containing the entire exif data
+ *
+ * To be used in conjunction with @link lua_exif_get_datum <exif-structure>:get_datum() @endlink
+ */
static int lua_image_get_exif(lua_State *L)
{
FileData *fd;
return 1;
}
+/**
+ * @brief Get full path of selected image
+ * @param L
+ * @returns char The full path of the file, including filename and extension
+ *
+ *
+ */
static int lua_image_get_path(lua_State *L)
{
FileData *fd;
return 1;
}
+/**
+ * @brief Get full filename of selected image
+ * @param L
+ * @returns char The full filename including extension
+ *
+ *
+ */
static int lua_image_get_name(lua_State *L)
{
FileData *fd;
return 1;
}
+/**
+ * @brief Get file extension of selected image
+ * @param L
+ * @returns char The file extension including preceding dot
+ *
+ *
+ */
static int lua_image_get_extension(lua_State *L)
{
FileData *fd;
return 1;
}
+/**
+ * @brief Get file date of selected image
+ * @param L
+ * @returns time_t The file date in Unix timestamp format.
+ *
+ * time_t - signed integer which represents the number of seconds since
+ * the start of the Unix epoch: midnight UTC of January 1, 1970
+ */
static int lua_image_get_date(lua_State *L)
{
FileData *fd;
return 1;
}
+/**
+ * @brief Get file size of selected image
+ * @param L
+ * @returns integer The file size in bytes
+ *
+ *
+ */
static int lua_image_get_size(lua_State *L)
{
FileData *fd;
return 1;
}
+/**
+ * @brief Get marks of selected image
+ * @param L
+ * @returns unsigned integer Bit map of marks set
+ *
+ * Bit 0 == Mark 1 etc.
+ *
+ *
+ */
static int lua_image_get_marks(lua_State *L)
{
FileData *fd;
return *exif;
}
-/* Interface for EXIF data */
+/**
+ * @brief Interface for EXIF data
+ * @param L
+ * @returns <i>return</i> A single exif tag extracted from a structure output by the @link lua_image_get_exif Image:get_exif() @endlink command
+ *
+ * e.g. \n
+ * exif_structure = Image:get_exif(); \n
+ * DateTimeDigitized = exif_structure:get_datum("Exif.Photo.DateTimeDigitized");
+ *
+ * Where <i>return</i> is: \n
+ * Exif.Photo.DateTimeOriginal = signed integer time_t \n
+ * Exif.Photo.DateTimeDigitized = signed integer time_t \n
+ * otherwise char
+ *
+ */
static int lua_exif_get_datum(lua_State *L)
{
const gchar *key;
return 1;
}
+/**
+ * @brief <b>Image:</b> metatable and methods \n
+ * Call by e.g. \n
+ * path_name = @link lua_image_get_path Image:getpath() @endlink \n
+ * where the keyword <b>Image</b> represents the currently selected image
+ */
+static const luaL_Reg image_methods[] = {
+ {"get_path", lua_image_get_path},
+ {"get_name", lua_image_get_name},
+ {"get_extension", lua_image_get_extension},
+ {"get_date", lua_image_get_date},
+ {"get_size", lua_image_get_size},
+ {"get_exif", lua_image_get_exif},
+ {"get_marks", lua_image_get_marks},
+ {NULL, NULL}
+};
+
+/**
+ * @brief <b>exif:</b> table and methods \n
+ * Call by e.g. \n
+ * @link lua_exif_get_datum <exif-structure>:get_datum() @endlink \n
+ * where <exif-structure> is the output of @link lua_image_get_exif Image:get_exif() @endlink
+ *
+ * exif_structure = Image:get_exif(); \n
+ * DateTimeDigitized = exif_structure:get_datum("Exif.Photo.DateTimeDigitized");
+ */
+static const luaL_Reg exif_methods[] = {
+ {"get_datum", lua_exif_get_datum},
+ {NULL, NULL}
+};
+
/**
* @brief Initialize the lua interpreter.
*/
{NULL, NULL}
};
- /* The Image metatable and methodes */
- static const luaL_Reg image_methods[] = {
- {"get_path", lua_image_get_path},
- {"get_name", lua_image_get_name},
- {"get_extension", lua_image_get_extension},
- {"get_date", lua_image_get_date},
- {"get_size", lua_image_get_size},
- {"get_exif", lua_image_get_exif},
- {"get_marks", lua_image_get_marks},
- {NULL, NULL}
- };
LUA_register_global(L, "Image", image_methods);
luaL_newmetatable(L, "Image");
LUA_register_meta(L, meta_methods);
lua_pop(L, 1);
lua_pop(L, 1);
- /* The Exif table and methodes */
- static const luaL_Reg exif_methods[] = {
- {"get_datum", lua_exif_get_datum},
- {NULL, NULL}
- };
LUA_register_global(L, "Exif", exif_methods);
luaL_newmetatable(L, "Exif");
LUA_register_meta(L, meta_methods);
#include "layout.h"
#include "layout_image.h"
#include "layout_util.h"
+#include "misc.h"
#include "options.h"
#include "remote.h"
#include "secure_save.h"
gboolean thumb_format_changed = FALSE;
static RemoteConnection *remote_connection = NULL;
+gchar *gq_prefix;
+gchar *gq_localedir;
+gchar *gq_helpdir;
+gchar *gq_htmldir;
+gchar *gq_app_dir;
+gchar *gq_bin_dir;
+gchar *desktop_file_template;
+
/*
*-----------------------------------------------------------------------------
* keyboard functions
static void setup_env_path(void)
{
const gchar *old_path = g_getenv("PATH");
- gchar *path = g_strconcat(GQ_BIN_DIR, ":", old_path, NULL);
+ gchar *path = g_strconcat(gq_bin_dir, ":", old_path, NULL);
g_setenv("PATH", path, TRUE);
g_free(path);
}
#endif
}
+/**
+ * @brief Set up the application paths
+ *
+ * This function is required for use of AppImages. AppImages are
+ * relocatable, and therefore cannot use fixed paths to various components.
+ * These paths were originally #defines created during compilation.
+ * They are now variables, all defined relative to one level above the
+ * directory that the executable is run from.
+ */
+static void create_application_paths()
+{
+ gchar buf[1024];
+ gchar *dirname;
+ gchar *basename;
+ gchar *tmp;
+
+ memset(buf, 0, sizeof(buf));
+ if (readlink("/proc/self/exe", buf, sizeof(buf) - 1) < 0)
+ {
+ /* There was an error. Perhaps the path does not exist
+ * or the buffer is not big enough. */
+ log_printf("Can't get path from /proc/self/exe");
+ exit(1);
+ }
+
+ dirname = g_path_get_dirname(buf); // default is /usr/bin/
+ gq_prefix = g_path_get_dirname(dirname);
+
+ gq_localedir = g_build_filename(gq_prefix, "share", "locale", NULL);
+ tmp = g_build_filename(gq_prefix, "share", "doc", NULL);
+ gq_helpdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, "geeqie-", VERSION, NULL);
+ gq_htmldir = g_build_filename(gq_helpdir, "html", NULL);
+ gq_app_dir = g_build_filename(gq_prefix, "share", "geeqie", NULL);
+ gq_bin_dir = g_build_filename(gq_prefix, "lib", "geeqie", NULL);
+ desktop_file_template = g_build_filename(gq_app_dir, "template.desktop", NULL);
+
+ g_free(tmp);
+ g_free(dirname);
+}
+
gint main(gint argc, gchar *argv[])
{
CollectionData *first_collection = NULL;
/* init execution time counter (debug only) */
init_exec_time();
+ create_application_paths();
+
/* setup locale, i18n */
setlocale(LC_ALL, "");
#ifdef ENABLE_NLS
- bindtextdomain(PACKAGE, GQ_LOCALEDIR);
+ bindtextdomain(PACKAGE, gq_localedir);
bind_textdomain_codeset(PACKAGE, "UTF-8");
textdomain(PACKAGE);
#endif
if (gtk_clutter_init(&argc, &argv) != CLUTTER_INIT_SUCCESS)
{
log_printf("Can't initialize clutter-gtk.\nStart Geeqie with the option \"geeqie --disable-clutter\"");
+ runcmd("zenity --error --title=\"Geeqie\" --text \"Can't initialize clutter-gtk.\n\nStart Geeqie with the option:\n geeqie --disable-clutter\" --width=300");
exit(1);
}
}
#include "debug.h"
#include "options.h"
-#define DESKTOP_FILE_TEMPLATE GQ_APP_DIR "/template.desktop"
-
#define TIMEZONE_DATABASE GQ_WEBSITE"downloads/timezone21.bin"
#define HELP_SEARCH_ENGINE "https://duckduckgo.com/?q=site:geeqie.org/help "
extern gboolean thumb_format_changed;
+extern gchar *gq_prefix;
+extern gchar *gq_localedir;
+extern gchar *gq_helpdir;
+extern gchar *gq_htmldir;
+extern gchar *gq_app_dir;
+extern gchar *gq_bin_dir;
+extern gchar *desktop_file_template;
+
void keyboard_scroll_calc(gint *x, gint *y, GdkEventKey *event);
gint key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer data);
gchar *message;
gchar *dir;
- message = decode_geo_script(GQ_BIN_DIR, input_text);
+ message = decode_geo_script(gq_bin_dir, input_text);
if (strstr(message, "Error"))
{
g_free(message);
options->bars_state.hidden = FALSE;
options->log_window.w = 520;
options->log_window.h = 400;
+ options->preferences_window.w = 700;
+ options->preferences_window.h = 600;
options->split_pane_sync = FALSE;
options->workspace = -1;
return options;
} tmp;
} stereo;
+ /* External preview extraction */
+ struct {
+ gboolean enable;
+ gchar *select; /**< path to executable */
+ gchar *extract; /**< path to executable */
+ } external_preview;
+
/**
* @struct cp_mv_rn
* copy move rename
static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
static GtkWidget *color_profile_screen_file_entry;
+static GtkWidget *external_preview_select_entry;
+static GtkWidget *external_preview_extract_entry;
static GtkWidget *sidecar_ext_entry;
static GtkWidget *help_search_engine_entry;
options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
+ options->external_preview.enable = c_options->external_preview.enable;
+ config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
+ config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
+
options->read_metadata_in_idle = c_options->read_metadata_in_idle;
options->star_rating.star = c_options->star_rating.star;
"GuideOptionsStereo.html",
"GuideOptionsBehavior.html",
"GuideOptionsToolbar.html",
- "GuideOptionsToolbar.html"
+ "GuideOptionsToolbar.html",
+ "GuideOptionsAdvanced.html"
};
i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
static void config_window_ok_cb(GtkWidget *widget, gpointer data)
{
LayoutWindow *lw;
+ GtkNotebook *notebook = data;
+ GdkWindow *window;
+ gint x;
+ gint y;
+ gint w;
+ gint h;
+ gint page_number;
+
lw = layout_window_list->data;
+ window = gtk_widget_get_window(widget);
+ gdk_window_get_root_origin(window, &x, &y);
+ w = gdk_window_get_width(window);
+ h = gdk_window_get_height(window);
+ page_number = gtk_notebook_get_current_page(notebook);
+
+ lw->options.preferences_window.x = x;
+ lw->options.preferences_window.y = y;
+ lw->options.preferences_window.w = w;
+ lw->options.preferences_window.h = h;
+ lw->options.preferences_window.page_number = page_number;
+
config_window_apply();
layout_util_sync(lw);
save_options(options);
gtk_widget_show(vbox);
}
+/* advanced tab */
+static gint extension_sort_cb(gconstpointer a, gconstpointer b)
+{
+ return g_strcmp0((gchar *)a, (gchar *)b);
+}
+
+static void config_tab_advanced(GtkWidget *notebook)
+{
+ GtkWidget *vbox;
+ GtkWidget *group;
+ GSList *formats_list;
+ GList *extensions_list = NULL;
+ gchar **extensions;
+ GtkWidget *tabcomp;
+ GdkPixbufFormat *fm;
+ gint i;
+ GString *types_string = g_string_new(NULL);
+
+ vbox = scrolled_notebook_page(notebook, _("Advanced"));
+ group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
+
+ pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
+
+ pref_spacer(group, PREF_PAD_GROUP);
+
+ formats_list = gdk_pixbuf_get_formats();
+
+ while (formats_list)
+ {
+ fm = formats_list->data;
+ extensions = gdk_pixbuf_format_get_extensions(fm);
+
+ i = 0;
+ while (extensions[i])
+ {
+ extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
+ i++;
+ }
+
+ g_strfreev(extensions);
+ formats_list = formats_list->next;
+ }
+
+ while (extensions_list)
+ {
+ if (types_string->len == 0)
+ {
+ types_string = g_string_append(types_string, extensions_list->data);
+ }
+ else
+ {
+ types_string = g_string_append(types_string, ", ");
+ types_string = g_string_append(types_string, extensions_list->data);
+ }
+
+ extensions_list = extensions_list->next;
+ }
+
+ types_string = g_string_prepend(types_string, _("Usable file types:\n"));
+ pref_label_new(group, types_string->str);
+ GtkWidget *types_string_label = gtk_label_new(types_string->str);
+ gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
+
+ pref_spacer(group, PREF_PAD_GROUP);
+
+ group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
+ external_preview_select_entry = gtk_entry_new();
+ tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
+ tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
+ gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
+ gtk_widget_show(tabcomp);
+
+ group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
+ external_preview_extract_entry = gtk_entry_new();
+ tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
+ tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
+ gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
+ gtk_widget_show(tabcomp);
+
+ gtk_widget_show(vbox);
+
+ g_slist_free(formats_list);
+ string_list_free(extensions_list);
+ g_string_free(types_string, TRUE);
+}
+
/* stereo tab */
static void config_tab_stereo(GtkWidget *notebook)
{
}
/* Main preferences window */
-static void config_window_create(void)
+static void config_window_create(LayoutWindow *lw)
{
GtkWidget *win_vbox;
GtkWidget *hbox;
gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
g_signal_connect(G_OBJECT(configwindow), "delete_event",
G_CALLBACK(config_window_delete), NULL);
- gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
+ if (options->save_dialog_window_positions)
+ {
+ gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
+ gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
+ }
+ else
+ {
+ gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
+ }
gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
config_tab_behavior(notebook);
config_tab_toolbar_main(notebook);
config_tab_toolbar_status(notebook);
+ config_tab_advanced(notebook);
+
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
hbox = gtk_hbutton_box_new();
gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
gtk_widget_show(button);
button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
- G_CALLBACK(config_window_ok_cb), NULL);
+ G_CALLBACK(config_window_ok_cb), notebook);
gtk_container_add(GTK_CONTAINER(hbox), button);
gtk_widget_set_can_default(button, TRUE);
gtk_widget_grab_default(button);
*-----------------------------------------------------------------------------
*/
-void show_config_window(void)
+void show_config_window(LayoutWindow *lw)
{
if (configwindow)
{
return;
}
- config_window_create();
+ config_window_create(lw);
}
/*
g_free(basename);
authors[0] = NULL;
- path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
+ path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
fp = fopen(path, "r");
if (fp)
{
#define PREFERENCES_H
-void show_config_window(void);
+void show_config_window(LayoutWindow *lw);
void show_about_window(LayoutWindow *lw);
/**
WRITE_NL(); WRITE_BOOL(*options, marks_save);
WRITE_NL(); WRITE_CHAR(*options, help_search_engine);
+ WRITE_NL(); WRITE_BOOL(*options, external_preview.enable);
+ WRITE_NL(); WRITE_CHAR(*options, external_preview.select);
+ WRITE_NL(); WRITE_CHAR(*options, external_preview.extract);
+
WRITE_NL(); WRITE_BOOL(*options, with_rename);
WRITE_NL(); WRITE_BOOL(*options, collections_on_top);
WRITE_NL(); WRITE_BOOL(*options, hide_window_in_fullscreen);
if (READ_BOOL(*options, marks_save)) continue;
if (READ_CHAR(*options, help_search_engine)) continue;
+ if (READ_BOOL(*options, external_preview.enable)) continue;
+ if (READ_CHAR(*options, external_preview.select)) continue;
+ if (READ_CHAR(*options, external_preview.extract)) continue;
+
if (READ_BOOL(*options, collections_on_top)) continue;
if (READ_BOOL(*options, hide_window_in_fullscreen)) continue;
gint y;
} log_window;
+ struct {
+ gint w;
+ gint h;
+ gint x;
+ gint y;
+ gint page_number;
+ } preferences_window;
+
struct {
gint w;
gint h;
}
}
-
-static void file_util_delete_full(FileData *source_fd, GList *flist, GtkWidget *parent, UtilityPhase phase)
+static void file_util_delete_full(FileData *source_fd, GList *flist, GtkWidget *parent, UtilityPhase phase, FileUtilDoneFunc done_func, gpointer done_data)
{
UtilityData *ud;
GList *ungrouped = NULL;
ud->flist = flist;
ud->content_list = NULL;
ud->parent = parent;
+ ud->done_data = done_data;
+ ud->done_func = done_func;
ud->details_func = file_util_details_dialog;
if(options->file_ops.safe_delete_enable)
void file_util_delete(FileData *source_fd, GList *source_list, GtkWidget *parent)
{
- file_util_delete_full(source_fd, source_list, parent, options->file_ops.confirm_delete ? UTILITY_PHASE_START : UTILITY_PHASE_ENTERING);
+ file_util_delete_full(source_fd, source_list, parent, options->file_ops.confirm_delete ? UTILITY_PHASE_START : UTILITY_PHASE_ENTERING, NULL, NULL);
+}
+
+void file_util_delete_notify_done(FileData *source_fd, GList *source_list, GtkWidget *parent, FileUtilDoneFunc done_func, gpointer done_data)
+{
+ file_util_delete_full(source_fd, source_list, parent, options->file_ops.confirm_delete ? UTILITY_PHASE_START : UTILITY_PHASE_ENTERING, done_func, done_data);
}
void file_util_write_metadata(FileData *source_fd, GList *source_list, GtkWidget *parent, gboolean force_dialog, FileUtilDoneFunc done_func, gpointer done_data)
/* all functions takes over the filelist and frees it when done */
void file_util_delete(FileData *source_fd, GList *source_list, GtkWidget *parent);
+void file_util_delete_notify_done(FileData *source_fd, GList *source_list, GtkWidget *parent, FileUtilDoneFunc done_func, gpointer done_data);
void file_util_move(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent);
void file_util_copy(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent);
void file_util_rename(FileData *source_fd, GList *source_list, GtkWidget *parent);
if (key && strstr(key, ".html") != 0)
{
- path = g_build_filename(GQ_HTMLDIR, key, NULL);
+ path = g_build_filename(gq_htmldir, key, NULL);
if (!isfile(path))
{
if (g_strcmp0(key, "index.html") == 0)
if (!strcmp(key, "release_notes"))
{
- path = g_build_filename(GQ_HELPDIR, "README.html", NULL);
+ path = g_build_filename(gq_helpdir, "README.html", NULL);
if (isfile(path))
{
g_free(path);
- path = g_build_filename("file://", GQ_HELPDIR, "README.html", NULL);
+ path = g_build_filename("file://", gq_helpdir, "README.html", NULL);
help_browser_run(path);
g_free(path);
}
else
{
g_free(path);
- path = g_build_filename(GQ_HELPDIR, "README.md", NULL);
+ path = g_build_filename(gq_helpdir, "README.md", NULL);
help_window = help_window_new(_("Help"), "help", path, key);
g_free(path);
}
else
{
- path = g_build_filename(GQ_HELPDIR, "ChangeLog.html", NULL);
+ path = g_build_filename(gq_helpdir, "ChangeLog.html", NULL);
if (isfile(path))
{
g_free(path);
- path = g_build_filename("file://", GQ_HELPDIR, "ChangeLog.html", NULL);
+ path = g_build_filename("file://", gq_helpdir, "ChangeLog.html", NULL);
help_browser_run(path);
g_free(path);
}
else
{
g_free(path);
- path = g_build_filename(GQ_HELPDIR, "ChangeLog", NULL);
+ path = g_build_filename(gq_helpdir, "ChangeLog", NULL);
help_window = help_window_new(_("Help"), "help", path, key);
g_free(path);
<option value="https://apps.fedoraproject.org/packages/geeqie">
Fedora
</option>
- <option value="https://packages.ubuntu.com/eoan/geeqie">
+ <option value="https://packages.ubuntu.com/geeqie">
Ubuntu
</option>
<option value="https://community.linuxmint.com/software/view/gqview">
</script>
<p>MacOS X <a href="https://formulae.brew.sh/formula/geeqie">Homebrew Formulae</a></p>
<p>Solaris <a href="https://www.opencsw.org/package/geeqie/">Openscw.org Solaris 10 & 11</a></p>
+ <p>Geeqie is also available:</p>
+ <ul><li>as a <a href="https://flathub.org/apps/details/org.geeqie.Geeqie">Flatpak</a> from the <a href="https://flathub.org/home">Flathub site</a></li>
+ <li>as an <a href="https://cclark.uk/Geeqie">AppImage</a></li></ul>
<p>The source tar for Geeqie v1.5 is available <a href="/geeqie-1.5.tar.xz">here.</a> (Signature also available under <a href="/geeqie-1.5.tar.xz.asc">geeqie-1.5.tar.xz.asc</a>)</p>
<p>However if you are compiling from sources it is recommended that you get the latest sources from the
<a href="/cgi-bin/gitweb.cgi?p=geeqie.git">Geeqie repository.</a></p>Geeqie is stable, there
are frequent updates, and compiling is a quick and painless task. The instructions for <a href=
"installing.html">downloading and installing</a> are easy to follow.
<p>For Ubuntu and other Debian-based systems, <a href="http://www.geeqie.org/web/geeqie-install-debian.sh"> this script</a> will download Geeqie sources, all dependencies, and compile and install Geeqie. You may also select which optional libraries to install.</p>
- <p>Also <a href="https://flathub.org/apps/details/org.geeqie.Geeqie">Geeqie is available as a flatpak</a> from the <a href="https://flathub.org/home">Flathub site</a>.</p>
<h4>Support</h4>
<p>If you need help or have questions about Geeqie, just <a href="mailto:geeqie@freelists.org">send a message</a> to the <a href="https://www.freelists.org/list/geeqie">mailing list</a>.
<form action="https://www.freelists.org/cgi-bin/subscription.cgi" method="post">