webview_signals_menu.py 12.8 KB
Newer Older
Cédric Bellegarde's avatar
Cédric Bellegarde committed
1
# Copyright (c) 2017-2018 Cedric Bellegarde <cedric.bellegarde@adishatz.org>
2 3 4 5 6 7 8 9 10 11 12
# This program is free software: you can redistribute it and/or modify
# 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.
# This program is distributed in the hope that it will be useful,
# 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
# along with this program. If not, see <http://www.gnu.org/licenses/>.

Cédric Bellegarde's avatar
Cédric Bellegarde committed
13
from gi.repository import Gtk, Gdk, Gio, WebKit2, GLib
14 15 16

from gettext import gettext as _
from urllib.parse import urlparse
17
from time import time
18

19
from eolie.define import App, LoadingType
20
from eolie.utils import get_snapshot
21
from eolie.search import Search
22
from eolie.logger import Logger
23 24 25 26 27 28 29 30 31 32 33 34


class WebViewMenuSignals:
    """
        Handle webview menu signals
    """

    def __init__(self):
        """
            Init class
        """
        self.connect("context-menu", self.__on_context_menu)
35 36
        self.connect("context-menu-dismissed",
                     self.__on_context_menu_dismissed)
37 38 39 40

#######################
# PRIVATE             #
#######################
41
    def __on_context_menu(self, webview, context_menu, event, hit):
42 43
        """
            Add custom items to menu
44
            @param webview as WebView
45 46 47 48
            @param context_menu as WebKit2.ContextMenu
            @param event as Gdk.Event
            @param hit as WebKit2.HitTestResult
        """
49
        parsed = urlparse(webview.uri)
50
        if parsed.scheme == "populars":
Cédric Bellegarde's avatar
Cédric Bellegarde committed
51
            context_menu.remove_all()
52
            if hit.context_is_link():
53
                action = Gio.SimpleAction(name="reload_preview")
54
                App().add_action(action)
55 56 57
                action.connect("activate",
                               self.__on_reload_preview_activate,
                               hit.get_link_uri())
58
                item = WebKit2.ContextMenuItem.new_from_gaction(
Cédric Bellegarde's avatar
Cédric Bellegarde committed
59 60 61
                    action,
                    _("Reload preview"),
                    None)
62
                context_menu.append(item)
63
                return
Cédric Bellegarde's avatar
Cédric Bellegarde committed
64 65 66
        position = 0
        for item in context_menu.get_items():
            action = item.get_stock_action()
67 68 69 70 71 72
            if action in [WebKit2.ContextMenuAction.OPEN_LINK,
                          WebKit2.ContextMenuAction.OPEN_VIDEO_IN_NEW_WINDOW,
                          WebKit2.ContextMenuAction.OPEN_AUDIO_IN_NEW_WINDOW,
                          WebKit2.ContextMenuAction.OPEN_FRAME_IN_NEW_WINDOW]:
                context_menu.remove(item)
            elif action == WebKit2.ContextMenuAction.OPEN_LINK_IN_NEW_WINDOW:
Cédric Bellegarde's avatar
Cédric Bellegarde committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
                context_menu.remove(item)
                action = Gio.SimpleAction(name="open_new_page")
                App().add_action(action)
                action.connect("activate",
                               self.__on_open_new_page_activate,
                               hit.get_link_uri(), False)
                item = WebKit2.ContextMenuItem.new_from_gaction(
                    action,
                    _("Open link in a new page"),
                    None)
                context_menu.insert(item, position)
                action = Gio.SimpleAction(name="open_new_private_page")
                App().add_action(action)
                action.connect("activate",
                               self.__on_open_new_page_activate,
                               hit.get_link_uri(), True)
                item = WebKit2.ContextMenuItem.new_from_gaction(
                    action,
                    _("Open link in a new private page"),
                    None)
                context_menu.insert(item, position + 1)
94 95 96 97 98 99 100 101 102 103 104 105 106
                action = Gio.SimpleAction(name="open_new_window")
                App().add_action(action)
                action.connect("activate",
                               self.__on_open_new_window_activate,
                               hit.get_link_uri())
                item = WebKit2.ContextMenuItem.new_from_gaction(
                    action,
                    _("Open link in a new window"),
                    None)
                context_menu.append(item)
                item = WebKit2.ContextMenuItem.new_separator()
                context_menu.insert(item, position + 2)

107 108 109 110 111 112 113
        # Get current selection
        selection = ""
        user_data = context_menu.get_user_data()
        if user_data is not None and user_data.get_string():
            selection = user_data.get_string()
        if selection and hit.context_is_selection():
            action = Gio.SimpleAction(name="search_words")
114
            App().add_action(action)
115 116 117 118
            action.connect("activate",
                           self.__on_search_words_activate,
                           selection)
            item = WebKit2.ContextMenuItem.new_from_gaction(
Cédric Bellegarde's avatar
Cédric Bellegarde committed
119 120 121
                action,
                _("Search on the Web"),
                None)
122
            context_menu.append(item)
Cédric Bellegarde's avatar
Cédric Bellegarde committed
123
        if not hit.context_is_link() and parsed.scheme in ["http", "https"]:
124 125
            item = WebKit2.ContextMenuItem.new_separator()
            context_menu.append(item)
126 127
            # Save all images
            action = Gio.SimpleAction(name="save_imgs")
128
            App().add_action(action)
129 130 131
            action.connect("activate",
                           self.__on_save_images_activate)
            item = WebKit2.ContextMenuItem.new_from_gaction(
Cédric Bellegarde's avatar
Cédric Bellegarde committed
132 133 134
                action,
                _("Save images"),
                None)
135 136 137
            context_menu.append(item)
            # Save all videos
            action = Gio.SimpleAction(name="save_videos")
138
            App().add_action(action)
139 140 141
            action.connect("activate",
                           self.__on_save_videos_activate)
            item = WebKit2.ContextMenuItem.new_from_gaction(
Cédric Bellegarde's avatar
Cédric Bellegarde committed
142 143 144
                action,
                _("Save videos"),
                None)
145 146 147
            context_menu.append(item)
            # Save page as image
            action = Gio.SimpleAction(name="save_as_image")
148
            App().add_action(action)
149 150 151
            action.connect("activate",
                           self.__on_save_as_image_activate)
            item = WebKit2.ContextMenuItem.new_from_gaction(
Cédric Bellegarde's avatar
Cédric Bellegarde committed
152 153 154
                action,
                _("Save page as image"),
                None)
155
            context_menu.append(item)
156

157 158 159 160 161 162 163
    def __on_context_menu_dismissed(self, webview):
        """
            Add custom items to menu
            @param webview as WebView
        """
        self._last_click_time = time()

164
    def __on_open_new_page_activate(self, action, variant, uri, ephemeral):
165 166
        """
            Open link in a new page
167 168
            @param action as Gio.SimpleAction
            @param variant as GLib.Variant
169
            @param uri as str
170
            @param ephemeral as bool
171 172
        """
        self._window.container.add_webview(uri,
173
                                           LoadingType.FOREGROUND,
174
                                           self.ephemeral or ephemeral)
175

176 177 178 179 180 181 182 183
    def __on_open_new_window_activate(self, action, variant, uri):
        """
            Open link in a new page
            @param action as Gio.SimpleAction
            @param variant as GLib.Variant
            @param uri as str
            @param ephemeral as bool
        """
184
        window = App().get_new_window()
185
        window.container.add_webview(uri,
186
                                     LoadingType.FOREGROUND,
187 188
                                     self.ephemeral)

189
    def __on_search_words_activate(self, action, variant, selection):
190 191
        """
            Open link in a new page
192 193
            @param action as Gio.SimpleAction
            @param variant as GLib.Variant
194 195 196 197
            @param selection as str
        """
        search = Search()
        uri = search.get_search_uri(selection)
198
        self._window.container.add_webview(uri, LoadingType.FOREGROUND)
199

200
    def __on_save_images_activate(self, action, variant):
201 202
        """
            Show images filtering popover
203 204
            @param action as Gio.SimpleAction
            @param variant as GLib.Variant
205
        """
206
        self._window.toolbar.end.save_images(self.uri,
207 208
                                             self.get_page_id())

209 210 211 212 213 214 215 216
    def __on_save_videos_activate(self, action, variant):
        """
            Show videos download popover
            @param action as Gio.SimpleAction
            @param variant as GLib.Variant
        """
        self._window.toolbar.end.save_videos(self.get_page_id())

217
    def __on_save_as_image_activate(self, action, variant):
218 219
        """
            Save image in /tmp and show it to user
220 221
            @param action as Gio.SimpleAction
            @param variant as GLib.Variant
222 223 224 225
        """
        self.get_snapshot(WebKit2.SnapshotRegion.FULL_DOCUMENT,
                          WebKit2.SnapshotOptions.NONE,
                          None,
226 227
                          self.__on_snapshot,
                          True)
228

229
    def __on_reload_preview_activate(self, action, variant, uri):
230 231
        """
            Reload preview for uri
232 233
            @param action as Gio.SimpleAction
            @param variant as GLib.Variant
234 235 236
            @param uri as str
        """
        try:
237
            webview = WebKit2.WebView.new()
238 239 240 241 242 243 244 245 246
            webview.show()
            window = Gtk.OffscreenWindow.new()
            window.set_size_request(self.get_allocated_width(),
                                    self.get_allocated_height())
            window.add(webview)
            window.show()
            webview.load_uri(uri)
            webview.connect("load-changed", self.__on_load_changed, uri)
        except Exception as e:
247 248
            Logger.error("""WebViewMenuSignals::
                            __on_reload_preview_activate(): %s""", e)
249 250 251 252 253 254 255 256 257

    def __on_load_changed(self, webview, event, uri):
        """
            Get a snapshot
            @param webview as WebView
            @param event as WebKit2.LoadEvent
            @param uri as str
        """
        if event == WebKit2.LoadEvent.FINISHED:
Cédric Bellegarde's avatar
Cédric Bellegarde committed
258 259 260 261 262 263 264 265
            GLib.timeout_add(3000,
                             webview.get_snapshot,
                             WebKit2.SnapshotRegion.FULL_DOCUMENT,
                             WebKit2.SnapshotOptions.NONE,
                             None,
                             get_snapshot,
                             self.__on_preview_snapshot,
                             webview,
266
                             uri, True)
267

268
    def __on_preview_snapshot(self, surface, webview, uri, first_pass):
269 270 271 272 273
        """
            Cache snapshot
            @param surface as cairo.Surface
            @param webview as WebKit2.WebView
            @param uri as str
274
            @param first_pass as bool
275
        """
276 277 278 279 280 281 282 283 284 285 286
        # The 32767 limit on the width/height dimensions
        # of an image surface is new in cairo 1.10,
        # try with WebKit2.SnapshotRegion.VISIBLE
        if surface is None and first_pass:
            webview.get_snapshot(WebKit2.SnapshotRegion.VISIBLE,
                                 WebKit2.SnapshotOptions.NONE,
                                 None,
                                 get_snapshot,
                                 self.__on_preview_snapshot,
                                 webview,
                                 uri, False)
287 288
        else:
            if surface is not None:
289
                App().art.save_artwork(uri, surface, "start")
290 291 292 293
                self.reload()
            window = webview.get_toplevel()
            webview.destroy()
            window.destroy()
294

295
    def __on_snapshot(self, webview, result, first_pass):
296 297 298 299
        """
            Set snapshot on main image
            @param webview as WebView
            @param result as Gio.AsyncResult
300
            @param first_pass as bool
301 302 303 304 305 306 307 308 309 310 311
        """
        try:
            snapshot = webview.get_snapshot_finish(result)
            pixbuf = Gdk.pixbuf_get_from_surface(snapshot, 0, 0,
                                                 snapshot.get_width(),
                                                 snapshot.get_height())
            pixbuf.savev("/tmp/eolie_snapshot.png", "png", [None], [None])
            Gtk.show_uri_on_window(self._window,
                                   "file:///tmp/eolie_snapshot.png",
                                   Gtk.get_current_event_time())
        except Exception as e:
312
            Logger.error("WebView::__on_snapshot(): %s", e)
313 314 315 316 317 318 319 320 321
            # The 32767 limit on the width/height dimensions
            # of an image surface is new in cairo 1.10,
            # try with WebKit2.SnapshotRegion.VISIBLE
            if first_pass:
                self.get_snapshot(WebKit2.SnapshotRegion.VISIBLE,
                                  WebKit2.SnapshotOptions.NONE,
                                  None,
                                  self.__on_snapshot,
                                  False)