Fix changing theme while app is running not applying until restart

Overall refactoring of how the theme is set, bounding it to the window
instead of the application, which generally makes it easier to listen
for the "style-updated" signal.
ft.font-size^2
Gonçalo Silva 2019-03-29 01:30:43 +00:00
parent 99641125ba
commit 16a8ac78db
4 changed files with 84 additions and 86 deletions

View File

@ -164,10 +164,6 @@ class Application(Gtk.Application):
self.set_accels_for_action("app.save_as", ["<Ctl><shift>s"])
self.set_accels_for_action("app.quit", ["<Ctl>w", "<Ctl>q"])
# Theme
self.apply_current_theme()
def do_activate(self, *args, **kwargs):
# We only allow a single window and raise any existing ones
if not self.window:
@ -199,23 +195,6 @@ class Application(Gtk.Application):
self.activate()
return 0
def apply_current_theme(self):
# get current theme
theme = Theme.get_current()
# set theme variant (dark/light)
Gtk.Settings.get_default().set_property(
"gtk-application-prefer-dark-theme",
GLib.Variant("b", theme.is_dark))
# set theme css
style_provider = Gtk.CssProvider()
style_provider.load_from_path(theme.gtk_css_path)
Gtk.StyleContext.add_provider_for_screen(
Gdk.Screen.get_default(), style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
def on_about(self, _action, _param):
builder = get_builder('About')
about_dialog = builder.get_object("AboutDialog")
@ -257,10 +236,6 @@ class Application(Gtk.Application):
GLib.Variant.new_boolean(not value.get_boolean()),
False)
# change the app theme accordingly
self.apply_current_theme()
# adjust window for theme
self.window.apply_current_theme()
def on_focus_mode(self, action, value):

View File

