Commit 5e0460cb authored by Cédric Bellegarde's avatar Cédric Bellegarde

Enhanced pages overlay widget

parent 31486523
......@@ -79,11 +79,15 @@
color: @theme_fg_color;
}
.uribar-title {
.no-background {
background-color: transparent;
background-image: none;
}
.no-border {
border: none;
}
.close-button {
border: 2px solid white;
background-color: black;
......
......@@ -28,13 +28,13 @@ app_PYTHON = \
menu_history.py\
menu_pages.py\
mozilla_sync.py\
page_overlay_child.py\
pages_manager.py\
pages_manager_child.py\
pages_manager_flowbox.py\
pages_manager_flowbox_child.py\
pages_manager_listbox.py\
pages_manager_listbox_child.py\
pages_overlay.py\
popover_cookies.py\
popover_credentials.py\
popover_downloads.py\
......
......@@ -34,7 +34,7 @@ class Container(Gtk.Overlay):
Gtk.Overlay.__init__(self)
self.__window = window
self.__history_queue = []
self.__overlay_widget = None
self.__pages_overlay = None
self.__popover = WebViewPopover(window)
if El().sync_worker is not None:
El().sync_worker.connect("sync-finished",
......@@ -84,10 +84,12 @@ class Container(Gtk.Overlay):
self.add_view(webview, parent, window_type)
if uri is not None:
if load:
panel_mode = El().settings.get_enum("panel-mode")
# Do not load uri until we are on screen
GLib.idle_add(webview.load_uri, uri)
# Notify user about new window
if window_type == Gdk.WindowType.OFFSCREEN:
if window_type == Gdk.WindowType.OFFSCREEN and\
panel_mode == PanelMode.NONE:
GLib.idle_add(
self.__add_overlay_view, webview)
else:
......@@ -161,6 +163,8 @@ class Container(Gtk.Overlay):
view.set_size_request(-1, -1)
self.__stack.add(view)
self.__stack.set_visible_child(view)
if self.__pages_overlay is not None:
self.__pages_overlay.destroy_child(view)
def stop(self):
"""
......@@ -214,6 +218,9 @@ class Container(Gtk.Overlay):
if self.__pages_manager is not None:
views = self.__pages_manager.views
self.__pages_manager.destroy()
if self.__pages_overlay is not None:
self.__pages_overlay.destroy()
self.__pages_overlay = None
if panel_mode == PanelMode.NONE:
from eolie.pages_manager_flowbox import PagesManagerFlowBox
self.__pages_manager = PagesManagerFlowBox(self.__window)
......@@ -329,13 +336,13 @@ class Container(Gtk.Overlay):
Add an overlay view
@param webview as WebView
"""
from eolie.page_overlay_child import PageOverlayChild
from eolie.pages_overlay import PagesOverlay
view = self.get_view_for_webview(webview)
if self.__overlay_widget is None:
self.__overlay_widget = PageOverlayChild(view, self.__window)
self.add_overlay(self.__overlay_widget)
else:
self.__overlay_widget.set_view(view)
if self.__pages_overlay is None:
self.__pages_overlay = PagesOverlay(self.__window)
self.add_overlay(self.__pages_overlay)
self.__pages_overlay.show()
self.__pages_overlay.add_child(view)
def __on_new_page(self, webview, uri, window_type):
"""
......
# Copyright (c) 2017 Cedric Bellegarde <cedric.bellegarde@adishatz.org>
# 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/>.
from gi.repository import Gtk, GLib, WebKit2
from eolie.pages_manager_flowbox_child import PagesManagerFlowBoxChild
class PageOverlayChild(PagesManagerFlowBoxChild):
"""
A movable PagesManagerFlowBoxChild
"""
__TIMEOUT = 15000
def __init__(self, view, window):
"""
Init child
@param view as View
@param window as Window
"""
PagesManagerFlowBoxChild.__init__(self, view, window)
self.__x_root = 0
self.__moved = False
self.__timeout_id = None
self.__destroyed_id = None
self.get_style_context().add_class("box-dark-shadow")
self.set_property("halign", Gtk.Align.START)
self.set_property("valign", Gtk.Align.END)
self.show()
view.webview.connect("destroy", self.__on_webview_destroy)
def set_view(self, view):
"""
Set a new view
@param view as View
"""
if self.__timeout_id is not None:
GLib.source_remove(self.__timeout_id)
self.__timeout_id = None
if self.__destroyed_id is not None:
self._view.webview.disconnect(self.__destroyed_id)
PagesManagerFlowBoxChild.set_view(self, view)
self.__destroyed_id = view.webview.connect("destroy",
self.__on_webview_destroy)
self.update()
self.show()
#######################
# PROTECTED #
#######################
def _on_button_press_event(self, eventbox, event):
"""
Hide popover or close view
@param eventbox as Gtk.EventBox
@param event as Gdk.EventButton
"""
self.__moved = False
self._widget.connect("motion-notify-event",
self.__on_motion_notify_event)
self.__x_root = event.x
PagesManagerFlowBoxChild._on_button_press_event(self,
eventbox,
event)
def _on_button_release_event(self, eventbox, event):
"""
@param eventbox as Gtk.EventBox
@param event as Gdk.Event
"""
self._widget.disconnect_by_func(self.__on_motion_notify_event)
ret = PagesManagerFlowBoxChild._on_button_release_event(self,
eventbox,
event)
if not self.__moved and not ret:
if event.button == 1:
self._window.container.set_visible_view(self._view)
self._window.container.set_expose(False)
self._window.container.pages_manager.update_visible_child()
self.hide()
if self.__destroyed_id is not None:
self._view.webview.disconnect(self.__destroyed_id)
self.__destroyed_id = None
if self.__timeout_id is not None:
GLib.source_remove(self.__timeout_id)
self.__timeout_id = None
def _on_close_button_press_event(self, eventbox, event):
"""
Hide self
@param eventbox as Gtk.EventBox
@param event as Gdk.Event
"""
ret = PagesManagerFlowBoxChild._on_close_button_press_event(self,
eventbox,
event)
if ret:
GLib.idle_add(self.hide)
if self.__destroyed_id is not None:
self._view.webview.disconnect(self.__destroyed_id)
self.__destroyed_id = None
if self.__timeout_id is not None:
GLib.source_remove(self.__timeout_id)
self.__timeout_id = None
def _on_load_changed(self, webview, event):
"""
Update widget content
@param webview as WebView
@param event as WebKit2.LoadEvent
"""
PagesManagerFlowBoxChild._on_load_changed(self, webview, event)
if event == WebKit2.LoadEvent.FINISHED:
self.__timeout_id = GLib.timeout_add(self.__TIMEOUT,
self.__hide_timeout)
#######################
# PRIVATE #
#######################
def __hide_timeout(self):
"""
Hide by opacity change
@param count as int
"""
GLib.idle_add(self.hide)
if self.__destroyed_id is not None:
self._view.webview.disconnect(self.__destroyed_id)
self.__destroyed_id = None
self.__timeout_id = None
def __on_motion_notify_event(self, eventbox, event):
"""
Move widget
@param eventbox as Gtk.EventBox
@param event as Gdk.EventMotion
"""
self.__moved = True
if event.x_root > self.__x_root:
self.set_property("halign", Gtk.Align.END)
else:
self.set_property("halign", Gtk.Align.START)
self.__x_root = event.x_root
def __on_webview_destroy(self, webview):
"""
Destroy self and disconnect signals
@param webview as WebView
"""
self.__destroyed_id = None
self.disconnect_signals()
if webview == self._view.webview:
self.hide()
......@@ -98,7 +98,6 @@ class PagesManager(Gtk.EventBox):
"""
# We force child to disconnect from view
for child in self._box.get_children():
child.disconnect_signals()
child.destroy()
Gtk.EventBox.destroy(self)
......
......@@ -54,22 +54,7 @@ class PagesManagerChild:
self.set_property("has-tooltip", True)
self.connect("query-tooltip", self.__on_query_tooltip)
self.connect_signals()
def update(self):
"""
Update child title and favicon
"""
title = self._view.webview.get_title()
if title is None:
title = self._view.webview.get_uri()
self._title.set_text(title)
self.__set_favicon()
def connect_signals(self):
"""
Connect signals to view
"""
self.connect("destroy", self.__on_destroy)
self.__connected_ids.append(
self._view.webview.connect(
"notify::favicon",
......@@ -91,13 +76,15 @@ class PagesManagerChild:
"load-changed",
self._on_load_changed))
def disconnect_signals(self):
def update(self):
"""
Disconnect signals
Update child title and favicon
"""
while self.__connected_ids:
connected_id = self.__connected_ids.pop(0)
self._view.webview.disconnect(connected_id)
title = self._view.webview.get_title()
if title is None:
title = self._view.webview.get_uri()
self._title.set_text(title)
self.__set_favicon()
def set_snapshot(self, uri, save):
"""
......@@ -371,3 +358,12 @@ class PagesManagerChild:
text = "<b>%s</b>\n%s" % (GLib.markup_escape_text(label),
GLib.markup_escape_text(uri))
widget.set_tooltip_markup(text)
def __on_destroy(self, widget):
"""
Disconnect signals
@param widget as Gtk.Widget
"""
while self.__connected_ids:
connected_id = self.__connected_ids.pop(0)
self._view.webview.disconnect(connected_id)
......@@ -30,10 +30,9 @@ class PagesManagerFlowBox(PagesManager):
self._box = Gtk.FlowBox.new()
self._box.set_activate_on_single_click(True)
self._box.set_selection_mode(Gtk.SelectionMode.NONE)
self._box.set_homogeneous(True)
self._box.set_max_children_per_line(1000)
self._box.show()
self._box.connect("child-activated", self.__on_child_activated)
self._box.connect("child-activated", self._on_child_activated)
self._viewport.set_property("valign", Gtk.Align.START)
self._viewport.add(self._box)
self._CHILD_CLASS = PagesManagerFlowBoxChild
......@@ -42,7 +41,7 @@ class PagesManagerFlowBox(PagesManager):
def add_child(self, view):
"""
Add child to sidebar
Add child to flowbox
@param view as View
@return child
"""
......@@ -73,10 +72,7 @@ class PagesManagerFlowBox(PagesManager):
"""
return self._box.get_child_at_index(index)
#######################
# PRIVATE #
#######################
def __on_child_activated(self, listbox, row):
def _on_child_activated(self, listbox, row):
"""
Show wanted web view
@param listbox as Gtk.ListBox
......@@ -85,3 +81,7 @@ class PagesManagerFlowBox(PagesManager):
self._window.container.set_visible_view(row.view)
self._window.container.set_expose(False)
self.update_visible_child()
#######################
# PRIVATE #
#######################
......@@ -41,16 +41,6 @@ class PagesManagerFlowBoxChild(Gtk.FlowBoxChild, PagesManagerChild):
# TODO: 12?
self.set_property("height-request", ArtSize.START_HEIGHT + 12)
def set_view(self, view):
"""
Set view
@param view as View
"""
self._image.clear()
self.disconnect_signals()
self._view = view
self.connect_signals()
#######################
# PROTECTED #
#######################
......
# Copyright (c) 2017 Cedric Bellegarde <cedric.bellegarde@adishatz.org>
# 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/>.
from gi.repository import Gtk, GLib
from eolie.pages_manager_flowbox_child import PagesManagerFlowBoxChild
from eolie.pages_manager_flowbox import PagesManagerFlowBox
class PagesManagerFlowBoxCustom(PagesManagerFlowBox):
"""
Flow box linked to a Gtk.Stack
"""
def __init__(self, window):
"""
Init stack
@param window as Window
"""
PagesManagerFlowBox.__init__(self, window)
self._box.set_max_children_per_line(1000)
self._box.set_min_children_per_line(1000)
self.get_style_context().add_class("no-background")
self.get_style_context().add_class("no-border")
self._scrolled.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.NEVER)
def add_child(self, child):
"""
Add child to flowbox
@param view as View
"""
self._box.insert(child, 0)
def pop_child(self):
"""
Pop first child
@return PagesManagerFlowBoxChild
"""
child = self._box.get_child_at_index(0)
if child is not None:
self._box.remove(child)
return child
@property
def children(self):
"""
Get children
@return [PagesManagerFlowBoxChild]
"""
return self._box.get_children()
#######################
# PROTECTED #
#######################
def _on_child_activated(self, listbox, row):
"""
Show wanted web view
@param listbox as Gtk.ListBox
@param row as PagesManagerFlowBoxChild
"""
self._window.container.set_visible_view(row.view)
self._window.container.set_expose(False)
GLib.idle_add(row.destroy)
class PagesOverlay(Gtk.EventBox):
"""
Flow box linked to a Gtk.Stack
"""
def __init__(self, window):
"""
Init stack
@param window as Window
"""
Gtk.EventBox.__init__(self)
self.__timeout_id = None
self.__window = window
self.get_style_context().add_class("no-background")
self.set_property("halign", Gtk.Align.START)
self.set_property("valign", Gtk.Align.END)
self.__pages_manager = PagesManagerFlowBoxCustom(window)
# Allow keeping button while main overlay widget is hidden
self.__fake = Gtk.Label.new(" ")
self.__fake.set_property("width-request", 24)
self.__fake.hide()
self.__grid = Gtk.Grid()
self.__grid.set_property("halign", Gtk.Align.START)
self.__grid.attach(self.__pages_manager, 1, 0, 1, 1)
self.__grid.attach(self.__fake, 2, 0, 1, 1)
self.__grid.show()
overlay = Gtk.Overlay.new()
overlay.add(self.__grid)
overlay.show()
button = Gtk.EventBox()
button.set_opacity(0.7)
button.set_property("halign", Gtk.Align.START)
button.set_property("valign", Gtk.Align.START)
button.get_style_context().add_class("close-button")
button.connect("button-press-event",
self.__on_close_button_press_event)
button.connect("enter-notify-event",
self.__on_close_enter_notify_event)
button.connect("leave-notify-event",
self.__on_close_leave_notify_event)
self.__image = Gtk.Image.new_from_icon_name("go-down-symbolic",
Gtk.IconSize.BUTTON)
self.__image.set_margin_start(5)
self.__image.set_margin_end(5)
self.__image.set_margin_top(5)
self.__image.set_margin_bottom(5)
self.__image.show()
button.add(self.__image)
button.show()
overlay.add_overlay(button)
self.connect("enter-notify-event", self.__on_enter_notify_event)
self.connect("leave-notify-event", self.__on_leave_notify_event)
self.connect("button-press-event", self.__on_button_press_event)
self.add(overlay)
def add_child(self, view):
"""
Add child to sidebar
@param view as View
@return child
"""
current = self.__grid.get_child_at(0, 0)
if current is not None:
current.disconnect_by_func(self.__on_child_destroy)
self.__grid.remove(current)
self.__pages_manager.add_child(current)
child = PagesManagerFlowBoxChild(view, self.__window)
child.get_style_context().add_class("box-dark-shadow")
child.connect("destroy", self.__on_child_destroy)
child.show()
self.__grid.attach(child, 0, 0, 1, 1)
def destroy_child(self, view):
"""
Destroy child associated with view if exists
@param view as View
"""
children = [self.__grid.get_child_at(0, 0)] +\
self.__pages_manager.children
for child in children:
if child is None:
continue
if child.view == view:
GLib.idle_add(child.destroy)
return
#######################
# PROTECTED #
#######################
#######################
# PRIVATE #
#######################
def __on_child_destroy(self, widget):
"""
Take another widget from pages manager
@param widget as Gtk.Widget
"""
self.__grid.remove(widget)
child = self.__pages_manager.pop_child()
if child is None:
self.hide()
self.__fake.hide()
else:
child.connect("destroy", self.__on_child_destroy)
self.__grid.attach(child, 0, 0, 1, 1)
def __on_button_press_event(self, eventbox, event):
"""
Hide popover or close view
@param eventbox as Gtk.EventBox
@param event as Gdk.Event
"""
current = self.__grid.get_child_at(0, 0)
if current is not None and event.button == 1:
self.__window.container.set_visible_view(current.view)
self.__window.container.set_expose(False)
self.__grid.hide()
def __on_enter_notify_event(self, eventbox, event):
"""
Reveal children
@param eventbox as Gtk.EventBox
@param event as Gdk.Event
"""
self.__pages_manager.show()
self.set_property("halign", Gtk.Align.FILL)
def __on_leave_notify_event(self, eventbox, event):
"""
Unreveal children
@param eventbox as Gtk.EventBox
@param event as Gdk.Event
"""
allocation = eventbox.get_allocation()
if event.x <= 0 or\
event.x >= allocation.width or\
event.y <= 0 or\
event.y >= allocation.height:
self.__pages_manager.hide()
self.set_property("halign", Gtk.Align.START)
def __on_close_button_press_event(self, eventbox, event):
"""
Hide self
@param eventbox as Gtk.EventBox
@param event as Gdk.Event
"""
current = self.__grid.get_child_at(0, 0)
if self.__image.get_icon_name()[0] == "go-down-symbolic":
self.__fake.show()
self.__pages_manager.hide()
if current is not None:
current.hide()
self.__image.set_from_icon_name("go-up-symbolic",
Gtk.IconSize.BUTTON)
else:
self.__fake.hide()
self.__pages_manager.show()
if current is not None:
current.show()
self.__image.set_from_icon_name("go-down-symbolic",
Gtk.IconSize.BUTTON)
return True
def __on_close_enter_notify_event(self, eventbox, event):
"""
Reveal children
@param eventbox as Gtk.EventBox
@param event as Gdk.Event
"""
eventbox.set_opacity(1)
def __on_close_leave_notify_event(self, eventbox, event):
"""
Unreveal children
@param eventbox as Gtk.EventBox
@param event as Gdk.Event
"""
eventbox.set_opacity(0.7)
......@@ -139,7 +139,7 @@ class ToolbarTitle(Gtk.Bin):
self.set_tooltip_text(uri)
self.__input_warning_shown = False
self.__secure_content = True
self.__entry.get_style_context().remove_class('uribar-title')
self.__entry.get_style_context().remove_class('no-background')
self.__update_secure_content_indicator()
bookmark_id = El().bookmarks.get_id(uri)
if bookmark_id is not None:
......@@ -164,7 +164,7 @@ class ToolbarTitle(Gtk.Bin):
self.__placeholder.set_text(self.__uri)
if not self.__popover.is_visible():
self.__placeholder.set_opacity(0.8)
self.__entry.get_style_context().add_class('uribar-title')
self.__entry.get_style_context().add_class('no-background')
self.set_text_entry("")
def set_insecure_content(self):
......@@ -333,7 +333,7 @@ class ToolbarTitle(Gtk.Bin):
self.set_text_entry(self.__uri)
else:
self.__set_default_placeholder()
self.__entry.get_style_context().remove_class("uribar-title")
self.__entry.get_style_context().remove_class("no-background")
def _on_leave_notify(self, widget, event):
"""
......@@ -359,7 +359,7 @@ class ToolbarTitle(Gtk.Bin):
"""
if self.__popover.is_visible():
return
self.__entry.get_style_context().remove_class("uribar-title")
self.__entry.get_style_context().remove_class("no-background")
self.__entry.get_style_context().add_class("input")
webview = self.__window.container.current.webview
self.__action_image2.set_from_icon_name("edit-clear-symbolic",
......@@ -615,7 +615,7 @@ class ToolbarTitle(Gtk.Bin):
self.__placeholder.set_opacity(0.8)
parsed = urlparse(self.__uri)
if parsed.scheme in ["http", "https", "file"]:
self.__entry.get_style_context().add_class('uribar-title')
self.__entry.get_style_context().add_class('no-background')
self.set_text_entry("")
else:
self.__set_default_placeholder()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment