forked from Mirrors/apostrophe
Add statistics for sentences and read time, allow user to toggle default
Fixes #63github/fork/yochananmarqos/patch-1
parent
1a7443fd3c
commit
c19f57f64b
|
@ -1,6 +1,13 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<schemalist>
|
<schemalist>
|
||||||
|
<enum id='de.wolfvollprecht.UberWriter.Stat'>
|
||||||
|
<value nick='characters' value='0' />
|
||||||
|
<value nick='words' value='1' />
|
||||||
|
<value nick='sentences' value='2' />
|
||||||
|
<value nick='read_time' value='3' />
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
|
||||||
<schema path="/de/wolfvollprecht/UberWriter/" id="de.wolfvollprecht.UberWriter">
|
<schema path="/de/wolfvollprecht/UberWriter/" id="de.wolfvollprecht.UberWriter">
|
||||||
|
|
||||||
|
@ -54,6 +61,13 @@
|
||||||
Open file paths of the current session
|
Open file paths of the current session
|
||||||
</description>
|
</description>
|
||||||
</key>
|
</key>
|
||||||
|
<key name='stat-default' enum='de.wolfvollprecht.UberWriter.Stat'>
|
||||||
|
<default>"words"</default>
|
||||||
|
<summary>Default statistic</summary>
|
||||||
|
<description>
|
||||||
|
Which statistic is shown on the main window.
|
||||||
|
</description>
|
||||||
|
</key>
|
||||||
|
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
|
|
|
@ -86,15 +86,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.status-bar-box label {
|
.stats-counter {
|
||||||
color: #666;
|
color: alpha(@foreground_color, 0.6);
|
||||||
}
|
|
||||||
|
|
||||||
.status-bar-box button {
|
|
||||||
/* finding reset */
|
|
||||||
background-color: @background_color;
|
background-color: @background_color;
|
||||||
text-shadow: inherit;
|
text-shadow: inherit;
|
||||||
/*icon-shadow: inherit;*/
|
|
||||||
box-shadow: initial;
|
box-shadow: initial;
|
||||||
background-clip: initial;
|
background-clip: initial;
|
||||||
background-origin: initial;
|
background-origin: initial;
|
||||||
|
@ -106,37 +101,15 @@
|
||||||
border-image-repeat: initial;
|
border-image-repeat: initial;
|
||||||
border-image-slice: initial;
|
border-image-slice: initial;
|
||||||
border-image-width: initial;
|
border-image-width: initial;
|
||||||
|
|
||||||
border-style: none;
|
border-style: none;
|
||||||
-button-images: true;
|
padding: 0px 16px;
|
||||||
border-radius: 2px;
|
|
||||||
color: #666;
|
|
||||||
padding: 3px 5px;
|
|
||||||
transition: 100ms ease-in;
|
transition: 100ms ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-bar-box button:hover,
|
.stats-counter:hover,
|
||||||
.status-bar-box button:checked {
|
.stats-counter:checked {
|
||||||
transition: 0s ease-in;
|
color: @foreground_color;
|
||||||
color: @background_color;
|
background-color: lighter(@background_color);
|
||||||
background-color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-bar-box button:hover label,
|
|
||||||
.status-bar-box button:checked label {
|
|
||||||
color: @background_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-bar-box button:active {
|
|
||||||
color: #EEE;
|
|
||||||
background-color: #EEE;
|
|
||||||
background-image: none;
|
|
||||||
box-shadow: 0 0 2px rgba(0,0,0,0.4)
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-bar-box separator {
|
|
||||||
border-color: #999;
|
|
||||||
border-right: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#PreviewMenuItem image {
|
#PreviewMenuItem image {
|
||||||
|
|
|
@ -75,97 +75,20 @@
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="hexpand">True</property>
|
<property name="hexpand">True</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkRevealer" id="status_bar_revealer">
|
<object class="GtkRevealer" id="stats_counter_revealer">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="transition_type">crossfade</property>
|
<property name="transition_type">crossfade</property>
|
||||||
<property name="transition_duration">750</property>
|
<property name="transition_duration">750</property>
|
||||||
<property name="reveal_child">True</property>
|
<property name="reveal_child">True</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkGrid" id="status_bar_box">
|
<object class="GtkButton" id="stats_counter">
|
||||||
|
<property name="label" translatable="yes">0 Words</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">True</property>
|
||||||
<child>
|
<property name="receives_default">True</property>
|
||||||
<object class="GtkLabel" id="label2">
|
<property name="tooltip_text" translatable="yes">Show Statistics</property>
|
||||||
<property name="visible">True</property>
|
<property name="halign">end</property>
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="halign">end</property>
|
|
||||||
<property name="hexpand">True</property>
|
|
||||||
<property name="label" translatable="yes">Words:</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">3</property>
|
|
||||||
<property name="top_attach">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="word_count">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="halign">end</property>
|
|
||||||
<property name="label">0</property>
|
|
||||||
<property name="justify">right</property>
|
|
||||||
<property name="width_chars">4</property>
|
|
||||||
<property name="xalign">1</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">4</property>
|
|
||||||
<property name="top_attach">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkSeparator" id="separator1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="halign">end</property>
|
|
||||||
<property name="margin_left">10</property>
|
|
||||||
<property name="margin_right">10</property>
|
|
||||||
<property name="margin_start">10</property>
|
|
||||||
<property name="margin_end">10</property>
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">5</property>
|
|
||||||
<property name="top_attach">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="label1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="halign">end</property>
|
|
||||||
<property name="label" translatable="yes">Characters:</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">6</property>
|
|
||||||
<property name="top_attach">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="char_count">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="halign">end</property>
|
|
||||||
<property name="margin_right">11</property>
|
|
||||||
<property name="margin_end">11</property>
|
|
||||||
<property name="label">0</property>
|
|
||||||
<property name="width_chars">6</property>
|
|
||||||
<property name="xalign">1</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">7</property>
|
|
||||||
<property name="top_attach">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|
|
@ -40,6 +40,8 @@ class Application(Gtk.Application):
|
||||||
|
|
||||||
self.settings.connect("changed", self.on_settings_changed)
|
self.settings.connect("changed", self.on_settings_changed)
|
||||||
|
|
||||||
|
# Header bar
|
||||||
|
|
||||||
action = Gio.SimpleAction.new("new", None)
|
action = Gio.SimpleAction.new("new", None)
|
||||||
action.connect("activate", self.on_new)
|
action.connect("activate", self.on_new)
|
||||||
self.add_action(action)
|
self.add_action(action)
|
||||||
|
@ -60,6 +62,8 @@ class Application(Gtk.Application):
|
||||||
action.connect("activate", self.on_search)
|
action.connect("activate", self.on_search)
|
||||||
self.add_action(action)
|
self.add_action(action)
|
||||||
|
|
||||||
|
# App Menu
|
||||||
|
|
||||||
action = Gio.SimpleAction.new_stateful(
|
action = Gio.SimpleAction.new_stateful(
|
||||||
"focus_mode", None, GLib.Variant.new_boolean(False))
|
"focus_mode", None, GLib.Variant.new_boolean(False))
|
||||||
action.connect("change-state", self.on_focus_mode)
|
action.connect("change-state", self.on_focus_mode)
|
||||||
|
@ -112,6 +116,14 @@ class Application(Gtk.Application):
|
||||||
action.connect("activate", self.on_quit)
|
action.connect("activate", self.on_quit)
|
||||||
self.add_action(action)
|
self.add_action(action)
|
||||||
|
|
||||||
|
# Stats Menu
|
||||||
|
|
||||||
|
stat_default = self.settings.get_string("stat-default")
|
||||||
|
action = Gio.SimpleAction.new_stateful(
|
||||||
|
"stat_default", GLib.VariantType.new('s'), GLib.Variant.new_string(stat_default))
|
||||||
|
action.connect("activate", self.on_stat_default)
|
||||||
|
self.add_action(action)
|
||||||
|
|
||||||
# Shortcuts
|
# Shortcuts
|
||||||
|
|
||||||
# TODO: be aware that a couple of shortcuts are defined in _gtk_base.css
|
# TODO: be aware that a couple of shortcuts are defined in _gtk_base.css
|
||||||
|
@ -166,6 +178,8 @@ class Application(Gtk.Application):
|
||||||
self.window.toggle_gradient_overlay(settings.get_value(key))
|
self.window.toggle_gradient_overlay(settings.get_value(key))
|
||||||
elif key == "input-format":
|
elif key == "input-format":
|
||||||
self.window.reload_preview()
|
self.window.reload_preview()
|
||||||
|
elif key == "stat-default":
|
||||||
|
self.window.update_default_stat()
|
||||||
|
|
||||||
def on_new(self, _action, _value):
|
def on_new(self, _action, _value):
|
||||||
self.window.new_document()
|
self.window.new_document()
|
||||||
|
@ -232,6 +246,10 @@ class Application(Gtk.Application):
|
||||||
def on_quit(self, _action, _param):
|
def on_quit(self, _action, _param):
|
||||||
self.quit()
|
self.quit()
|
||||||
|
|
||||||
|
def on_stat_default(self, action, value):
|
||||||
|
action.set_state(value)
|
||||||
|
self.settings.set_string("stat-default", value.get_string())
|
||||||
|
|
||||||
# ~ if __name__ == "__main__":
|
# ~ if __name__ == "__main__":
|
||||||
# ~ app = Application()
|
# ~ app = Application()
|
||||||
# ~ app.run(sys.argv)
|
# ~ app.run(sys.argv)
|
||||||
|
|
|
@ -9,7 +9,7 @@ from uberwriter import helpers
|
||||||
|
|
||||||
|
|
||||||
class StatsCounter:
|
class StatsCounter:
|
||||||
"""Counts characters, words, sentences and reading time using a background thread."""
|
"""Counts characters, words, sentences and read time using a background thread."""
|
||||||
|
|
||||||
# Regexp that matches any character, except for newlines and subsequent spaces.
|
# Regexp that matches any character, except for newlines and subsequent spaces.
|
||||||
CHARACTERS = re.compile(r"[^\s]|(?:[^\S\n](?!\s))")
|
CHARACTERS = re.compile(r"[^\s]|(?:[^\S\n](?!\s))")
|
||||||
|
@ -26,11 +26,11 @@ class StatsCounter:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.queue = Queue()
|
self.queue = Queue()
|
||||||
worker = Thread(target=self.__do_count_stats, name="stats-counter")
|
worker = Thread(target=self.__do_count, name="stats-counter")
|
||||||
worker.daemon = True
|
worker.daemon = True
|
||||||
worker.start()
|
worker.start()
|
||||||
|
|
||||||
def count_stats(self, text, callback):
|
def count(self, text, callback):
|
||||||
"""Count stats for text, calling callback with a result when done.
|
"""Count stats for text, calling callback with a result when done.
|
||||||
|
|
||||||
The callback argument contains the result, in the form:
|
The callback argument contains the result, in the form:
|
||||||
|
@ -44,7 +44,7 @@ class StatsCounter:
|
||||||
|
|
||||||
self.queue.put((None, None))
|
self.queue.put((None, None))
|
||||||
|
|
||||||
def __do_count_stats(self):
|
def __do_count(self):
|
||||||
while True:
|
while True:
|
||||||
while True:
|
while True:
|
||||||
(text, callback) = self.queue.get()
|
(text, callback) = self.queue.get()
|
||||||
|
@ -61,10 +61,8 @@ class StatsCounter:
|
||||||
|
|
||||||
sentence_count = len(re.findall(self.SENTENCES, text))
|
sentence_count = len(re.findall(self.SENTENCES, text))
|
||||||
|
|
||||||
dec_, int_ = math.modf(word_count / 200)
|
read_m, read_s = divmod(word_count / 200 * 60, 60)
|
||||||
hours = int(int_ / 60)
|
read_h, read_m = divmod(read_m, 60)
|
||||||
minutes = int(int_ % 60)
|
read_time = (int(read_h), int(read_m), int(read_s))
|
||||||
seconds = round(dec_ * 0.6)
|
|
||||||
reading_time = (hours, minutes, seconds)
|
|
||||||
|
|
||||||
GLib.idle_add(callback, (character_count, word_count, sentence_count, reading_time))
|
GLib.idle_add(callback, (character_count, word_count, sentence_count, read_time))
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
import math
|
||||||
|
import re
|
||||||
|
from gettext import gettext as _
|
||||||
|
from queue import Queue
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
from gi.repository import GLib, Gio, Gtk
|
||||||
|
|
||||||
|
from uberwriter import helpers
|
||||||
|
from uberwriter.helpers import get_builder
|
||||||
|
from uberwriter.settings import Settings
|
||||||
|
from uberwriter.stats_counter import StatsCounter
|
||||||
|
|
||||||
|
|
||||||
|
class StatsHandler:
|
||||||
|
"""Shows a default statistic on the stats button, and allows the user to toggle which one."""
|
||||||
|
|
||||||
|
def __init__(self, stats_button, text_view):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.stats_button = stats_button
|
||||||
|
self.stats_button.connect("clicked", self.on_stats_button_clicked)
|
||||||
|
self.stats_button.connect("destroy", self.on_destroy)
|
||||||
|
|
||||||
|
self.text_view = text_view
|
||||||
|
self.text_view.get_buffer().connect("changed", self.on_text_changed)
|
||||||
|
|
||||||
|
self.popover = None
|
||||||
|
|
||||||
|
self.characters = 0
|
||||||
|
self.words = 0
|
||||||
|
self.sentences = 0
|
||||||
|
self.read_time = (0, 0, 0)
|
||||||
|
|
||||||
|
self.settings = Settings.new()
|
||||||
|
self.default_stat = self.settings.get_enum("stat-default")
|
||||||
|
|
||||||
|
self.stats_counter = StatsCounter()
|
||||||
|
|
||||||
|
self.update_default_stat()
|
||||||
|
|
||||||
|
def on_stats_button_clicked(self, _button):
|
||||||
|
self.stats_button.set_state_flags(Gtk.StateFlags.CHECKED, False)
|
||||||
|
|
||||||
|
menu = Gio.Menu()
|
||||||
|
characters_menu_item = Gio.MenuItem.new(self.get_text_for_stat(0), None)
|
||||||
|
characters_menu_item.set_action_and_target_value(
|
||||||
|
"app.stat_default", GLib.Variant.new_string("characters"))
|
||||||
|
menu.append_item(characters_menu_item)
|
||||||
|
words_menu_item = Gio.MenuItem.new(self.get_text_for_stat(1), None)
|
||||||
|
words_menu_item.set_action_and_target_value(
|
||||||
|
"app.stat_default", GLib.Variant.new_string("words"))
|
||||||
|
menu.append_item(words_menu_item)
|
||||||
|
sentences_menu_item = Gio.MenuItem.new(self.get_text_for_stat(2), None)
|
||||||
|
sentences_menu_item.set_action_and_target_value(
|
||||||
|
"app.stat_default", GLib.Variant.new_string("sentences"))
|
||||||
|
menu.append_item(sentences_menu_item)
|
||||||
|
read_time_menu_item = Gio.MenuItem.new(self.get_text_for_stat(3), None)
|
||||||
|
read_time_menu_item.set_action_and_target_value(
|
||||||
|
"app.stat_default", GLib.Variant.new_string("read_time"))
|
||||||
|
menu.append_item(read_time_menu_item)
|
||||||
|
self.popover = Gtk.Popover.new_from_model(self.stats_button, menu)
|
||||||
|
self.popover.connect('closed', self.on_popover_closed)
|
||||||
|
self.popover.popup()
|
||||||
|
|
||||||
|
def on_popover_closed(self, _popover):
|
||||||
|
self.stats_button.unset_state_flags(Gtk.StateFlags.CHECKED)
|
||||||
|
|
||||||
|
self.popover = None
|
||||||
|
self.text_view.grab_focus()
|
||||||
|
|
||||||
|
def on_text_changed(self, buf):
|
||||||
|
self.stats_counter.count(
|
||||||
|
buf.get_text(buf.get_start_iter(), buf.get_end_iter(), False),
|
||||||
|
self.update_stats)
|
||||||
|
|
||||||
|
def get_text_for_stat(self, stat):
|
||||||
|
if stat == 0:
|
||||||
|
return _("{:n} Characters".format(self.characters))
|
||||||
|
elif stat == 1:
|
||||||
|
return _("{:n} Words".format(self.words))
|
||||||
|
elif stat == 2:
|
||||||
|
return _("{:n} Sentences".format(self.sentences))
|
||||||
|
elif stat == 3:
|
||||||
|
return _("{:d}:{:02d}:{:02d} Read Time".format(*self.read_time))
|
||||||
|
|
||||||
|
def update_stats(self, stats):
|
||||||
|
(characters, words, sentences, read_time) = stats
|
||||||
|
self.characters = characters
|
||||||
|
self.words = words
|
||||||
|
self.sentences = sentences
|
||||||
|
self.read_time = read_time
|
||||||
|
self.update_default_stat(False)
|
||||||
|
|
||||||
|
def update_default_stat(self, close_popover=True):
|
||||||
|
stat = self.settings.get_enum("stat-default")
|
||||||
|
text = self.get_text_for_stat(stat)
|
||||||
|
self.stats_button.set_label(text)
|
||||||
|
if close_popover and self.popover:
|
||||||
|
self.popover.popdown()
|
||||||
|
|
||||||
|
def on_destroy(self, _widget):
|
||||||
|
self.stats_counter.stop()
|
|
@ -18,7 +18,6 @@ import codecs
|
||||||
import locale
|
import locale
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import urllib
|
import urllib
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
|
@ -26,7 +25,7 @@ from gettext import gettext as _
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
from uberwriter.export_dialog import Export
|
from uberwriter.export_dialog import Export
|
||||||
from uberwriter.stats_counter import StatsCounter
|
from uberwriter.stats_handler import StatsHandler
|
||||||
from uberwriter.text_view import TextView
|
from uberwriter.text_view import TextView
|
||||||
|
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
|
@ -82,8 +81,6 @@ class Window(Gtk.ApplicationWindow):
|
||||||
|
|
||||||
self.set_default_size(900, 500)
|
self.set_default_size(900, 500)
|
||||||
|
|
||||||
self.connect('delete-event', self.on_destroy)
|
|
||||||
|
|
||||||
# Preferences
|
# Preferences
|
||||||
self.settings = Settings.new()
|
self.settings = Settings.new()
|
||||||
|
|
||||||
|
@ -95,17 +92,6 @@ class Window(Gtk.ApplicationWindow):
|
||||||
self.title_end = " – UberWriter"
|
self.title_end = " – UberWriter"
|
||||||
self.set_headerbar_title("New File" + self.title_end)
|
self.set_headerbar_title("New File" + self.title_end)
|
||||||
|
|
||||||
self.word_count = self.builder.get_object('word_count')
|
|
||||||
self.char_count = self.builder.get_object('char_count')
|
|
||||||
|
|
||||||
# Setup status bar hide after 3 seconds
|
|
||||||
self.status_bar = self.builder.get_object('status_bar_box')
|
|
||||||
self.statusbar_revealer = self.builder.get_object('status_bar_revealer')
|
|
||||||
self.status_bar.get_style_context().add_class('status-bar-box')
|
|
||||||
self.status_bar_visible = True
|
|
||||||
self.was_motion = True
|
|
||||||
self.buffer_modified_for_status_bar = False
|
|
||||||
|
|
||||||
self.timestamp_last_mouse_motion = 0
|
self.timestamp_last_mouse_motion = 0
|
||||||
if self.settings.get_value("poll-motion"):
|
if self.settings.get_value("poll-motion"):
|
||||||
self.connect("motion-notify-event", self.on_motion_notify)
|
self.connect("motion-notify-event", self.on_motion_notify)
|
||||||
|
@ -118,11 +104,10 @@ class Window(Gtk.ApplicationWindow):
|
||||||
self.text_view = TextView()
|
self.text_view = TextView()
|
||||||
self.text_view.props.halign = Gtk.Align.CENTER
|
self.text_view.props.halign = Gtk.Align.CENTER
|
||||||
self.text_view.connect('focus-out-event', self.focus_out)
|
self.text_view.connect('focus-out-event', self.focus_out)
|
||||||
|
self.text_view.get_buffer().connect('changed', self.on_text_changed)
|
||||||
self.text_view.show()
|
self.text_view.show()
|
||||||
self.text_view.grab_focus()
|
self.text_view.grab_focus()
|
||||||
|
|
||||||
self.text_view.get_buffer().connect('changed', self.on_text_changed)
|
|
||||||
|
|
||||||
# Setup preview webview
|
# Setup preview webview
|
||||||
self.preview_webview = None
|
self.preview_webview = None
|
||||||
|
|
||||||
|
@ -132,7 +117,15 @@ class Window(Gtk.ApplicationWindow):
|
||||||
self.editor_viewport = self.builder.get_object('editor_viewport')
|
self.editor_viewport = self.builder.get_object('editor_viewport')
|
||||||
|
|
||||||
# Stats counter
|
# Stats counter
|
||||||
self.stats_counter = StatsCounter()
|
self.stats_counter_revealer = self.builder.get_object('stats_counter_revealer')
|
||||||
|
self.stats_button = self.builder.get_object('stats_counter')
|
||||||
|
self.stats_button.get_style_context().add_class('stats-counter')
|
||||||
|
self.stats_handler = StatsHandler(self.stats_button, self.text_view)
|
||||||
|
|
||||||
|
# Setup header/stats bar hide after 3 seconds
|
||||||
|
self.top_bottom_bars_visible = True
|
||||||
|
self.was_motion = True
|
||||||
|
self.buffer_modified_for_status_bar = False
|
||||||
|
|
||||||
# some people seems to have performance problems with the overlay.
|
# some people seems to have performance problems with the overlay.
|
||||||
# Let them disable it
|
# Let them disable it
|
||||||
|
@ -194,14 +187,6 @@ class Window(Gtk.ApplicationWindow):
|
||||||
# Redraw contents of window
|
# Redraw contents of window
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
def update_stats_counts(self, stats):
|
|
||||||
"""Updates line and character counts.
|
|
||||||
"""
|
|
||||||
|
|
||||||
(characters, words, sentences, (hours, minutes, seconds)) = stats
|
|
||||||
self.char_count.set_text(str(characters))
|
|
||||||
self.word_count.set_text(str(words))
|
|
||||||
|
|
||||||
def on_text_changed(self, *_args):
|
def on_text_changed(self, *_args):
|
||||||
"""called when the text changes, sets the self.did_change to true and
|
"""called when the text changes, sets the self.did_change to true and
|
||||||
updates the title and the counters to reflect that
|
updates the title and the counters to reflect that
|
||||||
|
@ -214,9 +199,6 @@ class Window(Gtk.ApplicationWindow):
|
||||||
|
|
||||||
self.buffer_modified_for_status_bar = True
|
self.buffer_modified_for_status_bar = True
|
||||||
|
|
||||||
if self.status_bar_visible:
|
|
||||||
self.stats_counter.count_stats(self.text_view.get_text(), self.update_stats_counts)
|
|
||||||
|
|
||||||
def set_fullscreen(self, state):
|
def set_fullscreen(self, state):
|
||||||
"""Puts the application in fullscreen mode and show/hides
|
"""Puts the application in fullscreen mode and show/hides
|
||||||
the poller for motion in the top border
|
the poller for motion in the top border
|
||||||
|
@ -485,6 +467,9 @@ class Window(Gtk.ApplicationWindow):
|
||||||
self.set_filename()
|
self.set_filename()
|
||||||
self.set_headerbar_title(_("New File") + self.title_end)
|
self.set_headerbar_title(_("New File") + self.title_end)
|
||||||
|
|
||||||
|
def update_default_stat(self):
|
||||||
|
self.stats_handler.update_default_stat()
|
||||||
|
|
||||||
def menu_toggle_sidebar(self, _widget=None):
|
def menu_toggle_sidebar(self, _widget=None):
|
||||||
"""WIP
|
"""WIP
|
||||||
"""
|
"""
|
||||||
|
@ -666,13 +651,13 @@ class Window(Gtk.ApplicationWindow):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if (self.was_motion is False
|
if (self.was_motion is False
|
||||||
and self.status_bar_visible
|
and self.top_bottom_bars_visible
|
||||||
and self.buffer_modified_for_status_bar
|
and self.buffer_modified_for_status_bar
|
||||||
and self.text_view.props.has_focus): # pylint: disable=no-member
|
and self.text_view.props.has_focus): # pylint: disable=no-member
|
||||||
# self.status_bar.set_state_flags(Gtk.StateFlags.INSENSITIVE, True)
|
# self.status_bar.set_state_flags(Gtk.StateFlags.INSENSITIVE, True)
|
||||||
self.statusbar_revealer.set_reveal_child(False)
|
self.stats_counter_revealer.set_reveal_child(False)
|
||||||
self.headerbar.hb_revealer.set_reveal_child(False)
|
self.headerbar.hb_revealer.set_reveal_child(False)
|
||||||
self.status_bar_visible = False
|
self.top_bottom_bars_visible = False
|
||||||
self.buffer_modified_for_status_bar = False
|
self.buffer_modified_for_status_bar = False
|
||||||
|
|
||||||
self.was_motion = False
|
self.was_motion = False
|
||||||
|
@ -691,26 +676,24 @@ class Window(Gtk.ApplicationWindow):
|
||||||
return
|
return
|
||||||
if now - self.timestamp_last_mouse_motion > 100:
|
if now - self.timestamp_last_mouse_motion > 100:
|
||||||
# react on motion by fading in headerbar and statusbar
|
# react on motion by fading in headerbar and statusbar
|
||||||
if self.status_bar_visible is False:
|
if self.top_bottom_bars_visible is False:
|
||||||
self.statusbar_revealer.set_reveal_child(True)
|
self.stats_counter_revealer.set_reveal_child(True)
|
||||||
self.headerbar.hb_revealer.set_reveal_child(True)
|
self.headerbar.hb_revealer.set_reveal_child(True)
|
||||||
self.headerbar.hb.props.opacity = 1
|
self.headerbar.hb.props.opacity = 1
|
||||||
self.status_bar_visible = True
|
self.top_bottom_bars_visible = True
|
||||||
self.buffer_modified_for_status_bar = False
|
self.buffer_modified_for_status_bar = False
|
||||||
self.stats_counter.count_stats(self.text_view.get_text(), self.update_stats_counts)
|
|
||||||
# self.status_bar.set_state_flags(Gtk.StateFlags.NORMAL, True)
|
# self.status_bar.set_state_flags(Gtk.StateFlags.NORMAL, True)
|
||||||
self.was_motion = True
|
self.was_motion = True
|
||||||
|
|
||||||
def focus_out(self, _widget, _data=None):
|
def focus_out(self, _widget, _data=None):
|
||||||
"""events called when the window losses focus
|
"""events called when the window losses focus
|
||||||
"""
|
"""
|
||||||
if self.status_bar_visible is False:
|
if self.top_bottom_bars_visible is False:
|
||||||
self.statusbar_revealer.set_reveal_child(True)
|
self.stats_counter_revealer.set_reveal_child(True)
|
||||||
self.headerbar.hb_revealer.set_reveal_child(True)
|
self.headerbar.hb_revealer.set_reveal_child(True)
|
||||||
self.headerbar.hb.props.opacity = 1
|
self.headerbar.hb.props.opacity = 1
|
||||||
self.status_bar_visible = True
|
self.top_bottom_bars_visible = True
|
||||||
self.buffer_modified_for_status_bar = False
|
self.buffer_modified_for_status_bar = False
|
||||||
self.stats_counter.count_stats(self.text_view.get_text(), self.update_stats_counts)
|
|
||||||
|
|
||||||
def draw_gradient(self, _widget, cr):
|
def draw_gradient(self, _widget, cr):
|
||||||
"""draw fading gradient over the top and the bottom of the
|
"""draw fading gradient over the top and the bottom of the
|
||||||
|
@ -789,8 +772,3 @@ class Window(Gtk.ApplicationWindow):
|
||||||
webbrowser.open(web_view.get_uri())
|
webbrowser.open(web_view.get_uri())
|
||||||
decision.ignore()
|
decision.ignore()
|
||||||
return True # Don't let the event "bubble up"
|
return True # Don't let the event "bubble up"
|
||||||
|
|
||||||
def on_destroy(self, _widget, _data=None):
|
|
||||||
"""Called when the Window is closing.
|
|
||||||
"""
|
|
||||||
self.stats_counter.stop()
|
|
||||||
|
|
Loading…
Reference in New Issue