wxPython 4.3.2__cp315-cp315-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (472) hide show
  1. wx/WebView2Loader.dll +0 -0
  2. wx/__init__.py +22 -0
  3. wx/__init__.pyi +10 -0
  4. wx/__version__.py +9 -0
  5. wx/__version__.pyi +15 -0
  6. wx/_adv.cp315-win_amd64.pyd +0 -0
  7. wx/_aui.cp315-win_amd64.pyd +0 -0
  8. wx/_core.cp315-win_amd64.pyd +0 -0
  9. wx/_dataview.cp315-win_amd64.pyd +0 -0
  10. wx/_glcanvas.cp315-win_amd64.pyd +0 -0
  11. wx/_grid.cp315-win_amd64.pyd +0 -0
  12. wx/_html.cp315-win_amd64.pyd +0 -0
  13. wx/_html2.cp315-win_amd64.pyd +0 -0
  14. wx/_media.cp315-win_amd64.pyd +0 -0
  15. wx/_msw.cp315-win_amd64.pyd +0 -0
  16. wx/_propgrid.cp315-win_amd64.pyd +0 -0
  17. wx/_ribbon.cp315-win_amd64.pyd +0 -0
  18. wx/_richtext.cp315-win_amd64.pyd +0 -0
  19. wx/_stc.cp315-win_amd64.pyd +0 -0
  20. wx/_xml.cp315-win_amd64.pyd +0 -0
  21. wx/_xrc.cp315-win_amd64.pyd +0 -0
  22. wx/adv.py +127 -0
  23. wx/adv.pyi +5931 -0
  24. wx/aui.py +70 -0
  25. wx/aui.pyi +4805 -0
  26. wx/core.py +3417 -0
  27. wx/core.pyi +62949 -0
  28. wx/dataview.py +176 -0
  29. wx/dataview.pyi +3828 -0
  30. wx/gizmos.py +18 -0
  31. wx/glcanvas.py +13 -0
  32. wx/glcanvas.pyi +544 -0
  33. wx/grid.py +237 -0
  34. wx/grid.pyi +5678 -0
  35. wx/html.py +38 -0
  36. wx/html.pyi +3283 -0
  37. wx/html2.py +46 -0
  38. wx/html2.pyi +1301 -0
  39. wx/include/wxPython/sip.h +1938 -0
  40. wx/include/wxPython/wxpy_api.h +418 -0
  41. wx/lib/CDate.py +201 -0
  42. wx/lib/ClickableHtmlWindow.py +57 -0
  43. wx/lib/__init__.py +0 -0
  44. wx/lib/activex.py +178 -0
  45. wx/lib/activexwrapper.py +153 -0
  46. wx/lib/agw/__init__.py +128 -0
  47. wx/lib/agw/advancedsplash.py +563 -0
  48. wx/lib/agw/aquabutton.py +1127 -0
  49. wx/lib/agw/artmanager.py +2110 -0
  50. wx/lib/agw/aui/__init__.py +295 -0
  51. wx/lib/agw/aui/aui_constants.py +2616 -0
  52. wx/lib/agw/aui/aui_switcherdialog.py +1232 -0
  53. wx/lib/agw/aui/aui_utilities.py +648 -0
  54. wx/lib/agw/aui/auibar.py +4045 -0
  55. wx/lib/agw/aui/auibook.py +6288 -0
  56. wx/lib/agw/aui/dockart.py +1198 -0
  57. wx/lib/agw/aui/framemanager.py +10485 -0
  58. wx/lib/agw/aui/tabart.py +2749 -0
  59. wx/lib/agw/aui/tabmdi.py +679 -0
  60. wx/lib/agw/balloontip.py +1157 -0
  61. wx/lib/agw/buttonpanel.py +2787 -0
  62. wx/lib/agw/cubecolourdialog.py +3529 -0
  63. wx/lib/agw/customtreectrl.py +9908 -0
  64. wx/lib/agw/data/ShortcutEditor_1.png +0 -0
  65. wx/lib/agw/data/ShortcutEditor_1_thumb.png +0 -0
  66. wx/lib/agw/data/ShortcutEditor_2.png +0 -0
  67. wx/lib/agw/data/ShortcutEditor_2_thumb.png +0 -0
  68. wx/lib/agw/data/ShortcutEditor_3.png +0 -0
  69. wx/lib/agw/data/ShortcutEditor_3_thumb.png +0 -0
  70. wx/lib/agw/data/ShortcutEditor_4.png +0 -0
  71. wx/lib/agw/data/ShortcutEditor_4_thumb.png +0 -0
  72. wx/lib/agw/data/default_help_text.html +105 -0
  73. wx/lib/agw/flatmenu.py +7392 -0
  74. wx/lib/agw/flatnotebook.py +6669 -0
  75. wx/lib/agw/floatspin.py +1820 -0
  76. wx/lib/agw/fmcustomizedlg.py +535 -0
  77. wx/lib/agw/fmresources.py +407 -0
  78. wx/lib/agw/foldpanelbar.py +2282 -0
  79. wx/lib/agw/fourwaysplitter.py +1130 -0
  80. wx/lib/agw/genericmessagedialog.py +1549 -0
  81. wx/lib/agw/gradientbutton.py +731 -0
  82. wx/lib/agw/hyperlink.py +664 -0
  83. wx/lib/agw/hypertreelist.py +5756 -0
  84. wx/lib/agw/infobar.py +885 -0
  85. wx/lib/agw/knobctrl.py +944 -0
  86. wx/lib/agw/labelbook.py +3028 -0
  87. wx/lib/agw/multidirdialog.py +581 -0
  88. wx/lib/agw/peakmeter.py +1028 -0
  89. wx/lib/agw/persist/__init__.py +188 -0
  90. wx/lib/agw/persist/persist_constants.py +283 -0
  91. wx/lib/agw/persist/persist_handlers.py +2614 -0
  92. wx/lib/agw/persist/persistencemanager.py +863 -0
  93. wx/lib/agw/piectrl.py +1082 -0
  94. wx/lib/agw/pybusyinfo.py +399 -0
  95. wx/lib/agw/pycollapsiblepane.py +940 -0
  96. wx/lib/agw/pygauge.py +570 -0
  97. wx/lib/agw/pyprogress.py +916 -0
  98. wx/lib/agw/ribbon/__init__.py +198 -0
  99. wx/lib/agw/ribbon/art.py +219 -0
  100. wx/lib/agw/ribbon/art_aui.py +1283 -0
  101. wx/lib/agw/ribbon/art_default.py +81 -0
  102. wx/lib/agw/ribbon/art_internal.py +248 -0
  103. wx/lib/agw/ribbon/art_msw.py +2735 -0
  104. wx/lib/agw/ribbon/art_osx.py +52 -0
  105. wx/lib/agw/ribbon/bar.py +1259 -0
  106. wx/lib/agw/ribbon/buttonbar.py +1317 -0
  107. wx/lib/agw/ribbon/control.py +205 -0
  108. wx/lib/agw/ribbon/gallery.py +973 -0
  109. wx/lib/agw/ribbon/page.py +946 -0
  110. wx/lib/agw/ribbon/panel.py +1170 -0
  111. wx/lib/agw/ribbon/toolbar.py +1441 -0
  112. wx/lib/agw/rulerctrl.py +1885 -0
  113. wx/lib/agw/scrolledthumbnail.py +2116 -0
  114. wx/lib/agw/shapedbutton.py +1809 -0
  115. wx/lib/agw/shortcuteditor.py +2642 -0
  116. wx/lib/agw/speedmeter.py +1800 -0
  117. wx/lib/agw/supertooltip.py +1443 -0
  118. wx/lib/agw/thumbnailctrl.py +529 -0
  119. wx/lib/agw/toasterbox.py +1327 -0
  120. wx/lib/agw/ultimatelistctrl.py +13671 -0
  121. wx/lib/agw/xlsgrid.py +2111 -0
  122. wx/lib/agw/zoombar.py +1336 -0
  123. wx/lib/analogclock/__init__.py +140 -0
  124. wx/lib/analogclock/analogclock.py +630 -0
  125. wx/lib/analogclock/helpers.py +986 -0
  126. wx/lib/analogclock/lib_setup/__init__.py +0 -0
  127. wx/lib/analogclock/lib_setup/buttontreectrlpanel.py +297 -0
  128. wx/lib/analogclock/lib_setup/fontselect.py +57 -0
  129. wx/lib/analogclock/setup.py +490 -0
  130. wx/lib/analogclock/styles.py +47 -0
  131. wx/lib/anchors.py +103 -0
  132. wx/lib/art/__init__.py +4 -0
  133. wx/lib/art/flagart.py +1583 -0
  134. wx/lib/art/img2pyartprov.py +56 -0
  135. wx/lib/busy.py +152 -0
  136. wx/lib/buttons.py +1140 -0
  137. wx/lib/calendar.py +1596 -0
  138. wx/lib/checkbox.py +837 -0
  139. wx/lib/colourchooser/__init__.py +36 -0
  140. wx/lib/colourchooser/canvas.py +145 -0
  141. wx/lib/colourchooser/intl.py +24 -0
  142. wx/lib/colourchooser/pycolourbox.py +89 -0
  143. wx/lib/colourchooser/pycolourchooser.py +626 -0
  144. wx/lib/colourchooser/pycolourslider.py +98 -0
  145. wx/lib/colourchooser/pypalette.py +208 -0
  146. wx/lib/colourdb.py +740 -0
  147. wx/lib/colourselect.py +385 -0
  148. wx/lib/colourutils.py +118 -0
  149. wx/lib/combotreebox.py +944 -0
  150. wx/lib/delayedresult.py +420 -0
  151. wx/lib/dialogs.py +510 -0
  152. wx/lib/docview.py +3210 -0
  153. wx/lib/dragscroller.py +79 -0
  154. wx/lib/editor/README.txt +77 -0
  155. wx/lib/editor/__init__.py +24 -0
  156. wx/lib/editor/editor.py +974 -0
  157. wx/lib/editor/images.py +15 -0
  158. wx/lib/editor/selection.py +44 -0
  159. wx/lib/embeddedimage.py +76 -0
  160. wx/lib/eventStack.py +136 -0
  161. wx/lib/eventwatcher.py +440 -0
  162. wx/lib/evtmgr.py +521 -0
  163. wx/lib/expando.py +393 -0
  164. wx/lib/fancytext.py +494 -0
  165. wx/lib/filebrowsebutton.py +461 -0
  166. wx/lib/flashwin.py +262 -0
  167. wx/lib/flashwin_old.py +651 -0
  168. wx/lib/floatcanvas/FCEvents.py +53 -0
  169. wx/lib/floatcanvas/FCObjects.py +2910 -0
  170. wx/lib/floatcanvas/FloatCanvas.py +1025 -0
  171. wx/lib/floatcanvas/GUIMode.py +396 -0
  172. wx/lib/floatcanvas/NavCanvas.py +162 -0
  173. wx/lib/floatcanvas/Resources.py +319 -0
  174. wx/lib/floatcanvas/ScreenShot.py +1788 -0
  175. wx/lib/floatcanvas/Utilities/BBox.py +313 -0
  176. wx/lib/floatcanvas/Utilities/Colors.py +137 -0
  177. wx/lib/floatcanvas/Utilities/GUI.py +91 -0
  178. wx/lib/floatcanvas/Utilities/__init__.py +7 -0
  179. wx/lib/floatcanvas/__init__.py +124 -0
  180. wx/lib/foldmenu.py +89 -0
  181. wx/lib/gestures.py +310 -0
  182. wx/lib/gizmos/__init__.py +18 -0
  183. wx/lib/gizmos/dynamicsash.py +1202 -0
  184. wx/lib/gizmos/ledctrl.py +299 -0
  185. wx/lib/gizmos/treelistctrl.py +87 -0
  186. wx/lib/graphics.py +1942 -0
  187. wx/lib/gridmovers.py +516 -0
  188. wx/lib/iewin.py +249 -0
  189. wx/lib/iewin_old.py +894 -0
  190. wx/lib/imagebrowser.py +853 -0
  191. wx/lib/imageutils.py +163 -0
  192. wx/lib/infoframe.py +490 -0
  193. wx/lib/inspection.py +1254 -0
  194. wx/lib/intctrl.py +990 -0
  195. wx/lib/itemspicker.py +256 -0
  196. wx/lib/langlistctrl.py +480 -0
  197. wx/lib/layoutf.py +271 -0
  198. wx/lib/masked/__init__.py +27 -0
  199. wx/lib/masked/combobox.py +839 -0
  200. wx/lib/masked/ctrl.py +108 -0
  201. wx/lib/masked/ipaddrctrl.py +241 -0
  202. wx/lib/masked/maskededit.py +7262 -0
  203. wx/lib/masked/numctrl.py +2000 -0
  204. wx/lib/masked/textctrl.py +465 -0
  205. wx/lib/masked/timectrl.py +1465 -0
  206. wx/lib/mixins/__init__.py +17 -0
  207. wx/lib/mixins/grid.py +47 -0
  208. wx/lib/mixins/gridlabelrenderer.py +277 -0
  209. wx/lib/mixins/imagelist.py +77 -0
  210. wx/lib/mixins/inspection.py +184 -0
  211. wx/lib/mixins/listctrl.py +893 -0
  212. wx/lib/mixins/rubberband.py +403 -0
  213. wx/lib/mixins/treemixin.py +678 -0
  214. wx/lib/msgpanel.py +95 -0
  215. wx/lib/multisash.py +746 -0
  216. wx/lib/myole4ax.idl +178 -0
  217. wx/lib/myole4ax.tlb +0 -0
  218. wx/lib/newevent.py +229 -0
  219. wx/lib/newevent.pyi +25 -0
  220. wx/lib/nvdlg.py +156 -0
  221. wx/lib/ogl/__init__.py +13 -0
  222. wx/lib/ogl/basic.py +3989 -0
  223. wx/lib/ogl/bmpshape.py +86 -0
  224. wx/lib/ogl/canvas.py +467 -0
  225. wx/lib/ogl/composit.py +1576 -0
  226. wx/lib/ogl/diagram.py +230 -0
  227. wx/lib/ogl/divided.py +482 -0
  228. wx/lib/ogl/drawn.py +898 -0
  229. wx/lib/ogl/lines.py +1809 -0
  230. wx/lib/ogl/oglmisc.py +607 -0
  231. wx/lib/pdfviewer/__init__.py +113 -0
  232. wx/lib/pdfviewer/bitmaps/ArrowLeft.png +0 -0
  233. wx/lib/pdfviewer/bitmaps/ArrowRight.png +0 -0
  234. wx/lib/pdfviewer/bitmaps/DirectionH.png +0 -0
  235. wx/lib/pdfviewer/bitmaps/DirectionV.png +0 -0
  236. wx/lib/pdfviewer/bitmaps/PlayerFirst.png +0 -0
  237. wx/lib/pdfviewer/bitmaps/PlayerLast.png +0 -0
  238. wx/lib/pdfviewer/bitmaps/PlayerNext.png +0 -0
  239. wx/lib/pdfviewer/bitmaps/PlayerPrev.png +0 -0
  240. wx/lib/pdfviewer/bitmaps/Printer.png +0 -0
  241. wx/lib/pdfviewer/bitmaps/ReadMe.txt +28 -0
  242. wx/lib/pdfviewer/bitmaps/Save.png +0 -0
  243. wx/lib/pdfviewer/bitmaps/ZoomIn.png +0 -0
  244. wx/lib/pdfviewer/bitmaps/ZoomOut.png +0 -0
  245. wx/lib/pdfviewer/bitmaps/encode_bitmaps.py +37 -0
  246. wx/lib/pdfviewer/buttonpanel.py +285 -0
  247. wx/lib/pdfviewer/images.py +240 -0
  248. wx/lib/pdfviewer/viewer.py +1118 -0
  249. wx/lib/pdfwin.py +295 -0
  250. wx/lib/pdfwin_old.py +789 -0
  251. wx/lib/platebtn.py +789 -0
  252. wx/lib/plot/CHANGELOG.md +150 -0
  253. wx/lib/plot/README.md +16 -0
  254. wx/lib/plot/__init__.py +46 -0
  255. wx/lib/plot/__main__.py +5 -0
  256. wx/lib/plot/examples/__init__.py +0 -0
  257. wx/lib/plot/examples/demo.py +1010 -0
  258. wx/lib/plot/examples/simple_example.py +56 -0
  259. wx/lib/plot/plotcanvas.py +2985 -0
  260. wx/lib/plot/polyobjects.py +1524 -0
  261. wx/lib/plot/utils.py +334 -0
  262. wx/lib/popupctl.py +251 -0
  263. wx/lib/printout.py +1155 -0
  264. wx/lib/progressindicator.py +151 -0
  265. wx/lib/pubsub/LICENSE_BSD_Simple.txt +23 -0
  266. wx/lib/pubsub/README_WxPython.txt +22 -0
  267. wx/lib/pubsub/RELEASE_NOTES.txt +71 -0
  268. wx/lib/pubsub/__init__.py +25 -0
  269. wx/lib/pubsub/core/__init__.py +92 -0
  270. wx/lib/pubsub/core/arg1/__init__.py +16 -0
  271. wx/lib/pubsub/core/arg1/listenerimpl.py +97 -0
  272. wx/lib/pubsub/core/arg1/publisher.py +40 -0
  273. wx/lib/pubsub/core/arg1/publishermixin.py +34 -0
  274. wx/lib/pubsub/core/arg1/topicargspecimpl.py +66 -0
  275. wx/lib/pubsub/core/arg1/topicmgrimpl.py +19 -0
  276. wx/lib/pubsub/core/callables.py +198 -0
  277. wx/lib/pubsub/core/imp2.py +62 -0
  278. wx/lib/pubsub/core/itopicdefnprovider.py +0 -0
  279. wx/lib/pubsub/core/kwargs/__init__.py +16 -0
  280. wx/lib/pubsub/core/kwargs/datamsg.py +27 -0
  281. wx/lib/pubsub/core/kwargs/listenerimpl.py +93 -0
  282. wx/lib/pubsub/core/kwargs/publisher.py +77 -0
  283. wx/lib/pubsub/core/kwargs/publishermixin.py +65 -0
  284. wx/lib/pubsub/core/kwargs/topicargspecimpl.py +216 -0
  285. wx/lib/pubsub/core/kwargs/topicmgrimpl.py +13 -0
  286. wx/lib/pubsub/core/listener.py +40 -0
  287. wx/lib/pubsub/core/listenerbase.py +185 -0
  288. wx/lib/pubsub/core/notificationmgr.py +185 -0
  289. wx/lib/pubsub/core/publisherbase.py +189 -0
  290. wx/lib/pubsub/core/topicargspec.py +77 -0
  291. wx/lib/pubsub/core/topicdefnprovider.py +631 -0
  292. wx/lib/pubsub/core/topicexc.py +72 -0
  293. wx/lib/pubsub/core/topicmgr.py +454 -0
  294. wx/lib/pubsub/core/topicobj.py +472 -0
  295. wx/lib/pubsub/core/topictreetraverser.py +143 -0
  296. wx/lib/pubsub/core/topicutils.py +119 -0
  297. wx/lib/pubsub/core/treeconfig.py +21 -0
  298. wx/lib/pubsub/core/validatedefnargs.py +29 -0
  299. wx/lib/pubsub/core/weakmethod.py +102 -0
  300. wx/lib/pubsub/policies.py +24 -0
  301. wx/lib/pubsub/pub.py +199 -0
  302. wx/lib/pubsub/setuparg1.py +47 -0
  303. wx/lib/pubsub/setupkwargs.py +29 -0
  304. wx/lib/pubsub/utils/__init__.py +27 -0
  305. wx/lib/pubsub/utils/exchandling.py +100 -0
  306. wx/lib/pubsub/utils/misc.py +99 -0
  307. wx/lib/pubsub/utils/notification.py +331 -0
  308. wx/lib/pubsub/utils/topictreeprinter.py +195 -0
  309. wx/lib/pubsub/utils/xmltopicdefnprovider.py +286 -0
  310. wx/lib/pydocview.py +3300 -0
  311. wx/lib/rcsizer.py +227 -0
  312. wx/lib/resizewidget.py +357 -0
  313. wx/lib/scrolledpanel.py +243 -0
  314. wx/lib/sheet.py +350 -0
  315. wx/lib/sized_controls.py +691 -0
  316. wx/lib/softwareupdate.py +355 -0
  317. wx/lib/splitter.py +925 -0
  318. wx/lib/statbmp.py +199 -0
  319. wx/lib/stattext.py +321 -0
  320. wx/lib/throbber.py +424 -0
  321. wx/lib/ticker.py +306 -0
  322. wx/lib/ticker_xrc.py +48 -0
  323. wx/lib/utils.py +89 -0
  324. wx/lib/wordwrap.py +97 -0
  325. wx/lib/wxcairo/__init__.py +139 -0
  326. wx/lib/wxcairo/wx_cairocffi.py +200 -0
  327. wx/lib/wxcairo/wx_pycairo.py +455 -0
  328. wx/lib/wxpTag.py +274 -0
  329. wx/libcairo-2.dll +0 -0
  330. wx/locale/af/LC_MESSAGES/wxstd.mo +0 -0
  331. wx/locale/an/LC_MESSAGES/wxstd.mo +0 -0
  332. wx/locale/ar/LC_MESSAGES/wxstd.mo +0 -0
  333. wx/locale/ca/LC_MESSAGES/wxstd.mo +0 -0
  334. wx/locale/ca@valencia/LC_MESSAGES/wxstd.mo +0 -0
  335. wx/locale/co/LC_MESSAGES/wxstd.mo +0 -0
  336. wx/locale/cs/LC_MESSAGES/wxstd.mo +0 -0
  337. wx/locale/da/LC_MESSAGES/wxstd.mo +0 -0
  338. wx/locale/de/LC_MESSAGES/wxstd.mo +0 -0
  339. wx/locale/el/LC_MESSAGES/wxstd.mo +0 -0
  340. wx/locale/es/LC_MESSAGES/wxstd.mo +0 -0
  341. wx/locale/eu/LC_MESSAGES/wxstd.mo +0 -0
  342. wx/locale/fa_IR/LC_MESSAGES/wxstd.mo +0 -0
  343. wx/locale/fi/LC_MESSAGES/wxstd.mo +0 -0
  344. wx/locale/fr/LC_MESSAGES/wxstd.mo +0 -0
  345. wx/locale/gl_ES/LC_MESSAGES/wxstd.mo +0 -0
  346. wx/locale/hi/LC_MESSAGES/wxstd.mo +0 -0
  347. wx/locale/hr/LC_MESSAGES/wxstd.mo +0 -0
  348. wx/locale/hu/LC_MESSAGES/wxstd.mo +0 -0
  349. wx/locale/id/LC_MESSAGES/wxstd.mo +0 -0
  350. wx/locale/it/LC_MESSAGES/wxstd.mo +0 -0
  351. wx/locale/ja/LC_MESSAGES/wxstd.mo +0 -0
  352. wx/locale/ka/LC_MESSAGES/wxstd.mo +0 -0
  353. wx/locale/ko_KR/LC_MESSAGES/wxstd.mo +0 -0
  354. wx/locale/lt/LC_MESSAGES/wxstd.mo +0 -0
  355. wx/locale/lv/LC_MESSAGES/wxstd.mo +0 -0
  356. wx/locale/ms/LC_MESSAGES/wxstd.mo +0 -0
  357. wx/locale/nb/LC_MESSAGES/wxstd.mo +0 -0
  358. wx/locale/ne/LC_MESSAGES/wxstd.mo +0 -0
  359. wx/locale/nl/LC_MESSAGES/wxstd.mo +0 -0
  360. wx/locale/pl/LC_MESSAGES/wxstd.mo +0 -0
  361. wx/locale/pt/LC_MESSAGES/wxstd.mo +0 -0
  362. wx/locale/pt_BR/LC_MESSAGES/wxstd.mo +0 -0
  363. wx/locale/ro/LC_MESSAGES/wxstd.mo +0 -0
  364. wx/locale/ru/LC_MESSAGES/wxstd.mo +0 -0
  365. wx/locale/sk/LC_MESSAGES/wxstd.mo +0 -0
  366. wx/locale/sl/LC_MESSAGES/wxstd.mo +0 -0
  367. wx/locale/sq/LC_MESSAGES/wxstd.mo +0 -0
  368. wx/locale/sr/LC_MESSAGES/wxstd.mo +0 -0
  369. wx/locale/sv/LC_MESSAGES/wxstd.mo +0 -0
  370. wx/locale/ta/LC_MESSAGES/wxstd.mo +0 -0
  371. wx/locale/tr/LC_MESSAGES/wxstd.mo +0 -0
  372. wx/locale/uk/LC_MESSAGES/wxstd.mo +0 -0
  373. wx/locale/vi/LC_MESSAGES/wxstd.mo +0 -0
  374. wx/locale/zh_CN/LC_MESSAGES/wxstd.mo +0 -0
  375. wx/locale/zh_TW/LC_MESSAGES/wxstd.mo +0 -0
  376. wx/media.py +30 -0
  377. wx/media.pyi +272 -0
  378. wx/msw.py +16 -0
  379. wx/msw.pyi +91 -0
  380. wx/propgrid.py +498 -0
  381. wx/propgrid.pyi +7427 -0
  382. wx/py/CHANGES.txt +796 -0
  383. wx/py/Py.ico +0 -0
  384. wx/py/PyAlaCarte.py +34 -0
  385. wx/py/PyAlaMode.py +34 -0
  386. wx/py/PyAlaModeTest.py +33 -0
  387. wx/py/PyCrust.ico +0 -0
  388. wx/py/PyCrust.py +78 -0
  389. wx/py/PyCrust_16.png +0 -0
  390. wx/py/PyCrust_32.png +0 -0
  391. wx/py/PyFilling.py +35 -0
  392. wx/py/PyShell.py +78 -0
  393. wx/py/PySlices.ico +0 -0
  394. wx/py/PySlices.py +98 -0
  395. wx/py/PySlicesShell.py +94 -0
  396. wx/py/PySlices_16.png +0 -0
  397. wx/py/PySlices_32.png +0 -0
  398. wx/py/PyWrap.py +52 -0
  399. wx/py/README.txt +77 -0
  400. wx/py/__init__.py +20 -0
  401. wx/py/buffer.py +136 -0
  402. wx/py/crust.py +403 -0
  403. wx/py/crustslices.py +403 -0
  404. wx/py/dispatcher.py +259 -0
  405. wx/py/document.py +37 -0
  406. wx/py/editor.py +844 -0
  407. wx/py/editwindow.py +316 -0
  408. wx/py/filling.py +358 -0
  409. wx/py/frame.py +976 -0
  410. wx/py/images.py +212 -0
  411. wx/py/interpreter.py +161 -0
  412. wx/py/introspect.py +402 -0
  413. wx/py/magic.py +98 -0
  414. wx/py/parse.py +134 -0
  415. wx/py/path.py +36 -0
  416. wx/py/pseudo.py +99 -0
  417. wx/py/shell.py +1579 -0
  418. wx/py/sliceshell.py +3805 -0
  419. wx/py/tests/test_interpreter.py +71 -0
  420. wx/py/tests/test_introspect.py +810 -0
  421. wx/py/tests/test_pseudo.py +70 -0
  422. wx/py/tests/test_version.py +36 -0
  423. wx/py/tests/testall.py +22 -0
  424. wx/py/version.py +7 -0
  425. wx/py.typed +0 -0
  426. wx/ribbon.py +48 -0
  427. wx/ribbon.pyi +3099 -0
  428. wx/richtext.py +141 -0
  429. wx/richtext.pyi +13581 -0
  430. wx/siplib.cp315-win_amd64.pyd +0 -0
  431. wx/siplib.pyi +19 -0
  432. wx/stc.py +59 -0
  433. wx/stc.pyi +9918 -0
  434. wx/svg/__init__.py +363 -0
  435. wx/svg/_nanosvg.cp315-win_amd64.pyd +0 -0
  436. wx/tools/__init__.py +18 -0
  437. wx/tools/dbg.py +268 -0
  438. wx/tools/genaxmodule.py +50 -0
  439. wx/tools/helpviewer.py +92 -0
  440. wx/tools/img2img.py +85 -0
  441. wx/tools/img2png.py +54 -0
  442. wx/tools/img2py.py +306 -0
  443. wx/tools/img2xpm.py +54 -0
  444. wx/tools/pywxrc.py +951 -0
  445. wx/tools/wxget.py +254 -0
  446. wx/tools/wxget_docs_demo.py +183 -0
  447. wx/wxbase334u_net_vc140_x64.dll +0 -0
  448. wx/wxbase334u_vc140_x64.dll +0 -0
  449. wx/wxbase334u_xml_vc140_x64.dll +0 -0
  450. wx/wxmsw334u_adv_vc140_x64.dll +0 -0
  451. wx/wxmsw334u_aui_vc140_x64.dll +0 -0
  452. wx/wxmsw334u_core_vc140_x64.dll +0 -0
  453. wx/wxmsw334u_gl_vc140_x64.dll +0 -0
  454. wx/wxmsw334u_html_vc140_x64.dll +0 -0
  455. wx/wxmsw334u_media_vc140_x64.dll +0 -0
  456. wx/wxmsw334u_propgrid_vc140_x64.dll +0 -0
  457. wx/wxmsw334u_qa_vc140_x64.dll +0 -0
  458. wx/wxmsw334u_ribbon_vc140_x64.dll +0 -0
  459. wx/wxmsw334u_richtext_vc140_x64.dll +0 -0
  460. wx/wxmsw334u_stc_vc140_x64.dll +0 -0
  461. wx/wxmsw334u_webview_vc140_x64.dll +0 -0
  462. wx/wxmsw334u_xrc_vc140_x64.dll +0 -0
  463. wx/xml.py +18 -0
  464. wx/xml.pyi +728 -0
  465. wx/xrc.py +68 -0
  466. wx/xrc.pyi +896 -0
  467. wxpython-4.3.2.dist-info/METADATA +71 -0
  468. wxpython-4.3.2.dist-info/RECORD +472 -0
  469. wxpython-4.3.2.dist-info/WHEEL +5 -0
  470. wxpython-4.3.2.dist-info/entry_points.txt +13 -0
  471. wxpython-4.3.2.dist-info/licenses/LICENSE.txt +610 -0
  472. wxpython-4.3.2.dist-info/top_level.txt +1 -0
wx/lib/agw/xlsgrid.py ADDED
@@ -0,0 +1,2111 @@
1
+ # --------------------------------------------------------------------------------- #
2
+ # XLSGRID wxPython IMPLEMENTATION
3
+ #
4
+ # Andrea Gavana @ 08 Aug 2011
5
+ # Latest Revision: 27 Dec 2012, 21.00 GMT
6
+ #
7
+ #
8
+ # TODO List
9
+ #
10
+ # Current todo list:
11
+ #
12
+ # 1. There is currently no support for rich text, i.e. strings containing partial
13
+ # bold, italic and underlined text, change of font inside a string, etc... xlrd
14
+ # supports those (from version 0.7.2 in SVN) but there is no easy way to handle
15
+ # changing fonts/colours/formatting in the same string in wxPython;
16
+ #
17
+ # 2. XLSGrid is sufficiently efficient and fast for reasonably small Excel files.
18
+ # There might be some improvement to be made in the code to make it work with
19
+ # bigger files and in a faster way;
20
+ #
21
+ # 3. There is currently no support for strikethrough fonts, although xlrd correctly
22
+ # reports this format. The issue is a bug in wxWidgets itself which doesn't
23
+ # allow the creation of strikethrough fonts (http://trac.wxwidgets.org/ticket/9907).
24
+ #
25
+ # For all kind of problems, requests of enhancements and bug reports, please write
26
+ # to me at:
27
+ #
28
+ # andrea.gavana@gmail.com
29
+ # andrea.gavana@maerskoil.com
30
+ #
31
+ # Or, obviously, to the wxPython mailing list!!!
32
+ #
33
+ # Tags: phoenix-port, documented, unittest, py3-port
34
+ #
35
+ # End of comments
36
+ # --------------------------------------------------------------------------------- #
37
+
38
+
39
+ """
40
+ :class:`~wx.lib.agw.xlsgrid.XLSGrid` is a class based on :class:`grid.Grid` that can be used to faithfully
41
+ reproduce the appearance of a Microsoft Excel spreadsheet (one worksheet per
42
+ every instance of :class:`XLSGrid`).
43
+
44
+
45
+ Description
46
+ ===========
47
+
48
+ :class:`XLSGrid` is a class based on :class:`grid.Grid` that can be used to faithfully
49
+ reproduce the appearance of a Microsoft Excel spreadsheet (one worksheet per
50
+ every instance of :class:`XLSGrid`).
51
+
52
+ :class:`XLSGrid` is a completely owner-drawn control, and it relies on the power of
53
+ :class:`grid.PyGridTableBase` and :class:`grid.PyGridCellRenderer` to draw the cell
54
+ content. For this reasons (and for some others, see the TODOs section), it will
55
+ work efficiently only for relatively small Excel files.
56
+
57
+ :note:
58
+
59
+ :class:`XLSGrid` **requires** the `xlrd` package from:
60
+
61
+ http://pypi.python.org/pypi/xlrd
62
+
63
+ Minimum version requirement for `xlrd` is 0.7.1. If you wish to have
64
+ support for hyperlinks inside cells and rich text content, you need the
65
+ SVN version of `xlrd`.
66
+
67
+
68
+ :note:
69
+
70
+ On Windows, it is **strongly** recommended to install Mark Hammonds'
71
+ `pywin32` package:
72
+
73
+ http://sourceforge.net/projects/pywin32/
74
+
75
+ This will allow you to perfectly reproduce the appearance of the Excel
76
+ worksheet in your instance of :class:`XLSGrid`.
77
+
78
+ .. warning::
79
+
80
+ If Mark Hammonds' `pywin32` package is not available, the formatting
81
+ capabilities of :class:`XLSGrid` are severely limited; for instance, you won't
82
+ probably get the exact WYSIWYG between the Excel spreadsheet and :class:`XLSGrid`.
83
+
84
+
85
+ .. warning::
86
+
87
+ :class:`XLSGrid` can only read Excel `.xls` files, not the newer versions
88
+ `.xlsx` generated by Office 2007/2010. If you have a `.xlsx` file, you will
89
+ need to save it in 1997-2003 Office compatibility mode.
90
+
91
+
92
+ Currently this class provides a read-only subclass of :class:`grid.Grid`, with
93
+ the following formatting features already implemented:
94
+
95
+ * Cell background: support for any cell background colour and fill pattern
96
+ (hatching) in the Excel default set. There currently is no support for
97
+ gradient shading inside a cell as `xlrd` doesn't report this information.
98
+
99
+ * Cell borders: support for all the border types and colours exposed by Excel
100
+ (left, top, bottom, right and diagonal borders, thin, double, thick, etc...
101
+ line styles).
102
+
103
+ * Cell text: support for all kind of fonts (except strikethrough, but this is
104
+ a bug in wxWidgets), and font colours. As a subset of text/font capabilities,
105
+ :class:`XLSGrid` supports the following features found in Excel:
106
+
107
+ - Horizontal alignment: left, right, centered, left-indented;
108
+ - Vertical alignment: left, right, centered;
109
+ - Text direction: left-to-right or right-to-left;
110
+ - Text-wrapping: wrapping long texts inside a grid cell;
111
+ - Shrink-to-fit: text font is reduced until the text can fit in a one-line
112
+ inside the grid cell;
113
+ - Text rotation: text can be rotated from +90 to -90 degrees.
114
+
115
+ * Cell rich text (new in version 0.2): support for strings containing partial
116
+ bold, italic and underlined text, change of font inside a string etc...
117
+ Cells with rich text content can not be multi-line and they will not honour
118
+ the `shrink-to-fit` and `wrapping` settings.
119
+
120
+ * Cell text appearance: if you are using Mark Hammonds' `pywin32` package, the
121
+ text displayed in the :class:`XLSGrid` cells has exactly the same appearance as in
122
+ the Excel spreadsheet.
123
+
124
+ * Cell comments (notes): if you are using Mark Hammonds' `pywin32` package,
125
+ cell comments (notes) are extracted and you will see a small red triangle at
126
+ the top-right corner of any cell containing a comment. Hovering with the
127
+ mouse on that cell will pop-up a "comment-window" displaying the comment
128
+ text (the comment window is based on :mod:`lib.agw.supertooltip`).
129
+
130
+ * Cell hyperlinks: starting from version 0.7.2 (SVN), `xlrd` is capable of
131
+ extracting hyperlinks from Excel cells. This will be appropriately displayed
132
+ in :class:`XLSGrid` with a cursor changing and a tooltip on that cell.
133
+
134
+ * Cell merging: merged cells in the Excel spreadsheet will be correctly handled
135
+ by :class:`XLSGrid`.
136
+
137
+ * Columns and rows sizes: :class:`XLSGrid` calculates the correct rows and columns
138
+ sizes based on the Excel reported values in characters. The calculations are
139
+ based on the default width of the text in 1/256 of the width of the zero
140
+ character, using default Excel font (first FONT record in the Excel file).
141
+
142
+
143
+ And a lot more. Check the demo for an almost complete review of the functionalities.
144
+
145
+
146
+ Usage
147
+ =====
148
+
149
+ Sample usage::
150
+
151
+ import wx
152
+ import xlrd
153
+ import os
154
+
155
+ import xlsgrid as XG
156
+
157
+ class MyFrame(wx.Frame):
158
+
159
+ def __init__(self):
160
+
161
+ wx.Frame.__init__(self, parent, -1, "XLSGrid Demo", size=(1000, 800))
162
+
163
+ filename = os.path.join(os.getcwd(), "Excel", "Example_1.xls")
164
+ sheetname = "Example_1"
165
+
166
+ book = xlrd.open_workbook(filename, formatting_info=1)
167
+
168
+ sheet = book.sheet_by_name(sheetname)
169
+ rows, cols = sheet.nrows, sheet.ncols
170
+
171
+ comments, texts = XG.ReadExcelCOM(filename, sheetname, rows, cols)
172
+
173
+ xls_grid = XG.XLSGrid(self)
174
+ xls_grid.PopulateGrid(book, sheet, texts, comments)
175
+
176
+
177
+ # our normal wxApp-derived class, as usual
178
+
179
+ app = wx.App(0)
180
+
181
+ frame = MyFrame(None)
182
+ app.SetTopWindow(frame)
183
+ frame.Show()
184
+
185
+ app.MainLoop()
186
+
187
+
188
+ :note: Please note that you **have to** pass the keyword `formatting_info` to
189
+ the method `xlrd.open_workbook` to obtain the cell formatting.
190
+
191
+
192
+ TODOs
193
+ =====
194
+
195
+ 1. :class:`XLSGrid` is sufficiently efficient and fast for reasonably small Excel files.
196
+ There might be some improvement to be made in the code to make it work with
197
+ bigger files and in a faster way;
198
+ 2. :class:`grid.Grid` seems to completely redraw itself at every resize event, even
199
+ if the cell content has not changed and it has not been damaged (this seems
200
+ to be fixed in wxPython 2.9.2.1);
201
+ 3. There is currently no support for strikethrough fonts, although `xlrd` correctly
202
+ reports this format. The issue is a bug in wxWidgets itself which doesn't
203
+ allow the creation of strikethrough fonts (http://trac.wxwidgets.org/ticket/9907).
204
+
205
+
206
+ Supported Platforms
207
+ ===================
208
+
209
+ :class:`XLSGrid` has been tested on the following platforms:
210
+ * Windows (Windows Vista and 7);
211
+
212
+
213
+ Window Styles
214
+ =============
215
+
216
+ `No particular window styles are available for this class.`
217
+
218
+
219
+ Events Processing
220
+ =================
221
+
222
+ `No custom events are available for this class.`
223
+
224
+
225
+ License And Version
226
+ ===================
227
+
228
+ :class:`XLSGrid` is distributed under the wxPython license.
229
+
230
+ Latest Revision: Andrea Gavana @ 27 Dec 2012, 21.00 GMT
231
+
232
+ Version 0.4
233
+
234
+ """
235
+
236
+ # Version Info
237
+ __version__ = "0.4"
238
+
239
+ # Start the imports
240
+ import wx
241
+ import os
242
+
243
+ try:
244
+ import xlrd
245
+ except ImportError:
246
+ pass
247
+
248
+ import datetime
249
+ import string
250
+
251
+ import wx.grid as gridlib
252
+
253
+ from wx.lib.embeddedimage import PyEmbeddedImage
254
+ from wx.lib.wordwrap import wordwrap
255
+
256
+ from . import supertooltip as STT
257
+
258
+ from math import pi, sin, cos
259
+ from operator import attrgetter
260
+
261
+ _hasWin32 = False
262
+
263
+ if wx.Platform == "__WXMSW__":
264
+ try:
265
+ from win32com.client import Dispatch
266
+ import pywintypes
267
+ _hasWin32 = True
268
+ except ImportError:
269
+ pass
270
+
271
+
272
+ #----------------------------------------------------------------------
273
+ # Constants used to translate xlrd stuff into wxPython stuff
274
+ #----------------------------------------------------------------------
275
+
276
+ BOTTOM = wx.BOTTOM
277
+ TOP = wx.TOP
278
+ LEFT = wx.LEFT
279
+ RIGHT = wx.RIGHT
280
+ DIAGONAL = 2 << 7
281
+
282
+ XF_BORDER_STYLES = {"bottom": BOTTOM, "left": LEFT, "right": RIGHT,
283
+ "top": TOP, "diag": DIAGONAL}
284
+
285
+ HORIZONTAL_ALIGNMENTS = {0: 0, 1: 0, 2: wx.ALIGN_CENTER_HORIZONTAL, 3: wx.ALIGN_RIGHT}
286
+ VERTICAL_ALIGNMENTS = {0: 0, 1: wx.ALIGN_CENTER_VERTICAL, 2: wx.ALIGN_BOTTOM,
287
+ 3: wx.ALIGN_CENTER_VERTICAL, 4:wx.ALIGN_CENTER_VERTICAL}
288
+
289
+ NO_LINE = 0x0
290
+ THIN = 0x1
291
+ MEDIUM = 0x2
292
+ DASHED = 0x3
293
+ DOTTED = 0x4
294
+ THICK = 0x5
295
+ DOUBLE = 0x6
296
+ HAIR = 0x7
297
+ MEDIUM_DASHED = 0x8
298
+ THIN_DASH_DOTTED = 0x9
299
+ MEDIUM_DASH_DOTTED = 0xA
300
+ THIN_DASH_DOT_DOTTED = 0xB
301
+ MEDIUM_DASH_DOT_DOTTED = 0xC
302
+ SLANTED_MEDIUM_DASH_DOTTED = 0xD
303
+
304
+ XF_PEN_STYLES = {NO_LINE: (0, None), THIN: (1, wx.PENSTYLE_SOLID), MEDIUM: (2, wx.PENSTYLE_SOLID),
305
+ DASHED: (1, wx.PENSTYLE_SHORT_DASH), DOTTED: (1, wx.PENSTYLE_DOT),
306
+ THICK: (3, wx.PENSTYLE_SOLID), DOUBLE: (1, wx.PENSTYLE_SOLID), HAIR: (1, wx.PENSTYLE_DOT),
307
+ MEDIUM_DASHED: (2, wx.PENSTYLE_LONG_DASH), THIN_DASH_DOTTED: (1, wx.PENSTYLE_DOT_DASH),
308
+ MEDIUM_DASH_DOTTED: (2, wx.PENSTYLE_DOT_DASH), THIN_DASH_DOT_DOTTED: (1, wx.PENSTYLE_DOT_DASH),
309
+ MEDIUM_DASH_DOT_DOTTED: (2, wx.PENSTYLE_DOT_DASH),
310
+ SLANTED_MEDIUM_DASH_DOTTED: (2, wx.PENSTYLE_DOT_DASH)
311
+ }
312
+
313
+ XF_FONT_FAMILY = {0: wx.FONTFAMILY_SWISS, 1: wx.FONTFAMILY_ROMAN, 2: wx.FONTFAMILY_SWISS,
314
+ 3: wx.FONTFAMILY_MODERN, 4: wx.FONTFAMILY_SCRIPT, 5: wx.FONTFAMILY_DECORATIVE}
315
+
316
+ # Unicode ordinals for Hebrew, Arabic and Syriac
317
+ # I don't know if there are other RTL languages
318
+ RTL_UNICODE = list(range(1424, 1872))
319
+
320
+ # To guess text direction we exclude digits and punctuation
321
+ USELESS_CHARS = string.punctuation + string.digits + " "
322
+
323
+
324
+ #----------------------------------------------------------------------
325
+ # Images used to draw the hatching on Excel cells background
326
+ #----------------------------------------------------------------------
327
+
328
+ _xls_background_01 = PyEmbeddedImage(
329
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAADElE"
330
+ "QVQImWNgIB0AAAA0AAEjQ4N1AAAAAElFTkSuQmCC")
331
+
332
+ #----------------------------------------------------------------------
333
+ _xls_background_02 = PyEmbeddedImage(
334
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAFklE"
335
+ "QVQImWNgYGD4//8/lESwIAC7DABt4hfpI2a12wAAAABJRU5ErkJggg==")
336
+
337
+ #----------------------------------------------------------------------
338
+ _xls_background_03 = PyEmbeddedImage(
339
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAE0lE"
340
+ "QVQImWP4//8/AxqACuGUAQBI+Qv1NTPP3AAAAABJRU5ErkJggg==")
341
+
342
+ #----------------------------------------------------------------------
343
+ _xls_background_04 = PyEmbeddedImage(
344
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAH0lE"
345
+ "QVQImXXJsQ0AIAAEIc79d34LazsSwjbgPFXoOxdcCQwBh7OgqgAAAABJRU5ErkJggg==")
346
+
347
+ #----------------------------------------------------------------------
348
+ _xls_background_05 = PyEmbeddedImage(
349
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAFUlE"
350
+ "QVQImWNgwAUY////D+cwIcsAAEggAwHHgMubAAAAAElFTkSuQmCC")
351
+
352
+ #----------------------------------------------------------------------
353
+ _xls_background_06 = PyEmbeddedImage(
354
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAG0lE"
355
+ "QVQImWNkYGBgYGD4//8/AwMDEwMSwM0BAISAAwUnufp7AAAAAElFTkSuQmCC")
356
+
357
+ #----------------------------------------------------------------------
358
+ _xls_background_07 = PyEmbeddedImage(
359
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAHklE"
360
+ "QVQImWNkYGBgYGD4//8/EgVh/P//H86HikH4APOCFO3yiGicAAAAAElFTkSuQmCC")
361
+
362
+ #----------------------------------------------------------------------
363
+ _xls_background_08 = PyEmbeddedImage(
364
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAHUlE"
365
+ "QVQImWP4////////GSAAzvr//z8jmhADXCUAQSkU7eggG3gAAAAASUVORK5CYII=")
366
+
367
+ #----------------------------------------------------------------------
368
+ _xls_background_09 = PyEmbeddedImage(
369
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAIElE"
370
+ "QVQImWNkYGBgYGD4//8/AwMDEwMy+P//P0QYXQYACtQI/cTE6U0AAAAASUVORK5CYII=")
371
+
372
+ #----------------------------------------------------------------------
373
+ _xls_background_10 = PyEmbeddedImage(
374
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAG0lE"
375
+ "QVQImW3IsQ0AAAjAIPz/6LobGRmgclVfswpsCPmQczsGAAAAAElFTkSuQmCC")
376
+
377
+ #----------------------------------------------------------------------
378
+ _xls_background_11 = PyEmbeddedImage(
379
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAFklE"
380
+ "QVQImWNgQAKM////h3OYkGVQOABvOgMD4NUKkwAAAABJRU5ErkJggg==")
381
+
382
+ #----------------------------------------------------------------------
383
+ _xls_background_12 = PyEmbeddedImage(
384
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAG0lE"
385
+ "QVQImWNkYGD4//8/AwMDAwMDEwMSwM0BAI13AwWY+Mx+AAAAAElFTkSuQmCC")
386
+
387
+ #----------------------------------------------------------------------
388
+ _xls_background_13 = PyEmbeddedImage(
389
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAI0lE"
390
+ "QVQImT3KsQ0AMAyAMMj/P9MhUUcLBCoAmEo9bFn7H/UBXEwMBN75abEAAAAASUVORK5CYII=")
391
+
392
+ #----------------------------------------------------------------------
393
+ _xls_background_14 = PyEmbeddedImage(
394
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAIElE"
395
+ "QVQImT3KoQEAAAwCINz/P7tmI5C2QJKb2t6EYPMBOOUMBIWcMEIAAAAASUVORK5CYII=")
396
+
397
+ #----------------------------------------------------------------------
398
+ _xls_background_15 = PyEmbeddedImage(
399
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAGUlE"
400
+ "QVQImWNgQAKMDAwM////h3CYkGVQOABmQwMDJpgq9gAAAABJRU5ErkJggg==")
401
+
402
+ #----------------------------------------------------------------------
403
+ _xls_background_16 = PyEmbeddedImage(
404
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAHklE"
405
+ "QVQImWNgYGD4//8/lISzIAwEnxEqwMDAyMgIALKwF+2ym+hoAAAAAElFTkSuQmCC")
406
+
407
+ #----------------------------------------------------------------------
408
+ _xls_background_17 = PyEmbeddedImage(
409
+ "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAA3NCSVQICAjb4U/gAAAAIklE"
410
+ "QVQImWNkYGD4//8/AwMDAwMDI5zFwMDABBVjZESXAQAc+AkAQ4bzDAAAAABJRU5ErkJggg==")
411
+
412
+ #----------------------------------------------------------------------
413
+ _xls_background_18 = PyEmbeddedImage(
414
+ "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAECAIAAAA8r+mnAAAAA3NCSVQICAjb4U/gAAAAH0lE"
415
+ "QVQImWNkYGD4//8/AwZgxCrKwMDAhKKKkZGwDgA83QkAy10JvwAAAABJRU5ErkJggg==")
416
+
417
+ #----------------------------------------------------------------------
418
+
419
+
420
+ def SplitThousands(s, tSep=',', dSep='.'):
421
+ """
422
+ Splits a general float on thousands. GIGO on general input.
423
+
424
+ :param `s`: can be a float or a string, representing a number;
425
+ :param `tSep`: the character to be used as thousands separator;
426
+ :param `dSep`: the character to be used as decimal separator.
427
+
428
+ :returns: a string properly formatted with thousands and decimal
429
+ separators in it.
430
+
431
+ :note: This method is used only if Mark Hammonds' `pywin32` package is
432
+ not available to try and format a number in an intelligent way.
433
+
434
+ :note: This code has been obtained from the public domain:
435
+
436
+ http://code.activestate.com/recipes/498181-add-thousands-separator-commas-to-formatted-number/#c14
437
+
438
+ """
439
+
440
+ if not isinstance(s, str):
441
+ s = str(s)
442
+
443
+ cnt = 0
444
+ numChars = dSep + '0123456789'
445
+ ls = len(s)
446
+
447
+ while cnt < ls and s[cnt] not in numChars:
448
+ cnt += 1
449
+
450
+ lhs = s[0:cnt]
451
+ s = s[cnt:]
452
+
453
+ if dSep == '':
454
+ cnt = -1
455
+ else:
456
+ cnt = s.rfind(dSep)
457
+
458
+ if cnt > 0:
459
+ rhs = dSep + s[cnt+1:]
460
+ s = s[:cnt]
461
+ else:
462
+ rhs = ''
463
+
464
+ splt = ''
465
+ while s != '':
466
+ splt = s[-3:] + tSep + splt
467
+ s = s[:-3]
468
+
469
+ return lhs + splt[:-1] + rhs
470
+
471
+
472
+ def ReadExcelCOM(filename, sheetname, rows, cols):
473
+ """
474
+ Reads and Excel spreadsheet (a single worksheet) using Mark Hammonds' `pywin32`
475
+ package. If this package is not available, it returns two empty nested lists.
476
+
477
+ :param `filename`: a valid Excel `.xls` filename;
478
+ :param `sheetname`: the worksheet name inside the Excel file (i.e., the label
479
+ on the workbook tab at the bottom of the workbook);
480
+ :param `rows`: the number of significant rows in the worksheet, as returned
481
+ by `xlrd`;
482
+ :param `cols`: the number of significant columns in the worksheet, as returned
483
+ by `xlrd`.
484
+
485
+ :returns: two nested lists representing the comments (notes) on every cell and
486
+ the WYSIWYG representation of the cell content.
487
+
488
+ :note: If Mark Hammonds' `pywin32` package is not available, this method
489
+ returns two empty nested lists.
490
+ """
491
+
492
+ comments = [["" for i in range(cols)] for j in range(rows)]
493
+ texts = [[None for i in range(cols)] for j in range(rows)]
494
+
495
+ if not _hasWin32:
496
+ return comments, texts
497
+
498
+ try:
499
+ workbook = Excel(filename, sheetname)
500
+
501
+ for i in range(1, rows+1):
502
+ for j in range(1, cols+1):
503
+ texts[i-1][j-1] = workbook.GetText(i, j)
504
+
505
+ comm_range = workbook.GetCommentsRange()
506
+ if comm_range is not None:
507
+ for comm in comm_range:
508
+ comments[comm.Row-1][comm.Column-1] = comm.Comment.Text()
509
+
510
+ workbook.Close()
511
+
512
+ except pywintypes.com_error:
513
+ pass
514
+
515
+ return comments, texts
516
+
517
+
518
+ def FontFromFont(font):
519
+ """
520
+ Creates a copy of the input `font`.
521
+
522
+ :param `font`: an instance of :class:`wx.Font`.
523
+ """
524
+
525
+ new_font = wx.Font(font.GetPointSize(), font.GetFamily(), font.GetStyle(),
526
+ font.GetWeight(), font.GetUnderlined(),
527
+ font.GetFaceName(), font.GetEncoding())
528
+
529
+ return new_font
530
+
531
+
532
+ class Excel(object):
533
+ """
534
+ A simple class that holds a COM interface to Excel.
535
+
536
+ By using the `win32com` module from Mark Hammonds' `pywin32` package, we
537
+ can manipulate various workbook/worksheet methods inside this class.
538
+ """
539
+
540
+ def __init__(self, filename, sheetname):
541
+ """
542
+ Default class constructor.
543
+
544
+ :param `filename`: a valid Excel `.xls` filename;
545
+ :param `sheetname`: the worksheet name inside the Excel file (i.e., the label
546
+ on the workbook tab at the bottom of the workbook).
547
+ """
548
+
549
+ self.xlApp = Dispatch('Excel.Application')
550
+ self.filename = filename
551
+ self.xlBook = self.xlApp.Workbooks.Open(filename)
552
+ self.sheet = self.xlBook.Worksheets(sheetname)
553
+
554
+ self.xlApp.Visible = 0
555
+
556
+
557
+ def Close(self, save=False):
558
+ """
559
+ Closes the Excel workbook, interrupting the COM interface.
560
+
561
+ :param `save`: ``True`` to save the changes you made to the workbook,
562
+ ``False`` otherwise.
563
+ """
564
+
565
+ self.xlBook.Close(SaveChanges=save)
566
+ del self.xlApp
567
+
568
+
569
+ def GetCommentsRange(self):
570
+ """
571
+ Returns a range of cells containing comments, using the VBA API.
572
+
573
+ """
574
+
575
+ try:
576
+ return self.sheet.Cells.SpecialCells(-4144)
577
+ except pywintypes.com_error:
578
+ return None
579
+
580
+
581
+ def GetText(self, row, col):
582
+ """
583
+ Returns the WYSIWYG text contained in a cell.
584
+
585
+ :param `row`: the row in which the cell lives;
586
+ :param `col`: the column in which the cell lives.
587
+
588
+ :note: The `row` and `col` parameters are not real Python index, as they
589
+ use the Excel indexing mode (i.e., first index is 1 and not 0).
590
+ """
591
+
592
+ cell = self.sheet.Cells(row, col)
593
+
594
+ if cell:
595
+ return cell.Text
596
+
597
+
598
+ class XLSText(object):
599
+ """
600
+ This is a class which holds information about the cell content, in terms
601
+ of actual cell value, font, text colour, alignment and formatting.
602
+ """
603
+
604
+ def __init__(self, book, cell, xf_index, display_text=None, hyperlink=None, default_width=10):
605
+ """
606
+ Default class constructor.
607
+
608
+ :param `book`: an instance of the `xlrd.Book` class;
609
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
610
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
611
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
612
+ :param `display_text`: if Mark Hammonds' `pywin32` package is available,
613
+ this is the WYSIWYG cell content;
614
+ :param `hyperlink`: if this cell contains a hyperlink, it will be displayed
615
+ accordingly;
616
+ :param `default_width`: this is the default width of the text in 1/256
617
+ of the width of the zero character, using default Excel font (first FONT
618
+ record in the Excel file).
619
+
620
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
621
+ parameter will always be ``None`` as this feature is available only in
622
+ `xlrd` 0.7.2 (SVN).
623
+ """
624
+
625
+ XFClass = book.xf_list[xf_index]
626
+
627
+ font = book.font_list[XFClass.font_index]
628
+ self.font = self.CreateFont(font)
629
+
630
+ text_colour = book.colour_map[font.colour_index]
631
+ self.text_colour = self.CreateTextColour(text_colour)
632
+
633
+ if display_text is not None:
634
+ self.value = display_text
635
+ else:
636
+ format = book.format_map[XFClass.format_key]
637
+ self.CreateFormat(format, cell, book.datemode)
638
+
639
+ alignment = XFClass.alignment
640
+ self.CreateAlignment(alignment, default_width)
641
+
642
+ if hyperlink is not None:
643
+ self.SetupHyperlink(hyperlink)
644
+ else:
645
+ self.tooltip = None
646
+
647
+
648
+ def CreateFont(self, font):
649
+ """
650
+ Creates a suitable wxPython font starting from an Excel font.
651
+
652
+ :param `font`: an instance of `xlrd.formatting.Font` class.
653
+
654
+ :note: There is currently no support for strikethrough fonts, although
655
+ `xlrd` correctly reports this format. The issue is a bug in wxWidgets
656
+ itself which doesn't allow the creation of strikethrough fonts. See
657
+ (http://trac.wxwidgets.org/ticket/9907).
658
+ """
659
+
660
+ style, bold, underline = wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False
661
+ if font.italic:
662
+ style = wx.FONTSTYLE_ITALIC
663
+ if font.underline_type > 0:
664
+ underline = True
665
+ if font.weight > 600:
666
+ bold = wx.FONTWEIGHT_BOLD
667
+
668
+ family = XF_FONT_FAMILY[font.family]
669
+ name = font.name
670
+ size = int(font.height/20.0)
671
+
672
+ if font.escapement > 0:
673
+ # subscript/superscript
674
+ size = int(size*0.7)
675
+
676
+ # No support for strike-through fonts in wxWidgets
677
+ # if font.struck_out:
678
+ # style = wx.FONTFLAG_DEFAULT
679
+ # if bold:
680
+ # style += wx.FONTFLAG_BOLD
681
+ # if underline:
682
+ # style += wx.FONTFLAG_UNDERLINED
683
+ # if font.italic:
684
+ # style += wx.FONTFLAG_ITALIC
685
+ #
686
+ # style += wx.FONTFLAG_STRIKETHROUGH
687
+ # self.font = wx.FFont(size, family, style, name.encode())
688
+ # else:
689
+
690
+ return wx.Font(size, family, style, bold, underline, name.encode())
691
+
692
+
693
+ def CreateTextColour(self, text_colour):
694
+ """
695
+ Creates a suitable wxPython colour for the text starting from a `xlrd`
696
+ tuple representing this colour.
697
+
698
+ :param `text_colour`: a tuple representing the RGB components of the
699
+ colour. If `text_colour` is ``None``, use the default ``wx.SYS_COLOUR_WINDOWTEXT``.
700
+ """
701
+
702
+ if text_colour is not None:
703
+ text_colour = wx.Colour(*text_colour)
704
+ else:
705
+ text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
706
+
707
+ return text_colour
708
+
709
+
710
+ def CreateAlignment(self, alignment, default_width):
711
+ """
712
+ Creates a suitable wxPython alignment flag for the text starting from a
713
+ `xlrd` class representing this alignment.
714
+
715
+ :param `alignment`: an instance of `xlrd.formatting.XFAlignment` class;
716
+ :param `default_width`: this is the default width of the text in 1/256
717
+ of the width of the zero character, using default Excel font (first FONT
718
+ record in the Excel file).
719
+ """
720
+
721
+ hor_align, vert_align = alignment.hor_align, alignment.vert_align
722
+ self.horizontal_alignment = HORIZONTAL_ALIGNMENTS[hor_align]
723
+ self.vertical_alignment = VERTICAL_ALIGNMENTS[vert_align]
724
+
725
+ self.indent_level = alignment.indent_level
726
+ self.shrink_to_fit = alignment.shrink_to_fit
727
+ self.text_wrapped = alignment.text_wrapped
728
+
729
+ text_direction = 1
730
+
731
+ if alignment.text_direction == 0:
732
+ for char in self.value:
733
+ if char not in USELESS_CHARS:
734
+ if ord(char) in RTL_UNICODE:
735
+ text_direction = 2
736
+ break
737
+
738
+ self.text_direction = text_direction
739
+ self.default_width = default_width
740
+
741
+ if alignment.rotation > 90:
742
+ self.rotation = 90 - alignment.rotation
743
+ else:
744
+ self.rotation = alignment.rotation
745
+
746
+
747
+ def CreateFormat(self, format, cell, datemode):
748
+ """
749
+ This method tries to guess the best format to apply to the current text
750
+ value.
751
+
752
+ :param `format`: an instance of `xlrd.formatting.Format` class;
753
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
754
+ :param `datemode`: the datemode associated with this Excel workbook.
755
+
756
+ :note: This method is used only if Mark Hammonds' `pywin32` package is
757
+ not available to try and format the cell text in an intelligent way.
758
+
759
+ .. warning::
760
+
761
+ The formatting applied by this method is severely limited; for
762
+ instance, you won't probably get the exact WYSIWYG between the Excel
763
+ spreadsheet and :class:`XLSGrid`.
764
+ """
765
+
766
+ ctype, value = cell.ctype, cell.value
767
+
768
+ self.value = "%s"%value
769
+ isDate = False
770
+
771
+ if ctype == xlrd.XL_CELL_DATE:
772
+ value = xlrd.xldate_as_tuple(value, datemode)
773
+ isDate = True
774
+ elif ctype in [xlrd.XL_CELL_EMPTY, xlrd.XL_CELL_BLANK]:
775
+ return
776
+ elif ctype == xlrd.XL_CELL_TEXT:
777
+ self.value = "%s"%value
778
+ return
779
+ elif ctype == xlrd.XL_CELL_ERROR:
780
+ value = xlrd.error_text_from_code(ctype)
781
+ self.value = "%s"%value
782
+ return
783
+
784
+ self.FormatString(value, isDate, format.format_str)
785
+
786
+
787
+ def FormatString(self, value, isDate, format_str):
788
+ """
789
+ This method tries to guess the best format to apply to the current text
790
+ value.
791
+
792
+ :param `value`: the actual raw cell text value;
793
+ :param `isDate`: ``True`` if this value represents a `xlrd` date object,
794
+ ``False`` otherwise;
795
+ :param `format_str`: the actual formatting string as extracted from Excel.
796
+
797
+ :note: This method is used only if Mark Hammonds' `pywin32` package is
798
+ not available to try and format the cell text in an intelligent way.
799
+
800
+ .. warning::
801
+
802
+ The formatting applied by this method is severely limited; for
803
+ instance, you won't probably get the exact WYSIWYG between the Excel
804
+ spreadsheet and :class:`XLSGrid`.
805
+
806
+ """
807
+
808
+ if "General" in format_str:
809
+ self.value = "%s"%value
810
+ return
811
+
812
+ number_format = format_str
813
+ currency = percentage = ""
814
+
815
+ if not isDate:
816
+ symbol = ""
817
+ split = format_str.split()
818
+ if len(split) > 1:
819
+ # Accounting and currency shit
820
+ currency = split[0].split(".")[0] + "."
821
+ number_format = ".".join(split[1:])
822
+
823
+ if "%" in number_format:
824
+ percentage = "%"
825
+ value = 100*value
826
+ number_format = number_format[0:-1]
827
+
828
+ representation = "%d"
829
+ if "." in number_format:
830
+ split = number_format.split(".")
831
+ num_decimals = len(split[1])
832
+ representation = "%0." + str(num_decimals) + "f"
833
+
834
+ try:
835
+ value = representation%value
836
+ except ValueError:
837
+ # Fall back to string
838
+ value = str(value)
839
+
840
+ if "#," in number_format:
841
+ value = SplitThousands(value)
842
+
843
+ value = currency + value + percentage
844
+
845
+ else:
846
+ number_format = format_str.replace("\\", "")
847
+ number_format = number_format.replace("-", "-%").replace("/", "/%")
848
+ value = datetime.datetime(*value)
849
+ try:
850
+ value = value.strftime(number_format)
851
+ except (ValueError, TypeError):
852
+ value = value.strftime("%d.%m.%Y")
853
+
854
+ self.value = value
855
+
856
+
857
+ def SetupHyperlink(self, hyperlink):
858
+ """
859
+ Sets up the cell text value in case it represents a hyperlink.
860
+
861
+ :param `hyperlink`: an instance of `xlrd.sheet.hyperlink`.
862
+
863
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
864
+ parameter will always be ``None`` as this feature is available only in
865
+ `xlrd` 0.7.2 (SVN).
866
+ """
867
+
868
+ url = (hyperlink.url_or_path and [hyperlink.url_or_path] or [hyperlink.textmark])[0]
869
+ self.tooltip = url
870
+
871
+
872
+ def IsHyperLink(self):
873
+ """
874
+ Returns whether the cell text is representing a hyperlink.
875
+
876
+ :returns: ``True`` if the cell text represents a hyperlink, ``False``
877
+ otherwise.
878
+ """
879
+
880
+ return self.tooltip is not None
881
+
882
+
883
+ def CombineAttr(self, attr):
884
+ """
885
+ Combines the input attribute `attr` with the features of the :class:`XLSText` class.
886
+
887
+ :param `attr`: an instance of :class:`grid.GridCellAttr`.
888
+ """
889
+
890
+ attr.SetAlignment(self.horizontal_alignment, self.vertical_alignment)
891
+ attr.SetTextColour(self.text_colour)
892
+ attr.SetFont(self.font)
893
+
894
+
895
+ def GetValue(self):
896
+ """ Returns the string representation of the cell text value. """
897
+
898
+ return self.value
899
+
900
+
901
+ def Draw(self, dc, rect):
902
+ """
903
+ Actually draws the text value on a grid cell.
904
+
905
+ :param `dc`: an instance of :class:`wx.DC`;
906
+ :param `rect`: an instance of :class:`wx.Rect`, representing the cell rectangle.
907
+ """
908
+
909
+ new_rect = wx.Rect(*rect)
910
+
911
+ xshift = yshift = 0
912
+ if self.rotation:
913
+ xshift = cos(self.rotation*pi/180)
914
+ yshift = sin(self.rotation*pi/180)
915
+
916
+ dc.SetTextForeground(self.text_colour)
917
+ dc.SetFont(self.font)
918
+
919
+ value = self.value
920
+ text_width, text_height = dc.GetTextExtent(value)
921
+
922
+ default_width = int(round(float(self.default_width)*text_width/256.0))
923
+
924
+ indentation = int(256.0*default_width/float(self.default_width))
925
+
926
+ if xshift == 0 and self.indent_level:
927
+ new_rect.SetLeft(new_rect.x + indentation)
928
+ else:
929
+ if self.horizontal_alignment == wx.ALIGN_LEFT:
930
+ new_rect.SetLeft(new_rect.x + 3)
931
+ elif self.horizontal_alignment == wx.ALIGN_RIGHT:
932
+ new_rect.SetWidth(new_rect.width - 1)
933
+
934
+ new_width = rect.width
935
+
936
+ if xshift > 0:
937
+ new_width = new_width/xshift
938
+
939
+ if self.shrink_to_fit:
940
+
941
+ font = FontFromFont(self.font)
942
+ point_size = font.GetPointSize()
943
+
944
+ while 1:
945
+ value = wordwrap(self.value, new_width, dc)
946
+ if "\n" not in value or point_size < 2:
947
+ break
948
+
949
+ point_size -= 1
950
+ font.SetPointSize(point_size)
951
+ dc.SetFont(font)
952
+
953
+ elif self.text_wrapped:
954
+
955
+ value = wordwrap(self.value, new_width, dc)
956
+ text_width, text_height, dummy = dc.GetFullMultiLineTextExtent(value)
957
+
958
+ if self.rotation:
959
+ if self.shrink_to_fit:
960
+ text_width, text_height = dc.GetTextExtent(value)
961
+
962
+ xc, yc = (rect.x+rect.width/2, rect.y+rect.height/2)
963
+ xp = xc - (text_width/2)*xshift - (text_height/2)*yshift
964
+ yp = yc + (text_width/2)*yshift - (text_height/2)*xshift
965
+
966
+ dc.DrawRotatedText(value, int(xp), int(yp), self.rotation)
967
+
968
+ else:
969
+
970
+ dc.DrawLabel(value, new_rect, self.horizontal_alignment|self.vertical_alignment)
971
+
972
+
973
+ class XLSRichText(XLSText):
974
+ """
975
+ This is a class which holds information about the cell content, in terms
976
+ of actual cell value, font, text colour, alignment and formatting. In addition
977
+ to what :class:`XLSText` does, this class attempts to handle cells with rich text
978
+ content.
979
+ """
980
+
981
+ def __init__(self, book, cell, xf_index, display_text=None, hyperlink=None, rich_text=None, default_width=10):
982
+ """
983
+ Default class constructor.
984
+
985
+ :param `book`: an instance of the `xlrd.Book` class;
986
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
987
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
988
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
989
+ :param `display_text`: if Mark Hammonds' `pywin32` package is available,
990
+ this is the WYSIWYG cell content;
991
+ :param `hyperlink`: if this cell contains a hyperlink, it will be displayed
992
+ accordingly;
993
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
994
+ will do its best to render the text as rich text;
995
+ :param `default_width`: this is the default width of the text in 1/256
996
+ of the width of the zero character, using default Excel font (first FONT
997
+ record in the Excel file).
998
+
999
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
1000
+ parameter will always be ``None`` as this feature is available only in
1001
+ `xlrd` 0.7.2 (SVN).
1002
+
1003
+ :note: If you are using version 0.7.1 or lower for `xlrd`, this class will
1004
+ note be used by :class:`XLSGrid`.
1005
+
1006
+ .. warning::
1007
+
1008
+ This class currently supports only single-line non-rotated text,
1009
+ and it discards properties like `shrink-to-fit` and `wrapping`.
1010
+
1011
+ """
1012
+
1013
+ XLSText.__init__(self, book, cell, xf_index, display_text, hyperlink, default_width)
1014
+
1015
+ self.BuildChunks(book, xf_index, rich_text)
1016
+
1017
+
1018
+ def BuildChunks(self, book, xf_index, rich_text):
1019
+ """
1020
+ Splits the cell content accordingly to their rich text format index.
1021
+
1022
+ :param `book`: an instance of the `xlrd.Book` class;
1023
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
1024
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
1025
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
1026
+ will do its best to render the text as rich text.
1027
+ """
1028
+
1029
+ XFClass = book.xf_list[xf_index]
1030
+ offset, index = rich_text[0]
1031
+
1032
+ if offset != 0:
1033
+ new_tuple = (0, XFClass.font_index)
1034
+ rich_text.insert(0, new_tuple)
1035
+
1036
+ value = self.value
1037
+ rich_text.append((len(value), rich_text[-1][1]))
1038
+ attributes = []
1039
+
1040
+ for indx in range(len(rich_text)-1):
1041
+ offset_start, index_start = rich_text[indx]
1042
+ offset_end, index_end = rich_text[indx+1]
1043
+
1044
+ chunk = value[offset_start:offset_end]
1045
+
1046
+ font = book.font_list[index_start]
1047
+ ffont = self.CreateFont(font)
1048
+ text_colour = book.colour_map[font.colour_index]
1049
+ colour = self.CreateTextColour(text_colour)
1050
+
1051
+ ffont.escapement = font.escapement
1052
+ attributes.append([chunk, ffont, colour])
1053
+
1054
+ self.attributes = attributes
1055
+
1056
+
1057
+ def Measure(self, dc):
1058
+ """
1059
+ Convenience method to measure the maximum height and total width of all
1060
+ the chunks of text composing our rich text string.
1061
+
1062
+ :param `dc`: an instance of :class:`wx.DC`.
1063
+ """
1064
+
1065
+ maxH = -1
1066
+ full_width = 0
1067
+ for chunk, font, colour in self.attributes:
1068
+ dc.SetFont(font)
1069
+ width, height, descent, leading = dc.GetFullTextExtent(chunk, font)
1070
+ maxH = max(maxH, height-leading)
1071
+ full_width += width
1072
+
1073
+ return maxH, full_width
1074
+
1075
+
1076
+ def Draw(self, dc, rect):
1077
+ """
1078
+ Actually draws all the chunks of text on a grid cell, one by one.
1079
+
1080
+ :param `dc`: an instance of :class:`wx.DC`;
1081
+ :param `rect`: an instance of :class:`wx.Rect`, representing the cell rectangle.
1082
+ """
1083
+
1084
+ new_rect = wx.Rect(*rect)
1085
+
1086
+ text_width, text_height = dc.GetTextExtent(self.value)
1087
+ default_width = int(round(float(self.default_width)*text_width/256.0))
1088
+ indentation = int(256.0*default_width/float(self.default_width))
1089
+
1090
+ maxH, full_width = self.Measure(dc)
1091
+
1092
+ if self.indent_level:
1093
+ new_rect.SetLeft(new_rect.x + indentation)
1094
+ else:
1095
+ if self.horizontal_alignment == wx.ALIGN_LEFT:
1096
+ new_rect.SetLeft(new_rect.x + 3)
1097
+ elif self.horizontal_alignment == wx.ALIGN_RIGHT:
1098
+ new_rect.SetLeft(new_rect.x + (new_rect.width - full_width) - 1)
1099
+ else:
1100
+ space = int((new_rect.width - full_width)/2.0)
1101
+ new_rect.SetLeft(new_rect.x + space)
1102
+ new_rect.SetWidth(full_width+space)
1103
+
1104
+ if self.vertical_alignment == wx.ALIGN_TOP:
1105
+ vspace = 0
1106
+ elif self.vertical_alignment == wx.ALIGN_BOTTOM:
1107
+ vspace = (new_rect.height - maxH - 1)
1108
+ else:
1109
+ vspace = int((new_rect.height - maxH)/2.0)
1110
+
1111
+ start = new_rect.x
1112
+ y = new_rect.y
1113
+
1114
+ for chunk, font, colour in self.attributes:
1115
+ dc.SetTextForeground(colour)
1116
+ dc.SetFont(font)
1117
+ width, height, descent, leading = dc.GetFullTextExtent(chunk, font)
1118
+ if font.escapement > 0:
1119
+ height = height*0.7
1120
+
1121
+ ypos = y-height+maxH+vspace
1122
+
1123
+ if font.escapement == 1:
1124
+ ypos = ypos - maxH + height
1125
+
1126
+ dc.DrawText(chunk, start, int(ypos))
1127
+ start += width
1128
+
1129
+
1130
+ class XLSBackground(object):
1131
+ """
1132
+ This is a class which holds information about the cell background, in terms
1133
+ of background colour and background pattern (hatching).
1134
+ """
1135
+
1136
+ def __init__(self, book, xf_index):
1137
+ """
1138
+ Default class constructor.
1139
+
1140
+ :param `book`: an instance of the `xlrd.Book` class;
1141
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
1142
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`).
1143
+ """
1144
+
1145
+ XFClass = book.xf_list[xf_index]
1146
+
1147
+ background = XFClass.background
1148
+ background_colour = book.colour_map[background.background_colour_index]
1149
+ pattern_colour = book.colour_map[background.pattern_colour_index]
1150
+ fill_pattern = background.fill_pattern
1151
+
1152
+ self.CreateBackgroundColour(background_colour, pattern_colour, fill_pattern)
1153
+
1154
+
1155
+ def CreateBackgroundColour(self, background_colour, pattern_colour, fill_pattern):
1156
+ """
1157
+ Creates a suitable wxPython colour for the cell background starting from
1158
+ a `xlrd` tuple representing this colour.
1159
+
1160
+ :param `background_colour`: a tuple representing the RGB components of the
1161
+ cell background colour. If `background_colour` is ``None``, use the
1162
+ default ``wx.SYS_COLOUR_WINDOW``;
1163
+ :param `pattern_colour`: a tuple representing the RGB components of the
1164
+ cell pattern colour;
1165
+ :param `fill_pattern`: the pattern to use to draw hatches on top of the
1166
+ background.
1167
+ """
1168
+
1169
+ if background_colour is not None:
1170
+ background_colour = wx.Colour(*background_colour)
1171
+ else:
1172
+ background_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
1173
+
1174
+ if pattern_colour is not None:
1175
+ pattern_colour = wx.Colour(*pattern_colour)
1176
+
1177
+ self.background_brush = wx.Brush(background_colour)
1178
+ self.background_colour = background_colour
1179
+
1180
+ self.fill_brush = None
1181
+
1182
+ if fill_pattern <= 0:
1183
+ return
1184
+
1185
+ r, g, b, a = pattern_colour
1186
+
1187
+ fill_image = eval("_xls_background_%02d.GetImage()"%fill_pattern)
1188
+ fill_image.Replace(0, 0, 0, r, g, b)
1189
+ r, g, b = background_colour.Red(), background_colour.Green(), background_colour.Blue()
1190
+ fill_image.Replace(255, 255, 255, r, g, b)
1191
+ fill_bitmap = fill_image.ConvertToBitmap()
1192
+
1193
+ self.fill_brush = wx.Brush(fill_bitmap)
1194
+
1195
+
1196
+ def CombineAttr(self, attr):
1197
+ """
1198
+ Combines the input attribute `attr` with the features of the :class:`XLSBackground` class.
1199
+
1200
+ :param `attr`: an instance of :class:`grid.GridCellAttr`.
1201
+ """
1202
+
1203
+ attr.SetBackgroundColour(self.background_colour)
1204
+ return attr
1205
+
1206
+
1207
+ def Draw(self, dc, rect):
1208
+ """
1209
+ Actually draws the cell background and pattern hatching on a grid cell.
1210
+
1211
+ :param `dc`: an instance of :class:`wx.DC`;
1212
+ :param `rect`: an instance of :class:`wx.Rect`, representing the cell rectangle.
1213
+ """
1214
+
1215
+ dc.SetClippingRegion(rect)
1216
+
1217
+ dc.SetBackgroundMode(wx.SOLID)
1218
+ dc.SetBrush(self.background_brush)
1219
+ dc.SetPen(wx.TRANSPARENT_PEN)
1220
+ dc.DrawRectangle(rect)
1221
+
1222
+ if self.fill_brush:
1223
+
1224
+ dc.SetBrush(self.fill_brush)
1225
+ dc.SetBackgroundMode(wx.TRANSPARENT)
1226
+ dc.DrawRectangle(rect)
1227
+
1228
+ dc.DestroyClippingRegion()
1229
+
1230
+
1231
+ class XLSBorder(object):
1232
+ """
1233
+ This is a class which holds information about a single cell border, in terms
1234
+ of its location (top, left, bottom, right, diagonal), its colour, width and
1235
+ shape.
1236
+ """
1237
+
1238
+ def __init__(self, location, line_style, border_colour, default_colour, diagonals):
1239
+ """
1240
+ Default class constructor.
1241
+
1242
+ :param `location`: the actual border location (top, left, bottom, right,
1243
+ diagonal);
1244
+ :param `line_style`: the line style used by Excel to draw this border;
1245
+ :param `border_colour`: the colour used by Excel to draw this border;
1246
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
1247
+ border lines;
1248
+ :param `diagonals`: a tuple containing whether or not to draw the up and down
1249
+ diagonal borders.
1250
+ """
1251
+
1252
+ self.draw_priority = 2
1253
+
1254
+ if line_style == NO_LINE:
1255
+
1256
+ if border_colour == (0, 0, 0):
1257
+ self.draw_priority = 0
1258
+ border_colour = wx.Colour(*default_colour)
1259
+ else:
1260
+ self.draw_priority = 1
1261
+ border_colour = wx.BLACK
1262
+
1263
+ self.pen = wx.Pen(border_colour, 1, wx.PENSTYLE_SOLID)
1264
+ pen_style = THIN
1265
+
1266
+ else:
1267
+
1268
+ if border_colour == (0, 0, 0):
1269
+ border_colour = wx.Colour(*default_colour)
1270
+ self.draw_priority = 2
1271
+ elif border_colour is None:
1272
+ border_colour = wx.BLACK
1273
+ self.draw_priority = 2
1274
+ else:
1275
+ border_colour = wx.Colour(*border_colour)
1276
+
1277
+ pen_width, pen_style = XF_PEN_STYLES[line_style]
1278
+ if pen_width > 2:
1279
+ self.draw_priority = 4
1280
+ elif pen_width > 1:
1281
+ self.draw_priority = 3
1282
+
1283
+ self.pen = wx.Pen(border_colour, pen_width, pen_style)
1284
+
1285
+ self.diagonals = diagonals
1286
+ self.location = location
1287
+ self.pen_style = pen_style
1288
+ self.line_style = line_style
1289
+
1290
+
1291
+ def Draw(self, dc, rect):
1292
+ """
1293
+ Actually draws the cell border.
1294
+
1295
+ :param `dc`: an instance of :class:`wx.DC`;
1296
+ :param `rect`: an instance of :class:`wx.Rect`, representing the cell rectangle.
1297
+ """
1298
+
1299
+ dc.SetBackgroundMode(wx.TRANSPARENT)
1300
+ dc.SetPen(self.pen)
1301
+
1302
+ if self.location == DIAGONAL:
1303
+ self.DrawDiagonals(dc, rect)
1304
+ else:
1305
+ self.DrawBorder(dc, rect)
1306
+
1307
+
1308
+ def DrawDiagonals(self, dc, rect):
1309
+ """
1310
+ Actually draws the cell diagonal border.
1311
+
1312
+ :param `dc`: an instance of :class:`wx.DC`;
1313
+ :param `rect`: an instance of :class:`wx.Rect`, representing the cell rectangle.
1314
+ """
1315
+
1316
+ diag_up, diag_down = self.diagonals
1317
+
1318
+ if diag_down:
1319
+ xstart, ystart = rect.GetTopLeft()
1320
+ xend, yend = rect.GetBottomRight()
1321
+
1322
+ if self.line_style == DOUBLE:
1323
+ dc.DrawLine(xstart+2, ystart, xend, yend-2)
1324
+ dc.DrawLine(xstart, ystart+2, xend-2, yend)
1325
+ else:
1326
+ dc.DrawLine(xstart, ystart, xend, yend)
1327
+
1328
+ if diag_up:
1329
+
1330
+ xstart, ystart = rect.GetBottomLeft()
1331
+ xend, yend = rect.GetTopRight()
1332
+
1333
+ if self.line_style == DOUBLE:
1334
+ dc.DrawLine(xstart, ystart-2, xend-2, yend)
1335
+ dc.DrawLine(xstart+2, ystart, xend, yend+2)
1336
+ else:
1337
+ dc.DrawLine(xstart, ystart, xend, yend)
1338
+
1339
+
1340
+ def DrawBorder(self, dc, rect):
1341
+ """
1342
+ Actually draws the cell border (one of left, right, bottom, top).
1343
+
1344
+ :param `dc`: an instance of :class:`wx.DC`;
1345
+ :param `rect`: an instance of :class:`wx.Rect`, representing the cell rectangle.
1346
+ """
1347
+
1348
+ pen_width = self.pen.GetWidth()
1349
+ location = self.location
1350
+ new_rect = wx.Rect(*rect)
1351
+
1352
+ x, y, w, h = new_rect
1353
+ line_style = self.line_style
1354
+
1355
+ shift = 0
1356
+ if pen_width == 2:
1357
+ shift = pen_width - 1
1358
+ if pen_width > 2:
1359
+ shift = pen_width - 2
1360
+
1361
+ if location == BOTTOM:
1362
+
1363
+ if self.draw_priority < 2:
1364
+ return
1365
+
1366
+ if line_style == DOUBLE:
1367
+ dc.DrawLine(x, y+h-1, x+w, y+h-1)
1368
+ dc.DrawLine(x, y+h+1, x+w, y+h+1)
1369
+ else:
1370
+ dc.DrawLine(x+1, y+h, x+w, y+h)
1371
+
1372
+
1373
+ elif location == TOP:
1374
+
1375
+ if line_style == DOUBLE:
1376
+ dc.DrawLine(x, y-1, x+w, y-1)
1377
+ dc.DrawLine(x, y+1, x+w, y+1)
1378
+ else:
1379
+ dc.DrawLine(x+1, y+shift, x+w, y+shift)
1380
+
1381
+ elif location == LEFT:
1382
+
1383
+ if line_style == DOUBLE:
1384
+ dc.DrawLine(x-1, y, x-1, y+h)
1385
+ dc.DrawLine(x+1, y, x+1, y+h)
1386
+ else:
1387
+ dc.DrawLine(x+shift, y+1, x+shift, y+h)
1388
+
1389
+ elif location == RIGHT:
1390
+
1391
+ if self.draw_priority < 2:
1392
+ return
1393
+
1394
+ if line_style == DOUBLE:
1395
+ dc.DrawLine(x+w-1, y, x+w-1, y+h)
1396
+ dc.DrawLine(x+w+1, y, x+w+1, y+h)
1397
+ else:
1398
+ dc.DrawLine(x+w+1, y+1, x+w+1, y+h)
1399
+
1400
+
1401
+ class XLSBorderFactory(object):
1402
+ """
1403
+ This is a factory class which holds information about all the borders in a
1404
+ cell. Its implementation and use is merely to simplify the handling of the
1405
+ different cell borders (left, top, bottom, right, diagonal).
1406
+ """
1407
+
1408
+ def __init__(self, book, border, default_colour):
1409
+ """
1410
+ Default class constructor.
1411
+
1412
+ :param `book`: an instance of the `xlrd.Book` class;
1413
+ :param `border`: an instance of `xlrd.formatting.XFBorder` class;
1414
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
1415
+ border lines.
1416
+ """
1417
+
1418
+ borders = {}
1419
+ diagonals = border.diag_up, border.diag_down
1420
+
1421
+ for label, location in list(XF_BORDER_STYLES.items()):
1422
+ line_style = getattr(border, "%s_line_style"%label)
1423
+ colour_index = getattr(border, "%s_colour_index"%label)
1424
+ border_colour = book.colour_map[colour_index]
1425
+
1426
+ border_class = XLSBorder(location, line_style, border_colour, default_colour, diagonals)
1427
+ borders[location] = border_class
1428
+
1429
+ self.draw_priority = sorted(list(borders.values()), key=attrgetter('draw_priority'))
1430
+
1431
+
1432
+ def Draw(self, dc, rect):
1433
+ """
1434
+ Actually draws all the cell borders based on their drawing priority.
1435
+
1436
+ :param `dc`: an instance of :class:`wx.DC`;
1437
+ :param `rect`: an instance of :class:`wx.Rect`, representing the cell rectangle.
1438
+
1439
+ :note: The drawing priority is assigned depending on if the border is a
1440
+ custom one or not. Customized borders are drawn last.
1441
+ """
1442
+
1443
+ for border in self.draw_priority:
1444
+ border.Draw(dc, rect)
1445
+
1446
+
1447
+ class XLSComment(object):
1448
+ """
1449
+ This is a class which holds information about the content of the "comment
1450
+ window" (aka note) in Excel.
1451
+
1452
+ :note: If Mark Hammonds' `pywin32` package is not available, this class can
1453
+ not be used.
1454
+ """
1455
+
1456
+ def __init__(self, comment):
1457
+ """
1458
+ Default class constructor.
1459
+
1460
+ :param `comment`: the actual text contained in the Excel cell comment (note).
1461
+ """
1462
+
1463
+ self.comment = comment
1464
+
1465
+
1466
+ def Draw(self, dc, rect):
1467
+ """
1468
+ Actually draws a small red triangle in the top-right corder of the cell
1469
+ to indicate that a comment is present.
1470
+
1471
+ :param `dc`: an instance of :class:`wx.DC`;
1472
+ :param `rect`: an instance of :class:`wx.Rect`, representing the cell rectangle.
1473
+ """
1474
+
1475
+ right = rect.GetTopRight()
1476
+ points = [wx.Point(right.x-5, right.y),
1477
+ right,
1478
+ wx.Point(right.x, right.y+5)]
1479
+
1480
+ dc.SetBrush(wx.RED_BRUSH)
1481
+ dc.SetPen(wx.RED_PEN)
1482
+ dc.DrawPolygon(points)
1483
+
1484
+
1485
+ class XLSCell(object):
1486
+ """
1487
+ This is a class which holds information about a single cell in :class:`XLSGrid`.
1488
+ It stores (via auxiliary classes), all details about cell background, text,
1489
+ font, colours and borders.
1490
+ """
1491
+
1492
+ def __init__(self, book, cell, xf_index, xls_text, xls_comment, hyperlink, rich_text, default_width, default_colour):
1493
+ """
1494
+ Default class constructor.
1495
+
1496
+ :param `book`: an instance of the `xlrd.Book` class;
1497
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
1498
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
1499
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
1500
+ :param `xls_text`: the actual WYSIWYG cell text, if available;
1501
+ :param `xls_comment`: the cell comment (note), if any;
1502
+ :param `hyperlink`: an instance of `xlrd.sheet.hyperlink`;
1503
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
1504
+ will do its best to render the text as rich text;
1505
+ :param `default_width`: this is the default width of the text in 1/256
1506
+ of the width of the zero character, using default Excel font (first FONT
1507
+ record in the Excel file);
1508
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
1509
+ border lines.
1510
+
1511
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
1512
+ parameter will always be ``None`` as this feature is available only in
1513
+ `xlrd` 0.7.2 (SVN).
1514
+
1515
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the `rich_text`
1516
+ parameter will always be ``None`` as this feature is available only in
1517
+ `xlrd` 0.7.2 (SVN).
1518
+
1519
+ :note: if Mark Hammonds' `pywin32` package is not available, the `xls_text`
1520
+ parameter will almost surely not be the WYSIWYG representation of the cell
1521
+ text.
1522
+
1523
+ :note: If Mark Hammonds' `pywin32` package is not available, the `xls_comment`
1524
+ parameter will always be ``None``.
1525
+ """
1526
+
1527
+ self.size = 1, 1
1528
+
1529
+ self.comment = None
1530
+ self.hyperlink = None
1531
+
1532
+ self.SetupCell(book, cell, xf_index, xls_text, xls_comment, hyperlink, rich_text, default_width, default_colour)
1533
+
1534
+
1535
+ def SetupCell(self, book, cell, xf_index, xls_text, xls_comment, hyperlink, rich_text, default_width, default_colour):
1536
+ """
1537
+ Actually sets up the :class:`XLSCell` class. This is an auxiliary method to
1538
+ avoid cluttering the :meth:`~xlsgrid.XLSCell.__init__` method.
1539
+
1540
+ :param `book`: an instance of the `xlrd.Book` class;
1541
+ :param `cell`: an instance of `xlrd.sheet.Cell` class;
1542
+ :param `xf_index`: an index into `xlrd.Book.xf_list`, which holds a
1543
+ reference to the `xlrd.sheet.Cell` class (the actual cell for `xlrd`);
1544
+ :param `xls_text`: the actual WYSIWYG cell text, if available;
1545
+ :param `xls_comment`: the cell comment (note), if any;
1546
+ :param `hyperlink`: an instance of `xlrd.sheet.hyperlink`;
1547
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
1548
+ will do its best to render the text as rich text;
1549
+ :param `default_width`: this is the default width of the text in 1/256
1550
+ of the width of the zero character, using default Excel font (first FONT
1551
+ record in the Excel file);
1552
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
1553
+ border lines.
1554
+
1555
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
1556
+ parameter will always be ``None`` as this feature is available only in
1557
+ `xlrd` 0.7.2 (SVN).
1558
+
1559
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the `rich_text`
1560
+ parameter will always be ``None`` as this feature is available only in
1561
+ `xlrd` 0.7.2 (SVN).
1562
+
1563
+ :note: if Mark Hammonds' `pywin32` package is not available, the `xls_text`
1564
+ parameter will almost surely not be the WYSIWYG representation of the cell
1565
+ text.
1566
+
1567
+ :note: If Mark Hammonds' `pywin32` package is not available, the `xls_comment`
1568
+ parameter will always be ``None``.
1569
+ """
1570
+
1571
+ cvalue = cell.value
1572
+ self.raw_value = cvalue
1573
+
1574
+ if rich_text:
1575
+ self.text = XLSRichText(book, cell, xf_index, xls_text, hyperlink, rich_text, default_width)
1576
+ else:
1577
+ self.text = XLSText(book, cell, xf_index, xls_text, hyperlink, default_width)
1578
+
1579
+ self.background = XLSBackground(book, xf_index)
1580
+
1581
+ XFClass = book.xf_list[xf_index]
1582
+ border = XFClass.border
1583
+
1584
+ self.borders = XLSBorderFactory(book, border, default_colour)
1585
+
1586
+ if xls_comment:
1587
+ self.comment = XLSComment(xls_comment)
1588
+
1589
+ self.attr = None
1590
+
1591
+
1592
+ def GetAttr(self):
1593
+ """
1594
+ Returns the attribute to use for this specific cell.
1595
+
1596
+ :returns: an instance of :class:`grid.GridCellAttr`.
1597
+ """
1598
+
1599
+ if self.attr is not None:
1600
+ self.attr.IncRef()
1601
+ return self.attr
1602
+
1603
+ attr = gridlib.GridCellAttr()
1604
+
1605
+ attr.SetRenderer(XLSRenderer(self))
1606
+
1607
+ attr.SetSize(*self.size)
1608
+ attr.SetOverflow(True)
1609
+ self.attr = attr
1610
+ self.attr.IncRef()
1611
+
1612
+ return self.attr
1613
+
1614
+
1615
+ def GetValue(self):
1616
+ """ Returns the actual WYSIWYG representation of the cell value. """
1617
+
1618
+ return self.text.GetValue()
1619
+
1620
+
1621
+ def SetValue(self, value):
1622
+ """
1623
+ Sets the actual WYSIWYG representation of the cell value.
1624
+
1625
+ :param `value`: the current text value to insert in the cell.
1626
+
1627
+ :note: This method is currently unused as everything is handled inside the :class:`XLSText` class.
1628
+
1629
+ :see: :meth:`~xlsgrid.XLSCell.GetValue`
1630
+ """
1631
+
1632
+ self.value = value
1633
+
1634
+
1635
+ def SetCellSize(self, rows, cols):
1636
+ """
1637
+ Sets the size of the cell.
1638
+
1639
+ Specifying a value of more than 1 in `rows` or `cols` will make the cell
1640
+ at (`row`, `col`) span the block of the specified size, covering the other
1641
+ cells which would be normally shown in it. Passing 1 for both arguments
1642
+ resets the cell to normal appearance.
1643
+
1644
+ :param `rows`: number of rows to be occupied by this cell, must be >= 1;
1645
+ :param `cols`: number of columns to be occupied by this cell, must be >= 1.
1646
+ """
1647
+
1648
+ self.size = (rows, cols)
1649
+
1650
+
1651
+ def GetComment(self):
1652
+ """
1653
+ Returns the cell comment, if any.
1654
+
1655
+ :returns: an instance of :class:`XLSComment`.
1656
+
1657
+ :note: If Mark Hammonds' `pywin32` package is not available, this method
1658
+ always returns ``None``.
1659
+ """
1660
+
1661
+ return self.comment
1662
+
1663
+
1664
+ class XLSRenderer(gridlib.GridCellRenderer):
1665
+ """
1666
+ This class is responsible for actually drawing the cell in the grid.
1667
+
1668
+ """
1669
+
1670
+ def __init__(self, cell):
1671
+ """
1672
+ Default class constructor.
1673
+
1674
+ :param `cell`: an instance of :class:`XLSCell`.
1675
+ """
1676
+
1677
+ gridlib.GridCellRenderer.__init__(self)
1678
+ self.cell = cell
1679
+
1680
+
1681
+ def Draw(self, grid, attr, dc, rect, row, col, isSelected):
1682
+ """
1683
+ Draw the given cell on the provided `dc` inside the given rectangle using
1684
+ default or selected state corresponding to the `isSelected` value.
1685
+
1686
+ :param `grid`: an instance of :class:`grid.Grid`;
1687
+ :param `attr`: an instance of :class:`grid.GridCellAttr`;
1688
+ :param `dc`: an instance of :class:`wx.DC`;
1689
+ :param `rect`: an instance of :class:`wx.Rect`, representing the cell rectangle;
1690
+ :param `row`: the row in which this cell lives;
1691
+ :param `col`: the column in which this cell lives;
1692
+ :param `isSelected`: ``True`` if the cell is selected, ``False`` otherwise.
1693
+ """
1694
+
1695
+ # clear the background
1696
+ dc.SetBackgroundMode(wx.SOLID)
1697
+
1698
+ cell = self.cell
1699
+
1700
+ cell.background.Draw(dc, rect)
1701
+
1702
+ if cell.borders:
1703
+ cell.borders.Draw(dc, rect)
1704
+
1705
+ cell.text.Draw(dc, rect)
1706
+
1707
+ if cell.comment:
1708
+ cell.comment.Draw(dc, rect)
1709
+
1710
+ if isSelected:
1711
+
1712
+ gdc = wx.GCDC(dc)
1713
+
1714
+ sys_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
1715
+ brush_colour = wx.Colour(sys_colour.Red(), sys_colour.Green(), sys_colour.Blue(), 90)
1716
+
1717
+ gdc.SetBrush(wx.Brush(brush_colour))
1718
+ gdc.SetPen(wx.TRANSPARENT_PEN)
1719
+
1720
+ gdc.DrawRectangle(rect)
1721
+
1722
+
1723
+ class XLSTable(gridlib.GridTableBase):
1724
+ """
1725
+ The almost abstract base class for grid tables.
1726
+
1727
+ A grid table is responsible for storing the grid data and, indirectly, grid
1728
+ cell attributes. The data can be stored in the way most convenient for the
1729
+ application but has to be provided in string form to :class:`grid.Grid`.
1730
+ """
1731
+
1732
+ def __init__(self, grid, cells, rows, cols):
1733
+ """
1734
+ Default class constructor.
1735
+
1736
+ :param `grid`: an instance of :class:`grid.Grid`;
1737
+ :param `cells`: a Python dictionary. For every key `(row, col)`, the
1738
+ corresponding value is an instance of :class:`XLSCell`;
1739
+ :param `rows`: the number of rows in the table;
1740
+ :param `cols`: the number of columns in the table.
1741
+ """
1742
+
1743
+ # The base class must be initialized *first*
1744
+ gridlib.GridTableBase.__init__(self)
1745
+
1746
+ self.cells = cells
1747
+ self.dimens = (rows, cols)
1748
+
1749
+
1750
+ def GetNumberCols(self):
1751
+ """ Returns the number of columns in the table. """
1752
+
1753
+ return self.dimens[1]
1754
+
1755
+
1756
+ def GetNumberRows(self):
1757
+ """ Returns the number of rows in the table. """
1758
+
1759
+ return self.dimens[0]
1760
+
1761
+
1762
+ def GetValue(self, row, col):
1763
+ """
1764
+ Returns the cell content for the specified row and column.
1765
+
1766
+ :param `row`: the row in which this cell lives;
1767
+ :param `col`: the column in which this cell lives.
1768
+ """
1769
+
1770
+ cell = self.cells[(row, col)]
1771
+ return cell.GetValue()
1772
+
1773
+
1774
+ def SetValue(self, row, col, value):
1775
+ """
1776
+ sets the cell content for the specified row and column.
1777
+
1778
+ :param `row`: the row in which this cell lives;
1779
+ :param `col`: the column in which this cell lives;
1780
+ :param `value`: the new value to assign to the specified cell.
1781
+ """
1782
+
1783
+ cell = self.cells[(row, col)]
1784
+ cell.SetValue(value)
1785
+
1786
+
1787
+ def GetAttr(self, row, col, kind):
1788
+ """
1789
+ Return the attribute for the given cell.
1790
+
1791
+ :param `row`: the row in which this cell lives;
1792
+ :param `col`: the column in which this cell lives;
1793
+ :param `kind`: the kind of the attribute to return.
1794
+ """
1795
+
1796
+ cell = self.cells[(row, col)]
1797
+ return cell.GetAttr()
1798
+
1799
+
1800
+ def GetRawValue(self, row, col):
1801
+ """
1802
+ Returns the "raw" value for the cell content.
1803
+
1804
+ :param `row`: the row in which this cell lives;
1805
+ :param `col`: the column in which this cell lives.
1806
+ """
1807
+
1808
+ cell = self.cells[(row, col)]
1809
+ return cell.raw_value
1810
+
1811
+
1812
+ class XLSGrid(gridlib.Grid):
1813
+ """
1814
+ :class:`XLSGrid` is a class based on :class:`grid.Grid` that can be used to faithfully
1815
+ reproduce the appearance of a Microsoft Excel spreadsheet (one worksheet per
1816
+ every instance of :class:`XLSGrid`).
1817
+
1818
+ :class:`XLSGrid` is a completely owner-drawn control, and it relies on the power of
1819
+ :class:`grid.PyGridTableBase` and :class:`grid.PyGridCellRenderer` to draw the cell
1820
+ content. For this reasons (and for some others, see the TODOs section), it will
1821
+ work efficiently only for relatively small Excel files.
1822
+ """
1823
+
1824
+ def __init__(self, parent):
1825
+ """
1826
+ Default class constructor.
1827
+
1828
+ :param `parent`: the grid parent window. Must not be ``None``.
1829
+ """
1830
+
1831
+ gridlib.Grid.__init__(self, parent)
1832
+
1833
+ self.SetMargins(0, 0)
1834
+ self.SetDefaultCellBackgroundColour(parent.GetBackgroundColour())
1835
+ self.SetDefaultCellOverflow(True)
1836
+
1837
+ self.tip_window = None
1838
+ self.tip_shown = False
1839
+
1840
+
1841
+ def DestroyTip(self):
1842
+ """
1843
+ If a comment window or a tooltip over a hyperlink have been created, this
1844
+ method destroys them.
1845
+ """
1846
+
1847
+ if self.tip_window:
1848
+ try:
1849
+ self.tip_window.GetTipWindow().Destroy()
1850
+ except RuntimeError:
1851
+ pass
1852
+
1853
+ del self.tip_window
1854
+ self.tip_window = None
1855
+
1856
+ if self.tip_shown:
1857
+ self.GetGridWindow().SetToolTip("")
1858
+ self.GetGridWindow().SetCursor(wx.NullCursor)
1859
+ self.tip_shown = False
1860
+
1861
+
1862
+ def InstallGridHint(self):
1863
+ """
1864
+ Auxiliary method used to bind a ``wx.EVT_MOTION`` event to :class:`XLSGrid`.
1865
+ """
1866
+
1867
+ self.prev_rowcol = [None, None]
1868
+
1869
+ def OnMouseMotion(event):
1870
+ """
1871
+ Handles a the ``wx.EVT_MOTION`` events for :class:`XLSGrid`.
1872
+
1873
+ :param `event`: a :class:`MouseEvent` event to be processed.
1874
+ """
1875
+
1876
+ # evt.GetRow() and evt.GetCol() would be nice to have here,
1877
+ # but as this is a mouse event, not a grid event, they are not
1878
+ # available and we need to compute them by hand.
1879
+ position = event.GetPosition()
1880
+ x, y = self.CalcUnscrolledPosition(position)
1881
+ row = self.YToRow(y)
1882
+ col = self.XToCol(x)
1883
+
1884
+ if [row, col] != self.prev_rowcol and row >= 0 and col >= 0:
1885
+
1886
+ self.prev_rowcol[:] = [row, col]
1887
+ self.DestroyTip()
1888
+ cell = self.cells[(row, col)]
1889
+ rect = self.CellToRect(row, col)
1890
+ comment = cell.GetComment()
1891
+
1892
+ window = self.GetGridWindow()
1893
+ if cell.text.IsHyperLink():
1894
+ window.SetCursor(wx.Cursor(wx.CURSOR_HAND))
1895
+ window.SetToolTip(cell.text.tooltip)
1896
+ self.tip_shown = True
1897
+ if not comment:
1898
+ return
1899
+
1900
+ if comment:
1901
+ self.tip_window = TransientPopup(window, comment, wx.GetMousePosition())
1902
+ event.Skip()
1903
+
1904
+ self.GetGridWindow().Bind(wx.EVT_MOTION, OnMouseMotion)
1905
+
1906
+
1907
+ def PopulateGrid(self, book, sheet, display_texts, comments):
1908
+ """
1909
+ This is the main method of this class, and it is used to actually create
1910
+ the cells, size the columns and rows, merging cells, etc...
1911
+
1912
+ :param `book`: an instance of the `xlrd.Book` class;
1913
+ :param `sheet`: an instance of the `xlrd.sheet` class;
1914
+ :param `display_texts`: if Mark Hammonds' `pywin32` package is available,
1915
+ this is the WYSIWYG cell content for all the cells in the Excel worksheet;
1916
+ :param `comments`: if Mark Hammonds' `pywin32` package is available,
1917
+ this is a nested list of cell comments (notes) for all the cells in the
1918
+ Excel worksheet.
1919
+ """
1920
+
1921
+ self.BeginBatch()
1922
+
1923
+ nrows = sheet.nrows
1924
+ ncols = sheet.ncols
1925
+
1926
+ default_width, default_height = self.GetDefaultFontData(book)
1927
+ default_colour = self.GetGridLineColour()
1928
+
1929
+ hyperlinks, rich_text_list = {}, {}
1930
+ if hasattr(sheet, "hyperlink_map"):
1931
+ # New in xlrd version 0.7.2 from SVN
1932
+ hyperlinks = sheet.hyperlink_map
1933
+
1934
+ if hasattr(sheet, "rich_text_runlist_map"):
1935
+ # New in xlrd version 0.7.2 from SVN
1936
+ rich_text_list = sheet.rich_text_runlist_map
1937
+
1938
+ self.cells = {}
1939
+
1940
+ for i in range(nrows):
1941
+
1942
+ for j in range(ncols):
1943
+
1944
+ hyperlink = rich_text = None
1945
+
1946
+ if (i, j) in hyperlinks:
1947
+ hyperlink = hyperlinks[(i, j)]
1948
+ if (i, j) in rich_text_list:
1949
+ rich_text = rich_text_list[(i, j)]
1950
+
1951
+ self.FormatCell(book, sheet, i, j, display_texts, comments, hyperlink, rich_text, default_width, default_colour)
1952
+
1953
+ self.table = XLSTable(self, self.cells, nrows, ncols)
1954
+ self.SetTable(self.table)
1955
+
1956
+ row_height = sheet.default_row_height
1957
+ col_width = sheet.defcolwidth
1958
+
1959
+ for i in range(nrows):
1960
+ if i in sheet.rowinfo_map:
1961
+ current = sheet.rowinfo_map[i].height
1962
+ else:
1963
+ current = sheet.default_row_height
1964
+
1965
+ row_height = int(round(float(default_height)*current/256.0))
1966
+ self.SetRowSize(i, row_height)
1967
+
1968
+ for j in range(ncols):
1969
+ if j in sheet.colinfo_map:
1970
+ current = sheet.colinfo_map[j].width
1971
+ else:
1972
+ current = sheet.defcolwidth
1973
+
1974
+ col_width = int(round(float(default_width)*current/256.0))
1975
+ self.SetColSize(j, col_width)
1976
+
1977
+ for merged in sheet.merged_cells:
1978
+ rlo, rhi, clo, chi = merged
1979
+ if rlo >= 0 and rlo < len(self.cells) and clo >= 0:
1980
+ self.cells[(rlo, clo)].SetCellSize(rhi-rlo, chi-clo)
1981
+
1982
+ self.EnableEditing(False)
1983
+ self.EnableGridLines(False)
1984
+ self.EndBatch()
1985
+ self.ForceRefresh()
1986
+ self.InstallGridHint()
1987
+
1988
+
1989
+ def FormatCell(self, book, sheet, row, col, display_texts, comments, hyperlink, rich_text, default_width, default_colour):
1990
+ """
1991
+ Processes the creation of a single cell (an instance of :class:`XLSCell`).
1992
+
1993
+ :param `book`: an instance of the `xlrd.Book` class;
1994
+ :param `sheet`: an instance of the `xlrd.sheet` class;
1995
+ :param `row`: the row in which this cell lives;
1996
+ :param `col`: the column in which this cell lives;
1997
+ :param `display_texts`: if Mark Hammonds' `pywin32` package is available,
1998
+ this is the WYSIWYG cell content for all the cells in the Excel worksheet;
1999
+ :param `comments`: if Mark Hammonds' `pywin32` package is available,
2000
+ this is a nested list of cell comments (notes) for all the cells in the
2001
+ Excel worksheet;
2002
+ :param `hyperlink`: if this cell contains a hyperlink, it will be displayed
2003
+ accordingly;
2004
+ :param `rich_text`: if this cell contains text in rich text format, :class:`XLSGrid`
2005
+ will do its best to render the text as rich text;
2006
+ :param `default_width`: this is the default width of the text in 1/256
2007
+ of the width of the zero character, using default Excel font (first FONT
2008
+ record in the Excel file);
2009
+ :param `default_colour`: the "magic" colour used by Excel to draw non-custom
2010
+ border lines.
2011
+
2012
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the *hyperlink*
2013
+ parameter will always be ``None`` as this feature is available only in
2014
+ `xlrd` 0.7.2 (SVN).
2015
+
2016
+ :note: If you are using version 0.7.1 or lower for `xlrd`, the `rich_text`
2017
+ parameter will always be ``None`` as this feature is available only in
2018
+ `xlrd` 0.7.2 (SVN).
2019
+
2020
+ :note: If Mark Hammonds' `pywin32` package is not available, the `display_texts`
2021
+ and `comments` parameter will be two empty nested lists.
2022
+ """
2023
+
2024
+ cell = sheet.cell(row, col)
2025
+
2026
+ xf_index = sheet.cell_xf_index(row, col)
2027
+ xls_text, xls_comment = display_texts[row][col], comments[row][col]
2028
+
2029
+ gridCell = XLSCell(book, cell, xf_index, xls_text, xls_comment, hyperlink, rich_text, default_width, default_colour)
2030
+
2031
+ self.cells[(row, col)] = gridCell
2032
+
2033
+
2034
+ def GetDefaultFontData(self, book):
2035
+ """
2036
+ Returns suitable width and height (in pixels) starting from Excel's own
2037
+ measurements (in characters, whatever that means).
2038
+
2039
+ :param `book`: an instance of the `xlrd.Book` class.
2040
+
2041
+ :returns: a `default_width` and `default_height` in pixels, based on the
2042
+ default width of the text in 1/256 of the width of the zero character,
2043
+ using default Excel font (first FONT record in the Excel file).
2044
+ """
2045
+
2046
+ font = book.font_list[0]
2047
+ style, bold, underline = wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False
2048
+
2049
+ if font.italic:
2050
+ style = wx.FONTSTYLE_ITALIC
2051
+ if font.underline_type > 0:
2052
+ underline = True
2053
+ if font.weight > 600:
2054
+ bold = wx.FONTWEIGHT_BOLD
2055
+
2056
+ family = XF_FONT_FAMILY[font.family]
2057
+ name = font.name
2058
+ size = int(font.height/20.0)
2059
+
2060
+ dc = wx.ClientDC(self)
2061
+ font = wx.Font(size, family, style, bold, underline, name.encode())
2062
+ dc.SetFont(font)
2063
+ width, height, descent, leading = dc.GetFullTextExtent("0", font)
2064
+
2065
+ return width, height + descent - leading
2066
+
2067
+
2068
+ class TransientPopup(STT.SuperToolTip):
2069
+ """
2070
+ This is a subclass of :class:`SuperToolTip` and it is used to display a
2071
+ "comment-window" on the cells containing a comment (a note).
2072
+
2073
+ :note: If Mark Hammonds' `pywin32` package is not available, this class is
2074
+ never invoked.
2075
+ """
2076
+
2077
+ def __init__(self, grid_window, comment, position):
2078
+ """
2079
+ Default class constructor.
2080
+
2081
+ :param `grid_window`: the actual window representing the grid;
2082
+ :param `comment`: an instance of :class:`XLSComment`, containing the
2083
+ text for this comment;
2084
+ :param `position`: the position at which we pop up the comment
2085
+ window (currently unused).
2086
+ """
2087
+
2088
+ STT.SuperToolTip.__init__(self, grid_window)
2089
+
2090
+ xls_comment = comment.comment
2091
+
2092
+ split = xls_comment.split(":")
2093
+ header, rest = split[0], split[1:]
2094
+ rest = ":".join(rest)
2095
+
2096
+ dc = wx.ClientDC(grid_window)
2097
+ rest = wordwrap(rest, 400, dc)
2098
+
2099
+ self.SetHeader(header)
2100
+ self.SetMessage(rest)
2101
+ self.SetTarget(grid_window)
2102
+ self.SetDrawHeaderLine(True)
2103
+
2104
+ self.SetStartDelay(100000)
2105
+ self.SetEndDelay(100000)
2106
+ self.ApplyStyle("Office 2007 Blue")
2107
+
2108
+ self.SetDropShadow(True)
2109
+ self.DoShowNow()
2110
+
2111
+ grid_window.SetFocus()