@ -23,11 +23,29 @@ from gi.repository import Pango
class MarkupBuffer():
regex = {
"ITALIC": re.compile(r"(\*|_)(.*?)\1", re.UNICODE), # *asdasd* // _asdasd asd asd_
"STRONG": re.compile(r"(\*\*|__)(.*?)\1", re.UNICODE), # **as das** // __asdasd asd ad a__
"STRONGITALIC": re.compile(r"(\*\*\*|___)(.*?)\1"),
"BLOCKQUOTE": re.compile(r"^([\>]+ )", re.MULTILINE),
"STRIKETHROUGH": re.compile(r"~~[^ `~\n].+?~~"),
"LIST": re.compile(r"^[\-\*\+] ", re.MULTILINE),
"NUMERICLIST": re.compile(r"^((\d|[a-z]|\#)+[\.\)]) ", re.MULTILINE),
"INDENTEDLIST": re.compile(r"^(\t{1,6})((\d|[a-z]|\#)+[\.\)]|[\-\*\+]) ", re.MULTILINE),
"HEADINDICATOR": re.compile(r"^(#{1,6}) ", re.MULTILINE),
"HEADLINE": re.compile(r"^(#{1,6} [^\n]+)", re.MULTILINE),
"HEADLINE_TWO": re.compile(r"^\w.+\n[\=\-]{3,}", re.MULTILINE),
"MATH": re.compile(r"[\$]{1,2}([^` ].+?[^`\\ ])[\$]{1,2}"),
"HORIZONTALRULE": re.compile(r"(\n\n[\*\-]{3,}\n)"),
"TABLE": re.compile(r"^[\-\+]{5,}\n(.+?)\n[\-\+]{5,}\n", re.DOTALL),
"LINK": re.compile(r"\(http(.+?)\)")
}
def __init__(self, Parent, TextBuffer, base_leftmargin):
self.multiplier = 10
self.parent = Parent
self.text_buffer = TextBuffer
def __init__(self, window, text_editor, base_leftmargin):
self.margin_multiplier = 10
self.parent = window
self.text_editor = text_editor
self.text_buffer = text_editor.get_buffer()
# Styles
self.italic = self.text_buffer.create_tag("italic",
@ -94,37 +112,24 @@ class MarkupBuffer():
self.table_env = self.text_buffer.create_tag('table_env')
self.table_env.set_property('wrap-mode', Gtk.WrapMode.NONE)
# self.table_env.set_property('font', 'Ubuntu Mono 13px')
self.table_env.set_property('pixels-above-lines', 0)
self.table_env.set_property('pixels-below-lines', 0)
self.update_style()
# Theme
self.text_editor.connect('style-updated', self.apply_current_theme)
self.apply_current_theme()
regex = {
"ITALIC": re.compile(r"(\*|_)(.*?)\1", re.UNICODE), # *asdasd* // _asdasd asd asd_
"STRONG": re.compile(r"(\*\*|__)(.*?)\1", re.UNICODE), # **as das** // __asdasd asd ad a__
"STRONGITALIC": re.compile(r"(\*\*\*|___)(.*?)\1"),
"BLOCKQUOTE": re.compile(r"^([\>]+ )", re.MULTILINE),
"STRIKETHROUGH": re.compile(r"~~[^ `~\n].+?~~"),
"LIST": re.compile(r"^[\-\*\+] ", re.MULTILINE),
"NUMERICLIST": re.compile(r"^((\d|[a-z]|\#)+[\.\)]) ", re.MULTILINE),
"INDENTEDLIST": re.compile(r"^(\t{1,6})((\d|[a-z]|\#)+[\.\)]|[\-\*\+]) ", re.MULTILINE),
"HEADINDICATOR": re.compile(r"^(#{1,6}) ", re.MULTILINE),
"HEADLINE": re.compile(r"^(#{1,6} [^\n]+)", re.MULTILINE),
"HEADLINE_TWO": re.compile(r"^\w.+\n[\=\-]{3,}", re.MULTILINE),
"MATH": re.compile(r"[\$]{1,2}([^` ].+?[^`\\ ])[\$]{1,2}"),
"HORIZONTALRULE": re.compile(r"(\n\n[\*\-]{3,}\n)"),
"TABLE": re.compile(r"^[\-\+]{5,}\n(.+?)\n[\-\+]{5,}\n", re.DOTALL),
"LINK": re.compile(r"\(http(.+?)\)")
}
def update_style(self):
(found, color) = self.parent.get_style_context().lookup_color('math_text_color')
def apply_current_theme(self, *_):
# Math text color
(found, color) = self.text_editor.get_style_context().lookup_color('math_text_color')
if not found:
(_, color) = self.parent.get_style_context().lookup_color('foreground_color')
(_, color) = self.text_editor.get_style_context().lookup_color('foreground_color')
self.math_text.set_property("foreground", color.to_string())
# Margin
mets = self.text_editor.get_pango_context().get_metrics()
self.set_multiplier(Pango.units_to_double(mets.get_approximate_char_width()) + 1)
def markup_buffer(self, mode=0):
buf = self.text_buffer
@ -306,10 +311,10 @@ class MarkupBuffer():
end_sentence, self.text_buffer.get_end_iter())
def set_multiplier(self, multiplier):
self.multiplier = multiplier
self.margin_multiplier = multiplier
def recalculate(self, lm):
multiplier = self.multiplier
multiplier = self.margin_multiplier
for i in range(0, 6):
new_margin = (lm - multiplier) - multiplier * (i + 1)
self.rev_leftmargin[i].set_property("left-margin", 0 if new_margin < 0 else new_margin)

View File

@ -11,6 +11,7 @@ class Theme:
The light variant is listed first, followed by the dark variant, if any.
"""
previous = None
settings = Settings.new()
def __init__(self, name, gtk_css_path, web_css_path, is_dark, inverse_name):
@ -36,7 +37,17 @@ class Theme:
current_theme = cls.get_for_name(theme_name)
if not dark_mode_auto and dark_mode != current_theme.is_dark and current_theme.inverse_name:
current_theme = cls.get_for_name(current_theme.inverse_name, current_theme.name)
return current_theme
changed = current_theme != cls.previous
cls.previous = current_theme
return current_theme, changed
def __eq__(self, other):
return isinstance(other, self.__class__) and \
self.name == other.name and \
self.gtk_css_path == other.gtk_css_path and \
self.web_css_path == other.web_css_path and \
self.is_dark == other.is_dark and \
self.inverse_name == other.inverse_name
defaultThemes = [

View File

@ -64,6 +64,15 @@ CONFIG_PATH = os.path.expanduser("~/.config/uberwriter/")
class Window(Gtk.ApplicationWindow):
__gsignals__ = {
'save-file': (GObject.SIGNAL_ACTION, None, ()),
'open-file': (GObject.SIGNAL_ACTION, None, ()),
'save-file-as': (GObject.SIGNAL_ACTION, None, ()),
'new-file': (GObject.SIGNAL_ACTION, None, ()),
'toggle-bibtex': (GObject.SIGNAL_ACTION, None, ()),
'toggle-preview': (GObject.SIGNAL_ACTION, None, ()),
'close-window': (GObject.SIGNAL_ACTION, None, ())
}
WORDCOUNT = re.compile(r"(?!\-\w)[\s#*\+\-]+", re.UNICODE)
@ -74,6 +83,7 @@ class Window(Gtk.ApplicationWindow):
application=Gio.Application.get_default(),
title="Uberwriter")
# Set UI
self.builder = get_builder('UberwriterWindow')
self.add(self.builder.get_object("FullscreenOverlay"))
@ -127,7 +137,7 @@ class Window(Gtk.ApplicationWindow):
self.text_editor.set_vadjustment(self.builder.get_object('vadjustment1'))
self.text_editor.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
self.text_editor.connect('focus-out-event', self.focus_out)
self.text_editor.get_style_context().connect('changed', self.on_style_changed)
self.text_editor.connect('style-updated', self.apply_current_theme)
self.text_editor.set_top_margin(80)
self.text_editor.set_bottom_margin(16)
@ -183,12 +193,9 @@ class Window(Gtk.ApplicationWindow):
# Markup and Shortcuts for the TextBuffer
self.markup_buffer = MarkupBuffer(
self, self.text_buffer, base_leftmargin)
self, self.text_editor, base_leftmargin)
self.markup_buffer.markup_buffer()
# Set current theme
self.apply_current_theme()
# Scrolling -> Dark or not?
self.textchange = False
self.scroll_count = 0
@ -248,29 +255,34 @@ class Window(Gtk.ApplicationWindow):
self.connect("configure-event", self.window_resize)
self.connect("delete-event", self.on_delete_called)
__gsignals__ = {
'save-file': (GObject.SIGNAL_ACTION, None, ()),
'open-file': (GObject.SIGNAL_ACTION, None, ()),
'save-file-as': (GObject.SIGNAL_ACTION, None, ()),
'new-file': (GObject.SIGNAL_ACTION, None, ()),
'toggle-bibtex': (GObject.SIGNAL_ACTION, None, ()),
'toggle-preview': (GObject.SIGNAL_ACTION, None, ()),
'close-window': (GObject.SIGNAL_ACTION, None, ())
}
# Set current theme
self.apply_current_theme()
def apply_current_theme(self):
"""Adjusts both the window and the CSD for the current theme.
def apply_current_theme(self, *_):
"""Adjusts the window, CSD and preview for the current theme.
"""
# Get current theme
theme, changed = Theme.get_current()
# Update markup buffer's style
self.markup_buffer.update_style()
if changed:
# Set theme variant (dark/light)
Gtk.Settings.get_default().set_property(
"gtk-application-prefer-dark-theme",
GLib.Variant("b", theme.is_dark))
# Reload preview if it exists
if self.preview_webview:
self.show_preview()
# Set theme css
style_provider = Gtk.CssProvider()
style_provider.load_from_path(theme.gtk_css_path)
Gtk.StyleContext.add_provider_for_screen(
self.get_screen(), style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
# Redraw contents of window
self.queue_draw()
# Reload preview if it exists
if self.preview_webview:
self.show_preview()
# Redraw contents of window
self.queue_draw()
def scrolled(self, widget):
"""if window scrolled + focusmode make font black again"""
@ -547,12 +559,6 @@ class Window(Gtk.ApplicationWindow):
alloc.width = width_request
self.text_editor.size_allocate(alloc)
def on_style_changed(self, _widget, _data=None):
pgc = self.text_editor.get_pango_context()
mets = pgc.get_metrics()
self.markup_buffer.set_multiplier(
Pango.units_to_double(mets.get_approximate_char_width()) + 1)
# TODO: refactorizable
def save_document(self, _widget=None, _data=None):
"""provide to the user a filechooser and save the document
@ -876,12 +882,13 @@ class Window(Gtk.ApplicationWindow):
base_path = ''
os.environ['PANDOC_PREFIX'] = base_path + '/'
theme, _ = Theme.get_current()
args = ['pandoc',
'-s',
'--from=markdown',
'--to=html5',
'--mathjax',
'--css=' + Theme.get_current().web_css_path,
'--css=' + theme.web_css_path,
'--quiet',
'--lua-filter=' + helpers.get_script_path('relative_to_absolute.lua'),
'--lua-filter=' + helpers.get_script_path('task-list.lua')]