forked from Mirrors/apostrophe
several improvements, also introducing several new bugs
parent
8a98c35af0
commit
eed1c95a26
|
@ -4,6 +4,8 @@
|
||||||
inclusion in templates
|
inclusion in templates
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@define-color dark_bg #333;
|
||||||
|
|
||||||
@binding-set window-bindings {
|
@binding-set window-bindings {
|
||||||
bind "<ctl>n" { "new-file" () };
|
bind "<ctl>n" { "new-file" () };
|
||||||
bind "<ctl>o" { "open-file" () };
|
bind "<ctl>o" { "open-file" () };
|
||||||
|
@ -12,6 +14,9 @@
|
||||||
bind "<ctl>d" { "toggle-focusmode" () };
|
bind "<ctl>d" { "toggle-focusmode" () };
|
||||||
bind "<ctl>p" { "toggle-preview" () };
|
bind "<ctl>p" { "toggle-preview" () };
|
||||||
bind "<ctl>w" { "close-window" () };
|
bind "<ctl>w" { "close-window" () };
|
||||||
|
bind "<ctl>f" { "toggle-search" () };
|
||||||
|
bind "<ctl><shift>r" { "toggle-search-replace" () };
|
||||||
|
bind "<ctl><shift>f" { "toggle-search-replace" () };
|
||||||
bind "F11" { "toggle-fullscreen" () };
|
bind "F11" { "toggle-fullscreen" () };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,11 +29,6 @@
|
||||||
bind "<ctl>z" { "undo" () };
|
bind "<ctl>z" { "undo" () };
|
||||||
bind "<ctl>y" { "redo" () };
|
bind "<ctl>y" { "redo" () };
|
||||||
bind "<ctl><shift>z" { "redo" () };
|
bind "<ctl><shift>z" { "redo" () };
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkRevealer {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#UberwriterWindow {
|
#UberwriterWindow {
|
||||||
|
@ -37,16 +37,33 @@ GtkRevealer {
|
||||||
border-radius: 7px 7px 5px 5px;
|
border-radius: 7px 7px 5px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollbars-junction,
|
#UberwriterWindow.small #UberwriterEditor {
|
||||||
.scrollbar.trough {
|
font: Inconsolata 12;
|
||||||
background-image: none;
|
|
||||||
background-color: transparent;
|
|
||||||
border-width: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
border-image: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#UberwriterWindow GtkTextView {
|
#UberwriterWindow.medium #UberwriterEditor {
|
||||||
|
font: Inconsolata 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
#UberwriterWindow.large #UberwriterEditor {
|
||||||
|
font: Inconsolata 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
#UberwriterWindow.dark_mode {
|
||||||
|
background: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#UberwriterWindow.dark_mode #UberwriterEditor {
|
||||||
|
color: #CCC;
|
||||||
|
-GtkWidget-cursor-color: shade(#4D9FCE, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbars-junction,
|
||||||
|
.scrollbar.trough {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#UberwriterEditor {
|
||||||
border: none;
|
border: none;
|
||||||
color: #222;
|
color: #222;
|
||||||
-GtkWidget-cursor-color: shade(#4D9FCE, 0.9);
|
-GtkWidget-cursor-color: shade(#4D9FCE, 0.9);
|
||||||
|
@ -54,7 +71,12 @@ GtkRevealer {
|
||||||
gtk-key-bindings: editor-bindings;
|
gtk-key-bindings: editor-bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
#UberwriterWindow GtkTextView GtkButton {
|
#UberwriterEditor:selected {
|
||||||
|
background-color: #4D9FCE;
|
||||||
|
color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
#UberwriterEditor GtkButton {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
/*background: #CCC;*/
|
/*background: #CCC;*/
|
||||||
|
@ -66,10 +88,6 @@ GtkRevealer {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#UberwriterWindow GtkTextView:selected {
|
|
||||||
background-color: #4D9FCE;
|
|
||||||
color: #FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
#status_bar_box GtkLabel {
|
#status_bar_box GtkLabel {
|
||||||
color: #666;
|
color: #666;
|
||||||
|
@ -107,6 +125,7 @@ GtkRevealer {
|
||||||
transition: 500ms ease-in;
|
transition: 500ms ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#status_bar_box GtkButton:hover,
|
#status_bar_box GtkButton:hover,
|
||||||
#status_bar_box GtkButton:active:hover {
|
#status_bar_box GtkButton:active:hover {
|
||||||
transition: 0s ease-in;
|
transition: 0s ease-in;
|
||||||
|
@ -121,6 +140,13 @@ GtkRevealer {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
box-shadow: 0 0 2px rgba(0,0,0,0.4)
|
box-shadow: 0 0 2px rgba(0,0,0,0.4)
|
||||||
}
|
}
|
||||||
|
.dark_mode #status_bar_box GtkButton {
|
||||||
|
background: #F00;
|
||||||
|
}
|
||||||
|
.dark_mode #status_bar_box GtkButton:hover,
|
||||||
|
.dark_mode #status_bar_box GtkButton:active {
|
||||||
|
background-color: shade(@dark_bg, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
#status_bar_box GtkSeparator {
|
#status_bar_box GtkSeparator {
|
||||||
border-color: #999;
|
border-color: #999;
|
||||||
|
@ -138,4 +164,8 @@ GtkRevealer {
|
||||||
#UberwriterWindow GtkTreeView {
|
#UberwriterWindow GtkTreeView {
|
||||||
color: #333;
|
color: #333;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#LexikonBubble {
|
||||||
|
font: Inconsolata 10;
|
||||||
}
|
}
|
|
@ -414,7 +414,7 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkEntry" id="searchentrybox">
|
<object class="GtkSearchEntry" id="searchentrybox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="invisible_char">•</property>
|
<property name="invisible_char">•</property>
|
||||||
|
|
|
@ -46,6 +46,115 @@ GObject.threads_init() # Still needed?
|
||||||
# A jumping URL from that (for preview)
|
# A jumping URL from that (for preview)
|
||||||
# Also, after going to preview, set cursor back to where it was
|
# Also, after going to preview, set cursor back to where it was
|
||||||
|
|
||||||
|
import telnetlib
|
||||||
|
|
||||||
|
class DictAccessor(object):
|
||||||
|
def __init__( self, host='localhost', port=2628, timeout=60 ):
|
||||||
|
self.tn = telnetlib.Telnet( host, port )
|
||||||
|
self.timeout = timeout
|
||||||
|
self.login_response = self.tn.expect( [ self.reEndResponse ], self.timeout )[ 2 ]
|
||||||
|
bytes
|
||||||
|
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' ]:
|
||||||
|
d = '*'
|
||||||
|
else:
|
||||||
|
d = database
|
||||||
|
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 ]
|
||||||
|
for line in mlines:
|
||||||
|
lsplit = line.strip( ).split( )
|
||||||
|
db = lsplit[ 0 ]
|
||||||
|
word = unquote( ' '.join( lsplit[ 1: ] ) )
|
||||||
|
mlist.append( ( db, word ) )
|
||||||
|
return mlist
|
||||||
|
|
||||||
|
reEndResponse = re.compile( b'^[2-5][0-58][0-9] .*\r\n$', re.DOTALL + re.MULTILINE )
|
||||||
|
reDefinition = re.compile( b'^151(.*?)^\.', re.DOTALL + re.MULTILINE )
|
||||||
|
|
||||||
|
def getDefinition( 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 )
|
||||||
|
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 = [ dtext ]
|
||||||
|
return dlist
|
||||||
|
|
||||||
|
def close( self ):
|
||||||
|
t = self.runCommand( 'QUIT' )
|
||||||
|
self.tn.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)
|
||||||
|
lines = re.sub('\s+', ' ', lines).strip()
|
||||||
|
lines = re.split(r'( adv | adj | n | v |^adv |^adj |^n |^v )', lines)
|
||||||
|
res = {}
|
||||||
|
for l in lines:
|
||||||
|
l = l.strip()
|
||||||
|
act_res = {}
|
||||||
|
act_res['defs'] = []
|
||||||
|
if len(l) == 0:
|
||||||
|
continue
|
||||||
|
if l in ['adv', 'adj','n','v']:
|
||||||
|
act_res['class'] = l
|
||||||
|
else:
|
||||||
|
ll = re.split('(?: |^)(\d): ', l)
|
||||||
|
# print(ll)
|
||||||
|
act_def = {}
|
||||||
|
for lll in ll:
|
||||||
|
# print (lll)
|
||||||
|
if lll.strip().isdigit() or not lll.strip():
|
||||||
|
if 'description' in act_def and act_def['description']:
|
||||||
|
act_res['defs'].append(act_def.copy())
|
||||||
|
act_def = {'num': lll}
|
||||||
|
continue
|
||||||
|
a = re.findall(r'(\[(syn|ant): (.+?)\] ??)+', lll)
|
||||||
|
for n in a:
|
||||||
|
if n[1] == 'syn':
|
||||||
|
act_def['syn'] = re.findall(r'\{(.*?)\}.*?', n[2])
|
||||||
|
else:
|
||||||
|
act_def['ant'] = re.findall(r'\{(.*?)\}.*?', n[2])
|
||||||
|
tbr = re.search(r'\[.+\]', lll)
|
||||||
|
if tbr:
|
||||||
|
lll = lll[:tbr.start()]
|
||||||
|
lll = lll.split(';')
|
||||||
|
act_def['examples'] = []
|
||||||
|
act_def['description'] = []
|
||||||
|
for llll in lll:
|
||||||
|
llll = llll.strip()
|
||||||
|
if(llll.strip().startswith('"')):
|
||||||
|
act_def['examples'].append(llll)
|
||||||
|
else:
|
||||||
|
act_def['description'].append(llll)
|
||||||
|
|
||||||
|
if act_def and 'description' in act_def:
|
||||||
|
act_res['defs'].append(act_def.copy())
|
||||||
|
|
||||||
|
print(act_res)
|
||||||
|
return act_res
|
||||||
def check_url(url, item, spinner):
|
def check_url(url, item, spinner):
|
||||||
logger.debug("thread started, checking url")
|
logger.debug("thread started, checking url")
|
||||||
error = False
|
error = False
|
||||||
|
@ -65,6 +174,22 @@ def check_url(url, item, spinner):
|
||||||
spinner.destroy()
|
spinner.destroy()
|
||||||
item.set_label(text)
|
item.set_label(text)
|
||||||
|
|
||||||
|
def get_dictionary(term):
|
||||||
|
def parse_response(response):
|
||||||
|
# consisting of group (n,v,adj,adv)
|
||||||
|
# number, description, examples, synonyms, antonyms
|
||||||
|
lines = response.split('\n')
|
||||||
|
lines = lines[2:]
|
||||||
|
for l in lines:
|
||||||
|
l = l.lstrip()
|
||||||
|
print(l)
|
||||||
|
|
||||||
|
da = DictAccessor()
|
||||||
|
output = da.getDefinition('wn', term)
|
||||||
|
print (output)
|
||||||
|
|
||||||
|
output = output[0]
|
||||||
|
return da.parse_wordnet(output.decode(encoding='UTF-8'))
|
||||||
|
|
||||||
def get_web_thumbnail(url, item, spinner):
|
def get_web_thumbnail(url, item, spinner):
|
||||||
logger.debug("thread started, generating thumb")
|
logger.debug("thread started, generating thumb")
|
||||||
|
@ -91,6 +216,15 @@ def get_web_thumbnail(url, item, spinner):
|
||||||
item.add(image)
|
item.add(image)
|
||||||
item.show()
|
item.show()
|
||||||
|
|
||||||
|
def fill_lexikon_bubble(vocab, lexikon_dict):
|
||||||
|
grid = Gtk.Grid.new()
|
||||||
|
i = 0
|
||||||
|
for entry in lexikon_dict:
|
||||||
|
grid.attach(Gtk.Label.new(vocab + ' ~ ' + entry['class']), i, i, 3, 1)
|
||||||
|
grid.show_all()
|
||||||
|
return grid
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UberwriterInlinePreview():
|
class UberwriterInlinePreview():
|
||||||
|
|
||||||
|
@ -106,6 +240,19 @@ class UberwriterInlinePreview():
|
||||||
self.TextView.connect_after('popup-menu', self.move_popup)
|
self.TextView.connect_after('popup-menu', self.move_popup)
|
||||||
self.TextView.connect('button-press-event', self.click_move_button)
|
self.TextView.connect('button-press-event', self.click_move_button)
|
||||||
|
|
||||||
|
def open_popover_with_widget(self, widget):
|
||||||
|
a = self.TextBuffer.create_child_anchor(self.TextBuffer.get_iter_at_mark(self.ClickMark))
|
||||||
|
b = Gtk.Grid.new()
|
||||||
|
self.TextView.add_child_at_anchor(b, a)
|
||||||
|
b.show()
|
||||||
|
popover = Gtk.Popover.new(b)
|
||||||
|
dismiss, rect = popover.get_pointing_to()
|
||||||
|
rect.y = rect.y - 20
|
||||||
|
popover.set_pointing_to(rect)
|
||||||
|
popover.add(widget)
|
||||||
|
popover.show_all()
|
||||||
|
popover.set_property('width-request', 50)
|
||||||
|
|
||||||
def click_move_button(self, widget, event):
|
def click_move_button(self, widget, event):
|
||||||
if event.button == 3:
|
if event.button == 3:
|
||||||
x, y = self.TextView.window_to_buffer_coords(2,
|
x, y = self.TextView.window_to_buffer_coords(2,
|
||||||
|
@ -120,10 +267,10 @@ class UberwriterInlinePreview():
|
||||||
f.fix_table()
|
f.fix_table()
|
||||||
|
|
||||||
def populate_popup(self, editor, menu, data=None):
|
def populate_popup(self, editor, menu, data=None):
|
||||||
popover = Gtk.Popover.new(editor)
|
# popover = Gtk.Popover.new(editor)
|
||||||
# pop_cont = Gtk.Container.new()
|
# pop_cont = Gtk.Container.new()
|
||||||
# popover.add(pop_cont)
|
# popover.add(pop_cont)
|
||||||
popover.show_all()
|
# popover.show_all()
|
||||||
|
|
||||||
item = Gtk.MenuItem.new()
|
item = Gtk.MenuItem.new()
|
||||||
item.set_name("PreviewMenuItem")
|
item.set_name("PreviewMenuItem")
|
||||||
|
@ -169,10 +316,7 @@ class UberwriterInlinePreview():
|
||||||
image.show()
|
image.show()
|
||||||
logger.debug("logging image")
|
logger.debug("logging image")
|
||||||
# item.add(image)
|
# item.add(image)
|
||||||
popover.add(image)
|
self.open_popover_with_widget(image)
|
||||||
popover.show_all()
|
|
||||||
item.set_property('width-request', 50)
|
|
||||||
popover.set_property('width-request', 50)
|
|
||||||
else:
|
else:
|
||||||
label = Gtk.Label()
|
label = Gtk.Label()
|
||||||
msg = 'Formula looks incorrect:\n' + result
|
msg = 'Formula looks incorrect:\n' + result
|
||||||
|
@ -295,6 +439,27 @@ class UberwriterInlinePreview():
|
||||||
menu.show()
|
menu.show()
|
||||||
found_match = True
|
found_match = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if not found_match:
|
||||||
|
start_iter = self.TextBuffer.get_iter_at_mark(self.ClickMark)
|
||||||
|
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)
|
||||||
|
print(word)
|
||||||
|
terms = get_dictionary(word)
|
||||||
|
sc = Gtk.ScrolledWindow.new()
|
||||||
|
# tv = Gtk.TextView.new()
|
||||||
|
# tv.set_editable(False)
|
||||||
|
# tv.set_name('LexikonBubble')
|
||||||
|
|
||||||
|
sc.add(fill_lexikon_bubble(word, get_dictionary(word)))
|
||||||
|
sc.props.width_request = 500
|
||||||
|
sc.props.height_request = 400
|
||||||
|
tv.get_buffer().set_text(terms)
|
||||||
|
sc.show_all()
|
||||||
|
self.open_popover_with_widget(sc)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def move_popup(self):
|
def move_popup(self):
|
||||||
|
|
|
@ -84,6 +84,8 @@ class UberwriterWindow(Window):
|
||||||
'toggle-fullscreen': (GObject.SIGNAL_ACTION, None, ()),
|
'toggle-fullscreen': (GObject.SIGNAL_ACTION, None, ()),
|
||||||
'toggle-spellcheck': (GObject.SIGNAL_ACTION, None, ()),
|
'toggle-spellcheck': (GObject.SIGNAL_ACTION, None, ()),
|
||||||
'toggle-preview': (GObject.SIGNAL_ACTION, None, ()),
|
'toggle-preview': (GObject.SIGNAL_ACTION, None, ()),
|
||||||
|
'toggle-search': (GObject.SIGNAL_ACTION, None, ()),
|
||||||
|
'toggle-search-replace': (GObject.SIGNAL_ACTION, None, ()),
|
||||||
'close-window': (GObject.SIGNAL_ACTION, None, ())
|
'close-window': (GObject.SIGNAL_ACTION, None, ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,10 +140,10 @@ class UberwriterWindow(Window):
|
||||||
length = 0
|
length = 0
|
||||||
self.word_count.set_text(str(length))
|
self.word_count.set_text(str(length))
|
||||||
|
|
||||||
|
|
||||||
def mark_set(self, buffer, location, mark, data=None):
|
def mark_set(self, buffer, location, mark, data=None):
|
||||||
if mark.get_name() == 'insert':
|
if mark.get_name() in ['insert', 'gtk_drag_target']:
|
||||||
self.check_scroll()
|
self.check_scroll(mark)
|
||||||
|
return True
|
||||||
|
|
||||||
def text_changed(self, widget, data=None):
|
def text_changed(self, widget, data=None):
|
||||||
if self.did_change == False:
|
if self.did_change == False:
|
||||||
|
@ -154,7 +156,7 @@ class UberwriterWindow(Window):
|
||||||
|
|
||||||
self.buffer_modified_for_status_bar = True
|
self.buffer_modified_for_status_bar = True
|
||||||
self.update_line_and_char_count()
|
self.update_line_and_char_count()
|
||||||
self.check_scroll()
|
self.check_scroll(self.TextBuffer.get_insert())
|
||||||
|
|
||||||
def toggle_fullscreen(self, widget, data=None):
|
def toggle_fullscreen(self, widget, data=None):
|
||||||
if widget.get_active():
|
if widget.get_active():
|
||||||
|
@ -179,10 +181,9 @@ class UberwriterWindow(Window):
|
||||||
self.MarkupBuffer.focusmode_highlight()
|
self.MarkupBuffer.focusmode_highlight()
|
||||||
self.focusmode = True
|
self.focusmode = True
|
||||||
self.TextEditor.grab_focus()
|
self.TextEditor.grab_focus()
|
||||||
self.check_scroll()
|
self.check_scroll(self.TextBuffer.get_insert())
|
||||||
if self.spellcheck != False:
|
if self.spellcheck != False:
|
||||||
self.SpellChecker._misspelled.set_property('underline', 0)
|
self.SpellChecker._misspelled.set_property('underline', 0)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.remove_typewriter()
|
self.remove_typewriter()
|
||||||
self.focusmode = False
|
self.focusmode = False
|
||||||
|
@ -222,11 +223,10 @@ class UberwriterWindow(Window):
|
||||||
widget.get_vadjustment().props.value = pos
|
widget.get_vadjustment().props.value = pos
|
||||||
return True # continue ticking
|
return True # continue ticking
|
||||||
|
|
||||||
def check_scroll(self):
|
def check_scroll(self, mark):
|
||||||
gradient_offset = 80
|
gradient_offset = 80
|
||||||
buf = self.TextEditor.get_buffer()
|
buf = self.TextEditor.get_buffer()
|
||||||
ins = buf.get_insert()
|
ins_it = buf.get_iter_at_mark(mark)
|
||||||
ins_it = buf.get_iter_at_mark(ins)
|
|
||||||
loc_rect = self.TextEditor.get_iter_location(ins_it)
|
loc_rect = self.TextEditor.get_iter_location(ins_it)
|
||||||
|
|
||||||
# alignment offset added from top
|
# alignment offset added from top
|
||||||
|
@ -264,29 +264,34 @@ class UberwriterWindow(Window):
|
||||||
width_request = 600
|
width_request = 600
|
||||||
if(w_width < 900):
|
if(w_width < 900):
|
||||||
self.MarkupBuffer.set_multiplier(8)
|
self.MarkupBuffer.set_multiplier(8)
|
||||||
pango_font = Pango.FontDescription("Inconsolata 12px")
|
|
||||||
self.TextEditor.modify_font(pango_font)
|
|
||||||
self.current_font_size = 12
|
self.current_font_size = 12
|
||||||
self.alignment_padding = 30
|
self.alignment_padding = 30
|
||||||
lm = 7 * 8
|
lm = 7 * 8
|
||||||
|
self.get_style_context().remove_class("medium")
|
||||||
|
self.get_style_context().remove_class("large")
|
||||||
|
self.get_style_context().add_class("small")
|
||||||
|
|
||||||
elif(w_width < 1400):
|
elif(w_width < 1400):
|
||||||
self.MarkupBuffer.set_multiplier(10)
|
self.MarkupBuffer.set_multiplier(10)
|
||||||
pango_font = Pango.FontDescription("Inconsolata 15px")
|
|
||||||
self.TextEditor.modify_font(pango_font)
|
|
||||||
width_request = 800
|
width_request = 800
|
||||||
self.current_font_size = 15
|
self.current_font_size = 15
|
||||||
self.alignment_padding = 40
|
self.alignment_padding = 40
|
||||||
lm = 7 * 10
|
lm = 7 * 10
|
||||||
|
self.get_style_context().remove_class("small")
|
||||||
|
self.get_style_context().remove_class("large")
|
||||||
|
self.get_style_context().add_class("medium")
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.MarkupBuffer.set_multiplier(13)
|
self.MarkupBuffer.set_multiplier(13)
|
||||||
pango_font = Pango.FontDescription("Inconsolata 17px")
|
|
||||||
self.TextEditor.modify_font(pango_font)
|
|
||||||
self.current_font_size = 17
|
self.current_font_size = 17
|
||||||
width_request = 1000
|
width_request = 1000
|
||||||
self.alignment_padding = 60
|
self.alignment_padding = 60
|
||||||
lm = 7 * 13
|
lm = 7 * 13
|
||||||
|
self.get_style_context().remove_class("medium")
|
||||||
|
self.get_style_context().remove_class("small")
|
||||||
|
self.get_style_context().add_class("large")
|
||||||
|
|
||||||
self.EditorAlignment.props.top_padding = self.alignment_padding
|
self.EditorAlignment.props.top_padding = self.alignment_padding
|
||||||
self.EditorAlignment.props.bottom_padding = self.alignment_padding
|
self.EditorAlignment.props.bottom_padding = self.alignment_padding
|
||||||
self.TextEditor.set_left_margin(lm)
|
self.TextEditor.set_left_margin(lm)
|
||||||
|
@ -356,9 +361,9 @@ class UberwriterWindow(Window):
|
||||||
filechooser.destroy()
|
filechooser.destroy()
|
||||||
return response
|
return response
|
||||||
|
|
||||||
elif response == Gtk.ResponseType.CANCEL:
|
else:
|
||||||
filechooser.destroy()
|
filechooser.destroy()
|
||||||
return response
|
return Gtk.ResponseType.CANCEL
|
||||||
|
|
||||||
def save_document_as(self, widget, data=None):
|
def save_document_as(self, widget, data=None):
|
||||||
filechooser = Gtk.FileChooserDialog(
|
filechooser = Gtk.FileChooserDialog(
|
||||||
|
@ -398,8 +403,9 @@ class UberwriterWindow(Window):
|
||||||
filechooser.destroy()
|
filechooser.destroy()
|
||||||
self.did_change = False
|
self.did_change = False
|
||||||
|
|
||||||
elif response == Gtk.ResponseType.CANCEL:
|
else:
|
||||||
filechooser.destroy()
|
filechooser.destroy()
|
||||||
|
return Gtk.ResponseType.CANCEL
|
||||||
|
|
||||||
def export(self, export_type="html"):
|
def export(self, export_type="html"):
|
||||||
filechooser = Gtk.FileChooserDialog(
|
filechooser = Gtk.FileChooserDialog(
|
||||||
|
@ -530,10 +536,12 @@ class UberwriterWindow(Window):
|
||||||
)
|
)
|
||||||
dialog.add_button(_("Close without Saving"), Gtk.ResponseType.NO)
|
dialog.add_button(_("Close without Saving"), Gtk.ResponseType.NO)
|
||||||
dialog.add_button(_("Cancel"), Gtk.ResponseType.CANCEL)
|
dialog.add_button(_("Cancel"), Gtk.ResponseType.CANCEL)
|
||||||
dialog.add_button(_("Save now"), Gtk.ResponseType.YES).grab_focus()
|
dialog.add_button(_("Save now"), Gtk.ResponseType.YES)
|
||||||
dialog.set_title(_('Unsaved changes'))
|
dialog.set_title(_('Unsaved changes'))
|
||||||
dialog.set_default_size(200, 150)
|
dialog.set_default_size(200, 150)
|
||||||
|
dialog.set_default_response(Gtk.ResponseType.YES)
|
||||||
response = dialog.run()
|
response = dialog.run()
|
||||||
|
|
||||||
if response == Gtk.ResponseType.YES:
|
if response == Gtk.ResponseType.YES:
|
||||||
title = self.get_title()
|
title = self.get_title()
|
||||||
if self.save_document(widget = None) == Gtk.ResponseType.CANCEL:
|
if self.save_document(widget = None) == Gtk.ResponseType.CANCEL:
|
||||||
|
@ -542,12 +550,12 @@ class UberwriterWindow(Window):
|
||||||
else:
|
else:
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
return response
|
return response
|
||||||
elif response == Gtk.ResponseType.CANCEL:
|
|
||||||
dialog.destroy()
|
|
||||||
return response
|
|
||||||
elif response == Gtk.ResponseType.NO:
|
elif response == Gtk.ResponseType.NO:
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
return response
|
return response
|
||||||
|
else:
|
||||||
|
dialog.destroy()
|
||||||
|
return Gtk.ResponseType.CANCEL
|
||||||
|
|
||||||
def new_document(self, widget):
|
def new_document(self, widget):
|
||||||
if self.check_change() == Gtk.ResponseType.CANCEL:
|
if self.check_change() == Gtk.ResponseType.CANCEL:
|
||||||
|
@ -604,10 +612,10 @@ class UberwriterWindow(Window):
|
||||||
def on_drag_data_received(self, widget, drag_context, x, y,
|
def on_drag_data_received(self, widget, drag_context, x, y,
|
||||||
data, info, time):
|
data, info, time):
|
||||||
"""Handle drag and drop events"""
|
"""Handle drag and drop events"""
|
||||||
|
|
||||||
if info == 1:
|
if info == 1:
|
||||||
# uri target
|
# uri target
|
||||||
uris = data.get_uris()
|
uris = data.get_uris()
|
||||||
|
print(uris)
|
||||||
for uri in uris:
|
for uri in uris:
|
||||||
uri = urllib.parse.unquote_plus(uri)
|
uri = urllib.parse.unquote_plus(uri)
|
||||||
mime = mimetypes.guess_type(uri)
|
mime = mimetypes.guess_type(uri)
|
||||||
|
@ -622,21 +630,28 @@ class UberwriterWindow(Window):
|
||||||
text = "[Insert link title here](%s)" % uri
|
text = "[Insert link title here](%s)" % uri
|
||||||
ll = 1
|
ll = 1
|
||||||
lr = 22
|
lr = 22
|
||||||
|
self.TextBuffer.place_cursor(self.TextBuffer.get_iter_at_mark(
|
||||||
|
self.TextBuffer.get_mark('gtk_drag_target')))
|
||||||
self.TextBuffer.insert_at_cursor(text)
|
self.TextBuffer.insert_at_cursor(text)
|
||||||
insert_mark = self.TextBuffer.get_insert()
|
insert_mark = self.TextBuffer.get_insert()
|
||||||
selection_bound = self.TextBuffer.get_selection_bound()
|
selection_bound = self.TextBuffer.get_selection_bound()
|
||||||
cursor_iter = self.TextBuffer.get_iter_at_mark(insert_mark)
|
cursor_iter = self.TextBuffer.get_iter_at_mark(insert_mark)
|
||||||
cursor_iter.backward_chars(len(text) - ll)
|
cursor_iter.backward_chars(len(text) - ll)
|
||||||
|
print('move_cursor')
|
||||||
self.TextBuffer.move_mark(insert_mark, cursor_iter)
|
self.TextBuffer.move_mark(insert_mark, cursor_iter)
|
||||||
cursor_iter.forward_chars(lr)
|
cursor_iter.forward_chars(lr)
|
||||||
self.TextBuffer.move_mark(selection_bound, cursor_iter)
|
self.TextBuffer.move_mark(selection_bound, cursor_iter)
|
||||||
|
print('move selection')
|
||||||
|
|
||||||
elif info == 2:
|
elif info == 2:
|
||||||
# Text target
|
# Text target
|
||||||
|
self.TextBuffer.place_cursor(self.TextBuffer.get_iter_at_mark(
|
||||||
|
self.TextBuffer.get_mark('gtk_drag_target')))
|
||||||
self.TextBuffer.insert_at_cursor(data.get_text())
|
self.TextBuffer.insert_at_cursor(data.get_text())
|
||||||
|
Gtk.drag_finish(drag_context, True, True, time)
|
||||||
self.present()
|
self.present()
|
||||||
|
print("returning true")
|
||||||
|
return False
|
||||||
|
|
||||||
def toggle_preview(self, widget, data=None):
|
def toggle_preview(self, widget, data=None):
|
||||||
if widget.get_active():
|
if widget.get_active():
|
||||||
|
@ -680,6 +695,7 @@ class UberwriterWindow(Window):
|
||||||
self.TextEditor.show()
|
self.TextEditor.show()
|
||||||
|
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
return True
|
||||||
|
|
||||||
def on_click_link(self, view, frame, req, data=None):
|
def on_click_link(self, view, frame, req, data=None):
|
||||||
# This provide ability for self.webview to open links in default browser
|
# This provide ability for self.webview to open links in default browser
|
||||||
|
@ -692,30 +708,25 @@ class UberwriterWindow(Window):
|
||||||
self.dark_mode = widget.get_active()
|
self.dark_mode = widget.get_active()
|
||||||
if self.dark_mode:
|
if self.dark_mode:
|
||||||
# Dark Mode is on
|
# Dark Mode is on
|
||||||
css = open(helpers.get_media_path('style_dark.css'), 'rb')
|
self.gtk_settings.set_property('gtk-application-prefer-dark-theme', True)
|
||||||
css_data = css.read()
|
self.get_style_context().add_class("dark_mode")
|
||||||
css.close()
|
|
||||||
self.style_provider.load_from_data(css_data)
|
|
||||||
# self.background_image = helpers.get_media_path('bg_dark.png')
|
|
||||||
self.MarkupBuffer.dark_mode(True)
|
self.MarkupBuffer.dark_mode(True)
|
||||||
|
# self.background_image = helpers.get_media_path('bg_dark.png')
|
||||||
else:
|
else:
|
||||||
# Dark mode off
|
# Dark mode off
|
||||||
css = open(helpers.get_media_path('style.css'), 'rb')
|
self.gtk_settings.set_property('gtk-application-prefer-dark-theme', False)
|
||||||
css_data = css.read()
|
self.get_style_context().remove_class("dark_mode")
|
||||||
css.close()
|
|
||||||
self.style_provider.load_from_data(css_data)
|
|
||||||
# self.background_image = helpers.get_media_path('bg_light.png')
|
|
||||||
self.MarkupBuffer.dark_mode(False)
|
self.MarkupBuffer.dark_mode(False)
|
||||||
|
# self.background_image = helpers.get_media_path('bg_light.png')
|
||||||
|
|
||||||
# surface = cairo.ImageSurface.create_from_png(self.background_image)
|
# surface = cairo.ImageSurface.create_from_png(self.background_image)
|
||||||
# self.background_pattern = cairo.SurfacePattern(surface)
|
# self.background_pattern = cairo.SurfacePattern(surface)
|
||||||
# self.background_pattern.set_extend(cairo.EXTEND_REPEAT)
|
# self.background_pattern.set_extend(cairo.EXTEND_REPEAT)
|
||||||
|
|
||||||
Gtk.StyleContext.add_provider_for_screen(
|
# Gtk.StyleContext.add_provider_for_screen(
|
||||||
Gdk.Screen.get_default(), self.style_provider,
|
# Gdk.Screen.get_default(), self.style_provider,
|
||||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
# Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||||
)
|
# )
|
||||||
# Redraw contents of window (self)
|
# Redraw contents of window (self)
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
|
@ -807,7 +818,8 @@ class UberwriterWindow(Window):
|
||||||
def poll_for_motion(self):
|
def poll_for_motion(self):
|
||||||
if (self.was_motion == False
|
if (self.was_motion == False
|
||||||
and self.status_bar_visible
|
and self.status_bar_visible
|
||||||
and self.buffer_modified_for_status_bar):
|
and self.buffer_modified_for_status_bar
|
||||||
|
and self.TextEditor.props.has_focus):
|
||||||
# self.status_bar.set_state_flags(Gtk.StateFlags.INSENSITIVE, True)
|
# self.status_bar.set_state_flags(Gtk.StateFlags.INSENSITIVE, True)
|
||||||
self.statusbar_revealer.set_reveal_child(False)
|
self.statusbar_revealer.set_reveal_child(False)
|
||||||
self.hb_revealer.set_reveal_child(False)
|
self.hb_revealer.set_reveal_child(False)
|
||||||
|
@ -838,20 +850,33 @@ class UberwriterWindow(Window):
|
||||||
GObject.timeout_add(3000, self.poll_for_motion)
|
GObject.timeout_add(3000, self.poll_for_motion)
|
||||||
self.was_motion = True
|
self.was_motion = True
|
||||||
|
|
||||||
|
def focus_out(self, widget, data=None):
|
||||||
|
if self.status_bar_visible == False:
|
||||||
|
self.statusbar_revealer.set_reveal_child(True)
|
||||||
|
self.hb_revealer.set_reveal_child(True)
|
||||||
|
self.hb.props.opacity = 1
|
||||||
|
self.status_bar_visible = True
|
||||||
|
self.buffer_modified_for_status_bar = False
|
||||||
|
self.update_line_and_char_count()
|
||||||
|
|
||||||
def draw_gradient(self, widget, cr):
|
def draw_gradient(self, widget, cr):
|
||||||
|
bg_color = self.get_style_context().get_background_color(Gtk.StateFlags.ACTIVE)
|
||||||
|
|
||||||
lg_top = cairo.LinearGradient(0, 0, 0, 80)
|
lg_top = cairo.LinearGradient(0, 0, 0, 80)
|
||||||
lg_top.add_color_stop_rgba(0, 1, 1, 1, 1)
|
lg_top.add_color_stop_rgba(0, bg_color.red, bg_color.green, bg_color.blue, 1)
|
||||||
lg_top.add_color_stop_rgba(1, 1, 1, 1, 0)
|
lg_top.add_color_stop_rgba(1, bg_color.red, bg_color.green, bg_color.blue, 0)
|
||||||
|
|
||||||
width = widget.get_allocation().width
|
width = widget.get_allocation().width
|
||||||
height = widget.get_allocation().height
|
height = widget.get_allocation().height
|
||||||
|
|
||||||
cr.rectangle(0, 0, width, 80)
|
cr.rectangle(0, 0, width, 80)
|
||||||
cr.set_source(lg_top)
|
cr.set_source(lg_top)
|
||||||
cr.fill()
|
cr.fill()
|
||||||
cr.rectangle(0, height - 80, width, height)
|
cr.rectangle(0, height - 80, width, height)
|
||||||
|
|
||||||
lg_btm = cairo.LinearGradient(0, height - 80, 0, height)
|
lg_btm = cairo.LinearGradient(0, height - 80, 0, height)
|
||||||
lg_btm.add_color_stop_rgba(1, 1, 1, 1, 1)
|
lg_btm.add_color_stop_rgba(1, bg_color.red, bg_color.green, bg_color.blue, 1)
|
||||||
lg_btm.add_color_stop_rgba(0, 1, 1, 1, 0)
|
lg_btm.add_color_stop_rgba(0, bg_color.red, bg_color.green, bg_color.blue, 0)
|
||||||
|
|
||||||
cr.set_source(lg_btm)
|
cr.set_source(lg_btm)
|
||||||
cr.fill()
|
cr.fill()
|
||||||
|
@ -873,6 +898,7 @@ class UberwriterWindow(Window):
|
||||||
self.connect('toggle-preview', self.menu_activate_preview)
|
self.connect('toggle-preview', self.menu_activate_preview)
|
||||||
self.connect('toggle-spellcheck', self.toggle_spellcheck)
|
self.connect('toggle-spellcheck', self.toggle_spellcheck)
|
||||||
self.connect('close-window', self.on_mnu_close_activate)
|
self.connect('close-window', self.on_mnu_close_activate)
|
||||||
|
self.connect('toggle-search', self.open_search_and_replace)
|
||||||
self.scroll_adjusted = False
|
self.scroll_adjusted = False
|
||||||
# Code for other initialization actions should be added here.
|
# Code for other initialization actions should be added here.
|
||||||
|
|
||||||
|
@ -887,6 +913,7 @@ class UberwriterWindow(Window):
|
||||||
self.hb = Gtk.HeaderBar()
|
self.hb = Gtk.HeaderBar()
|
||||||
self.hb_revealer.add(self.hb)
|
self.hb_revealer.add(self.hb)
|
||||||
self.hb_revealer.props.transition_duration = 1000
|
self.hb_revealer.props.transition_duration = 1000
|
||||||
|
self.hb_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
|
||||||
self.hb.props.show_close_button = True
|
self.hb.props.show_close_button = True
|
||||||
self.hb.get_style_context().add_class("titlebar")
|
self.hb.get_style_context().add_class("titlebar")
|
||||||
self.set_titlebar(self.hb_revealer)
|
self.set_titlebar(self.hb_revealer)
|
||||||
|
@ -906,6 +933,7 @@ class UberwriterWindow(Window):
|
||||||
self.hb.pack_end(btn_settings)
|
self.hb.pack_end(btn_settings)
|
||||||
self.hb.show_all()
|
self.hb.show_all()
|
||||||
|
|
||||||
|
|
||||||
self.title_end = " – UberWriter"
|
self.title_end = " – UberWriter"
|
||||||
self.set_headerbar_title("New File" + self.title_end)
|
self.set_headerbar_title("New File" + self.title_end)
|
||||||
|
|
||||||
|
@ -941,6 +969,7 @@ class UberwriterWindow(Window):
|
||||||
|
|
||||||
# Setup light background
|
# Setup light background
|
||||||
self.TextEditor = TextEditor()
|
self.TextEditor = TextEditor()
|
||||||
|
self.TextEditor.set_name('UberwriterEditor')
|
||||||
|
|
||||||
base_leftmargin = 40
|
base_leftmargin = 40
|
||||||
# self.TextEditor.set_left_margin(base_leftmargin)
|
# self.TextEditor.set_left_margin(base_leftmargin)
|
||||||
|
@ -949,6 +978,7 @@ class UberwriterWindow(Window):
|
||||||
self.TextEditor.props.halign = Gtk.Align.CENTER
|
self.TextEditor.props.halign = Gtk.Align.CENTER
|
||||||
self.TextEditor.set_vadjustment(builder.get_object('vadjustment1'))
|
self.TextEditor.set_vadjustment(builder.get_object('vadjustment1'))
|
||||||
self.TextEditor.set_wrap_mode(Gtk.WrapMode.WORD)
|
self.TextEditor.set_wrap_mode(Gtk.WrapMode.WORD)
|
||||||
|
self.TextEditor.connect('focus-out-event', self.focus_out)
|
||||||
|
|
||||||
self.TextEditor.show()
|
self.TextEditor.show()
|
||||||
self.TextEditor.grab_focus()
|
self.TextEditor.grab_focus()
|
||||||
|
@ -972,9 +1002,6 @@ class UberwriterWindow(Window):
|
||||||
|
|
||||||
self.PreviewPane = builder.get_object('preview_scrolledwindow')
|
self.PreviewPane = builder.get_object('preview_scrolledwindow')
|
||||||
|
|
||||||
pangoFont = Pango.FontDescription("Inconsolata 12px")
|
|
||||||
self.TextEditor.modify_font(pangoFont)
|
|
||||||
|
|
||||||
self.TextEditor.set_margin_top(38)
|
self.TextEditor.set_margin_top(38)
|
||||||
self.TextEditor.set_margin_bottom(16)
|
self.TextEditor.set_margin_bottom(16)
|
||||||
|
|
||||||
|
@ -1015,18 +1042,21 @@ class UberwriterWindow(Window):
|
||||||
self.textchange = False
|
self.textchange = False
|
||||||
self.scroll_count = 0
|
self.scroll_count = 0
|
||||||
self.timestamp_last_mouse_motion = 0
|
self.timestamp_last_mouse_motion = 0
|
||||||
self.TextBuffer.connect('mark-set', self.mark_set)
|
self.TextBuffer.connect_after('mark-set', self.mark_set)
|
||||||
|
|
||||||
|
# Drag and drop
|
||||||
|
|
||||||
# self.TextEditor.drag_dest_unset()
|
# self.TextEditor.drag_dest_unset()
|
||||||
# Drag and drop
|
# self.TextEditor.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
|
||||||
self.TextEditor.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
|
|
||||||
|
|
||||||
self.target_list = Gtk.TargetList.new([])
|
self.target_list = Gtk.TargetList.new([])
|
||||||
self.target_list.add_uri_targets(1)
|
self.target_list.add_uri_targets(1)
|
||||||
self.target_list.add_text_targets(2)
|
self.target_list.add_text_targets(2)
|
||||||
|
|
||||||
self.TextEditor.drag_dest_set_target_list(self.target_list)
|
self.TextEditor.drag_dest_set_target_list(self.target_list)
|
||||||
self.TextEditor.connect('drag-data-received', self.on_drag_data_received)
|
self.TextEditor.connect_after('drag-data-received', self.on_drag_data_received)
|
||||||
|
def on_drop(widget, *args):
|
||||||
|
print("drop")
|
||||||
|
self.TextEditor.connect('drag-drop', on_drop)
|
||||||
|
|
||||||
|
|
||||||
self.TextBuffer.connect('paste-done', self.paste_done)
|
self.TextBuffer.connect('paste-done', self.paste_done)
|
||||||
|
@ -1075,8 +1105,15 @@ class UberwriterWindow(Window):
|
||||||
self.connect("configure-event", self.window_resize)
|
self.connect("configure-event", self.window_resize)
|
||||||
self.connect("delete-event", self.on_delete_called)
|
self.connect("delete-event", self.on_delete_called)
|
||||||
|
|
||||||
|
self.gtk_settings = Gtk.Settings.get_default()
|
||||||
self.load_settings(builder)
|
self.load_settings(builder)
|
||||||
|
|
||||||
|
self.connect_after('realize', self.color_window)
|
||||||
|
|
||||||
|
def color_window(self, widget, data=None):
|
||||||
|
window_gdk = self.get_window()
|
||||||
|
window_gdk.set_background(Gdk.Color(0, 1, 0))
|
||||||
|
|
||||||
def alt_mod(self, widget, event, data=None):
|
def alt_mod(self, widget, event, data=None):
|
||||||
# TODO: Click and open when alt is pressed
|
# TODO: Click and open when alt is pressed
|
||||||
if event.state & Gdk.ModifierType.MOD2_MASK:
|
if event.state & Gdk.ModifierType.MOD2_MASK:
|
||||||
|
|
Loading…
Reference in New Issue