forked from Mirrors/apostrophe
Basic linting (whitespace, docstrings, etc)
commit
cf9d3d6fbc
|
@ -1,221 +1,190 @@
|
|||
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
|
||||
### BEGIN LICENSE
|
||||
# BEGIN LICENSE
|
||||
# Copyright (C) 2012, Wolf Vollprecht <w.vollprecht@gmail.com>
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, 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
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
### END LICENSE
|
||||
# END LICENSE
|
||||
|
||||
|
||||
import gettext
|
||||
|
||||
import re
|
||||
from gi.repository import Gtk, Gdk # pylint: disable=E0611
|
||||
from gi.repository import Pango # pylint: disable=E0611
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
from . MarkupBuffer import MarkupBuffer
|
||||
|
||||
|
||||
class FormatShortcuts():
|
||||
"""Manage the insertion of formatting for insert them using shortcuts
|
||||
"""
|
||||
|
||||
def __init__(self, textbuffer, texteditor):
|
||||
self.TextBuffer = textbuffer
|
||||
self.TextEditor = texteditor
|
||||
|
||||
def rule(self):
|
||||
self.TextBuffer.insert_at_cursor("\n\n-------\n")
|
||||
self.TextEditor.scroll_mark_onscreen(self.TextBuffer.get_insert())
|
||||
self.regex = MarkupBuffer.regex
|
||||
def __init__(self, textbuffer, texteditor):
|
||||
self.text_buffer = textbuffer
|
||||
self.text_editor = texteditor
|
||||
self.regex = MarkupBuffer.regex
|
||||
|
||||
def bold(self):
|
||||
self.apply_format("**")
|
||||
|
||||
def italic(self):
|
||||
self.apply_format("*")
|
||||
def rule(self):
|
||||
"""insert ruler at cursor
|
||||
"""
|
||||
|
||||
def strikeout(self):
|
||||
self.apply_format("~~")
|
||||
self.text_buffer.insert_at_cursor("\n\n-------\n")
|
||||
self.text_editor.scroll_mark_onscreen(self.text_buffer.get_insert())
|
||||
|
||||
def apply_format(self, wrap = "*"):
|
||||
if self.TextBuffer.get_has_selection():
|
||||
## Find current highlighting
|
||||
def bold(self):
|
||||
"""set selected text as bold
|
||||
"""
|
||||
|
||||
(start, end) = self.TextBuffer.get_selection_bounds()
|
||||
moved = False
|
||||
if (
|
||||
start.get_offset() >= len(wrap) and
|
||||
end.get_offset() <= self.TextBuffer.get_char_count() - len(wrap)
|
||||
):
|
||||
moved = True
|
||||
ext_start = start.copy()
|
||||
ext_start.backward_chars(len(wrap))
|
||||
ext_end = end.copy()
|
||||
ext_end.forward_chars(len(wrap))
|
||||
text = self.TextBuffer.get_text(ext_start, ext_end, True)
|
||||
else:
|
||||
text = self.TextBuffer.get_text(start, end, True)
|
||||
|
||||
if moved and text.startswith(wrap) and text.endswith(wrap):
|
||||
text = text[len(wrap):-len(wrap)]
|
||||
new_text = text
|
||||
self.TextBuffer.delete(ext_start, ext_end)
|
||||
move_back = 0
|
||||
else:
|
||||
if moved:
|
||||
text = text[len(wrap):-len(wrap)]
|
||||
new_text = text.lstrip().rstrip()
|
||||
text = text.replace(new_text, wrap + new_text + wrap)
|
||||
self.apply_format("**")
|
||||
|
||||
self.TextBuffer.delete(start, end)
|
||||
move_back = len(wrap)
|
||||
|
||||
self.TextBuffer.insert_at_cursor(text)
|
||||
text_length = len(new_text)
|
||||
def italic(self):
|
||||
"""set selected text as italic
|
||||
"""
|
||||
self.apply_format("*")
|
||||
|
||||
else:
|
||||
helptext = ""
|
||||
if wrap == "*":
|
||||
helptext = _("emphasized text")
|
||||
elif wrap == "**":
|
||||
helptext = _("strong text")
|
||||
elif wrap == "~~":
|
||||
helptext = _("striked out text")
|
||||
def strikeout(self):
|
||||
"""set selected text as stricked out
|
||||
"""
|
||||
self.apply_format("~~")
|
||||
|
||||
self.TextBuffer.insert_at_cursor(wrap + helptext + wrap)
|
||||
text_length = len(helptext)
|
||||
move_back = len(wrap)
|
||||
def apply_format(self, wrap="*"):
|
||||
"""apply the given wrap to a selected text, or insert a helper text wraped
|
||||
if nothing is selected
|
||||
|
||||
cursor_mark = self.TextBuffer.get_insert()
|
||||
cursor_iter = self.TextBuffer.get_iter_at_mark(cursor_mark)
|
||||
cursor_iter.backward_chars(move_back)
|
||||
self.TextBuffer.move_mark_by_name('selection_bound', cursor_iter)
|
||||
cursor_iter.backward_chars(text_length)
|
||||
self.TextBuffer.move_mark_by_name('insert', cursor_iter)
|
||||
Keyword Arguments:
|
||||
wrap {str} -- [the format mark] (default: {"*"})
|
||||
"""
|
||||
|
||||
def unordered_list_item(self):
|
||||
helptext = _("List item")
|
||||
text_length = len(helptext)
|
||||
move_back = 0
|
||||
if self.TextBuffer.get_has_selection():
|
||||
(start, end) = self.TextBuffer.get_selection_bounds()
|
||||
if start.starts_line():
|
||||
text = self.TextBuffer.get_text(start, end, False)
|
||||
if text.startswith(("- ", "* ", "+ ")):
|
||||
delete_end = start.forward_chars(2)
|
||||
self.TextBuffer.delete(start, delete_end)
|
||||
else:
|
||||
self.TextBuffer.insert(start, "- ")
|
||||
else:
|
||||
move_back = 0
|
||||
cursor_mark = self.TextBuffer.get_insert()
|
||||
cursor_iter = self.TextBuffer.get_iter_at_mark(cursor_mark)
|
||||
if self.text_buffer.get_has_selection():
|
||||
# Find current highlighting
|
||||
(start, end) = self.text_buffer.get_selection_bounds()
|
||||
moved = False
|
||||
if (start.get_offset() >= len(wrap) and
|
||||
end.get_offset() <= self.text_buffer.get_char_count() - len(wrap)):
|
||||
moved = True
|
||||
ext_start = start.copy()
|
||||
ext_start.backward_chars(len(wrap))
|
||||
ext_end = end.copy()
|
||||
ext_end.forward_chars(len(wrap))
|
||||
text = self.text_buffer.get_text(ext_start, ext_end, True)
|
||||
else:
|
||||
text = self.text_buffer.get_text(start, end, True)
|
||||
|
||||
start_ext = cursor_iter.copy()
|
||||
start_ext.backward_lines(3)
|
||||
text = self.TextBuffer.get_text(cursor_iter, start_ext, False)
|
||||
lines = text.splitlines()
|
||||
if moved and text.startswith(wrap) and text.endswith(wrap):
|
||||
text = text[len(wrap):-len(wrap)]
|
||||
new_text = text
|
||||
self.text_buffer.delete(ext_start, ext_end)
|
||||
move_back = 0
|
||||
else:
|
||||
if moved:
|
||||
text = text[len(wrap):-len(wrap)]
|
||||
new_text = text.lstrip().rstrip()
|
||||
text = text.replace(new_text, wrap + new_text + wrap)
|
||||
|
||||
for line in reversed(lines):
|
||||
if len(line) and line.startswith(("- ", "* ", "+ ")):
|
||||
if cursor_iter.starts_line():
|
||||
self.TextBuffer.insert_at_cursor(line[:2] + helptext)
|
||||
else:
|
||||
self.TextBuffer.insert_at_cursor("\n" + line[:2] + helptext)
|
||||
break
|
||||
else:
|
||||
if len(lines[-1]) == 0 and len(lines[-2]) == 0:
|
||||
self.TextBuffer.insert_at_cursor("- " + helptext)
|
||||
elif len(lines[-1]) == 0:
|
||||
if cursor_iter.starts_line():
|
||||
self.TextBuffer.insert_at_cursor("- " + helptext)
|
||||
else:
|
||||
self.TextBuffer.insert_at_cursor("\n- " + helptext)
|
||||
else:
|
||||
self.TextBuffer.insert_at_cursor("\n\n- " + helptext)
|
||||
break
|
||||
self.text_buffer.delete(start, end)
|
||||
move_back = len(wrap)
|
||||
|
||||
self.select_edit(move_back, text_length)
|
||||
self.text_buffer.insert_at_cursor(text)
|
||||
text_length = len(new_text)
|
||||
|
||||
def ordered_list_item(self):
|
||||
pass
|
||||
else:
|
||||
helptext = ""
|
||||
if wrap == "*":
|
||||
helptext = _("emphasized text")
|
||||
elif wrap == "**":
|
||||
helptext = _("strong text")
|
||||
elif wrap == "~~":
|
||||
helptext = _("striked out text")
|
||||
|
||||
def select_edit(self, move_back, text_length):
|
||||
cursor_mark = self.TextBuffer.get_insert()
|
||||
cursor_iter = self.TextBuffer.get_iter_at_mark(cursor_mark)
|
||||
cursor_iter.backward_chars(move_back)
|
||||
self.TextBuffer.move_mark_by_name('selection_bound', cursor_iter)
|
||||
cursor_iter.backward_chars(text_length)
|
||||
self.TextBuffer.move_mark_by_name('insert', cursor_iter)
|
||||
self.TextEditor.scroll_mark_onscreen(self.TextBuffer.get_insert())
|
||||
self.text_buffer.insert_at_cursor(wrap + helptext + wrap)
|
||||
text_length = len(helptext)
|
||||
move_back = len(wrap)
|
||||
|
||||
def above(self, linestart = ""):
|
||||
if not cursor_iter.starts_line():
|
||||
return ""
|
||||
else:
|
||||
cursor_mark = self.TextBuffer.get_insert()
|
||||
cursor_iter = self.TextBuffer.get_iter_at_mark(cursor_mark)
|
||||
cursor_mark = self.text_buffer.get_insert()
|
||||
cursor_iter = self.text_buffer.get_iter_at_mark(cursor_mark)
|
||||
cursor_iter.backward_chars(move_back)
|
||||
self.text_buffer.move_mark_by_name('selection_bound', cursor_iter)
|
||||
cursor_iter.backward_chars(text_length)
|
||||
self.text_buffer.move_mark_by_name('insert', cursor_iter)
|
||||
|
||||
start_ext = cursor_iter.copy()
|
||||
start_ext.backward_lines(2)
|
||||
text = self.TextBuffer.get_text(cursor_iter, start_ext, False)
|
||||
lines = text.splitlines()
|
||||
def unordered_list_item(self):
|
||||
"""insert unordered list items or mark a selection as
|
||||
an item in an unordered list
|
||||
"""
|
||||
|
||||
#if line[-1].startswith
|
||||
helptext = _("List item")
|
||||
text_length = len(helptext)
|
||||
move_back = 0
|
||||
if self.text_buffer.get_has_selection():
|
||||
(start, end) = self.text_buffer.get_selection_bounds()
|
||||
if start.starts_line():
|
||||
text = self.text_buffer.get_text(start, end, False)
|
||||
if text.startswith(("- ", "* ", "+ ")):
|
||||
delete_end = start.forward_chars(2)
|
||||
self.text_buffer.delete(start, delete_end)
|
||||
else:
|
||||
self.text_buffer.insert(start, "- ")
|
||||
else:
|
||||
move_back = 0
|
||||
cursor_mark = self.text_buffer.get_insert()
|
||||
cursor_iter = self.text_buffer.get_iter_at_mark(cursor_mark)
|
||||
|
||||
def get_lines(self, cursor_iter):
|
||||
start_ext = cursor_iter.copy()
|
||||
start_ext.backward_lines(3)
|
||||
text = self.text_buffer.get_text(cursor_iter, start_ext, False)
|
||||
lines = text.splitlines()
|
||||
|
||||
start_ext = cursor_iter.copy()
|
||||
start_ext.backward_lines(2)
|
||||
text = self.TextBuffer.get_text(cursor_iter, start_ext, False)
|
||||
lines = text.splitlines()
|
||||
for line in reversed(lines):
|
||||
if line and line.startswith(("- ", "* ", "+ ")):
|
||||
if cursor_iter.starts_line():
|
||||
self.text_buffer.insert_at_cursor(line[:2] + helptext)
|
||||
else:
|
||||
self.text_buffer.insert_at_cursor(
|
||||
"\n" + line[:2] + helptext)
|
||||
break
|
||||
else:
|
||||
if not lines[-1] and not lines[-2]:
|
||||
self.text_buffer.insert_at_cursor("- " + helptext)
|
||||
elif not lines[-1]:
|
||||
if cursor_iter.starts_line():
|
||||
self.text_buffer.insert_at_cursor("- " + helptext)
|
||||
else:
|
||||
self.text_buffer.insert_at_cursor("\n- " + helptext)
|
||||
else:
|
||||
self.text_buffer.insert_at_cursor("\n\n- " + helptext)
|
||||
break
|
||||
|
||||
abs_line = cursor_iter.get_line()
|
||||
self.select_edit(move_back, text_length)
|
||||
|
||||
return reversed(lines)
|
||||
def ordered_list_item(self):
|
||||
# TODO: implement ordered lists
|
||||
pass
|
||||
|
||||
def heading(self, level = 0):
|
||||
helptext = _("Heading")
|
||||
before = ""
|
||||
if self.TextBuffer.get_has_selection():
|
||||
(start, end) = self.TextBuffer.get_selection_bounds()
|
||||
text = self.TextBuffer.get_text(start, end, False)
|
||||
self.TextBuffer.delete(start, end)
|
||||
else:
|
||||
text = helptext
|
||||
def select_edit(self, move_back, text_length):
|
||||
cursor_mark = self.text_buffer.get_insert()
|
||||
cursor_iter = self.text_buffer.get_iter_at_mark(cursor_mark)
|
||||
cursor_iter.backward_chars(move_back)
|
||||
self.text_buffer.move_mark_by_name('selection_bound', cursor_iter)
|
||||
cursor_iter.backward_chars(text_length)
|
||||
self.text_buffer.move_mark_by_name('insert', cursor_iter)
|
||||
self.text_editor.scroll_mark_onscreen(self.text_buffer.get_insert())
|
||||
|
||||
cursor_mark = self.TextBuffer.get_insert()
|
||||
cursor_iter = self.TextBuffer.get_iter_at_mark(cursor_mark)
|
||||
def heading(self):
|
||||
"""insert heading at cursor position or set selected text as one
|
||||
"""
|
||||
helptext = _("Heading")
|
||||
if self.text_buffer.get_has_selection():
|
||||
(start, end) = self.text_buffer.get_selection_bounds()
|
||||
text = self.text_buffer.get_text(start, end, False)
|
||||
self.text_buffer.delete(start, end)
|
||||
else:
|
||||
text = helptext
|
||||
|
||||
#lines = self.get_lines(cursor_iter)
|
||||
|
||||
#if cursor_iter.starts_line():
|
||||
# if lines[1] != '':
|
||||
# before = before + "\n"
|
||||
#else:
|
||||
# match = re.match(r'([\#]+ )(.+)', lines[0])
|
||||
# if match:
|
||||
# if match.group(1):
|
||||
#
|
||||
# print match.group(0)
|
||||
# if len(match.group(0)) < 6:
|
||||
# before = before + "#" * (len(match.group(0)) + 1)
|
||||
# else:
|
||||
# before = before + "#"
|
||||
# else:
|
||||
# before = before + "\n\n"
|
||||
#
|
||||
#
|
||||
# check_text = self.TextBuffer.get_text(start, cursor_iter, False).decode("utf-8")
|
||||
# print check_text
|
||||
|
||||
self.TextBuffer.insert_at_cursor("#" + " " + text)
|
||||
self.select_edit(0, len(text))
|
||||
self.text_buffer.insert_at_cursor("#" + " " + text)
|
||||
self.select_edit(0, len(text))
|
||||
|
|
|
@ -102,7 +102,7 @@ class MarkupBuffer():
|
|||
# self.ftag = self.TextBuffer.create_tag("pix_front", pixels_above_lines = 100)
|
||||
regex = {
|
||||
"ITALIC": re.compile(r"(\*|_)(.*?)\1", re.UNICODE), # *asdasd* // _asdasd asd asd_
|
||||
"STRONG": re.compile(r"(\*\*|__)(.*?)\1", re.UNICODE), # **as das** // __asdasdasd asd ad a__
|
||||
"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].+?~~"),
|
||||
|
|
|
@ -13,16 +13,14 @@
|
|||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
### END LICENSE
|
||||
|
||||
from gi.repository import Gtk, Gdk, GLib, Gio
|
||||
|
||||
from gettext import gettext as _
|
||||
from gi.repository import Gio
|
||||
|
||||
class Settings(Gio.Settings):
|
||||
|
||||
"""
|
||||
UberWriter Settings
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Init Settings
|
||||
|
@ -35,4 +33,4 @@ class Settings(Gio.Settings):
|
|||
"""
|
||||
settings = Gio.Settings.new("de.wolfvollprecht.UberWriter")
|
||||
settings.__class__ = Settings
|
||||
return settings
|
||||
return settings
|
||||
|
|
|
@ -43,8 +43,8 @@ class UberwriterAutoCorrect:
|
|||
if self.bubble:
|
||||
self.bubble_label.set_text(suggestion)
|
||||
else:
|
||||
pos = self.TextView.get_iter_location(iterator)
|
||||
pos_adjusted = self.TextView.buffer_to_window_coords(
|
||||
pos = self.text_view.get_iter_location(iterator)
|
||||
pos_adjusted = self.text_view.buffer_to_window_coords(
|
||||
Gtk.TextWindowType.TEXT, pos.x, pos.y + pos.height)
|
||||
self.bubble_eventbox = Gtk.EventBox.new()
|
||||
self.bubble = Gtk.Grid.new()
|
||||
|
@ -52,7 +52,7 @@ class UberwriterAutoCorrect:
|
|||
self.bubble_eventbox.add(self.bubble)
|
||||
self.bubble_eventbox.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
|
||||
self.bubble_eventbox.connect("button_press_event", self.clicked_bubble)
|
||||
self.TextView.add_child_in_window(self.bubble_eventbox,
|
||||
self.text_view.add_child_in_window(self.bubble_eventbox,
|
||||
Gtk.TextWindowType.TEXT,
|
||||
pos_adjusted[0], pos_adjusted[1])
|
||||
|
||||
|
@ -196,12 +196,12 @@ class UberwriterAutoCorrect:
|
|||
self.enchant_dict = enchant.Dict(self.language)
|
||||
|
||||
def __init__(self, textview, textbuffer):
|
||||
self.TextView = textview
|
||||
self.text_view = textview
|
||||
self.buffer = textbuffer
|
||||
self.suggestion = ""
|
||||
self.bubble = self.bubble_label = None
|
||||
self.buffer.connect_after('insert-text', self.text_insert)
|
||||
self.TextView.connect('key-press-event', self.key_pressed)
|
||||
self.text_view.connect('key-press-event', self.key_pressed)
|
||||
|
||||
self.language = "en_US"
|
||||
self.frequency_dict = {}
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
|
||||
### BEGIN LICENSE
|
||||
# BEGIN LICENSE
|
||||
# Copyright (C) 2012, Wolf Vollprecht <w.vollprecht@gmail.com>
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, 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
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
### END LICENSE
|
||||
# END LICENSE
|
||||
|
||||
import os
|
||||
import re
|
||||
import http.client
|
||||
import urllib
|
||||
from urllib.error import URLError, HTTPError
|
||||
from urllib.error import URLError
|
||||
import webbrowser
|
||||
import gettext
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
import logging
|
||||
import threading
|
||||
from pprint import pprint
|
||||
import telnetlib
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
from gi.repository import Gtk, Gdk, GdkPixbuf, GObject
|
||||
from uberwriter_lib import LatexToPNG
|
||||
|
@ -35,12 +34,9 @@ from .FixTable import FixTable
|
|||
|
||||
from .MarkupBuffer import MarkupBuffer
|
||||
|
||||
from gettext import gettext as _
|
||||
LOGGER = logging.getLogger('uberwriter')
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger('uberwriter')
|
||||
|
||||
GObject.threads_init() # Still needed?
|
||||
GObject.threads_init() # Still needed?
|
||||
|
||||
# TODO:
|
||||
# - Don't insert a span with id, it breaks the text to often
|
||||
|
@ -48,78 +44,77 @@ GObject.threads_init() # Still needed?
|
|||
# A jumping URL from that (for preview)
|
||||
# Also, after going to preview, set cursor back to where it was
|
||||
|
||||
import telnetlib
|
||||
|
||||
import subprocess
|
||||
class DictAccessor():
|
||||
|
||||
class DictAccessor(object):
|
||||
|
||||
def __init__( self, host='pan.alephnull.com', port=2628, timeout=60 ):
|
||||
self.tn = telnetlib.Telnet( host, port )
|
||||
def __init__(self, host='pan.alephnull.com', port=2628, timeout=60):
|
||||
self.telnet = telnetlib.Telnet(host, port)
|
||||
self.timeout = timeout
|
||||
self.login_response = self.tn.expect( [ self.reEndResponse ], self.timeout )[ 2 ]
|
||||
self.login_response = self.telnet.expect(
|
||||
[self.reEndResponse], self.timeout)[2]
|
||||
|
||||
def get_online(self, word):
|
||||
process = subprocess.Popen(['dict', '-d', 'wn', word],
|
||||
stdout=subprocess.PIPE)
|
||||
return process.communicate()[0]
|
||||
|
||||
def getOnline(self, word):
|
||||
p = subprocess.Popen(['dict', '-d', 'wn', word], stdout=subprocess.PIPE)
|
||||
return p.communicate()[0]
|
||||
def run_command(self, cmd):
|
||||
self.telnet.write(cmd.encode('utf-8') + b'\r\n')
|
||||
return self.telnet.expect([self.reEndResponse], self.timeout)[2]
|
||||
|
||||
def runCommand( self, cmd ):
|
||||
self.tn.write( cmd.encode('utf-8') + b'\r\n' )
|
||||
return self.tn.expect( [ self.reEndResponse ], self.timeout )[ 2 ]
|
||||
|
||||
def getMatches( self, database, strategy, word ):
|
||||
if database in [ '', 'all' ]:
|
||||
def get_matches(self, database, strategy, word):
|
||||
if database in ['', 'all']:
|
||||
d = '*'
|
||||
else:
|
||||
d = database
|
||||
if strategy in [ '', 'default' ]:
|
||||
if strategy in ['', 'default']:
|
||||
s = '.'
|
||||
else:
|
||||
s = strategy
|
||||
w = word.replace( '"', r'\"' )
|
||||
tsplit = self.runCommand( 'MATCH %s %s "%s"' % ( d, s, w ) ).splitlines( )
|
||||
mlist = list( )
|
||||
if tsplit[ -1 ].startswith( b'250 ok' ) and tsplit[ 0 ].startswith( b'1' ):
|
||||
mlines = tsplit[ 1:-2 ]
|
||||
w = word.replace('"', r'\"')
|
||||
tsplit = self.run_command('MATCH %s %s "%s"' % (d, s, w)).splitlines()
|
||||
mlist = list()
|
||||
if tsplit[-1].startswith(b'250 ok') and tsplit[0].startswith(b'1'):
|
||||
mlines = tsplit[1:-2]
|
||||
for line in mlines:
|
||||
lsplit = line.strip( ).split( )
|
||||
db = lsplit[ 0 ]
|
||||
word = unquote( ' '.join( lsplit[ 1: ] ) )
|
||||
mlist.append( ( db, word ) )
|
||||
lsplit = line.strip().split()
|
||||
db = lsplit[0]
|
||||
word = unquote(' '.join(lsplit[1:]))
|
||||
mlist.append((db, word))
|
||||
return mlist
|
||||
|
||||
reEndResponse = re.compile( br'^[2-5][0-58][0-9] .*\r\n$', re.DOTALL + re.MULTILINE )
|
||||
reDefinition = re.compile( br'^151(.*?)^\.', re.DOTALL + re.MULTILINE )
|
||||
reEndResponse = re.compile(
|
||||
br'^[2-5][0-58][0-9] .*\r\n$', re.DOTALL + re.MULTILINE)
|
||||
reDefinition = re.compile(br'^151(.*?)^\.', re.DOTALL + re.MULTILINE)
|
||||
|
||||
def getDefinition( self, database, word ):
|
||||
if database in [ '', 'all' ]:
|
||||
def get_definition(self, database, word):
|
||||
if database in ['', 'all']:
|
||||
d = '*'
|
||||
else:
|
||||
d = database
|
||||
w = word.replace( '"', r'\"' )
|
||||
dsplit = self.runCommand( 'DEFINE %s "%s"' % ( d, w ) ).splitlines( True )
|
||||
w = word.replace('"', r'\"')
|
||||
dsplit = self.run_command('DEFINE %s "%s"' % (d, w)).splitlines(True)
|
||||
# dsplit = self.getOnline(word).splitlines()
|
||||
|
||||
dlist = list( )
|
||||
if dsplit[ -1 ].startswith( b'250 ok' ) and dsplit[ 0 ].startswith( b'1' ):
|
||||
dlines = dsplit[ 1:-1 ]
|
||||
dtext = b''.join( dlines )
|
||||
dlist = self.reDefinition.findall( dtext )
|
||||
dlist = list()
|
||||
if dsplit[-1].startswith(b'250 ok') and dsplit[0].startswith(b'1'):
|
||||
dlines = dsplit[1:-1]
|
||||
dtext = b''.join(dlines)
|
||||
dlist = self.reDefinition.findall(dtext)
|
||||
# print(dlist)
|
||||
dlist = [ dtext ]
|
||||
dlist = [dtext]
|
||||
# dlist = dsplit # not using the localhost telnet connection
|
||||
return dlist
|
||||
|
||||
def close( self ):
|
||||
t = self.runCommand( 'QUIT' )
|
||||
self.tn.close( )
|
||||
def close(self):
|
||||
t = self.run_command('QUIT')
|
||||
self.telnet.close()
|
||||
return t
|
||||
|
||||
def parse_wordnet(self, response):
|
||||
# consisting of group (n,v,adj,adv)
|
||||
# number, description, examples, synonyms, antonyms
|
||||
capture = {}
|
||||
|
||||
lines = response.splitlines()
|
||||
lines = lines[2:]
|
||||
lines = ' '.join(lines)
|
||||
|
@ -129,9 +124,9 @@ class DictAccessor(object):
|
|||
act_res = {'defs': [], 'class': 'none', 'num': 'None'}
|
||||
for l in lines:
|
||||
l = l.strip()
|
||||
if len(l) == 0:
|
||||
if not l:
|
||||
continue
|
||||
if l in ['adv', 'adj', 'n', 'v']:
|
||||
if l in ['adv', 'adj', 'n', 'v']:
|
||||
if act_res:
|
||||
res.append(act_res.copy())
|
||||
act_res = {}
|
||||
|
@ -160,7 +155,7 @@ class DictAccessor(object):
|
|||
act_def['description'] = []
|
||||
for llll in lll:
|
||||
llll = llll.strip()
|
||||
if(llll.strip().startswith('"')):
|
||||
if llll.strip().startswith('"'):
|
||||
act_def['examples'].append(llll)
|
||||
else:
|
||||
act_def['description'].append(llll)
|
||||
|
@ -172,8 +167,9 @@ class DictAccessor(object):
|
|||
res.append(act_res.copy())
|
||||
return res
|
||||
|
||||
|
||||
def check_url(url, item, spinner):
|
||||
logger.debug("thread started, checking url")
|
||||
LOGGER.debug("thread started, checking url")
|
||||
error = False
|
||||
try:
|
||||
response = urllib.request.urlopen(url)
|
||||
|
@ -183,25 +179,27 @@ def check_url(url, item, spinner):
|
|||
|
||||
if not error:
|
||||
if (response.code / 100) >= 4:
|
||||
logger.debug("Website not available")
|
||||
LOGGER.debug("Website not available")
|
||||
text = _("Website is not available")
|
||||
else:
|
||||
text = _("Website is available")
|
||||
logger.debug("Response: %s" % text)
|
||||
LOGGER.debug("Response: %s" % text)
|
||||
spinner.destroy()
|
||||
item.set_label(text)
|
||||
|
||||
|
||||
def get_dictionary(term):
|
||||
da = DictAccessor()
|
||||
output = da.getDefinition('wn', term)
|
||||
if(len(output)):
|
||||
output = da.get_definition('wn', term)
|
||||
if output:
|
||||
output = output[0]
|
||||
else:
|
||||
return None
|
||||
return da.parse_wordnet(output.decode(encoding='UTF-8'))
|
||||
|
||||
|
||||
def get_web_thumbnail(url, item, spinner):
|
||||
logger.debug("thread started, generating thumb")
|
||||
LOGGER.debug("thread started, generating thumb")
|
||||
|
||||
# error = False
|
||||
|
||||
|
@ -211,9 +209,10 @@ def get_web_thumbnail(url, item, spinner):
|
|||
|
||||
filename = tempfile.mktemp(suffix='.png')
|
||||
thumb_size = '256' # size can only be 32, 64, 96, 128 or 256!
|
||||
args = ['gnome-web-photo', '--mode=thumbnail', '-s', thumb_size, url, filename]
|
||||
p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
output = p.communicate()[0]
|
||||
args = ['gnome-web-photo', '--mode=thumbnail',
|
||||
'-s', thumb_size, url, filename]
|
||||
process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
_output = process.communicate()[0]
|
||||
|
||||
image = Gtk.Image.new_from_file(filename)
|
||||
image.show()
|
||||
|
@ -229,6 +228,7 @@ def get_web_thumbnail(url, item, spinner):
|
|||
item.add(image)
|
||||
item.show()
|
||||
|
||||
|
||||
def fill_lexikon_bubble(vocab, lexikon_dict):
|
||||
grid = Gtk.Grid.new()
|
||||
i = 0
|
||||
|
@ -259,31 +259,30 @@ def fill_lexikon_bubble(vocab, lexikon_dict):
|
|||
i = i + 1
|
||||
grid.show_all()
|
||||
return grid
|
||||
else:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class UberwriterInlinePreview():
|
||||
|
||||
def __init__(self, view, text_buffer):
|
||||
self.TextView = view
|
||||
self.TextBuffer = text_buffer
|
||||
self.LatexConverter = LatexToPNG.LatexToPNG()
|
||||
cursor_mark = self.TextBuffer.get_insert()
|
||||
cursor_iter = self.TextBuffer.get_iter_at_mark(cursor_mark)
|
||||
self.ClickMark = self.TextBuffer.create_mark('click', cursor_iter)
|
||||
self.text_view = view
|
||||
self.text_buffer = text_buffer
|
||||
self.latex_converter = LatexToPNG.LatexToPNG()
|
||||
cursor_mark = self.text_buffer.get_insert()
|
||||
cursor_iter = self.text_buffer.get_iter_at_mark(cursor_mark)
|
||||
self.click_mark = self.text_buffer.create_mark('click', cursor_iter)
|
||||
# Events for popup menu
|
||||
# self.TextView.connect_after('populate-popup', self.populate_popup)
|
||||
# self.TextView.connect_after('popup-menu', self.move_popup)
|
||||
self.TextView.connect('button-press-event', self.click_move_button)
|
||||
self.text_view.connect('button-press-event', self.click_move_button)
|
||||
self.popover = None
|
||||
self.settings = Settings.new()
|
||||
|
||||
def open_popover_with_widget(self, widget):
|
||||
a = self.TextBuffer.create_child_anchor(self.TextBuffer.get_iter_at_mark(self.ClickMark))
|
||||
a = self.text_buffer.create_child_anchor(
|
||||
self.text_buffer.get_iter_at_mark(self.click_mark))
|
||||
lbl = Gtk.Label('')
|
||||
self.TextView.add_child_at_anchor(lbl, a)
|
||||
self.text_view.add_child_at_anchor(lbl, a)
|
||||
lbl.show()
|
||||
# a = Gtk.Window.new(Gtk.WindowType.POPUP)
|
||||
# a.set_transient_for(self.TextView.get_toplevel())
|
||||
|
@ -296,7 +295,6 @@ class UberwriterInlinePreview():
|
|||
# if(event.keyval == Gdk.KEY_Escape):
|
||||
# widget.destroy()
|
||||
# a.connect('key-press-event', close)
|
||||
b = Gtk.Grid.new()
|
||||
alignment = Gtk.Alignment()
|
||||
alignment.props.margin_bottom = 5
|
||||
alignment.props.margin_top = 5
|
||||
|
@ -310,7 +308,7 @@ class UberwriterInlinePreview():
|
|||
self.popover.get_style_context().add_class("QuickPreviewPopup")
|
||||
self.popover.add(alignment)
|
||||
# a.add(alignment)
|
||||
dismiss, rect = self.popover.get_pointing_to()
|
||||
_dismiss, rect = self.popover.get_pointing_to()
|
||||
rect.y = rect.y - 20
|
||||
self.popover.set_pointing_to(rect)
|
||||
# widget = Gtk.Label.new("testasds a;12j3 21 lk3j213")
|
||||
|
@ -322,21 +320,21 @@ class UberwriterInlinePreview():
|
|||
# print(self.popover)
|
||||
self.popover.set_property('width-request', 50)
|
||||
|
||||
def click_move_button(self, widget, event):
|
||||
def click_move_button(self, _widget, event):
|
||||
if event.button == 1 and event.state & Gdk.ModifierType.CONTROL_MASK:
|
||||
x, y = self.TextView.window_to_buffer_coords(2,
|
||||
int(event.x),
|
||||
int(event.y))
|
||||
self.TextBuffer.move_mark(self.ClickMark,
|
||||
self.TextView.get_iter_at_location(x, y).iter)
|
||||
self.populate_popup(self.TextView)
|
||||
x, y = self.text_view.window_to_buffer_coords(2,
|
||||
int(event.x),
|
||||
int(event.y))
|
||||
self.text_buffer.move_mark(self.click_mark,
|
||||
self.text_view.get_iter_at_location(x, y).iter)
|
||||
self.populate_popup(self.text_view)
|
||||
|
||||
def fix_table(self, widget, data=None):
|
||||
logger.debug('fixing that table')
|
||||
f = FixTable(self.TextBuffer)
|
||||
f.fix_table()
|
||||
def fix_table(self, _widget, _data=None):
|
||||
LOGGER.debug('fixing that table')
|
||||
fix_table = FixTable(self.text_buffer)
|
||||
fix_table.fix_table()
|
||||
|
||||
def populate_popup(self, editor, data=None):
|
||||
def populate_popup(self, _editor, _data=None):
|
||||
# popover = Gtk.Popover.new(editor)
|
||||
# pop_cont = Gtk.Container.new()
|
||||
# popover.add(pop_cont)
|
||||
|
@ -354,14 +352,14 @@ class UberwriterInlinePreview():
|
|||
# menu.prepend(table_item)
|
||||
# menu.show()
|
||||
|
||||
start_iter = self.TextBuffer.get_iter_at_mark(self.ClickMark)
|
||||
start_iter = self.text_buffer.get_iter_at_mark(self.click_mark)
|
||||
# Line offset of click mark
|
||||
line_offset = start_iter.get_line_offset()
|
||||
end_iter = start_iter.copy()
|
||||
start_iter.set_line_offset(0)
|
||||
end_iter.forward_to_line_end()
|
||||
|
||||
text = self.TextBuffer.get_text(start_iter, end_iter, False)
|
||||
text = self.text_buffer.get_text(start_iter, end_iter, False)
|
||||
|
||||
math = MarkupBuffer.regex["MATH"]
|
||||
link = MarkupBuffer.regex["LINK"]
|
||||
|
@ -369,22 +367,18 @@ class UberwriterInlinePreview():
|
|||
footnote = re.compile(r'\[\^([^\s]+?)\]')
|
||||
image = re.compile(r"!\[(.*?)\]\((.+?)\)")
|
||||
|
||||
buf = self.TextBuffer
|
||||
context_offset = 0
|
||||
|
||||
matchlist = []
|
||||
|
||||
found_match = False
|
||||
|
||||
matches = re.finditer(math, text)
|
||||
for match in matches:
|
||||
logger.debug(match.group(1))
|
||||
if match.start() < line_offset and match.end() > line_offset:
|
||||
success, result = self.LatexConverter.generatepng(match.group(1))
|
||||
LOGGER.debug(match.group(1))
|
||||
if match.start() < line_offset < match.end():
|
||||
success, result = self.latex_converter.generatepng(
|
||||
match.group(1))
|
||||
if success:
|
||||
image = Gtk.Image.new_from_file(result)
|
||||
image.show()
|
||||
logger.debug("logging image")
|
||||
LOGGER.debug("logging image")
|
||||
# item.add(image)
|
||||
self.open_popover_with_widget(image)
|
||||
else:
|
||||
|
@ -407,12 +401,12 @@ class UberwriterInlinePreview():
|
|||
# Links
|
||||
matches = re.finditer(link, text)
|
||||
for match in matches:
|
||||
if match.start() < line_offset and match.end() > line_offset:
|
||||
if match.start() < line_offset < match.end():
|
||||
text = text[text.find("http://"):-1]
|
||||
|
||||
item.connect("activate", lambda w: webbrowser.open(text))
|
||||
|
||||
logger.debug(text)
|
||||
LOGGER.debug(text)
|
||||
|
||||
statusitem = Gtk.MenuItem.new()
|
||||
statusitem.show()
|
||||
|
@ -421,9 +415,9 @@ class UberwriterInlinePreview():
|
|||
spinner.start()
|
||||
statusitem.add(spinner)
|
||||
spinner.show()
|
||||
|
||||
thread = threading.Thread(target=check_url,
|
||||
args=(text, statusitem, spinner))
|
||||
|
||||
thread = threading.Thread(target=check_url,
|
||||
args=(text, statusitem, spinner))
|
||||
thread.start()
|
||||
|
||||
webphoto_item = Gtk.MenuItem.new()
|
||||
|
@ -433,15 +427,15 @@ class UberwriterInlinePreview():
|
|||
webphoto_item.add(spinner_2)
|
||||
spinner_2.show()
|
||||
|
||||
thread_image = threading.Thread(target=get_web_thumbnail,
|
||||
args=(text, webphoto_item, spinner_2))
|
||||
thread_image = threading.Thread(target=get_web_thumbnail,
|
||||
args=(text, webphoto_item, spinner_2))
|
||||
|
||||
thread_image.start()
|
||||
|
||||
item.set_label(_("Open Link in Webbrowser"))
|
||||
item.show()
|
||||
self.open_popover_with_widget(webphoto_item)
|
||||
|
||||
|
||||
# menu.prepend(separator)
|
||||
# separator.show()
|
||||
|
||||
|
@ -450,25 +444,25 @@ class UberwriterInlinePreview():
|
|||
# menu.prepend(item)
|
||||
# menu.show()
|
||||
|
||||
|
||||
found_match = True
|
||||
break
|
||||
|
||||
if not found_match:
|
||||
matches = re.finditer(image, text)
|
||||
for match in matches:
|
||||
if match.start() < line_offset and match.end() > line_offset:
|
||||
if match.start() < line_offset < match.end():
|
||||
path = match.group(2)
|
||||
if path.startswith("file://"):
|
||||
path = path[7:]
|
||||
elif not path.startswith("/"):
|
||||
# then the path is relative
|
||||
base_path = self.settings.get_value("open-file-path").get_string()
|
||||
base_path = self.settings.get_value(
|
||||
"open-file-path").get_string()
|
||||
path = base_path + "/" + path
|
||||
|
||||
logger.info(path)
|
||||
pb = GdkPixbuf.Pixbuf.new_from_file_at_size(path, 400, 300)
|
||||
image = Gtk.Image.new_from_pixbuf(pb)
|
||||
|
||||
LOGGER.info(path)
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(path, 400, 300)
|
||||
image = Gtk.Image.new_from_pixbuf(pixbuf)
|
||||
image.show()
|
||||
self.open_popover_with_widget(image)
|
||||
item.set_property('width-request', 50)
|
||||
|
@ -486,15 +480,18 @@ class UberwriterInlinePreview():
|
|||
if not found_match:
|
||||
matches = re.finditer(footnote, text)
|
||||
for match in matches:
|
||||
if match.start() < line_offset and match.end() > line_offset:
|
||||
logger.debug(match.group(1))
|
||||
footnote_match = re.compile(r"\[\^" + match.group(1) + r"\]: (.+(?:\n|\Z)(?:^[\t].+(?:\n|\Z))*)", re.MULTILINE)
|
||||
if match.start() < line_offset < match.end():
|
||||
LOGGER.debug(match.group(1))
|
||||
footnote_match = re.compile(
|
||||
r"\[\^" + match.group(1) + r"\]: (.+(?:\n|\Z)(?:^[\t].+(?:\n|\Z))*)",
|
||||
re.MULTILINE)
|
||||
replace = re.compile(r"^\t", re.MULTILINE)
|
||||
start, end = self.TextBuffer.get_bounds()
|
||||
fn_match = re.search(footnote_match, self.TextBuffer.get_text(start, end, False))
|
||||
start, end = self.text_buffer.get_bounds()
|
||||
fn_match = re.search(
|
||||
footnote_match, self.text_buffer.get_text(start, end, False))
|
||||
label = Gtk.Label()
|
||||
label.set_alignment(0.0, 0.5)
|
||||
logger.debug(fn_match)
|
||||
LOGGER.debug(fn_match)
|
||||
if fn_match:
|
||||
result = re.sub(replace, "", fn_match.group(1))
|
||||
if result.endswith("\n"):
|
||||
|
@ -517,21 +514,19 @@ class UberwriterInlinePreview():
|
|||
break
|
||||
|
||||
if not found_match:
|
||||
start_iter = self.TextBuffer.get_iter_at_mark(self.ClickMark)
|
||||
start_iter = self.text_buffer.get_iter_at_mark(self.click_mark)
|
||||
start_iter.backward_word_start()
|
||||
end_iter = start_iter.copy()
|
||||
end_iter.forward_word_end()
|
||||
word = self.TextBuffer.get_text(start_iter, end_iter, False)
|
||||
word = self.text_buffer.get_text(start_iter, end_iter, False)
|
||||
terms = get_dictionary(word)
|
||||
if terms:
|
||||
sc = Gtk.ScrolledWindow.new()
|
||||
sc.add(fill_lexikon_bubble(word, terms))
|
||||
sc.props.width_request = 500
|
||||
sc.props.height_request = 400
|
||||
sc.show_all()
|
||||
self.open_popover_with_widget(sc)
|
||||
|
||||
return
|
||||
scrolled_window = Gtk.ScrolledWindow.new()
|
||||
scrolled_window.add(fill_lexikon_bubble(word, terms))
|
||||
scrolled_window.props.width_request = 500
|
||||
scrolled_window.props.height_request = 400
|
||||
scrolled_window.show_all()
|
||||
self.open_popover_with_widget(scrolled_window)
|
||||
|
||||
def move_popup(self):
|
||||
pass
|
||||
|
|
|
@ -44,8 +44,6 @@ Extending
|
|||
A TextEditor is Gtk.TextView
|
||||
|
||||
"""
|
||||
|
||||
|
||||
try:
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
@ -55,8 +53,6 @@ try:
|
|||
except:
|
||||
print("couldn't load depencies")
|
||||
|
||||
|
||||
|
||||
import logging
|
||||
LOGGER = logging.getLogger('uberwriter')
|
||||
|
||||
|
@ -104,7 +100,6 @@ class TextEditor(Gtk.TextView):
|
|||
'redo': (GObject.SIGNAL_ACTION, None, ())
|
||||
}
|
||||
|
||||
# TODO: delete this?
|
||||
def scroll_to_iter(self, iterable, *args):
|
||||
self.get_buffer().place_cursor(iterable)
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ import os
|
|||
import codecs
|
||||
import webbrowser
|
||||
import urllib
|
||||
import pickle
|
||||
import logging
|
||||
|
||||
import mimetypes
|
||||
|
@ -195,6 +194,8 @@ class UberwriterWindow(Window):
|
|||
self.check_scroll(self.text_buffer.get_insert())
|
||||
if self.spellcheck:
|
||||
self.spell_checker._misspelled.set_property('underline', 0)
|
||||
self.click_event = self.text_editor.connect("button-release-event",
|
||||
self.on_focusmode_click)
|
||||
else:
|
||||
self.remove_typewriter()
|
||||
self.focusmode = False
|
||||
|
@ -210,7 +211,14 @@ class UberwriterWindow(Window):
|
|||
self.update_line_and_char_count()
|
||||
self.check_scroll()
|
||||
if self.spellcheck:
|
||||
self.spell_checker._misspelled.set_property('underline', 4)
|
||||
self.SpellChecker._misspelled.set_property('underline', 4)
|
||||
_click_event = self.text_editor.disconnect(self.click_event)
|
||||
|
||||
def on_focusmode_click(self, *_args):
|
||||
"""call MarkupBuffer to mark as bold the line where the cursor is
|
||||
"""
|
||||
|
||||
self.markup_buffer.markup_buffer(1)
|
||||
|
||||
def scroll_smoothly(self, widget, frame_clock, _data=None):
|
||||
if self.smooth_scroll_data['target_pos'] == -1:
|
||||
|
|
|
@ -0,0 +1,568 @@
|
|||
[MASTER]
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code.
|
||||
extension-pkg-whitelist=
|
||||
|
||||
# Add files or directories to the blacklist. They should be base names, not
|
||||
# paths.
|
||||
ignore=CVS
|
||||
|
||||
# Add files or directories matching the regex patterns to the blacklist. The
|
||||
# regex matches against base names, not paths.
|
||||
ignore-patterns=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
|
||||
# number of processors available to use.
|
||||
jobs=1
|
||||
|
||||
# Control the amount of potential inferred values when inferring a single
|
||||
# object. This can help the performance when dealing with large functions or
|
||||
# complex, nested conditions.
|
||||
limit-inference-results=100
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# Specify a configuration file.
|
||||
#rcfile=
|
||||
|
||||
# When enabled, pylint would attempt to guess common misconfiguration and emit
|
||||
# user-friendly hints instead of false-positive error messages.
|
||||
suggestion-mode=yes
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
|
||||
confidence=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once). You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use "--disable=all --enable=classes
|
||||
# --disable=W".
|
||||
# disable=print-statement,
|
||||
parameter-unpacking,
|
||||
unpacking-in-except,
|
||||
old-raise-syntax,
|
||||
backtick,
|
||||
long-suffix,
|
||||
old-ne-operator,
|
||||
old-octal-literal,
|
||||
import-star-module-level,
|
||||
non-ascii-bytes-literal,
|
||||
raw-checker-failed,
|
||||
bad-inline-option,
|
||||
locally-disabled,
|
||||
locally-enabled,
|
||||
file-ignored,
|
||||
suppressed-message,
|
||||
useless-suppression,
|
||||
deprecated-pragma,
|
||||
use-symbolic-message-instead,
|
||||
apply-builtin,
|
||||
basestring-builtin,
|
||||
buffer-builtin,
|
||||
cmp-builtin,
|
||||
coerce-builtin,
|
||||
execfile-builtin,
|
||||
file-builtin,
|
||||
long-builtin,
|
||||
raw_input-builtin,
|
||||
reduce-builtin,
|
||||
standarderror-builtin,
|
||||
unicode-builtin,
|
||||
xrange-builtin,
|
||||
coerce-method,
|
||||
delslice-method,
|
||||
getslice-method,
|
||||
setslice-method,
|
||||
no-absolute-import,
|
||||
old-division,
|
||||
dict-iter-method,
|
||||
dict-view-method,
|
||||
next-method-called,
|
||||
metaclass-assignment,
|
||||
indexing-exception,
|
||||
raising-string,
|
||||
reload-builtin,
|
||||
oct-method,
|
||||
hex-method,
|
||||
nonzero-method,
|
||||
cmp-method,
|
||||
input-builtin,
|
||||
round-builtin,
|
||||
intern-builtin,
|
||||
unichr-builtin,
|
||||
map-builtin-not-iterating,
|
||||
zip-builtin-not-iterating,
|
||||
range-builtin-not-iterating,
|
||||
filter-builtin-not-iterating,
|
||||
using-cmp-argument,
|
||||
eq-without-hash,
|
||||
div-method,
|
||||
idiv-method,
|
||||
rdiv-method,
|
||||
exception-message-attribute,
|
||||
invalid-str-codec,
|
||||
sys-max-int,
|
||||
bad-python3-import,
|
||||
deprecated-string-function,
|
||||
deprecated-str-translate-call,
|
||||
deprecated-itertools-function,
|
||||
deprecated-types-field,
|
||||
next-method-defined,
|
||||
dict-items-not-iterating,
|
||||
dict-keys-not-iterating,
|
||||
dict-values-not-iterating,
|
||||
deprecated-operator-function,
|
||||
deprecated-urllib-function,
|
||||
xreadlines-attribute,
|
||||
deprecated-sys-function,
|
||||
exception-escape,
|
||||
comprehension-escape
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
enable=c-extension-no-member
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Python expression which should return a note less than 10 (10 is the highest
|
||||
# note). You have access to the variables errors warning, statement which
|
||||
# respectively contain the number of errors / warnings messages and the total
|
||||
# number of statements analyzed. This is used by the global evaluation report
|
||||
# (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details.
|
||||
#msg-template=
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, json
|
||||
# and msvs (visual studio). You can also give a reporter class, e.g.
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
output-format=msvs
|
||||
|
||||
# Tells whether to display a full report or only the messages.
|
||||
reports=yes
|
||||
|
||||
# Activate the evaluation score.
|
||||
score=yes
|
||||
|
||||
|
||||
[REFACTORING]
|
||||
|
||||
# Maximum number of nested blocks for function / method body
|
||||
max-nested-blocks=5
|
||||
|
||||
# Complete name of functions that never returns. When checking for
|
||||
# inconsistent-return-statements if a never returning function is called then
|
||||
# it will be considered as an explicit return statement and no message will be
|
||||
# printed.
|
||||
never-returning-functions=sys.exit
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=100
|
||||
|
||||
# Maximum number of lines in a module.
|
||||
max-module-lines=1000
|
||||
|
||||
# List of optional constructs for which whitespace checking is disabled. `dict-
|
||||
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
|
||||
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
|
||||
# `empty-line` allows space-only lines.
|
||||
no-space-check=trailing-comma,
|
||||
dict-separator
|
||||
|
||||
# Allow the body of a class to be on the same line as the declaration if body
|
||||
# contains single statement.
|
||||
single-line-class-stmt=no
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=no
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format.
|
||||
logging-modules=logging
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Limits count of emitted suggestions for spelling mistakes.
|
||||
max-spelling-suggestions=4
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: he (hspell), en_IE
|
||||
# (hunspell), es_BO (hunspell), en_NZ (hunspell), es_DO (hunspell), es_MX
|
||||
# (hunspell), en_ZA (hunspell), en_IN (hunspell), en_TT (hunspell), ca
|
||||
# (aspell), ca_FR (hunspell), es_HN (hunspell), ca_AD (hunspell), es_SV
|
||||
# (hunspell), es_PA (hunspell), en_DK (hunspell), es_NI (hunspell), es_PE
|
||||
# (hunspell), en_SG (hunspell), es_UY (hunspell), en_BS (hunspell), en_BW
|
||||
# (hunspell), es_CL (hunspell), es_AR (hunspell), en_BZ (hunspell), es_CO
|
||||
# (hunspell), en_ZW (hunspell), en_HK (hunspell), es_CR (hunspell), en_NA
|
||||
# (hunspell), es_PR (hunspell), en_JM (hunspell), es_VE (hunspell), en_AG
|
||||
# (hunspell), es_CU (hunspell), en_NG (hunspell), ca_ES (hunspell), es_ES
|
||||
# (hunspell), es_ANY (hunspell), es_EC (hunspell), es_GT (hunspell), en_PH
|
||||
# (hunspell), en_GB (hunspell), en_US (hunspell), ca_IT (hunspell), es_PY
|
||||
# (hunspell), en_GH (hunspell)..
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to indicated private dictionary in
|
||||
# --spelling-private-dict-file option instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Ignore imports when computing similarities.
|
||||
ignore-imports=no
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# Tells whether to warn about missing members when the owner of the attribute
|
||||
# is inferred to be None.
|
||||
ignore-none=yes
|
||||
|
||||
# This flag controls whether pylint should warn about no-member and similar
|
||||
# checks whenever an opaque object is returned when inferring. The inference
|
||||
# can return multiple potential results while evaluating a Python object, but
|
||||
# some branches might not be evaluated, which results in partial inference. In
|
||||
# that case, it might be useful to still emit no-member and other checks for
|
||||
# the rest of the inferred objects.
|
||||
ignore-on-opaque-inference=yes
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis. It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=
|
||||
|
||||
# Show a hint with possible names when a member name was not found. The aspect
|
||||
# of finding the hint is based on edit distance.
|
||||
missing-member-hint=yes
|
||||
|
||||
# The minimum edit distance a name should have in order to be considered a
|
||||
# similar match for a missing member name.
|
||||
missing-member-hint-distance=1
|
||||
|
||||
# The total number of similar names that should be taken in consideration when
|
||||
# showing a hint for a missing member.
|
||||
missing-member-max-choices=1
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Naming style matching correct argument names.
|
||||
argument-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct argument names. Overrides argument-
|
||||
# naming-style.
|
||||
#argument-rgx=
|
||||
|
||||
# Naming style matching correct attribute names.
|
||||
attr-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct attribute names. Overrides attr-naming-
|
||||
# style.
|
||||
#attr-rgx=
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma.
|
||||
bad-names=foo,
|
||||
bar,
|
||||
baz,
|
||||
toto,
|
||||
tutu,
|
||||
tata
|
||||
|
||||
# Naming style matching correct class attribute names.
|
||||
class-attribute-naming-style=any
|
||||
|
||||
# Regular expression matching correct class attribute names. Overrides class-
|
||||
# attribute-naming-style.
|
||||
#class-attribute-rgx=
|
||||
|
||||
# Naming style matching correct class names.
|
||||
class-naming-style=PascalCase
|
||||
|
||||
# Regular expression matching correct class names. Overrides class-naming-
|
||||
# style.
|
||||
#class-rgx=
|
||||
|
||||
# Naming style matching correct constant names.
|
||||
const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct constant names. Overrides const-naming-
|
||||
# style.
|
||||
#const-rgx=
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=-1
|
||||
|
||||
# Naming style matching correct function names.
|
||||
function-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct function names. Overrides function-
|
||||
# naming-style.
|
||||
#function-rgx=
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma.
|
||||
good-names=i,
|
||||
j,
|
||||
k,
|
||||
ex,
|
||||
Run,
|
||||
_
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name.
|
||||
include-naming-hint=yes
|
||||
|
||||
# Naming style matching correct inline iteration names.
|
||||
inlinevar-naming-style=any
|
||||
|
||||
# Regular expression matching correct inline iteration names. Overrides
|
||||
# inlinevar-naming-style.
|
||||
#inlinevar-rgx=
|
||||
|
||||
# Naming style matching correct method names.
|
||||
method-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct method names. Overrides method-naming-
|
||||
# style.
|
||||
#method-rgx=
|
||||
|
||||
# Naming style matching correct module names.
|
||||
module-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct module names. Overrides module-naming-
|
||||
# style.
|
||||
#module-rgx=
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=^_
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
property-classes=abc.abstractproperty
|
||||
|
||||
# Naming style matching correct variable names.
|
||||
variable-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct variable names. Overrides variable-
|
||||
# naming-style.
|
||||
#variable-rgx=
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# Tells whether unused global variables should be treated as a violation.
|
||||
allow-global-unused-variables=yes
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,
|
||||
_cb
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expected to
|
||||
# not be used).
|
||||
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore.
|
||||
ignored-argument-names=_.*|^ignored_|^unused_
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,
|
||||
XXX,
|
||||
TODO
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,
|
||||
__new__,
|
||||
setUp
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,
|
||||
_fields,
|
||||
_replace,
|
||||
_source,
|
||||
_make
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=cls
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# Maximum number of arguments for function / method.
|
||||
max-args=5
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Maximum number of boolean expressions in an if statement.
|
||||
max-bool-expr=5
|
||||
|
||||
# Maximum number of branch for function / method body.
|
||||
max-branches=12
|
||||
|
||||
# Maximum number of locals for function / method body.
|
||||
max-locals=15
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
# Maximum number of return / yield for function / method body.
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of statements in function / method body.
|
||||
max-statements=50
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# Allow wildcard imports from modules that define __all__.
|
||||
allow-wildcard-with-all=no
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma.
|
||||
deprecated-modules=optparse,tkinter.tix
|
||||
|
||||
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||
# not be disabled).
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report RP0402 must not be disabled).
|
||||
import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||
# not be disabled).
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "Exception".
|
||||
overgeneral-exceptions=Exception
|
|
@ -1,32 +1,29 @@
|
|||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, 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
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
import gettext
|
||||
import os
|
||||
from gettext import gettext as _
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gtk', '3.0') # pylint: disable=wrong-import-position
|
||||
from gi.repository import GLib, Gio, Gtk, GdkPixbuf
|
||||
|
||||
from . helpers import get_builder, show_uri, get_help_uri, get_media_path
|
||||
from uberwriter import UberwriterWindow
|
||||
from uberwriter.Settings import Settings
|
||||
from uberwriter_lib import set_up_logging
|
||||
from uberwriter_lib.PreferencesDialog import PreferencesDialog
|
||||
from . helpers import get_builder, get_media_path
|
||||
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
class Window(Gtk.ApplicationWindow):
|
||||
|
||||
|
@ -35,26 +32,26 @@ class Window(Gtk.ApplicationWindow):
|
|||
|
||||
# This will be in the windows group and have the "win" prefix
|
||||
max_action = Gio.SimpleAction.new_stateful("maximize", None,
|
||||
GLib.Variant.new_boolean(False))
|
||||
GLib.Variant.new_boolean(False))
|
||||
max_action.connect("change-state", self.on_maximize_toggle)
|
||||
self.add_action(max_action)
|
||||
|
||||
# Keep it in sync with the actual state
|
||||
self.connect("notify::is-maximized",
|
||||
lambda obj, pspec: max_action.set_state(
|
||||
GLib.Variant.new_boolean(obj.props.is_maximized)))
|
||||
|
||||
self.set_default_size(850,500)
|
||||
|
||||
lambda obj, pspec: max_action.set_state(
|
||||
GLib.Variant.new_boolean(obj.props.is_maximized)))
|
||||
|
||||
self.set_default_size(850, 500)
|
||||
|
||||
icon_file = get_media_path("uberwriter.svg")
|
||||
self.set_icon_from_file(icon_file)
|
||||
|
||||
|
||||
builder = get_builder('UberwriterWindow')
|
||||
new_object = builder.get_object("FullscreenOverlay")
|
||||
|
||||
|
||||
self.contents = new_object
|
||||
self.add(self.contents)
|
||||
|
||||
|
||||
self.finish_initializing(builder)
|
||||
|
||||
def on_maximize_toggle(self, action, value):
|
||||
|
@ -63,7 +60,7 @@ class Window(Gtk.ApplicationWindow):
|
|||
self.maximize()
|
||||
else:
|
||||
self.unmaximize()
|
||||
|
||||
|
||||
def finish_initializing(self, builder):
|
||||
"""Called while initializing this instance in __new__
|
||||
|
||||
|
@ -74,11 +71,10 @@ class Window(Gtk.ApplicationWindow):
|
|||
# Get a reference to the builder and set up the signals.
|
||||
self.builder = builder
|
||||
self.ui = builder.get_ui(self, True)
|
||||
self.PreferencesDialog = None # class
|
||||
self.preferences_dialog = None # instance
|
||||
self.AboutDialog = None # class
|
||||
self.PreferencesDialog = None # class
|
||||
self.preferences_dialog = None # instance
|
||||
self.AboutDialog = None # class
|
||||
|
||||
|
||||
# self.settings = Gio.Settings("net.launchpad.uberwriter")
|
||||
# self.settings.connect('changed', self.on_preferences_changed)
|
||||
|
||||
|
@ -94,7 +90,7 @@ class Window(Gtk.ApplicationWindow):
|
|||
self.indicator = indicator.new_application_indicator(self)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class Application(Gtk.Application):
|
||||
|
||||
|
@ -104,7 +100,7 @@ class Application(Gtk.Application):
|
|||
**kwargs)
|
||||
self.window = None
|
||||
self.settings = Settings.new()
|
||||
|
||||
|
||||
def do_startup(self):
|
||||
Gtk.Application.do_startup(self)
|
||||
|
||||
|
@ -113,11 +109,11 @@ class Application(Gtk.Application):
|
|||
action = Gio.SimpleAction.new("help", None)
|
||||
action.connect("activate", self.on_help)
|
||||
self.add_action(action)
|
||||
|
||||
|
||||
action = Gio.SimpleAction.new("shortcuts", None)
|
||||
action.connect("activate", self.on_shortcuts)
|
||||
self.add_action(action)
|
||||
|
||||
|
||||
action = Gio.SimpleAction.new("about", None)
|
||||
action.connect("activate", self.on_about)
|
||||
self.add_action(action)
|
||||
|
@ -136,26 +132,26 @@ class Application(Gtk.Application):
|
|||
|
||||
set_dark_mode = self.settings.get_value("dark-mode")
|
||||
action = Gio.SimpleAction.new_stateful("dark_mode",
|
||||
None,
|
||||
GLib.Variant.new_boolean(set_dark_mode))
|
||||
None,
|
||||
GLib.Variant.new_boolean(set_dark_mode))
|
||||
action.connect("change-state", self.on_dark_mode)
|
||||
self.add_action(action)
|
||||
|
||||
action = Gio.SimpleAction.new_stateful("focus_mode",
|
||||
None,
|
||||
GLib.Variant.new_boolean(False))
|
||||
None,
|
||||
GLib.Variant.new_boolean(False))
|
||||
action.connect("change-state", self.on_focus_mode)
|
||||
self.add_action(action)
|
||||
|
||||
action = Gio.SimpleAction.new_stateful("fullscreen",
|
||||
None,
|
||||
GLib.Variant.new_boolean(False))
|
||||
None,
|
||||
GLib.Variant.new_boolean(False))
|
||||
action.connect("change-state", self.on_fullscreen)
|
||||
self.add_action(action)
|
||||
|
||||
action = Gio.SimpleAction.new_stateful("preview",
|
||||
None,
|
||||
GLib.Variant.new_boolean(False))
|
||||
None,
|
||||
GLib.Variant.new_boolean(False))
|
||||
action.connect("change-state", self.on_preview)
|
||||
self.add_action(action)
|
||||
|
||||
|
@ -164,8 +160,8 @@ class Application(Gtk.Application):
|
|||
self.add_action(action)
|
||||
|
||||
action = Gio.SimpleAction.new_stateful("spellcheck",
|
||||
None,
|
||||
GLib.Variant.new_boolean(True))
|
||||
None,
|
||||
GLib.Variant.new_boolean(True))
|
||||
action.connect("change-state", self.on_spellcheck)
|
||||
self.add_action(action)
|
||||
|
||||
|
@ -207,20 +203,18 @@ class Application(Gtk.Application):
|
|||
action.connect("activate", self.on_preferences)
|
||||
self.add_action(action)
|
||||
|
||||
|
||||
'''Shortcuts'''
|
||||
|
||||
self.set_accels_for_action("app.focus_mode",["<Ctl>d"])
|
||||
self.set_accels_for_action("app.fullscreen",["F11"])
|
||||
self.set_accels_for_action("app.preview",["<Ctl>p"])
|
||||
self.set_accels_for_action("app.search",["<Ctl>f"])
|
||||
self.set_accels_for_action("app.spellcheck",["F7"])
|
||||
|
||||
self.set_accels_for_action("app.new",["<Ctl>n"])
|
||||
self.set_accels_for_action("app.open",["<Ctl>o"])
|
||||
self.set_accels_for_action("app.save",["<Ctl>s"])
|
||||
self.set_accels_for_action("app.save_as",["<Ctl><shift>s"])
|
||||
self.set_accels_for_action("app.focus_mode", ["<Ctl>d"])
|
||||
self.set_accels_for_action("app.fullscreen", ["F11"])
|
||||
self.set_accels_for_action("app.preview", ["<Ctl>p"])
|
||||
self.set_accels_for_action("app.search", ["<Ctl>f"])
|
||||
self.set_accels_for_action("app.spellcheck", ["F7"])
|
||||
|
||||
self.set_accels_for_action("app.new", ["<Ctl>n"])
|
||||
self.set_accels_for_action("app.open", ["<Ctl>o"])
|
||||
self.set_accels_for_action("app.save", ["<Ctl>s"])
|
||||
self.set_accels_for_action("app.save_as", ["<Ctl><shift>s"])
|
||||
|
||||
def do_activate(self):
|
||||
# We only allow a single window and raise any existing ones
|
||||
|
@ -228,17 +222,16 @@ class Application(Gtk.Application):
|
|||
# Windows are associated with the application
|
||||
# when the last one is closed the application shuts down
|
||||
# self.window = Window(application=self, title="UberWriter")
|
||||
self.window = UberwriterWindow.UberwriterWindow(application=self, title="UberWriter")
|
||||
if len(self.args) > 0:
|
||||
self.window.load_file(self.args[0])
|
||||
self.window = UberwriterWindow.UberwriterWindow(
|
||||
application=self, title="UberWriter")
|
||||
if self.args:
|
||||
self.window.load_file(self.args[0])
|
||||
if self.options.experimental_features:
|
||||
self.window.use_experimental_features(True)
|
||||
|
||||
|
||||
self.window.present()
|
||||
|
||||
def do_command_line(self, command_line):
|
||||
|
||||
def do_command_line(self, _command_line):
|
||||
"""Support for command line options"""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
|
@ -247,37 +240,36 @@ class Application(Gtk.Application):
|
|||
parser.add_argument(
|
||||
"-e", "--experimental-features", help=_("Use experimental features"),
|
||||
action='store_true'
|
||||
)
|
||||
)
|
||||
(self.options, self.args) = parser.parse_known_args()
|
||||
|
||||
set_up_logging(self.options)
|
||||
|
||||
|
||||
self.activate()
|
||||
return 0
|
||||
|
||||
|
||||
def on_about(self, action, param):
|
||||
def on_about(self, _action, _param):
|
||||
builder = get_builder('About')
|
||||
about_dialog = builder.get_object("AboutDialog")
|
||||
about_dialog.set_transient_for(self.window)
|
||||
|
||||
logo_file = get_media_path("uberwriter.svg")
|
||||
logo = GdkPixbuf.Pixbuf.new_from_file(logo_file)
|
||||
|
||||
|
||||
about_dialog.set_logo(logo)
|
||||
|
||||
|
||||
about_dialog.present()
|
||||
|
||||
def on_help(self, action, param):
|
||||
|
||||
def on_help(self, _action, _param):
|
||||
self.window.open_pandoc_markdown(self)
|
||||
|
||||
def on_translate(self, action, param):
|
||||
def on_translate(self, _action, _param):
|
||||
self.window.open_translation()
|
||||
|
||||
def on_donate(self, action, param):
|
||||
def on_donate(self, _action, _param):
|
||||
self.window.open_donation()
|
||||
|
||||
def on_shortcuts(self, action, param):
|
||||
|
||||
def on_shortcuts(self, _action, _param):
|
||||
builder = get_builder('Shortcuts')
|
||||
builder.get_object("shortcuts").set_transient_for(self.window)
|
||||
builder.get_object("shortcuts").show()
|
||||
|
@ -285,12 +277,13 @@ class Application(Gtk.Application):
|
|||
def on_dark_mode(self, action, value):
|
||||
action.set_state(value)
|
||||
self.settings.set_value("dark-mode",
|
||||
GLib.Variant("b", value))
|
||||
GLib.Variant("b", value))
|
||||
self.window.toggle_dark_mode(value)
|
||||
|
||||
#this changes the headerbar theme accordingly
|
||||
# this changes the headerbar theme accordingly
|
||||
self.dark_setting = Gtk.Settings.get_default()
|
||||
self.dark_setting.set_property("gtk-application-prefer-dark-theme", value)
|
||||
self.dark_setting.set_property(
|
||||
"gtk-application-prefer-dark-theme", value)
|
||||
|
||||
def on_focus_mode(self, action, value):
|
||||
action.set_state(value)
|
||||
|
@ -304,44 +297,44 @@ class Application(Gtk.Application):
|
|||
action.set_state(value)
|
||||
self.window.toggle_preview(value)
|
||||
|
||||
def on_search(self, action, value):
|
||||
def on_search(self, _action, _value):
|
||||
self.window.open_search_and_replace()
|
||||
|
||||
def on_spellcheck(self, action, value):
|
||||
action.set_state(value)
|
||||
self.window.toggle_spellcheck(value)
|
||||
|
||||
def on_new(self, action, value):
|
||||
def on_new(self, _action, _value):
|
||||
self.window.new_document()
|
||||
|
||||
def on_open(self, action, value):
|
||||
def on_open(self, _action, _value):
|
||||
self.window.open_document()
|
||||
|
||||
|
||||
def on_open_recent(self, action, value):
|
||||
pass
|
||||
|
||||
def on_example(self, action, value):
|
||||
|
||||
def on_example(self, _action, _value):
|
||||
self.window.open_uberwriter_markdown()
|
||||
|
||||
def on_save(self, action, value):
|
||||
|
||||
def on_save(self, _action, _value):
|
||||
self.window.save_document()
|
||||
|
||||
def on_save_as(self, action, value):
|
||||
|
||||
def on_save_as(self, _action, _value):
|
||||
self.window.save_document_as()
|
||||
|
||||
def on_export(self, action, value):
|
||||
|
||||
def on_export(self, _action, _value):
|
||||
self.window.open_advanced_export()
|
||||
|
||||
def on_html_copy(self, action, value):
|
||||
|
||||
def on_html_copy(self, _action, _value):
|
||||
self.window.copy_html_to_clipboard()
|
||||
|
||||
def on_preferences(self, action, value):
|
||||
def on_preferences(self, _action, _value):
|
||||
PreferencesWindow = PreferencesDialog()
|
||||
PreferencesWindow.set_application(self)
|
||||
PreferencesWindow.set_transient_for(self.window)
|
||||
PreferencesWindow.show()
|
||||
|
||||
def on_quit(self, action, param):
|
||||
|
||||
def on_quit(self, _action, _param):
|
||||
self.quit()
|
||||
|
||||
# ~ if __name__ == "__main__":
|
||||
|
|
|
@ -1,34 +1,35 @@
|
|||
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
|
||||
### BEGIN LICENSE
|
||||
# BEGIN LICENSE
|
||||
# Copyright (C) 2012, Wolf Vollprecht <w.vollprecht@gmail.com>
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, 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
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
### END LICENSE
|
||||
# END LICENSE
|
||||
|
||||
### DO NOT EDIT THIS FILE ###
|
||||
|
||||
'''Enhances builder connections, provides object to access glade objects'''
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import GObject, Gtk # pylint: disable=E0611
|
||||
|
||||
import inspect
|
||||
import functools
|
||||
import logging
|
||||
logger = logging.getLogger('uberwriter_lib')
|
||||
|
||||
from xml.etree.cElementTree import ElementTree
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0') # pylint: disable=wrong-import-position
|
||||
from gi.repository import GObject, Gtk # pylint: disable=E0611
|
||||
|
||||
LOGGER = logging.getLogger('uberwriter_lib')
|
||||
|
||||
# this module is big so uses some conventional prefixes and postfixes
|
||||
# *s list, except self.widgets is a dictionary
|
||||
# *_dict dictionary
|
||||
|
@ -57,7 +58,7 @@ class Builder(Gtk.Builder):
|
|||
# pylint: disable=R0201
|
||||
# this is a method so that a subclass of Builder can redefine it
|
||||
def default_handler(self,
|
||||
handler_name, filename, *args, **kwargs):
|
||||
handler_name, filename, *args, **kwargs):
|
||||
'''helps the apprentice guru
|
||||
|
||||
glade defined handlers that do not exist come here instead.
|
||||
|
@ -65,7 +66,7 @@ class Builder(Gtk.Builder):
|
|||
now he can define any likely candidates in glade and notice which
|
||||
ones get triggered when he plays with the project.
|
||||
this method does not appear in Gtk.Builder'''
|
||||
logger.debug('''tried to call non-existent function:%s()
|
||||
LOGGER.debug('''tried to call non-existent function:%s()
|
||||
expected in %s
|
||||
args:%s
|
||||
kwargs:%s''', handler_name, filename, args, kwargs)
|
||||
|
@ -101,8 +102,8 @@ class Builder(Gtk.Builder):
|
|||
|
||||
connections = [
|
||||
(name,
|
||||
ele_signal.attrib['name'],
|
||||
ele_signal.attrib['handler']) for ele_signal in ele_signals]
|
||||
ele_signal.attrib['name'],
|
||||
ele_signal.attrib['handler']) for ele_signal in ele_signals]
|
||||
|
||||
if connections:
|
||||
self.connections.extend(connections)
|
||||
|
@ -110,7 +111,7 @@ class Builder(Gtk.Builder):
|
|||
ele_signals = tree.getiterator("signal")
|
||||
for ele_signal in ele_signals:
|
||||
self.glade_handler_dict.update(
|
||||
{ele_signal.attrib["handler"]: None})
|
||||
{ele_signal.attrib["handler"]: None})
|
||||
|
||||
def connect_signals(self, callback_obj):
|
||||
'''connect the handlers defined in glade
|
||||
|
@ -131,8 +132,8 @@ class Builder(Gtk.Builder):
|
|||
connection_dict[item[0]] = handler
|
||||
|
||||
# replace the run time warning
|
||||
logger.warn("expected handler '%s' in %s",
|
||||
item[0], filename)
|
||||
LOGGER.warning("expected handler '%s' in %s",
|
||||
item[0], filename)
|
||||
|
||||
# connect glade define handlers
|
||||
Gtk.Builder.connect_signals(self, connection_dict)
|
||||
|
@ -140,8 +141,8 @@ class Builder(Gtk.Builder):
|
|||
# let's tell the user how we applied the glade design
|
||||
for connection in self.connections:
|
||||
widget_name, signal_name, handler_name = connection
|
||||
logger.debug("connect builder by design '%s', '%s', '%s'",
|
||||
widget_name, signal_name, handler_name)
|
||||
LOGGER.debug("connect builder by design '%s', '%s', '%s'",
|
||||
widget_name, signal_name, handler_name)
|
||||
|
||||
def get_ui(self, callback_obj=None, by_name=True):
|
||||
'''Creates the ui object with widgets as attributes
|
||||
|
@ -167,6 +168,7 @@ class Builder(Gtk.Builder):
|
|||
# apart from the glade widgets
|
||||
class UiFactory():
|
||||
''' provides an object with attributes as glade widgets'''
|
||||
|
||||
def __init__(self, widget_dict):
|
||||
self._widget_dict = widget_dict
|
||||
for (widget_name, widget) in widget_dict.items():
|
||||
|
@ -177,14 +179,14 @@ class UiFactory():
|
|||
cannot_message = """cannot bind ui.%s, name already exists
|
||||
consider using a pythonic name instead of design name '%s'"""
|
||||
consider_message = """consider using a pythonic name instead of design name '%s'"""
|
||||
|
||||
|
||||
for (widget_name, widget) in widget_dict.items():
|
||||
pyname = make_pyname(widget_name)
|
||||
if pyname != widget_name:
|
||||
if hasattr(self, pyname):
|
||||
logger.debug(cannot_message, pyname, widget_name)
|
||||
LOGGER.debug(cannot_message, pyname, widget_name)
|
||||
else:
|
||||
logger.debug(consider_message, widget_name)
|
||||
LOGGER.debug(consider_message, widget_name)
|
||||
setattr(self, pyname, widget)
|
||||
|
||||
def iterator():
|
||||
|
@ -203,14 +205,14 @@ def make_pyname(name):
|
|||
pyname = ''
|
||||
for character in name:
|
||||
if (character.isalpha() or character == '_' or
|
||||
(pyname and character.isdigit())):
|
||||
(pyname and character.isdigit())):
|
||||
pyname += character
|
||||
else:
|
||||
pyname += '_'
|
||||
return pyname
|
||||
|
||||
|
||||
# Until bug https://bugzilla.gnome.org/show_bug.cgi?id=652127 is fixed, we
|
||||
# Until bug https://bugzilla.gnome.org/show_bug.cgi?id=652127 is fixed, we
|
||||
# need to reimplement inspect.getmembers. GObject introspection doesn't
|
||||
# play nice with it.
|
||||
def getmembers(obj, check):
|
||||
|
@ -233,10 +235,10 @@ def dict_from_callback_obj(callback_obj):
|
|||
aliased_methods = [x[1] for x in methods if hasattr(x[1], 'aliases')]
|
||||
|
||||
# a method may have several aliases
|
||||
#~ @alias('on_btn_foo_clicked')
|
||||
#~ @alias('on_tool_foo_activate')
|
||||
#~ on_menu_foo_activate():
|
||||
#~ pass
|
||||
# ~ @alias('on_btn_foo_clicked')
|
||||
# ~ @alias('on_tool_foo_activate')
|
||||
# ~ on_menu_foo_activate():
|
||||
# ~ pass
|
||||
alias_groups = [(x.aliases, x) for x in aliased_methods]
|
||||
|
||||
aliases = []
|
||||
|
@ -287,13 +289,13 @@ def auto_connect_by_name(callback_obj, builder):
|
|||
handler_names.append("on_%s" % sig)
|
||||
|
||||
do_connect(item, sig, handler_names,
|
||||
callback_handler_dict, builder.connections)
|
||||
callback_handler_dict, builder.connections)
|
||||
|
||||
log_unconnected_functions(callback_handler_dict, builder.connections)
|
||||
|
||||
|
||||
def do_connect(item, signal_name, handler_names,
|
||||
callback_handler_dict, connections):
|
||||
callback_handler_dict, connections):
|
||||
'''connect this signal to an unused handler'''
|
||||
widget_name, widget = item
|
||||
|
||||
|
@ -305,8 +307,8 @@ def do_connect(item, signal_name, handler_names,
|
|||
widget.connect(signal_name, callback_handler_dict[handler_name])
|
||||
connections.append(connection)
|
||||
|
||||
logger.debug("connect builder by name '%s','%s', '%s'",
|
||||
widget_name, signal_name, handler_name)
|
||||
LOGGER.debug("connect builder by name '%s','%s', '%s'",
|
||||
widget_name, signal_name, handler_name)
|
||||
|
||||
|
||||
def log_unconnected_functions(callback_handler_dict, connections):
|
||||
|
@ -324,4 +326,4 @@ def log_unconnected_functions(callback_handler_dict, connections):
|
|||
pass
|
||||
|
||||
for handler_name in unconnected:
|
||||
logger.debug("Not connected to builder '%s'", handler_name)
|
||||
LOGGER.debug("Not connected to builder '%s'", handler_name)
|
||||
|
|
|
@ -16,11 +16,15 @@ COPYING
|
|||
granted under the terms of the MIT License.
|
||||
"""
|
||||
|
||||
import os, sys, tempfile, subprocess
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import subprocess
|
||||
|
||||
|
||||
class LatexToPNG():
|
||||
|
||||
TEX_HEADER = r'''\documentclass{article}
|
||||
TEX_HEADER = r'''\documentclass{article}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsthm}
|
||||
\usepackage{amssymb}
|
||||
|
@ -30,79 +34,79 @@ class LatexToPNG():
|
|||
\newcommand{\T}{\text{T}} % Transpose
|
||||
\pagestyle{empty}
|
||||
\begin{document}'''
|
||||
|
||||
TEX_FOOTER = r'''\end{document}'''
|
||||
|
||||
def __init__(self):
|
||||
self.temp_result = tempfile.NamedTemporaryFile(suffix='.png')
|
||||
TEX_FOOTER = r'''\end{document}'''
|
||||
|
||||
def latex2png(self, tex, outfile, dpi, modified):
|
||||
'''Convert LaTeX input file infile to PNG file named outfile.'''
|
||||
outfile = os.path.abspath(outfile)
|
||||
outdir = os.path.dirname(outfile)
|
||||
texfile = tempfile.mktemp(suffix='.tex', dir=os.path.dirname(outfile))
|
||||
basefile = os.path.splitext(texfile)[0]
|
||||
dvifile = basefile + '.dvi'
|
||||
temps = [basefile + ext for ext in ('.tex','.dvi', '.aux', '.log')]
|
||||
skip = False
|
||||
|
||||
tex = '%s\n%s\n%s\n' % (self.TEX_HEADER, tex.strip(), self.TEX_FOOTER)
|
||||
def __init__(self):
|
||||
self.temp_result = tempfile.NamedTemporaryFile(suffix='.png')
|
||||
|
||||
open(texfile, 'w').write(tex)
|
||||
saved_pwd = os.getcwd()
|
||||
def latex2png(self, tex, outfile, dpi, modified):
|
||||
'''Convert LaTeX input file infile to PNG file named outfile.'''
|
||||
outfile = os.path.abspath(outfile)
|
||||
outdir = os.path.dirname(outfile)
|
||||
texfile = tempfile.mktemp(suffix='.tex', dir=os.path.dirname(outfile))
|
||||
basefile = os.path.splitext(texfile)[0]
|
||||
dvifile = basefile + '.dvi'
|
||||
temps = [basefile + ext for ext in ('.tex', '.dvi', '.aux', '.log')]
|
||||
skip = False
|
||||
|
||||
os.chdir(outdir)
|
||||
|
||||
args = ['latex', '-halt-on-error', texfile]
|
||||
p = subprocess.Popen(args,
|
||||
stderr=subprocess.STDOUT,
|
||||
stdout=subprocess.PIPE)
|
||||
tex = '%s\n%s\n%s\n' % (self.TEX_HEADER, tex.strip(), self.TEX_FOOTER)
|
||||
|
||||
output = p.stdout
|
||||
output_lines = output.readlines()
|
||||
if os.path.isfile(dvifile): # DVI File exists
|
||||
# Convert DVI file to PNG.
|
||||
args = ['dvipng',
|
||||
'-D', str(dpi),
|
||||
'-T', 'tight',
|
||||
'-x', '1000',
|
||||
'-z', '9',
|
||||
'-bg', 'Transparent',
|
||||
'-o', outfile,
|
||||
dvifile]
|
||||
open(texfile, 'w').write(tex)
|
||||
saved_pwd = os.getcwd()
|
||||
|
||||
p = subprocess.Popen(args)
|
||||
p.communicate()
|
||||
|
||||
else:
|
||||
self.clean_up(temps)
|
||||
'''
|
||||
os.chdir(outdir)
|
||||
|
||||
args = ['latex', '-halt-on-error', texfile]
|
||||
p = subprocess.Popen(args,
|
||||
stderr=subprocess.STDOUT,
|
||||
stdout=subprocess.PIPE)
|
||||
|
||||
output = p.stdout
|
||||
output_lines = output.readlines()
|
||||
if os.path.isfile(dvifile): # DVI File exists
|
||||
# Convert DVI file to PNG.
|
||||
args = ['dvipng',
|
||||
'-D', str(dpi),
|
||||
'-T', 'tight',
|
||||
'-x', '1000',
|
||||
'-z', '9',
|
||||
'-bg', 'Transparent',
|
||||
'-o', outfile,
|
||||
dvifile]
|
||||
|
||||
p = subprocess.Popen(args)
|
||||
p.communicate()
|
||||
|
||||
else:
|
||||
self.clean_up(temps)
|
||||
'''
|
||||
Errors in Latex output start with "! "
|
||||
Stripping exclamation marks and superflous newlines
|
||||
and telling the user what he's done wrong.
|
||||
'''
|
||||
i = []
|
||||
error = ""
|
||||
for line in output_lines:
|
||||
line = line.decode('utf-8')
|
||||
if line.startswith("!"):
|
||||
error += line[2:] # removing "! "
|
||||
if error.endswith("\n"):
|
||||
error = error[:-1]
|
||||
raise Exception(error)
|
||||
i = []
|
||||
error = ""
|
||||
for line in output_lines:
|
||||
line = line.decode('utf-8')
|
||||
if line.startswith("!"):
|
||||
error += line[2:] # removing "! "
|
||||
if error.endswith("\n"):
|
||||
error = error[:-1]
|
||||
raise Exception(error)
|
||||
|
||||
def generatepng(self, formula):
|
||||
try:
|
||||
self.temp_result = tempfile.NamedTemporaryFile(suffix='.png')
|
||||
formula = "$" + formula + "$"
|
||||
self.latex2png(formula, self.temp_result.name, 300, False)
|
||||
return (True, self.temp_result.name)
|
||||
def generatepng(self, formula):
|
||||
try:
|
||||
self.temp_result = tempfile.NamedTemporaryFile(suffix='.png')
|
||||
formula = "$" + formula + "$"
|
||||
self.latex2png(formula, self.temp_result.name, 300, False)
|
||||
return (True, self.temp_result.name)
|
||||
|
||||
except Exception as e:
|
||||
self.temp_result.close()
|
||||
return (False, e.args[0])
|
||||
except Exception as e:
|
||||
self.temp_result.close()
|
||||
return (False, e.args[0])
|
||||
|
||||
def clean_up(self, files):
|
||||
for f in files:
|
||||
if os.path.isfile(f):
|
||||
os.remove(f)
|
||||
def clean_up(self, files):
|
||||
for f in files:
|
||||
if os.path.isfile(f):
|
||||
os.remove(f)
|
||||
|
|
|
@ -1,39 +1,34 @@
|
|||
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
|
||||
### BEGIN LICENSE
|
||||
# BEGIN LICENSE
|
||||
# Copyright (C) 2012, Wolf Vollprecht <w.vollprecht@gmail.com>
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, 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
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
### END LICENSE
|
||||
# END LICENSE
|
||||
|
||||
### DO NOT EDIT THIS FILE ###
|
||||
|
||||
"""Helpers for an Ubuntu application."""
|
||||
"""Helpers for the application."""
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
from . uberwriterconfig import get_data_file
|
||||
from . Builder import Builder
|
||||
|
||||
import locale
|
||||
import gettext
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
def get_builder(builder_file_name):
|
||||
"""Return a fully-instantiated Gtk.Builder instance from specified ui
|
||||
"""Return a fully-instantiated Gtk.Builder instance from specified ui
|
||||
file
|
||||
|
||||
|
||||
:param builder_file_name: The name of the builder file, without extension.
|
||||
Assumed to be in the 'ui' directory under the data path.
|
||||
"""
|
||||
|
@ -50,35 +45,50 @@ def get_builder(builder_file_name):
|
|||
|
||||
# Owais Lone : To get quick access to icons and stuff.
|
||||
def get_media_file(media_file_name):
|
||||
"""Return the full path of a given filename under the media dir
|
||||
(starts with file:///)
|
||||
"""
|
||||
|
||||
media_filename = get_data_file('media', '%s' % (media_file_name,))
|
||||
if not os.path.exists(media_filename):
|
||||
media_filename = None
|
||||
|
||||
return "file:///"+media_filename
|
||||
return "file:///" + media_filename
|
||||
|
||||
|
||||
def get_media_path(media_file_name):
|
||||
"""Return the full path of a given filename under the media dir
|
||||
(doesn't start with file:///)
|
||||
"""
|
||||
|
||||
media_filename = get_data_file('media', '%s' % (media_file_name,))
|
||||
if not os.path.exists(media_filename):
|
||||
media_filename = None
|
||||
return media_filename
|
||||
|
||||
|
||||
def get_script_path(script_file_name):
|
||||
"""Return the full path of a given filename under the script dir
|
||||
"""
|
||||
script_filename = get_data_file('lua', '%s' % (script_file_name,))
|
||||
if not os.path.exists(script_filename):
|
||||
script_filename = None
|
||||
return script_filename
|
||||
|
||||
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
|
||||
|
||||
def set_up_logging(opts):
|
||||
# add a handler to prevent basicConfig
|
||||
root = logging.getLogger()
|
||||
null_handler = NullHandler()
|
||||
root.addHandler(null_handler)
|
||||
|
||||
formatter = logging.Formatter("%(levelname)s:%(name)s: %(funcName)s() '%(message)s'")
|
||||
formatter = logging.Formatter(
|
||||
"%(levelname)s:%(name)s: %(funcName)s() '%(message)s'")
|
||||
|
||||
logger = logging.getLogger('uberwriter')
|
||||
logger_sh = logging.StreamHandler()
|
||||
|
@ -97,6 +107,7 @@ def set_up_logging(opts):
|
|||
if opts.verbose and opts.verbose > 1:
|
||||
lib_logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
def get_help_uri(page=None):
|
||||
# help_uri from source tree - default language
|
||||
here = os.path.dirname(__file__)
|
||||
|
@ -112,11 +123,13 @@ def get_help_uri(page=None):
|
|||
|
||||
return help_uri
|
||||
|
||||
|
||||
def show_uri(parent, link):
|
||||
from gi.repository import Gtk # pylint: disable=E0611
|
||||
from gi.repository import Gtk # pylint: disable=E0611
|
||||
screen = parent.get_screen()
|
||||
Gtk.show_uri(screen, link, Gtk.get_current_event_time())
|
||||
|
||||
|
||||
def alias(alternative_function_name):
|
||||
'''see http://www.drdobbs.com/web-development/184406073#l9'''
|
||||
def decorator(function):
|
||||
|
@ -127,5 +140,15 @@ def alias(alternative_function_name):
|
|||
return function
|
||||
return decorator
|
||||
|
||||
|
||||
def exist_executable(command):
|
||||
return shutil.which(command) is not None
|
||||
"""return if a command can be executed in the SO
|
||||
|
||||
Arguments:
|
||||
command {str} -- a command
|
||||
|
||||
Returns:
|
||||
{bool} -- if the given command exists in the system
|
||||
"""
|
||||
|
||||
return shutil.which(command) is not None
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
|
||||
### BEGIN LICENSE
|
||||
# Copyright (C) 2012, Wolf Vollprecht <w.vollprecht@gmail.com>
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
# MERCHANTABILITY, SATISFACTORY QUALITY, 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
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
### END LICENSE
|
||||
|
||||
|
@ -30,9 +30,7 @@ __version__ = 'VERSION'
|
|||
|
||||
import os
|
||||
|
||||
from locale import gettext as _
|
||||
|
||||
class project_path_not_found(Exception):
|
||||
class ProjectPathNotFound(Exception):
|
||||
"""Raised when we can't find the project directory."""
|
||||
|
||||
|
||||
|
@ -68,7 +66,7 @@ def get_data_path():
|
|||
if not os.path.exists(abs_data_path):
|
||||
abs_data_path = '/opt/uberwriter/data/'
|
||||
elif not os.path.exists(abs_data_path):
|
||||
raise project_path_not_found
|
||||
raise ProjectPathNotFound
|
||||
|
||||
return abs_data_path
|
||||
|
||||
|
|
Loading…
Reference in New Issue