/usr/share/cherrytree/modules/machines.py is in cherrytree 0.37.6-1.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | # -*- coding: UTF-8 -*-
#
# machines.py
#
# Copyright 2009-2016 Giuseppe Penone <giuspen@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY 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 with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
import gtk, xml.dom.minidom, re, base64, copy, StringIO
import cons, config, support, exports
def get_blob_buffer_from_pixbuf(pixbuf):
"""Pixbuf To BLOB Buffer"""
io = StringIO.StringIO()
pixbuf.save_to_callback(io.write, "png")
blob_buffer = buffer(io.getvalue())
return blob_buffer
def get_pixbuf_from_png_blob_buffer(blob_buffer):
"""Encoded Buffer To Pixbuf"""
pixbuf_loader = gtk.gdk.pixbuf_loader_new_with_mime_type("image/png")
try:
pixbuf_loader.write(blob_buffer)
pixbuf_loader.close()
pixbuf = pixbuf_loader.get_pixbuf()
except: pixbuf = None
return pixbuf
def get_encoded_buffer_from_pixbuf(pixbuf):
"""Pixbuf To Encoded Buffer"""
io = StringIO.StringIO()
pixbuf.save_to_callback(io.write, "png")
encoded_buffer = base64.b64encode(io.getvalue())
return encoded_buffer
def get_pixbuf_from_encoded_buffer(encoded_buffer):
"""Encoded Buffer To Pixbuf"""
pixbuf_loader = gtk.gdk.pixbuf_loader_new_with_mime_type("image/png")
try:
pixbuf_loader.write(base64.b64decode(encoded_buffer))
pixbuf_loader.close()
pixbuf = pixbuf_loader.get_pixbuf()
except: pixbuf = None
return pixbuf
def get_pixbuf_from_png_encoded_string(png_encoded_string):
"""PNG Encoded String To Pixbuf"""
fd = open(cons.IMG_PATH, "wb")
fd.write(base64.b64decode(png_encoded_string))
fd.close()
pixbuf = gtk.gdk.pixbuf_new_from_file(cons.IMG_PATH)
return pixbuf
class XMLHandler:
"""The Handler of the procedures involving XML"""
def __init__(self, dad):
"""Machine boot"""
self.dad = dad
def dom_to_buffer(self, textbuffer, tagged_text):
"""Given a TextBuffer and a string of rich text, fills the buffer properly"""
textbuffer.delete(*textbuffer.get_bounds())
dom = xml.dom.minidom.parseString(tagged_text)
dom_iter = dom.firstChild
if dom_iter.nodeName != "node": return False
child_dom_iter = dom_iter.firstChild
# loop for text
while child_dom_iter!= None:
if child_dom_iter.nodeName == "rich_text": self.rich_text_deserialize(textbuffer, child_dom_iter)
child_dom_iter = child_dom_iter.nextSibling
textbuffer.set_modified(False)
return True
def reset_nodes_names(self):
"""Reset Nodes Names"""
self.dad.nodes_names_dict = {}
bookmarks_menu = self.dad.ui.get_widget("/MenuBar/BookmarksMenu").get_submenu()
for menu_item in self.dad.bookmarks_menu_items:
bookmarks_menu.remove(menu_item)
self.dad.bookmarks_menu_items = []
def dom_to_treestore(self, ctd, discard_ids, tree_father=None):
"""Parse an XML Cherry Tree Document file and build the Tree"""
dom = xml.dom.minidom.parseString(ctd)
cherrytree = dom.firstChild
if cherrytree.nodeName != cons.APP_NAME: return False
else:
dom_iter = cherrytree.firstChild
node_sequence = self.dad.nodes_sequences_get_max_siblings(tree_father)
while dom_iter!= None:
if dom_iter.nodeName == "node":
node_sequence += 1
self.append_tree_node(dom_iter, tree_father, discard_ids, node_sequence)
elif dom_iter.nodeName == "bookmarks":
self.dad.bookmarks = dom_iter.attributes['list'].value.split(",")
for node_id_str in self.dad.bookmarks:
tree_iter = self.dad.get_tree_iter_from_node_id(int(node_id_str))
if tree_iter:
self.dad.update_node_pre_icon(tree_iter, stock_id="pin")
dom_iter = dom_iter.nextSibling
return True
def append_tree_node(self, dom_iter, tree_father, discard_ids, node_sequence):
"""Given the dom_iter node, adds it to the tree"""
if not discard_ids and dom_iter.hasAttribute('unique_id'):
unique_id = long(dom_iter.attributes['unique_id'].value)
else: unique_id = self.dad.node_id_get()
node_tags = dom_iter.attributes['tags'].value if dom_iter.hasAttribute('tags') else ""
if node_tags: self.dad.tags_add_from_node(node_tags)
readonly = (dom_iter.attributes['readonly'].value == "True") if dom_iter.hasAttribute('readonly') else False
custom_icon_id = int(dom_iter.attributes['custom_icon_id'].value) if dom_iter.hasAttribute('custom_icon_id') else 0
is_bold = (dom_iter.attributes['is_bold'].value == "True") if dom_iter.hasAttribute('is_bold') else False
foreground = dom_iter.attributes['foreground'].value if dom_iter.hasAttribute('foreground') else ""
if not foreground: foreground = None
syntax_highlighting = dom_iter.attributes['prog_lang'].value
if syntax_highlighting not in [cons.RICH_TEXT_ID, cons.PLAIN_TEXT_ID]\
and syntax_highlighting not in self.dad.available_languages:
syntax_highlighting = syntax_highlighting.lower().replace("C++", "cpp")
if syntax_highlighting not in self.dad.available_languages:
syntax_highlighting = cons.RICH_TEXT_ID
node_depth = 0 if not tree_father else self.dad.treestore.iter_depth(tree_father)+1
cherry = self.dad.get_node_icon(node_depth, syntax_highlighting, custom_icon_id)
curr_buffer = self.dad.buffer_create(syntax_highlighting)
if syntax_highlighting != cons.RICH_TEXT_ID: curr_buffer.begin_not_undoable_action()
# loop into rich text, write into the buffer
child_dom_iter = dom_iter.firstChild
while child_dom_iter != None:
if child_dom_iter.nodeName == "rich_text":
self.rich_text_deserialize(curr_buffer, child_dom_iter)
elif child_dom_iter.nodeName == "encoded_png": self.image_deserialize(curr_buffer, child_dom_iter, 2)
elif child_dom_iter.nodeName == "table": self.table_deserialize(curr_buffer, child_dom_iter)
elif child_dom_iter.nodeName == "codebox": self.codebox_deserialize(curr_buffer, child_dom_iter)
elif child_dom_iter.nodeName == "encoded_image": self.image_deserialize(curr_buffer, child_dom_iter, 1)
elif child_dom_iter.nodeName == "node": break
child_dom_iter = child_dom_iter.nextSibling
if syntax_highlighting != cons.RICH_TEXT_ID: curr_buffer.end_not_undoable_action()
curr_buffer.set_modified(False)
#print unique_id
# insert the node containing the buffer into the tree
tree_iter = self.dad.treestore.append(tree_father, [cherry,
dom_iter.attributes['name'].value,
curr_buffer,
unique_id,
syntax_highlighting,
node_sequence,
node_tags,
readonly,
None,
custom_icon_id,
support.get_pango_weight(is_bold),
foreground])
self.dad.nodes_names_dict[unique_id] = self.dad.treestore[tree_iter][1]
if discard_ids:
# we are importing nodes
self.dad.ctdb_handler.pending_new_db_node(unique_id)
# loop for child nodes
child_sequence = 0
while child_dom_iter!= None:
if child_dom_iter.nodeName == "node":
child_sequence += 1
self.append_tree_node(child_dom_iter, tree_iter, discard_ids, child_sequence)
elif child_dom_iter.nodeName == 'rich_text':
support.dialog_error("Rich text instead of child node??!!", self.dad.window)
break
child_dom_iter = child_dom_iter.nextSibling
def codebox_deserialize(self, curr_buffer, dom_node):
"""From the XML codebox text to the SourceBuffer"""
char_offset = int(dom_node.attributes["char_offset"].value)
justification = dom_node.attributes[cons.TAG_JUSTIFICATION].value if dom_node.hasAttribute(cons.TAG_JUSTIFICATION) else cons.TAG_PROP_LEFT
codebox_dict = {
'frame_width': int(dom_node.attributes['frame_width'].value),
'frame_height': int(dom_node.attributes['frame_height'].value),
'width_in_pixels': dom_node.hasAttribute("width_in_pixels") and dom_node.attributes['width_in_pixels'].value == "True",
'syntax_highlighting': dom_node.attributes['syntax_highlighting'].value,
'highlight_brackets': dom_node.hasAttribute("highlight_brackets") and dom_node.attributes['highlight_brackets'].value == "True",
'show_line_numbers': dom_node.hasAttribute("show_line_numbers") and dom_node.attributes['show_line_numbers'].value == "True",
'fill_text': dom_node.firstChild.data if dom_node.firstChild else ""
}
self.dad.codeboxes_handler.codebox_insert(curr_buffer.get_iter_at_offset(char_offset),
codebox_dict,
codebox_justification=justification,
text_buffer=curr_buffer)
def table_deserialize(self, curr_buffer, dom_node):
"""From the XML table text to the SourceBuffer"""
char_offset = int(dom_node.attributes["char_offset"].value)
if dom_node.hasAttribute(cons.TAG_JUSTIFICATION): justification = dom_node.attributes[cons.TAG_JUSTIFICATION].value
else: justification = cons.TAG_PROP_LEFT
table_dict = {
'matrix': [],
'col_min': int(dom_node.attributes['col_min'].value),
'col_max': int(dom_node.attributes["col_max"].value)
}
child_dom_iter = dom_node.firstChild
while child_dom_iter != None:
if child_dom_iter.nodeName == "row":
table_dict['matrix'].append([])
nephew_dom_iter = child_dom_iter.firstChild
while nephew_dom_iter != None:
if nephew_dom_iter.nodeName == "cell":
if nephew_dom_iter.firstChild != None:
table_dict['matrix'][-1].append(nephew_dom_iter.firstChild.data)
else: table_dict['matrix'][-1].append("")
nephew_dom_iter = nephew_dom_iter.nextSibling
child_dom_iter = child_dom_iter.nextSibling
self.dad.tables_handler.table_insert(curr_buffer.get_iter_at_offset(char_offset),
table_dict,
table_justification=justification,
text_buffer=curr_buffer)
def image_deserialize(self, curr_buffer, dom_node, version):
"""From the XML embedded image text to the SourceBuffer"""
char_offset = int(dom_node.attributes["char_offset"].value)
if dom_node.hasAttribute(cons.TAG_JUSTIFICATION): justification = dom_node.attributes[cons.TAG_JUSTIFICATION].value
else: justification = cons.TAG_PROP_LEFT
if dom_node.hasAttribute("anchor"):
pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(cons.ANCHOR_CHAR, self.dad.anchor_size, self.dad.anchor_size)
pixbuf.anchor = dom_node.attributes["anchor"].value
elif dom_node.hasAttribute("filename"):
pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(cons.FILE_CHAR, self.dad.embfile_size, self.dad.embfile_size)
pixbuf.filename = dom_node.attributes["filename"].value
pixbuf.embfile = base64.b64decode(dom_node.firstChild.data)
pixbuf.time = float(dom_node.attributes["time"].value) if dom_node.hasAttribute("time") else 0
else:
if version == 2: pixbuf = get_pixbuf_from_encoded_buffer(dom_node.firstChild.data)
else: pixbuf = get_pixbuf_from_png_encoded_string(dom_node.firstChild.data)
if pixbuf:
pixbuf.link = dom_node.attributes["link"].value if dom_node.hasAttribute("link") else ""
self.dad.image_insert(curr_buffer.get_iter_at_offset(char_offset),
pixbuf,
image_justification=justification,
text_buffer=curr_buffer)
def rich_text_deserialize(self, curr_buffer, dom_node):
"""From the XML rich text to the SourceBuffer"""
if dom_node.firstChild: text = dom_node.firstChild.data
else: text = ""
tag_names = []
for tag_property in cons.TAG_PROPERTIES:
if dom_node.hasAttribute(tag_property):
property_value = dom_node.attributes[tag_property].value
if property_value: tag_names.append(self.dad.apply_tag_exist_or_create(tag_property, property_value))
tags_num = len(tag_names)
if tags_num == 0: curr_buffer.insert(curr_buffer.get_end_iter(), text)
else: curr_buffer.insert_with_tags_by_name(curr_buffer.get_end_iter(), text, *tag_names)
def treestore_node_to_dom(self, node_iter):
"""Given a treestore iter returns the CherryTree rich text"""
if "dom" in dir(self): del self.dom
self.dom = xml.dom.minidom.Document()
self.append_dom_node(node_iter, self.dom, to_disk=False, skip_children=True)
return self.dom.toxml()
def treestore_sel_node_only_to_dom(self, tree_iter, sel_range=None):
"""Parse the Given Node and Subnodes and Generate an XML Cherry Tree Document"""
if "dom" in dir(self): del self.dom
self.dom = xml.dom.minidom.Document()
cherrytree = self.dom.createElement(cons.APP_NAME)
self.dom.appendChild(cherrytree)
# given node and subnodes parsing
self.append_dom_node(tree_iter, cherrytree, to_disk=True, skip_children=True, sel_range=sel_range)
return self.dom.toxml()
def treestore_sel_node_and_subnodes_to_dom(self, tree_iter):
"""Parse the Given Node and Subnodes and Generate an XML Cherry Tree Document"""
if "dom" in dir(self): del self.dom
self.dom = xml.dom.minidom.Document()
cherrytree = self.dom.createElement(cons.APP_NAME)
self.dom.appendChild(cherrytree)
# given node and subnodes parsing
self.append_dom_node(tree_iter, cherrytree, to_disk=True)
return self.dom.toxml()
def treestore_to_dom(self):
"""Parse the Tree and Generate an XML Cherry Tree Document"""
if "dom" in dir(self): del self.dom
self.dom = xml.dom.minidom.Document()
cherrytree = self.dom.createElement(cons.APP_NAME)
self.dom.appendChild(cherrytree)
# full tree parsing
tree_iter = self.dad.treestore.get_iter_first()
while tree_iter != None:
self.append_dom_node(tree_iter, cherrytree, to_disk=True)
tree_iter = self.dad.treestore.iter_next(tree_iter)
self.append_bookmarks(cherrytree)
return self.dom.toprettyxml()
def append_bookmarks(self, dom_father):
"""Adds the bookmarks data to the DOM"""
if len(self.dad.bookmarks) == 0: return
dom_iter = self.dom.createElement("bookmarks")
dom_iter.setAttribute("list", ",".join(self.dad.bookmarks))
dom_father.appendChild(dom_iter)
def append_dom_node(self, tree_iter, dom_father, to_disk, skip_children=False, sel_range=None):
"""Given the tree_iter node, adds it to the DOM"""
dom_iter = self.dom.createElement("node")
dom_iter.setAttribute("name", self.dad.treestore[tree_iter][1])
dom_iter.setAttribute("unique_id", str(self.dad.treestore[tree_iter][3]))
programming_language = self.dad.treestore[tree_iter][4]
dom_iter.setAttribute("prog_lang", programming_language)
dom_iter.setAttribute("tags", self.dad.treestore[tree_iter][6])
dom_iter.setAttribute("readonly", str(self.dad.treestore[tree_iter][7]))
dom_iter.setAttribute("custom_icon_id", str(self.dad.treestore[tree_iter][9]))
dom_iter.setAttribute("is_bold", str(support.get_pango_is_bold(self.dad.treestore[tree_iter][10])))
foreground = self.dad.treestore[tree_iter][11]
if not foreground: foreground = ""
dom_iter.setAttribute("foreground", foreground)
dom_father.appendChild(dom_iter)
# allocate and init the rich text attributes
self.curr_attributes = {}
for tag_property in cons.TAG_PROPERTIES: self.curr_attributes[tag_property] = ""
curr_buffer = self.dad.get_textbuffer_from_tree_iter(tree_iter)
if not sel_range:
start_iter = curr_buffer.get_start_iter()
end_iter = curr_buffer.get_end_iter()
else:
start_iter = curr_buffer.get_iter_at_offset(sel_range[0])
end_iter = curr_buffer.get_iter_at_offset(sel_range[1])
if programming_language == cons.RICH_TEXT_ID:
# rich text insert
curr_iter = start_iter.copy()
self.rich_text_attributes_update(curr_iter, self.curr_attributes)
tag_found = curr_iter.forward_to_tag_toggle(None)
while tag_found:
if not self.tag_richtext_toggling_on_or_off(curr_iter):
if not curr_iter.forward_char(): tag_found = False
else: tag_found = curr_iter.forward_to_tag_toggle(None)
continue
self.rich_txt_serialize(dom_iter, start_iter, curr_iter, self.curr_attributes)
if curr_iter.compare(end_iter) >= 0: break
else:
self.rich_text_attributes_update(curr_iter, self.curr_attributes)
offset_old = curr_iter.get_offset()
start_iter.set_offset(offset_old)
tag_found = curr_iter.forward_to_tag_toggle(None)
if curr_iter.get_offset() == offset_old: break
else: self.rich_txt_serialize(dom_iter, start_iter, curr_iter, self.curr_attributes)
# in case of writing to disk it's time to serialize the info about the images
if to_disk == True:
pixbuf_table_codebox_vector = self.dad.state_machine.get_embedded_pixbufs_tables_codeboxes(curr_buffer, sel_range=sel_range)
# pixbuf_table_codebox_vector is [ [ "pixbuf"/"table"/"codebox", [offset, pixbuf, alignment] ],... ]
for element in pixbuf_table_codebox_vector:
if sel_range: element[1][0] -= sel_range[0]
if element[0] == "pixbuf": self.pixbuf_element_to_xml(element[1], dom_iter, self.dom)
elif element[0] == "table": self.table_element_to_xml(element[1], dom_iter, self.dom)
elif element[0] == "codebox": self.codebox_element_to_xml(element[1], dom_iter, self.dom)
else:
# plain text insert
self.rich_txt_serialize(dom_iter, start_iter, end_iter, self.curr_attributes)
if not skip_children:
tree_iter = self.dad.treestore.iter_children(tree_iter) # check for children
while tree_iter != None:
self.append_dom_node(tree_iter, dom_iter, to_disk)
tree_iter = self.dad.treestore.iter_next(tree_iter)
def codebox_element_to_xml(self, element, dom_node, dom):
"""From element [char_offset, codebox, justification] to dom node"""
dom_iter = dom.createElement("codebox")
dom_iter.setAttribute("char_offset", str(element[0]))
if element[2] != cons.TAG_PROP_LEFT: dom_iter.setAttribute(cons.TAG_JUSTIFICATION, element[2])
dom_iter.setAttribute("frame_width", str(element[1]['frame_width']))
dom_iter.setAttribute("frame_height", str(element[1]['frame_height']))
dom_iter.setAttribute("width_in_pixels", str(element[1]['width_in_pixels']))
dom_iter.setAttribute("syntax_highlighting", str(element[1]['syntax_highlighting']))
dom_iter.setAttribute("highlight_brackets", str(element[1]['highlight_brackets']))
dom_iter.setAttribute("show_line_numbers", str(element[1]['show_line_numbers']))
dom_node.appendChild(dom_iter)
text_iter = dom.createTextNode(element[1]['fill_text'])
dom_iter.appendChild(text_iter)
def table_element_to_xml(self, element, dom_node, dom):
"""From element [char_offset, table, justification] to dom node"""
dom_iter = dom.createElement("table")
dom_iter.setAttribute("char_offset", str(element[0]))
if element[2] != cons.TAG_PROP_LEFT: dom_iter.setAttribute(cons.TAG_JUSTIFICATION, element[2])
dom_iter.setAttribute("col_min", str(element[1]['col_min']))
dom_iter.setAttribute("col_max", str(element[1]['col_max']))
dom_node.appendChild(dom_iter)
for row in element[1]['matrix']:
dom_row = dom.createElement("row")
dom_iter.appendChild(dom_row)
for cell in row:
dom_cell = dom.createElement("cell")
dom_row.appendChild(dom_cell)
text_iter = dom.createTextNode(cell)
dom_cell.appendChild(text_iter)
def pixbuf_element_to_xml(self, element, dom_node, dom):
"""From element [char_offset, pixbuf, justification] to dom node"""
dom_iter = dom.createElement("encoded_png")
dom_iter.setAttribute("char_offset", str(element[0]))
if element[2] != cons.TAG_PROP_LEFT: dom_iter.setAttribute(cons.TAG_JUSTIFICATION, element[2])
pixbuf_attrs = dir(element[1])
if "anchor" in pixbuf_attrs:
dom_iter.setAttribute("anchor", element[1].anchor)
dom_node.appendChild(dom_iter)
text_iter = dom.createTextNode("anchor")
elif "filename" in pixbuf_attrs:
dom_iter.setAttribute("filename", element[1].filename)
dom_node.appendChild(dom_iter)
text_iter = dom.createTextNode(base64.b64encode(element[1].embfile))
if "time" in dir(element[1]) and element[1].time:
dom_iter.setAttribute("time", str(element[1].time))
else:
if "link" in dir(element[1]) and element[1].link:
dom_iter.setAttribute("link", element[1].link)
dom_node.appendChild(dom_iter)
text_iter = dom.createTextNode(get_encoded_buffer_from_pixbuf(element[1]))
dom_iter.appendChild(text_iter)
def rich_txt_serialize(self, dom_node, start_iter, end_iter, curr_attributes, change_case="n", dom=None):
"""Appends a new SourceBuffer part to the XML rich text"""
if not dom: dom = self.dom
dom_iter = dom.createElement("rich_text")
for tag_property in cons.TAG_PROPERTIES:
if curr_attributes[tag_property] != "":
dom_iter.setAttribute(tag_property, curr_attributes[tag_property])
dom_node.appendChild(dom_iter)
slot_text = start_iter.get_text(end_iter)
if change_case != "n":
if change_case == "l": slot_text = slot_text.lower()
elif change_case == "u": slot_text = slot_text.upper()
elif change_case == "t": slot_text = slot_text.swapcase()
text_iter = dom.createTextNode(slot_text)
dom_iter.appendChild(text_iter)
def tag_richtext_toggling_on_or_off(self, curr_iter):
"""Check for tag rich text toggle on or off"""
toggled_onoff = []
toggled_off = curr_iter.get_toggled_tags(toggled_on=False)
toggled_on = curr_iter.get_toggled_tags(toggled_on=True)
if toggled_off: toggled_onoff.extend(toggled_off)
if toggled_on: toggled_onoff.extend(toggled_on)
for tag in toggled_onoff:
tag_name = tag.get_property("name")
if not tag_name: continue
if tag_name.startswith("weight_") \
or tag_name.startswith("foreground_") \
or tag_name.startswith("background_") \
or tag_name.startswith("style_") \
or tag_name.startswith("underline_") \
or tag_name.startswith("strikethrough_") \
or tag_name.startswith("scale_") \
or tag_name.startswith("justification_") \
or tag_name.startswith("link_") \
or tag_name.startswith("family_"):
return True
return False
def rich_text_attributes_update(self, curr_iter, curr_attributes):
"""Updates the list of Attributes for the Current Slice"""
toggled_off = curr_iter.get_toggled_tags(toggled_on=False)
for tag in toggled_off:
tag_name = tag.get_property("name")
if tag_name and tag_name != cons.GTKSPELLCHECK_TAG_NAME:
if tag_name.startswith("weight_"): curr_attributes[cons.TAG_WEIGHT] = ""
elif tag_name.startswith("foreground_"): curr_attributes[cons.TAG_FOREGROUND] = ""
elif tag_name.startswith("background_"): curr_attributes[cons.TAG_BACKGROUND] = ""
elif tag_name.startswith("style_"): curr_attributes[cons.TAG_STYLE] = ""
elif tag_name.startswith("underline_"): curr_attributes[cons.TAG_UNDERLINE] = ""
elif tag_name.startswith("strikethrough_"): curr_attributes[cons.TAG_STRIKETHROUGH] = ""
elif tag_name.startswith("scale_"): curr_attributes[cons.TAG_SCALE] = ""
elif tag_name.startswith("justification_"): curr_attributes[cons.TAG_JUSTIFICATION] = ""
elif tag_name.startswith("link_"): curr_attributes[cons.TAG_LINK] = ""
elif tag_name.startswith("family_"): curr_attributes[cons.TAG_FAMILY] = ""
else: support.dialog_error("Failure processing the toggling OFF tag %s" % tag_name, self.dad.window)
toggled_on = curr_iter.get_toggled_tags(toggled_on=True)
for tag in toggled_on:
tag_name = tag.get_property("name")
if tag_name and tag_name != cons.GTKSPELLCHECK_TAG_NAME:
if tag_name.startswith("weight_"): curr_attributes[cons.TAG_WEIGHT] = tag_name[7:]
elif tag_name.startswith("foreground_"): curr_attributes[cons.TAG_FOREGROUND] = tag_name[11:]
elif tag_name.startswith("background_"): curr_attributes[cons.TAG_BACKGROUND] = tag_name[11:]
elif tag_name.startswith("scale_"): curr_attributes[cons.TAG_SCALE] = tag_name[6:]
elif tag_name.startswith("justification_"): curr_attributes[cons.TAG_JUSTIFICATION] = tag_name[14:]
elif tag_name.startswith("style_"): curr_attributes[cons.TAG_STYLE] = tag_name[6:]
elif tag_name.startswith("underline_"): curr_attributes[cons.TAG_UNDERLINE] = tag_name[10:]
elif tag_name.startswith("strikethrough_"): curr_attributes[cons.TAG_STRIKETHROUGH] = tag_name[14:]
elif tag_name.startswith("link_"): curr_attributes[cons.TAG_LINK] = tag_name[5:]
elif tag_name.startswith("family_"): curr_attributes[cons.TAG_FAMILY] = tag_name[7:]
else: support.dialog_error("Failure processing the toggling ON tag %s" % tag_name, self.dad.window)
def toc_insert_all(self, text_buffer, top_tree_iter):
"""Insert a TOC at top of text_buffer, including Node and Subnodes starting from top_tree_iter"""
config.get_tree_expanded_collapsed_string(self.dad)
starting_tree_iter = self.dad.curr_tree_iter.copy()
if top_tree_iter: toc_list_per_node = self.toc_insert_all_iter(top_tree_iter)
else:
top_tree_iter = self.dad.treestore.get_iter_first()
toc_list_per_node = []
while top_tree_iter != None:
toc_list_per_node.extend(self.toc_insert_all_iter(top_tree_iter))
top_tree_iter = self.dad.treestore.iter_next(top_tree_iter)
config.set_tree_expanded_collapsed_string(self.dad)
self.dad.treeview_safe_set_cursor(starting_tree_iter)
self.dad.objects_buffer_refresh()
#print toc_list_per_node
curr_node_id = -1
curr_node_level = 0
if toc_list_per_node:
tag_property = cons.TAG_LINK
curr_offset = 0
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), cons.CHAR_NEWLINE)
curr_offset += 1
for element in toc_list_per_node:
property_value = cons.LINK_TYPE_NODE + cons.CHAR_SPACE + str(element[2])
if curr_node_id != element[2]:
curr_node_id = element[2]
node_tree_iter = self.dad.get_tree_iter_from_node_id(curr_node_id)
curr_node_level = self.dad.treestore.iter_depth(node_tree_iter)
node_name = self.dad.treestore[node_tree_iter][1].replace(cons.CHAR_NEWLINE, cons.CHAR_SPACE).replace(cons.CHAR_CR, "")
tag_names = [self.dad.apply_tag_exist_or_create(tag_property, property_value)]
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), 2*curr_node_level*cons.CHAR_SPACE + self.dad.chars_toc[0] + cons.CHAR_SPACE)
curr_offset += 2 + 2*curr_node_level
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), cons.CHAR_NEWLINE)
text_buffer.insert_with_tags_by_name(text_buffer.get_iter_at_offset(curr_offset), node_name, *tag_names)
curr_offset += 1
while text_buffer.get_iter_at_offset(curr_offset).get_char() != cons.CHAR_NEWLINE:
curr_offset += 1
curr_offset += 1
tag_names = [self.dad.apply_tag_exist_or_create(tag_property, property_value + cons.CHAR_SPACE + element[0])]
if not element[0]: continue
if element[0][:2] == cons.TAG_PROP_H1:
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), (2+2*curr_node_level)*cons.CHAR_SPACE + self.dad.chars_toc[1] + cons.CHAR_SPACE)
curr_offset += 4 + 2*curr_node_level
elif element[0][:2] == cons.TAG_PROP_H2:
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), (4+2*curr_node_level)*cons.CHAR_SPACE + self.dad.chars_toc[2] + cons.CHAR_SPACE)
curr_offset += 6 + 2*curr_node_level
else:
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), (6+2*curr_node_level)*cons.CHAR_SPACE + self.dad.chars_toc[3] + cons.CHAR_SPACE)
curr_offset += 8 + 2*curr_node_level
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), cons.CHAR_NEWLINE)
text_buffer.insert_with_tags_by_name(text_buffer.get_iter_at_offset(curr_offset), element[1], *tag_names)
curr_offset += 1
while text_buffer.get_iter_at_offset(curr_offset).get_char() != cons.CHAR_NEWLINE:
curr_offset += 1
curr_offset += 1
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), cons.CHAR_NEWLINE)
return toc_list_per_node
def toc_insert_all_iter(self, top_tree_iter):
"""Iterate on nodes for toc_insert_all"""
self.dad.treeview_safe_set_cursor(top_tree_iter)
node_id = self.dad.treestore[top_tree_iter][3]
text_buffer = self.dad.get_textbuffer_from_tree_iter(top_tree_iter)
toc_list_per_node = []
toc_list_this_one = self.toc_insert_one(text_buffer, node_id, just_get_toc_list=True)
toc_list_per_node.extend(toc_list_this_one or [["", "", node_id]])
child_tree_iter = self.dad.treestore.iter_children(top_tree_iter)
while child_tree_iter != None:
toc_list_per_node.extend(self.toc_insert_all_iter(child_tree_iter))
child_tree_iter = self.dad.treestore.iter_next(child_tree_iter)
return toc_list_per_node
def tag_h_in_given_iter(self, given_iter):
"""Check for tag header in given_iter"""
for tag in given_iter.get_tags():
tag_name = tag.get_property("name")
if tag_name.startswith("scale_") and tag_name[6:] in [cons.TAG_PROP_H1, cons.TAG_PROP_H2, cons.TAG_PROP_H3]:
return True
return False
def safe_forward_to_h_toggle(self, curr_iter):
"""Forward to the Toggle of a scale tag"""
if self.curr_attributes[cons.TAG_SCALE] in [cons.TAG_PROP_H1, cons.TAG_PROP_H2, cons.TAG_PROP_H3]:
# ON to OFF
if not self.tag_h_in_given_iter(curr_iter): return True
while curr_iter.forward_char():
if not self.tag_h_in_given_iter(curr_iter): return True
return True # at least at the buffer end, the tag will go off
else:
# OFF to ON
if self.tag_h_in_given_iter(curr_iter): return True
while curr_iter.forward_char():
if self.tag_h_in_given_iter(curr_iter): return True
return False
def toc_insert_one(self, text_buffer, node_id, just_get_toc_list=False):
"""Given the text_buffer, inserts the Table Of Contents"""
self.curr_attributes = {}
self.toc_counters = {cons.TAG_PROP_H1:0, cons.TAG_PROP_H2:0, cons.TAG_PROP_H3:0}
self.toc_list = [] # 0: anchor name; 1: text in h1, h2 or h3; 2:node id
for tag_property in cons.TAG_PROPERTIES: self.curr_attributes[tag_property] = ""
start_iter = text_buffer.get_start_iter()
end_iter = text_buffer.get_end_iter()
curr_iter = start_iter.copy()
self.rich_text_attributes_update(curr_iter, self.curr_attributes)
tag_found = self.safe_forward_to_h_toggle(curr_iter)
while tag_found:
offsets = self.toc_insert_parser(text_buffer, start_iter, curr_iter, node_id)
if offsets:
start_iter = text_buffer.get_iter_at_offset(offsets[0])
curr_iter = text_buffer.get_iter_at_offset(offsets[1])
end_iter = text_buffer.get_end_iter()
if curr_iter.compare(end_iter) == 0: break
else:
self.rich_text_attributes_update(curr_iter, self.curr_attributes)
offset_old = curr_iter.get_offset()
start_iter.set_offset(offset_old)
tag_found = self.safe_forward_to_h_toggle(curr_iter)
if curr_iter.get_offset() == offset_old: break
else: self.toc_insert_parser(text_buffer, start_iter, curr_iter, node_id)
if self.toc_list and not just_get_toc_list:
tag_property = cons.TAG_LINK
property_value = cons.LINK_TYPE_NODE + cons.CHAR_SPACE + str(node_id)
curr_offset = 0
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), cons.CHAR_NEWLINE)
curr_offset += 1
for element in self.toc_list:
tag_names = []
tag_names.append(self.dad.apply_tag_exist_or_create(tag_property, property_value + cons.CHAR_SPACE + element[0]))
if element[0][:2] == cons.TAG_PROP_H1:
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), self.dad.chars_toc[1] + cons.CHAR_SPACE)
curr_offset += 2
elif element[0][:2] == cons.TAG_PROP_H2:
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), 2*cons.CHAR_SPACE + self.dad.chars_toc[2] + cons.CHAR_SPACE)
curr_offset += 4
else:
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), 4*cons.CHAR_SPACE + self.dad.chars_toc[3] + cons.CHAR_SPACE)
curr_offset += 6
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), cons.CHAR_NEWLINE)
text_buffer.insert_with_tags_by_name(text_buffer.get_iter_at_offset(curr_offset), element[1], *tag_names)
curr_offset += 1
while text_buffer.get_iter_at_offset(curr_offset).get_char() != cons.CHAR_NEWLINE:
curr_offset += 1
curr_offset += 1
text_buffer.insert(text_buffer.get_iter_at_offset(curr_offset), cons.CHAR_NEWLINE)
return self.toc_list
def toc_insert_parser(self, text_buffer, start_iter, end_iter, node_id):
"""Parses a Tagged String for the TOC insert"""
if self.curr_attributes[cons.TAG_SCALE] not in [cons.TAG_PROP_H1, cons.TAG_PROP_H2, cons.TAG_PROP_H3]: return None
start_offset = start_iter.get_offset()
end_offset = end_iter.get_offset()
if self.curr_attributes[cons.TAG_SCALE] == cons.TAG_PROP_H1:
self.toc_counters[cons.TAG_PROP_H1] += 1
self.toc_list.append(["h1-%d" % self.toc_counters[cons.TAG_PROP_H1], text_buffer.get_text(start_iter, end_iter), node_id])
elif self.curr_attributes[cons.TAG_SCALE] == cons.TAG_PROP_H2:
self.toc_counters[cons.TAG_PROP_H2] += 1
self.toc_list.append(["h2-%d" % self.toc_counters[cons.TAG_PROP_H2], text_buffer.get_text(start_iter, end_iter), node_id])
else:
self.toc_counters[cons.TAG_PROP_H3] += 1
self.toc_list.append(["h3-%d" % self.toc_counters[cons.TAG_PROP_H3], text_buffer.get_text(start_iter, end_iter), node_id])
anchor_start = start_iter.copy()
if anchor_start.backward_char():
anchor = anchor_start.get_child_anchor()
if anchor and "pixbuf" in dir(anchor) and "anchor" in dir(anchor.pixbuf):
text_buffer.delete(anchor_start, start_iter)
start_offset -= 1
end_offset -= 1
start_iter = text_buffer.get_iter_at_offset(start_offset)
pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(cons.ANCHOR_CHAR, self.dad.anchor_size, self.dad.anchor_size)
pixbuf.anchor = self.toc_list[-1][0]
self.dad.image_insert(start_iter, pixbuf)
self.dad.ctdb_handler.pending_edit_db_node_buff(node_id, force_user_active=True)
return (start_offset+1, end_offset+1)
class StateMachine:
"""The State Machine for the TextBuffer Ctrl+Z / Ctrl+Y Utility"""
def __init__(self, dad):
"""Machine boot"""
self.nodes_vectors = {}
self.nodes_indexes = {}
self.nodes_indicators = {}
self.visited_nodes_list = []
self.visited_nodes_idx = 0
# indicator 0 -> current text in node_vector matches the textbuffer
# indicator 1 -> textbuffer is ahead, but only of non alphanumeric chars
# indicator 2 -> textbuffer is ahead with alphanumeric chars
self.dad = dad
def get_embedded_pixbufs_tables_codeboxes(self, text_buffer, for_print=0, sel_range=None):
"""Retrieve the list of Images Embedded into the Buffer"""
pixbuf_table_codebox_vector = []
if sel_range: curr_iter = text_buffer.get_iter_at_offset(sel_range[0])
else: curr_iter = text_buffer.get_start_iter()
while 1:
anchor = curr_iter.get_child_anchor()
if anchor:
anchor_dir = dir(anchor)
if "pixbuf" in anchor_dir:
if for_print != 1 or not "anchor" in dir(anchor.pixbuf):
pixbuf_table_codebox_vector.append(["pixbuf", [curr_iter.get_offset(),
anchor.pixbuf,
self.get_iter_alignment(curr_iter)] ])
elif "liststore" in anchor_dir:
pixbuf_table_codebox_vector.append(["table", [curr_iter.get_offset(),
self.table_to_dict(anchor),
self.get_iter_alignment(curr_iter)] ])
elif "sourcebuffer" in anchor_dir:
pixbuf_table_codebox_vector.append(["codebox", [curr_iter.get_offset(),
self.codebox_to_dict(anchor, for_print),
self.get_iter_alignment(curr_iter)] ])
if not curr_iter.forward_char(): break
if sel_range and curr_iter.get_offset() > sel_range[1]: break
return pixbuf_table_codebox_vector
def table_to_dict(self, anchor):
"""Given an Anchor, Returns the Embedded Table as a dictionary"""
columns_num = len(anchor.headers)
table_dict = {'matrix':[], 'col_min': anchor.table_col_min, 'col_max': anchor.table_col_max}
tree_iter = anchor.liststore.get_iter_first()
while tree_iter != None:
row = []
for column in range(columns_num): row.append(anchor.liststore[tree_iter][column])
table_dict['matrix'].append(row)
tree_iter = anchor.liststore.iter_next(tree_iter)
table_dict['matrix'].append(copy.deepcopy(anchor.headers))
return table_dict
def codebox_to_dict(self, anchor, for_print):
"""Given an Anchor, Returns the Embedded Codebox as a dictionary"""
codebox_dict = {
'frame_width': anchor.frame_width,
'frame_height': anchor.frame_height,
'width_in_pixels': anchor.width_in_pixels,
'syntax_highlighting': anchor.syntax_highlighting,
'highlight_brackets': anchor.highlight_brackets,
'show_line_numbers': anchor.show_line_numbers,
'fill_text': ""
}
if for_print == 1:
pango_handler = exports.Export2Pango(self)
codebox_dict['fill_text'] = pango_handler.pango_get_from_code_buffer(anchor.sourcebuffer)
elif for_print == 2:
codebox_dict['fill_text'] = self.dad.html_handler.html_get_from_code_buffer(anchor.sourcebuffer)
else: codebox_dict['fill_text'] = anchor.sourcebuffer.get_text(*anchor.sourcebuffer.get_bounds())
return codebox_dict
def get_iter_alignment(self, iter_text):
"""Get the Alignment Value of the given Iter"""
align_center = self.dad.apply_tag_exist_or_create(cons.TAG_JUSTIFICATION, cons.TAG_PROP_CENTER)
align_fill = self.dad.apply_tag_exist_or_create(cons.TAG_JUSTIFICATION, cons.TAG_PROP_FILL)
align_right = self.dad.apply_tag_exist_or_create(cons.TAG_JUSTIFICATION, cons.TAG_PROP_RIGHT)
if iter_text.has_tag(self.dad.tag_table.lookup(align_center)):
return cons.TAG_PROP_CENTER
if iter_text.has_tag(self.dad.tag_table.lookup(align_fill)):
return cons.TAG_PROP_FILL
if iter_text.has_tag(self.dad.tag_table.lookup(align_right)):
return cons.TAG_PROP_RIGHT
return cons.TAG_PROP_LEFT
def load_embedded_image_element(self, text_buffer, element):
"""Load an Image from the Embedded Vector into the Buffer"""
iter_insert = text_buffer.get_iter_at_offset(element[0])
self.dad.image_insert(iter_insert, element[1], element[2], text_buffer=text_buffer)
def load_embedded_table_element(self, text_buffer, element):
"""Load a Table from the Embedded Vector into the Buffer"""
iter_insert = text_buffer.get_iter_at_offset(element[0])
self.dad.tables_handler.table_insert(iter_insert, element[1], element[2], text_buffer=text_buffer)
def load_embedded_codebox_element(self, text_buffer, element):
"""Load a CodeBox from the Embedded Vector into the Buffer"""
iter_insert = text_buffer.get_iter_at_offset(element[0])
codebox_dict = {
'frame_width': element[1]['frame_width'],
'frame_height': element[1]['frame_height'],
'width_in_pixels': element[1]['width_in_pixels'],
'syntax_highlighting': element[1]['syntax_highlighting'],
'highlight_brackets': element[1]['highlight_brackets'],
'show_line_numbers': element[1]['show_line_numbers'],
'fill_text': element[1]['fill_text']
}
self.dad.codeboxes_handler.codebox_insert(iter_insert,
codebox_dict,
codebox_justification=element[2],
text_buffer=text_buffer)
def apply_object_justification(self, iter_start, justification, text_buffer):
"""Apply the Proper Justification to an Image"""
if justification == None: return
iter_end = iter_start.copy()
iter_end.forward_char()
self.dad.apply_tag(cons.TAG_JUSTIFICATION,
justification,
iter_sel_start=iter_start,
iter_sel_end=iter_end,
text_buffer=text_buffer)
def reset(self):
"""State Machine Reset"""
self.nodes_vectors = {}
self.nodes_indexes = {}
self.nodes_indicators = {}
self.visited_nodes_list = []
self.visited_nodes_idx = 0
def requested_visited_previous(self):
"""Requested the Previous Visited Node"""
if self.visited_nodes_idx != None and self.visited_nodes_idx > 0:
self.visited_nodes_idx -= 1
return self.visited_nodes_list[self.visited_nodes_idx]
else:
#print "self.visited_nodes_idx", self.visited_nodes_idx
return None
def requested_visited_next(self):
"""Requested the Next Visited Node"""
if self.visited_nodes_idx != None and self.visited_nodes_idx < len(self.visited_nodes_list) - 1:
self.visited_nodes_idx += 1
return self.visited_nodes_list[self.visited_nodes_idx]
else:
#print "self.visited_nodes_idx", self.visited_nodes_idx
#print "last_index", len(self.visited_nodes_list) - 1
return None
def node_selected_changed(self, node_id):
"""When a New Node is Selected"""
if self.dad.user_active and not self.dad.go_bk_fw_click:
last_index = len(self.visited_nodes_list) - 1
if self.visited_nodes_idx != last_index: del self.visited_nodes_list[self.visited_nodes_idx+1:last_index+1]
if node_id in self.visited_nodes_list:
self.visited_nodes_list.remove(node_id)
self.visited_nodes_list.append(node_id)
self.visited_nodes_idx = len(self.visited_nodes_list) - 1
if node_id not in self.nodes_vectors:
self.nodes_vectors[node_id] = []
xml_content = self.dad.xml_handler.treestore_node_to_dom(self.dad.curr_tree_iter)
pixbuf_table_codebox_vector = self.get_embedded_pixbufs_tables_codeboxes(self.dad.curr_buffer)
self.nodes_vectors[node_id].append([xml_content, pixbuf_table_codebox_vector, 0])
self.nodes_indexes[node_id] = 0 # first state
self.nodes_indicators[node_id] = 0 # the current buffer state is saved
def text_variation(self, node_id, varied_text):
"""Insertion or Removal of text in the given node_id"""
if cons.CHAR_NEWLINE in varied_text:
self.update_state()
return
alphanum = re.search("\w", varied_text, re.UNICODE) # we search for an alphanumeric character
if self.nodes_indicators[node_id] < 2:
if alphanum != None: self.nodes_indicators[node_id] = 2 # alphanumeric transition
else: self.nodes_indicators[node_id] = 1 # non alphanumeric transition
elif alphanum == None: # self.nodes_indicators[node_id] == 2 and non alphanumeric transition
self.update_state()
def requested_state_previous(self, node_id):
"""A Previous State, if Existing, is Requested"""
if self.curr_index_is_last_index(node_id):
self.update_state()
if self.nodes_indexes[node_id] > 0:
self.nodes_indexes[node_id] -= 1
return self.nodes_vectors[node_id][self.nodes_indexes[node_id]]
def requested_state_current(self, node_id):
"""The current state is requested"""
return self.nodes_vectors[node_id][self.nodes_indexes[node_id]]
def requested_state_subsequent(self, node_id):
"""A Subsequent State, if Existing, is Requested"""
if self.nodes_indexes[node_id] < (len(self.nodes_vectors[node_id])-1):
self.nodes_indexes[node_id] += 1
return self.nodes_vectors[node_id][self.nodes_indexes[node_id]]
def delete_states(self, node_id):
"""Delete the states for the given node_id"""
del self.nodes_indexes[node_id]
del self.nodes_vectors[node_id]
del self.nodes_indicators[node_id]
if node_id in self.visited_nodes_list:
self.visited_nodes_list.remove(node_id)
self.visited_nodes_idx = len(self.visited_nodes_list)-1
def curr_index_is_last_index(self, node_id):
"""Are we in the last state?"""
curr_index = self.nodes_indexes[node_id]
last_index = len(self.nodes_vectors[node_id]) - 1
return curr_index == last_index
def update_state(self):
"""Update the state for the given node_id"""
if self.dad.syntax_highlighting != cons.RICH_TEXT_ID:
return
node_id = self.dad.treestore[self.dad.curr_tree_iter][3]
if not self.curr_index_is_last_index(node_id):
del self.nodes_vectors[node_id][self.nodes_indexes[node_id]+1:]
xml_content = self.dad.xml_handler.treestore_node_to_dom(self.dad.curr_tree_iter)
pixbuf_table_codebox_vector = self.get_embedded_pixbufs_tables_codeboxes(self.dad.curr_buffer)
cursor_pos = self.dad.curr_buffer.get_property(cons.STR_CURSOR_POSITION)
new_state = [xml_content, pixbuf_table_codebox_vector, cursor_pos]
if len(self.nodes_vectors[node_id]) > 0:
if new_state == self.nodes_vectors[node_id][-1]:
#print "update_state not needed"
return
self.nodes_vectors[node_id].append(new_state)
num_saved_states = len(self.nodes_vectors[node_id])
while num_saved_states > self.dad.limit_undoable_steps:
self.nodes_vectors[node_id].pop(0)
num_saved_states -= 1
self.nodes_indexes[node_id] = num_saved_states - 1
self.nodes_indicators[node_id] = 0 # the current buffer state is saved
def update_curr_state_cursor_pos(self, node_id):
"""If the buffer is still not modified update cursor pos"""
if not node_id in self.nodes_indexes: return
curr_index = self.nodes_indexes[node_id]
cursor_pos = self.dad.curr_buffer.get_property(cons.STR_CURSOR_POSITION)
self.nodes_vectors[node_id][curr_index][2] = cursor_pos
#print "SM UPD cursor_pos", cursor_pos
|