def insert_abbreviation(self, text, title):
     # escape HTML
     text = utility.escape_html_chars(text)
     title = utility.escape_html_chars(title)
     # unicode
     assert isinstance(text, unicode)
     assert isinstance(title, unicode)
     # create new tag
     div_id = "".join(random.choice(string.ascii_letters) for _ in xrange(20))
     self.editor_instance.web.eval("""\
             var abbr = document.createElement('abbr');
             var text = document.createTextNode('%s');
             abbr.appendChild(text);
             abbr.setAttribute('title', '%s');
             abbr.id = '%s';
             var marker = '@#!';
             var toBeInserted = marker + abbr.outerHTML + marker;
             document.execCommand('insertHTML', false, toBeInserted);
             var elem = document.getElementById('%s');
             var leftString = elem.previousSibling.nodeValue;
             var rightString = elem.nextSibling.nodeValue;
             elem.previousSibling.nodeValue =
                     leftString.substring(0, (leftString.length - marker.length));
             elem.nextSibling.nodeValue =
                     rightString.substring(marker.length);
             elem.removeAttribute('id');
     """ % (text, title, div_id, div_id))
Esempio n. 2
0
 def insert_abbreviation(self, text, title):
     # escape HTML
     text = utility.escape_html_chars(text)
     title = utility.escape_html_chars(title)
     # unicode
     # assert isinstance(text, unicode)
     # assert isinstance(title, unicode)
     # create new tag
     div_id = "".join(
         random.choice(string.ascii_letters) for _ in xrange(20))
     self.editor_instance.web.eval("""\
             var abbr = document.createElement('abbr');
             var text = document.createTextNode('%s');
             abbr.appendChild(text);
             abbr.setAttribute('title', '%s');
             abbr.id = '%s';
             var marker = '@#!';
             var toBeInserted = marker + abbr.outerHTML + marker;
             document.execCommand('insertHTML', false, toBeInserted);
             var elem = document.getElementById('%s');
             var leftString = elem.previousSibling.nodeValue;
             var rightString = elem.nextSibling.nodeValue;
             elem.previousSibling.nodeValue =
                     leftString.substring(0, (leftString.length - marker.length));
             elem.nextSibling.nodeValue =
                     rightString.substring(marker.length);
             elem.removeAttribute('id');
     """ % (text, title, div_id, div_id))
Esempio n. 3
0
    def start(self):
        self.backup_html = self.html

        # definition lists have some quirks
        has_def_list = False
        if "<dl>" in self.html:
            has_def_list = True
            self.create_correct_md_for_def_list()
            self.html = self.note.fields[self.current_field]

        # first, we reverse engineer the Markdown from the rendered card
        clean_md = utility.strip_html_from_markdown(self.html)

        if has_def_list:
            clean_md = utility.remove_leading_whitespace_from_dd_element(
                clean_md)
        clean_md = utility.remove_whitespace_before_abbreviation_definition(
            clean_md)
        clean_md_escaped = utility.escape_html_chars(clean_md)

        if not clean_md:
            return

        # HTML --> Markdown
        if self.has_data and self.isconverted == "True":
            # check if the stored data and the current text differ from each other
            compare_md = self.convert_markdown_to_html(self.md)
            # handle quirks
            compare_md = utility.put_colons_in_html_def_list(compare_md)
            compare_md = utility.strip_html_from_markdown(compare_md)
            if has_def_list:
                compare_md = utility.remove_leading_whitespace_from_dd_element(
                    compare_md)
            compare_md = utility.remove_whitespace_before_abbreviation_definition(
                compare_md)

            # escape HTML if we haven't done so already
            if not any(x in compare_md
                       for x in ("&amp;", "&quot;", "&apos;", "&gt;", "&lt;")):
                compare_md = utility.escape_html_chars(compare_md)
            if utility.is_same_markdown(clean_md_escaped,
                                        compare_md) or self.p.get(
                                            const.MARKDOWN_ALWAYS_REVERT):
                self.revert_to_stored_markdown()
            else:
                self.handle_conflict()

        # Markdown --> HTML
        else:
            new_html = self.convert_markdown_to_html(clean_md)
            # needed for proper display of images
            if "<img" in new_html:
                new_html = utility.unescape_html(new_html)
            html_with_data = utility.insert_md_data(self.note_id_field, "True",
                                                    clean_md_escaped, new_html)
            self.insert_into_field(html_with_data, self.current_field)

            # resolve quirks
            self.align_elements()
    def setupUI(self):
        self.widget = QtGui.QDialog(self.parentWindow)
        # self.widget.resize(500, 300)
        self.widget.setWindowTitle("Add a definition list")

        self.dt_part = QtGui.QLineEdit(self.widget)
        self.dt_part.setPlaceholderText("definition term")
        dl_part_label = QtGui.QLabel("Definition term:")

        self.dd_part = QtGui.QTextEdit(self.widget)
        self.dd_part.setAcceptRichText(False)
        if self.selection:
            self.dd_part.setText(self.selection)
        dd_part_label = QtGui.QLabel("Definition description:")

        addButton = QtGui.QPushButton("&Add more", self.widget)
        addButton.clicked.connect(self.addMore)

        buttonBox = QtGui.QDialogButtonBox(self.widget)
        buttonBox.addButton(addButton, QtGui.QDialogButtonBox.ActionRole)
        buttonBox.addButton(QtGui.QDialogButtonBox.Ok)
        buttonBox.addButton(QtGui.QDialogButtonBox.Cancel)

        buttonBox.accepted.connect(self.widget.accept)
        buttonBox.rejected.connect(self.widget.reject)

        vbox = QtGui.QVBoxLayout(self.widget)
        vbox.addWidget(dl_part_label)
        vbox.addWidget(self.dt_part)
        vbox.addWidget(dd_part_label)
        vbox.addWidget(self.dd_part)
        vbox.addWidget(buttonBox)

        self.widget.setLayout(vbox)

        if self.widget.exec_() == QtGui.QDialog.Accepted:
            # we won't allow any empty terms
            if not self.dt_part.text() == "":
                self.data.append(
                    (self.dt_part.text(), self.dd_part.toPlainText()))

            # if OK button pressed, but empty self.data list
            if not self.data:
                return

            # create all the terms and descriptions
            result = "<dl>"
            for key, value in self.data:
                key = utility.escape_html_chars(key)
                value = utility.escape_html_chars(value)
                result = result + "<dt><b>" + key + "</b></dt><dd>" + \
                    value + "</dd>"

            # we need the break <br /> at the end to "get out" of the <dl>
            result = result + "</dl><br />"

            self.editor_instance.web.eval(
                "document.execCommand('insertHTML', false, %s);" %
                json.dumps(result))
    def setupUI(self):
        self.widget = QtGui.QDialog(self.parentWindow)
        # self.widget.resize(500, 300)
        self.widget.setWindowTitle("Add a definition list")

        self.dt_part = QtGui.QLineEdit(self.widget)
        self.dt_part.setPlaceholderText("definition term")
        dl_part_label = QtGui.QLabel("Definition term:")

        self.dd_part = QtGui.QTextEdit(self.widget)
        self.dd_part.setAcceptRichText(False)
        if self.selection:
            self.dd_part.setText(self.selection)
        dd_part_label = QtGui.QLabel("Definition description:")

        addButton = QtGui.QPushButton("&Add more", self.widget)
        addButton.clicked.connect(self.addMore)

        buttonBox = QtGui.QDialogButtonBox(self.widget)
        buttonBox.addButton(addButton, QtGui.QDialogButtonBox.ActionRole)
        buttonBox.addButton(QtGui.QDialogButtonBox.Ok)
        buttonBox.addButton(QtGui.QDialogButtonBox.Cancel)

        buttonBox.accepted.connect(self.widget.accept)
        buttonBox.rejected.connect(self.widget.reject)

        vbox = QtGui.QVBoxLayout(self.widget)
        vbox.addWidget(dl_part_label)
        vbox.addWidget(self.dt_part)
        vbox.addWidget(dd_part_label)
        vbox.addWidget(self.dd_part)
        vbox.addWidget(buttonBox)

        self.widget.setLayout(vbox)

        if self.widget.exec_() == QtGui.QDialog.Accepted:
            # we won't allow any empty terms
            if not self.dt_part.text() == "":
                self.data.append((self.dt_part.text(), self.dd_part.toPlainText()))

            # if OK button pressed, but empty self.data list
            if not self.data:
                return

            # create all the terms and descriptions
            result = "<dl>"
            for key, value in self.data:
                key = utility.escape_html_chars(key)
                value = utility.escape_html_chars(value)
                result = result + "<dt><b>" + key + "</b></dt><dd>" + \
                    value + "</dd>"

            # we need the break <br /> at the end to "get out" of the <dl>
            result = result + "</dl><br />"

            self.editor_instance.web.eval("document.execCommand('insertHTML', false, %s);"
                % json.dumps(result))
Esempio n. 6
0
 def apply_markdown(self):
     self.cancel_html = self.html
     has_def_list = False
     if "<dl>" in self.html:
         has_def_list = True
         self.create_correct_md_for_def_list()
         self.html = self.note.fields[self.current_field]
     clean_md = utility.convert_html_to_markdown(self.html)
     if has_def_list:
         clean_md = utility.remove_leading_whitespace_from_dd_element(
             clean_md)
     clean_md = utility.remove_whitespace_before_abbreviation_definition(
         clean_md)
     clean_md_escaped = utility.escape_html_chars(clean_md)
     if not clean_md:
         return
     # check for changed Markdown between the stored data and the current text
     if self.has_data and self.isconverted == "True":
         compare_md = utility.convert_markdown_to_html(self.md)
         compare_md = utility.put_colons_in_html_def_list(compare_md)
         compare_md = utility.convert_html_to_markdown(compare_md)
         if has_def_list:
             compare_md = utility.remove_leading_whitespace_from_dd_element(
                 compare_md)
         compare_md = utility.remove_whitespace_before_abbreviation_definition(
             compare_md)
         if not any(x in compare_md
                    for x in ("&amp;", "&quot;", "&apos;", "&gt;", "&lt;")):
             compare_md_escaped = utility.escape_html_chars(compare_md)
             compare_md = compare_md_escaped
         if (utility.is_same_markdown(clean_md_escaped, compare_md)
                 or self.p.get(const.MARKDOWN_ALWAYS_REVERT)):
             self.revert_to_stored_markdown()
         else:
             self.handle_conflict()
     else:
         # make abbreviations behave correctly
         new_html = utility.convert_markdown_to_html(clean_md)
         # needed for proper display of images
         if "<img" in new_html:
             new_html = utility.unescape_html(new_html)
         html_with_data = utility.make_data_ready_to_insert(
             self.current_note_id_and_field, "True", clean_md_escaped,
             new_html)
         self.insert_markup_in_field(html_with_data,
                                     self.editor_instance.currentField)
         self.align_elements()
         const.MARKDOWN_PREFS["disable_buttons"] = True
         self.warn_about_changes(self.editor_instance, self.current_field,
                                 const.MARKDOWN_BG_COLOR)
Esempio n. 7
0
 def apply_markdown(self):
     self.cancel_html = self.html
     has_def_list = False
     if "<dl>" in self.html:
         has_def_list = True
         self.create_correct_md_for_def_list()
         self.html = self.note.fields[self.current_field]
     clean_md = utility.convert_html_to_markdown(self.html)
     if has_def_list:
         clean_md = utility.remove_leading_whitespace_from_dd_element(clean_md)
     clean_md = utility.remove_whitespace_before_abbreviation_definition(
             clean_md)
     clean_md_escaped = utility.escape_html_chars(clean_md)
     if not clean_md:
         return
     # check for changed Markdown between the stored data and the current text
     if (self.has_data and self.isconverted == "True"):
         compare_md = utility.convert_markdown_to_html(self.md)
         compare_md = utility.put_colons_in_html_def_list(compare_md)
         compare_md = utility.convert_html_to_markdown(compare_md)
         if has_def_list:
             compare_md = utility.remove_leading_whitespace_from_dd_element(compare_md)
         compare_md = utility.remove_whitespace_before_abbreviation_definition(
                 compare_md)
         if not any(x in compare_md for x in("&amp;", "&quot;", "&apos;",
                                             "&gt;", "&lt;")):
             compare_md_escaped = utility.escape_html_chars(compare_md)
             compare_md = compare_md_escaped
         if (utility.is_same_markdown(clean_md_escaped, compare_md) or
                preferences.PREFS.get(const.MARKDOWN_ALWAYS_REVERT)):
             self.revert_to_stored_markdown()
         else:
             self.handle_conflict()
     else:
         # make abbreviations behave correctly
         new_html = utility.convert_markdown_to_html(clean_md)
         # needed for proper display of images
         if "<img" in new_html:
             new_html = utility.unescape_html(new_html)
         html_with_data = utility.make_data_ready_to_insert(
                 self.current_note_id_and_field, "True",
                 clean_md_escaped, new_html)
         self.insert_markup_in_field(
                 html_with_data, self.editor_instance.currentField)
         self.align_elements()
         const.MARKDOWN_PREFS["disable_buttons"] = True
         self.warn_about_changes(self.editor_instance,
                                 self.current_field,
                                 const.MARKDOWN_BG_COLOR)
    def create_anchor(url, text):
        """
        Create a hyperlink string, where `url` is the hyperlink reference
        and `text` the content of the tag.
        """
        assert isinstance(url, unicode), "Input `url` is not Unicode"
        assert isinstance(text, unicode), "Input `text` is not Unicode"

        text = utility.escape_html_chars(text)

        return u"<a href=\"{0}\">{1}</a>".format(url, text)
Esempio n. 9
0
 def overwrite_stored_data(self):
     """
     Create new Markdown from the current HTML.
     """
     clean_md = utility.strip_html_from_markdown(self.html, keep_empty_lines=True)
     clean_md = utility.remove_whitespace_before_abbreviation_definition(clean_md)
     if "<dl" in self.html:
         clean_md = utility.remove_leading_whitespace_from_dd_element(clean_md, add_newline=True)
     if re.search(const.IS_LINK_OR_IMG_REGEX, clean_md):
         clean_md = utility.escape_html_chars(clean_md)
     new_html = utility.convert_clean_md_to_html(clean_md, put_breaks=True)
     self.insert_into_field(new_html, self.current_field)
     self.remove_warn_msg(self.editor, self.current_field)
    def create_anchor(self, url, text):
        """
        Create a hyperlink string, where `url` is the hyperlink reference
        and `text` the content of the tag.
        """
        assert isinstance(url, unicode), "Input `url` is not Unicode"
        assert isinstance(text, unicode), "Input `text` is not Unicode"

        # uncomment to check for and force `http` prefix
        # pattern = re.compile(r"(?i)https?://")
        # match = re.match(pattern, url)
        # if not match:
        #     url = u"http://" + url

        text = utility.escape_html_chars(text)

        return u"<a href=\"{0}\">{1}</a>".format(url, text)
    def create_anchor(self, url, text):
        """
        Create a hyperlink string, where `url` is the hyperlink reference
        and `text` the content of the tag.
        """
        assert isinstance(url, unicode), "Input `url` is not Unicode"
        assert isinstance(text, unicode), "Input `text` is not Unicode"

        # uncomment to check for and force `http` prefix
        # pattern = re.compile(r"(?i)https?://")
        # match = re.match(pattern, url)
        # if not match:
        #     url = u"http://" + url

        text = utility.escape_html_chars(text)

        return u"<a href=\"{0}\">{1}</a>".format(url, text)
Esempio n. 12
0
 def overwrite_stored_data(self):
     """
     Create new Markdown from the current HTML.
     """
     clean_md = utility.convert_html_to_markdown(self.html,
                                                 keep_empty_lines=True)
     clean_md = utility.remove_whitespace_before_abbreviation_definition(
         clean_md)
     if "<dl" in self.html:
         clean_md = utility.remove_leading_whitespace_from_dd_element(
             clean_md, add_newline=True)
     if re.search(const.IS_LINK_OR_IMG_REGEX, clean_md):
         clean_md = utility.escape_html_chars(clean_md)
     new_html = utility.convert_clean_md_to_html(clean_md, put_breaks=True)
     self.insert_markup_in_field(new_html, self.current_field)
     const.MARKDOWN_PREFS["disable_buttons"] = False
     const.MARKDOWN_PREFS["isconverted"] = False
     self.remove_warn_msg(self.editor_instance, self.current_field)
Esempio n. 13
0
 def overwrite_stored_data(self):
     """
     Create new Markdown from the current HTML.
     """
     clean_md = utility.convert_html_to_markdown(
             self.html, keep_empty_lines=True)
     clean_md = utility.remove_whitespace_before_abbreviation_definition(
             clean_md)
     if "<dl" in self.html:
         clean_md = utility.remove_leading_whitespace_from_dd_element(
                 clean_md, add_newline=True)
     if re.search(const.IS_LINK_OR_IMG_REGEX, clean_md):
         clean_md = utility.escape_html_chars(clean_md)
     new_html = utility.convert_clean_md_to_html(clean_md,
                                                 put_breaks=True)
     self.insert_markup_in_field(new_html, self.current_field)
     const.MARKDOWN_PREFS["disable_buttons"] = False
     const.MARKDOWN_PREFS["isconverted"] = False
     self.remove_warn_msg(self.editor_instance, self.current_field)
Esempio n. 14
0
def wrap_in_tags(self, tag, class_name=None):
    """
    Wrap selected text in a tag, optionally giving it a class.
    """
    selection = self.web.selectedText()

    if not selection:
        return

    selection = utility.escape_html_chars(selection)

    tag_string_begin = ("<{0} class='{1}'>".format(tag, class_name) if
                        class_name else "<{0}>".format(tag))
    tag_string_end = "</{0}>".format(tag)

    html = self.note.fields[self.currentField]

    if "<li><br /></li>" in html:
        # an empty list means trouble, because somehow Anki will also make the
        # line in which we want to put a <code> tag a list if we continue
        replacement = tag_string_begin + selection + tag_string_end
        self.web.eval("document.execCommand('insertHTML', false, %s);"
                      % json.dumps(replacement))

        self.web.setFocus()
        self.web.eval("focusField(%d);" % self.currentField)
        self.saveNow()

        html_after = self.note.fields[self.currentField]

        if html_after != html:
            # you're in luck!
            return
        else:
            # nothing happened :( this is another Anki bug :( that has to do
            # with <code> tags following <div> tags
            return

    # Due to a bug in Anki or BeautifulSoup, we cannot use a simple
    # wrap operation like with <a>. So this is a very hackish way of making
    # sure that a <code> tag may precede or follow a <div> and that the tag
    # won't eat the character immediately preceding or following it
    pattern = "@%*!"
    len_p = len(pattern)

    # first, wrap the selection up in a pattern that the user is unlikely
    # to use in its own cards
    self.web.eval("wrap('{0}', '{1}')".format(pattern, pattern[::-1]))

    # focus the field, so that changes are saved
    # this causes the cursor to go to the end of the field
    self.web.setFocus()
    self.web.eval("focusField(%d);" % self.currentField)

    self.saveNow()

    html = self.note.fields[self.currentField]

    begin = html.find(pattern)
    end = html.find(pattern[::-1], begin)

    html = (html[:begin] + tag_string_begin + selection + tag_string_end +
            html[end+len_p:])

    # delete the current HTML and replace it by our new & improved one
    self.note.fields[self.currentField] = html

    # reload the note: this is needed on OS X, because it will otherwise
    # falsely show that the formatting of the element at the start of
    # the HTML has spread across the entire note
    self.loadNote()

    # focus the field, so that changes are saved
    self.web.setFocus()
    self.web.eval("focusField(%d);" % self.currentField)
    self.saveNow()
    self.web.setFocus()
    self.web.eval("focusField(%d);" % self.currentField)
