diff options
| author | Michael Soegtrop <MSoegtrop@yahoo.de> | 2017-06-05 13:01:17 +0000 |
|---|---|---|
| committer | Michael Soegtrop <MSoegtrop@yahoo.de> | 2017-06-05 13:01:17 +0000 |
| commit | 509ca3687330fea576ea67ae6c7f31d16e66b800 (patch) | |
| tree | 9097520c54e355ded9bd0b4d6618af4e8dacdd91 /src/inkview.cpp | |
| parent | updated to latest trunk (diff) | |
| parent | [Bug #1695016] Xaml export misses some radialGradients. (diff) | |
| download | inkscape-509ca3687330fea576ea67ae6c7f31d16e66b800.tar.gz inkscape-509ca3687330fea576ea67ae6c7f31d16e66b800.zip | |
updated to latest trunk
(bzr r14876.2.4)
Diffstat (limited to 'src/inkview.cpp')
| -rw-r--r-- | src/inkview.cpp | 629 |
1 files changed, 143 insertions, 486 deletions
diff --git a/src/inkview.cpp b/src/inkview.cpp index db4b1aeb0..0b2b07f42 100644 --- a/src/inkview.cpp +++ b/src/inkview.cpp @@ -25,542 +25,199 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ - #ifdef HAVE_CONFIG_H # include "config.h" #endif -#include <cstring> -#include <sys/stat.h> -#include <locale.h> - #include <gtkmm/main.h> -#include <glib.h> - -// #include <stropts.h> #include <libxml/tree.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> - -#include "inkgc/gc-core.h" -#include "preferences.h" +#include <glibmm.h> #include <glibmm/i18n.h> -#include "document.h" -#include "svg-view.h" -#include "svg-view-widget.h" -#include "util/units.h" - -#ifdef WITH_INKJAR -#include "io/inkjar.h" -#endif +#include "document.h" #include "inkscape.h" - -#include <iostream> - -#ifndef HAVE_BIND_TEXTDOMAIN_CODESET -#define bind_textdomain_codeset(p,c) -#endif - -#include "ui/icon-names.h" - -extern char *optarg; -extern int optind, opterr; - -struct SPSlideShow { - char **slides; - int size; - int length; - int current; - SPDocument *doc; - GtkWidget *view; - GtkWidget *window; - bool fullscreen; - int timer; -}; - -static GtkWidget *sp_svgview_control_show (struct SPSlideShow *ss); -static void sp_svgview_show_next (struct SPSlideShow *ss); -static void sp_svgview_show_prev (struct SPSlideShow *ss); -static void sp_svgview_goto_first (struct SPSlideShow *ss); -static void sp_svgview_goto_last (struct SPSlideShow *ss); - -static int sp_svgview_show_next_cb (GtkWidget *widget, void *data); -static int sp_svgview_show_prev_cb (GtkWidget *widget, void *data); -static int sp_svgview_goto_first_cb (GtkWidget *widget, void *data); -static int sp_svgview_goto_last_cb (GtkWidget *widget, void *data); -#ifdef WITH_INKJAR -static bool is_jar(char const *filename); +#include "preferences.h" +#ifdef ENABLE_NLS +#include "helper/gettext.h" #endif -static void usage(); +#include "inkgc/gc-core.h" +#include "io/sys.h" +#include "svg-view-slideshow.h" -static GtkWidget *ctrlwin = NULL; -// Dummy functions to keep linker happy -int sp_main_gui (int, char const**) { return 0; } -int sp_main_console (int, char const**) { return 0; } -static int sp_svgview_main_delete (GtkWidget */*widget*/, - GdkEvent */*event*/, - struct SPSlideShow */*ss*/) -{ - gtk_main_quit (); - return FALSE; -} -static int sp_svgview_main_key_press (GtkWidget */*widget*/, - GdkEventKey *event, - struct SPSlideShow *ss) -{ - switch (event->keyval) { - case GDK_KEY_Up: - case GDK_KEY_Home: - sp_svgview_goto_first(ss); - break; - case GDK_KEY_Down: - case GDK_KEY_End: - sp_svgview_goto_last(ss); - break; - case GDK_KEY_F11: - if (ss->fullscreen) { - gtk_window_unfullscreen (GTK_WINDOW(ss->window)); - ss->fullscreen = false; - } else { - gtk_window_fullscreen (GTK_WINDOW(ss->window)); - ss->fullscreen = true; - } - break; - case GDK_KEY_Return: - sp_svgview_control_show (ss); - break; - case GDK_KEY_KP_Page_Down: - case GDK_KEY_Page_Down: - case GDK_KEY_Right: - case GDK_KEY_space: - sp_svgview_show_next (ss); - break; - case GDK_KEY_KP_Page_Up: - case GDK_KEY_Page_Up: - case GDK_KEY_Left: - case GDK_KEY_BackSpace: - sp_svgview_show_prev (ss); - break; - case GDK_KEY_Escape: - case GDK_KEY_q: - case GDK_KEY_Q: - gtk_main_quit(); - break; - default: - break; - } - gtk_window_set_title(GTK_WINDOW(ss->window), ss->doc->getName()); - return TRUE; -} -int main (int argc, const char **argv) -{ - if (argc == 1) { - usage(); +/** + * \brief Set of command-line options for Inkview + */ +class InkviewOptionsGroup : public Glib::OptionGroup +{ +public: + // list of all input filenames; + // this list contains all arguments that are not recognized as an option (so needs to be checked) + Glib::OptionGroup::vecustrings filenames; + + bool fullscreen = false; // wether to launch in fullscreen mode + bool recursive = false; // wether to search folders for SVG files recursively + int timer = 0; // time (in seconds) after which the next image of the slideshow is automatically loaded + double scale = 1; // scale factor for images + // (currently only applied to the first image - others are resized to window dimensions) + + InkviewOptionsGroup() : Glib::OptionGroup(N_("Inkscape Options"), + N_("Default program options")) + { + // Entry for the "fullscreen" option + Glib::OptionEntry entry_fullscreen; + entry_fullscreen.set_short_name('f'); + entry_fullscreen.set_long_name("fullscreen"); + entry_fullscreen.set_description(N_("Launch in fullscreen mode")); + add_entry(entry_fullscreen, fullscreen); + + // Entry for the "recursive" option + Glib::OptionEntry entry_recursive; + entry_recursive.set_short_name('r'); + entry_recursive.set_long_name("recursive"); + entry_recursive.set_description(N_("Search folders recursively")); + add_entry(entry_recursive, recursive); + + // Entry for the "timer" option + Glib::OptionEntry entry_timer; + entry_timer.set_short_name('t'); + entry_timer.set_long_name("timer"); + entry_timer.set_arg_description(N_("NUM")); + entry_timer.set_description(N_("Change image every NUM seconds")); + add_entry(entry_timer, timer); + + // Entry for the "scale" option + Glib::OptionEntry entry_scale; + entry_scale.set_short_name('s'); + entry_scale.set_long_name("scale"); + entry_scale.set_arg_description(N_("NUM")); + entry_scale.set_description(N_("Scale image by factor NUM")); + add_entry(entry_scale, scale); + + // Entry for the remaining non-option arguments + Glib::OptionEntry entry_args; + entry_args.set_long_name(G_OPTION_REMAINING); + entry_args.set_arg_description(N_("FILES/FOLDERS…")); + + add_entry(entry_args, filenames); } +}; - // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example) - Gtk::Main::init_gtkmm_internals(); - - Gtk::Main main_instance (&argc, const_cast<char ***>(&argv)); - struct SPSlideShow ss; +/** get a list of valid SVG files from a list of strings */ +std::vector<Glib::ustring> get_valid_files(std::vector<Glib::ustring> filenames, bool recursive = false, bool first_iteration = false) +{ + std::vector<Glib::ustring> valid_files; - int num_parsed_options = 0; + for(auto file : filenames) + { + if (!Inkscape::IO::file_test( file.c_str(), G_FILE_TEST_EXISTS )) { + g_printerr("%s: %s\n", _("File or folder does not exist"), file.c_str()); + continue; + } - // the list of arguments is in the net line - for (int i = 1; i < argc; i++) { - if ((argv[i][0] == '-')) { - if (!strcmp(argv[i], "--")) { - break; - } - else if ((!strcmp(argv[i], "-t"))) { - if (i + 1 >= argc) { - usage(); + if (Inkscape::IO::file_test( file.c_str(), G_FILE_TEST_IS_DIR )) { + // only recurse into directories if explicitly specified by user on command line or if recursive = true + if (first_iteration || recursive) { + std::vector<Glib::ustring> new_filenames; + Glib::Dir directory(file); + for (auto new_file: directory) { + new_filenames.push_back(Glib::build_filename(file, new_file)); } - ss.timer = atoi(argv[i+1]); - num_parsed_options = i+1; - i++; - } - else { - usage(); + std::vector<Glib::ustring> new_valid_files = get_valid_files(new_filenames, recursive); + valid_files.insert(valid_files.end(), new_valid_files.begin(), new_valid_files.end()); } - } - } - - GtkWidget *w; - int i; - - bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - LIBXML_TEST_VERSION - - Inkscape::GC::init(); - Inkscape::Preferences::get(); // ensure preferences are initialized - - gtk_init (&argc, (char ***) &argv); - -#ifdef lalaWITH_MODULES - g_warning ("Have to autoinit modules (lauris)"); - sp_modulesys_init(); -#endif /* WITH_MODULES */ - - /* We must set LC_NUMERIC to default, or otherwise */ - /* we'll end with localised SVG files :-( */ - - setlocale (LC_NUMERIC, "C"); - - ss.size = 32; - ss.length = 0; - ss.current = 0; - ss.slides = g_new (char *, ss.size); - ss.current = 0; - ss.doc = NULL; - ss.view = NULL; - ss.fullscreen = false; - - Inkscape::Application::create(argv[0], true); - //Inkscape::Application &inkscape = Inkscape::Application::instance(); - - // starting at where the commandline options stopped parsing because - // we want all the files to be in the list - for (i = num_parsed_options + 1 ; i < argc; i++) { - struct stat st; - if (stat (argv[i], &st) - || !S_ISREG (st.st_mode) - || (st.st_size < 64)) { - fprintf(stderr, "could not open file %s\n", argv[i]); } else { - - #ifdef WITH_INKJAR - if (is_jar(argv[i])) { - Inkjar::JarFileReader jar_file_reader(argv[i]); - for (;;) { - GByteArray *gba = jar_file_reader.get_next_file(); - if (gba == NULL) { - char *c_ptr; - gchar *last_filename = jar_file_reader.get_last_filename(); - if (last_filename == NULL) - break; - if ((c_ptr = std::strrchr(last_filename, '/')) != NULL) { - if (*(++c_ptr) == '\0') { - g_free(last_filename); - continue; - } - } - } else if (gba->len > 0) { - //::write(1, gba->data, gba->len); - /* Append to list */ - if (ss.length >= ss.size) { - /* Expand */ - ss.size <<= 1; - ss.slides = g_renew (char *, ss.slides, ss.size); - } - - ss.doc = SPDocument::createNewDocFromMem ((const gchar *)gba->data, - gba->len, - TRUE); - gchar *last_filename = jar_file_reader.get_last_filename(); - if (ss.doc) { - ss.slides[ss.length++] = strdup (last_filename); - (ss.doc)->setUri (last_filename); - } - g_byte_array_free(gba, TRUE); - g_free(last_filename); - } else { - break; - } + if (!first_iteration) { + // filter out files based on extension if they were not explicitly specified on command line + Glib::ustring extension = file.substr( file.find_last_of(".") + 1 ); + if (extension.compare("svg") && extension.compare("svgz")) { + continue; } - } else { - #endif /* WITH_INKJAR */ - /* Append to list */ - if (ss.length >= ss.size) { - /* Expand */ - ss.size <<= 1; - ss.slides = g_renew (char *, ss.slides, ss.size); } - ss.slides[ss.length++] = strdup (argv[i]); - - if (!ss.doc) { - ss.doc = SPDocument::createNewDoc (ss.slides[ss.current], TRUE, false); - if (!ss.doc) { - ++ss.current; - } - } - #ifdef WITH_INKJAR + auto doc = SPDocument::createNewDoc(file.c_str(), TRUE, false); + if(doc) { + /* Append to list */ + valid_files.push_back(file); + } else { + g_printerr("%s: %s\n", _("Could not open file"), file.c_str()); } - #endif } } - if(!ss.doc) { - return 1; /* none of the slides loadable */ - } - - w = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title( GTK_WINDOW(w), ss.doc->getName() ); - gtk_window_set_default_size (GTK_WINDOW (w), - MIN ((int)(ss.doc)->getWidth().value("px"), (int)gdk_screen_width() - 64), - MIN ((int)(ss.doc)->getHeight().value("px"), (int)gdk_screen_height() - 64)); - ss.window = w; - - g_signal_connect (G_OBJECT (w), "delete_event", (GCallback) sp_svgview_main_delete, &ss); - g_signal_connect (G_OBJECT (w), "key_press_event", (GCallback) sp_svgview_main_key_press, &ss); - - (ss.doc)->ensureUpToDate(); - ss.view = sp_svg_view_widget_new (ss.doc); - (ss.doc)->doUnref (); - SP_SVG_VIEW_WIDGET(ss.view)->setResize( false, ss.doc->getWidth().value("px"), ss.doc->getHeight().value("px") ); - gtk_widget_show (ss.view); - gtk_container_add (GTK_CONTAINER (w), ss.view); - - gtk_widget_show (w); - - gtk_main (); - - return 0; -} - -static int sp_svgview_ctrlwin_delete (GtkWidget */*widget*/, - GdkEvent */*event*/, - void */*data*/) -{ - ctrlwin = NULL; - return FALSE; + return valid_files; } -static GtkWidget* sp_svgview_control_show(struct SPSlideShow *ss) -{ - if (!ctrlwin) { - ctrlwin = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_resizable(GTK_WINDOW(ctrlwin), FALSE); - gtk_window_set_transient_for(GTK_WINDOW(ctrlwin), GTK_WINDOW(ss->window)); - g_signal_connect(G_OBJECT (ctrlwin), "key_press_event", (GCallback) sp_svgview_main_key_press, ss); - g_signal_connect(G_OBJECT (ctrlwin), "delete_event", (GCallback) sp_svgview_ctrlwin_delete, NULL); - -#if GTK_CHECK_VERSION(3,0,0) - GtkWidget *t = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); -#else - GtkWidget *t = gtk_hbutton_box_new(); -#endif - - gtk_container_add(GTK_CONTAINER(ctrlwin), t); - -#if GTK_CHECK_VERSION(3,10,0) - GtkWidget *b = gtk_button_new_from_icon_name(INKSCAPE_ICON("go-first"), GTK_ICON_SIZE_BUTTON); -#else - GtkWidget *b = gtk_button_new(); - GtkWidget *img = gtk_image_new_from_icon_name(INKSCAPE_ICON("go-first"), GTK_ICON_SIZE_BUTTON); - gtk_button_set_image(GTK_BUTTON(b), img); +#ifdef WIN32 +// minimal print handler (just prints the string to stdout) +void g_print_no_convert(const gchar *buf) { fputs(buf, stdout); } +void g_printerr_no_convert(const gchar *buf) { fputs(buf, stderr); } #endif - gtk_container_add(GTK_CONTAINER(t), b); - - g_signal_connect(G_OBJECT(b), "clicked", (GCallback) sp_svgview_goto_first_cb, ss); -#if GTK_CHECK_VERSION(3,10,0) - b = gtk_button_new_from_icon_name(INKSCAPE_ICON("go-previous"), GTK_ICON_SIZE_BUTTON); -#else - b = gtk_button_new(); - img = gtk_image_new_from_icon_name(INKSCAPE_ICON("go-previous"), GTK_ICON_SIZE_BUTTON); - gtk_button_set_image(GTK_BUTTON(b), img); -#endif - gtk_container_add(GTK_CONTAINER(t), b); - - g_signal_connect(G_OBJECT(b), "clicked", (GCallback) sp_svgview_show_prev_cb, ss); -#if GTK_CHECK_VERSION(3,10,0) - b = gtk_button_new_from_icon_name(INKSCAPE_ICON("go-next"), GTK_ICON_SIZE_BUTTON); -#else - b = gtk_button_new(); - img = gtk_image_new_from_icon_name(INKSCAPE_ICON("go-next"), GTK_ICON_SIZE_BUTTON); - gtk_button_set_image(GTK_BUTTON(b), img); -#endif - gtk_container_add(GTK_CONTAINER(t), b); - - g_signal_connect(G_OBJECT(b), "clicked", (GCallback) sp_svgview_show_next_cb, ss); -#if GTK_CHECK_VERSION(3,10,0) - b = gtk_button_new_from_icon_name(INKSCAPE_ICON("go-last"), GTK_ICON_SIZE_BUTTON); -#else - b = gtk_button_new(); - img = gtk_image_new_from_icon_name(INKSCAPE_ICON("go-last"), GTK_ICON_SIZE_BUTTON); - gtk_button_set_image(GTK_BUTTON(b), img); -#endif - gtk_container_add(GTK_CONTAINER(t), b); - g_signal_connect(G_OBJECT(b), "clicked", (GCallback) sp_svgview_goto_last_cb, ss); - gtk_widget_show_all(ctrlwin); - } else { - gtk_window_present(GTK_WINDOW(ctrlwin)); - } - - return NULL; -} - -static int sp_svgview_show_next_cb (GtkWidget */*widget*/, void *data) -{ - sp_svgview_show_next(static_cast<struct SPSlideShow *>(data)); - return FALSE; -} - -static int sp_svgview_show_prev_cb (GtkWidget */*widget*/, void *data) -{ - sp_svgview_show_prev(static_cast<struct SPSlideShow *>(data)); - return FALSE; -} -static int sp_svgview_goto_first_cb (GtkWidget */*widget*/, void *data) +int main (int argc, char **argv) { - sp_svgview_goto_first(static_cast<struct SPSlideShow *>(data)); - return FALSE; -} - -static int sp_svgview_goto_last_cb (GtkWidget */*widget*/, void *data) -{ - sp_svgview_goto_last(static_cast<struct SPSlideShow *>(data)); - return FALSE; -} - -static void sp_svgview_waiting_cursor(struct SPSlideShow *ss) -{ - GdkDisplay *display = gdk_display_get_default(); - GdkCursor *waiting = gdk_cursor_new_for_display(display, GDK_WATCH); - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(ss->window)), waiting); -#if GTK_CHECK_VERSION(3,0,0) - g_object_unref(waiting); -#else - gdk_cursor_unref(waiting); +#ifdef WIN32 + // Ugly hack to make g_print emit UTF-8 encoded characters. Otherwise glib will *always* + // perform character conversion to the system's ANSI code page making UTF-8 output impossible. + g_set_print_handler(g_print_no_convert); + g_set_printerr_handler(g_print_no_convert); #endif - if (ctrlwin) { - GdkCursor *waiting = gdk_cursor_new_for_display(display, GDK_WATCH); - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(ctrlwin)), waiting); -#if GTK_CHECK_VERSION(3,0,0) - g_object_unref(waiting); -#else - gdk_cursor_unref(waiting); +#ifdef ENABLE_NLS + Inkscape::initialize_gettext(); #endif - } - while(gtk_events_pending()) { - gtk_main_iteration(); - } -} - -static void sp_svgview_normal_cursor(struct SPSlideShow *ss) -{ - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(ss->window)), NULL); - if (ctrlwin) { - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(ctrlwin)), NULL); - } -} - -static void sp_svgview_set_document(struct SPSlideShow *ss, - SPDocument *doc, - int current) -{ - if (doc && doc != ss->doc) { - doc->ensureUpToDate(); - reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc); - ss->doc = doc; - ss->current = current; - } -} - -static void sp_svgview_show_next (struct SPSlideShow *ss) -{ - sp_svgview_waiting_cursor(ss); - - SPDocument *doc = NULL; - int current = ss->current; - while (!doc && (current < ss->length - 1)) { - doc = SPDocument::createNewDoc (ss->slides[++current], TRUE, false); - } - - sp_svgview_set_document(ss, doc, current); - - sp_svgview_normal_cursor(ss); -} -static void sp_svgview_show_prev (struct SPSlideShow *ss) -{ - sp_svgview_waiting_cursor(ss); - - SPDocument *doc = NULL; - int current = ss->current; - while (!doc && (current > 0)) { - doc = SPDocument::createNewDoc (ss->slides[--current], TRUE, false); + Glib::OptionContext context(N_("- display SVG files")); + context.set_summary(N_( + "Quickly browse through a collection of .svg(z) files\n" + "or show them as a slide show.")); + context.set_description(N_( + "Example:\n" + " inkview -t 3 file1.svg file2.svgz series*.svg more_files")); + context.set_translation_domain(GETTEXT_PACKAGE); + + InkviewOptionsGroup options; + options.set_translation_domain(GETTEXT_PACKAGE); + + context.set_main_group(options); + + Gtk::Main main_instance(true); + try { + context.parse(argc, argv); + } catch (const Glib::Error& ex) { + g_printerr("%s\n\n", ex.what().c_str()); + g_print("%s", context.get_help().c_str()); + exit(EXIT_FAILURE); } - sp_svgview_set_document(ss, doc, current); + LIBXML_TEST_VERSION - sp_svgview_normal_cursor(ss); -} + Inkscape::GC::init(); + Inkscape::Preferences::get(); // ensure preferences are initialized -static void sp_svgview_goto_first (struct SPSlideShow *ss) -{ - sp_svgview_waiting_cursor(ss); + Inkscape::Application::create(argv[0], true); - SPDocument *doc = NULL; - int current = 0; - while ( !doc && (current < ss->length - 1)) { - if (current == ss->current) { - break; - } - doc = SPDocument::createNewDoc (ss->slides[current++], TRUE, false); + if(options.filenames.empty()) + { + g_print("%s", context.get_help().c_str()); + exit(EXIT_FAILURE); } - sp_svgview_set_document(ss, doc, current - 1); - - sp_svgview_normal_cursor(ss); -} - -static void sp_svgview_goto_last (struct SPSlideShow *ss) -{ - sp_svgview_waiting_cursor(ss); - - SPDocument *doc = NULL; - int current = ss->length - 1; - while (!doc && (current >= 0)) { - if (current == ss->current) { - break; - } - doc = SPDocument::createNewDoc (ss->slides[current--], TRUE, false); + std::vector<Glib::ustring> valid_files = get_valid_files(options.filenames, options.recursive, true); + if(valid_files.empty()) { + g_printerr("%s\n", _("No valid files to load.")); + return 1; /* none of the slides loadable */ } - sp_svgview_set_document(ss, doc, current + 1); - - sp_svgview_normal_cursor(ss); -} - -#ifdef WITH_INKJAR -static bool is_jar(char const *filename) -{ - /* fixme: Check MIME type or something. /usr/share/misc/file/magic suggests that checking for - initial string "PK\003\004" in content should suffice. */ - size_t const filename_len = strlen(filename); - if (filename_len < 5) { - return false; - } - char const *extension = filename + filename_len - 4; - return ((memcmp(extension, ".jar", 4) == 0) || - (memcmp(extension, ".sxw", 4) == 0) ); -} -#endif /* WITH_INKJAR */ + SPSlideShow ss(valid_files, options.fullscreen, options.timer, options.scale); + main_instance.run(); -static void usage() -{ - fprintf(stderr, - "Usage: inkview [OPTIONS...] [FILES ...]\n" - "\twhere FILES are SVG (.svg or .svgz)" -#ifdef WITH_INKJAR - " or archives of SVGs (.sxw, .jar)" -#endif - "\n"); - exit(1); + return 0; } /* |
