latexila_app.vala 11.3 KB
Newer Older
1
/*
2
 * This file is part of GNOME LaTeX.
3
 *
4
 * Copyright © 2010-2015, 2017, 2018 Sébastien Wilmet
5
 *
6
 * GNOME LaTeX is free software: you can redistribute it and/or modify
7
8
9
10
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
11
 * GNOME LaTeX is distributed in the hope that it will be useful,
12
13
14
15
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
17
 * along with GNOME LaTeX.  If not, see <http://www.gnu.org/licenses/>.
Sébastien Wilmet's avatar
Sébastien Wilmet committed
18
19
 *
 * Author: Sébastien Wilmet
20
21
 */

22
public class LatexilaApp : Gtk.Application
23
{
24
25
    static Gtk.CssProvider? _provider = null;

26
27
28
29
30
31
    private const GLib.ActionEntry[] _app_actions =
    {
        { "new-document", new_document_cb },
        { "preferences", preferences_cb },
        { "manage-build-tools", manage_build_tools_cb },
        { "help", help_cb },
32
        { "fundraising", fundraising_cb },
33
34
35
36
        { "about", about_cb },
        { "quit", quit_cb }
    };

37
    public LatexilaApp ()
Sébastien Wilmet's avatar
Sébastien Wilmet committed
38
    {
39
        Object (application_id: "org.gnome.gnome-latex");
40
        set_flags (ApplicationFlags.HANDLES_OPEN);
41
        Environment.set_application_name (Config.PACKAGE_NAME);
42
        Gtk.Window.set_default_icon_name ("gnome-latex");
Sébastien Wilmet's avatar
Sébastien Wilmet committed
43

44
45
        setup_main_option_entries ();

46
        startup.connect (startup_cb);
47
        open.connect (open_documents);
48
        shutdown.connect (shutdown_cb);
49
50
51

        Tepl.Application tepl_app = Tepl.Application.get_from_gtk_application (this);
        tepl_app.handle_activate ();
52
    }
53

54
55
56
57
58
    public static LatexilaApp get_instance ()
    {
        return GLib.Application.get_default () as LatexilaApp;
    }

59
60
    public MainWindow? get_active_main_window ()
    {
61
62
63
64
65
        Tepl.Application tepl_app = Tepl.Application.get_from_gtk_application (this);
        Gtk.ApplicationWindow? main_window = tepl_app.get_active_main_window ();

        if (main_window == null)
            return null;
66

67
        return main_window as MainWindow;
68
69
    }

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    private void setup_main_option_entries ()
    {
        bool show_version = false;
        bool new_document = false;
        bool new_window = false;

        OptionEntry[] options = new OptionEntry[4];

        options[0] = { "version", 'V', 0, OptionArg.NONE, ref show_version,
            N_("Show the application's version"), null };

        options[1] = { "new-document", 'n', 0, OptionArg.NONE, ref new_document,
            N_("Create new document"), null };

        options[2] = { "new-window", 0, 0, OptionArg.NONE, ref new_window,
85
            N_("Create a new top-level window in an existing instance of GNOME LaTeX"), null };
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

        options[3] = { null };

        add_main_option_entries (options);

        handle_local_options.connect (() =>
        {
            if (show_version)
            {
                stdout.printf ("%s %s\n", Config.PACKAGE_NAME, Config.PACKAGE_VERSION);
                return 0;
            }

            try
            {
                register ();
            }
            catch (Error e)
            {
                error ("Failed to register the application: %s", e.message);
            }

            if (new_window)
109
                activate_action ("tepl-new-window", null);
110
111
112
113
114
115
116
117

            if (new_document)
                activate_action ("new-document", null);

            return -1;
        });
    }

118
119
120
    private void startup_cb ()
    {
        hold ();
121

122
        Latexila.utils_migrate_latexila_to_gnome_latex ();
123

124
        add_action_entries (_app_actions, this);
125
        Latexila.latex_commands_add_action_infos (this);
126
127
128
129
130
131
132
133
134
135
136
137

        GLib.MenuModel manual_app_menu = get_menu_by_id ("manual-app-menu");
        if (manual_app_menu == null)
            warning ("manual-app-menu not available.");

        // The menubar contains everything, so we don't need the fallback app
        // menu on desktops that don't support app menus (e.g. on Xfce).
        if (prefers_app_menu ())
        {
            set_app_menu (manual_app_menu);
        }

138
139
140
141
142
        Latexila.utils_register_icons ();
        StockIcons.register_stock_icons ();
        setup_theme_extensions ();
        AppSettings.get_default ();
        support_backward_search ();
143
        Gtk.AccelMap.load (get_accel_filename ());
144

145
146
147
        release ();
    }

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
    private void shutdown_cb ()
    {
        hold ();

        Projects.get_default ().save ();
        MostUsedSymbols.get_default ().save ();

        /* Save accel file */
        string accel_filename = get_accel_filename ();
        File accel_file = File.new_for_path (accel_filename);
        try
        {
            Latexila.utils_create_parent_directories (accel_file);
            Gtk.AccelMap.save (accel_filename);
        }
        catch (Error error)
        {
            warning ("Error when saving accel file: %s", error.message);
        }

        release ();
Sébastien Wilmet's avatar
Sébastien Wilmet committed
169
170
    }

171
172
    private void new_document_cb ()
    {
173
        MainWindow? window = get_active_main_window ();
174
175
176
        if (window == null)
            window = create_window ();

177
        window.create_tab (true);
178
    }
179

180
181
    private void preferences_cb ()
    {
182
        PreferencesDialog.show_me (get_active_main_window ());
183
    }
184

185
186
    private void manage_build_tools_cb ()
    {
187
        new BuildToolsPreferences (get_active_main_window ());
188
    }
189

190
191
    private void help_cb ()
    {
192
193
        MainWindow? window = get_active_main_window ();

194
        try
195
        {
196
            Latexila.utils_show_uri (window, "help:gnome-latex", Gdk.CURRENT_TIME);
197
198
199
200
201
202
        }
        catch (Error e)
        {
            warning ("Impossible to open the documentation: %s", e.message);
        }
    }
203

204
    private void fundraising_cb ()
205
206
207
208
    {
        Finance.show_dialog (get_active_main_window (), false);
    }

209
210
211
    private void about_cb ()
    {
        string comments =
212
            _("GNOME LaTeX is a LaTeX editor for the GNOME desktop");
213
        string copyright = "Copyright 2009-2018 – Sébastien Wilmet";
214

215
        string website = "https://wiki.gnome.org/Apps/GNOME-LaTeX";
216

217
        string[] authors =
218
        {
219
220
221
            "Sébastien Wilmet <swilmet@gnome.org>",
            null
        };
222

223
        string[] artists =
224
        {
225
226
227
228
229
230
231
232
            "Eric Forgeot <e.forgeot@laposte.net>",
            "Sébastien Wilmet <swilmet@gnome.org>",
            "Alexander Wilms <f.alexander.wilms@gmail.com>",
            "The Kile Team http://kile.sourceforge.net/",
            "Gedit LaTeX Plugin https://wiki.gnome.org/Apps/Gedit/LaTeXPlugin",
            null
        };

233
        Gtk.show_about_dialog (get_active_main_window (),
234
            "program-name", Config.PACKAGE_NAME,
235
236
237
238
239
240
            "version", Config.PACKAGE_VERSION,
            "authors", authors,
            "artists", artists,
            "comments", comments,
            "copyright", copyright,
            "license-type", Gtk.License.GPL_3_0,
241
            "title", _("About GNOME LaTeX"),
242
243
            "translator-credits", _("translator-credits"),
            "website", website,
244
            "logo-icon-name", "gnome-latex"
245
246
        );
    }
247

248
249
250
    private void quit_cb ()
    {
        hold ();
251

252
253
        bool cont = true;
        while (cont)
254
        {
255
256
257
258
259
260
            MainWindow? main_window = get_active_main_window ();
            if (main_window == null)
                break;

            main_window.present ();
            cont = main_window.quit ();
261
        }
262

263
        if (cont)
264
        {
265
266
            while (this.active_window != null)
                this.active_window.destroy ();
267
        }
268

269
        release ();
Sébastien Wilmet's avatar
Sébastien Wilmet committed
270
    }
271

272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
    private void setup_theme_extensions ()
    {
        Gtk.Settings settings = Gtk.Settings.get_default ();
        settings.notify["gtk-theme-name"].connect (update_theme);
        update_theme ();
    }

    private void update_theme ()
    {
        Gtk.Settings settings = Gtk.Settings.get_default ();
        Gdk.Screen screen = Gdk.Screen.get_default ();

        if (settings.gtk_theme_name == "Adwaita")
        {
            if (_provider == null)
            {
                _provider = new Gtk.CssProvider ();
289
                File file = File.new_for_uri ("resource:///org/gnome/gnome-latex/ui/gnome-latex.adwaita.css");
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
                try
                {
                    _provider.load_from_file (file);
                }
                catch (Error e)
                {
                    warning ("Cannot load CSS: %s", e.message);
                }
            }

            Gtk.StyleContext.add_provider_for_screen (screen, _provider,
                Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
        }
        else if (_provider != null)
        {
            Gtk.StyleContext.remove_provider_for_screen (screen, _provider);
            _provider = null;
        }
    }

Sébastien Wilmet's avatar
Sébastien Wilmet committed
310
311
    // Get all the documents currently opened.
    public Gee.List<Document> get_documents ()
312
    {
Sébastien Wilmet's avatar
Sébastien Wilmet committed
313
        Gee.List<Document> all_documents = new Gee.LinkedList<Document> ();
Sébastien Wilmet's avatar
Sébastien Wilmet committed
314
315
        foreach (Gtk.Window window in get_windows ())
        {
316
317
318
319
320
            if (window is MainWindow)
            {
                MainWindow main_window = window as MainWindow;
                all_documents.add_all (main_window.get_documents ());
            }
Sébastien Wilmet's avatar
Sébastien Wilmet committed
321
        }
Sébastien Wilmet's avatar
Sébastien Wilmet committed
322
323

        return all_documents;
324
325
    }

Sébastien Wilmet's avatar
Sébastien Wilmet committed
326
327
    // Get all the document views.
    public Gee.List<DocumentView> get_views ()
328
    {
Sébastien Wilmet's avatar
Sébastien Wilmet committed
329
        Gee.List<DocumentView> all_views = new Gee.LinkedList<DocumentView> ();
Sébastien Wilmet's avatar
Sébastien Wilmet committed
330
331
        foreach (Gtk.Window window in get_windows ())
        {
332
333
334
335
336
            if (window is MainWindow)
            {
                MainWindow main_window = window as MainWindow;
                all_views.add_all (main_window.get_views ());
            }
Sébastien Wilmet's avatar
Sébastien Wilmet committed
337
        }
338

Sébastien Wilmet's avatar
Sébastien Wilmet committed
339
340
        return all_views;
    }
341

342
    public MainWindow create_window ()
343
    {
344
345
        Tepl.AbstractFactoryVala factory = Tepl.AbstractFactory.get_singleton ()
            as Tepl.AbstractFactoryVala;
346

347
        return factory.create_main_window_vala (this) as MainWindow;
348
    }
349

350
    public void open_documents (File[] files)
351
    {
352
        MainWindow? main_window = get_active_main_window ();
353
354
        if (main_window == null)
            main_window = create_window ();
355

356
        bool jump_to = true;
357
        foreach (File file in files)
358
        {
359
            main_window.open_document (file, jump_to);
360
            jump_to = false;
361
        }
362

363
        main_window.present ();
364
    }
365
366
367
368

    private string get_accel_filename ()
    {
        return Path.build_filename (Environment.get_user_config_dir (),
369
            "gnome-latex", "accels");
370
    }
Sébastien Wilmet's avatar
Sébastien Wilmet committed
371
372
373
374
375
376
377
378

    private void support_backward_search ()
    {
        Latexila.Synctex synctex = Latexila.Synctex.get_instance ();

        synctex.backward_search.connect ((tex_uri, line, timestamp) =>
        {
            File tex_file = File.new_for_uri (tex_uri);
379
            if (!tex_file.query_exists ())
Sébastien Wilmet's avatar
Sébastien Wilmet committed
380
381
382
383
384
            {
                warning (@"Backward search: the file \"$tex_uri\" doesn't exist.");
                return;
            }

385
386
387
388
389
            // TODO choose the right MainWindow, if tex_file is already opened
            // in another window.
            MainWindow? main_window = get_active_main_window ();
            if (main_window != null)
            {
390
                main_window.jump_to_file_position (tex_file, line, line);
391
392
                main_window.present_with_time (timestamp);
            }
Sébastien Wilmet's avatar
Sébastien Wilmet committed
393
394
        });
    }
395
}