Esempio n. 15
0
def wrap_in_tags(self, tag, class_name=None):
    """
    Wrap selected text in a tag, optionally giving it a class.
    """
    selection = self.web.selectedText()

    if not selection:
        return

    selection = utility.escape_html_chars(selection)

    tag_string_begin = ("<{0} class='{1}'>".format(tag, class_name) if
                        class_name else "<{0}>".format(tag))
    tag_string_end = "</{0}>".format(tag)

    html = self.note.fields[self.currentField]

    if "<li><br /></li>" in html:
        # an empty list means trouble, because somehow Anki will also make the
        # line in which we want to put a <code> tag a list if we continue
        replacement = tag_string_begin + selection + tag_string_end
        self.web.eval("document.execCommand('insertHTML', false, %s);"
                      % json.dumps(replacement))

        self.web.setFocus()
        self.web.eval("focusField(%d);" % self.currentField)
        self.saveNow()

        html_after = self.note.fields[self.currentField]

        if html_after != html:
            # you're in luck!
            return
        else:
            # nothing happened :( this is a quirk that has to do with <code> tags following <div> tags
            return

    # Due to a bug in Anki or BeautifulSoup, we cannot use a simple
    # wrap operation like with <a>. So this is a very hackish way of making
    # sure that a <code> tag may precede or follow a <div> and that the tag
    # won't eat the character immediately preceding or following it
    pattern = "@%*!"
    len_p = len(pattern)

    # first, wrap the selection up in a pattern that the user is unlikely
    # to use in its own cards
    self.web.eval("wrap('{0}', '{1}')".format(pattern, pattern[::-1]))

    # focus the field, so that changes are saved
    # this causes the cursor to go to the end of the field
    self.web.setFocus()
    self.web.eval("focusField(%d);" % self.currentField)

    self.saveNow()

    html = self.note.fields[self.currentField]

    begin = html.find(pattern)
    end = html.find(pattern[::-1], begin)

    html = (html[:begin] + tag_string_begin + selection + tag_string_end +
            html[end+len_p:])

    # delete the current HTML and replace it by our new & improved one
    self.note.fields[self.currentField] = html

    # reload the note: this is needed on OS X, because it will otherwise
    # falsely show that the formatting of the element at the start of
    # the HTML has spread across the entire note
    self.loadNote()

    # focus the field, so that changes are saved
    self.web.setFocus()
    self.web.eval("focusField(%d);" % self.currentField)
    self.saveNow()
    self.web.setFocus()
    self.web.eval("focusField(%d);" % self.currentField)
    def create_table_from_selection(self):
        """
        Create a table out of the selected text.
        """

        # there is no text to make a table from
        if not self.selected_text:
            return False

        # there is a single line of text
        if not self.selected_text.count(u"\n"):
            return False

        # there is no content in table
        if all(c in (u"|", u"\n") for c in self.selected_text):
            return False

        # split on newlines
        first = [x for x in self.selected_text.split(u"\n") if x]

        # split on pipes
        second = list()
        for elem in first[:]:
            new_elem = [x.strip() for x in elem.split(u"|")]
            new_elem = [utility.escape_html_chars(word) for word in new_elem]
            second.append(new_elem)

        # keep track of the max number of cols
        # so as to make all rows of equal length
        max_num_cols = len(max(second, key=len))

        # decide how much horizontal space each column may take
        width = 100 / max_num_cols

        # check for "-|-|-" alignment row
        if all(x.strip(u":") in (u"-", u"") for x in second[1]):
            start = 2
            align_line = second[1]
            len_align_line = len(align_line)
            if len_align_line < max_num_cols:
                align_line += [u"-"] * (max_num_cols - len_align_line)
            alignments = list()
            for elem in second[1]:
                alignments.append(utility.check_alignment(elem))
        else:
            alignments = [u"left"] * max_num_cols
            start = 1

        # create a table
        head_row = u""
        head_html = \
            u"<th align=\"{0}\" style=\"width: {1}%; padding: 5px;" \
            + u"border-bottom: 2px solid #00B3FF\">{2}</th>"
        for elem, alignment in zip(second[0], alignments):
            head_row += (head_html.format(alignment, width, elem))
        extra_cols = u""
        if len(second[0]) < max_num_cols:
            diff = len(second[0]) - max_num_cols
            assert diff < 0, "Difference between len(second[0]) and max_num_cols is positive"
            extra_html = \
                u"<th align=\"{0}\" style=\"width: {1}%; padding: 5px;" \
                + u"border-bottom: 2px solid #00B3FF\"></th>"
            for alignment in alignments[diff:]:
                extra_cols += (extra_html.format(alignment, width))
        head_row += extra_cols

        body_rows = u""
        for row in second[start:]:
            body_rows += u"<tr>"
            body_html = \
                u"<td style=\"text-align: {0}; padding: 5px; border-bottom:" \
                + u"1px solid #B0B0B0\">{1}</td>"
            for elem, alignment in zip(row, alignments):
                body_rows += (body_html.format(alignment, elem))
            # if particular row is not up to par with number of cols
            extra_cols = ""
            if len(row) < max_num_cols:
                diff = len(row) - max_num_cols
                assert diff < 0, "Difference between len(row) and max_num_cols is positive"
                extra_html = \
                    u"<td style=\"text-align: {0}; padding: 5px;" \
                    + u"border-bottom: 1px solid #B0B0B0\"></td>"
                for alignment in alignments[diff:]:
                    extra_cols += (extra_html.format(alignment))
            body_rows += extra_cols + "</tr>"

        html = u"""
        <table style="width: 100%; border-collapse: collapse;">
            <thead>
                <tr>
                    {0}
                </tr>
            </thead>
            <tbody>
                {1}
            </tbody>
        </table>""".format(head_row, body_rows)

        self.editor_instance.web.eval(
                "document.execCommand('insertHTML', false, %s);"
                % json.dumps(html))

        return True
