Zim

Merge lp:~plprgt/zim/lines into lp:~jaap.karssenberg/zim/pyzim

Proposed by Pl
Status: Merged
Merged at revision: 825
Proposed branch: lp:~plprgt/zim/lines
Merge into: lp:~jaap.karssenberg/zim/pyzim
Diff against target: 363 lines (+203/-1) (has conflicts)
10 files modified
data/menubar.xml (+1/-0)
tests/pageview.py (+50/-0)
zim/formats/__init__.py (+3/-0)
zim/formats/html.py (+5/-0)
zim/formats/latex.py (+3/-0)
zim/formats/markdown.py (+3/-0)
zim/formats/plain.py (+2/-0)
zim/formats/rst.py (+3/-0)
zim/formats/wiki.py (+15/-1)
zim/gui/pageview.py (+118/-0)
Text conflict in zim/gui/pageview.py
To merge this branch: bzr merge lp:~plprgt/zim/lines
Reviewer Review Type Date Requested Status
Jaap Karssenberg Pending
Review via email: mp+276927@code.launchpad.net

Description of the change

Addition of horizontal lines to separate different sections in Zim.

To post a comment you must log in.
lp:~plprgt/zim/lines updated
807. By Pavel_M

Horizontal Lines: Change from '___' to '---'.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/menubar.xml'
2--- data/menubar.xml 2015-11-13 20:21:57 +0000
3+++ data/menubar.xml 2016-01-18 16:19:18 +0000
4@@ -88,6 +88,7 @@
5 <menuitem action='insert_bullet_list'/>
6 <menuitem action='insert_numbered_list'/>
7 <menuitem action='insert_checkbox_list'/>
8+ <menuitem action='insert_line'/>
9 <placeholder name='plugin_items'/>
10 <separator/>
11 <menuitem action='insert_text_from_file'/>
12
13=== modified file 'tests/pageview.py'
14--- tests/pageview.py 2015-11-13 20:21:57 +0000
15+++ tests/pageview.py 2016-01-18 16:19:18 +0000
16@@ -47,6 +47,56 @@
17 return PageView(ui)
18
19
20+class TestLines(tests.TestCase):
21+
22+ def testLines(self):
23+ '''Test lines formatting.'''
24+
25+ pageview = setUpPageView()
26+ buffer = pageview.view.get_buffer()
27+
28+ def check_text(input, result):
29+ buffer.set_text(input)
30+ tree = buffer.get_parsetree()
31+ dumper = get_format('wiki').Dumper()
32+ text = ''.join(dumper.dump(tree))
33+ self.assertEqual(text, result)
34+
35+ # Check formatting.
36+ string = 'text... \n{}\n text... \n'
37+ input = string.format('-'*4)
38+ check_text(input, input) # doesn't format
39+ for i in range(30):
40+ if i < 5:
41+ output = string.format('-'*i)
42+ else:
43+ output = string.format(LINE_TEXT)
44+ input = string.format('-'*i)
45+ check_text(input, output)
46+
47+ # Check that any additional symbol other than '-' fails.
48+ input = 'text... {}\n text... \n'.format('-'*10)
49+ check_text(input, input)
50+ input = 'text... \n{}text... \n'.format('-'*10)
51+ check_text(input, input)
52+ input = 'text... \n{} \n text... \n'.format('-'*10)
53+ check_text(input, input)
54+ input = 'text... \n {}\n text... \n'.format('-'*10)
55+ check_text(input, input)
56+
57+ # Check more complex text.
58+ string = 'text... \n\n{0}\n\n{0}\n\n text... \n'
59+ input = string.format('-'*7)
60+ output = string.format(LINE_TEXT)
61+ check_text(input, output)
62+
63+ string = '... \n{}\n{}\n{}\n ... \n{}\n{}0\n'
64+ input = string.format('-'*8, '-'*6, '-'*4, '-'*11, '-'*10)
65+ output = string.format(LINE_TEXT, LINE_TEXT, '-'*4, LINE_TEXT, '-'*10)
66+ check_text(input, output)
67+
68+
69+
70 class TestCaseMixin(object):
71 # Mixin class with extra test methods
72
73
74=== modified file 'zim/formats/__init__.py'
75--- zim/formats/__init__.py 2015-10-30 21:34:34 +0000
76+++ zim/formats/__init__.py 2016-01-18 16:19:18 +0000
77@@ -141,6 +141,9 @@
78 TABLEROW = 'trow'
79 TABLEDATA = 'td'
80
81+LINE = 'line'
82+LINE_TEXT = '-'*20
83+
84 BLOCK_LEVEL = (PARAGRAPH, HEADING, VERBATIM_BLOCK, BLOCK, OBJECT, IMAGE, LISTITEM, TABLE)
85
86
87
88=== modified file 'zim/formats/html.py'
89--- zim/formats/html.py 2015-02-15 20:12:11 +0000
90+++ zim/formats/html.py 2016-01-18 16:19:18 +0000
91@@ -265,3 +265,8 @@
92 strings.insert(0, ' <td>')
93 strings.append('</td>\n')
94 return strings
95+
96+ def dump_line(self, tag, attrib, strings=None):
97+ return '\n<hr>\n'
98+
99+
100
101=== modified file 'zim/formats/latex.py'
102--- zim/formats/latex.py 2015-06-13 19:48:28 +0000
103+++ zim/formats/latex.py 2016-01-18 16:19:18 +0000
104@@ -253,3 +253,6 @@
105
106 table.append('\end{tabular}')
107 return map(lambda line: line+"\n", table)
108+
109+ def dump_line(self, tag, attrib, strings=None):
110+ return '\n\\hrule\n'
111
112=== modified file 'zim/formats/markdown.py'
113--- zim/formats/markdown.py 2015-10-30 21:34:34 +0000
114+++ zim/formats/markdown.py 2016-01-18 16:19:18 +0000
115@@ -130,3 +130,6 @@
116 def dump_td(self, tag, attrib, strings):
117 strings = [s.replace('\n', '<br>').replace('|', '∣') for s in strings]
118 return [self._concat(strings)]
119+
120+ def dump_line(self, tag, attrib, strings=None):
121+ return '\n{}\n'.format('*'*5)
122
123=== modified file 'zim/formats/plain.py'
124--- zim/formats/plain.py 2015-10-30 21:34:34 +0000
125+++ zim/formats/plain.py 2016-01-18 16:19:18 +0000
126@@ -226,3 +226,5 @@
127 strings = [s.replace('|', '∣') for s in strings]
128 return [self._concat(strings)]
129
130+ def dump_line(self, tag, attrib, strings=None):
131+ return '\n{}\n'.format(LINE_TEXT)
132
133=== modified file 'zim/formats/rst.py'
134--- zim/formats/rst.py 2015-10-30 21:34:34 +0000
135+++ zim/formats/rst.py 2016-01-18 16:19:18 +0000
136@@ -120,3 +120,6 @@
137 def dump_td(self, tag, attrib, strings):
138 strings = [s.replace('|', '∣') for s in strings]
139 return [self._concat(strings)]
140+
141+ def dump_line(self, tag, attrib, strings=None):
142+ return '\n{}\n'.format('*'*5)
143
144=== modified file 'zim/formats/wiki.py'
145--- zim/formats/wiki.py 2015-10-30 21:34:34 +0000
146+++ zim/formats/wiki.py 2016-01-18 16:19:18 +0000
147@@ -171,7 +171,10 @@
148 ^(?= \s*? \n) # empty line / only spaces
149 ''',
150 process=self.parse_table
151- )
152+ ),
153+ # line format
154+ Rule(LINE, r'(?<=\n)-{4}-+(?=\n)', process=self.parse_line) # \n-----\n
155+
156 )
157 p.process_unmatched = self.parse_para
158 return p
159@@ -428,6 +431,9 @@
160 def parse_tag(builder, text):
161 builder.append(TAG, {'name': text[1:]}, text)
162
163+ @staticmethod
164+ def parse_line(builder, text):
165+ builder.append(LINE)
166
167
168
169@@ -576,3 +582,11 @@
170 strings = map(lambda s: s.replace('\n', '\\n').replace('|', '\\|'), strings)
171 strings = map(lambda s: s.replace('<br>', '\\n'), strings)
172 return [self._concat(strings)]
173+
174+ def dump_line(self, tag, attrib, strings = None):
175+ #logger.debug("Dumping line tag:%s, attrib:%s, strings:%s", tag, attrib, strings)
176+ if not strings:
177+ strings = [LINE_TEXT]
178+ elif isinstance(strings, basestring):
179+ strings = [strings]
180+ return strings
181
182=== modified file 'zim/gui/pageview.py'
183--- zim/gui/pageview.py 2016-01-07 11:10:24 +0000
184+++ zim/gui/pageview.py 2016-01-18 16:19:18 +0000
185@@ -34,8 +34,13 @@
186 from zim.parsing import link_type, Re, url_re
187 from zim.formats import get_format, increase_list_iter, \
188 ParseTree, ElementTreeModule, OldParseTreeBuilder, \
189+<<<<<<< TREE
190 BULLET, CHECKED_BOX, UNCHECKED_BOX, XCHECKED_BOX
191 from zim.actions import get_gtk_actiongroup, gtk_accelerator_preparse_list, action, toggle_action
192+=======
193+ BULLET, CHECKED_BOX, UNCHECKED_BOX, XCHECKED_BOX, LINE_TEXT
194+from zim.actions import gtk_accelerator_preparse_list
195+>>>>>>> MERGE-SOURCE
196 from zim.gui.widgets import ui_environment, \
197 Dialog, FileDialog, QuestionDialog, ErrorDialog, \
198 Button, CloseButton, MenuButton, BrowserTreeView, InputEntry, \
199@@ -55,6 +60,37 @@
200 logger = logging.getLogger('zim.gui.pageview')
201
202
203+class LineSeparator(CustomObjectWidget):
204+ '''Class to create a separation line.'''
205+ __gsignals__ = {
206+ 'size-request': 'override',
207+ }
208+
209+ def __init__(self):
210+ CustomObjectWidget.__init__(self)
211+ # Set color of the line.
212+ self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('darkgrey'))
213+ # Set size of the line.
214+ self.vbox.set_size_request(self._textview_width, height = 3)
215+
216+class LineObject(CustomObjectClass):
217+ '''Class to work with 'LineSeparator' objects.'''
218+ OBJECT_ATTR = {
219+ 'type': String('line'),
220+ }
221+
222+ def get_widget(self):
223+ '''Creates a new line which can be displayed on the wiki-page.'''
224+ return LineSeparator()
225+
226+ObjectManager.register_object('line', LineObject)
227+
228+def IS_LINE(line):
229+ '''Function used for line autoformatting.'''
230+ length = len(line)
231+ return (line == '-'*length) and (length > 4)
232+
233+
234 STOCK_CHECKED_BOX = 'zim-checked-box'
235 STOCK_UNCHECKED_BOX = 'zim-unchecked-box'
236 STOCK_XCHECKED_BOX = 'zim-xchecked-box'
237@@ -113,9 +149,52 @@
238 # States that influence keybindings - we use this to explicitly
239 # exclude other states. E.g. MOD2_MASK seems to be set when either
240 # numlock or fn keys are active, resulting in keybindings failing
241+<<<<<<< TREE
242 KEYSTATES = gtk.gdk.CONTROL_MASK |gtk.gdk.META_MASK| gtk.gdk.SHIFT_MASK | gtk.gdk.MOD1_MASK
243
244 MENU_ACTIONS = (
245+=======
246+KEYSTATES = gtk.gdk.META_MASK | gtk.gdk.SHIFT_MASK | gtk.gdk.MOD1_MASK
247+
248+ui_actions = (
249+ # name, stock id, label, accelerator, tooltip, readonly
250+ ('undo', 'gtk-undo', _('_Undo'), '<Primary>Z', '', False), # T: Menu item
251+ ('redo', 'gtk-redo', _('_Redo'), '<Primary><shift>Z', '', False), # T: Menu item
252+ ('redo_alt1', None, '', '<Primary>Y', '', False),
253+ ('cut', 'gtk-cut', _('Cu_t'), '<Primary>X', '', False), # T: Menu item
254+ ('copy', 'gtk-copy', _('_Copy'), '<Primary>C', '', False), # T: Menu item
255+ ('paste', 'gtk-paste', _('_Paste'), '<Primary>V', '', False), # T: Menu item
256+ ('delete', 'gtk-delete', _('_Delete'), '', '', False), # T: Menu item
257+ ('toggle_checkbox', STOCK_CHECKED_BOX, _('Toggle Checkbox \'V\''), 'F12', '', False), # T: Menu item
258+ ('xtoggle_checkbox', STOCK_XCHECKED_BOX, _('Toggle Checkbox \'X\''), '<shift>F12', '', False), # T: Menu item
259+ ('edit_object', 'gtk-properties', _('_Edit Link or Object...'), '<Primary>E', '', False), # T: Menu item
260+ ('remove_link', None, _('_Remove Link'), '', '', False), # T: Menu item
261+ ('insert_date', None, _('_Date and Time...'), '<Primary>D', '', False), # T: Menu item
262+ ('insert_image', None, _('_Image...'), '', '', False), # T: Menu item
263+ ('insert_bullet_list', None, _('Bulle_t List'), '', '', False), # T: Menu item
264+ ('insert_numbered_list', None, _('_Numbered List'), '', '', False), # T: Menu item
265+ ('insert_checkbox_list', None, _('Checkbo_x List'), '', '', False), # T: Menu item,
266+ ('apply_format_bullet_list', None, _('Bulle_t List'), '', '', False), # T: Menu item,
267+ ('apply_format_numbered_list', None, _('_Numbered List'), '', '', False), # T: Menu item,
268+ ('apply_format_checkbox_list', None, _('Checkbo_x List'), '', '', False), # T: Menu item,
269+ ('insert_text_from_file', None, _('Text From _File...'), '', '', False), # T: Menu item
270+ ('insert_link', 'zim-link', _('_Link...'), '<Primary>L', _('Insert Link'), False), # T: Menu item
271+ ('insert_line', None, _('Line'), '', '', False), # T: Menu item
272+ ('clear_formatting', None, _('_Clear Formatting'), '<Primary>9', '', False), # T: Menu item
273+ ('show_find', 'gtk-find', _('_Find...'), '<Primary>F', '', True), # T: Menu item
274+ ('show_find_alt1', None, '', '<Primary>F3', '', True),
275+ ('find_next', None, _('Find Ne_xt'), '<Primary>G', '', True), # T: Menu item
276+ ('find_next_alt1', None, '', 'F3', '', True), # T: Menu item
277+ ('find_previous', None, _('Find Pre_vious'), '<Primary><shift>G', '', True), # T: Menu item
278+ ('find_previous_alt1', None, '', '<shift>F3', '', True),
279+ ('show_find_and_replace', 'gtk-find-and-replace', _('_Replace...'), '<Primary>H', '', False), # T: Menu item
280+ ('show_word_count', None, _('Word Count...'), '', '', True), # T: Menu item
281+ ('zoom_in', 'gtk-zoom-in', _('_Zoom In'), '<Primary>plus', '', True), # T: Menu item
282+ ('zoom_in_alt1', None, '', '<Primary>equal', '', True),
283+ ('zoom_out', 'gtk-zoom-out', _('Zoom _Out'), '<Primary>minus', '', True), # T: Menu item
284+ ('zoom_reset', 'gtk-zoom-100', _('_Normal Size'), '<Primary>0', '', True), # T: Menu item to reset zoom
285+
286+>>>>>>> MERGE-SOURCE
287 # name, stock id, label
288 ('insert_new_file_menu', None, _('New _Attachment')), # T: Menu title
289 )
290@@ -891,6 +970,10 @@
291 self.insert_object_at_cursor(obj)
292
293 set_indent(None)
294+ elif element.tag == 'line':
295+ obj = ObjectManager.get_object('line', None, None)
296+ self.insert_object_at_cursor(obj)
297+
298 elif element.tag == 'object':
299 if 'indent' in element.attrib:
300 set_indent(int(element.attrib['indent']))
301@@ -2332,6 +2415,18 @@
302 and hasattr(anchor.manager, 'build_parsetree_of_table'): # fallback should not go here...
303 obj = anchor.manager
304 obj.build_parsetree_of_table(builder, iter)
305+ elif attrib and attrib['type'] == 'line':
306+ # Add (if necessary) additional newline symbols
307+ # to prevent formatting back from line object to text.
308+ _new_iter = iter.copy()
309+ _start = '' if _new_iter.starts_line() else '\n'
310+ _new_iter.forward_char()
311+ _end = '' if _new_iter.ends_line() else '\n'
312+ data = '{}{}{}'.format(_start, LINE_TEXT, _end)
313+ logger.debug("Anchor with Line, obj:%s", anchor.manager)
314+ builder.start('line', attrib)
315+ builder.data(data)
316+ builder.end('line')
317 else:
318 # general object related parsing
319 data = anchor.manager.get_data()
320@@ -4203,6 +4298,12 @@
321 buffer.insert_with_tags_by_name(
322 buffer.get_iter_at_mark(mark), heading, 'style-h'+str(level))
323 buffer.delete_mark(mark)
324+ elif IS_LINE(line):
325+ with buffer.user_action:
326+ buffer.delete(start, end)
327+ obj = ObjectManager.get_object('line', None, None)
328+ buffer.insert_object_at_cursor(obj)
329+ buffer.insert_at_cursor('\n')
330 elif not buffer.get_bullet_at_iter(start) is None:
331 # we are part of bullet list
332 # FIXME should logic be handled by TextBufferList ?
333@@ -4364,6 +4465,7 @@
334 ('insert-text', self.do_insert_text),
335 #~ ('inserted-tree', self.do_insert_tree), # TODO
336 ('insert-pixbuf', self.do_insert_pixbuf),
337+ ('insert-child-anchor', self.do_insert_pixbuf),
338 ('delete-range', self.do_delete_range),
339 ('begin-user-action', self.do_begin_user_action),
340 ('end-user-action', self.do_end_user_action),
341@@ -5585,7 +5687,23 @@
342 with buffer.user_action:
343 buffer.insert_object_at_cursor(obj)
344
345+<<<<<<< TREE
346 @action(_('_Image...'), readonly=False) # T: Menu item
347+=======
348+ def insert_line(self):
349+ '''
350+ This function is called from menu action.
351+ Insert a line at the cursor position.
352+ '''
353+ obj = ObjectManager.get_object('line', None, None)
354+
355+ buffer = self.view.get_buffer()
356+ with buffer.user_action:
357+ buffer.insert_object_at_cursor(obj)
358+ # Add newline after line separator widget.
359+ buffer.insert_at_cursor('\n')
360+
361+>>>>>>> MERGE-SOURCE
362 def insert_image(self, file=None, type=None, interactive=True, force=False):
363 '''Menu action to insert an image, shows the L{InsertImageDialog}
364