PageRenderTime 57ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/pwiki/WikiHtmlView.py

https://bitbucket.org/xkjq/wikidpad_svn
Python | 739 lines | 635 code | 74 blank | 30 comment | 50 complexity | dae437934baf69b09c9aaf5977076a13 MD5 | raw file
Possible License(s): LGPL-2.1
  1. ## import hotshot
  2. ## _prof = hotshot.Profile("hotshot.prf")
  3. import traceback, os, os.path, re
  4. import wx, wx.html
  5. from WikiExceptions import *
  6. from .SystemInfo import isWindows, isOSX
  7. from . import wxHelper
  8. from .wxHelper import getAccelPairFromKeyDown, GUI_ID, wxKeyFunctionSink, \
  9. appendToMenuByMenuDesc
  10. from .MiscEvent import KeyFunctionSink
  11. from . import StringOps
  12. from StringOps import uniToGui, utf8Enc, utf8Dec, pathEnc, urlFromPathname, \
  13. urlQuote, pathnameFromUrl, flexibleUrlUnquote
  14. from .Configuration import MIDDLE_MOUSE_CONFIG_TO_TABMODE
  15. from . import OsAbstract
  16. from . import DocPages
  17. from .TempFileSet import TempFileSet
  18. from . import PluginManager
  19. # Try and load the html2 webview renderer
  20. try:
  21. WikiHtmlViewWK = None
  22. if wx.version().startswith(("2.9", "3")):
  23. import WikiHtmlView2
  24. else:
  25. WikiHtmlView2 = None
  26. try:
  27. import WikiHtmlViewWK
  28. except:
  29. WikiHtmlViewWK = None
  30. import ExceptionLogger
  31. ExceptionLogger.logOptionalComponentException("Initialize webkit HTML renderer")
  32. except:
  33. # traceback.print_exc()
  34. WikiHtmlView2 = None
  35. import ExceptionLogger
  36. ExceptionLogger.logOptionalComponentException("Initialize webkit HTML2 renderer")
  37. # Try and load Windows IE renderer
  38. if isWindows():
  39. try:
  40. import WikiHtmlViewIE
  41. except:
  42. import ExceptionLogger
  43. ExceptionLogger.logOptionalComponentException("Initialize IE HTML renderer")
  44. WikiHtmlViewIE = None
  45. else:
  46. WikiHtmlViewIE = None
  47. class LinkConverterForPreview:
  48. """
  49. Faked link dictionary for HTML exporter
  50. """
  51. def __init__(self, wikiDocument):
  52. self.wikiDocument = wikiDocument
  53. def getLinkForWikiWord(self, word, default = None):
  54. if self.wikiDocument.isDefinedWikiLinkTerm(word):
  55. return u"internaljump:wikipage/%s" % word
  56. else:
  57. return default
  58. def createWikiHtmlView(presenter, parent, ID):
  59. pvRenderer = presenter.getConfig().getint("main", "html_preview_renderer", 0)
  60. if WikiHtmlViewIE and pvRenderer in (1, 2):
  61. # Set preview renderer to 0 = Internal
  62. config = presenter.getConfig()
  63. config.set("main", "html_preview_renderer", "0")
  64. config.saveGlobalConfig()
  65. hvIe = WikiHtmlViewIE.WikiHtmlViewIE(presenter, parent, ID,
  66. pvRenderer == 2)
  67. # If no error occurred, set back to previous value
  68. config.set("main", "html_preview_renderer", str(pvRenderer))
  69. config.saveGlobalConfig()
  70. return hvIe
  71. elif WikiHtmlViewWK and pvRenderer == 3:
  72. return WikiHtmlViewWK.WikiHtmlViewWK(presenter, parent, ID)
  73. elif WikiHtmlView2 and pvRenderer == 4:
  74. return WikiHtmlView2.WikiHtmlView2(presenter, parent, ID)
  75. # Internal preview if nothing else wanted or possible
  76. return WikiHtmlView(presenter, parent, ID)
  77. class WikiHtmlView(wx.html.HtmlWindow):
  78. def __init__(self, presenter, parent, ID):
  79. wx.html.HtmlWindow.__init__(self, parent, ID)
  80. self.presenter = presenter
  81. self.presenterListener = wxKeyFunctionSink((
  82. ("loaded current wiki page", self.onLoadedCurrentWikiPage),
  83. ("reloaded current doc page", self.onReloadedCurrentPage),
  84. ("opened wiki", self.onOpenedWiki),
  85. ("closing current wiki", self.onClosingCurrentWiki)
  86. ), self.presenter.getMiscEvent())
  87. self.__sinkApp = wxKeyFunctionSink((
  88. ("options changed", self.onOptionsChanged),
  89. ), wx.GetApp().getMiscEvent())
  90. self.__sinkDocPage = wxKeyFunctionSink((
  91. ("updated wiki page", self.onUpdatedWikiPage),
  92. ("changed live text", self.onChangedLiveText)
  93. ), self.presenter.getCurrentDocPageProxyEvent())
  94. self.visible = False
  95. self.outOfSync = True # HTML content is out of sync with live content
  96. self.counterResizeIgnore = 0 # How often to ignore a size event
  97. self.deferredScrollPos = None # Used by scrollDeferred()
  98. self.currentLoadedWikiWord = None
  99. self.anchor = None # Name of anchor to jump to when view gets visible
  100. self.contextHref = None # Link href on which context menu was opened
  101. # TODO Should be changed to presenter as controller
  102. self.exporterInstance = PluginManager.getExporterTypeDict(
  103. self.presenter.getMainControl(), False)[u"html_single"][0]\
  104. (self.presenter.getMainControl())
  105. self._DEFAULT_FONT_SIZES = self.presenter.getMainControl().presentationExt.INTHTML_FONTSIZES
  106. # TODO More elegantly
  107. self.exporterInstance.exportType = u"html_previewWX"
  108. self.exporterInstance.styleSheet = u""
  109. self.exporterInstance.tempFileSet = TempFileSet()
  110. self._updateTempFilePrefPath()
  111. self.exporterInstance.setWikiDocument(
  112. self.presenter.getWikiDocument())
  113. self.exporterInstance.setLinkConverter(
  114. LinkConverterForPreview(self.presenter.getWikiDocument()))
  115. wx.EVT_KEY_DOWN(self, self.OnKeyDown)
  116. wx.EVT_KEY_UP(self, self.OnKeyUp)
  117. wx.EVT_SIZE(self, self.OnSize)
  118. wx.EVT_MENU(self, GUI_ID.CMD_CLIPBOARD_COPY, self.OnClipboardCopy)
  119. wx.EVT_MENU(self, GUI_ID.CMD_SELECT_ALL, lambda evt: self.SelectAll())
  120. wx.EVT_MENU(self, GUI_ID.CMD_ZOOM_IN, lambda evt: self.addZoom(1))
  121. wx.EVT_MENU(self, GUI_ID.CMD_ZOOM_OUT, lambda evt: self.addZoom(-1))
  122. wx.EVT_MENU(self, GUI_ID.CMD_ACTIVATE_THIS, self.OnActivateThis)
  123. wx.EVT_MENU(self, GUI_ID.CMD_ACTIVATE_NEW_TAB_THIS,
  124. self.OnActivateNewTabThis)
  125. wx.EVT_MENU(self, GUI_ID.CMD_ACTIVATE_NEW_TAB_BACKGROUND_THIS,
  126. self.OnActivateNewTabBackgroundThis)
  127. wx.EVT_MENU(self, GUI_ID.CMD_ACTIVATE_NEW_WINDOW_THIS,
  128. self.OnActivateNewWindowThis)
  129. wx.EVT_MENU(self, GUI_ID.CMD_OPEN_CONTAINING_FOLDER_THIS,
  130. self.OnOpenContainingFolderThis)
  131. self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
  132. wx.EVT_LEFT_DCLICK(self, self.OnLeftDClick)
  133. wx.EVT_MIDDLE_DOWN(self, self.OnMiddleDown)
  134. wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
  135. wx.EVT_MOTION(self, self.OnMouseMotion)
  136. def setLayerVisible(self, vis, scName=""):
  137. """
  138. Informs the widget if it is really visible on the screen or not
  139. """
  140. if not self.visible and vis:
  141. self.outOfSync = True # Just to be sure
  142. self.refresh()
  143. if not vis:
  144. self.exporterInstance.tempFileSet.clear()
  145. self.visible = vis
  146. if isWindows():
  147. _RE_RIGHT_FILE_URL = re.compile(u"file:/[a-zA-Z]:")
  148. def OnOpeningURL(self, typ, url):
  149. if url.startswith("file:"):
  150. if self._RE_RIGHT_FILE_URL.match(url):
  151. return wx.html.HTML_OPEN
  152. # At least under Windows, wxWidgets has another
  153. # opinion how a local file URL should look like
  154. # than Python.
  155. # The same processing is done already by the exporter
  156. # for WikidPad URL but not for URLs in HTML tags.
  157. p = pathnameFromUrl(url)
  158. url = wx.FileSystem.FileNameToURL(p)
  159. return url
  160. return wx.html.HTML_OPEN
  161. def close(self):
  162. self.Unbind(wx.EVT_SET_FOCUS)
  163. self.setLayerVisible(False)
  164. self.presenterListener.disconnect()
  165. self.__sinkApp.disconnect()
  166. self.__sinkDocPage.disconnect()
  167. # This doesn't work for wxPython 2.8 and newer, constants are missing
  168. # _DEFAULT_FONT_SIZES = (wx.html.HTML_FONT_SIZE_1, wx.html.HTML_FONT_SIZE_2,
  169. # wx.html.HTML_FONT_SIZE_3, wx.html.HTML_FONT_SIZE_4,
  170. # wx.html.HTML_FONT_SIZE_5, wx.html.HTML_FONT_SIZE_6,
  171. # wx.html.HTML_FONT_SIZE_7)
  172. # These are the Windows sizes
  173. # if isWindows():
  174. # _DEFAULT_FONT_SIZES = (7, 8, 10, 12, 16, 22, 30)
  175. # elif isOSX():
  176. # _DEFAULT_FONT_SIZES = (9, 12, 14, 18, 24, 30, 36)
  177. # else:
  178. # _DEFAULT_FONT_SIZES = (10, 12, 14, 16, 19, 24, 32)
  179. # For __WXGPE__ (?)
  180. # _DEFAULT_FONT_SIZES = (6, 7, 8, 9, 10, 12, 14)
  181. # For others
  182. # _DEFAULT_FONT_SIZES = (10, 12, 14, 16, 19, 24, 32)
  183. def refresh(self):
  184. ## _prof.start()
  185. # Store position of currently displayed page, if any
  186. if self.currentLoadedWikiWord:
  187. try:
  188. prevPage = self.presenter.getWikiDocument().getWikiPage(
  189. self.currentLoadedWikiWord)
  190. prevPage.setPresentation(self.getIntendedViewStart(), 3)
  191. except WikiWordNotFoundException, e:
  192. pass
  193. wikiPage = self.presenter.getDocPage()
  194. if isinstance(wikiPage,
  195. (DocPages.DataCarryingPage, DocPages.AliasWikiPage)) and \
  196. not wikiPage.checkFileSignatureAndMarkDirty():
  197. # Valid wiki page and invalid signature -> rebuild HTML page
  198. self.outOfSync = True
  199. if self.outOfSync:
  200. self.currentLoadedWikiWord = None
  201. if wikiPage is None:
  202. return # TODO Do anything else here?
  203. word = wikiPage.getWikiWord()
  204. if word is None:
  205. return # TODO Do anything else here?
  206. # Remove previously used temporary files
  207. self.exporterInstance.tempFileSet.clear()
  208. self.exporterInstance.buildStyleSheetList()
  209. self.currentLoadedWikiWord = word
  210. # content = self.presenter.getLiveText()
  211. html = self.exporterInstance.exportWikiPageToHtmlString(wikiPage)
  212. wx.GetApp().getInsertionPluginManager().taskEnd()
  213. # TODO Reset after open wiki
  214. zoom = self.presenter.getConfig().getint("main", "preview_zoom", 0)
  215. lx, ly = self.getIntendedViewStart()
  216. self.SetFonts("", "", [max(s + 2 * zoom, 1)
  217. for s in self._DEFAULT_FONT_SIZES])
  218. # print "-- refresh8", html.encode("mbcs", "ignore")
  219. self.SetPage(uniToGui(html))
  220. self.scrollDeferred(lx, ly)
  221. # traceback.print_stack()
  222. if self.anchor: # and self.HasAnchor(self.anchor):
  223. if self.HasAnchor(self.anchor):
  224. self.ScrollToAnchor(self.anchor)
  225. # Workaround because ScrollToAnchor scrolls too far
  226. # Here the real scroll position is needed so
  227. # getIntendedViewStart() is not called
  228. lx, ly = self.GetViewStart()
  229. self.scrollDeferred(lx, ly-1)
  230. else:
  231. self.scrollDeferred(0, 0)
  232. elif self.outOfSync:
  233. lx, ly = wikiPage.getPresentation()[3:5]
  234. self.scrollDeferred(lx, ly)
  235. self.anchor = None
  236. self.outOfSync = False
  237. ## _prof.stop()
  238. def gotoAnchor(self, anchor):
  239. self.anchor = anchor
  240. if self.visible:
  241. self.refresh()
  242. def GetSelectedText(self):
  243. return self.SelectionToText()
  244. def _updateTempFilePrefPath(self):
  245. wikiDocument = self.presenter.getWikiDocument()
  246. if wikiDocument is not None:
  247. self.exporterInstance.tempFileSet.setPreferredPath(
  248. wikiDocument.getWikiTempDir())
  249. else:
  250. self.exporterInstance.tempFileSet.setPreferredPath(None)
  251. def onLoadedCurrentWikiPage(self, miscevt):
  252. self.anchor = miscevt.get("anchor")
  253. self.outOfSync = True
  254. if self.visible:
  255. self.refresh()
  256. def onReloadedCurrentPage(self, miscevt):
  257. """
  258. Called when already loaded page should be loaded again, mainly
  259. interesting if a link with anchor is activated
  260. """
  261. anchor = miscevt.get("anchor")
  262. if anchor:
  263. self.gotoAnchor(anchor)
  264. # self.anchor = anchor
  265. # if self.visible:
  266. # self.refresh()
  267. def onOpenedWiki(self, miscevt):
  268. self.currentLoadedWikiWord = None
  269. self._updateTempFilePrefPath()
  270. self.exporterInstance.setWikiDocument(
  271. self.presenter.getWikiDocument())
  272. self.exporterInstance.setLinkConverter(
  273. LinkConverterForPreview(self.presenter.getWikiDocument()))
  274. def onClosingCurrentWiki(self, miscevt):
  275. if self.currentLoadedWikiWord:
  276. try:
  277. prevPage = self.presenter.getWikiDocument().getWikiPage(
  278. self.currentLoadedWikiWord)
  279. prevPage.setPresentation(self.getIntendedViewStart(), 3)
  280. except WikiWordNotFoundException, e:
  281. pass
  282. def onOptionsChanged(self, miscevt):
  283. self.outOfSync = True
  284. self._updateTempFilePrefPath()
  285. if self.visible:
  286. self.refresh()
  287. def onUpdatedWikiPage(self, miscevt):
  288. if self.presenter.getConfig().getboolean("main",
  289. "html_preview_reduceUpdateHandling", False):
  290. return
  291. self.outOfSync = True
  292. if self.visible:
  293. self.refresh()
  294. def onChangedLiveText(self, miscevt):
  295. self.outOfSync = True
  296. def scrollDeferred(self, lx, ly):
  297. if self.deferredScrollPos is not None:
  298. # An unprocessed _scrollAndThaw is in the message queue yet ->
  299. # just change scrollPos
  300. self.deferredScrollPos = (lx, ly)
  301. else:
  302. # Put new _scrollAndThaw into queue
  303. self.Freeze()
  304. self.deferredScrollPos = (lx, ly)
  305. wx.CallAfter(self._scrollAndThaw)
  306. def _scrollAndThaw(self):
  307. if wxHelper.isDead(self):
  308. return
  309. self.Scroll(self.deferredScrollPos[0], self.deferredScrollPos[1])
  310. self.Thaw()
  311. self.deferredScrollPos = None
  312. self.counterResizeIgnore = 0
  313. def OnSize(self, evt):
  314. lx, ly = self.getIntendedViewStart()
  315. self.scrollDeferred(lx, ly)
  316. evt.Skip()
  317. def OnSetFocus(self, evt):
  318. if self.visible:
  319. self.presenter.makeCurrent()
  320. self.refresh()
  321. def OnClipboardCopy(self, evt):
  322. text = self.SelectionToText()
  323. if len(text) == 0:
  324. return
  325. wxHelper.copyTextToClipboard(text)
  326. def OnLeftDClick(self, evt):
  327. pos = self.CalcUnscrolledPosition(evt.GetPosition())
  328. cell = self.GetInternalRepresentation().FindCellByPos(pos.x, pos.y)
  329. if cell is not None:
  330. linkInfo = cell.GetLink()
  331. if linkInfo is not None:
  332. evt.Skip()
  333. return
  334. pres = self.presenter
  335. mc = pres.getMainControl()
  336. paramDict = {"page": pres.getDocPage(), "presenter": pres,
  337. "main control": mc}
  338. mc.getUserActionCoord().reactOnUserEvent(
  339. u"mouse/leftdoubleclick/preview/body", paramDict)
  340. # self.presenter.switchSubControl("textedit")
  341. def OnMiddleDown(self, evt):
  342. pos = self.CalcUnscrolledPosition(evt.GetPosition())
  343. cell = self.GetInternalRepresentation().FindCellByPos(pos.x, pos.y)
  344. if cell is not None:
  345. linkInfo = cell.GetLink()
  346. if linkInfo is not None:
  347. if not evt.ControlDown():
  348. middleConfig = self.presenter.getConfig().getint("main",
  349. "mouse_middleButton_withoutCtrl", 2)
  350. else:
  351. middleConfig = self.presenter.getConfig().getint("main",
  352. "mouse_middleButton_withCtrl", 3)
  353. tabMode = MIDDLE_MOUSE_CONFIG_TO_TABMODE[middleConfig]
  354. self._activateLink(cell.GetLink().GetHref(), tabMode=tabMode)
  355. return
  356. evt.Skip()
  357. def OnLinkClicked(self, linkinfo):
  358. href = linkinfo.GetHref()
  359. evt = linkinfo.GetEvent()
  360. if evt.RightUp():
  361. self.contextHref = linkinfo.GetHref()
  362. menu = wx.Menu()
  363. if href.startswith(u"internaljump:wikipage/"):
  364. appendToMenuByMenuDesc(menu, _CONTEXT_MENU_INTERNAL_JUMP)
  365. else:
  366. appendToMenuByMenuDesc(menu, u"Activate;CMD_ACTIVATE_THIS")
  367. if href.startswith(u"file:") or \
  368. href.startswith(u"rel://"):
  369. appendToMenuByMenuDesc(menu,
  370. u"Open Containing Folder;"
  371. u"CMD_OPEN_CONTAINING_FOLDER_THIS")
  372. self.PopupMenuXY(menu, evt.GetX(), evt.GetY())
  373. else:
  374. # Jump to another wiki page
  375. # First check for an anchor. In URLs, anchors are always
  376. # separated by '#' regardless which character is used
  377. # in the wiki syntax (normally '!')
  378. # Now open wiki
  379. self._activateLink(href, tabMode=0)
  380. if isOSX():
  381. def GetViewStart(self):
  382. result = wx.html.HtmlWindow.GetViewStart(self)
  383. if isinstance(result, wx.Point):
  384. return (result.x, result.y)
  385. else:
  386. return result
  387. def getIntendedViewStart(self):
  388. """
  389. If a deferred scrolling waits for process, this returns the deferred
  390. scroll values instead of real view start
  391. """
  392. if self.deferredScrollPos is not None:
  393. return self.deferredScrollPos
  394. else:
  395. return tuple(self.GetViewStart())
  396. def _activateLink(self, href, tabMode=0):
  397. """
  398. Called if link was activated by clicking in the context menu,
  399. therefore only links starting with "internaljump:wikipage/" can be
  400. handled.
  401. tabMode -- 0:Same tab; 2: new tab in foreground; 3: new tab in background
  402. """
  403. if href.startswith(u"internaljump:wikipage/"):
  404. # Jump to another wiki page
  405. # First check for an anchor. In URLs, anchors are always
  406. # separated by '#' regardless which character is used
  407. # in the wiki syntax (normally '!')
  408. try:
  409. word, anchor = href[22:].split(u"#", 1)
  410. except ValueError:
  411. word = href[22:]
  412. anchor = None
  413. # open the wiki page
  414. if tabMode & 2:
  415. if tabMode == 6:
  416. # New Window
  417. presenter = self.presenter.getMainControl().\
  418. createNewDocPagePresenterTabInNewFrame()
  419. else:
  420. # New tab
  421. presenter = self.presenter.getMainControl().\
  422. createNewDocPagePresenterTab()
  423. presenter.switchSubControl("preview", False)
  424. else:
  425. # Same tab
  426. presenter = self.presenter
  427. presenter.openWikiPage(word, motionType="child", anchor=anchor)
  428. if not tabMode & 1:
  429. # Show in foreground
  430. # presenter.switchSubControl("preview", True)
  431. presenter.getMainControl().getMainAreaPanel().\
  432. showPresenter(presenter)
  433. presenter.SetFocus()
  434. # else:
  435. # presenter.switchSubControl("preview", False)
  436. elif href == u"internaljump:action/history/back":
  437. # Go back in history
  438. self.presenter.getMainControl().goBrowserBack()
  439. elif href.startswith(u"#"):
  440. anchor = href[1:]
  441. if self.HasAnchor(anchor):
  442. self.ScrollToAnchor(anchor)
  443. # Workaround because ScrollToAnchor scrolls too far
  444. # Here the real scroll position is needed so
  445. # getIntendedViewStart() is not called
  446. lx, ly = self.GetViewStart()
  447. self.scrollDeferred(lx, ly-1)
  448. else:
  449. self.scrollDeferred(0, 0)
  450. else:
  451. self.presenter.getMainControl().launchUrl(href)
  452. def OnActivateThis(self, evt):
  453. self._activateLink(self.contextHref, tabMode=0)
  454. def OnActivateNewTabThis(self, evt):
  455. self._activateLink(self.contextHref, tabMode=2)
  456. def OnActivateNewTabBackgroundThis(self, evt):
  457. self._activateLink(self.contextHref, tabMode=3)
  458. def OnActivateNewWindowThis(self, evt):
  459. self._activateLink(self.contextHref, tabMode=6)
  460. def OnOpenContainingFolderThis(self, evt):
  461. if not self.contextHref:
  462. return
  463. link = self.contextHref
  464. if link.startswith(u"rel://"):
  465. link = self.presenter.getWikiDocument().makeRelUrlAbsolute(link)
  466. if link.startswith(u"file:"):
  467. try:
  468. path = os.path.dirname(StringOps.pathnameFromUrl(link))
  469. if not os.path.exists(StringOps.longPathEnc(path)):
  470. self.presenter.displayErrorMessage(
  471. _(u"Folder does not exist"))
  472. return
  473. OsAbstract.startFile(self.presenter.getMainControl(),
  474. path)
  475. except IOError:
  476. pass # Error message?
  477. def OnKeyUp(self, evt):
  478. acc = getAccelPairFromKeyDown(evt)
  479. if acc == (wx.ACCEL_CTRL, ord('C')):
  480. # Consume original clipboard copy function
  481. pass
  482. else:
  483. evt.Skip()
  484. def addZoom(self, step):
  485. """
  486. Modify the zoom setting by step relative to current zoom in
  487. configuration.
  488. """
  489. zoom = self.presenter.getConfig().getint("main", "preview_zoom", 0)
  490. zoom += step
  491. self.presenter.getConfig().set("main", "preview_zoom", str(zoom))
  492. self.outOfSync = True
  493. self.refresh()
  494. def OnKeyDown(self, evt):
  495. acc = getAccelPairFromKeyDown(evt)
  496. if acc == (wx.ACCEL_CTRL, ord('+')) or \
  497. acc == (wx.ACCEL_CTRL, wx.WXK_NUMPAD_ADD):
  498. self.addZoom(1)
  499. elif acc == (wx.ACCEL_CTRL, ord('-')) or \
  500. acc == (wx.ACCEL_CTRL, wx.WXK_NUMPAD_SUBTRACT):
  501. self.addZoom(-1)
  502. else:
  503. evt.Skip()
  504. def OnMouseWheel(self, evt):
  505. if evt.ControlDown():
  506. if self.presenter.getConfig().getboolean(
  507. "main", "mouse_reverseWheelZoom", False):
  508. self.addZoom( -(evt.GetWheelRotation() // evt.GetWheelDelta()) )
  509. else:
  510. self.addZoom( evt.GetWheelRotation() // evt.GetWheelDelta() )
  511. else:
  512. evt.Skip()
  513. def OnMouseMotion(self, evt):
  514. evt.Skip()
  515. pos = self.CalcUnscrolledPosition(evt.GetPosition())
  516. irep = self.GetInternalRepresentation()
  517. if irep is None:
  518. cell = None
  519. else:
  520. cell = irep.FindCellByPos(pos.x, pos.y)
  521. callTip = u""
  522. status = u""
  523. if cell is not None:
  524. linkInfo = cell.GetLink()
  525. if linkInfo is not None:
  526. href = linkInfo.GetHref()
  527. if href.startswith(u"internaljump:wikipage/"):
  528. # Jump to another wiki page
  529. # First check for an anchor. In URLs, anchors are always
  530. # separated by '#' regardless which character is used
  531. # in the wiki syntax (normally '!')
  532. try:
  533. wikiWord, anchor = href[22:].split(u"#", 1)
  534. anchor = flexibleUrlUnquote(anchor)
  535. except ValueError:
  536. wikiWord = href[22:]
  537. anchor = None
  538. wikiWord = flexibleUrlUnquote(wikiWord)
  539. wikiDocument = self.presenter.getWikiDocument()
  540. if wikiDocument is None:
  541. return
  542. wikiWord = wikiDocument.getWikiPageNameForLinkTerm(wikiWord)
  543. if wikiWord is not None:
  544. propList = wikiDocument.getAttributeTriples(wikiWord,
  545. u"short_hint", None)
  546. if len(propList) > 0:
  547. callTip = propList[-1][2]
  548. status = _(u"Link to page: %s") % wikiWord
  549. else:
  550. status = href
  551. self.presenter.getMainControl().statusBar.SetStatusText(
  552. uniToGui(status), 0)
  553. self.SetToolTipString(callTip)
  554. _CONTEXT_MENU_INTERNAL_JUMP = \
  555. u"""
  556. Activate;CMD_ACTIVATE_THIS
  557. Activate New Tab;CMD_ACTIVATE_NEW_TAB_THIS
  558. Activate New Tab Backgrd.;CMD_ACTIVATE_NEW_TAB_BACKGROUND_THIS
  559. Activate New Window;CMD_ACTIVATE_NEW_WINDOW_THIS
  560. """
  561. # Entries to support i18n of context menus
  562. if False:
  563. N_(u"Activate")
  564. N_(u"Activate New Tab")
  565. N_(u"Activate New Tab Backgrd.")
  566. N_(u"Activate New Window")