forked from Mirrors/apostrophe
Add toggle between various preview modes
Including: * Full-width (original) * Half-width * Half-height * Windowedgithub/fork/yochananmarqos/patch-1
parent
f72f61ae7d
commit
65e7028843
|
@ -10,6 +10,13 @@
|
||||||
<value nick='read_time' value='4' />
|
<value nick='read_time' value='4' />
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
|
<enum id='de.wolfvollprecht.UberWriter.PreviewMode'>
|
||||||
|
<value nick='full-width' value='0' />
|
||||||
|
<value nick='half-width' value='1' />
|
||||||
|
<value nick='half-height' value='2' />
|
||||||
|
<value nick='windowed' value='3' />
|
||||||
|
</enum>
|
||||||
|
|
||||||
<schema path="/de/wolfvollprecht/UberWriter/" id="de.wolfvollprecht.UberWriter">
|
<schema path="/de/wolfvollprecht/UberWriter/" id="de.wolfvollprecht.UberWriter">
|
||||||
|
|
||||||
<key name='dark-mode-auto' type='b'>
|
<key name='dark-mode-auto' type='b'>
|
||||||
|
@ -76,11 +83,11 @@
|
||||||
Maximum number of characters per line within the editor.
|
Maximum number of characters per line within the editor.
|
||||||
</description>
|
</description>
|
||||||
</key>
|
</key>
|
||||||
<key name='preview-side-by-side' type='b'>
|
<key name='preview-mode' enum='de.wolfvollprecht.UberWriter.PreviewMode'>
|
||||||
<default>false</default>
|
<default>"full-width"</default>
|
||||||
<summary>Side-by-side preview</summary>
|
<summary>Preview mode</summary>
|
||||||
<description>
|
<description>
|
||||||
Show the preview side by side, instead of full-width.
|
How to display the preview.
|
||||||
</description>
|
</description>
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-button {
|
.toggle-button {
|
||||||
color: alpha(@theme_fg_color, 0.6);
|
color: alpha(@theme_fg_color, 0.6);
|
||||||
background-color: @theme_base_color;
|
background-color: @theme_base_color;
|
||||||
text-shadow: inherit;
|
text-shadow: inherit;
|
||||||
|
@ -116,8 +116,8 @@
|
||||||
transition: 100ms ease-in;
|
transition: 100ms ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-button :hover,
|
.toggle-button:hover,
|
||||||
.stats-button :checked {
|
.toggle-button:checked {
|
||||||
color: @theme_fg_color;
|
color: @theme_fg_color;
|
||||||
background-color: mix(@theme_base_color, @theme_bg_color, 0.5);
|
background-color: mix(@theme_base_color, @theme_bg_color, 0.5);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
<object class="GtkBox" id="preview">
|
<object class="GtkBox" id="preview">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="vexpand">True</property>
|
||||||
<property name="orientation">vertical</property>
|
<property name="orientation">vertical</property>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<placeholder/>
|
||||||
|
@ -33,6 +34,9 @@
|
||||||
<property name="image">pan-down</property>
|
<property name="image">pan-down</property>
|
||||||
<property name="image_position">right</property>
|
<property name="image_position">right</property>
|
||||||
<property name="always_show_image">True</property>
|
<property name="always_show_image">True</property>
|
||||||
|
<style>
|
||||||
|
<class name="toggle-button"/>
|
||||||
|
</style>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|
|
@ -115,6 +115,9 @@
|
||||||
<property name="image">pan-down</property>
|
<property name="image">pan-down</property>
|
||||||
<property name="image_position">right</property>
|
<property name="image_position">right</property>
|
||||||
<property name="always_show_image">True</property>
|
<property name="always_show_image">True</property>
|
||||||
|
<style>
|
||||||
|
<class name="toggle-button"/>
|
||||||
|
</style>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|
|
@ -120,10 +120,18 @@ class Application(Gtk.Application):
|
||||||
|
|
||||||
stat_default = self.settings.get_string("stat-default")
|
stat_default = self.settings.get_string("stat-default")
|
||||||
action = Gio.SimpleAction.new_stateful(
|
action = Gio.SimpleAction.new_stateful(
|
||||||
"stat_default", GLib.VariantType.new('s'), GLib.Variant.new_string(stat_default))
|
"stat_default", GLib.VariantType.new("s"), GLib.Variant.new_string(stat_default))
|
||||||
action.connect("activate", self.on_stat_default)
|
action.connect("activate", self.on_stat_default)
|
||||||
self.add_action(action)
|
self.add_action(action)
|
||||||
|
|
||||||
|
# Preview Menu
|
||||||
|
|
||||||
|
preview_mode = self.settings.get_string("preview-mode")
|
||||||
|
action = Gio.SimpleAction.new_stateful(
|
||||||
|
"preview_mode", GLib.VariantType.new("s"), GLib.Variant.new_string(preview_mode))
|
||||||
|
action.connect("activate", self.on_preview_mode)
|
||||||
|
self.add_action(action)
|
||||||
|
|
||||||
# Shortcuts
|
# Shortcuts
|
||||||
|
|
||||||
# TODO: be aware that a couple of shortcuts are defined in base.css
|
# TODO: be aware that a couple of shortcuts are defined in base.css
|
||||||
|
@ -180,6 +188,8 @@ class Application(Gtk.Application):
|
||||||
self.window.reload_preview()
|
self.window.reload_preview()
|
||||||
elif key == "stat-default":
|
elif key == "stat-default":
|
||||||
self.window.update_default_stat()
|
self.window.update_default_stat()
|
||||||
|
elif key == "preview-mode":
|
||||||
|
self.window.update_preview_mode()
|
||||||
|
|
||||||
def on_new(self, _action, _value):
|
def on_new(self, _action, _value):
|
||||||
self.window.new_document()
|
self.window.new_document()
|
||||||
|
@ -250,6 +260,10 @@ class Application(Gtk.Application):
|
||||||
action.set_state(value)
|
action.set_state(value)
|
||||||
self.settings.set_string("stat-default", value.get_string())
|
self.settings.set_string("stat-default", value.get_string())
|
||||||
|
|
||||||
|
def on_preview_mode(self, action, value):
|
||||||
|
action.set_state(value)
|
||||||
|
self.settings.set_string("preview-mode", value.get_string())
|
||||||
|
|
||||||
# ~ if __name__ == "__main__":
|
# ~ if __name__ == "__main__":
|
||||||
# ~ app = Application()
|
# ~ app = Application()
|
||||||
# ~ app.run(sys.argv)
|
# ~ app.run(sys.argv)
|
||||||
|
|
|
@ -5,12 +5,12 @@ from enum import auto, IntEnum
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
from uberwriter.helpers import get_builder
|
from uberwriter.helpers import get_builder
|
||||||
|
from uberwriter.preview_renderer import PreviewRenderer
|
||||||
|
|
||||||
gi.require_version('WebKit2', '4.0')
|
gi.require_version('WebKit2', '4.0')
|
||||||
from gi.repository import WebKit2
|
from gi.repository import WebKit2
|
||||||
|
|
||||||
from uberwriter.preview_converter import PreviewConverter
|
from uberwriter.preview_converter import PreviewConverter
|
||||||
from uberwriter.settings import Settings
|
|
||||||
from uberwriter.web_view import WebView
|
from uberwriter.web_view import WebView
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,38 +20,31 @@ class Step(IntEnum):
|
||||||
RENDER = auto()
|
RENDER = auto()
|
||||||
|
|
||||||
|
|
||||||
class Previewer:
|
class PreviewHandler:
|
||||||
def __init__(self, content, editor, text_view):
|
def __init__(self, window, content, editor, text_view):
|
||||||
self.content = content
|
|
||||||
self.editor = editor
|
|
||||||
self.text_view = text_view
|
self.text_view = text_view
|
||||||
|
|
||||||
self.web_view = None
|
self.web_view = None
|
||||||
self.web_view_pending_html = None
|
self.web_view_pending_html = None
|
||||||
|
|
||||||
builder = get_builder("Preview")
|
builder = get_builder("Preview")
|
||||||
self.preview = builder.get_object("preview")
|
preview = builder.get_object("preview")
|
||||||
self.preview_mode_button = builder.get_object("preview_mode_button")
|
mode_button = builder.get_object("preview_mode_button")
|
||||||
self.preview_mode_button.get_style_context().add_class('toggle-button')
|
|
||||||
|
|
||||||
self.preview_converter = PreviewConverter()
|
self.preview_converter = PreviewConverter()
|
||||||
|
self.preview_renderer = PreviewRenderer(
|
||||||
|
window, content, editor, text_view, preview, mode_button)
|
||||||
|
|
||||||
self.web_scroll_handler_id = None
|
self.web_scroll_handler_id = None
|
||||||
self.text_scroll_handler_id = None
|
self.text_scroll_handler_id = None
|
||||||
self.text_changed_handler_id = None
|
self.text_changed_handler_id = None
|
||||||
|
|
||||||
self.settings = Settings.new()
|
|
||||||
|
|
||||||
self.loading = False
|
self.loading = False
|
||||||
self.showing = False
|
self.shown = False
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
self.__show()
|
self.__show()
|
||||||
|
|
||||||
def reload(self):
|
|
||||||
if self.showing:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def __show(self, html=None, step=Step.CONVERT_HTML):
|
def __show(self, html=None, step=Step.CONVERT_HTML):
|
||||||
if step == Step.CONVERT_HTML:
|
if step == Step.CONVERT_HTML:
|
||||||
# First step: convert text to HTML.
|
# First step: convert text to HTML.
|
||||||
|
@ -80,41 +73,37 @@ class Previewer:
|
||||||
self.web_view.load_html(html, 'file://localhost/')
|
self.web_view.load_html(html, 'file://localhost/')
|
||||||
|
|
||||||
elif step == Step.RENDER:
|
elif step == Step.RENDER:
|
||||||
# Last and one-time step: show the web view.
|
# Last and one-time step: show the preview.
|
||||||
if self.showing:
|
if self.shown:
|
||||||
return
|
return
|
||||||
self.showing = True
|
self.shown = True
|
||||||
|
|
||||||
if self.settings.get_boolean("preview-side-by-side"):
|
self.web_view.set_scroll_scale(self.text_view.get_scroll_scale())
|
||||||
self.content.set_size_request(self.text_view.get_min_width() * 2, -1)
|
|
||||||
self.web_view.set_scroll_scale(self.text_view.get_scroll_scale())
|
|
||||||
self.web_scroll_handler_id = \
|
|
||||||
self.web_view.connect("scroll-scale-changed", self.on_web_view_scrolled)
|
|
||||||
self.text_scroll_handler_id = \
|
|
||||||
self.text_view.connect("scroll-scale-changed", self.on_text_view_scrolled)
|
|
||||||
self.text_changed_handler_id = \
|
|
||||||
self.text_view.get_buffer().connect("changed", self.__show)
|
|
||||||
else:
|
|
||||||
self.content.remove(self.editor)
|
|
||||||
|
|
||||||
self.preview.pack_start(self.web_view, True, True, 0)
|
self.text_changed_handler_id =\
|
||||||
self.content.add(self.preview)
|
self.text_view.get_buffer().connect("changed", self.__show)
|
||||||
self.web_view.show()
|
self.web_scroll_handler_id =\
|
||||||
|
self.web_view.connect("scroll-scale-changed", self.on_web_view_scrolled)
|
||||||
|
self.text_scroll_handler_id =\
|
||||||
|
self.text_view.connect("scroll-scale-changed", self.on_text_view_scrolled)
|
||||||
|
|
||||||
|
self.preview_renderer.show(self.web_view)
|
||||||
|
|
||||||
|
def reload(self):
|
||||||
|
if self.shown:
|
||||||
|
self.show()
|
||||||
|
|
||||||
def hide(self):
|
def hide(self):
|
||||||
if self.showing:
|
if self.shown:
|
||||||
self.showing = False
|
self.shown = False
|
||||||
|
|
||||||
if self.settings.get_boolean("preview-side-by-side"):
|
self.text_view.set_scroll_scale(self.web_view.get_scroll_scale())
|
||||||
self.content.set_size_request(-1, -1)
|
|
||||||
self.web_view.disconnect(self.web_scroll_handler_id)
|
|
||||||
self.text_view.disconnect(self.text_scroll_handler_id)
|
|
||||||
self.text_view.get_buffer().disconnect(self.text_changed_handler_id)
|
|
||||||
else:
|
|
||||||
self.content.add(self.editor)
|
|
||||||
|
|
||||||
self.content.remove(self.preview)
|
self.text_view.get_buffer().disconnect(self.text_changed_handler_id)
|
||||||
self.preview.remove(self.web_view)
|
self.text_view.disconnect(self.text_scroll_handler_id)
|
||||||
|
self.web_view.disconnect(self.web_scroll_handler_id)
|
||||||
|
|
||||||
|
self.preview_renderer.hide(self.web_view)
|
||||||
|
|
||||||
if self.loading:
|
if self.loading:
|
||||||
self.loading = False
|
self.loading = False
|
||||||
|
@ -122,6 +111,9 @@ class Previewer:
|
||||||
self.web_view.destroy()
|
self.web_view.destroy()
|
||||||
self.web_view = None
|
self.web_view = None
|
||||||
|
|
||||||
|
def update_preview_mode(self):
|
||||||
|
self.preview_renderer.update_mode(self.web_view)
|
||||||
|
|
||||||
def on_load_changed(self, _web_view, event):
|
def on_load_changed(self, _web_view, event):
|
||||||
if event == WebKit2.LoadEvent.FINISHED:
|
if event == WebKit2.LoadEvent.FINISHED:
|
||||||
self.loading = False
|
self.loading = False
|
||||||
|
@ -132,11 +124,11 @@ class Previewer:
|
||||||
self.__show(step=Step.RENDER)
|
self.__show(step=Step.RENDER)
|
||||||
|
|
||||||
def on_text_view_scrolled(self, _text_view, scale):
|
def on_text_view_scrolled(self, _text_view, scale):
|
||||||
if not math.isclose(scale, self.web_view.get_scroll_scale(), rel_tol=1e-5):
|
if self.shown and not math.isclose(scale, self.web_view.get_scroll_scale(), rel_tol=1e-5):
|
||||||
self.web_view.set_scroll_scale(scale)
|
self.web_view.set_scroll_scale(scale)
|
||||||
|
|
||||||
def on_web_view_scrolled(self, _web_view, scale):
|
def on_web_view_scrolled(self, _web_view, scale):
|
||||||
if not math.isclose(scale, self.text_view.get_scroll_scale(), rel_tol=1e-5):
|
if self.shown and not math.isclose(scale, self.text_view.get_scroll_scale(), rel_tol=1e-5):
|
||||||
self.text_view.set_scroll_scale(scale)
|
self.text_view.set_scroll_scale(scale)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
|
@ -0,0 +1,127 @@
|
||||||
|
from gettext import gettext as _
|
||||||
|
|
||||||
|
from gi.repository import Gtk, Gio, GLib
|
||||||
|
|
||||||
|
from uberwriter.settings import Settings
|
||||||
|
|
||||||
|
|
||||||
|
class PreviewRenderer:
|
||||||
|
"""Renders the preview according to the user selected mode."""
|
||||||
|
|
||||||
|
# Must match the order/index defined in gschema.xml
|
||||||
|
FULL_WIDTH = 0
|
||||||
|
HALF_WIDTH = 1
|
||||||
|
HALF_HEIGHT = 2
|
||||||
|
WINDOWED = 3
|
||||||
|
|
||||||
|
def __init__(self, main_window, content, editor, text_view, preview, mode_button):
|
||||||
|
self.content = content
|
||||||
|
self.editor = editor
|
||||||
|
self.text_view = text_view
|
||||||
|
self.preview = preview
|
||||||
|
self.mode_button = mode_button
|
||||||
|
self.mode_button.connect("clicked", self.show_mode_popover)
|
||||||
|
self.popover = None
|
||||||
|
self.settings = Settings.new()
|
||||||
|
self.main_window = main_window
|
||||||
|
self.window = None
|
||||||
|
self.mode = self.settings.get_enum("preview-mode")
|
||||||
|
|
||||||
|
def show(self, web_view):
|
||||||
|
self.preview.pack_start(web_view, True, True, 0)
|
||||||
|
|
||||||
|
if self.mode == self.FULL_WIDTH:
|
||||||
|
self.content.remove(self.editor)
|
||||||
|
self.content.add(self.preview)
|
||||||
|
|
||||||
|
elif self.mode == self.HALF_WIDTH:
|
||||||
|
self.content.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||||
|
self.content.set_size_request(self.text_view.get_min_width() * 2, -1)
|
||||||
|
self.content.add(self.preview)
|
||||||
|
|
||||||
|
elif self.mode == self.HALF_HEIGHT:
|
||||||
|
self.content.set_orientation(Gtk.Orientation.VERTICAL)
|
||||||
|
self.content.set_size_request(-1, 800)
|
||||||
|
self.content.add(self.preview)
|
||||||
|
|
||||||
|
elif self.mode == self.WINDOWED:
|
||||||
|
self.window = Gtk.Window(title=_("Preview"))
|
||||||
|
self.window.set_application(self.main_window.get_application())
|
||||||
|
self.window.set_default_size(
|
||||||
|
self.main_window.get_allocated_width(), self.main_window.get_allocated_height())
|
||||||
|
self.window.set_transient_for(self.main_window)
|
||||||
|
self.window.set_modal(False)
|
||||||
|
self.window.add(self.preview)
|
||||||
|
self.window.connect("delete-event", self.on_window_closed)
|
||||||
|
self.window.show()
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown preview mode {}".format(self.mode))
|
||||||
|
|
||||||
|
web_view.show()
|
||||||
|
|
||||||
|
def hide(self, web_view):
|
||||||
|
if self.mode == self.FULL_WIDTH:
|
||||||
|
self.content.remove(self.preview)
|
||||||
|
self.content.add(self.editor)
|
||||||
|
|
||||||
|
elif self.mode == self.HALF_WIDTH or self.mode == self.HALF_HEIGHT:
|
||||||
|
self.content.remove(self.preview)
|
||||||
|
self.content.set_size_request(-1, -1)
|
||||||
|
|
||||||
|
elif self.mode == self.WINDOWED:
|
||||||
|
self.window.remove(self.preview)
|
||||||
|
self.window.destroy()
|
||||||
|
self.window = None
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown preview mode {}".format(self.mode))
|
||||||
|
|
||||||
|
self.preview.remove(web_view)
|
||||||
|
|
||||||
|
def update_mode(self, web_view):
|
||||||
|
mode = self.settings.get_enum("preview-mode")
|
||||||
|
if mode != self.mode:
|
||||||
|
if web_view:
|
||||||
|
self.hide(web_view)
|
||||||
|
self.mode = mode
|
||||||
|
self.show(web_view)
|
||||||
|
text = self.get_text_for_preview_mode(self.mode)
|
||||||
|
self.mode_button.set_label(text)
|
||||||
|
if self.popover:
|
||||||
|
self.popover.popdown()
|
||||||
|
|
||||||
|
def show_mode_popover(self, _button):
|
||||||
|
self.mode_button.set_state_flags(Gtk.StateFlags.CHECKED, False)
|
||||||
|
|
||||||
|
menu = Gio.Menu()
|
||||||
|
modes = self.settings.props.settings_schema.get_key("preview-mode").get_range()[1]
|
||||||
|
for i, mode in enumerate(modes):
|
||||||
|
menu_item = Gio.MenuItem.new(self.get_text_for_preview_mode(i), None)
|
||||||
|
menu_item.set_action_and_target_value("app.preview_mode", GLib.Variant.new_string(mode))
|
||||||
|
menu.append_item(menu_item)
|
||||||
|
self.popover = Gtk.Popover.new_from_model(self.mode_button, menu)
|
||||||
|
self.popover.connect('closed', self.on_popover_closed)
|
||||||
|
self.popover.popup()
|
||||||
|
|
||||||
|
def on_popover_closed(self, _popover):
|
||||||
|
self.mode_button.unset_state_flags(Gtk.StateFlags.CHECKED)
|
||||||
|
|
||||||
|
self.popover = None
|
||||||
|
self.text_view.grab_focus()
|
||||||
|
|
||||||
|
def on_window_closed(self, window, _event):
|
||||||
|
preview_action = window.get_application().lookup_action("preview")
|
||||||
|
preview_action.change_state(GLib.Variant.new_boolean(False))
|
||||||
|
|
||||||
|
def get_text_for_preview_mode(self, mode):
|
||||||
|
if mode == self.FULL_WIDTH:
|
||||||
|
return _("Full-Width")
|
||||||
|
elif mode == self.HALF_WIDTH:
|
||||||
|
return _("Half-Width")
|
||||||
|
elif mode == self.HALF_HEIGHT:
|
||||||
|
return _("Half-Height")
|
||||||
|
elif mode == self.WINDOWED:
|
||||||
|
return _("Windowed")
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown preview mode {}".format(mode))
|
|
@ -9,6 +9,13 @@ from uberwriter.stats_counter import StatsCounter
|
||||||
class StatsHandler:
|
class StatsHandler:
|
||||||
"""Shows a default statistic on the stats button, and allows the user to toggle which one."""
|
"""Shows a default statistic on the stats button, and allows the user to toggle which one."""
|
||||||
|
|
||||||
|
# Must match the order/index defined in gschema.xml
|
||||||
|
CHARACTERS = 0
|
||||||
|
WORDS = 1
|
||||||
|
SENTENCES = 2
|
||||||
|
PARAGRAPHS = 3
|
||||||
|
READ_TIME = 4
|
||||||
|
|
||||||
def __init__(self, stats_button, text_view):
|
def __init__(self, stats_button, text_view):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
@ -28,7 +35,6 @@ class StatsHandler:
|
||||||
self.read_time = (0, 0, 0)
|
self.read_time = (0, 0, 0)
|
||||||
|
|
||||||
self.settings = Settings.new()
|
self.settings = Settings.new()
|
||||||
self.default_stat = self.settings.get_enum("stat-default")
|
|
||||||
|
|
||||||
self.stats_counter = StatsCounter()
|
self.stats_counter = StatsCounter()
|
||||||
|
|
||||||
|
@ -59,15 +65,15 @@ class StatsHandler:
|
||||||
self.update_stats)
|
self.update_stats)
|
||||||
|
|
||||||
def get_text_for_stat(self, stat):
|
def get_text_for_stat(self, stat):
|
||||||
if stat == 0:
|
if stat == self.CHARACTERS:
|
||||||
return _("{:n} Characters").format(self.characters)
|
return _("{:n} Characters").format(self.characters)
|
||||||
elif stat == 1:
|
elif stat == self.WORDS:
|
||||||
return _("{:n} Words").format(self.words)
|
return _("{:n} Words").format(self.words)
|
||||||
elif stat == 2:
|
elif stat == self.SENTENCES:
|
||||||
return _("{:n} Sentences").format(self.sentences)
|
return _("{:n} Sentences").format(self.sentences)
|
||||||
elif stat == 3:
|
elif stat == self.PARAGRAPHS:
|
||||||
return _("{:n} Paragraphs").format(self.paragraphs)
|
return _("{:n} Paragraphs").format(self.paragraphs)
|
||||||
elif stat == 4:
|
elif stat == self.READ_TIME:
|
||||||
return _("{:d}:{:02d}:{:02d} Read Time").format(*self.read_time)
|
return _("{:d}:{:02d}:{:02d} Read Time").format(*self.read_time)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unknown stat {}".format(stat))
|
raise ValueError("Unknown stat {}".format(stat))
|
||||||
|
|
|
@ -16,7 +16,7 @@ class WebView(WebKit2.WebView):
|
||||||
|
|
||||||
GET_SCROLL_SCALE_JS = """
|
GET_SCROLL_SCALE_JS = """
|
||||||
e = document.documentElement;
|
e = document.documentElement;
|
||||||
e.scrollHeight > e.clientHeight ? e.scrollTop / (e.scrollHeight - e.clientHeight) : 0;
|
e.scrollHeight > e.clientHeight ? e.scrollTop / (e.scrollHeight - e.clientHeight) : -1;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
SET_SCROLL_SCALE_JS = """
|
SET_SCROLL_SCALE_JS = """
|
||||||
|
@ -37,10 +37,10 @@ e.scrollTop = (e.scrollHeight - e.clientHeight) * scale;
|
||||||
self.connect("destroy", self.on_destroy)
|
self.connect("destroy", self.on_destroy)
|
||||||
|
|
||||||
self.scroll_scale = 0.0
|
self.scroll_scale = 0.0
|
||||||
self.pending_scroll_scale = None
|
|
||||||
|
|
||||||
self.state_loaded = False
|
self.state_loaded = False
|
||||||
self.state_load_failed = False
|
self.state_load_failed = False
|
||||||
|
self.state_dirty = False
|
||||||
self.state_waiting = False
|
self.state_waiting = False
|
||||||
|
|
||||||
self.timeout_id = None
|
self.timeout_id = None
|
||||||
|
@ -49,13 +49,13 @@ e.scrollTop = (e.scrollHeight - e.clientHeight) * scale;
|
||||||
return self.scroll_scale
|
return self.scroll_scale
|
||||||
|
|
||||||
def set_scroll_scale(self, scale):
|
def set_scroll_scale(self, scale):
|
||||||
self.pending_scroll_scale = scale
|
self.state_dirty = True
|
||||||
|
self.scroll_scale = scale
|
||||||
self.state_loop()
|
self.state_loop()
|
||||||
|
|
||||||
def on_load_changed(self, _web_view, event):
|
def on_load_changed(self, _web_view, event):
|
||||||
self.state_loaded = event >= WebKit2.LoadEvent.COMMITTED and not self.state_load_failed
|
self.state_loaded = event >= WebKit2.LoadEvent.COMMITTED and not self.state_load_failed
|
||||||
self.state_load_failed = False
|
self.state_load_failed = False
|
||||||
self.pending_scroll_scale = self.scroll_scale
|
|
||||||
self.state_loop()
|
self.state_loop()
|
||||||
|
|
||||||
def on_load_failed(self, _web_view, _event):
|
def on_load_failed(self, _web_view, _event):
|
||||||
|
@ -72,9 +72,10 @@ e.scrollTop = (e.scrollHeight - e.clientHeight) * scale;
|
||||||
self.run_javascript(
|
self.run_javascript(
|
||||||
self.GET_SCROLL_SCALE_JS, None, self.sync_scroll_scale)
|
self.GET_SCROLL_SCALE_JS, None, self.sync_scroll_scale)
|
||||||
|
|
||||||
def write_scroll_scale(self, scroll_scale):
|
def write_scroll_scale(self):
|
||||||
|
self.state_dirty = False
|
||||||
self.run_javascript(
|
self.run_javascript(
|
||||||
self.SET_SCROLL_SCALE_JS.format(scroll_scale), None, None)
|
self.SET_SCROLL_SCALE_JS.format(self.scroll_scale), None, None)
|
||||||
|
|
||||||
def sync_scroll_scale(self, _web_view, result):
|
def sync_scroll_scale(self, _web_view, result):
|
||||||
self.state_waiting = False
|
self.state_waiting = False
|
||||||
|
@ -88,16 +89,15 @@ e.scrollTop = (e.scrollHeight - e.clientHeight) * scale;
|
||||||
self.timeout_id = None
|
self.timeout_id = None
|
||||||
|
|
||||||
# Set scroll scale if specified, and the state is not dirty
|
# Set scroll scale if specified, and the state is not dirty
|
||||||
if scroll_scale not in (None, self.scroll_scale):
|
if scroll_scale not in (None, -1, self.scroll_scale):
|
||||||
self.scroll_scale = scroll_scale
|
self.scroll_scale = scroll_scale
|
||||||
self.emit("scroll-scale-changed", self.scroll_scale)
|
self.emit("scroll-scale-changed", self.scroll_scale)
|
||||||
|
|
||||||
# Handle the current state
|
# Handle the current state
|
||||||
if not self.state_loaded or self.state_load_failed or self.state_waiting:
|
if not self.state_loaded or self.state_load_failed or self.state_waiting:
|
||||||
return
|
return
|
||||||
if self.pending_scroll_scale:
|
if self.state_dirty:
|
||||||
self.write_scroll_scale(self.pending_scroll_scale)
|
self.write_scroll_scale()
|
||||||
self.pending_scroll_scale = None
|
|
||||||
if delay > 0:
|
if delay > 0:
|
||||||
self.timeout_id = GLib.timeout_add(delay, self.state_loop, None, 0)
|
self.timeout_id = GLib.timeout_add(delay, self.state_loop, None, 0)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# END LICENSE
|
# END LICENSE
|
||||||
|
|
||||||
import codecs
|
import codecs
|
||||||
import locale
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import urllib
|
import urllib
|
||||||
|
@ -24,7 +23,7 @@ from gettext import gettext as _
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
from uberwriter.export_dialog import Export
|
from uberwriter.export_dialog import Export
|
||||||
from uberwriter.previewer import Previewer
|
from uberwriter.preview_handler import PreviewHandler
|
||||||
from uberwriter.stats_handler import StatsHandler
|
from uberwriter.stats_handler import StatsHandler
|
||||||
from uberwriter.text_view import TextView
|
from uberwriter.text_view import TextView
|
||||||
|
|
||||||
|
@ -112,13 +111,12 @@ class Window(Gtk.ApplicationWindow):
|
||||||
# Setup stats counter
|
# Setup stats counter
|
||||||
self.stats_revealer = builder.get_object('editor_stats_revealer')
|
self.stats_revealer = builder.get_object('editor_stats_revealer')
|
||||||
self.stats_button = builder.get_object('editor_stats_button')
|
self.stats_button = builder.get_object('editor_stats_button')
|
||||||
self.stats_button.get_style_context().add_class('toggle-button')
|
|
||||||
self.stats_handler = StatsHandler(self.stats_button, self.text_view)
|
self.stats_handler = StatsHandler(self.stats_button, self.text_view)
|
||||||
|
|
||||||
# Setup preview
|
# Setup preview
|
||||||
content = builder.get_object('content')
|
content = builder.get_object('content')
|
||||||
editor = builder.get_object('editor')
|
editor = builder.get_object('editor')
|
||||||
self.previewer = Previewer(content, editor, self.text_view)
|
self.preview_handler = PreviewHandler(self, content, editor, self.text_view)
|
||||||
|
|
||||||
# Setup header/stats bar hide after 3 seconds
|
# Setup header/stats bar hide after 3 seconds
|
||||||
self.top_bottom_bars_visible = True
|
self.top_bottom_bars_visible = True
|
||||||
|
@ -419,6 +417,9 @@ class Window(Gtk.ApplicationWindow):
|
||||||
def update_default_stat(self):
|
def update_default_stat(self):
|
||||||
self.stats_handler.update_default_stat()
|
self.stats_handler.update_default_stat()
|
||||||
|
|
||||||
|
def update_preview_mode(self):
|
||||||
|
self.preview_handler.update_preview_mode()
|
||||||
|
|
||||||
def menu_toggle_sidebar(self, _widget=None):
|
def menu_toggle_sidebar(self, _widget=None):
|
||||||
"""WIP
|
"""WIP
|
||||||
"""
|
"""
|
||||||
|
@ -455,14 +456,14 @@ class Window(Gtk.ApplicationWindow):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if state.get_boolean():
|
if state.get_boolean():
|
||||||
self.previewer.show()
|
self.preview_handler.show()
|
||||||
else:
|
else:
|
||||||
self.previewer.hide()
|
self.preview_handler.hide()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def reload_preview(self):
|
def reload_preview(self):
|
||||||
self.previewer.reload()
|
self.preview_handler.reload()
|
||||||
|
|
||||||
def load_file(self, filename=None):
|
def load_file(self, filename=None):
|
||||||
"""Open File from command line or open / open recent etc."""
|
"""Open File from command line or open / open recent etc."""
|
||||||
|
|
Loading…
Reference in New Issue