From 0e2a08c4ceb2a083ec648e3fa84bfbeb6b777bf7 Mon Sep 17 00:00:00 2001 From: Shlomi Fish Date: Fri, 17 Feb 2017 16:18:20 +0200 Subject: [PATCH] Create a base class - refactoring. --- pysollib/tile/tkhtml.py | 237 ++--------------------------------- pysollib/tk/tkhtml.py | 237 ++--------------------------------- pysollib/ui/tktile/tkhtml.py | 230 +++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 460 deletions(-) diff --git a/pysollib/tile/tkhtml.py b/pysollib/tile/tkhtml.py index d118abd1..1d446a63 100644 --- a/pysollib/tile/tkhtml.py +++ b/pysollib/tile/tkhtml.py @@ -36,25 +36,26 @@ if __name__ == '__main__': gettext.install('pysol', d, unicode=True) # PySol imports -from pysollib.mygettext import _, n_ -from pysollib.mfxutil import Struct, openURL -from pysollib.settings import TITLE +from pysollib.mygettext import _ +from pysollib.mfxutil import Struct # Toolkit imports -from pysollib.ui.tktile.tkutil import bind, unbind_destroy from tkwidget import MfxMessageDialog from statusbar import HtmlStatusbar -from pysollib.ui.tktile.tkhtml import REMOTE_PROTOCOLS, tkHTMLWriter, tkHTMLParser +from pysollib.ui.tktile.tkhtml import Base_HTMLViewer, REMOTE_PROTOCOLS, tkHTMLWriter, tkHTMLParser # ************************************************************************ # * # ************************************************************************ -class HTMLViewer: +class HTMLViewer(Base_HTMLViewer): symbols_fn = {} # filenames, loaded in Application.loadImages3 symbols_img = {} + def _calc_MfxMessageDialog(self): + return MfxMessageDialog + def __init__(self, parent, app=None, home=None): self.parent = parent self.app = app @@ -120,230 +121,6 @@ class HTMLViewer: self.initBindings() - def initBindings(self): - w = self.parent - bind(w, "WM_DELETE_WINDOW", self.destroy) - bind(w, "", self.destroy) - bind(w, "", self.page_up) - bind(w, "", self.page_down) - bind(w, "", self.unit_up) - bind(w, "", self.unit_down) - bind(w, "", self.scroll_top) - bind(w, "", self.scroll_top) - bind(w, "", self.scroll_bottom) - bind(w, "", self.goBack) - - def destroy(self, *event): - unbind_destroy(self.parent) - try: - self.parent.wm_withdraw() - except: pass - try: - self.parent.destroy() - except: pass - self.parent = None - - def _yview(self, *args): - self.text.yview(*args) - return 'break' - - def page_up(self, *event): - return self._yview('scroll', -1, 'page') - def page_down(self, *event): - return self._yview('scroll', 1, 'page') - def unit_up(self, *event): - return self._yview('scroll', -1, 'unit') - def unit_down(self, *event): - return self._yview('scroll', 1, 'unit') - def scroll_top(self, *event): - return self._yview('moveto', 0) - def scroll_bottom(self, *event): - return self._yview('moveto', 1) - - # locate a file relative to the current self.url - def basejoin(self, url, baseurl=None, relpath=1): - if baseurl is None: - baseurl = self.url - if 0: - import urllib - url = urllib.pathname2url(url) - if relpath and self.url: - url = urllib.basejoin(baseurl, url) - else: - url = os.path.normpath(url) - if relpath and baseurl and not os.path.isabs(url): - h1, t1 = os.path.split(url) - h2, t2 = os.path.split(baseurl) - if cmp(h1, h2) != 0: - url = os.path.join(h2, h1, t1) - url = os.path.normpath(url) - return url - - def normurl(self, url, with_protocol=True): - for p in REMOTE_PROTOCOLS: - if url.startswith(p): - break - else: - url = self.basejoin(url) - if with_protocol: - if os.name == 'nt': - url = url.replace('\\', '/') - url = 'file://'+url - return url - - def openfile(self, url): - if url[-1:] == "/" or os.path.isdir(url): - url = os.path.join(url, "index.html") - url = os.path.normpath(url) - return open(url, "rb"), url - - def display(self, url, add=1, relpath=1, xview=0, yview=0): - # for some reason we have to stop the PySol demo - # (is this a multithread problem with Tkinter ?) - if self.app and self.app.game: - self.app.game.stopDemo() - ##self.app.game._cancelDrag() - ##pass - - # ftp: and http: would work if we use urllib, but this widget is - # far too limited to display anything but our documentation... - for p in REMOTE_PROTOCOLS: - if url.startswith(p): - if not openURL(url): - self.errorDialog(TITLE + _('''HTML limitation: -The %s protocol is not supported yet. - -Please use your standard web browser -to open the following URL: -%s -''') % (p, url)) - return - - # locate the file relative to the current url - url = self.basejoin(url, relpath=relpath) - - # read the file - try: - file = None - if 0: - import urllib - file = urllib.urlopen(url) - else: - file, url = self.openfile(url) - data = file.read() - file.close() - file = None - except Exception, ex: - if file: file.close() - self.errorDialog(_("Unable to service request:\n") + url + "\n\n" + str(ex)) - return - except: - if file: file.close() - self.errorDialog(_("Unable to service request:\n") + url) - return - - self.url = url - if self.home is None: - self.home = self.url - if add: - self.addHistory(self.url, xview=xview, yview=yview) - - ##print self.history.index, self.history.list - if self.history.index > 1: - self.backButton.config(state="normal") - else: - self.backButton.config(state="disabled") - if self.history.index < len(self.history.list): - self.forwardButton.config(state="normal") - else: - self.forwardButton.config(state="disabled") - - old_c1, old_c2 = self.defcursor, self.handcursor - self.defcursor = self.handcursor = "watch" - self.text.config(cursor=self.defcursor) - self.text.update_idletasks() - ##self.frame.config(cursor=self.defcursor) - ##self.frame.update_idletasks() - self.text.config(state="normal") - self.text.delete("1.0", "end") - ##self.images = {} - writer = tkHTMLWriter(self.text, self, self.app) - fmt = formatter.AbstractFormatter(writer) - parser = tkHTMLParser(fmt) - parser.feed(data) - parser.close() - self.text.config(state="disabled") - if 0.0 <= xview <= 1.0: - self.text.xview_moveto(xview) - if 0.0 <= yview <= 1.0: - self.text.yview_moveto(yview) - self.parent.wm_title(parser.title) - self.parent.wm_iconname(parser.title) - self.defcursor, self.handcursor = old_c1, old_c2 - self.text.config(cursor=self.defcursor) - ##self.frame.config(cursor=self.defcursor) - - def addHistory(self, url, xview=0, yview=0): - if url not in self.visited_urls: - self.visited_urls.append(url) - if self.history.index > 0: - u, xv, yv = self.history.list[self.history.index-1] - if cmp(u, url) == 0: - self.updateHistoryXYView() - return - del self.history.list[self.history.index : ] - self.history.list.append((url, xview, yview)) - self.history.index = self.history.index + 1 - - def updateHistoryXYView(self): - if self.history.index > 0: - url, xview, yview = self.history.list[self.history.index-1] - xview = self.text.xview()[0] - yview = self.text.yview()[0] - self.history.list[self.history.index-1] = (url, xview, yview) - - def goBack(self, *event): - if self.history.index > 1: - self.updateHistoryXYView() - self.history.index = self.history.index - 1 - url, xview, yview = self.history.list[self.history.index-1] - self.display(url, add=0, relpath=0, xview=xview, yview=yview) - - def goForward(self, *event): - if self.history.index < len(self.history.list): - self.updateHistoryXYView() - url, xview, yview = self.history.list[self.history.index] - self.history.index = self.history.index + 1 - self.display(url, add=0, relpath=0, xview=xview, yview=yview) - - def goHome(self, *event): - if self.home and cmp(self.home, self.url) != 0: - self.updateHistoryXYView() - self.display(self.home, relpath=0) - - def errorDialog(self, msg): - d = MfxMessageDialog(self.parent, title=TITLE+" HTML Problem", - text=msg, - ##bitmap="warning", # FIXME: this interp don't have images - strings=(_("&OK"),), default=0) - - def getImage(self, fn): - if fn in self.images: - return self.images[fn] - try: - img = Tkinter.PhotoImage(master=self.parent, file=fn) - except: - img = None - self.images[fn] = img - return img - - def showImage(self, src, alt, ismap, align, width, height): - url = self.basejoin(src) - img = self.getImage(url) - if img: - self.text.image_create(index="insert", image=img, padx=0, pady=0) - - # ************************************************************************ # * diff --git a/pysollib/tk/tkhtml.py b/pysollib/tk/tkhtml.py index 9c327361..2d3a3754 100644 --- a/pysollib/tk/tkhtml.py +++ b/pysollib/tk/tkhtml.py @@ -35,25 +35,26 @@ if __name__ == '__main__': gettext.install('pysol', d, unicode=True) # PySol imports -from pysollib.mygettext import _, n_ -from pysollib.mfxutil import Struct, openURL -from pysollib.settings import TITLE +from pysollib.mygettext import _ +from pysollib.mfxutil import Struct # Toolkit imports -from pysollib.ui.tktile.tkutil import bind, unbind_destroy from tkwidget import MfxMessageDialog from statusbar import HtmlStatusbar -from pysollib.ui.tktile.tkhtml import REMOTE_PROTOCOLS, tkHTMLWriter, tkHTMLParser +from pysollib.ui.tktile.tkhtml import Base_HTMLViewer, REMOTE_PROTOCOLS, tkHTMLWriter, tkHTMLParser # ************************************************************************ # * # ************************************************************************ -class HTMLViewer: +class HTMLViewer(Base_HTMLViewer): symbols_fn = {} # filenames, loaded in Application.loadImages3 symbols_img = {} + def _calc_MfxMessageDialog(self): + return MfxMessageDialog + def __init__(self, parent, app=None, home=None): self.parent = parent self.app = app @@ -115,230 +116,6 @@ class HTMLViewer: self.initBindings() - def initBindings(self): - w = self.parent - bind(w, "WM_DELETE_WINDOW", self.destroy) - bind(w, "", self.destroy) - bind(w, "", self.page_up) - bind(w, "", self.page_down) - bind(w, "", self.unit_up) - bind(w, "", self.unit_down) - bind(w, "", self.scroll_top) - bind(w, "", self.scroll_top) - bind(w, "", self.scroll_bottom) - bind(w, "", self.goBack) - - def destroy(self, *event): - unbind_destroy(self.parent) - try: - self.parent.wm_withdraw() - except: pass - try: - self.parent.destroy() - except: pass - self.parent = None - - def _yview(self, *args): - self.text.yview(*args) - return 'break' - - def page_up(self, *event): - return self._yview('scroll', -1, 'page') - def page_down(self, *event): - return self._yview('scroll', 1, 'page') - def unit_up(self, *event): - return self._yview('scroll', -1, 'unit') - def unit_down(self, *event): - return self._yview('scroll', 1, 'unit') - def scroll_top(self, *event): - return self._yview('moveto', 0) - def scroll_bottom(self, *event): - return self._yview('moveto', 1) - - # locate a file relative to the current self.url - def basejoin(self, url, baseurl=None, relpath=1): - if baseurl is None: - baseurl = self.url - if 0: - import urllib - url = urllib.pathname2url(url) - if relpath and self.url: - url = urllib.basejoin(baseurl, url) - else: - url = os.path.normpath(url) - if relpath and baseurl and not os.path.isabs(url): - h1, t1 = os.path.split(url) - h2, t2 = os.path.split(baseurl) - if cmp(h1, h2) != 0: - url = os.path.join(h2, h1, t1) - url = os.path.normpath(url) - return url - - def normurl(self, url, with_protocol=True): - for p in REMOTE_PROTOCOLS: - if url.startswith(p): - break - else: - url = self.basejoin(url) - if with_protocol: - if os.name == 'nt': - url = url.replace('\\', '/') - url = 'file://'+url - return url - - def openfile(self, url): - if url[-1:] == "/" or os.path.isdir(url): - url = os.path.join(url, "index.html") - url = os.path.normpath(url) - return open(url, "rb"), url - - def display(self, url, add=1, relpath=1, xview=0, yview=0): - # for some reason we have to stop the PySol demo - # (is this a multithread problem with Tkinter ?) - if self.app and self.app.game: - self.app.game.stopDemo() - ##self.app.game._cancelDrag() - ##pass - - # ftp: and http: would work if we use urllib, but this widget is - # far too limited to display anything but our documentation... - for p in REMOTE_PROTOCOLS: - if url.startswith(p): - if not openURL(url): - self.errorDialog(TITLE + _('''HTML limitation: -The %s protocol is not supported yet. - -Please use your standard web browser -to open the following URL: -%s -''') % (p, url)) - return - - # locate the file relative to the current url - url = self.basejoin(url, relpath=relpath) - - # read the file - try: - file = None - if 0: - import urllib - file = urllib.urlopen(url) - else: - file, url = self.openfile(url) - data = file.read() - file.close() - file = None - except Exception, ex: - if file: file.close() - self.errorDialog(_("Unable to service request:\n") + url + "\n\n" + str(ex)) - return - except: - if file: file.close() - self.errorDialog(_("Unable to service request:\n") + url) - return - - self.url = url - if self.home is None: - self.home = self.url - if add: - self.addHistory(self.url, xview=xview, yview=yview) - - ##print self.history.index, self.history.list - if self.history.index > 1: - self.backButton.config(state="normal") - else: - self.backButton.config(state="disabled") - if self.history.index < len(self.history.list): - self.forwardButton.config(state="normal") - else: - self.forwardButton.config(state="disabled") - - old_c1, old_c2 = self.defcursor, self.handcursor - self.defcursor = self.handcursor = "watch" - self.text.config(cursor=self.defcursor) - self.text.update_idletasks() - ##self.frame.config(cursor=self.defcursor) - ##self.frame.update_idletasks() - self.text.config(state="normal") - self.text.delete("1.0", "end") - ##self.images = {} - writer = tkHTMLWriter(self.text, self, self.app) - fmt = formatter.AbstractFormatter(writer) - parser = tkHTMLParser(fmt) - parser.feed(data) - parser.close() - self.text.config(state="disabled") - if 0.0 <= xview <= 1.0: - self.text.xview_moveto(xview) - if 0.0 <= yview <= 1.0: - self.text.yview_moveto(yview) - self.parent.wm_title(parser.title) - self.parent.wm_iconname(parser.title) - self.defcursor, self.handcursor = old_c1, old_c2 - self.text.config(cursor=self.defcursor) - ##self.frame.config(cursor=self.defcursor) - - def addHistory(self, url, xview=0, yview=0): - if url not in self.visited_urls: - self.visited_urls.append(url) - if self.history.index > 0: - u, xv, yv = self.history.list[self.history.index-1] - if cmp(u, url) == 0: - self.updateHistoryXYView() - return - del self.history.list[self.history.index : ] - self.history.list.append((url, xview, yview)) - self.history.index = self.history.index + 1 - - def updateHistoryXYView(self): - if self.history.index > 0: - url, xview, yview = self.history.list[self.history.index-1] - xview = self.text.xview()[0] - yview = self.text.yview()[0] - self.history.list[self.history.index-1] = (url, xview, yview) - - def goBack(self, *event): - if self.history.index > 1: - self.updateHistoryXYView() - self.history.index = self.history.index - 1 - url, xview, yview = self.history.list[self.history.index-1] - self.display(url, add=0, relpath=0, xview=xview, yview=yview) - - def goForward(self, *event): - if self.history.index < len(self.history.list): - self.updateHistoryXYView() - url, xview, yview = self.history.list[self.history.index] - self.history.index = self.history.index + 1 - self.display(url, add=0, relpath=0, xview=xview, yview=yview) - - def goHome(self, *event): - if self.home and cmp(self.home, self.url) != 0: - self.updateHistoryXYView() - self.display(self.home, relpath=0) - - def errorDialog(self, msg): - d = MfxMessageDialog(self.parent, title=TITLE+" HTML Problem", - text=msg, - ##bitmap="warning", # FIXME: this interp don't have images - strings=(_("&OK"),), default=0) - - def getImage(self, fn): - if fn in self.images: - return self.images[fn] - try: - img = Tkinter.PhotoImage(master=self.parent, file=fn) - except: - img = None - self.images[fn] = img - return img - - def showImage(self, src, alt, ismap, align, width, height): - url = self.basejoin(src) - img = self.getImage(url) - if img: - self.text.image_create(index="insert", image=img, padx=0, pady=0) - - # ************************************************************************ # * diff --git a/pysollib/ui/tktile/tkhtml.py b/pysollib/ui/tktile/tkhtml.py index 91bb94b5..d14212e3 100644 --- a/pysollib/ui/tktile/tkhtml.py +++ b/pysollib/ui/tktile/tkhtml.py @@ -21,7 +21,14 @@ ## ##---------------------------------------------------------------------------## +import os import htmllib, formatter +import Tkinter + +from pysollib.ui.tktile.tkutil import bind, unbind_destroy +from pysollib.mygettext import _ +from pysollib.settings import TITLE +from pysollib.mfxutil import openURL REMOTE_PROTOCOLS = ("ftp:", "gopher:", "http:", "mailto:", "news:", "telnet:") @@ -189,3 +196,226 @@ class tkHTMLParser(htmllib.HTMLParser): def handle_image(self, src, alt, ismap, align, width, height): self.formatter.writer.viewer.showImage(src, alt, ismap, align, width, height) +class Base_HTMLViewer: + def initBindings(self): + w = self.parent + bind(w, "WM_DELETE_WINDOW", self.destroy) + bind(w, "", self.destroy) + bind(w, "", self.page_up) + bind(w, "", self.page_down) + bind(w, "", self.unit_up) + bind(w, "", self.unit_down) + bind(w, "", self.scroll_top) + bind(w, "", self.scroll_top) + bind(w, "", self.scroll_bottom) + bind(w, "", self.goBack) + + def destroy(self, *event): + unbind_destroy(self.parent) + try: + self.parent.wm_withdraw() + except: pass + try: + self.parent.destroy() + except: pass + self.parent = None + + def _yview(self, *args): + self.text.yview(*args) + return 'break' + + def page_up(self, *event): + return self._yview('scroll', -1, 'page') + def page_down(self, *event): + return self._yview('scroll', 1, 'page') + def unit_up(self, *event): + return self._yview('scroll', -1, 'unit') + def unit_down(self, *event): + return self._yview('scroll', 1, 'unit') + def scroll_top(self, *event): + return self._yview('moveto', 0) + def scroll_bottom(self, *event): + return self._yview('moveto', 1) + + # locate a file relative to the current self.url + def basejoin(self, url, baseurl=None, relpath=1): + if baseurl is None: + baseurl = self.url + if 0: + import urllib + url = urllib.pathname2url(url) + if relpath and self.url: + url = urllib.basejoin(baseurl, url) + else: + url = os.path.normpath(url) + if relpath and baseurl and not os.path.isabs(url): + h1, t1 = os.path.split(url) + h2, t2 = os.path.split(baseurl) + if cmp(h1, h2) != 0: + url = os.path.join(h2, h1, t1) + url = os.path.normpath(url) + return url + + def normurl(self, url, with_protocol=True): + for p in REMOTE_PROTOCOLS: + if url.startswith(p): + break + else: + url = self.basejoin(url) + if with_protocol: + if os.name == 'nt': + url = url.replace('\\', '/') + url = 'file://'+url + return url + + def openfile(self, url): + if url[-1:] == "/" or os.path.isdir(url): + url = os.path.join(url, "index.html") + url = os.path.normpath(url) + return open(url, "rb"), url + + def display(self, url, add=1, relpath=1, xview=0, yview=0): + # for some reason we have to stop the PySol demo + # (is this a multithread problem with Tkinter ?) + if self.app and self.app.game: + self.app.game.stopDemo() + ##self.app.game._cancelDrag() + ##pass + + # ftp: and http: would work if we use urllib, but this widget is + # far too limited to display anything but our documentation... + for p in REMOTE_PROTOCOLS: + if url.startswith(p): + if not openURL(url): + self.errorDialog(TITLE + _('''HTML limitation: +The %s protocol is not supported yet. + +Please use your standard web browser +to open the following URL: +%s +''') % (p, url)) + return + + # locate the file relative to the current url + url = self.basejoin(url, relpath=relpath) + + # read the file + try: + file = None + if 0: + import urllib + file = urllib.urlopen(url) + else: + file, url = self.openfile(url) + data = file.read() + file.close() + file = None + except Exception, ex: + if file: file.close() + self.errorDialog(_("Unable to service request:\n") + url + "\n\n" + str(ex)) + return + except: + if file: file.close() + self.errorDialog(_("Unable to service request:\n") + url) + return + + self.url = url + if self.home is None: + self.home = self.url + if add: + self.addHistory(self.url, xview=xview, yview=yview) + + ##print self.history.index, self.history.list + if self.history.index > 1: + self.backButton.config(state="normal") + else: + self.backButton.config(state="disabled") + if self.history.index < len(self.history.list): + self.forwardButton.config(state="normal") + else: + self.forwardButton.config(state="disabled") + + old_c1, old_c2 = self.defcursor, self.handcursor + self.defcursor = self.handcursor = "watch" + self.text.config(cursor=self.defcursor) + self.text.update_idletasks() + ##self.frame.config(cursor=self.defcursor) + ##self.frame.update_idletasks() + self.text.config(state="normal") + self.text.delete("1.0", "end") + ##self.images = {} + writer = tkHTMLWriter(self.text, self, self.app) + fmt = formatter.AbstractFormatter(writer) + parser = tkHTMLParser(fmt) + parser.feed(data) + parser.close() + self.text.config(state="disabled") + if 0.0 <= xview <= 1.0: + self.text.xview_moveto(xview) + if 0.0 <= yview <= 1.0: + self.text.yview_moveto(yview) + self.parent.wm_title(parser.title) + self.parent.wm_iconname(parser.title) + self.defcursor, self.handcursor = old_c1, old_c2 + self.text.config(cursor=self.defcursor) + ##self.frame.config(cursor=self.defcursor) + + def addHistory(self, url, xview=0, yview=0): + if url not in self.visited_urls: + self.visited_urls.append(url) + if self.history.index > 0: + u, xv, yv = self.history.list[self.history.index-1] + if cmp(u, url) == 0: + self.updateHistoryXYView() + return + del self.history.list[self.history.index : ] + self.history.list.append((url, xview, yview)) + self.history.index = self.history.index + 1 + + def updateHistoryXYView(self): + if self.history.index > 0: + url, xview, yview = self.history.list[self.history.index-1] + xview = self.text.xview()[0] + yview = self.text.yview()[0] + self.history.list[self.history.index-1] = (url, xview, yview) + + def goBack(self, *event): + if self.history.index > 1: + self.updateHistoryXYView() + self.history.index = self.history.index - 1 + url, xview, yview = self.history.list[self.history.index-1] + self.display(url, add=0, relpath=0, xview=xview, yview=yview) + + def goForward(self, *event): + if self.history.index < len(self.history.list): + self.updateHistoryXYView() + url, xview, yview = self.history.list[self.history.index] + self.history.index = self.history.index + 1 + self.display(url, add=0, relpath=0, xview=xview, yview=yview) + + def goHome(self, *event): + if self.home and cmp(self.home, self.url) != 0: + self.updateHistoryXYView() + self.display(self.home, relpath=0) + + def errorDialog(self, msg): + d = self._calc_MfxMessageDialog()(self.parent, title=TITLE+" HTML Problem", + text=msg, + ##bitmap="warning", # FIXME: this interp don't have images + strings=(_("&OK"),), default=0) + + def getImage(self, fn): + if fn in self.images: + return self.images[fn] + try: + img = Tkinter.PhotoImage(master=self.parent, file=fn) + except: + img = None + self.images[fn] = img + return img + + def showImage(self, src, alt, ismap, align, width, height): + url = self.basejoin(src) + img = self.getImage(url) + if img: + self.text.image_create(index="insert", image=img, padx=0, pady=0)