PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/pwiki/WikiHtmlView.py

https://bitbucket.org/chriz/wikidpad
Python | 738 lines | 634 code | 74 blank | 30 comment | 50 complexity | 6351af8709c4574ee677fb0840ef6aa4 MD5 | raw file
Possible License(s): Apache-2.0, 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.refresh()
  320. def OnClipboardCopy(self, evt):
  321. text = self.SelectionToText()
  322. if len(text) == 0:
  323. return
  324. wxHelper.copyTextToClipboard(text)
  325. def OnLeftDClick(self, evt):
  326. pos = self.CalcUnscrolledPosition(evt.GetPosition())
  327. cell = self.GetInternalRepresentation().FindCellByPos(pos.x, pos.y)
  328. if cell is not None:
  329. linkInfo = cell.GetLink()
  330. if linkInfo is not None:
  331. evt.Skip()
  332. return
  333. pres = self.presenter
  334. mc = pres.getMainControl()
  335. paramDict = {"page": pres.getDocPage(), "presenter": pres,
  336. "main control": mc}
  337. mc.getUserActionCoord().reactOnUserEvent(
  338. u"mouse/leftdoubleclick/preview/body", paramDict)
  339. # self.presenter.switchSubControl("textedit")
  340. def OnMiddleDown(self, evt):
  341. pos = self.CalcUnscrolledPosition(evt.GetPosition())
  342. cell = self.GetInternalRepresentation().FindCellByPos(pos.x, pos.y)
  343. if cell is not None:
  344. linkInfo = cell.GetLink()
  345. if linkInfo is not None:
  346. if not evt.ControlDown():
  347. middleConfig = self.presenter.getConfig().getint("main",
  348. "mouse_middleButton_withoutCtrl", 2)
  349. else:
  350. middleConfig = self.presenter.getConfig().getint("main",
  351. "mouse_middleButton_withCtrl", 3)
  352. tabMode = MIDDLE_MOUSE_CONFIG_TO_TABMODE[middleConfig]
  353. self._activateLink(cell.GetLink().GetHref(), tabMode=tabMode)
  354. return
  355. evt.Skip()
  356. def OnLinkClicked(self, linkinfo):
  357. href = linkinfo.GetHref()
  358. evt = linkinfo.GetEvent()
  359. if evt.RightUp():
  360. self.contextHref = linkinfo.GetHref()
  361. menu = wx.Menu()
  362. if href.startswith(u"internaljump:wikipage/"):
  363. appendToMenuByMenuDesc(menu, _CONTEXT_MENU_INTERNAL_JUMP)
  364. else:
  365. appendToMenuByMenuDesc(menu, u"Activate;CMD_ACTIVATE_THIS")
  366. if href.startswith(u"file:") or \
  367. href.startswith(u"rel://"):
  368. appendToMenuByMenuDesc(menu,
  369. u"Open Containing Folder;"
  370. u"CMD_OPEN_CONTAINING_FOLDER_THIS")
  371. self.PopupMenuXY(menu, evt.GetX(), evt.GetY())
  372. else:
  373. # Jump to another wiki page
  374. # First check for an anchor. In URLs, anchors are always
  375. # separated by '#' regardless which character is used
  376. # in the wiki syntax (normally '!')
  377. # Now open wiki
  378. self._activateLink(href, tabMode=0)
  379. if isOSX():
  380. def GetViewStart(self):
  381. result = wx.html.HtmlWindow.GetViewStart(self)
  382. if isinstance(result, wx.Point):
  383. return (result.x, result.y)
  384. else:
  385. return result
  386. def getIntendedViewStart(self):
  387. """
  388. If a deferred scrolling waits for process, this returns the deferred
  389. scroll values instead of real view start
  390. """
  391. if self.deferredScrollPos is not None:
  392. return self.deferredScrollPos
  393. else:
  394. return tuple(self.GetViewStart())
  395. def _activateLink(self, href, tabMode=0):
  396. """
  397. Called if link was activated by clicking in the context menu,
  398. therefore only links starting with "internaljump:wikipage/" can be
  399. handled.
  400. tabMode -- 0:Same tab; 2: new tab in foreground; 3: new tab in background
  401. """
  402. if href.startswith(u"internaljump:wikipage/"):
  403. # Jump to another wiki page
  404. # First check for an anchor. In URLs, anchors are always
  405. # separated by '#' regardless which character is used
  406. # in the wiki syntax (normally '!')
  407. try:
  408. word, anchor = href[22:].split(u"#", 1)
  409. except ValueError:
  410. word = href[22:]
  411. anchor = None
  412. # open the wiki page
  413. if tabMode & 2:
  414. if tabMode == 6:
  415. # New Window
  416. presenter = self.presenter.getMainControl().\
  417. createNewDocPagePresenterTabInNewFrame()
  418. else:
  419. # New tab
  420. presenter = self.presenter.getMainControl().\
  421. createNewDocPagePresenterTab()
  422. presenter.switchSubControl("preview", False)
  423. else:
  424. # Same tab
  425. presenter = self.presenter
  426. presenter.openWikiPage(word, motionType="child", anchor=anchor)
  427. if not tabMode & 1:
  428. # Show in foreground
  429. # presenter.switchSubControl("preview", True)
  430. presenter.getMainControl().getMainAreaPanel().\
  431. showPresenter(presenter)
  432. presenter.SetFocus()
  433. # else:
  434. # presenter.switchSubControl("preview", False)
  435. elif href == u"internaljump:action/history/back":
  436. # Go back in history
  437. self.presenter.getMainControl().goBrowserBack()
  438. elif href.startswith(u"#"):
  439. anchor = href[1:]
  440. if self.HasAnchor(anchor):
  441. self.ScrollToAnchor(anchor)
  442. # Workaround because ScrollToAnchor scrolls too far
  443. # Here the real scroll position is needed so
  444. # getIntendedViewStart() is not called
  445. lx, ly = self.GetViewStart()
  446. self.scrollDeferred(lx, ly-1)
  447. else:
  448. self.scrollDeferred(0, 0)
  449. else:
  450. self.presenter.getMainControl().launchUrl(href)
  451. def OnActivateThis(self, evt):
  452. self._activateLink(self.contextHref, tabMode=0)
  453. def OnActivateNewTabThis(self, evt):
  454. self._activateLink(self.contextHref, tabMode=2)
  455. def OnActivateNewTabBackgroundThis(self, evt):
  456. self._activateLink(self.contextHref, tabMode=3)
  457. def OnActivateNewWindowThis(self, evt):
  458. self._activateLink(self.contextHref, tabMode=6)
  459. def OnOpenContainingFolderThis(self, evt):
  460. if not self.contextHref:
  461. return
  462. link = self.contextHref
  463. if link.startswith(u"rel://"):
  464. link = self.presenter.getWikiDocument().makeRelUrlAbsolute(link)
  465. if link.startswith(u"file:"):
  466. try:
  467. path = os.path.dirname(StringOps.pathnameFromUrl(link))
  468. if not os.path.exists(StringOps.longPathEnc(path)):
  469. self.presenter.displayErrorMessage(
  470. _(u"Folder does not exist"))
  471. return
  472. OsAbstract.startFile(self.presenter.getMainControl(),
  473. path)
  474. except IOError:
  475. pass # Error message?
  476. def OnKeyUp(self, evt):
  477. acc = getAccelPairFromKeyDown(evt)
  478. if acc == (wx.ACCEL_CTRL, ord('C')):
  479. # Consume original clipboard copy function
  480. pass
  481. else:
  482. evt.Skip()
  483. def addZoom(self, step):
  484. """
  485. Modify the zoom setting by step relative to current zoom in
  486. configuration.
  487. """
  488. zoom = self.presenter.getConfig().getint("main", "preview_zoom", 0)
  489. zoom += step
  490. self.presenter.getConfig().set("main", "preview_zoom", str(zoom))
  491. self.outOfSync = True
  492. self.refresh()
  493. def OnKeyDown(self, evt):
  494. acc = getAccelPairFromKeyDown(evt)
  495. if acc == (wx.ACCEL_CTRL, ord('+')) or \
  496. acc == (wx.ACCEL_CTRL, wx.WXK_NUMPAD_ADD):
  497. self.addZoom(1)
  498. elif acc == (wx.ACCEL_CTRL, ord('-')) or \
  499. acc == (wx.ACCEL_CTRL, wx.WXK_NUMPAD_SUBTRACT):
  500. self.addZoom(-1)
  501. else:
  502. evt.Skip()
  503. def OnMouseWheel(self, evt):
  504. if evt.ControlDown():
  505. if self.presenter.getConfig().getboolean(
  506. "main", "mouse_reverseWheelZoom", False):
  507. self.addZoom( -(evt.GetWheelRotation() // evt.GetWheelDelta()) )
  508. else:
  509. self.addZoom( evt.GetWheelRotation() // evt.GetWheelDelta() )
  510. else:
  511. evt.Skip()
  512. def OnMouseMotion(self, evt):
  513. evt.Skip()
  514. pos = self.CalcUnscrolledPosition(evt.GetPosition())
  515. irep = self.GetInternalRepresentation()
  516. if irep is None:
  517. cell = None
  518. else:
  519. cell = irep.FindCellByPos(pos.x, pos.y)
  520. callTip = u""
  521. status = u""
  522. if cell is not None:
  523. linkInfo = cell.GetLink()
  524. if linkInfo is not None:
  525. href = linkInfo.GetHref()
  526. if href.startswith(u"internaljump:wikipage/"):
  527. # Jump to another wiki page
  528. # First check for an anchor. In URLs, anchors are always
  529. # separated by '#' regardless which character is used
  530. # in the wiki syntax (normally '!')
  531. try:
  532. wikiWord, anchor = href[22:].split(u"#", 1)
  533. anchor = flexibleUrlUnquote(anchor)
  534. except ValueError:
  535. wikiWord = href[22:]
  536. anchor = None
  537. wikiWord = flexibleUrlUnquote(wikiWord)
  538. wikiDocument = self.presenter.getWikiDocument()
  539. if wikiDocument is None:
  540. return
  541. wikiWord = wikiDocument.getWikiPageNameForLinkTerm(wikiWord)
  542. if wikiWord is not None:
  543. propList = wikiDocument.getAttributeTriples(wikiWord,
  544. u"short_hint", None)
  545. if len(propList) > 0:
  546. callTip = propList[-1][2]
  547. status = _(u"Link to page: %s") % wikiWord
  548. else:
  549. status = href
  550. self.presenter.getMainControl().statusBar.SetStatusText(
  551. uniToGui(status), 0)
  552. self.SetToolTipString(callTip)
  553. _CONTEXT_MENU_INTERNAL_JUMP = \
  554. u"""
  555. Activate;CMD_ACTIVATE_THIS
  556. Activate New Tab;CMD_ACTIVATE_NEW_TAB_THIS
  557. Activate New Tab Backgrd.;CMD_ACTIVATE_NEW_TAB_BACKGROUND_THIS
  558. Activate New Window;CMD_ACTIVATE_NEW_WINDOW_THIS
  559. """
  560. # Entries to support i18n of context menus
  561. if False:
  562. N_(u"Activate")
  563. N_(u"Activate New Tab")
  564. N_(u"Activate New Tab Backgrd.")
  565. N_(u"Activate New Window")