Beispiel #1
0
    def __init__ (self):
        self.currentPage = None
        self.editMode = False
        self.textChanged = False

        self.gladeFile = "wikiorg.glade"
        self.tree = gtk.glade.XML(self.gladeFile)
        self.tree.signal_autoconnect(self)

        # set up storage backend:
        self.storage = FileStorageBackend()

        # set up link history:
        self.linkHistory = LinkHistory(self)

        # set up menus for back/forward buttons:
        btnGoBack = self.tree.get_widget("btnGoBack")
        self.backMenu = gtk.Menu()
        btnGoBack.set_menu(self.backMenu)

        btnGoForward = self.tree.get_widget("btnGoForward")
        self.forwardMenu = gtk.Menu()
        btnGoForward.set_menu(self.forwardMenu)

        # set up HTML viewer widget:
        self.viewer = HtmlViewer()
        self.viewer.setLinkHandler(self.linkHandler)
        self.viewer.getWidget().show()

        # remove the TextView from ScrolledWindow but keep it for later:
        viewerParent = self.tree.get_widget('mainScrollWin')
        self.textView = viewerParent.get_children()[0]
        viewerParent.remove(self.textView)
        # instead, add the HTML viewer widget:
        viewerParent.add(self.viewer.getWidget())

        # set up text view:
        fontName = "Monospace"
        pangoFont = pango.FontDescription(fontName)
        self.textView.modify_font(pangoFont)

        # add TextBuffer for text view:
        self.textBuffer = gtk.TextBuffer(None)
        self.textView.set_buffer(self.textBuffer)

        # display start page:
        self.displayMarkdown('index')
