Merge lp:~plprgt/zim/lines into lp:~jaap.karssenberg/zim/pyzim
- lines
- Merge into 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 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jaap Karssenberg | Pending | ||
Review via email: mp+276927@code.launchpad.net |
Commit message
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 |