Commit 3b98c25e authored by Cédric Bellegarde's avatar Cédric Bellegarde

Add a new panel mode: disabled. Fix #127

parent 62e8529b
......@@ -120,6 +120,54 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="view_button">
<property name="visible">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="toggled" handler="_on_view_button_toggled" swapped="no"/>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="column_spacing">5</property>
<property name="row_homogeneous">True</property>
<child>
<object class="GtkImage" id="image6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">view-paged-symbolic</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="count">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="valign">end</property>
<property name="label" translatable="yes">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="pages_button">
<property name="visible">True</property>
......@@ -134,7 +182,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
<style>
......
......@@ -29,7 +29,7 @@
<file compressed="true" preprocess="xml-stripblanks">RowDownload.ui</file>
<file compressed="true" preprocess="xml-stripblanks">SettingsDialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks">Shortcuts.ui</file>
<file compressed="true" preprocess="xml-stripblanks">SidebarChild.ui</file>
<file compressed="true" preprocess="xml-stripblanks">StackChild.ui</file>
<file compressed="true" preprocess="xml-stripblanks">TagWidget.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ToolbarActions.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ToolbarEnd.ui</file>
......
......@@ -17,6 +17,7 @@
<value nick="preview" value="0" />
<value nick="no-preview" value="1" />
<value nick="minimal" value="2" />
<value nick="none" value="3" />
</enum>
<schema path="/org/gnome/Eolie/" id="org.gnome.Eolie" gettext-domain="eolie">
<key type="ai" name="window-size">
......
......@@ -38,6 +38,10 @@ app_PYTHON = \
popover_webview.py\
search.py\
settings.py\
stack.py\
stackbox.py\
stackbox_child.py\
stack_child.py\
stacksidebar.py\
stacksidebar_child.py\
sqlcursor.py\
......
......@@ -306,7 +306,7 @@ class Application(Gtk.Application):
self.art = Art()
self.search = Search()
self.download_manager = DownloadManager()
self.pages_menu = PagesMenu(self)
self.pages_menu = PagesMenu()
shortcut_action = Gio.SimpleAction.new('shortcut',
GLib.VariantType.new('s'))
......
......@@ -16,7 +16,6 @@ from urllib.parse import urlparse
from time import time
from eolie.view_web import WebView
from eolie.stacksidebar import StackSidebar
from eolie.view import View
from eolie.popover_webview import WebViewPopover
from eolie.define import El
......@@ -29,7 +28,7 @@ class Container(Gtk.Overlay):
def __init__(self, window):
"""
Init container
Ini.container
@param window as Window
"""
Gtk.Overlay.__init__(self)
......@@ -45,20 +44,27 @@ class Container(Gtk.Overlay):
self.__stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
self.__stack.set_transition_duration(150)
self.__stack.show()
self.__stack_sidebar = StackSidebar(window)
self.__stack_sidebar.show()
grid = Gtk.Grid()
grid.add(self.__stack_sidebar)
grid.add(self.__stack)
grid.show()
self.add(grid)
self.__grid_stack = Gtk.Stack()
self.__grid_stack.set_hexpand(True)
self.__grid_stack.set_vexpand(True)
self.__grid_stack.set_transition_type(
Gtk.StackTransitionType.CROSSFADE)
self.__grid_stack.set_transition_duration(150)
self.__grid_stack.show()
self.__grid = Gtk.Grid()
# Attach at position 1 to let place to pages_manager
self.__grid.attach(self.__stack, 1, 0, 1, 1)
self.__grid.show()
self.__pages_manager = None
self.__grid_stack.add_named(self.__grid, "grid")
self.add(self.__grid_stack)
self.connect("unmap", self.__on_unmap)
self.__stack_sidebar.set_property("halign", Gtk.Align.START)
def add_webview(self, uri, window_type, ephemeral=False,
parent=None, state=None, load=True):
"""
Add a web view to container
Add a web view t.container
@param uri as str
@param window_type as Gdk.WindowType
@param parent as View
......@@ -85,30 +91,39 @@ class Container(Gtk.Overlay):
def add_view(self, webview, parent, window_type):
"""
Add view to container
Add view t.container
@param webview as WebView
@param parent as WebView
@param window_type as Gdk.WindowType
"""
view = self.__get_new_view(webview, parent)
view.show()
self.__stack_sidebar.add_child(view, window_type)
self.__pages_manager.add_child(view)
# Force window type as current window is not visible
if self.__grid_stack.get_visible_child_name() == "expose":
window_type = Gdk.WindowType.OFFSCREEN
if window_type == Gdk.WindowType.CHILD:
self.__stack.add(view)
self.__stack.set_visible_child(view)
elif window_type == Gdk.WindowType.OFFSCREEN:
panel_mode = El().settings.get_enum("panel-mode")
# Little hack, we force webview to be shown (offscreen)
# This allow getting snapshots from webkit
window = Gtk.OffscreenWindow.new()
width = self.get_allocated_width() -\
self.__stack_sidebar.get_allocated_width()
if panel_mode == 3:
width = self.get_allocated_width()
else:
width = self.get_allocated_width() -\
self.__pages_manager.get_allocated_width()
view.set_size_request(width, self.get_allocated_height())
window.add(view)
window.show()
window.remove(view)
view.set_size_request(-1, -1)
self.__stack.add(view)
self.__stack_sidebar.update_visible_child()
self.__pages_manager.update_visible_child()
count = str(len(self.__stack.get_children()))
self.__window.toolbar.actions.count_label.set_text(count)
def load_uri(self, uri):
"""
......@@ -157,6 +172,40 @@ class Container(Gtk.Overlay):
self.__popover.set_position(Gtk.PositionType.BOTTOM)
self.__popover.popup()
def set_expose(self, b):
"""
Show current views
@param b as bool
"""
if b:
self.__grid_stack.set_visible_child_name("expose")
else:
self.__grid_stack.set_visible_child_name("grid")
self.__window.toolbar.actions.view_button.set_active(False)
def update_pages_manager(self, panel_mode):
"""
Switch pages manager
@param panel mode as int
"""
views = []
if self.__pages_manager is not None:
views = self.__pages_manager.views
self.__pages_manager.destroy()
if panel_mode == 3:
from eolie.stackbox import StackBox
self.__pages_manager = StackBox(self.__window)
self.__grid_stack.add_named(self.__pages_manager, "expose")
else:
from eolie.stacksidebar import StackSidebar
self.__pages_manager = StackSidebar(self.__window)
self.__grid.attach(self.__pages_manager, 0, 0, 1, 1)
self.__pages_manager.show()
for view in views:
child = self.__pages_manager.add_child(view)
child.use_cached_snapshot()
self.__pages_manager.update_visible_child()
def on_view_map(self, webview):
"""
Update window
......@@ -184,13 +233,22 @@ class Container(Gtk.Overlay):
elif uri:
self.__window.toolbar.title.set_title(uri)
def set_panel_mode(self, panel_mode):
"""
Set panel mode
@param panel_mode as int
"""
self.update_pages_manager(panel_mode)
if panel_mode != 3:
self.pages_manager.set_panel_mode(panel_mode)
@property
def sidebar(self):
def pages_manager(self):
"""
Get sidebar
@return StackSidebar
Get page manager
@return StackSidebar or StackBox
"""
return self.__stack_sidebar
return self.__pages_manager
@property
def views(self):
......@@ -265,9 +323,9 @@ class Container(Gtk.Overlay):
if uri:
if window_type == Gdk.WindowType.SUBSURFACE:
if webview.ephemeral:
webview = WebView.new_ephemeral()
webview = WebView.new_ephemeral(self.__window)
else:
webview = WebView.new()
webview = WebView.new(self.__window)
self.popup_webview(webview, True)
GLib.idle_add(webview.load_uri, uri)
else:
......@@ -422,14 +480,14 @@ class Container(Gtk.Overlay):
Hide sidebar (conflict with fs)
@param webview as WebView
"""
self.__stack_sidebar.hide()
self.__pages_manager.hide()
def __on_leave_fullscreen(self, webview):
"""
Show sidebar (conflict with fs)
@param webview as WebView
"""
self.__stack_sidebar.show()
self.__pages_manager.show()
def __on_insecure_content_detected(self, webview, event):
"""
......
......@@ -23,31 +23,29 @@ class PagesMenu(Gio.Menu):
Menu showing closed page
"""
def __init__(self, app):
def __init__(self):
"""
Init menu
@param app as Gio.Application
"""
Gio.Menu.__init__(self)
self.__app = app
# Setup actions
action = Gio.SimpleAction(name="new-private")
app.add_action(action)
El().add_action(action)
action.connect('activate',
self.__on_private_clicked)
action = Gio.SimpleAction(name="openall")
app.add_action(action)
El().add_action(action)
action.connect('activate',
self.__on_openall_clicked)
panel_mode = app.settings.get_enum("panel-mode")
panel_mode = El().settings.get_enum("panel-mode")
self.__panel_action = Gio.SimpleAction.new_stateful(
"panel_mode",
GLib.VariantType.new("i"),
GLib.Variant("i", panel_mode))
self.__panel_action.connect("activate",
self.__on_panel_mode_active)
app.add_action(self.__panel_action)
El().add_action(self.__panel_action)
# Setup submenu
submenu = Gio.Menu.new()
......@@ -56,7 +54,9 @@ class PagesMenu(Gio.Menu):
Gio.MenuItem.new(_("Do not show preview"),
"app.panel_mode(1)"),
Gio.MenuItem.new(_("Minimal panel"),
"app.panel_mode(2)")]
"app.panel_mode(2)"),
Gio.MenuItem.new(_("No panel"),
"app.panel_mode(3)")]
for item in items:
submenu.append_item(item)
# Setup menu
......@@ -79,7 +79,7 @@ class PagesMenu(Gio.Menu):
if self.__closed_section.get_n_items():
uri = self.__closed_section.get_item_attribute_value(0, "uri")
encoded = sha256(uri.get_string().encode("utf-8")).hexdigest()
action = self.__app.lookup_action(encoded)
action = El().lookup_action(encoded)
action.activate(None)
def add_action(self, title, uri, private, state):
......@@ -98,7 +98,7 @@ class PagesMenu(Gio.Menu):
self.__clean_actions()
encoded = sha256(uri.encode("utf-8")).hexdigest()
action = Gio.SimpleAction(name=encoded)
self.__app.add_action(action)
El().add_action(action)
action.connect('activate',
self.__on_action_clicked,
(uri, private, state))
......@@ -125,9 +125,9 @@ class PagesMenu(Gio.Menu):
Remove action from menu
"""
encoded = sha256(uri.encode("utf-8")).hexdigest()
action = self.__app.lookup_action(encoded)
action = El().lookup_action(encoded)
if action is not None:
self.__app.remove_action(encoded)
El().remove_action(encoded)
for i in range(0, self.__closed_section.get_n_items() - 1):
attribute = self.__closed_section.get_item_attribute_value(
i,
......@@ -158,9 +158,9 @@ class PagesMenu(Gio.Menu):
uri = self.__closed_section.get_item_attribute_value(
0, "uri").get_string()
encoded = sha256(uri.encode("utf-8")).hexdigest()
action = self.__app.lookup_action(encoded)
action = El().lookup_action(encoded)
if action is not None:
self.__app.remove_action(encoded)
El().remove_action(encoded)
self.__closed_section.remove(0)
def __on_private_clicked(self, action, variant):
......@@ -169,9 +169,9 @@ class PagesMenu(Gio.Menu):
@param Gio.SimpleAction
@param GVariant
"""
self.__app.active_window.container.add_webview(self.__app.start_page,
Gdk.WindowType.CHILD,
True)
El().active_window.container.add_webview(El().start_page,
Gdk.WindowType.CHILD,
True)
def __on_openall_clicked(self, action, variant):
"""
......@@ -184,7 +184,7 @@ class PagesMenu(Gio.Menu):
"uri")
if uri_attr is None:
continue
GLib.idle_add(self.__app.active_window.container.add_webview,
GLib.idle_add(El().active_window.container.add_webview,
uri_attr.get_string(), Gdk.WindowType.OFFSCREEN,
False,
None, None, False)
......@@ -200,7 +200,7 @@ class PagesMenu(Gio.Menu):
uri = data[0]
private = data[1]
state = data[2]
GLib.idle_add(self.__app.active_window.container.add_webview,
GLib.idle_add(El().active_window.container.add_webview,
uri, Gdk.WindowType.CHILD, private, None, state)
self.remove_action(uri)
......@@ -211,6 +211,7 @@ class PagesMenu(Gio.Menu):
@param param as GLib.Variant
"""
action.set_state(param)
self.__app.settings.set_enum('panel-mode', param.get_int32())
for window in self.__app.windows:
window.container.sidebar.set_panel_mode()
panel_mode = param.get_int32()
El().settings.set_enum('panel-mode', panel_mode)
for window in El().windows:
window.container.set_panel_mode(panel_mode)
# 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, Gdk, GLib
from gettext import gettext as _
from eolie.define import El
class Stack(Gtk.EventBox):
"""
Box linked to a Gtk.Stack
Should be inherited by a class providing self._CHILD_CLASS
"""
def __init__(self, window):
"""
Init stack
@param window as Window
"""
Gtk.EventBox.__init__(self)
self._window = window
self.get_style_context().add_class("sidebar")
self.connect("button-press-event", self.__on_button_press)
grid = Gtk.Grid()
grid.set_orientation(Gtk.Orientation.VERTICAL)
grid.show()
self.__search_entry = Gtk.SearchEntry.new()
self.__search_entry.connect("search-changed", self.__on_search_changed)
self.__search_entry.show()
self.__search_bar = Gtk.SearchBar.new()
self.__search_bar.add(self.__search_entry)
grid.add(self.__search_bar)
self.__scrolled = Gtk.ScrolledWindow()
self.__scrolled.set_vexpand(True)
self.__scrolled.set_hexpand(True)
self.__scrolled.show()
self._viewport = Gtk.Viewport()
self._viewport.show()
self.__scrolled.add(self._viewport)
self.set_hexpand(False)
grid.add(self.__scrolled)
self.add(grid)
def add_child(self, view):
"""
Add child to sidebar
@param view as WebView
@return child
"""
child = self._CHILD_CLASS(view, self._window)
child.connect("moved", self.__on_moved)
child.show()
# We want to insert child next to its parent and brothers
wanted_index = -1
i = 1
for row in self._box.get_children():
if row.view == view.parent or (view.parent is not None and
row.view.parent == view.parent):
wanted_index = i
i += 1
self._box.insert(child, wanted_index)
return child
def update_visible_child(self):
"""
Mark current child as visible
Unmark all others
"""
visible = self._window.container.current
for child in self._box.get_children():
if child.view.webview.ephemeral:
class_name = "sidebar-item-selected-private"
else:
class_name = "sidebar-item-selected"
if child.view == visible:
child.get_style_context().add_class(class_name)
# Wait loop empty: will fails otherwise if child just created
GLib.idle_add(self.__scroll_to_child, child)
else:
child.get_style_context().remove_class(class_name)
def destroy(self):
"""
Destroy widget and child
"""
# We force child to disconnect from view
for child in self._box.get_children():
child.disconnect_signals()
child.destroy()
Gtk.EventBox.destroy(self)
def set_filtered(self, b):
"""
Show filtering widget
@param b as bool
"""
if b:
if self._window.is_fullscreen:
height = self._window.toolbar.get_allocated_height()
self.__search_bar.set_margin_top(height)
else:
self.__search_bar.set_margin_top(0)
self.__search_bar.show()
self.__search_entry.grab_focus()
self.__search_entry.connect("key-press-event",
self.__on_key_press)
self._box.set_filter_func(self.__filter_func)
for child in self._box.get_children():
child.show_title(True)
else:
self.__search_bar.hide()
self.__search_entry.disconnect_by_func(self.__on_key_press)
self._box.set_filter_func(None)
for child in self._box.get_children():
child.show_title(self.__panel_mode != 2)
self.__search_bar.set_search_mode(b)
def next(self):
"""
Show next view
"""
children = self._box.get_children()
index = self.__get_index(self._window.container.current)
if index + 1 < len(children):
next_row = self._get_child_at_index(index + 1)
else:
next_row = self._get_child_at_index(0)
if next_row is not None:
self._window.container.set_visible_view(next_row.view)
self.update_visible_child()
panel_mode = El().settings.get_enum("panel-mode")
if panel_mode == 3:
self._window.container.set_expose(True)
def previous(self):
"""
Show next view
"""
children = self._box.get_children()
index = self.__get_index(self._window.container.current)
if index == 0:
next_row = self._get_child_at_index(len(children) - 1)
else:
next_row = self._get_child_at_index(index - 1)
if next_row is not None:
self._window.container.set_visible_view(next_row.view)
self.update_visible_child()
panel_mode = El().settings.get_enum("panel-mode")
if panel_mode == 3:
self._window.container.set_expose(True)
def close_view(self, view):
"""
Ask user before closing view if forms filled
@param view as View
"""
page_id = view.webview.get_page_id()
El().helper.call("FormsFilled",
GLib.Variant("(i)", (page_id,)),
self.__on_forms_filled, view, page_id)
def set_panel_mode(self, panel_mode=None):
pass
@property
def panel_mode(self):
"""
Get current panel mode
@return int
"""
return 0
@property
def views(self):
"""
Get views ordered
@return [View]
"""
views = []
for child in self._box.get_children():
views.append(child.view)
return views
#######################
# PROTECTED #
#######################
#######################
# PRIVATE #
#######################
def __close_view(self, view):
"""
close current view
@param view as View
"""
count = len(self._window.container.views)
El().history.set_page_state(view.webview.get_uri())
self._window.close_popovers()
# Needed to unfocus titlebar
self._window.set_focus(None)
was_current = view == self._window.container.current
child_index = self.__get_index(view)
# Delay view destroy to allow stack animation
child = self._get_child_at_index(child_index)
if child is None:
return
El().pages_menu.add_action(view.webview.get_title(),
view.webview.get_uri(),
view.webview.ephemeral,
view.webview.get_session_state())
GLib.timeout_add(1000, view.destroy)
child.destroy()
# Nothing to do if was not current page
if not was_current:
return False
next_row = None
# First we search a child with same parent as closed
brother = None
for child in reversed(self._box.get_children()):
if child.view != view and (
child.view.parent == view.parent or
child.view.parent == view):
brother = child
break
# Load brother
if brother is not None:
brother_index = self.__get_index(brother.view)
next_row = self._get_child_at_index(brother_index)
# Go back to parent page
elif view.parent is not None:
parent_index = self.__get_index(view.parent)
next_row = self._get_child_at_index(parent_index)
# Find best near page
else:
children = self._box.get_children()
# We are last row, add a new one
if len(children) == 0:
self._window.container.add_webview(El().start_page,
Gdk.WindowType.CHILD)
# We have rows before closed
elif child_index - 1 >= 0:
next_row = self._get_child_at_index(child_index - 1)
# We have rows next to closed, so reload current index
elif child_index < len(children):
next_row = self._get_child_at_index(child_index)
if next_row is not None:
self._window.container.set_visible_view(next_row.view)
self.update_visible_child()
self._window.toolbar.actions.count_label.set_text(str(count - 1))
def __scroll_to_child(self, row):
"""
Scroll to row
@param row as Row
"""
adj = self.__scrolled.get_vadjustment().get_value()
coordinates = row.translate_coordinates(self._box, 0, 0)
if coordinates is None:
return
y = coordinates[1]
if y + row.get_allocated_height() >\
self.__scrolled.get_allocated_height() + adj or\
y - row.get_allocated_height() < 0 + adj:
self.__scrolled.get_vadjustment().set_value(y)
def __get_index(self, view):
"""
Get view index
@param view as View
@return int
"""
# Search current index
children = self._box.get_children()
index = 0
for child in children:
if child.view == view:
break
index += 1
return index
def __get_index_for_string(self, view_str):
"""
Get view index for str
@param view_str as str
@return int
"""
# Search current index
children = self._box.get_children()
index = 0
for child in children: