Module pgwkit

This encapsulates the webkit import and failure thereof

Expand source code
#!/usr/bin/env python

''' This encapsulates the webkit import and failure thereof '''

import os, sys, getopt, signal, random, time, warnings
import inspect

#realinc = os.path.realpath(os.path.dirname(__file__) + os.sep + "../pycommon")
#sys.path.append(realinc)

from pgutils import  *
from pggui import  *
from pgsimp import  *
from pgtextview import  *

import gi
gi.require_version("Gtk", "3.0")

from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Pango

WebKit2 = None

class dummywebview(Gtk.VBox):

    def __int__(self):
        super().__init__(self)
        #self.pack_start(Gtk.Label(label="No WebView"), 1, 1, 0)
    def set_editable(self, flag):
        self.pack_start(Gtk.Label(label="No WebView Available"), 1, 1, 0)
        pass
    def load_html(self, ff, kk = None):
        pass
    def connect(self, aa, bb):
        pass

class dummywebkit():
    WebView = dummywebview

try:
    gi.require_version("WebKit2", '4.1')
    from gi.repository import WebKit2
    #present = 1
except:
    try:
        #print("Trying V 4.0:", sys.exc_info())
        gi.require_version("WebKit2", '4.0')
        from gi.repository import WebKit2
    except:
        try:
            #print("Trying with jno qualifier")
            #gi.require_version("WebKit2", '4.0')
            from gi.repository import WebKit2
        except:
            # Giving up, patch fake one
            print("Cannot import:", sys.exc_info())
            print("WebWiew is not available.")
            try:
                WebKit2 = dummywebkit
            except:
                print("Fake kit Exc:", sys.exc_info())
            #print("Fake kit:", WebKit2)
            #raise

ui_def = """
        <ui>
            <toolbar name="toolbar_format">
                <toolitem action="cut" />
                <toolitem action="copy" />
                <toolitem action="paste" />
                <separator />
                <toolitem action="removeformat" />
                <toolitem action="bold" />
                <toolitem action="italic" />
                <toolitem action="underline" />
                <toolitem action="strikethrough" />
                <separator />
                <toolitem action="justifyleft" />
                <toolitem action="justifyright" />
                <toolitem action="justifycenter" />
                <toolitem action="justifyfull" />
                <separator />
                <toolitem action="undo" />
                <toolitem action="redo" />
                <separator />
                <toolitem action="font" />
                <toolitem action="fontsize" />
                <toolitem action="color" />
                <toolitem action="backgroundcolor" />
                <separator />
                <toolitem action="insertimage" />
                <toolitem action="insertlink" />
                <toolitem action="inserttable" />
                <toolitem action="editmarker" />
                <toolitem action="H1" />
                <toolitem action="H2" />
                <toolitem action="H3" />
                <toolitem action="H4" />
            </toolbar>
        </ui>
        """

#unmask_reserved =   Gdk.ModifierType.GDK_MODIFIER_RESERVED_13_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_14_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_15_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_16_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_17_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_18_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_19_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_20_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_21_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_22_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_23_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_24_MASK | \
#                    Gdk.ModifierType.GDK_MODIFIER_RESERVED_25_MASK

# These are not setting the modified flag

navkeys = [   \
                Gdk.KEY_Up,         Gdk.KEY_KP_Up,
                Gdk.KEY_Down,       Gdk.KEY_KP_Down ,
                Gdk.KEY_Left,       Gdk.KEY_KP_Left,
                Gdk.KEY_Right,      Gdk.KEY_KP_Right,
                Gdk.KEY_Page_Up,    Gdk.KEY_KP_Page_Up,
                Gdk.KEY_Page_Down,  Gdk.KEY_KP_Page_Down,
                Gdk.KEY_Home,       Gdk.KEY_KP_Home,
                Gdk.KEY_End,        Gdk.KEY_KP_End,

                # Also the modifier keys themselves
                Gdk.KEY_Alt_L,      Gdk.KEY_Alt_R,
                Gdk.KEY_Control_L,  Gdk.KEY_Control_R,
                Gdk.KEY_Super_L,    Gdk.KEY_Super_R,
                Gdk.KEY_Shift_L,    Gdk.KEY_Shift_R,

          ]

# ------------------------------------------------------------------------

class pgwebw(WebKit2.WebView):

    ''' Define our override of the webkit class '''

    def __init__(self, xlink=None):
        try:
            GObject.GObject.__init__(self)
        except:
            print("Cannot ??? in parent object", sys.exc_info())
            pass
        self.xlink = xlink
        self.set_editable(True)

        #if editable:
        #    self.set_editable(True)

        self.fname = ""
        self.load_html("", "file:///")
        self.ui = self.generate_ui()
        self.connect("key-release-event",  self.keypress)
        self.modified = False

    def  _get_response_data_finish(self, resource, result, user_data=None):
        self.old_html = resource.get_data_finish(result)
        #print((self.old_html))

    def keypress(self, arg, arg2):

        ''' Here we imitate the way the accelerator works '''

        state = arg2.get_state() & Gdk.ModifierType.MODIFIER_MASK
        key = arg2.get_keyval()[1]
        #print("key",  key, "state", state)

        #GDK_MODIFIER_RESERVED_25_MASK

        # Feeding off the accelarator's definitions
        ag = self.ui.get_action_groups()[0]
        acts = ag.list_actions()

        # Scan - Fire
        for aa in acts:
            if aa.accel:
                #print(nnn, aa.accel, aa.accel_parsed)
                if state == aa.accel_parsed[1]:
                    #print("state match")
                    if key == aa.accel_parsed[0]:
                        #print("Fire ", aa.get_name(), aa.get_label())
                        #lab = aa.get_label()
                        aa.activate()
                        break   # Only one accel the other is a mistake

        # See if nav key
        navkey = False
        for aa in navkeys:
            if key == aa:
                #print("Navkey", aa)
                navkey = True
        if not navkey:
            # Exclude Ctrl-s
            if state == Gdk.ModifierType.CONTROL_MASK and key == 115:
                #print("Control s")
                pass
            else:
                #print("set on key", key)
                self.modified =  True

    def do_ready_to_show(self):
        print("do_ready_to_show() was called")
        pass

    def do_load_changed(self, status):

        #print("do_load_changed()", status)
        if status == WebKit2.LoadEvent.FINISHED:
            ''' Create a shadow of content '''

            # This gets it without spaces
            #resource = self.get_main_resource()
            #resource.get_data(None, self._get_response_data_finish, None)

            # Get it by JS
            def completion(html, user_data):
                self.old_html = html
            self.get_html(completion, '')


        if self.get_uri():
            if self.xlink:
                self.xlink.set_status("Loading ... " + self.get_uri()[:64])

        if status == 3: #WebKit2.LoadEvent.WEBKIT_LOAD_FINISHED:
            #print("got WEBKIT_LOAD_FINISHED")
            if self.get_uri():
                if self.xlink:
                    self.xlink.edit.set_text(self.get_uri()[:64])
                    self.xlink.set_status("Finished: " + self.get_uri()[:64])
            self.grab_focus()

    def do_load_failed(self, load_event, failing_uri, error):
        print("do_load_failed() was called", failing_uri)
        if self.xlink:
            self.xlink.set_status("Failed: " + failing_uri[:64])

    def on_header(self, action):
        #print("on_aheader", action.get_name())
        ddd = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
        ccc = None
        while True:
            #target = Gdk.Atom.intern ("text/html", True);
            #ccc = ddd.wait_for_contents(target)
            #if ccc:
            #    break
            target2 = Gdk.Atom.intern ("text/plain", True);
            ccc = ddd.wait_for_contents(target2)
            if ccc:
                break
            break

        if not ccc:
            return

        dddd = ccc.get_data().decode()
        if not dddd:
            return
        #print("dddd", dddd)
        htmlx = "<%s>%s</%s>" % (action.get_name(), dddd, action.get_name())
        self.run_javascript("document.execCommand \
                            ('insertHTML', null, '%s');" % htmlx)
        Gtk.Clipboard.clear(ddd)
        self.modified = True

    def on_action(self, action):
        #print("on_action", action.get_name())
        # Make it caller neutral
        if type(action) == str:
            nnn = action
        else:
            nnn = action.get_name()
        self.run_javascript("document.execCommand('%s', false, false);" % nnn)
        self.modified = True

    def on_paste(self, action = ""):
        print("Paste")
        self.execute_editing_command(WebKit2.EDITING_COMMAND_PASTE)

    def on_new(self, action):
        self.load_html("", "file:///")
        self.modified = False

    def on_fontsize(self, action):
        #print("on_fontsize")
        sizex = sizedialog()
        #print("sizex", sizex)
        if not sizex:
            return

        c = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
        sel = c.wait_for_targets()
        #print("sel", sel)
        target = Gdk.Atom.intern ("text/plain", True);
        ccc = c.wait_for_contents(target)
        if not ccc:
            htmlx = "<span style=\"font-size: %dpx;\">%s</span>" % (int(sizex), "")
            self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
            return

        ddd = ccc.get_data().decode()
        if not ddd:
            return

        #print("ddd", ddd)
        htmlx = "<span style=\"font-size: %dpx;\">%s</span>" % (int(sizex), ddd)
        self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
        Gtk.Clipboard.clear(c)
        self.modified = True

    def on_select_font(self, action):
        dialog = Gtk.FontChooserDialog("Select a font")
        if dialog.run() == Gtk.ResponseType.OK:
            fname = dialog.get_font_desc().get_family()
            fsize = dialog.get_font_desc().get_size() / Pango.SCALE
            ttt = int(1 + round(fsize / 10)) % 9
            print("Setting font", fname, fsize, ttt)
            self.run_javascript("document.execCommand('fontname', null, '%s');" % fname)
            self.run_javascript("document.execCommand('fontsize', null, '%s');" % ttt)
        dialog.destroy()

    def on_select_color(self, action):
        dialog = Gtk.ColorChooserDialog("Select Color")
        if dialog.run() == Gtk.ResponseType.OK:
            (r, g, b, a) = dialog.get_rgba()
            color = "#%0.2x%0.2x%0.2x%0.2x" % (
                int(r * 255),
                int(g * 255),
                int(b * 255),
                int(a * 255))
            self.run_javascript("document.execCommand('forecolor', null, '%s');" % color)
        dialog.destroy()

    def on_select_bgcolor(self, action):
        dialog = Gtk.ColorChooserDialog("Select Background Color")
        if dialog.run() == Gtk.ResponseType.OK:
            (r, g, b, a) = dialog.get_rgba()
            color = "#%0.2x%0.2x%0.2x%0.2x" % (
                int(r * 255),
                int(g * 255),
                int(b * 255),
                int(a * 255))
            self.run_javascript("document.execCommand('backcolor', null, '%s');" % color)
        dialog.destroy()

    def on_edit_marker(self, action):
        print("on_edit_marker", action.get_name())

        c = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
        sel = c.wait_for_targets()
        target = Gdk.Atom.intern ("text/html", True);
        ccc = c.wait_for_contents(target)
        #print("sel", ccc.get_data())
        #ccc.free()
        htmlx = markdialog(ccc.get_data().decode())
        if htmlx:
            print("markdialog result:\n", htmlx)
            self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)

    def on_insert_table(self, action):
        htmlx = "<table align=center border=0 contentEditable=true>" + \
                "<tr><td>TR1 C1 <td>| TR1 C2 <tr><td>TR2 C1<td>| TR2 C1</table><br>"

        #print("table", htmlx)
        self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
        self.modified = True

    def on_insert_link(self, action):
        dialog = Gtk.Dialog("   Enter a URL:   ", None, 0,
        (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK))

        entry = Gtk.Entry()
        dialog.vbox.pack_start(Gtk.Label("  "), False, False, 0)
        hbox = Gtk.HBox()
        hbox.pack_start(Gtk.Label("  "), False, False, 0)
        hbox.pack_start(entry, False, False, 0)
        hbox.pack_start(Gtk.Label("  "), False, False, 0)
        dialog.vbox.pack_start(hbox, False, False, 0)

        dialog.vbox.pack_start(Gtk.Label("  "), False, False, 0)
        dialog.show_all()

        if dialog.run() == Gtk.ResponseType.OK:
            self.run_javascript(
                "document.execCommand('createLink', True, '%s');" % entry.get_text())
        dialog.destroy()
        self.modified = True

    def on_insert_image(self, action):
        dialog = Gtk.FileChooserDialog("Select an image file", None, Gtk.FileChooserAction.OPEN,
        (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))

        if dialog.run() == Gtk.ResponseType.OK:
            fn = dialog.get_filename()
            if os.path.exists(fn):
                self.run_javascript(
                "document.execCommand('insertImage', null, '%s');" % fn)
        dialog.destroy()
        self.modified = True

    def on_open(self, action):
        dialog = Gtk.FileChooserDialog("Select an HTML file", self, Gtk.FileChooserAction.OPEN,
        (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))

        if dialog.run() == Gtk.ResponseType.OK:
            fn = dialog.get_filename()
            if os.path.exists(fn):
                self.fname = fn
                with open(fn) as fd:
                    self.load_html(fd.read(), "file:///")
        dialog.destroy()

    def on_save(self, action):
        def completion(html, user_data):
            open_mode = user_data
            with open(self.fname, open_mode) as fd:
                fd.write(html)

        if self.fname:
            self.get_html(completion, 'w')
        else:
            dialog = Gtk.FileChooserDialog("Select an HTML file", None,
                    Gtk.FileChooserAction.SAVE,
                        (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                            Gtk.STOCK_SAVE, Gtk.ResponseType.OK))

            if dialog.run() == Gtk.ResponseType.OK:
                self.fname = dialog.get_filename()
                print("Saving", self.fname)
                self.get_html(completion, "w+")
            dialog.destroy()

    def get_html(self, completion_function, user_data):

        #print("get_html")
        def javascript_completion(obj, result, user_data):
            #print("javascript_completion", result)
            fin = self.run_javascript_finish(result)
            #print("fin", fin)
            html = fin.get_js_value().to_string()
            #print("len html", len(html), "\n")
            completion_function(html, user_data)
        self.run_javascript("document.documentElement.innerHTML;",
                                   None,
                                   javascript_completion,
                                   user_data)

    def get_lastmod(self, completion_function, user_data):

        print("get_lastmod")
        def javascript_completion(obj, result, user_data):
            print("javascript_completion", result)
            fin = self.run_javascript_finish(result)
            #print("fin", fin)
            html = fin.get_js_value().to_string()
            print("lastmod", html, "\n")
            #completion_function(html, user_data)
        self.run_javascript("document.lastModified",
                                   None,
                                   javascript_completion,
                                   user_data)


    def generate_ui(self):

        ''' define toolbar items and actions here '''

        actions = Gtk.ActionGroup("Actions")
    # ----------------------------------------------------------------
    # Name,     Stock Icon,   Accelerator,  ToolTip,   Action

    # Some already has app accels

        accel_arr = [ \

    #("menuFile",    None, "_File"),
    #("menuEdit",    None, "_Edit"),
    #("menuInsert",  None, "_Insert"),
    #("menuFormat",  None, "_Format"),
    #("new",         Gtk.STOCK_NEW, "_New", None, None, self.on_new),
    #("open",        Gtk.STOCK_OPEN, "_Open", None, None, self.on_open),
    #("save",        Gtk.STOCK_SAVE, "_Save", None, None, self.on_save),

    ("cut",         Gtk.STOCK_CUT, "_Cut", None, None, self.on_action),
    ("copy",        Gtk.STOCK_COPY, "_Copy", None, None, self.on_action),
    ("paste",       Gtk.STOCK_PASTE, "_Paste", None, None, self.on_paste),

    ("undo",        Gtk.STOCK_UNDO, "_Undo", "<Control>z", "Undo Last Edit", self.on_action),
    ("redo",        Gtk.STOCK_REDO, "_Redo", "<Control>y", "Redo Last Undo", self.on_action),

    ("removeformat", Gtk.STOCK_PROPERTIES, "_removeFormat", "<Control>M", "Remove Formatting", self.on_action),
    ("bold",        Gtk.STOCK_BOLD, "_Bold", "", "Bold / UnBold Selection", self.on_action),
    ("italic",      Gtk.STOCK_ITALIC, "_Italic", "", None, self.on_action),
    ("underline",       Gtk.STOCK_UNDERLINE, "_Underline", "", None, self.on_action),
    ("strikethrough", Gtk.STOCK_STRIKETHROUGH, "_Strike", "", None, self.on_action),
    ("font",        Gtk.STOCK_SELECT_FONT, "Select _Font", "", None, self.on_select_font),
    ("fontsize",    None, "Select Font _Size", "<Control>f", "Set Absolute Size (removes color)", self.on_fontsize),
    ("color",       Gtk.STOCK_SELECT_COLOR, "Select _Color", None, None, self.on_select_color),
    ("backgroundcolor", Gtk.STOCK_COLOR_PICKER, "Select Back Color", None, None, self.on_select_bgcolor),

    ("justifyleft",  Gtk.STOCK_JUSTIFY_LEFT, "Justify _Left", None, None, self.on_action),
    ("justifyright", Gtk.STOCK_JUSTIFY_RIGHT, "Justify _Right", None, None, self.on_action),
    ("justifycenter", Gtk.STOCK_JUSTIFY_CENTER, "Justify _Center", None, None, self.on_action),
    ("justifyfull",   Gtk.STOCK_JUSTIFY_FILL, "Justify _Full", None, None, self.on_action),

    # Pad Images by name (may not be present in all styles)
    ("insertimage", "insert-image", "Insert _Image", None, None, self.on_insert_image),
    ("insertlink", "insert-link", "Insert _Link", None, None, self.on_insert_link),
    ("inserttable", "insert-table", "Insert _Table", None, None, self.on_insert_table),
    ("editmarker", "edit-marker", "edit _Marker", None, None, self.on_edit_marker),

    ("H1",   Gtk.STOCK_EXECUTE, "Header 1", None, "Insert Header 1", self.on_header),
    ("H2",   Gtk.STOCK_EXECUTE, "Header 2", None, "Insert Header 2", self.on_header),
    ("H3",   Gtk.STOCK_EXECUTE, "Header 3", None, "Insert Header 3", self.on_header),
    ("H4",   Gtk.STOCK_EXECUTE, "Header 4", None, "Insert Header 4", self.on_header),

    ]

        actions.add_actions(accel_arr)

        #print(dir(actions))
        for aa in accel_arr:
        #    print("acc arr", dir(aa))
        #    break
        #    act = actions.get_action(aa[0])
        #    print("act", act.get_name(), act.get_tooltip())
            pass
        #    try:
        #        act = Gtk.Action.new(aa[0], aa[2], aa[4], aa[1])
        #        actions.add_action_with_accel(act, aa[3])
        #    except:
        #        #print("Exc on", aa)
        #        pass

        actions.get_action("insertimage").set_property("icon-name", "insert-image")
        actions.get_action("insertlink").set_property("icon-name", "insert-link")
        actions.get_action("inserttable").set_property("icon-name", "appointment-new")
        actions.get_action("editmarker").set_property("icon-name", "text-editor")
        actions.get_action("fontsize").set_property("icon-name", "preferences-desktop-font")
        actions.get_action("removeformat").set_property("icon-name", "text-direction")

        ui = Gtk.UIManager()
        ui.insert_action_group(actions)
        ui.add_ui_from_string(ui_def)

        # Fill in defaults
        xxx = ui.get_action_groups()[0].list_actions()
        for aa in xxx:
            nnn = aa.get_name()
            # Find the original, patth missing info
            for bb in accel_arr:
                # Convert tuple
                bbb = list(bb)
                if bb[0] == nnn:
                    # Pad for this round
                    for cc in range(5 - len(bbb)):
                        bbb.append("")

                    #print("lab", bb[2], aa.get_label())
                    #print("found", nnn, bbb[3])

                    setattr(aa, "accel", bbb[3])
                    if bbb[3]:
                        try:
                            nn, ss = Gtk.accelerator_parse(bbb[3])
                            setattr(aa, "accel_parsed", (nn, ss))
                        except:
                            pass

            # Pad it with capitalize name if not there
            if  not aa.get_tooltip():
                aa.set_tooltip(nnn[0].upper() + nnn[1:])

        return ui

# This is kicked in if there is no library  (is it used?)

class pgwebw_fake(Gtk.VBox):

    def __init__(self):
        super(pgwebw_fake, self).__init__();
        pass

    def load_uri(self, url):
        pass

def markdialog(sss):

    spaceneed = 64
    # Wrap tesxt if long
    ssss = ""
    cnt = 0; fff = 0
    for aa in sss:
        if cnt > spaceneed:
            fff = 1
        if fff and aa.isspace():
            cnt = 0; fff = 0
            ssss += "\n"
        ssss += aa
        cnt += 1

    dialog = Gtk.Dialog("   Edit markup   ", None, 0,
    (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK))

    textview = Gtk.TextView()
    textview.set_editable(True)

    textbuffer = textview.get_buffer()
    textbuffer.set_text(ssss)

    scrolledwindow = Gtk.ScrolledWindow()
    scrolledwindow.set_hexpand(True)
    scrolledwindow.set_vexpand(True)
    scrolledwindow.add(textview)
    scrolledwindow.set_size_request(640, 480)

    hhh = "\n          " \
            "In general, any valid html can go here. Keep it simple.\n" \
            "The editor already decorated this sufficiently, "\
              "try to edit existing items in place.\n"

    lll = Gtk.Label(hhh)
    fd = Pango.FontDescription("Sans 9")
    lll.override_font(fd)
    thbox = Gtk.HBox()
    thbox.pack_start(lll, 1, 1, 1)
    dialog.vbox.pack_start(thbox, False, False, 0)
    hbox = Gtk.HBox()
    hbox.pack_start(Gtk.Label(" "), False, False, 0)
    hbox.pack_start(scrolledwindow, 1, 1, 0)
    hbox.pack_start(Gtk.Label(" "), False, False, 0)
    dialog.vbox.pack_start(hbox, 1, 1, 0)
    #dialog.vbox.pack_start(Gtk.Label(" "), False, False, 0)
    dialog.show_all()

    htmlx = ""
    if dialog.run() == Gtk.ResponseType.OK:
        bi = textbuffer.get_start_iter()
        ei = textbuffer.get_end_iter()
        htmlx = textbuffer.get_text(bi, ei, False)

    dialog.destroy()

    # Unwrap it
    usss = ""
    cnt = 0; fff = 0
    for aa in htmlx:
        if aa == '\n':
            pass
        else:
            usss += aa
    return usss

def treecallb(ddd):
    global sizex
    #print("tree cb", ddd[0])
    sizex = ddd[0]

def sizedialog():

    ''' Present a selection Dialog for font sizes '''

    dialog = Gtk.Dialog("  Font Size   ", None, 0, () )

    #(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK))

    global sizex
    sizex = ""
    treedat = ["8", "9", "10", "12", "14", "20", "24", "32", "48", "56", "64",
                    "72", "96", "128"]

    tree = SimpleTree(["Font Sizes"])
    for aa in treedat:
        tree.append((aa,))

    def actcallb(ddd):
        #print("Activate cb", ddd, dialog)
        dialog.response(Gtk.ResponseType.OK)
        #print("Activate cb2", ddd, dialog)

    scrolledwindow = Gtk.ScrolledWindow()
    scrolledwindow.set_hexpand(True)
    scrolledwindow.set_vexpand(True)
    scrolledwindow.add(tree)
    scrolledwindow.set_size_request(120, 300)

    tree.setcallb(treecallb)
    tree.setActcallb(actcallb)

    hhh = "\n          " \
            "In general, any valid html can go here. Keep it simple.\n" \
            "The editor already decorated this sufficiently, "\
              "try to edit existing items in place.\n"

    lll = Gtk.Label(hhh)
    fd = Pango.FontDescription("Sans 9")
    lll.override_font(fd)
    thbox = Gtk.HBox()
    thbox.pack_start(lll, 1, 1, 1)
    #dialog.vbox.pack_start(thbox, False, False, 0)

    hbox = Gtk.HBox()
    hbox.pack_start(Gtk.Label(" "), False, False, 0)
    hbox.pack_start(scrolledwindow, 1, 1, 0)
    hbox.pack_start(Gtk.Label(" "), False, False, 0)
    dialog.vbox.pack_start(hbox, 1, 1, 0)
    #dialog.vbox.pack_start(Gtk.Label(" "), False, False, 0)
    dialog.show_all()

    if dialog.run() == Gtk.ResponseType.OK:
        #print("ok", sizex)
        pass
    else:
        sizex = 0

    dialog.destroy()
    return sizex

# EOF

Functions

def markdialog(sss)
Expand source code
def markdialog(sss):

    spaceneed = 64
    # Wrap tesxt if long
    ssss = ""
    cnt = 0; fff = 0
    for aa in sss:
        if cnt > spaceneed:
            fff = 1
        if fff and aa.isspace():
            cnt = 0; fff = 0
            ssss += "\n"
        ssss += aa
        cnt += 1

    dialog = Gtk.Dialog("   Edit markup   ", None, 0,
    (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK))

    textview = Gtk.TextView()
    textview.set_editable(True)

    textbuffer = textview.get_buffer()
    textbuffer.set_text(ssss)

    scrolledwindow = Gtk.ScrolledWindow()
    scrolledwindow.set_hexpand(True)
    scrolledwindow.set_vexpand(True)
    scrolledwindow.add(textview)
    scrolledwindow.set_size_request(640, 480)

    hhh = "\n          " \
            "In general, any valid html can go here. Keep it simple.\n" \
            "The editor already decorated this sufficiently, "\
              "try to edit existing items in place.\n"

    lll = Gtk.Label(hhh)
    fd = Pango.FontDescription("Sans 9")
    lll.override_font(fd)
    thbox = Gtk.HBox()
    thbox.pack_start(lll, 1, 1, 1)
    dialog.vbox.pack_start(thbox, False, False, 0)
    hbox = Gtk.HBox()
    hbox.pack_start(Gtk.Label(" "), False, False, 0)
    hbox.pack_start(scrolledwindow, 1, 1, 0)
    hbox.pack_start(Gtk.Label(" "), False, False, 0)
    dialog.vbox.pack_start(hbox, 1, 1, 0)
    #dialog.vbox.pack_start(Gtk.Label(" "), False, False, 0)
    dialog.show_all()

    htmlx = ""
    if dialog.run() == Gtk.ResponseType.OK:
        bi = textbuffer.get_start_iter()
        ei = textbuffer.get_end_iter()
        htmlx = textbuffer.get_text(bi, ei, False)

    dialog.destroy()

    # Unwrap it
    usss = ""
    cnt = 0; fff = 0
    for aa in htmlx:
        if aa == '\n':
            pass
        else:
            usss += aa
    return usss
def sizedialog()

Present a selection Dialog for font sizes

Expand source code
def sizedialog():

    ''' Present a selection Dialog for font sizes '''

    dialog = Gtk.Dialog("  Font Size   ", None, 0, () )

    #(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK))

    global sizex
    sizex = ""
    treedat = ["8", "9", "10", "12", "14", "20", "24", "32", "48", "56", "64",
                    "72", "96", "128"]

    tree = SimpleTree(["Font Sizes"])
    for aa in treedat:
        tree.append((aa,))

    def actcallb(ddd):
        #print("Activate cb", ddd, dialog)
        dialog.response(Gtk.ResponseType.OK)
        #print("Activate cb2", ddd, dialog)

    scrolledwindow = Gtk.ScrolledWindow()
    scrolledwindow.set_hexpand(True)
    scrolledwindow.set_vexpand(True)
    scrolledwindow.add(tree)
    scrolledwindow.set_size_request(120, 300)

    tree.setcallb(treecallb)
    tree.setActcallb(actcallb)

    hhh = "\n          " \
            "In general, any valid html can go here. Keep it simple.\n" \
            "The editor already decorated this sufficiently, "\
              "try to edit existing items in place.\n"

    lll = Gtk.Label(hhh)
    fd = Pango.FontDescription("Sans 9")
    lll.override_font(fd)
    thbox = Gtk.HBox()
    thbox.pack_start(lll, 1, 1, 1)
    #dialog.vbox.pack_start(thbox, False, False, 0)

    hbox = Gtk.HBox()
    hbox.pack_start(Gtk.Label(" "), False, False, 0)
    hbox.pack_start(scrolledwindow, 1, 1, 0)
    hbox.pack_start(Gtk.Label(" "), False, False, 0)
    dialog.vbox.pack_start(hbox, 1, 1, 0)
    #dialog.vbox.pack_start(Gtk.Label(" "), False, False, 0)
    dialog.show_all()

    if dialog.run() == Gtk.ResponseType.OK:
        #print("ok", sizex)
        pass
    else:
        sizex = 0

    dialog.destroy()
    return sizex
def treecallb(ddd)
Expand source code
def treecallb(ddd):
    global sizex
    #print("tree cb", ddd[0])
    sizex = ddd[0]

Classes

class dummywebkit
Expand source code
class dummywebkit():
    WebView = dummywebview

Class variables

var WebView

:Constructors:

::

VBox(**properties)
new(homogeneous:bool, spacing:int) -> Gtk.Widget
class dummywebview (*args, **kwargs)

:Constructors:

::

VBox(**properties)
new(homogeneous:bool, spacing:int) -> Gtk.Widget

Initializer for a GObject based classes with support for property sets through the use of explicit keyword arguments.

Expand source code
class dummywebview(Gtk.VBox):

    def __int__(self):
        super().__init__(self)
        #self.pack_start(Gtk.Label(label="No WebView"), 1, 1, 0)
    def set_editable(self, flag):
        self.pack_start(Gtk.Label(label="No WebView Available"), 1, 1, 0)
        pass
    def load_html(self, ff, kk = None):
        pass
    def connect(self, aa, bb):
        pass

Ancestors

  • gi.repository.Gtk.VBox
  • gi.overrides.Gtk.Box
  • gi.repository.Gtk.Box
  • gi.overrides.Gtk.Container
  • gi.repository.Gtk.Container
  • gi.overrides.Gtk.Widget
  • gi.repository.Gtk.Widget
  • gi.repository.GObject.InitiallyUnowned
  • gi.overrides.GObject.Object
  • gi.repository.GObject.Object
  • gi._gi.GObject
  • gi.repository.Atk.ImplementorIface
  • gi.repository.Gtk.Buildable
  • gi.repository.Gtk.Orientable
  • gobject.GInterface

Methods

def connect(self, aa, bb)
Expand source code
def connect(self, aa, bb):
    pass
def load_html(self, ff, kk=None)
Expand source code
def load_html(self, ff, kk = None):
    pass
def set_editable(self, flag)
Expand source code
def set_editable(self, flag):
    self.pack_start(Gtk.Label(label="No WebView Available"), 1, 1, 0)
    pass
class pgwebw (xlink=None)

Define our override of the webkit class

