1/*
2* Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com)
3*
4* This file is part of Akira.
5*
6* Akira is free software: you can redistribute it and/or modify
7* it under the terms of the GNU General Public License as published by
8* the Free Software Foundation, either version 3 of the License, or
9* (at your option) any later version.
10
11* Akira is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14* GNU General Public License for more details.
15
16* You should have received a copy of the GNU General Public License
17* along with Akira. If not, see <https://www.gnu.org/licenses/>.
18*
19* Authored by: Alessandro "Alecaddd" Castellani <castellani.ale@gmail.com>
20*/
21
22namespace Akira {
23    public Akira.Services.Settings settings;
24}
25
26public class Akira.Application : Gtk.Application {
27    public GLib.List<Window> windows;
28
29    construct {
30        flags |= ApplicationFlags.HANDLES_OPEN;
31
32        settings = new Akira.Services.Settings ();
33        windows = new GLib.List<Window> ();
34
35        application_id = Constants.APP_ID;
36    }
37
38    public override void open (File[] files, string hint) {
39        // Loop through all selected files.
40        foreach (var file in files) {
41            if (is_file_opened (file)) {
42                // Present active window with currently opened file.
43                // We don't allow opening the same file on multiple windows.
44                var window = get_window_from_file (file);
45                window.show_app ();
46                continue;
47            }
48
49            // If the current window is empty, load the file in this one.
50            var current_window = active_window as Akira.Window;
51            if (current_window != null && current_window.akira_file == null && !current_window.edited) {
52                current_window.open_file (file);
53                current_window.event_bus.file_saved (file.get_basename ());
54                continue;
55            }
56
57            // The application was requested to open some files. Be sure to
58            // initialize the theme in case it wasn't already running.
59            init_theme ();
60
61            // Open a new window.
62            var window = new Akira.Window (this);
63            this.add_window (window);
64
65            window.open_file (file);
66            window.show_app ();
67            window.event_bus.file_saved (file.get_basename ());
68        }
69    }
70
71    public Akira.Window? get_window_from_file (File file) {
72        foreach (Akira.Window window in windows) {
73            if (window.akira_file != null && window.akira_file.opened_file.get_path () == file.get_path ()) {
74                return window;
75            }
76        }
77
78        return null;
79    }
80
81    public bool is_file_opened (File file) {
82        foreach (Akira.Window window in windows) {
83            if (window.akira_file != null && window.akira_file.opened_file.get_path () == file.get_path ()) {
84                return true;
85            }
86        }
87
88        return false;
89    }
90
91    public void new_window () {
92        new Akira.Window (this).present ();
93    }
94
95    public override void window_added (Gtk.Window window) {
96        windows.append (window as Akira.Window);
97        base.window_added (window);
98    }
99
100    public override void window_removed (Gtk.Window window) {
101        windows.remove (window as Akira.Window);
102        base.window_removed (window);
103    }
104
105    /**
106     * Update the list of recently opened files in all the currently opened Windows.
107     */
108    public void update_recent_files_list () {
109        foreach (Akira.Window window in windows) {
110            window.event_bus.update_recent_files_list ();
111        }
112    }
113
114    protected override void activate () {
115        init_theme ();
116
117        var window = new Akira.Window (this);
118        this.add_window (window);
119
120        if (settings.version != Constants.VERSION) {
121            var dialog = new Akira.Dialogs.ReleaseDialog (window);
122            dialog.show_all ();
123            dialog.present ();
124
125            // Update the settings so we don't show the same dialog again.
126            settings.version = Constants.VERSION;
127        }
128
129        // Load the most recently opened/saved file.
130        if (settings.open_quick) {
131            window.action_manager.action_load_first ();
132        }
133    }
134
135    private void init_theme () {
136        // Interrupt if we have at least one existing window, meaning the theme
137        // was previously initialized.
138        if (windows.length () > 0) {
139            return;
140        }
141
142        Gtk.Settings.get_default ().set_property ("gtk-icon-theme-name", "elementary");
143        Gtk.Settings.get_default ().set_property ("gtk-theme-name", "io.elementary.stylesheet.blueberry");
144
145        weak Gtk.IconTheme default_theme = Gtk.IconTheme.get_default ();
146        default_theme.add_resource_path ("/com/github/akiraux/akira");
147    }
148}
149