Beispiel #2
0
class WikiOrgGui:
    """ Main class for this application (holds the GUI etc.) """
    def __init__ (self):
        self.currentPage = None
        self.editMode = False
        self.textChanged = False

        self.gladeFile = "wikiorg.glade"
        self.tree = gtk.glade.XML(self.gladeFile)
        self.tree.signal_autoconnect(self)

        # set up storage backend:
        self.storage = FileStorageBackend()

        # set up link history:
        self.linkHistory = LinkHistory(self)

        # set up menus for back/forward buttons:
        btnGoBack = self.tree.get_widget("btnGoBack")
        self.backMenu = gtk.Menu()
        btnGoBack.set_menu(self.backMenu)

        btnGoForward = self.tree.get_widget("btnGoForward")
        self.forwardMenu = gtk.Menu()
        btnGoForward.set_menu(self.forwardMenu)

        # set up HTML viewer widget:
        self.viewer = HtmlViewer()
        self.viewer.setLinkHandler(self.linkHandler)
        self.viewer.getWidget().show()

        # remove the TextView from ScrolledWindow but keep it for later:
        viewerParent = self.tree.get_widget('mainScrollWin')
        self.textView = viewerParent.get_children()[0]
        viewerParent.remove(self.textView)
        # instead, add the HTML viewer widget:
        viewerParent.add(self.viewer.getWidget())

        # set up text view:
        fontName = "Monospace"
        pangoFont = pango.FontDescription(fontName)
        self.textView.modify_font(pangoFont)

        # add TextBuffer for text view:
        self.textBuffer = gtk.TextBuffer(None)
        self.textView.set_buffer(self.textBuffer)

        # display start page:
        self.displayMarkdown('index')

    def on_mainWindow_delete_event (self, widget, dummy):
        gtk.main_quit()

    def on_miQuit_activate (self, dummy):
        gtk.main_quit()

    def on_btnEdit_clicked (self, widget):
        if self.editMode:
            if self.textChanged:
                print "(unsaved changes left)"
                parentWin = self.tree.get_widget("mainWindow")
                saveDialog = gtk.MessageDialog(parentWin, gtk.DIALOG_MODAL,
                    gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO,
                    "There are unsaved changes.")
                saveDialog.format_secondary_text("Do you want to save?")
                saveDialog.set_default_response(gtk.RESPONSE_YES)

                result = saveDialog.run()
                saveDialog.destroy()
                if result == gtk.RESPONSE_YES:
                    print "(do save)"
                    self.on_btnSave_clicked(None)
                else:
                    print "(don't save)"

            print "(back to view)"
            parent = self.tree.get_widget('mainScrollWin')
            child = parent.get_children()[0]
            assert(child == self.textView)
            parent.remove(child)

            self.textBuffer.disconnect(self.changeHandlerId)
            self.changeHandlerId = None
            self.tree.get_widget('btnSave').set_property('sensitive', False)
            self.tree.get_widget('miSave').set_property('sensitive', False)
            self.displayMarkdown(self.currentPage)

            parent.add(self.viewer.getWidget())
            self.tree.get_widget('btnEdit').set_property('stock_id', 'gtk-edit')
            self.editMode = False
        else:
            print "(edit)"
            parent = self.tree.get_widget('mainScrollWin')
            child = parent.get_children()[0]
            assert(child == self.viewer.getWidget())
            parent.remove(child)

            # load page content:
            text = self.storage.getPageContent(self.currentPage)
            self.textBuffer.set_text(text)
            self.textChanged = False
            self.changeHandlerId = self.textBuffer.connect('changed', self.on_textBuffer_changed)

            parent.add(self.textView)
            self.tree.get_widget('btnEdit').set_property('stock_id', 'gtk-ok')
            self.editMode = True

    def on_btnSave_clicked (self, widget):
        print "(save)"
        text = self.textBuffer.get_text(*self.textBuffer.get_bounds())
        self.storage.savePageContent(self.currentPage, text)
        self.textChanged = False
        self.tree.get_widget('btnSave').set_property('sensitive', False)
        self.tree.get_widget('miSave').set_property('sensitive', False)

    def on_miSave_activate (self, dummy):
        print "(miSave)"
        if self.editMode:
            self.on_btnSave_clicked(dummy)

    def on_btnHome_clicked (self, widget):
        print "(home)"
        if not(self.editMode): # TODO: what to do if we're in edit mode?
            self.displayMarkdown('index')

    def on_textBuffer_changed (self, textBuffer):
        self.textChanged = True
        self.tree.get_widget('btnSave').set_property('sensitive', True)
        self.tree.get_widget('miSave').set_property('sensitive', True)

    def on_btnGoBack_clicked (self, widget):
        print "(go back)"
        self.linkHistory.goBack()

    def on_btnGoForward_clicked (self, widget):
        print "(go forward)"
        self.linkHistory.goForward()

    def on_backMenuItem_activate (self, item, position):
        print "(back menu item at pos. %d)" % position
        self.linkHistory.goBack(position)

    def on_forwardMenuItem_activate (self, item, position):
        print "(forward menu item at pos. %d)" % position
        self.linkHistory.goForward(position)

    def setHistoryButtonState (self, backEnabled, forwardEnabled):
        self.tree.get_widget('btnGoBack').set_property('sensitive', backEnabled)
        self.tree.get_widget('btnGoForward').set_property('sensitive', forwardEnabled)

        # delete all entries from back button menu:
        for mi in self.backMenu.get_children():
            self.backMenu.remove(mi)

        # add current entries to back button menu:
        itemPos = 1
        for page in self.linkHistory.getBackPages():
            mi = gtk.MenuItem(page)
            mi.connect('activate', self.on_backMenuItem_activate, itemPos)
            mi.show()
            self.backMenu.append(mi)
            itemPos = itemPos + 1

        # delete all entries from forward button menu:
        for mi in self.forwardMenu.get_children():
            self.forwardMenu.remove(mi)

        # add current entries to forward button menu:
        itemPos = 1
        for page in self.linkHistory.getForwardPages():
            mi = gtk.MenuItem(page)
            mi.connect('activate', self.on_forwardMenuItem_activate, itemPos)
            mi.show()
            self.forwardMenu.append(mi)
            itemPos = itemPos + 1

    def linkHandler (self, url):
        """Is called when a link is clicked in HTML view"""
        print "link clicked (%s)" % url
        if url.startswith('wiki://'):
            wikiword = url[7:]
            print "(internal link to '%s')" % wikiword

            # create new page if necessary:
            if not(self.storage.pageExists(wikiword)):
                self.storage.createNewPage(wikiword)
                # TODO: maybe switch to edit mode here?

            self.displayMarkdown(wikiword)
        else:
            os.system("xdg-open '%s' &" % url)

    def wikiwordToHtmlLink (self, wikiword):
        """ Returns an HTML link tag for the given wikiword. """
        if self.storage.pageExists(wikiword):
            return "<a class='wikilink' href='wiki://%s'>%s</a>" % (wikiword, wikiword)
        else:
            return "<a class='wikilinkbroken' href='wiki://%s'>%s</a>" % (wikiword, wikiword)

    # TODO: maybe use another syntax for wiki links.
    # See http://boodler.org/wiki/show/Markdown/ for an idea
    def convertWikiLinks (self, html):
        """ Converts Wiki links in the given HTML text to HTML tags """
        newHtml = re.sub("\[\[([\w ]+)\]\]",
            lambda x: self.wikiwordToHtmlLink(x.groups()[0]), html)
        return newHtml

    def displayMarkdown (self, wikiword):
        """ Convert the Markdown+WikiLink text to HTML, and display the HTML """
        filename = self.storage.pageToFile(wikiword)
        cmd = "perl Markdown.pl < '%s'" % filename
        html = os.popen(cmd).read()
        if (html):
            html = self.convertWikiLinks(html)
            html = """<html>
<head>
<title>%s</title>
<style type="text/css">
a { color:#6666FF; font-style: italic; }
a:after { content:" (ext)"; }
.wikilink { color:#0000FF; font-style: normal; }
.wikilink:after { content:""; }
.wikilinkbroken { color:#FF0000; font-style: normal; }
.wikilinkbroken:after { content:""; }
</style>

</head>
<body>
%s
</body>
</html>
""" % (wikiword, html)
            self.viewer.setHTML(html)
            self.currentPage = wikiword
            self.tree.get_widget("lblStatusBar").set_label("<i>%s</i>" % wikiword)
            self.linkHistory.pushPageName(wikiword)