Source

codeaide / contrib / htmledit.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# http://qt.gitorious.org/qt-labs/graphics-dojo/blobs/master/htmleditor/htmleditor.cpp
# http://www.w3.org/TR/html5/editing.html#execCommand
from PyQt4.QtCore import SIGNAL, QString
from PyQt4.QtGui import (
    QApplication, QVBoxLayout, QWidget, QFont, QLabel, QColor)
from PyQt4.QtWebKit import QWebView, QWebPage


js_helpers = """
function getSelectionStart(){
    var node = document.getSelection().anchorNode;
    var startNode = (node.nodeName == "#text" ? node.parentNode : node);
    return startNode;
}
"""

class Editor(QWidget):


    def __init__(self, parent):
        QWidget.__init__(self)
        self.vblayout = QVBoxLayout(self)
        self.view = QWebView(self)
        self.layout().addWidget(self.view)
        self.sbar = QLabel(self)
        self.layout().addWidget(self.sbar)
        self.load("/usr/share/doc/ubuntu-artwork/html/home/firefox-index.html")


    def set_html(self, html):
        self.view.setContent(html, "text/html")
        self.page = self.view.page()
        self.page.setContentEditable(True)
        self.page.setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.connect(self.page, SIGNAL("linkClicked(QUrl)"), self.on_link_clicked)
        self.frame = self.page.mainFrame()
        self.frame.evaluateJavaScript(js_helpers)

        self.connect(self.page, SIGNAL("selectionChanged()"), self.on_selection_changed)
        self.connect(self.page, SIGNAL("contentsChanged()"), self.on_contents_changed)


    def convert_hashmap(self, d):
        r = {}
        for name, value in d.items():
            if isinstance(value, QString):
                value = unicode(value)
            elif isinstance(value, dict):
                value = self.convert_hashmap(value)
            r[unicode(name)] = value
        return r


    def on_selection_changed(self):
        r = self.frame.evaluateJavaScript("getSelectionStart()")
        d = self.convert_hashmap(r.toPyObject())
        print d



    def on_contents_changed(self):
        pass


    def load(self, filename):
        data = open(filename).read()
        self.set_html(data)
        


    def on_link_clicked(self, url):
        pass


    def exec_command(self, cmd, arg=None):
        if arg is None:
            arg = "null"
        else:
            arg = repr(arg)
        js = "document.execCommand(%r, false, %s)" % (
            cmd, arg
            )
        self.frame.evaluateJavaScript(js)


    


    def query_command(self, cmd):
        result = self.frame.evaluateJavaScript(js)
        return unicode(result.toString())


    def query_state(self, cmd):
        result = self.query_command(cmd)
        return result.lower() == "true"



    def insert_html(self, html):
        self.exec_command("insertHTML", html)


    def insert_image(self, html):
        self.exec_command("insertImage", html)


    def create_link(self, link):
        self.exec_command("createLink", link)


    def format_block(self, paragraph_tag):
        self.exec_command(paragraph_tag)


    def align_left(self):
        self.exec_command("justifyLeft")


    def align_right(self):
        self.exec_command("justifyRight")


    def align_center(self):
        self.exec_command("justifyCenter")


    def align_justify(self):
        self.exec_command("justifyFull")


    def bold(self):
        self.exec_command("bold")


    def italic(self):
        self.exec_command("italic")


    def underline(self):
        self.exec_command("underline")


    def strike_through(self):
        self.exec_command("strikeThrough")


    def is_strike_through(self):
        return self.query_state("strikeThrough")


    def is_ordered_list(self):
        return self.query_state("insertOrderedList")


    def is_unordered_list(self):
        return self.query_state("insertUnorderedList")


    def indent(self):
        self.exec_command("indent")


    def dedent(self):
        self.exec_command("outdent")


    def insert_ordered_list(self):
        self.exec_command("insertOrderedList")


    def insert_unordered_list(self):
        self.exec_command("insertUnorderedList")


    def set_font_name(self, font):
        if isinstance(font, QFont):
            font = unicode(font.family())
        self.exec_command("fontName", font)


    def set_font_size(self, size):
        size_list = ["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"]
        if isinstance(size, basestring):
            size = size_list.index(size)
        self.exec_command("fontSize", size)


    def set_font_color(self, color):
        if not isinstance(color, QColor):
            if instance(color, tuple):
                color = QColor(*color)
            else:
                color = QColor(color)
        self.exec_command("foreColor", unicode(color.name()))


    def set_background_color(self, color):
        if not isinstance(color, QColor):
            if instance(color, tuple):
                color = QColor(*color)
            else:
                color = QColor(color)
        self.exec_command("hiliteColor", unicode(color.name()))



def main():
    import sys
    app = QApplication(sys.argv)
    edit = Editor(None)
    edit.resize(640, 480)
    edit.show()
    app.exec_()

if __name__ == "__main__":
    main()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.