Esempio n. 17
0
    def create_table_from_selection(self):
        """
        Create a table out of the selected text.
        """

        # there is no text to make a table from
        if not self.selected_text:
            return False

        # there is a single line of text
        if not self.selected_text.count(u"\n"):
            return False

        # there is no content in table
        if all(c in (u"|", u"\n") for c in self.selected_text):
            return False

        # split on newlines
        first = [x for x in self.selected_text.split(u"\n") if x]

        # split on pipes
        second = list()
        for elem in first[:]:
            new_elem = [x.strip() for x in elem.split(u"|")]
            new_elem = [utility.escape_html_chars(word) for word in new_elem]
            second.append(new_elem)

        # keep track of the max number of cols
        # so as to make all rows of equal length
        max_num_cols = len(max(second, key=len))

        # decide how much horizontal space each column may take
        width = 100 / max_num_cols

        # check for "-|-|-" alignment row
        if all(x.strip(u":") in (u"-", u"") for x in second[1]):
            start = 2
            align_line = second[1]
            len_align_line = len(align_line)
            if len_align_line < max_num_cols:
                align_line += [u"-"] * (max_num_cols - len_align_line)
            alignments = list()
            for elem in second[1]:
                alignments.append(utility.check_alignment(elem))
        else:
            alignments = [u"left"] * max_num_cols
            start = 1

        # create a table
        head_row = u""
        head_html = \
            u"<th align=\"{0}\" style=\"width: {1}%; padding: 5px;" \
            + u"border-bottom: 2px solid #00B3FF\">{2}</th>"
        for elem, alignment in zip(second[0], alignments):
            head_row += (head_html.format(alignment, width, elem))
        extra_cols = u""
        if len(second[0]) < max_num_cols:
            diff = len(second[0]) - max_num_cols
            assert diff < 0, "Difference between len(second[0]) and max_num_cols is positive"
            extra_html = \
                u"<th align=\"{0}\" style=\"width: {1}%; padding: 5px;" \
                + u"border-bottom: 2px solid #00B3FF\"></th>"
            for alignment in alignments[diff:]:
                extra_cols += (extra_html.format(alignment, width))
        head_row += extra_cols

        body_rows = u""
        for row in second[start:]:
            body_rows += u"<tr>"
            body_html = \
                u"<td style=\"text-align: {0}; padding: 5px; border-bottom:" \
                + u"1px solid #B0B0B0\">{1}</td>"
            for elem, alignment in zip(row, alignments):
                body_rows += (body_html.format(alignment, elem))
            # if particular row is not up to par with number of cols
            extra_cols = ""
            if len(row) < max_num_cols:
                diff = len(row) - max_num_cols
                assert diff < 0, "Difference between len(row) and max_num_cols is positive"
                extra_html = \
                    u"<td style=\"text-align: {0}; padding: 5px;" \
                    + u"border-bottom: 1px solid #B0B0B0\"></td>"
                for alignment in alignments[diff:]:
                    extra_cols += (extra_html.format(alignment))
            body_rows += extra_cols + "</tr>"

        html = u"""
        <table style="width: 100%; border-collapse: collapse;">
            <thead>
                <tr>
                    {0}
                </tr>
            </thead>
            <tbody>
                {1}
            </tbody>
        </table>""".format(head_row, body_rows)

        self.editor_instance.web.eval(
            "document.execCommand('insertHTML', false, %s);" %
            json.dumps(html))

        return True
    def create_custom_heading(self, selected_text=None):
        dialog = QtGui.QDialog(self.parent_window)
        dialog.setWindowTitle("Create custom heading")

        text_label = QtGui.QLabel("Text:", dialog)
        text_line_edit = QtGui.QLineEdit(dialog)
        if selected_text:
            text_line_edit.setText(selected_text)

        text_hbox = QtGui.QHBoxLayout()
        text_hbox.addWidget(text_label)
        text_hbox.addWidget(text_line_edit)

        stylesheet = """
        QGroupBox { border: 1px inset lightgrey;
                            border-radius: 5px;
                            margin-top: 10px;
                            font-weight: bold; }
        QGroupBox::title {  subcontrol-origin: margin;
                            subcontrol-position: top;
                            padding:0 3px 0 3px; }
        """

        groupbox = QtGui.QGroupBox("Choose a size", dialog)
        groupbox.setStyleSheet(stylesheet)

        radio_button1 = QtGui.QRadioButton("Biggest", dialog)
        radio_button1.setChecked(True)
        radio_button2 = QtGui.QRadioButton("Big", dialog)
        radio_button3 = QtGui.QRadioButton("Medium", dialog)
        radio_button4 = QtGui.QRadioButton("Small", dialog)
        radio_button5 = QtGui.QRadioButton("Smaller", dialog)
        radio_button6 = QtGui.QRadioButton("Tiny", dialog)

        radio_button_group = QtGui.QButtonGroup(dialog)
        radio_button_group.addButton(radio_button1)
        radio_button_group.setId(radio_button1, 1)
        radio_button_group.addButton(radio_button2)
        radio_button_group.setId(radio_button2, 2)
        radio_button_group.addButton(radio_button3)
        radio_button_group.setId(radio_button3, 3)
        radio_button_group.addButton(radio_button4)
        radio_button_group.setId(radio_button4, 4)
        radio_button_group.addButton(radio_button5)
        radio_button_group.setId(radio_button5, 5)
        radio_button_group.addButton(radio_button6)
        radio_button_group.setId(radio_button6, 6)

        radio_hbox = QtGui.QHBoxLayout()
        radio_hbox.addWidget(radio_button1)
        radio_hbox.addWidget(radio_button2)
        radio_hbox.addWidget(radio_button3)
        radio_hbox.addWidget(radio_button4)
        radio_hbox.addWidget(radio_button5)
        radio_hbox.addWidget(radio_button6)

        groupbox.setLayout(radio_hbox)

        button_box = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok |
                                            QtGui.QDialogButtonBox.Cancel,
                                            QtCore.Qt.Horizontal, dialog)

        button_box.accepted.connect(dialog.accept)
        button_box.rejected.connect(dialog.reject)

        vbox = QtGui.QVBoxLayout()
        vbox.addLayout(text_hbox)
        vbox.addStretch(1)
        vbox.addWidget(groupbox)
        vbox.addWidget(button_box)

        vbox.setSizeConstraint(QtGui.QLayout.SetFixedSize)

        dialog.setLayout(vbox)

        if dialog.exec_() == QtGui.QDialog.Accepted:
            text = unicode(text_line_edit.text())
            size_heading = radio_button_group.id(
                    radio_button_group.checkedButton())
            heading_tag = "h" + str(size_heading)
            if text == "":
                return
            else:
                text = utility.escape_html_chars(text)
                start_tag = "<{0}>".format(heading_tag)
                end_tag = "</{0}>".format(heading_tag)
                if selected_text:
                    self.editor_instance.web.eval(
                            "wrap('{0}', '{1}')".format(start_tag, end_tag))
                    self.cleanup_headings()
                else:
                    result = u"{0}{1}{2}".format(start_tag, text, end_tag)
                    self.editor_instance.web.eval(
                            "document.execCommand('insertHTML', false, %s);"
                            % json.dumps(unicode(result)))