Expand source code
class pgwebw(WebKit2.WebView):

    ''' Define our override of the webkit class '''

    def __init__(self, xlink=None):
        try:
            GObject.GObject.__init__(self)
        except:
            print("Cannot ??? in parent object", sys.exc_info())
            pass
        self.xlink = xlink
        self.set_editable(True)

        #if editable:
        #    self.set_editable(True)

        self.fname = ""
        self.load_html("", "file:///")
        self.ui = self.generate_ui()
        self.connect("key-release-event",  self.keypress)
        self.modified = False

    def  _get_response_data_finish(self, resource, result, user_data=None):
        self.old_html = resource.get_data_finish(result)
        #print((self.old_html))

    def keypress(self, arg, arg2):

        ''' Here we imitate the way the accelerator works '''

        state = arg2.get_state() & Gdk.ModifierType.MODIFIER_MASK
        key = arg2.get_keyval()[1]
        #print("key",  key, "state", state)

        #GDK_MODIFIER_RESERVED_25_MASK

        # Feeding off the accelarator's definitions
        ag = self.ui.get_action_groups()[0]
        acts = ag.list_actions()

        # Scan - Fire
        for aa in acts:
            if aa.accel:
                #print(nnn, aa.accel, aa.accel_parsed)
                if state == aa.accel_parsed[1]:
                    #print("state match")
                    if key == aa.accel_parsed[0]:
                        #print("Fire ", aa.get_name(), aa.get_label())
                        #lab = aa.get_label()
                        aa.activate()
                        break   # Only one accel the other is a mistake

        # See if nav key
        navkey = False
        for aa in navkeys:
            if key == aa:
                #print("Navkey", aa)
                navkey = True
        if not navkey:
            # Exclude Ctrl-s
            if state == Gdk.ModifierType.CONTROL_MASK and key == 115:
                #print("Control s")
                pass
            else:
                #print("set on key", key)
                self.modified =  True

    def do_ready_to_show(self):
        print("do_ready_to_show() was called")
        pass

    def do_load_changed(self, status):

        #print("do_load_changed()", status)
        if status == WebKit2.LoadEvent.FINISHED:
            ''' Create a shadow of content '''

            # This gets it without spaces
            #resource = self.get_main_resource()
            #resource.get_data(None, self._get_response_data_finish, None)

            # Get it by JS
            def completion(html, user_data):
                self.old_html = html
            self.get_html(completion, '')


        if self.get_uri():
            if self.xlink:
                self.xlink.set_status("Loading ... " + self.get_uri()[:64])

        if status == 3: #WebKit2.LoadEvent.WEBKIT_LOAD_FINISHED:
            #print("got WEBKIT_LOAD_FINISHED")
            if self.get_uri():
                if self.xlink:
                    self.xlink.edit.set_text(self.get_uri()[:64])
                    self.xlink.set_status("Finished: " + self.get_uri()[:64])
            self.grab_focus()

    def do_load_failed(self, load_event, failing_uri, error):
        print("do_load_failed() was called", failing_uri)
        if self.xlink:
            self.xlink.set_status("Failed: " + failing_uri[:64])

    def on_header(self, action):
        #print("on_aheader", action.get_name())
        ddd = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
        ccc = None
        while True:
            #target = Gdk.Atom.intern ("text/html", True);
            #ccc = ddd.wait_for_contents(target)
            #if ccc:
            #    break
            target2 = Gdk.Atom.intern ("text/plain", True);
            ccc = ddd.wait_for_contents(target2)
            if ccc:
                break
            break

        if not ccc:
            return

        dddd = ccc.get_data().decode()
        if not dddd:
            return
        #print("dddd", dddd)
        htmlx = "<%s>%s</%s>" % (action.get_name(), dddd, action.get_name())
        self.run_javascript("document.execCommand \
                            ('insertHTML', null, '%s');" % htmlx)
        Gtk.Clipboard.clear(ddd)
        self.modified = True

    def on_action(self, action):
        #print("on_action", action.get_name())
        # Make it caller neutral
        if type(action) == str:
            nnn = action
        else:
            nnn = action.get_name()
        self.run_javascript("document.execCommand('%s', false, false);" % nnn)
        self.modified = True

    def on_paste(self, action = ""):
        print("Paste")
        self.execute_editing_command(WebKit2.EDITING_COMMAND_PASTE)

    def on_new(self, action):
        self.load_html("", "file:///")
        self.modified = False

    def on_fontsize(self, action):
        #print("on_fontsize")
        sizex = sizedialog()
        #print("sizex", sizex)
        if not sizex:
            return

        c = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
        sel = c.wait_for_targets()
        #print("sel", sel)
        target = Gdk.Atom.intern ("text/plain", True);
        ccc = c.wait_for_contents(target)
        if not ccc:
            htmlx = "<span style=\"font-size: %dpx;\">%s</span>" % (int(sizex), "")
            self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
            return

        ddd = ccc.get_data().decode()
        if not ddd:
            return

        #print("ddd", ddd)
        htmlx = "<span style=\"font-size: %dpx;\">%s</span>" % (int(sizex), ddd)
        self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
        Gtk.Clipboard.clear(c)
        self.modified = True

    def on_select_font(self, action):
        dialog = Gtk.FontChooserDialog("Select a font")
        if dialog.run() == Gtk.ResponseType.OK:
            fname = dialog.get_font_desc().get_family()
            fsize = dialog.get_font_desc().get_size() / Pango.SCALE
            ttt = int(1 + round(fsize / 10)) % 9
            print("Setting font", fname, fsize, ttt)
            self.run_javascript("document.execCommand('fontname', null, '%s');" % fname)
            self.run_javascript("document.execCommand('fontsize', null, '%s');" % ttt)
        dialog.destroy()

    def on_select_color(self, action):
        dialog = Gtk.ColorChooserDialog("Select Color")
        if dialog.run() == Gtk.ResponseType.OK:
            (r, g, b, a) = dialog.get_rgba()
            color = "#%0.2x%0.2x%0.2x%0.2x" % (
                int(r * 255),
                int(g * 255),
                int(b * 255),
                int(a * 255))
            self.run_javascript("document.execCommand('forecolor', null, '%s');" % color)
        dialog.destroy()

    def on_select_bgcolor(self, action):
        dialog = Gtk.ColorChooserDialog("Select Background Color")
        if dialog.run() == Gtk.ResponseType.OK:
            (r, g, b, a) = dialog.get_rgba()
            color = "#%0.2x%0.2x%0.2x%0.2x" % (
                int(r * 255),
                int(g * 255),
                int(b * 255),
                int(a * 255))
            self.run_javascript("document.execCommand('backcolor', null, '%s');" % color)
        dialog.destroy()

    def on_edit_marker(self, action):
        print("on_edit_marker", action.get_name())

        c = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
        sel = c.wait_for_targets()
        target = Gdk.Atom.intern ("text/html", True);
        ccc = c.wait_for_contents(target)
        #print("sel", ccc.get_data())
        #ccc.free()
        htmlx = markdialog(ccc.get_data().decode())
        if htmlx:
            print("markdialog result:\n", htmlx)
            self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)

    def on_insert_table(self, action):
        htmlx = "<table align=center border=0 contentEditable=true>" + \
                "<tr><td>TR1 C1 <td>| TR1 C2 <tr><td>TR2 C1<td>| TR2 C1</table><br>"

        #print("table", htmlx)
        self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
        self.modified = True

    def on_insert_link(self, action):
        dialog = Gtk.Dialog("   Enter a URL:   ", None, 0,
        (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK))

        entry = Gtk.Entry()
        dialog.vbox.pack_start(Gtk.Label("  "), False, False, 0)
        hbox = Gtk.HBox()
        hbox.pack_start(Gtk.Label("  "), False, False, 0)
        hbox.pack_start(entry, False, False, 0)
        hbox.pack_start(Gtk.Label("  "), False, False, 0)
        dialog.vbox.pack_start(hbox, False, False, 0)

        dialog.vbox.pack_start(Gtk.Label("  "), False, False, 0)
        dialog.show_all()

        if dialog.run() == Gtk.ResponseType.OK:
            self.run_javascript(
                "document.execCommand('createLink', True, '%s');" % entry.get_text())
        dialog.destroy()
        self.modified = True

    def on_insert_image(self, action):
        dialog = Gtk.FileChooserDialog("Select an image file", None, Gtk.FileChooserAction.OPEN,
        (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))

        if dialog.run() == Gtk.ResponseType.OK:
            fn = dialog.get_filename()
            if os.path.exists(fn):
                self.run_javascript(
                "document.execCommand('insertImage', null, '%s');" % fn)
        dialog.destroy()
        self.modified = True

    def on_open(self, action):
        dialog = Gtk.FileChooserDialog("Select an HTML file", self, Gtk.FileChooserAction.OPEN,
        (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))

        if dialog.run() == Gtk.ResponseType.OK:
            fn = dialog.get_filename()
            if os.path.exists(fn):
                self.fname = fn
                with open(fn) as fd:
                    self.load_html(fd.read(), "file:///")
        dialog.destroy()

    def on_save(self, action):
        def completion(html, user_data):
            open_mode = user_data
            with open(self.fname, open_mode) as fd:
                fd.write(html)

        if self.fname:
            self.get_html(completion, 'w')
        else:
            dialog = Gtk.FileChooserDialog("Select an HTML file", None,
                    Gtk.FileChooserAction.SAVE,
                        (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                            Gtk.STOCK_SAVE, Gtk.ResponseType.OK))

            if dialog.run() == Gtk.ResponseType.OK:
                self.fname = dialog.get_filename()
                print("Saving", self.fname)
                self.get_html(completion, "w+")
            dialog.destroy()

    def get_html(self, completion_function, user_data):

        #print("get_html")
        def javascript_completion(obj, result, user_data):
            #print("javascript_completion", result)
            fin = self.run_javascript_finish(result)
            #print("fin", fin)
            html = fin.get_js_value().to_string()
            #print("len html", len(html), "\n")
            completion_function(html, user_data)
        self.run_javascript("document.documentElement.innerHTML;",
                                   None,
                                   javascript_completion,
                                   user_data)

    def get_lastmod(self, completion_function, user_data):

        print("get_lastmod")
        def javascript_completion(obj, result, user_data):
            print("javascript_completion", result)
            fin = self.run_javascript_finish(result)
            #print("fin", fin)
            html = fin.get_js_value().to_string()
            print("lastmod", html, "\n")
            #completion_function(html, user_data)
        self.run_javascript("document.lastModified",
                                   None,
                                   javascript_completion,
                                   user_data)


    def generate_ui(self):

        ''' define toolbar items and actions here '''

        actions = Gtk.ActionGroup("Actions")
    # ----------------------------------------------------------------
    # Name,     Stock Icon,   Accelerator,  ToolTip,   Action

    # Some already has app accels

        accel_arr = [ \

    #("menuFile",    None, "_File"),
    #("menuEdit",    None, "_Edit"),
    #("menuInsert",  None, "_Insert"),
    #("menuFormat",  None, "_Format"),
    #("new",         Gtk.STOCK_NEW, "_New", None, None, self.on_new),
    #("open",        Gtk.STOCK_OPEN, "_Open", None, None, self.on_open),
    #("save",        Gtk.STOCK_SAVE, "_Save", None, None, self.on_save),

    ("cut",         Gtk.STOCK_CUT, "_Cut", None, None, self.on_action),
    ("copy",        Gtk.STOCK_COPY, "_Copy", None, None, self.on_action),
    ("paste",       Gtk.STOCK_PASTE, "_Paste", None, None, self.on_paste),

    ("undo",        Gtk.STOCK_UNDO, "_Undo", "<Control>z", "Undo Last Edit", self.on_action),
    ("redo",        Gtk.STOCK_REDO, "_Redo", "<Control>y", "Redo Last Undo", self.on_action),

    ("removeformat", Gtk.STOCK_PROPERTIES, "_removeFormat", "<Control>M", "Remove Formatting", self.on_action),
    ("bold",        Gtk.STOCK_BOLD, "_Bold", "", "Bold / UnBold Selection", self.on_action),
    ("italic",      Gtk.STOCK_ITALIC, "_Italic", "", None, self.on_action),
    ("underline",       Gtk.STOCK_UNDERLINE, "_Underline", "", None, self.on_action),
    ("strikethrough", Gtk.STOCK_STRIKETHROUGH, "_Strike", "", None, self.on_action),
    ("font",        Gtk.STOCK_SELECT_FONT, "Select _Font", "", None, self.on_select_font),
    ("fontsize",    None, "Select Font _Size", "<Control>f", "Set Absolute Size (removes color)", self.on_fontsize),
    ("color",       Gtk.STOCK_SELECT_COLOR, "Select _Color", None, None, self.on_select_color),
    ("backgroundcolor", Gtk.STOCK_COLOR_PICKER, "Select Back Color", None, None, self.on_select_bgcolor),

    ("justifyleft",  Gtk.STOCK_JUSTIFY_LEFT, "Justify _Left", None, None, self.on_action),
    ("justifyright", Gtk.STOCK_JUSTIFY_RIGHT, "Justify _Right", None, None, self.on_action),
    ("justifycenter", Gtk.STOCK_JUSTIFY_CENTER, "Justify _Center", None, None, self.on_action),
    ("justifyfull",   Gtk.STOCK_JUSTIFY_FILL, "Justify _Full", None, None, self.on_action),

    # Pad Images by name (may not be present in all styles)
    ("insertimage", "insert-image", "Insert _Image", None, None, self.on_insert_image),
    ("insertlink", "insert-link", "Insert _Link", None, None, self.on_insert_link),
    ("inserttable", "insert-table", "Insert _Table", None, None, self.on_insert_table),
    ("editmarker", "edit-marker", "edit _Marker", None, None, self.on_edit_marker),

    ("H1",   Gtk.STOCK_EXECUTE, "Header 1", None, "Insert Header 1", self.on_header),
    ("H2",   Gtk.STOCK_EXECUTE, "Header 2", None, "Insert Header 2", self.on_header),
    ("H3",   Gtk.STOCK_EXECUTE, "Header 3", None, "Insert Header 3", self.on_header),
    ("H4",   Gtk.STOCK_EXECUTE, "Header 4", None, "Insert Header 4", self.on_header),

    ]

        actions.add_actions(accel_arr)

        #print(dir(actions))
        for aa in accel_arr:
        #    print("acc arr", dir(aa))
        #    break
        #    act = actions.get_action(aa[0])
        #    print("act", act.get_name(), act.get_tooltip())
            pass
        #    try:
        #        act = Gtk.Action.new(aa[0], aa[2], aa[4], aa[1])
        #        actions.add_action_with_accel(act, aa[3])
        #    except:
        #        #print("Exc on", aa)
        #        pass

        actions.get_action("insertimage").set_property("icon-name", "insert-image")
        actions.get_action("insertlink").set_property("icon-name", "insert-link")
        actions.get_action("inserttable").set_property("icon-name", "appointment-new")
        actions.get_action("editmarker").set_property("icon-name", "text-editor")
        actions.get_action("fontsize").set_property("icon-name", "preferences-desktop-font")
        actions.get_action("removeformat").set_property("icon-name", "text-direction")

        ui = Gtk.UIManager()
        ui.insert_action_group(actions)
        ui.add_ui_from_string(ui_def)

        # Fill in defaults
        xxx = ui.get_action_groups()[0].list_actions()
        for aa in xxx:
            nnn = aa.get_name()
            # Find the original, patth missing info
            for bb in accel_arr:
                # Convert tuple
                bbb = list(bb)
                if bb[0] == nnn:
                    # Pad for this round
                    for cc in range(5 - len(bbb)):
                        bbb.append("")

                    #print("lab", bb[2], aa.get_label())
                    #print("found", nnn, bbb[3])

                    setattr(aa, "accel", bbb[3])
                    if bbb[3]:
                        try:
                            nn, ss = Gtk.accelerator_parse(bbb[3])
                            setattr(aa, "accel_parsed", (nn, ss))
                        except:
                            pass

            # Pad it with capitalize name if not there
            if  not aa.get_tooltip():
                aa.set_tooltip(nnn[0].upper() + nnn[1:])

        return ui

Ancestors

  • gi.repository.WebKit2.WebView
  • gi.repository.WebKit2.WebViewBase
  • gi.overrides.Gtk.Container
  • gi.repository.Gtk.Container
  • gi.overrides.Gtk.Widget
  • gi.repository.Gtk.Widget
  • gi.repository.GObject.InitiallyUnowned
  • gi.overrides.GObject.Object
  • gi.repository.GObject.Object
  • gi._gi.GObject
  • gi.repository.Atk.ImplementorIface
  • gi.repository.Gtk.Buildable
  • gobject.GInterface

Methods

def do_load_changed(self, status)

load_changed(self, load_event:WebKit2.LoadEvent)

Expand source code
def do_load_changed(self, status):

    #print("do_load_changed()", status)
    if status == WebKit2.LoadEvent.FINISHED:
        ''' Create a shadow of content '''

        # This gets it without spaces
        #resource = self.get_main_resource()
        #resource.get_data(None, self._get_response_data_finish, None)

        # Get it by JS
        def completion(html, user_data):
            self.old_html = html
        self.get_html(completion, '')


    if self.get_uri():
        if self.xlink:
            self.xlink.set_status("Loading ... " + self.get_uri()[:64])

    if status == 3: #WebKit2.LoadEvent.WEBKIT_LOAD_FINISHED:
        #print("got WEBKIT_LOAD_FINISHED")
        if self.get_uri():
            if self.xlink:
                self.xlink.edit.set_text(self.get_uri()[:64])
                self.xlink.set_status("Finished: " + self.get_uri()[:64])
        self.grab_focus()
def do_load_failed(self, load_event, failing_uri, error)

load_failed(self, load_event:WebKit2.LoadEvent, failing_uri:str, error:error) -> bool

Expand source code
def do_load_failed(self, load_event, failing_uri, error):
    print("do_load_failed() was called", failing_uri)
    if self.xlink:
        self.xlink.set_status("Failed: " + failing_uri[:64])
def do_ready_to_show(self)

ready_to_show(self)

Expand source code
def do_ready_to_show(self):
    print("do_ready_to_show() was called")
    pass
def generate_ui(self)

define toolbar items and actions here

Expand source code
def generate_ui(self):

    ''' define toolbar items and actions here '''

    actions = Gtk.ActionGroup("Actions")
# ----------------------------------------------------------------
# Name,     Stock Icon,   Accelerator,  ToolTip,   Action

# Some already has app accels

    accel_arr = [ \

#("menuFile",    None, "_File"),
#("menuEdit",    None, "_Edit"),
#("menuInsert",  None, "_Insert"),
#("menuFormat",  None, "_Format"),
#("new",         Gtk.STOCK_NEW, "_New", None, None, self.on_new),
#("open",        Gtk.STOCK_OPEN, "_Open", None, None, self.on_open),
#("save",        Gtk.STOCK_SAVE, "_Save", None, None, self.on_save),

("cut",         Gtk.STOCK_CUT, "_Cut", None, None, self.on_action),
("copy",        Gtk.STOCK_COPY, "_Copy", None, None, self.on_action),
("paste",       Gtk.STOCK_PASTE, "_Paste", None, None, self.on_paste),

("undo",        Gtk.STOCK_UNDO, "_Undo", "<Control>z", "Undo Last Edit", self.on_action),
("redo",        Gtk.STOCK_REDO, "_Redo", "<Control>y", "Redo Last Undo", self.on_action),

("removeformat", Gtk.STOCK_PROPERTIES, "_removeFormat", "<Control>M", "Remove Formatting", self.on_action),
("bold",        Gtk.STOCK_BOLD, "_Bold", "", "Bold / UnBold Selection", self.on_action),
("italic",      Gtk.STOCK_ITALIC, "_Italic", "", None, self.on_action),
("underline",       Gtk.STOCK_UNDERLINE, "_Underline", "", None, self.on_action),
("strikethrough", Gtk.STOCK_STRIKETHROUGH, "_Strike", "", None, self.on_action),
("font",        Gtk.STOCK_SELECT_FONT, "Select _Font", "", None, self.on_select_font),
("fontsize",    None, "Select Font _Size", "<Control>f", "Set Absolute Size (removes color)", self.on_fontsize),
("color",       Gtk.STOCK_SELECT_COLOR, "Select _Color", None, None, self.on_select_color),
("backgroundcolor", Gtk.STOCK_COLOR_PICKER, "Select Back Color", None, None, self.on_select_bgcolor),

("justifyleft",  Gtk.STOCK_JUSTIFY_LEFT, "Justify _Left", None, None, self.on_action),
("justifyright", Gtk.STOCK_JUSTIFY_RIGHT, "Justify _Right", None, None, self.on_action),
("justifycenter", Gtk.STOCK_JUSTIFY_CENTER, "Justify _Center", None, None, self.on_action),
("justifyfull",   Gtk.STOCK_JUSTIFY_FILL, "Justify _Full", None, None, self.on_action),

# Pad Images by name (may not be present in all styles)
("insertimage", "insert-image", "Insert _Image", None, None, self.on_insert_image),
("insertlink", "insert-link", "Insert _Link", None, None, self.on_insert_link),
("inserttable", "insert-table", "Insert _Table", None, None, self.on_insert_table),
("editmarker", "edit-marker", "edit _Marker", None, None, self.on_edit_marker),

("H1",   Gtk.STOCK_EXECUTE, "Header 1", None, "Insert Header 1", self.on_header),
("H2",   Gtk.STOCK_EXECUTE, "Header 2", None, "Insert Header 2", self.on_header),
("H3",   Gtk.STOCK_EXECUTE, "Header 3", None, "Insert Header 3", self.on_header),
("H4",   Gtk.STOCK_EXECUTE, "Header 4", None, "Insert Header 4", self.on_header),

]

    actions.add_actions(accel_arr)

    #print(dir(actions))
    for aa in accel_arr:
    #    print("acc arr", dir(aa))
    #    break
    #    act = actions.get_action(aa[0])
    #    print("act", act.get_name(), act.get_tooltip())
        pass
    #    try:
    #        act = Gtk.Action.new(aa[0], aa[2], aa[4], aa[1])
    #        actions.add_action_with_accel(act, aa[3])
    #    except:
    #        #print("Exc on", aa)
    #        pass

    actions.get_action("insertimage").set_property("icon-name", "insert-image")
    actions.get_action("insertlink").set_property("icon-name", "insert-link")
    actions.get_action("inserttable").set_property("icon-name", "appointment-new")
    actions.get_action("editmarker").set_property("icon-name", "text-editor")
    actions.get_action("fontsize").set_property("icon-name", "preferences-desktop-font")
    actions.get_action("removeformat").set_property("icon-name", "text-direction")

    ui = Gtk.UIManager()
    ui.insert_action_group(actions)
    ui.add_ui_from_string(ui_def)

    # Fill in defaults
    xxx = ui.get_action_groups()[0].list_actions()
    for aa in xxx:
        nnn = aa.get_name()
        # Find the original, patth missing info
        for bb in accel_arr:
            # Convert tuple
            bbb = list(bb)
            if bb[0] == nnn:
                # Pad for this round
                for cc in range(5 - len(bbb)):
                    bbb.append("")

                #print("lab", bb[2], aa.get_label())
                #print("found", nnn, bbb[3])

                setattr(aa, "accel", bbb[3])
                if bbb[3]:
                    try:
                        nn, ss = Gtk.accelerator_parse(bbb[3])
                        setattr(aa, "accel_parsed", (nn, ss))
                    except:
                        pass

        # Pad it with capitalize name if not there
        if  not aa.get_tooltip():
            aa.set_tooltip(nnn[0].upper() + nnn[1:])

    return ui
def get_html(self, completion_function, user_data)
Expand source code
def get_html(self, completion_function, user_data):

    #print("get_html")
    def javascript_completion(obj, result, user_data):
        #print("javascript_completion", result)
        fin = self.run_javascript_finish(result)
        #print("fin", fin)
        html = fin.get_js_value().to_string()
        #print("len html", len(html), "\n")
        completion_function(html, user_data)
    self.run_javascript("document.documentElement.innerHTML;",
                               None,
                               javascript_completion,
                               user_data)
def get_lastmod(self, completion_function, user_data)
Expand source code
def get_lastmod(self, completion_function, user_data):

    print("get_lastmod")
    def javascript_completion(obj, result, user_data):
        print("javascript_completion", result)
        fin = self.run_javascript_finish(result)
        #print("fin", fin)
        html = fin.get_js_value().to_string()
        print("lastmod", html, "\n")
        #completion_function(html, user_data)
    self.run_javascript("document.lastModified",
                               None,
                               javascript_completion,
                               user_data)
def keypress(self, arg, arg2)

Here we imitate the way the accelerator works

Expand source code
def keypress(self, arg, arg2):

    ''' Here we imitate the way the accelerator works '''

    state = arg2.get_state() & Gdk.ModifierType.MODIFIER_MASK
    key = arg2.get_keyval()[1]
    #print("key",  key, "state", state)

    #GDK_MODIFIER_RESERVED_25_MASK

    # Feeding off the accelarator's definitions
    ag = self.ui.get_action_groups()[0]
    acts = ag.list_actions()

    # Scan - Fire
    for aa in acts:
        if aa.accel:
            #print(nnn, aa.accel, aa.accel_parsed)
            if state == aa.accel_parsed[1]:
                #print("state match")
                if key == aa.accel_parsed[0]:
                    #print("Fire ", aa.get_name(), aa.get_label())
                    #lab = aa.get_label()
                    aa.activate()
                    break   # Only one accel the other is a mistake

    # See if nav key
    navkey = False
    for aa in navkeys:
        if key == aa:
            #print("Navkey", aa)
            navkey = True
    if not navkey:
        # Exclude Ctrl-s
        if state == Gdk.ModifierType.CONTROL_MASK and key == 115:
            #print("Control s")
            pass
        else:
            #print("set on key", key)
            self.modified =  True
