diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2018-10-28 17:07:34 +0000 |
|---|---|---|
| committer | Tavmjong Bah <tavmjong@free.fr> | 2018-11-04 09:37:02 +0000 |
| commit | 422ea274ba9ed5b038c767bceead4c38d8d78152 (patch) | |
| tree | dbe228fdc5e4fdd99ec70a9ca1bb98e50fee69b2 /src | |
| parent | Merge branch 'fix-knot-selection' of gitlab.com:ao2/inkscape (diff) | |
| download | inkscape-422ea274ba9ed5b038c767bceead4c38d8d78152.tar.gz inkscape-422ea274ba9ed5b038c767bceead4c38d8d78152.zip | |
Rewrite of inkview using InkApplication (Gtk::Application).
Use Gio::File for accessing files.
Use Gio options to handle command line arguments.
Use Gio::Action's.
Use Gtk::Builder for control window.
Only create SPDocument when requested for display and then cache it (should speed up start-up).
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | src/inkview-application.cpp | 139 | ||||
| -rw-r--r-- | src/inkview-application.h | 54 | ||||
| -rw-r--r-- | src/inkview-main.cpp | 28 | ||||
| -rw-r--r-- | src/inkview-options-group.cpp | 56 | ||||
| -rw-r--r-- | src/inkview-options-group.h | 35 | ||||
| -rw-r--r-- | src/inkview-window.cpp | 412 | ||||
| -rw-r--r-- | src/inkview-window.h | 64 | ||||
| -rw-r--r-- | src/inkview.cpp | 187 | ||||
| -rw-r--r-- | src/svg-view-slideshow.cpp | 325 | ||||
| -rw-r--r-- | src/svg-view-slideshow.h | 83 |
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 : |