Esempio n. 19
0
    def create_custom_heading(self, selected_text=None):
        dialog = QtGui.QDialog(self.parent_window)
        dialog.setWindowTitle("Create custom heading")

        text_label = QtGui.QLabel("Text:", dialog)
        text_line_edit = QtGui.QLineEdit(dialog)
        if selected_text:
            text_line_edit.setText(selected_text)

        text_hbox = QtGui.QHBoxLayout()
        text_hbox.addWidget(text_label)
        text_hbox.addWidget(text_line_edit)

        groupbox = QtGui.QGroupBox("Choose a size", dialog)
        groupbox.setStyleSheet(const.QGROUPBOX_STYLE)

        radio_button1 = QtGui.QRadioButton("Biggest", dialog)
        radio_button1.setChecked(True)
        radio_button2 = QtGui.QRadioButton("Big", dialog)
        radio_button3 = QtGui.QRadioButton("Medium", dialog)
        radio_button4 = QtGui.QRadioButton("Small", dialog)
        radio_button5 = QtGui.QRadioButton("Smaller", dialog)
        radio_button6 = QtGui.QRadioButton("Tiny", dialog)

        radio_button_group = QtGui.QButtonGroup(dialog)
        radio_button_group.addButton(radio_button1)
        radio_button_group.setId(radio_button1, 1)
        radio_button_group.addButton(radio_button2)
        radio_button_group.setId(radio_button2, 2)
        radio_button_group.addButton(radio_button3)
        radio_button_group.setId(radio_button3, 3)
        radio_button_group.addButton(radio_button4)
        radio_button_group.setId(radio_button4, 4)
        radio_button_group.addButton(radio_button5)
        radio_button_group.setId(radio_button5, 5)
        radio_button_group.addButton(radio_button6)
        radio_button_group.setId(radio_button6, 6)

        radio_hbox = QtGui.QHBoxLayout()
        radio_hbox.addWidget(radio_button1)
        radio_hbox.addWidget(radio_button2)
        radio_hbox.addWidget(radio_button3)
        radio_hbox.addWidget(radio_button4)
        radio_hbox.addWidget(radio_button5)
        radio_hbox.addWidget(radio_button6)

        groupbox.setLayout(radio_hbox)

        button_box = QtGui.QDialogButtonBox(
            QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel,
            QtCore.Qt.Horizontal, dialog)

        button_box.accepted.connect(dialog.accept)
        button_box.rejected.connect(dialog.reject)

        vbox = QtGui.QVBoxLayout()
        vbox.addLayout(text_hbox)
        vbox.addStretch(1)
        vbox.addWidget(groupbox)
        vbox.addWidget(button_box)

        vbox.setSizeConstraint(QtGui.QLayout.SetFixedSize)

        dialog.setLayout(vbox)

        if dialog.exec_() == QtGui.QDialog.Accepted:
            text = unicode(text_line_edit.text())
            size_heading = radio_button_group.id(
                radio_button_group.checkedButton())
            heading_tag = "h" + str(size_heading)
            if text == "":
                return
            else:
                text = utility.escape_html_chars(text)
                start_tag = "<{0}>".format(heading_tag)
                end_tag = "</{0}>".format(heading_tag)
                if selected_text:
                    self.editor_instance.web.eval("wrap('{0}', '{1}')".format(
                        start_tag, end_tag))
                    self.cleanup_headings()
                else:
                    result = u"{0}{1}{2}".format(start_tag, text, end_tag)
                    self.editor_instance.web.eval(
                        "document.execCommand('insertHTML', false, %s);" %
                        json.dumps(unicode(result)))
Esempio n. 20
0
    def create_table_from_selection(self):
        """
        Create a table out of the selected text.
        """

        # there is no text to make a table from
        if not self.selected_text:
            return False

        # there is a single line of text
        if not self.selected_text.count(u"\n"):
            return False

        # there is no content in table
        if all(c in (u"|", u"\n") for c in self.selected_text):
            return False

        # split on newlines
        first = [x for x in self.selected_text.split(u"\n") if x]

        # split on pipes
        second = list()
        for elem in first[:]:
            new_elem = [x.strip() for x in elem.split(u"|")]
            new_elem = [utility.escape_html_chars(word) for word in new_elem]
            second.append(new_elem)

        # keep track of the max number of cols
        # so as to make all rows of equal length
        max_num_cols = len(max(second, key=len))

        # decide how much horizontal space each column may take
        width = 100 / max_num_cols

        # check for "-|-|-" alignment row
        if all(x.strip(u":") in (u"-", u"") for x in second[1]):
            start = 2
            align_line = second[1]
            len_align_line = len(align_line)
            if len_align_line < max_num_cols:
                align_line += [u"-"] * (max_num_cols - len_align_line)
            alignments = list()
            for elem in second[1]:
                alignments.append(utility.check_alignment(elem))
        else:
            alignments = [u"left"] * max_num_cols
            start = 1

        # create a table
        head_row = u""
        head_html = u"<th {0}>{1}</th>"
        for elem, alignment in zip(second[0], alignments):
            head_row += head_html.format(
                self.HEAD_STYLING.format(alignment, width), elem)
        extra_cols = u""
        if len(second[0]) < max_num_cols:
            diff = len(second[0]) - max_num_cols
            assert diff < 0, \
                "Difference between len(second[0]) and max_num_cols is positive"
            for alignment in alignments[diff:]:
                extra_cols += head_html.format(
                    self.HEAD_STYLING.format(alignment, width), u"")
        head_row += extra_cols

        body_rows = u""
        for row in second[start:]:
            body_rows += u"<tr>"
            body_html = u"<td {0}>{1}</td>"
            for elem, alignment in zip(row, alignments):
                body_rows += body_html.format(
                    self.BODY_STYLING.format(alignment), elem)
            # if particular row is not up to par with number of cols
            extra_cols = ""
            if len(row) < max_num_cols:
                diff = len(row) - max_num_cols
                assert diff < 0, \
                    "Difference between len(row) and max_num_cols is positive"
                # use the correct alignment for the last few rows
                for alignment in alignments[diff:]:
                    extra_cols += body_html.format(
                        self.BODY_STYLING.format(alignment), u"")
            body_rows += extra_cols + u"</tr>"

        html = u"""
        <table {0}>
            <thead>
                <tr>
                    {1}
                </tr>
            </thead>
            <tbody>
                {2}
            </tbody>
        </table>""".format(self.TABLE_STYLING, head_row, body_rows)

        self.editor_instance.web.eval(
            "document.execCommand('insertHTML', false, %s);" %
            json.dumps(html))

        return True
Esempio n. 21
0
    def create_table_from_selection(self):
        """
        Create a table out of the selected text.
        """

        # there is no text to make a table from
        if not self.selected_text:
            return False

        # there is a single line of text
        if not self.selected_text.count(u"\n"):
            return False

        # there is no content in table
        if all(c in (u"|", u"\n") for c in self.selected_text):
            return False

        # split on newlines
        first = [x for x in self.selected_text.split(u"\n") if x]

        # split on pipes
        second = list()
        for elem in first[:]:
            new_elem = [x.strip() for x in elem.split(u"|")]
            new_elem = [utility.escape_html_chars(word) for word in new_elem]
            second.append(new_elem)

        # keep track of the max number of cols
        # so as to make all rows of equal length
        max_num_cols = len(max(second, key=len))

        # decide how much horizontal space each column may take
        width = 100 / max_num_cols

        # check for "-|-|-" alignment row
        if all(x.strip(u":") in (u"-", u"") for x in second[1]):
            start = 2
            align_line = second[1]
            len_align_line = len(align_line)
            if len_align_line < max_num_cols:
                align_line += [u"-"] * (max_num_cols - len_align_line)
            alignments = list()
            for elem in second[1]:
                alignments.append(utility.check_alignment(elem))
        else:
            alignments = [u"left"] * max_num_cols
            start = 1

        # create a table
        head_row = u""
        head_html = u"<th {0}>{1}</th>"
        for elem, alignment in zip(second[0], alignments):
            head_row += head_html.format(
                    self.HEAD_STYLING.format(alignment, width), elem)
        extra_cols = u""
        if len(second[0]) < max_num_cols:
            diff = len(second[0]) - max_num_cols
            assert diff < 0, \
                "Difference between len(second[0]) and max_num_cols is positive"
            for alignment in alignments[diff:]:
                extra_cols += head_html.format(
                        self.HEAD_STYLING.format(alignment, width), u"")
        head_row += extra_cols

        body_rows = u""
        for row in second[start:]:
            body_rows += u"<tr>"
            body_html = u"<td {0}>{1}</td>"
            for elem, alignment in zip(row, alignments):
                body_rows += body_html.format(
                        self.BODY_STYLING.format(alignment), elem)
            # if particular row is not up to par with number of cols
            extra_cols = ""
            if len(row) < max_num_cols:
                diff = len(row) - max_num_cols
                assert diff < 0, \
                    "Difference between len(row) and max_num_cols is positive"
                # use the correct alignment for the last few rows
                for alignment in alignments[diff:]:
                    extra_cols += body_html.format(
                            self.BODY_STYLING.format(alignment), u"")
            body_rows += extra_cols + u"</tr>"

        html = u"""
        <table {0}>
            <thead>
                <tr>
                    {1}
                </tr>
            </thead>
            <tbody>
                {2}
            </tbody>
        </table>""".format(self.TABLE_STYLING, head_row, body_rows)

        self.editor_instance.web.eval(
                "document.execCommand('insertHTML', false, %s);"
                % json.dumps(html))

        return True