summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt10
-rw-r--r--src/inkview-application.cpp139
-rw-r--r--src/inkview-application.h54
-rw-r--r--src/inkview-main.cpp28
-rw-r--r--src/inkview-options-group.cpp56
-rw-r--r--src/inkview-options-group.h35
-rw-r--r--src/inkview-window.cpp412
-rw-r--r--src/inkview-window.h64
-rw-r--r--src/inkview.cpp187
-rw-r--r--src/svg-view-slideshow.cpp325
-rw-r--r--src/svg-view-slideshow.h83
11 files changed, 702 insertions, 691 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 920674a93..9daea38bb 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -86,7 +86,6 @@ set(inkscape_SRC
sp-item-notify-moveto.cpp
style-internal.cpp
style.cpp
- svg-view-slideshow.cpp
svg-view-widget.cpp
svg-view.cpp
text-chemistry.cpp
@@ -207,7 +206,6 @@ set(inkscape_SRC
style-internal.h
style.h
svg-profile.h
- svg-view-slideshow.h
svg-view-widget.h
svg-view.h
syseq.h
@@ -285,9 +283,11 @@ set(inkscape_SRC
# -----------------------------------------------------------------------------
set(main_SRC main.cpp)
set(view_SRC
- inkview.cpp
- inkview-options-group.cpp
- inkview-options-group.h
+ inkview-main.cpp
+ inkview-application.h
+ inkview-application.cpp
+ inkview-window.h
+ inkview-window.cpp
)
if(WIN32)
diff --git a/src/inkview-application.cpp b/src/inkview-application.cpp
new file mode 100644
index 000000000..cfcd8ecad
--- /dev/null
+++ b/src/inkview-application.cpp
@@ -0,0 +1,139 @@
+/*
+ * Inkview - An SVG file viewer.
+ *
+ * Copyright (C) 2018 Tavmjong Bah
+ *
+ * The contents of this file may be used under the GNU General Public License Version 2 or later.
+ *
+ */
+
+#include <iostream>
+
+#include <glibmm/i18n.h> // Internationalization
+
+#include "inkview-application.h"
+
+#include "inkscape.h" // Inkscape::Application
+#include "inkgc/gc-core.h" // Garbage Collecting init
+#include "inkview-window.h"
+
+#ifdef ENABLE_NLS
+// Native Language Support - shouldn't this always be used?
+#include "helper/gettext.h" // gettext init
+#endif // ENABLE_NLS
+
+// This is a bit confusing as there are two ways to handle command line arguments and files
+// depending on if the Gio::APPLICATION_HANDLES_OPEN and/or Gio::APPLICATION_HANDLES_COMMAND_LINE
+// flags are set. If the open flag is set and the command line not, the all the remainng arguments
+// after calling on_handle_local_options() are assumed to be filenames.
+
+InkviewApplication::InkviewApplication()
+ : Gtk::Application("org.inkscape.application.inkview",
+ Gio::APPLICATION_HANDLES_OPEN | // Use default file opening.
+ Gio::APPLICATION_NON_UNIQUE ) // Allows different instances of Inkview to run at same time.
+ , fullscreen(false)
+ , recursive(false)
+ , timer(0)
+ , scale(1.0)
+{
+ // ==================== Initializations =====================
+ // Garbage Collector
+ Inkscape::GC::init();
+
+#ifdef ENABLE_NLS
+ // Native Language Support (shouldn't this always be used?).
+ Inkscape::initialize_gettext();
+#endif
+
+ Glib::set_application_name(N_("Inkview - An SVG File Viewer")); // After gettext() init.
+
+ // Will automatically handle character conversions.
+ // Note: OPTION_TYPE_FILENAME => std::string, OPTION_TYPE_STRING => Glib::ustring.
+
+ add_main_option_entry(OPTION_TYPE_BOOL, "fullscreen", 'f', N_("Launch in fullscreen mode"), "");
+ add_main_option_entry(OPTION_TYPE_BOOL, "recursive", 'r', N_("Search folders recursively"), "");
+ add_main_option_entry(OPTION_TYPE_INT, "timer", 't', N_("Change image every NUMBER seconds"), N_("NUMBER"));
+ add_main_option_entry(OPTION_TYPE_DOUBLE, "scale", 's', N_("Scale image by factor NUMBER"), N_("NUMBER"));
+
+ signal_handle_local_options().connect(sigc::mem_fun(*this, &InkviewApplication::on_handle_local_options));
+
+ // This is normally called for us... but after the "handle_local_options" signal is emitted. If
+ // we want to rely on actions for handling options, we need to call it here. This appears to
+ // have no unwanted side-effect. It will also trigger the call to on_startup().
+ register_application();
+}
+
+Glib::RefPtr<InkviewApplication> InkviewApplication::create()
+{
+ return Glib::RefPtr<InkviewApplication>(new InkviewApplication());
+}
+
+void
+InkviewApplication::on_startup()
+{
+ Gtk::Application::on_startup();
+
+ // Inkscape::Application should disappear!
+ Inkscape::Application::create(nullptr, true); // argv appears to not be used.
+}
+
+
+// Open document window with default document. Either this or on_open() is called.
+void
+InkviewApplication::on_activate()
+{
+ std::cerr << "InkviewApplication: No documents to open!" << std::endl;
+}
+
+// Open document window for each file. Either this or on_activate() is called.
+void
+InkviewApplication::on_open(const Gio::Application::type_vec_files& files, const Glib::ustring& hint)
+{
+ window = new InkviewWindow(files, fullscreen, recursive, timer, scale);
+ window->show_all();
+ add_window(*window);
+}
+
+
+// ========================= Callbacks ==========================
+
+/*
+ * Handle command line options callback.
+ */
+int
+InkviewApplication::on_handle_local_options(const Glib::RefPtr<Glib::VariantDict>& options)
+{
+ if (!options) {
+ std::cerr << "InkviewApplication::on_handle_local_options: options is null!" << std::endl;
+ return -1; // Keep going
+ }
+
+ if (options->contains("fullscreen")) {
+ fullscreen = true;
+ }
+
+ if (options->contains("recursive")) {
+ recursive = true;
+ }
+
+ if (options->contains("timer")) {
+ options->lookup_value("timer", timer);
+ }
+
+ if (options->contains("scale")) {
+ options->lookup_value("scale", scale);
+ }
+
+ return -1; // Keep going
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/inkview-application.h b/src/inkview-application.h
new file mode 100644
index 000000000..d9160ddd1
--- /dev/null
+++ b/src/inkview-application.h
@@ -0,0 +1,54 @@
+/*
+ * Inkview - An SVG file viewer.
+ *
+ * Copyright (C) 2018 Tavmjong Bah
+ *
+ * The contents of this file may be used under the GNU General Public License Version 2 or later.
+ *
+ */
+
+#ifndef INKVIEW_APPLICATION_H
+#define INKVIEW_APPLICATION_H
+
+#include <gtkmm.h>
+
+class InkviewWindow;
+
+class InkviewApplication : public Gtk::Application
+{
+protected:
+ InkviewApplication();
+
+public:
+ static Glib::RefPtr<InkviewApplication> create();
+
+protected:
+ void on_startup() override;
+ void on_activate() override;
+ void on_open(const Gio::Application::type_vec_files& files, const Glib::ustring& hint) override;
+
+private:
+ // Callbacks
+ int on_handle_local_options(const Glib::RefPtr<Glib::VariantDict>& options);
+
+ // Command line options
+ bool fullscreen;
+ bool recursive;
+ int timer;
+ double scale;
+
+ InkviewWindow* window;
+};
+
+#endif // INKVIEW_APPLICATION_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/inkview-main.cpp b/src/inkview-main.cpp
new file mode 100644
index 000000000..ed694596d
--- /dev/null
+++ b/src/inkview-main.cpp
@@ -0,0 +1,28 @@
+/*
+ * Inkview - An SVG file viewer.
+ *
+ * Copyright (C) 2018 Tavmjong Bah
+ *
+ * The contents of this file may be used under the GNU General Public License Version 2 or later.
+ *
+ */
+
+#include "inkview-application.h"
+
+int main(int argc, char *argv[])
+{
+ auto application = InkviewApplication::create();
+
+ return application->run(argc, argv);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/inkview-options-group.cpp b/src/inkview-options-group.cpp
deleted file mode 100644
index 7879c55e2..000000000
--- a/src/inkview-options-group.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-#include "inkview-options-group.h"
-
-#include <glibmm/i18n.h>
-
-InkviewOptionsGroup::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);
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/inkview-options-group.h b/src/inkview-options-group.h
deleted file mode 100644
index 592caf1af..000000000
--- a/src/inkview-options-group.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef INKVIEW_OPTIONS_GROUP_H
-#define INKVIEW_OPTIONS_GROUP_H
-
-#include <glibmm.h>
-
-/**
- * \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; // whether to launch in fullscreen mode
- bool recursive = false; // whether 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();
-};
-#endif // INKVIEW_OPTIONS_GROUP_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/inkview-window.cpp b/src/inkview-window.cpp
new file mode 100644
index 000000000..7f4826ae6
--- /dev/null
+++ b/src/inkview-window.cpp
@@ -0,0 +1,412 @@
+/*
+ * Inkview - An SVG file viewer.
+ *
+ * Copyright (C) 2018 Tavmjong Bah
+ *
+ * The contents of this file may be used under the GNU General Public License Version 2 or later.
+ *
+ */
+
+#include "inkview-window.h"
+
+#include <iostream>
+
+#include "document.h"
+#include "inkscape.h" // INKSCAPE macro
+#include "svg-view.h"
+#include "svg-view-widget.h"
+
+#include "ui/monitor.h"
+#include "util/units.h"
+
+InkviewWindow::InkviewWindow(const Gio::Application::type_vec_files files,
+ bool fullscreen,
+ bool recursive,
+ int timer,
+ double scale)
+ : _files(files)
+ , _fullscreen(fullscreen)
+ , _recursive(recursive)
+ , _timer(timer)
+ , _scale(scale)
+ , _index(-1)
+ , _view(nullptr)
+ , _controlwindow(nullptr)
+{
+ _files = create_file_list(_files);
+ _documents.resize( _files.size(), nullptr); // We keep _documents and _files in sync.
+
+ // Callbacks
+ signal_key_press_event().connect(sigc::mem_fun(*this, &InkviewWindow::key_press), false);
+
+ if (_timer) {
+ Glib::signal_timeout().connect_seconds(sigc::mem_fun(*this, &InkviewWindow::on_timer), _timer);
+ }
+
+ // Actions
+ add_action( "show_first", sigc::mem_fun(*this, &InkviewWindow::show_first) );
+ add_action( "show_prev", sigc::mem_fun(*this, &InkviewWindow::show_prev) );
+ add_action( "show_next", sigc::mem_fun(*this, &InkviewWindow::show_next) );
+ add_action( "show_last", sigc::mem_fun(*this, &InkviewWindow::show_last) );
+
+ // ToDo: Add Pause, Resume.
+
+ // Show first file
+ activate_action( "show_first" );
+}
+
+std::vector<Glib::RefPtr<Gio::File> >
+InkviewWindow::create_file_list(const std::vector<Glib::RefPtr<Gio::File > >& files)
+{
+ std::vector<Glib::RefPtr<Gio::File> > valid_files;
+
+ for (auto file : files) {
+ Gio::FileType type = file->query_file_type();
+ switch (type) {
+ case Gio::FILE_TYPE_NOT_KNOWN:
+ std::cerr << "InkviewWindow: File or directory does not exist: "
+ << file->get_basename() << std::endl;
+ break;
+
+ case Gio::FILE_TYPE_REGULAR:
+ {
+ // If recursive, only look at SVG and SVGZ files.
+ std::string basename = file->get_basename();
+ std::string extension = basename.substr(basename.find_last_of(".") + 1);
+ if (!_recursive || extension == "svg" || extension == "svgz") {
+ valid_files.push_back(file);
+ }
+ break;
+ }
+
+ case Gio::FILE_TYPE_DIRECTORY:
+ {
+ if (_recursive) {
+ // No easy way to get children of directory!
+ Glib::RefPtr<Gio::FileEnumerator> children = file->enumerate_children();
+ Glib::RefPtr<Gio::FileInfo> info;
+ std::vector<Glib::RefPtr<Gio::File> > input;
+ while (info = children->next_file()) {
+ input.push_back(children->get_child(info));
+ }
+ auto new_files = create_file_list(input);
+ valid_files.insert(valid_files.end(), new_files.begin(), new_files.end());
+ }
+ break;
+ }
+ default:
+ std::cerr << "InkviewWindow: Unknown file type: " << type << std::endl;
+ }
+ }
+
+ return valid_files;
+}
+
+void
+InkviewWindow::update_title()
+{
+ Glib::ustring title(_documents[_index]->getName());
+
+ if (_documents.size() > 1) {
+ title += Glib::ustring::compose(" (%1/%2)", _index+1, _documents.size());
+ }
+
+ set_title(title);
+}
+
+// Returns true if successfully shows document.
+bool
+InkviewWindow::show_document(SPDocument* document)
+{
+ document->ensureUpToDate(); // Crashes on some documents if this isn't called!
+
+ // Resize window: (Might be better to use get_monitor_geometry_at_window(this))
+ Gdk::Rectangle monitor_geometry = Inkscape::UI::get_monitor_geometry_primary();
+ int width = MIN((int)document->getWidth().value("px") * _scale, monitor_geometry.get_width());
+ int height = MIN((int)document->getHeight().value("px") * _scale, monitor_geometry.get_height());
+ resize (width, height);
+
+ // setDocument() reduces the document count... bump it up so document won't be deleted.
+ // ToDo: view should not be handling document lifetime.
+ INKSCAPE.add_document(document);
+
+ if (_view) {
+ reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW(_view))->setDocument(document);
+ } else {
+ _view = sp_svg_view_widget_new(document);
+ add (*Glib::wrap(_view));
+ }
+
+ update_title();
+
+ return true;
+}
+
+
+// Load document, if fail, remove entry from lists.
+SPDocument*
+InkviewWindow::load_document()
+{
+ SPDocument* document = _documents[_index];
+
+ if (!document) {
+ // We need to load document. ToDo: Pass Gio::File. Is get_base_name() better?
+ document = SPDocument::createNewDoc (_files[_index]->get_parse_name().c_str(), true, false);
+ if (document) {
+ // We've successfully loaded it!
+ _documents[_index] = document;
+ }
+ }
+
+ if (!document) {
+ // Failed to load document, remove from vectors.
+ _documents.erase(std::next(_documents.begin(), _index));
+ _files.erase( std::next( _files.begin(), _index));
+ }
+
+ return document;
+}
+
+static std::string window_markup = R"(
+<interface>
+ <object class="GtkWindow" id="ControlWindow">
+ <child>
+ <object class="GtkButtonBox">
+ <child>
+ <object class="GtkButton" id="show-first">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">go-first</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="show-prev">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">go-previous</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="show-next">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">go-next</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="show-last">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">go-last</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
+)";
+
+void
+InkviewWindow::show_control()
+{
+ if (!_controlwindow) {
+
+ auto builder = Gtk::Builder::create();
+ try
+ {
+ builder->add_from_string(window_markup);
+ }
+ catch (const Glib::Error& err)
+ {
+ std::cerr << "InkviewWindow::show_control: builder failed: " << err.what() << std::endl;
+ return;
+ }
+
+
+ builder->get_widget("ControlWindow", _controlwindow);
+ if (!_controlwindow) {
+ std::cerr << "InkviewWindow::show_control: Control Window not found!" << std::endl;
+ return;
+ }
+
+ // Need to give control window access to viewer window's actions.
+ Glib::RefPtr<Gio::ActionGroup> viewer = get_action_group("win");
+ if (viewer) {
+ _controlwindow->insert_action_group("viewer", viewer);
+ }
+
+ // Gtk::Button not derived from Gtk::Actionable due to ABI issues. Must use Gtk.
+ // Fixed in Gtk4. In Gtk4 this can be replaced by setting the action in the interface.
+ Gtk::Button* button;
+ builder->get_widget("show-first", button);
+ gtk_actionable_set_action_name( GTK_ACTIONABLE(button->gobj()), "viewer.show_first");
+ builder->get_widget("show-prev", button);
+ gtk_actionable_set_action_name( GTK_ACTIONABLE(button->gobj()), "viewer.show_prev");
+ builder->get_widget("show-next", button);
+ gtk_actionable_set_action_name( GTK_ACTIONABLE(button->gobj()), "viewer.show_next");
+ builder->get_widget("show-last", button);
+ gtk_actionable_set_action_name( GTK_ACTIONABLE(button->gobj()), "viewer.show_last");
+
+ _controlwindow->set_resizable(false);
+ _controlwindow->set_transient_for(*this);
+ _controlwindow->show_all();
+
+ } else {
+ _controlwindow->present();
+ }
+}
+
+// Next document
+void
+InkviewWindow::show_next()
+{
+ ++_index;
+
+ SPDocument* document = nullptr;
+
+ while (_index < _documents.size() && !document) {
+ document = load_document();
+ }
+
+ if (document) {
+ // Show new document
+ show_document(document);
+ } else {
+ // Failed to load new document, keep current.
+ --_index;
+ }
+}
+
+// Previous document
+void
+InkviewWindow::show_prev()
+{
+ SPDocument* document = nullptr;
+ int old_index = _index;
+
+ while (_index > 0 && !document) {
+ --_index;
+ document = load_document();
+ }
+
+ if (document) {
+ // Show new document
+ show_document(document);
+ } else {
+ // Failed to load new document, keep current.
+ _index = old_index;
+ }
+}
+
+// Show first document
+void
+InkviewWindow::show_first()
+{
+ _index = -1;
+ show_next();
+}
+
+// Show last document
+void
+InkviewWindow::show_last()
+{
+ _index = _documents.size();
+ show_prev();
+}
+
+bool
+InkviewWindow::key_press(GdkEventKey* event)
+{
+ switch (event->keyval) {
+ case GDK_KEY_Up:
+ case GDK_KEY_Home:
+ show_first();
+ break;
+
+ case GDK_KEY_Down:
+ case GDK_KEY_End:
+ show_last();
+ break;
+
+ case GDK_KEY_F11:
+ if (_fullscreen) {
+ unfullscreen();
+ _fullscreen = false;
+ } else {
+ fullscreen();
+ _fullscreen = true;
+ }
+ break;
+
+ case GDK_KEY_Return:
+ show_control();
+ break;
+
+ case GDK_KEY_KP_Page_Down:
+ case GDK_KEY_Page_Down:
+ case GDK_KEY_Right:
+ case GDK_KEY_space:
+ show_next();
+ break;
+
+ case GDK_KEY_KP_Page_Up:
+ case GDK_KEY_Page_Up:
+ case GDK_KEY_Left:
+ case GDK_KEY_BackSpace:
+ show_prev();
+ break;
+
+ case GDK_KEY_Escape:
+ case GDK_KEY_q:
+ case GDK_KEY_Q:
+ close();
+ break;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+bool
+InkviewWindow::on_timer()
+{
+ show_next();
+
+ // Stop if at end.
+ if (_index >= _documents.size() - 1) {
+ return false;
+ }
+ return true;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/inkview-window.h b/src/inkview-window.h
new file mode 100644
index 000000000..83cb4d1d1
--- /dev/null
+++ b/src/inkview-window.h
@@ -0,0 +1,64 @@
+/*
+ * Inkview - An SVG file viewer.
+ *
+ * Copyright (C) 2018 Tavmjong Bah
+ *
+ * The contents of this file may be used under the GNU General Public License Version 2 or later.
+ *
+ */
+
+#ifndef INKVIEW_WINDOW_H
+#define INKVIEW_WINDOW_H
+
+#include <gtkmm.h>
+
+class SPDocument;
+
+class InkviewWindow : public Gtk::ApplicationWindow {
+
+ public:
+ InkviewWindow(const Gio::Application::type_vec_files files,
+ bool fullscreen, bool recursive, int timer, double scale);
+
+ private:
+ std::vector<Glib::RefPtr<Gio::File> >
+ create_file_list(const std::vector<Glib::RefPtr<Gio::File > >& files);
+ void update_title();
+ bool show_document(SPDocument* document);
+ SPDocument* load_document();
+
+ Gio::Application::type_vec_files _files;
+ bool _fullscreen;
+ bool _recursive;
+ int _timer;
+ double _scale;
+
+ int _index;
+ std::vector<SPDocument*> _documents;
+
+ GtkWidget* _view;
+ Gtk::Window* _controlwindow;
+
+ // Callbacks
+ void show_control();
+ void show_next();
+ void show_prev();
+ void show_first();
+ void show_last();
+
+ bool key_press(GdkEventKey* event);
+ bool on_timer();
+};
+
+#endif // INKVIEW_WINDOW_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/inkview.cpp b/src/inkview.cpp
deleted file mode 100644
index f33962704..000000000
--- a/src/inkview.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Inkscape - an ambitious vector drawing program
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Frank Felfe <innerspace@iname.com>
- * Davide Puricelli <evo@debian.org>
- * Mitsuru Oka <oka326@parkcity.ne.jp>
- * Masatake YAMATO <jet@gyve.org>
- * F.J.Franklin <F.J.Franklin@sheffield.ac.uk>
- * Michael Meeks <michael@helixcode.com>
- * Chema Celorio <chema@celorio.com>
- * Pawel Palucha
- * ... and various people who have worked with various projects
- * Abhishek Sharma
- *
- * Copyright (C) 1999-2002 authors
- * Copyright (C) 2001-2002 Ximian, Inc.
- *
- * Inkscape authors:
- * Johan Ceuppens
- *
- * Copyright (C) 2004 Inkscape authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h" // only include where actually required!
-#endif
-
-#include <gtkmm/main.h>
-
-#include <libxml/tree.h>
-
-#include <glibmm/i18n.h>
-
-#include "document.h"
-#include "inkscape.h"
-#include "preferences.h"
-#ifdef ENABLE_NLS
-#include "helper/gettext.h"
-#endif
-#include "inkgc/gc-core.h"
-#include "io/sys.h"
-#include "svg-view-slideshow.h"
-#include "inkview-options-group.h"
-
-/**
- * @brief Get a list of valid SVG files from a list of strings
- *
- * @param[in] filenames The list of filenames/folders to check
- * @param[in] recursive True if we want to search within subfolders
- * @param[in] first_iteration True if this is the first iteration of the search
- *
- * @returns A new vector containing the complete paths for any valid SVG files
- */
-std::vector<Glib::ustring>
-get_valid_files(std::vector<Glib::ustring> filenames,
- bool recursive = false,
- bool first_iteration = false)
-{
- // List to store all the valid files found by the search
- std::vector<Glib::ustring> valid_files;
-
- // Loop through all the input filenames
- for(auto file : filenames)
- {
- // First check if the file actually exists. Skip to the next item if not
- 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;
- }
-
- // Now determine if this is a directory or a single file
- 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.emplace_back(Glib::build_filename(file, new_file));
- }
- 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());
- }
- } else {
- 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;
- }
- }
-
- // Try to create a new document from the contents of the file, and if it is valid
- // add the path to the list
- 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());
- }
- }
- }
-
- return valid_files;
-}
-
-#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
-
-int main (int argc, char **argv)
-{
-#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
-#ifdef ENABLE_NLS
- Inkscape::initialize_gettext();
-#endif
-
- 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);
- }
-
- LIBXML_TEST_VERSION
-
- Inkscape::GC::init();
- Inkscape::Preferences::get(); // ensure preferences are initialized
-
- Inkscape::Application::create(argv[0], true);
-
- if(options.filenames.empty())
- {
- g_print("%s", context.get_help().c_str());
- exit(EXIT_FAILURE);
- }
-
- 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 */
- }
-
- SPSlideShow ss(valid_files, options.fullscreen, options.timer, options.scale);
- main_instance.run();
-
- return 0;
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/svg-view-slideshow.cpp b/src/svg-view-slideshow.cpp
deleted file mode 100644
index f405f58c7..000000000
--- a/src/svg-view-slideshow.cpp
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Inkscape - an ambitious vector drawing program
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Frank Felfe <innerspace@iname.com>
- * Davide Puricelli <evo@debian.org>
- * Mitsuru Oka <oka326@parkcity.ne.jp>
- * Masatake YAMATO <jet@gyve.org>
- * F.J.Franklin <F.J.Franklin@sheffield.ac.uk>
- * Michael Meeks <michael@helixcode.com>
- * Chema Celorio <chema@celorio.com>
- * Pawel Palucha
- * ... and various people who have worked with various projects
- * Abhishek Sharma
- *
- * Copyright (C) 1999-2002 authors
- * Copyright (C) 2001-2002 Ximian, Inc.
- *
- * Inkscape authors:
- * Johan Ceuppens
- *
- * Copyright (C) 2004 Inkscape authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <glibmm/main.h>
-#include <gtkmm/button.h>
-#include <gtkmm/buttonbox.h>
-#include <gtkmm/image.h>
-#include <gtkmm/main.h>
-
-#include <utility>
-
-#include "document.h"
-#include "helper/icon-loader.h"
-#include "ui/icon-names.h"
-#include "ui/monitor.h"
-#include "util/units.h"
-
-#include "svg-view.h"
-#include "svg-view-slideshow.h"
-#include "svg-view-widget.h"
-
-
-SPSlideShow::SPSlideShow(std::vector<Glib::ustring> slides, bool full_screen, int timer, double scale)
- : _slides(std::move(slides))
- , _current(0)
- , _doc(SPDocument::createNewDoc(_slides[0].c_str(), true, false))
- , _fullscreen(full_screen)
- , _timer(timer)
- , _scale(scale)
- , _view(nullptr)
- , _ctrlwin(nullptr)
-{
- // setup initial document
- Gdk::Rectangle monitor_geometry = Inkscape::UI::get_monitor_geometry_primary(); // TODO: is inkview always launched on primary monitor?
- set_default_size(MIN ((int)_doc->getWidth().value("px")*_scale, monitor_geometry.get_width() - 64),
- MIN ((int)_doc->getHeight().value("px")*_scale, monitor_geometry.get_height() - 64));
-
- _view = sp_svg_view_widget_new(_doc);
- SP_SVG_VIEW_WIDGET(_view)->setResize( false, _doc->getWidth().value("px"), _doc->getHeight().value("px") );
- gtk_widget_show (_view);
- add(*Glib::wrap(_view));
-
- update_title();
- show();
- if(_fullscreen) {
- fullscreen();
- }
-
- // connect signals
- this->signal_key_press_event().connect(sigc::mem_fun(*this, &SPSlideShow::key_press), false);
- this->signal_delete_event().connect(sigc::mem_fun(*this, &SPSlideShow::main_delete), false);
- if(_timer) {
- Glib::signal_timeout().connect_seconds(sigc::mem_fun(*this, &SPSlideShow::timer_callback), _timer);
- }
-}
-
-
-
-/**
- * @brief Show the control buttons (next, previous etc) for the application
- */
-void SPSlideShow::control_show()
-{
- if (!_ctrlwin) {
- _ctrlwin = new Gtk::Window();
- _ctrlwin->set_resizable(false);
- _ctrlwin->set_transient_for(*this);
-
- _ctrlwin->signal_key_press_event().connect(sigc::mem_fun(*this, &SPSlideShow::key_press), false);
- _ctrlwin->signal_delete_event().connect(sigc::mem_fun(*this, &SPSlideShow::ctrlwin_delete), false);
-
- auto t = Gtk::manage(new Gtk::ButtonBox());
- _ctrlwin->add(*t);
-
- auto btn_go_first = Gtk::manage(new Gtk::Button());
- auto img_go_first = Gtk::manage(sp_get_icon_image(INKSCAPE_ICON("go-first"), Gtk::ICON_SIZE_BUTTON));
- btn_go_first->set_image(*img_go_first);
- t->add(*btn_go_first);
- btn_go_first->signal_clicked().connect(sigc::mem_fun(*this, &SPSlideShow::goto_first));
-
- auto btn_go_prev = Gtk::manage(new Gtk::Button());
- auto img_go_prev = Gtk::manage(sp_get_icon_image(INKSCAPE_ICON("go-previous"), Gtk::ICON_SIZE_BUTTON));
-
- btn_go_prev->set_image(*img_go_prev);
- t->add(*btn_go_prev);
- btn_go_prev->signal_clicked().connect(sigc::mem_fun(*this, &SPSlideShow::show_prev));
-
- auto btn_go_next = Gtk::manage(new Gtk::Button());
- auto img_go_next = Gtk::manage(sp_get_icon_image(INKSCAPE_ICON("go-next"), Gtk::ICON_SIZE_BUTTON));
-
- btn_go_next->set_image(*img_go_next);
- t->add(*btn_go_next);
- btn_go_next->signal_clicked().connect(sigc::mem_fun(*this, &SPSlideShow::show_next));
-
- auto btn_go_last = Gtk::manage(new Gtk::Button());
- auto img_go_last = Gtk::manage(sp_get_icon_image(INKSCAPE_ICON("go-last"), Gtk::ICON_SIZE_BUTTON));
- btn_go_last->set_image(*img_go_last);
- t->add(*btn_go_last);
- btn_go_last->signal_clicked().connect(sigc::mem_fun(*this, &SPSlideShow::goto_last));
-
- _ctrlwin->show_all();
- } else {
- _ctrlwin->present();
- }
-}
-
-void SPSlideShow::waiting_cursor()
-{
- auto display = Gdk::Display::get_default();
- auto waiting = Gdk::Cursor::create(display, Gdk::WATCH);
- get_window()->set_cursor(waiting);
-
- if (_ctrlwin) {
- _ctrlwin->get_window()->set_cursor(waiting);
- }
- while(Gtk::Main::events_pending()) {
- Gtk::Main::iteration();
- }
-}
-
-void SPSlideShow::normal_cursor()
-{
- get_window()->set_cursor();
- if (_ctrlwin) {
- _ctrlwin->get_window()->set_cursor();
- }
-}
-
-
-/// Update the window title with current document name
-void SPSlideShow::update_title()
-{
- Glib::ustring title(_doc->getName());
- if (_slides.size() > 1) {
- title += Glib::ustring::compose(" (%1/%2)", _current+1, _slides.size());
- }
-
- set_title(title);
-}
-
-void SPSlideShow::set_document(SPDocument *doc,
- int current)
-{
- if (doc && doc != _doc) {
- doc->ensureUpToDate();
- reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (_view))->setDocument (doc);
- _doc = doc;
- _current = current;
- update_title();
- }
-}
-
-/**
- * @brief Show the next file in the slideshow
- */
-void SPSlideShow::show_next()
-{
- waiting_cursor();
-
- SPDocument *doc = nullptr;
- while (!doc && (_current < _slides.size() - 1)) {
- doc = SPDocument::createNewDoc ((_slides[++_current]).c_str(), TRUE, false);
- }
-
- set_document(doc, _current);
- normal_cursor();
-}
-
-/**
- * @brief Show the previous file in the slideshow
- */
-void SPSlideShow::show_prev()
-{
- waiting_cursor();
-
- SPDocument *doc = nullptr;
- while (!doc && (_current > 0)) {
- doc = SPDocument::createNewDoc ((_slides[--_current]).c_str(), TRUE, false);
- }
-
- set_document(doc, _current);
- normal_cursor();
-}
-
-/**
- * @brief Switch to first slide in slideshow
- */
-void SPSlideShow::goto_first()
-{
- waiting_cursor();
-
- SPDocument *doc = nullptr;
- int current = 0;
- while ( !doc && (current < _slides.size() - 1)) {
- doc = SPDocument::createNewDoc((_slides[current++]).c_str(), TRUE, false);
- }
-
- set_document(doc, current - 1);
-
- normal_cursor();
-}
-
-/**
- * @brief Switch to last slide in slideshow
- */
-void SPSlideShow::goto_last()
-{
- waiting_cursor();
-
- SPDocument *doc = nullptr;
- int current = _slides.size() - 1;
- while (!doc && (current >= 0)) {
- doc = SPDocument::createNewDoc((_slides[current--]).c_str(), TRUE, false);
- }
-
- set_document(doc, current + 1);
-
- normal_cursor();
-}
-
-bool SPSlideShow::timer_callback()
-{
- show_next();
-
- // stop the timer if the last slide is reached
- if (_current == _slides.size()-1) {
- return false;
- } else {
- return true;
- }
-}
-
-bool SPSlideShow::ctrlwin_delete (GdkEventAny */*event*/)
-{
- if(_ctrlwin) delete _ctrlwin;
- _ctrlwin = nullptr;
- return true;
-}
-
-bool SPSlideShow::main_delete (GdkEventAny */*event*/)
-{
- Gtk::Main::quit();
- return true;
-}
-
-bool SPSlideShow::key_press(GdkEventKey* event)
-{
- switch (event->keyval) {
- case GDK_KEY_Up:
- case GDK_KEY_Home:
- goto_first();
- break;
- case GDK_KEY_Down:
- case GDK_KEY_End:
- goto_last();
- break;
- case GDK_KEY_F11:
- if (_fullscreen) {
- unfullscreen();
- _fullscreen = false;
- } else {
- fullscreen();
- _fullscreen = true;
- }
- break;
- case GDK_KEY_Return:
- control_show();
- break;
- case GDK_KEY_KP_Page_Down:
- case GDK_KEY_Page_Down:
- case GDK_KEY_Right:
- case GDK_KEY_space:
- show_next();
- break;
- case GDK_KEY_KP_Page_Up:
- case GDK_KEY_Page_Up:
- case GDK_KEY_Left:
- case GDK_KEY_BackSpace:
- show_prev();
- break;
- case GDK_KEY_Escape:
- case GDK_KEY_q:
- case GDK_KEY_Q:
- Gtk::Main::quit();
- break;
- default:
- break;
- }
- return false;
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/svg-view-slideshow.h b/src/svg-view-slideshow.h
deleted file mode 100644
index 9de62ae9e..000000000
--- a/src/svg-view-slideshow.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Inkscape - an ambitious vector drawing program
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Frank Felfe <innerspace@iname.com>
- * Davide Puricelli <evo@debian.org>
- * Mitsuru Oka <oka326@parkcity.ne.jp>
- * Masatake YAMATO <jet@gyve.org>
- * F.J.Franklin <F.J.Franklin@sheffield.ac.uk>
- * Michael Meeks <michael@helixcode.com>
- * Chema Celorio <chema@celorio.com>
- * Pawel Palucha
- * ... and various people who have worked with various projects
- * Abhishek Sharma
- *
- * Copyright (C) 1999-2002 authors
- * Copyright (C) 2001-2002 Ximian, Inc.
- *
- * Inkscape authors:
- * Johan Ceuppens
- *
- * Copyright (C) 2004 Inkscape authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-
-#ifndef SEEN_SP_SVG_SLIDESHOW_H
-#define SEEN_SP_SVG_SLIDESHOW_H
-
-#include <gtkmm/applicationwindow.h>
-
-/**
- * The main application window for the slideshow
- */
-class SPSlideShow : public Gtk::ApplicationWindow {
-public:
- SPSlideShow(std::vector<Glib::ustring> slides,
- bool fullscreen,
- int timer,
- double scale);
-
-private:
- std::vector<Glib::ustring> _slides; // list of filenames for each slide
- int _current; // index of the currently displayed slide
- SPDocument *_doc; // parsed SPDocument of the currently displayed slide
- bool _fullscreen; // is window fullscreen? (also controls whether to launch in fullscreen mode)
- int _timer; // time after which slides are automatically changed (in seconds)
- double _scale; // scale factor for images
- GtkWidget *_view; // the canvas to which the images are drawn
- Gtk::Window *_ctrlwin; // window containing slideshow control buttons
-
- void control_show();
- void show_next();
- void show_prev();
- void goto_first();
- void goto_last();
- bool timer_callback();
-
- bool key_press (GdkEventKey *event);
- bool main_delete (GdkEventAny *event);
- bool ctrlwin_delete (GdkEventAny *event);
-
- void update_title();
- void waiting_cursor();
- void normal_cursor();
- void set_document(SPDocument *doc,
- int current);
-};
-
-#endif // SEEN_SP_SVG_SLIDESHOW_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :