505 lines
11 KiB
C
505 lines
11 KiB
C
/* Entice - small and simple image viewer using the EFL
|
|
* Copyright (C) 2021 Vincent Torri
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <Elementary.h>
|
|
#include <Ecore_Getopt.h>
|
|
|
|
#include "entice_private.h"
|
|
#include "entice_config.h"
|
|
#include "entice_image.h"
|
|
#include "entice_win.h"
|
|
|
|
#define ENTICE_COPYRIGHT "(C) 2021 Vincent Torri and others"
|
|
|
|
/* list image extensions to use for good first-guess tries */
|
|
static const char *_image_ext[] =
|
|
{
|
|
".png",
|
|
|
|
".jpg",
|
|
".jpeg",
|
|
".jfif",
|
|
|
|
".j2k",
|
|
".jp2",
|
|
".jpx",
|
|
".jpf",
|
|
|
|
".xpm",
|
|
|
|
".tiff",
|
|
".tif",
|
|
|
|
".gif",
|
|
|
|
".pbm",
|
|
".pgm",
|
|
".ppm",
|
|
".pnm",
|
|
|
|
".bmp",
|
|
|
|
".tga",
|
|
|
|
".wbmp",
|
|
|
|
".webp",
|
|
|
|
".ico",
|
|
".cur",
|
|
|
|
".psd",
|
|
|
|
".avif",
|
|
".avifs",
|
|
".avis",
|
|
|
|
".heif",
|
|
".heic",
|
|
|
|
".jxl",
|
|
|
|
".xcf",
|
|
".xcf.gz",
|
|
|
|
".svg",
|
|
".svg.gz",
|
|
|
|
".3fr",
|
|
".ari",
|
|
".arw",
|
|
".bay",
|
|
".braw",
|
|
".crw",
|
|
".cr2",
|
|
".cr3",
|
|
".cap",
|
|
".data",
|
|
".dcr",
|
|
".dcs",
|
|
".dng",
|
|
".drf",
|
|
".eip",
|
|
".erf",
|
|
".fff",
|
|
".gpr",
|
|
".iiq",
|
|
".k25",
|
|
".kdc",
|
|
".mdc",
|
|
".mef",
|
|
".mos",
|
|
".mrw",
|
|
".nef",
|
|
".nrw",
|
|
".obm",
|
|
".orf",
|
|
".pef",
|
|
".ptx",
|
|
".pxn",
|
|
".r3d",
|
|
".raf",
|
|
".raw",
|
|
".rw1",
|
|
".rw2",
|
|
".rwz",
|
|
".sr2",
|
|
".srf",
|
|
".srw",
|
|
".tif",
|
|
".x3f",
|
|
|
|
".dds",
|
|
|
|
".tgv",
|
|
|
|
".pdf",
|
|
|
|
NULL
|
|
};
|
|
|
|
static Ecore_Getopt options = {
|
|
PACKAGE_NAME,
|
|
"%prog [options] [filename]",
|
|
PACKAGE_VERSION,
|
|
gettext_noop(ENTICE_COPYRIGHT),
|
|
"BSD 2-Clause License",
|
|
gettext_noop("Simple image viewer written with Enlightenment Foundation Libraries."),
|
|
EINA_TRUE,
|
|
{
|
|
ECORE_GETOPT_STORE_TRUE('f', "fullscreen",
|
|
gettext_noop("Go into the fullscreen mode from start.")),
|
|
|
|
ECORE_GETOPT_VERSION ('V', "version"),
|
|
ECORE_GETOPT_COPYRIGHT ('C', "copyright"),
|
|
ECORE_GETOPT_LICENSE ('L', "license"),
|
|
ECORE_GETOPT_HELP ('h', "help"),
|
|
ECORE_GETOPT_SENTINEL
|
|
}
|
|
};
|
|
|
|
int entice_app_log_dom_global = 1;
|
|
|
|
#if ENABLE_NLS
|
|
static void
|
|
_entice_translate_options(void)
|
|
{
|
|
Ecore_Getopt_Desc *desc;
|
|
|
|
options.copyright = eina_stringshare_printf(_(options.copyright),
|
|
2020);
|
|
|
|
desc = (Ecore_Getopt_Desc *)options.descs;
|
|
while ((desc->shortname != '\0') ||
|
|
(desc->longname) ||
|
|
(desc->action == ECORE_GETOPT_ACTION_CATEGORY))
|
|
{
|
|
if (desc->help)
|
|
{
|
|
switch (desc->action)
|
|
{
|
|
case ECORE_GETOPT_ACTION_VERSION:
|
|
desc->help = _("show program version.");
|
|
break;
|
|
case ECORE_GETOPT_ACTION_COPYRIGHT:
|
|
desc->help = _("show copyright.");
|
|
break;
|
|
case ECORE_GETOPT_ACTION_LICENSE:
|
|
desc->help = _("show license.");
|
|
break;
|
|
case ECORE_GETOPT_ACTION_HELP:
|
|
desc->help = _("show this message.");
|
|
break;
|
|
default:
|
|
desc->help = _(desc->help);
|
|
}
|
|
}
|
|
desc++;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static int
|
|
_entice_compare_path(const void *data1, const void *data2)
|
|
{
|
|
const Entice_List_Data *d1;
|
|
const Entice_List_Data *d2;
|
|
|
|
d1 = (const Entice_List_Data *)data1;
|
|
d2 = (const Entice_List_Data *)data2;
|
|
return strcmp(d1->path, d2->path);
|
|
}
|
|
|
|
static int
|
|
_entice_compare_date(const void *data1, const void *data2)
|
|
{
|
|
const Entice_List_Data *d1;
|
|
const Entice_List_Data *d2;
|
|
|
|
d1 = (const Entice_List_Data *)data1;
|
|
d2 = (const Entice_List_Data *)data2;
|
|
|
|
if (d1->date < d2->date)
|
|
return 1;
|
|
|
|
else if (d1->date > d2->date)
|
|
return -1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static Eina_Compare_Cb _entice_compare_default = _entice_compare_path;
|
|
|
|
static Eina_List *
|
|
_file_list_append(Eina_List *list, const char *path, unsigned long mtime, Eina_Bool sort)
|
|
{
|
|
Entice_List_Data *data;
|
|
Eina_Bool found = EINA_FALSE;
|
|
|
|
/* check if the file has a supported extension */
|
|
for (size_t i = 0; _image_ext[i]; i++)
|
|
{
|
|
if (eina_str_has_extension(path, _image_ext[i]))
|
|
{
|
|
found = EINA_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
WRN("File %s has no supported extension.", path);
|
|
return list;
|
|
}
|
|
INF("File %s added.", path);
|
|
|
|
data = calloc(1, sizeof(Entice_List_Data));
|
|
if (!data)
|
|
{
|
|
WRN("Can not allocate data for %s.", path);
|
|
return list;
|
|
}
|
|
|
|
data->path = eina_stringshare_add(path);
|
|
data->date = mtime;
|
|
|
|
if (sort)
|
|
{
|
|
list = eina_list_sorted_insert(list, _entice_compare_default, data);
|
|
}
|
|
else
|
|
{
|
|
list = eina_list_append(list, data);
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
|
|
static Eina_List *
|
|
_dir_parse(Eina_List *list, const char *path)
|
|
{
|
|
Eina_Iterator *it;
|
|
Eina_File_Direct_Info *info;
|
|
|
|
if (!path || !*path)
|
|
return list;
|
|
|
|
it = eina_file_stat_ls(path);
|
|
EINA_ITERATOR_FOREACH(it, info)
|
|
{
|
|
if (info->type == EINA_FILE_REG)
|
|
{
|
|
Eina_Stat buf;
|
|
int ret;
|
|
|
|
ret = eina_file_statat(eina_iterator_container_get(it),
|
|
info, &buf);
|
|
if (ret == 0)
|
|
{
|
|
list = _file_list_append(list, info->path, buf.mtime, EINA_TRUE);
|
|
}
|
|
}
|
|
}
|
|
eina_iterator_free(it);
|
|
|
|
return list;
|
|
}
|
|
|
|
static char *
|
|
_path_uri_decode(const char *arg)
|
|
{
|
|
char *path = NULL;
|
|
|
|
if (!strncasecmp(arg, "file://", strlen("file://")))
|
|
{
|
|
Efreet_Uri *uri = efreet_uri_decode(arg);
|
|
if (uri)
|
|
{
|
|
path = strdup(uri->path);
|
|
efreet_uri_free(uri);
|
|
}
|
|
}
|
|
else path = strdup(arg);
|
|
return path;
|
|
}
|
|
|
|
EAPI_MAIN int
|
|
elm_main(int argc, char **argv)
|
|
{
|
|
Evas_Object *win;
|
|
Entice_Config *cfg;
|
|
Eina_List *list;
|
|
Eina_List *first = NULL;
|
|
Eina_Bool fullscreen = EINA_FALSE;
|
|
Eina_Bool quit_option = EINA_FALSE;
|
|
Ecore_Getopt_Value values[] = {
|
|
ECORE_GETOPT_VALUE_BOOL(fullscreen),
|
|
|
|
ECORE_GETOPT_VALUE_BOOL(quit_option),
|
|
ECORE_GETOPT_VALUE_BOOL(quit_option),
|
|
ECORE_GETOPT_VALUE_BOOL(quit_option),
|
|
ECORE_GETOPT_VALUE_BOOL(quit_option),
|
|
|
|
ECORE_GETOPT_VALUE_NONE
|
|
};
|
|
int win_w;
|
|
int win_h;
|
|
int args;
|
|
|
|
elm_need_efreet();
|
|
|
|
entice_app_log_dom_global = eina_log_domain_register(PACKAGE_NAME, NULL);
|
|
if (entice_app_log_dom_global < 0)
|
|
{
|
|
EINA_LOG_CRIT(_("could not create log domain '" PACKAGE_NAME "'."));
|
|
goto end;
|
|
}
|
|
|
|
args = ecore_getopt_parse(&options, values, argc, argv);
|
|
if (args < 0)
|
|
{
|
|
ERR(_("Could not parse command line options."));
|
|
goto unregister_log;
|
|
}
|
|
|
|
if (quit_option)
|
|
goto unregister_log;
|
|
|
|
entice_config_init();
|
|
cfg = entice_config_load();
|
|
if (!cfg)
|
|
goto shutdown_config;
|
|
|
|
switch (cfg->order)
|
|
{
|
|
case 0:
|
|
_entice_compare_default = _entice_compare_path;
|
|
break;
|
|
case 1:
|
|
_entice_compare_default = _entice_compare_date;
|
|
break;
|
|
default:
|
|
_entice_compare_default = _entice_compare_path;
|
|
}
|
|
|
|
list = NULL;
|
|
if (args == argc)
|
|
{
|
|
list = _dir_parse(list, efreet_pictures_dir_get());
|
|
first = list;
|
|
}
|
|
else
|
|
{
|
|
// only 1 file passed, so scan dir as list and jump to file in that dir
|
|
if (args == (argc - 1))
|
|
{
|
|
char *dir = NULL, *path;
|
|
Eina_List *l;
|
|
Entice_List_Data *data;
|
|
|
|
path = _path_uri_decode(argv[args]);
|
|
if (ecore_file_is_dir(path)) dir = strdup(path);
|
|
else dir = ecore_file_dir_get(path);
|
|
list = _dir_parse(list, dir);
|
|
EINA_LIST_FOREACH(list, l, data)
|
|
{
|
|
if (!strcmp(ecore_file_file_get(data->path),
|
|
ecore_file_file_get(path)))
|
|
{
|
|
first = l;
|
|
break;
|
|
}
|
|
}
|
|
free(path);
|
|
free(dir);
|
|
}
|
|
// multiple files passed - just append them in order as given
|
|
else
|
|
{
|
|
int i;
|
|
|
|
for (i = args; i < argc; i++)
|
|
{
|
|
char *path = _path_uri_decode(argv[i]);
|
|
list = _file_list_append(list, path, 0UL, EINA_FALSE);
|
|
free(path);
|
|
}
|
|
}
|
|
if (!first) first = list;
|
|
}
|
|
|
|
/* FIXME key binding */
|
|
|
|
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
|
|
elm_app_compile_bin_dir_set(PACKAGE_BIN_DIR);
|
|
elm_app_compile_lib_dir_set(PACKAGE_LIB_DIR);
|
|
elm_app_compile_data_dir_set(PACKAGE_DATA_DIR);
|
|
#if ENABLE_NLS
|
|
elm_app_compile_locale_set(LOCALEDIR);
|
|
#endif
|
|
elm_app_name_set(PACKAGE_NAME);
|
|
elm_app_info_set(elm_main, PACKAGE_NAME, "themes/default.edj");
|
|
|
|
#if ENABLE_NLS
|
|
bindtextdomain(PACKAGE_NAME, elm_app_locale_dir_get());
|
|
textdomain(PACKAGE_NAME);
|
|
_entice_translate_options();
|
|
#else
|
|
options.copyright = ENTICE_COPYRIGHT;
|
|
#endif
|
|
|
|
win = entice_win_add();
|
|
if (!win)
|
|
{
|
|
ERR(_("could not create main window."));
|
|
goto del_cfg;
|
|
}
|
|
|
|
win_w = 960;
|
|
win_h = 540;
|
|
if (cfg)
|
|
{
|
|
win_w = cfg->cg_width;
|
|
win_h = cfg->cg_height;
|
|
}
|
|
|
|
evas_object_resize(win,
|
|
win_w * elm_config_scale_get(),
|
|
win_h * elm_config_scale_get());
|
|
|
|
evas_object_show(win);
|
|
|
|
entice_win_images_set(win, list);
|
|
|
|
if (fullscreen) elm_win_fullscreen_set(win, EINA_TRUE);
|
|
|
|
/* once the images are in the list, display the first and current one */
|
|
entice_win_image_first_set(win, first);
|
|
|
|
elm_run();
|
|
|
|
entice_config_del(cfg);
|
|
entice_config_shutdown();
|
|
eina_log_domain_unregister(entice_app_log_dom_global);
|
|
entice_app_log_dom_global = -1;
|
|
|
|
return 0;
|
|
|
|
del_cfg:
|
|
entice_config_del(cfg);
|
|
shutdown_config:
|
|
entice_config_shutdown();
|
|
unregister_log:
|
|
eina_log_domain_unregister(entice_app_log_dom_global);
|
|
entice_app_log_dom_global = -1;
|
|
end:
|
|
return 1;
|
|
}
|
|
ELM_MAIN()
|