summaryrefslogtreecommitdiffstats
path: root/src/inkscape-application.h
blob: e66ae12c577d0a97ab9c5799cf44c5571f136a93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * The main Inkscape application.
 *
 * Copyright (C) 2018 Tavmjong Bah
 *
 * The contents of this file may be used under the GNU General Public License Version 2 or later.
 *
 */

#ifndef INKSCAPE_APPLICATION_H
#define INKSCAPE_APPLICATION_H

/*
 * The main Inkscape application.
 *
 * Copyright (C) 2018 Tavmjong Bah
 *
 * The contents of this file may be used under the GNU General Public License Version 2 or later.
 *
 */

#include <gtkmm.h>

#include "document.h"
#include "selection.h"

#include "actions/actions-effect-data.h"
#include "actions/actions-extra-data.h"
#include "actions/actions-hint-data.h"
#include "io/file-export-cmd.h"   // File export (non-verb)

typedef std::vector<std::pair<std::string, Glib::VariantBase> > action_vector_t;

class InkscapeWindow;
class SPDocument;
class SPDesktop;

class InkscapeApplication
{
    Glib::RefPtr<Gio::Application> _gio_application;

public:
    /// Singleton instance
    static InkscapeApplication &singleton();
    /// Singleton instance, if it exists (will not create it)
    static InkscapeApplication *instance();

    /// The Gtk application instance, or NULL if running headless without display
    Gtk::Application *gtk_app() { return dynamic_cast<Gtk::Application *>(_gio_application.get()); }
    /// The Gio application instance, never NULL
    Gio::Application *gio_app() { return _gio_application.get(); }

    InkscapeWindow *create_window(SPDocument *document, bool replace);
    void create_window(const Glib::RefPtr<Gio::File> &file = Glib::RefPtr<Gio::File>());
    bool destroy_window(InkscapeWindow *window, bool keep_alive = false);
    bool destroy_all();
    void print_action_list();

    void on_startup2();
    InkFileExportCmd *file_export() { return &_file_export; }
    int on_handle_local_options(const Glib::RefPtr<Glib::VariantDict> &options);
    void on_new();
    void on_quit(); // Check for data loss.
    void on_quit_immediate(); // Don't check for data loss.

    // Gio::Actions need to know what document, selection, view to work on.
    // In headless mode, these are set for each file processed.
    // With GUI, these are set everytime the cursor enters an InkscapeWindow.
    SPDocument*           get_active_document() { return _active_document; };
    void                  set_active_document(SPDocument* document);

    Inkscape::Selection*  get_active_selection() { return _active_selection; }
    void                  set_active_selection(Inkscape::Selection* selection)
                                                               {_active_selection = selection;};

    // A view should track selection and canvas to document transform matrix. This is partially
    // redundant with the selection functions above. Maybe we should get rid of view altogether.
    // Canvas to document transform matrix should be stored in InkscapeWindow.
    Inkscape::UI::View::View* get_active_view() { return _active_view; }
    void                  set_active_view(Inkscape::UI::View::View* view) { _active_view = view; }

    // The currently focused window (nominally corresponding to _active_document).
    // A window must have a document but a document may have zero, one, or more windows.
    // This will replace _active_view.
    InkscapeWindow*       get_active_window() { return _active_window; }
    void                  set_active_window(InkscapeWindow* window) { _active_window = window; }

    /****** Document ******/
    /* These should not require a GUI! */
    void                  document_add(SPDocument* document);

    SPDocument*           document_new(const std::string &Template = "");
    SPDocument*           document_open(const Glib::RefPtr<Gio::File>& file, bool *cancelled = nullptr);
    SPDocument*           document_open(const std::string& data);
    bool                  document_swap(InkscapeWindow* window, SPDocument* document);
    bool                  document_revert(SPDocument* document);
    void                  document_close(SPDocument* document);
    unsigned              document_window_count(SPDocument* document);

    /* These require a GUI! */
    void                  document_fix(InkscapeWindow* window); // MOVE TO ANOTHER FILE

    std::vector<SPDocument *> get_documents();

    /******* Window *******/
    InkscapeWindow*       window_open(SPDocument* document);
    void                  window_close(InkscapeWindow* window);
    void                  window_close_active();
    void                  startup_close();

    // Update all windows connected to a document.
    void                  windows_update(SPDocument* document);


    /****** Actions *******/
    InkActionExtraData&     get_action_extra_data()     { return _action_extra_data;  }
    InkActionEffectData&    get_action_effect_data()    { return _action_effect_data; }
    InkActionHintData&      get_action_hint_data()      { return _action_hint_data;   }
    std::map<Glib::ustring, Glib::ustring>& get_menu_label_to_tooltip_map() { return _menu_label_to_tooltip_map; };

    /******* Debug ********/
    void                  dump();

    // These are needed to cast Glib::RefPtr<Gtk::Application> to Glib::RefPtr<InkscapeApplication>,
    // Presumably, Gtk/Gio::Application takes care of ref counting in ConcreteInkscapeApplication
    // so we just provide dummies (and there is only one application in the application!).
    // void reference()   { /*printf("reference()\n"  );*/ }
    // void unreference() { /*printf("unreference()\n");*/ }

    int get_number_of_windows() const;

protected:
    bool _with_gui    = true;
    bool _batch_process = false; // Temp
    bool _use_shell   = false;
    bool _use_pipe    = false;
    bool _auto_export = false;
    int _pdf_page     = 1;
    int _pdf_poppler  = false;
    bool _use_command_line_argument = false;
    InkscapeApplication();

    // Documents are owned by the application which is responsible for opening/saving/exporting. WIP
    // std::vector<SPDocument*> _documents;   For a true headless version
    std::map<SPDocument*, std::vector<InkscapeWindow*> > _documents;

    // We keep track of these things so we don't need a window to find them (for headless operation).
    SPDocument*               _active_document   = nullptr;
    Inkscape::Selection*      _active_selection  = nullptr;
    Inkscape::UI::View::View* _active_view       = nullptr;
    InkscapeWindow*           _active_window     = nullptr;

    InkFileExportCmd _file_export;

    // Actions from the command line or file.
    // Must read in on_handle_local_options() but parse in on_startup(). This is done as we must
    // have a valid app before initializing extensions which must be done before parsing.
    Glib::ustring _command_line_actions_input;
    action_vector_t _command_line_actions;

    // Extra data associated with actions (Label, Section, Tooltip/Help).
    InkActionExtraData  _action_extra_data;
    InkActionEffectData  _action_effect_data;
    InkActionHintData   _action_hint_data;
    std::map<Glib::ustring, Glib::ustring> _menu_label_to_tooltip_map; // Needed due to the
                                                                       // inabilitiy to get the
                                                                       // corresponding Gio::Action
                                                                       // from a Gtk::MenuItem.
    void on_startup();
    void on_activate();
    void on_open(const Gio::Application::type_vec_files &files, const Glib::ustring &hint);
    void process_document(SPDocument* document, std::string output_path);
    void parse_actions(const Glib::ustring& input, action_vector_t& action_vector);

    void on_about();
    void shell();

    void _start_main_option_section(const Glib::ustring& section_name = "");
};

#endif // INKSCAPE_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 :