def on_action(self, action)
Expand source code
def on_action(self, action):
    #print("on_action", action.get_name())
    # Make it caller neutral
    if type(action) == str:
        nnn = action
    else:
        nnn = action.get_name()
    self.run_javascript("document.execCommand('%s', false, false);" % nnn)
    self.modified = True
def on_edit_marker(self, action)
Expand source code
def on_edit_marker(self, action):
    print("on_edit_marker", action.get_name())

    c = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
    sel = c.wait_for_targets()
    target = Gdk.Atom.intern ("text/html", True);
    ccc = c.wait_for_contents(target)
    #print("sel", ccc.get_data())
    #ccc.free()
    htmlx = markdialog(ccc.get_data().decode())
    if htmlx:
        print("markdialog result:\n", htmlx)
        self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
def on_fontsize(self, action)
Expand source code
def on_fontsize(self, action):
    #print("on_fontsize")
    sizex = sizedialog()
    #print("sizex", sizex)
    if not sizex:
        return

    c = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
    sel = c.wait_for_targets()
    #print("sel", sel)
    target = Gdk.Atom.intern ("text/plain", True);
    ccc = c.wait_for_contents(target)
    if not ccc:
        htmlx = "<span style=\"font-size: %dpx;\">%s</span>" % (int(sizex), "")
        self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
        return

    ddd = ccc.get_data().decode()
    if not ddd:
        return

    #print("ddd", ddd)
    htmlx = "<span style=\"font-size: %dpx;\">%s</span>" % (int(sizex), ddd)
    self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
    Gtk.Clipboard.clear(c)
    self.modified = True
def on_header(self, action)
Expand source code
def on_header(self, action):
    #print("on_aheader", action.get_name())
    ddd = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
    ccc = None
    while True:
        #target = Gdk.Atom.intern ("text/html", True);
        #ccc = ddd.wait_for_contents(target)
        #if ccc:
        #    break
        target2 = Gdk.Atom.intern ("text/plain", True);
        ccc = ddd.wait_for_contents(target2)
        if ccc:
            break
        break

    if not ccc:
        return

    dddd = ccc.get_data().decode()
    if not dddd:
        return
    #print("dddd", dddd)
    htmlx = "<%s>%s</%s>" % (action.get_name(), dddd, action.get_name())
    self.run_javascript("document.execCommand \
                        ('insertHTML', null, '%s');" % htmlx)
    Gtk.Clipboard.clear(ddd)
    self.modified = True
def on_insert_image(self, action)
Expand source code
def on_insert_image(self, action):
    dialog = Gtk.FileChooserDialog("Select an image file", None, Gtk.FileChooserAction.OPEN,
    (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))

    if dialog.run() == Gtk.ResponseType.OK:
        fn = dialog.get_filename()
        if os.path.exists(fn):
            self.run_javascript(
            "document.execCommand('insertImage', null, '%s');" % fn)
    dialog.destroy()
    self.modified = True
Expand source code
def on_insert_link(self, action):
    dialog = Gtk.Dialog("   Enter a URL:   ", None, 0,
    (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK))

    entry = Gtk.Entry()
    dialog.vbox.pack_start(Gtk.Label("  "), False, False, 0)
    hbox = Gtk.HBox()
    hbox.pack_start(Gtk.Label("  "), False, False, 0)
    hbox.pack_start(entry, False, False, 0)
    hbox.pack_start(Gtk.Label("  "), False, False, 0)
    dialog.vbox.pack_start(hbox, False, False, 0)

    dialog.vbox.pack_start(Gtk.Label("  "), False, False, 0)
    dialog.show_all()

    if dialog.run() == Gtk.ResponseType.OK:
        self.run_javascript(
            "document.execCommand('createLink', True, '%s');" % entry.get_text())
    dialog.destroy()
    self.modified = True
def on_insert_table(self, action)
Expand source code
def on_insert_table(self, action):
    htmlx = "<table align=center border=0 contentEditable=true>" + \
            "<tr><td>TR1 C1 <td>| TR1 C2 <tr><td>TR2 C1<td>| TR2 C1</table><br>"

    #print("table", htmlx)
    self.run_javascript("document.execCommand('insertHTML', null, '%s');" % htmlx)
    self.modified = True
def on_new(self, action)
Expand source code
def on_new(self, action):
    self.load_html("", "file:///")
    self.modified = False
def on_open(self, action)
Expand source code
def on_open(self, action):
    dialog = Gtk.FileChooserDialog("Select an HTML file", self, Gtk.FileChooserAction.OPEN,
    (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))

    if dialog.run() == Gtk.ResponseType.OK:
        fn = dialog.get_filename()
        if os.path.exists(fn):
            self.fname = fn
            with open(fn) as fd:
                self.load_html(fd.read(), "file:///")
    dialog.destroy()
def on_paste(self, action='')
Expand source code
def on_paste(self, action = ""):
    print("Paste")
    self.execute_editing_command(WebKit2.EDITING_COMMAND_PASTE)
def on_save(self, action)
Expand source code
def on_save(self, action):
    def completion(html, user_data):
        open_mode = user_data
        with open(self.fname, open_mode) as fd:
            fd.write(html)

    if self.fname:
        self.get_html(completion, 'w')
    else:
        dialog = Gtk.FileChooserDialog("Select an HTML file", None,
                Gtk.FileChooserAction.SAVE,
                    (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                        Gtk.STOCK_SAVE, Gtk.ResponseType.OK))

        if dialog.run() == Gtk.ResponseType.OK:
            self.fname = dialog.get_filename()
            print("Saving", self.fname)
            self.get_html(completion, "w+")
        dialog.destroy()
def on_select_bgcolor(self, action)
Expand source code
def on_select_bgcolor(self, action):
    dialog = Gtk.ColorChooserDialog("Select Background Color")
    if dialog.run() == Gtk.ResponseType.OK:
        (r, g, b, a) = dialog.get_rgba()
        color = "#%0.2x%0.2x%0.2x%0.2x" % (
            int(r * 255),
            int(g * 255),
            int(b * 255),
            int(a * 255))
        self.run_javascript("document.execCommand('backcolor', null, '%s');" % color)
    dialog.destroy()
def on_select_color(self, action)
Expand source code
def on_select_color(self, action):
    dialog = Gtk.ColorChooserDialog("Select Color")
    if dialog.run() == Gtk.ResponseType.OK:
        (r, g, b, a) = dialog.get_rgba()
        color = "#%0.2x%0.2x%0.2x%0.2x" % (
            int(r * 255),
            int(g * 255),
            int(b * 255),
            int(a * 255))
        self.run_javascript("document.execCommand('forecolor', null, '%s');" % color)
    dialog.destroy()
def on_select_font(self, action)
Expand source code
def on_select_font(self, action):
    dialog = Gtk.FontChooserDialog("Select a font")
    if dialog.run() == Gtk.ResponseType.OK:
        fname = dialog.get_font_desc().get_family()
        fsize = dialog.get_font_desc().get_size() / Pango.SCALE
        ttt = int(1 + round(fsize / 10)) % 9
        print("Setting font", fname, fsize, ttt)
        self.run_javascript("document.execCommand('fontname', null, '%s');" % fname)
        self.run_javascript("document.execCommand('fontsize', null, '%s');" % ttt)
    dialog.destroy()
class pgwebw_fake

:Constructors:

::

VBox(**properties)
new(homogeneous:bool, spacing:int) -> Gtk.Widget

Initializer for a GObject based classes with support for property sets through the use of explicit keyword arguments.

Expand source code
class pgwebw_fake(Gtk.VBox):

    def __init__(self):
        super(pgwebw_fake, self).__init__();
        pass

    def load_uri(self, url):
        pass

Ancestors

  • gi.repository.Gtk.VBox
  • gi.overrides.Gtk.Box
  • gi.repository.Gtk.Box
  • gi.overrides.Gtk.Container
  • gi.repository.Gtk.Container
  • gi.overrides.Gtk.Widget
  • gi.repository.Gtk.Widget
  • gi.repository.GObject.InitiallyUnowned
  • gi.overrides.GObject.Object
  • gi.repository.GObject.Object
  • gi._gi.GObject
  • gi.repository.Atk.ImplementorIface
  • gi.repository.Gtk.Buildable
  • gi.repository.Gtk.Orientable
  • gobject.GInterface

Methods

def load_uri(self, url)
Expand source code
def load_uri(self, url):
    pass