1# Copyright (c) 2017-2021 Cedric Bellegarde <cedric.bellegarde@adishatz.org>
2# This program is free software: you can redistribute it and/or modify
3# it under the terms of the GNU General Public License as published by
4# the Free Software Foundation, either version 3 of the License, or
5# (at your option) any later version.
6# This program is distributed in the hope that it will be useful,
7# but WITHOUT ANY WARRANTY; without even the implied warranty of
8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9# GNU General Public License for more details.
10# You should have received a copy of the GNU General Public License
11# along with this program. If not, see <http://www.gnu.org/licenses/>.
12
13from gi.repository import Gtk, WebKit2
14
15
16class WebViewPopover(Gtk.Popover):
17    """
18        Show a popover with a webview stack
19    """
20
21    def __init__(self, window):
22        """
23            Init popover
24            @param window as Window
25        """
26        Gtk.Popover.__init__(self)
27        self.set_modal(False)
28        window.register(self, False)
29        self.__window = window
30        builder = Gtk.Builder()
31        builder.add_from_resource('/org/gnome/Eolie/PopoverWebView.ui')
32        builder.connect_signals(self)
33        self.__stack = builder.get_object("stack")
34        self.__title = builder.get_object("title")
35        self.__prev_button = builder.get_object("prev_button")
36        self.__next_button = builder.get_object("next_button")
37        self.__spinner = builder.get_object("spinner")
38        self.__combobox = builder.get_object("combobox")
39        self.__label = builder.get_object("label")
40        self.add(builder.get_object("widget"))
41        self.connect("closed", self.__on_closed)
42
43    def add_webview(self, webview):
44        """
45            Add view to popover
46            @param webview as WebView
47        """
48        position = len(self.__stack.get_children())
49        self.__stack.add(webview)
50        self.__stack.set_visible_child(webview)
51        webview.connect("close", self.__on_webview_close)
52        webview.connect("title-changed", self.__on_webview_title_changed)
53        webview.connect("load-changed", self.__on_webview_load_changed)
54        title = webview.title or webview.uri or ""
55        self.__combobox.append(str(webview), title)
56
57        size = self.__window.get_size()
58        width = min(800, size[0] * 0.8)
59        height = min(800, size[1] * 0.6)
60        self.set_size_request(width, height)
61
62        if position == 0:
63            self.__label.set_text(title)
64            self.__label.show()
65            self.__combobox.set_active_id(str(webview))
66            self.__combobox.hide()
67        else:
68            self.__label.hide()
69            self.__combobox.show()
70
71#######################
72# PROTECTED           #
73#######################
74    def _on_combobox_changed(self, combobox):
75        """
76            Update visible webview
77            @param combobox as Gtk.ComboBoxText
78        """
79        active_id = combobox.get_active_id()
80        for child in self.__stack.get_children():
81            if str(child) == active_id:
82                self.__stack.set_visible_child(child)
83                break
84
85#######################
86# PRIVATE             #
87#######################
88    def __get_prev_child(self):
89        """
90            Get previous child
91            @return webview
92        """
93        current = self.__stack.get_visible_child()
94        child = None
95        for webview in self.__stack:
96            if webview == current:
97                break
98            child = webview
99        return child
100
101    def __get_next_child(self):
102        """
103            Get next child
104            @return webview
105        """
106        current = self.__stack.get_visible_child()
107        at_current = False
108        child = None
109        for webview in self.__stack:
110            if at_current:
111                child = webview
112                break
113            if webview == current:
114                at_current = True
115        return child
116
117    def __on_webview_title_changed(self, webview, title):
118        """
119            Update title if webview is current
120            @param webview as WebView
121            @param title as str
122        """
123        # Search previous entry
124        position = 0
125        for child in self.__stack.get_children():
126            if webview == child:
127                break
128            position += 1
129        self.__combobox.remove(position)
130        self.__combobox.insert(position, str(webview), title)
131        self.__label.set_text(title)
132        visible = self.__stack.get_visible_child()
133        if visible == webview:
134            self.__combobox.set_active_id(str(visible))
135
136    def __on_webview_load_changed(self, webview, event):
137        """
138            Update spinner
139            @param webview as WebView
140            @param event as WebKit2.LoadEvent
141        """
142        if event == WebKit2.LoadEvent.STARTED:
143            self.__spinner.start()
144        elif event == event == WebKit2.LoadEvent.FINISHED:
145            self.__spinner.stop()
146
147    def __on_webview_close(self, webview):
148        """
149            Remove view from stack, destroy it if wanted
150            @param webview as WebView
151            @param destroy as bool
152        """
153        webview.disconnect_by_func(self.__on_webview_title_changed)
154        webview.disconnect_by_func(self.__on_webview_load_changed)
155        for child in self.__stack.get_children():
156            if child == webview:
157                self.__stack.remove(child)
158                break
159        if self.__stack.get_children():
160            pass
161        else:
162            self.hide()
163        child.destroy()
164
165    def __on_closed(self, popover):
166        """
167            Clean up popover
168            Remove children
169            @param popover as Gtk.Popover
170        """
171        for webview in self.__stack.get_children():
172            webview.destroy()
173