WizardDialog.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. #
  2. # This file is part of the LibreOffice project.
  3. #
  4. # This Source Code Form is subject to the terms of the Mozilla Public
  5. # License, v. 2.0. If a copy of the MPL was not distributed with this
  6. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
  7. #
  8. # This file incorporates work covered by the following license notice:
  9. #
  10. # Licensed to the Apache Software Foundation (ASF) under one or more
  11. # contributor license agreements. See the NOTICE file distributed
  12. # with this work for additional information regarding copyright
  13. # ownership. The ASF licenses this file to you under the Apache
  14. # License, Version 2.0 (the "License"); you may not use this file
  15. # except in compliance with the License. You may obtain a copy of
  16. # the License at http://www.apache.org/licenses/LICENSE-2.0 .
  17. #
  18. import uno
  19. import traceback
  20. from abc import ABCMeta, abstractmethod
  21. from .UnoDialog2 import UnoDialog2, Desktop, PropertyNames, UIConsts, \
  22. ItemListenerProcAdapter
  23. from ..common.HelpIds import HelpIds
  24. from ..common.FileAccess import FileAccess
  25. from com.sun.star.lang import NoSuchMethodException
  26. from com.sun.star.frame import TerminationVetoException
  27. from com.sun.star.awt.PushButtonType import HELP, STANDARD
  28. from com.sun.star.awt.FontWeight import BOLD
  29. import sys, os
  30. # imp is deprecated since Python v.3.4
  31. if sys.version_info >= (3,3):
  32. from importlib.machinery import SourceFileLoader
  33. SourceFileLoader('strings', os.path.join(os.path.dirname(__file__), '../common/strings.hrc')).load_module()
  34. else:
  35. import imp
  36. imp.load_source('strings', os.path.join(os.path.dirname(__file__), '../common/strings.hrc'))
  37. import strings
  38. class WizardDialog(UnoDialog2):
  39. __metaclass__ = ABCMeta
  40. __NEXT_ACTION_PERFORMED = "gotoNextAvailableStep"
  41. __BACK_ACTION_PERFORMED = "gotoPreviousAvailableStep"
  42. __FINISH_ACTION_PERFORMED = "finishWizard_1"
  43. __CANCEL_ACTION_PERFORMED = "cancelWizard_1"
  44. __HELP_ACTION_PERFORMED = None
  45. '''
  46. Creates a new instance of WizardDialog
  47. the hid is used as following :
  48. "HID:(hid)" - the dialog
  49. "HID:(hid+1) - the help button
  50. "HID:(hid+2)" - the back button
  51. "HID:(hid+3)" - the next button
  52. "HID:(hid+4)" - the create button
  53. "HID:(hid+5)" - the cancel button
  54. @param xMSF
  55. @param hid_
  56. '''
  57. def __init__(self, xMSF, hid_):
  58. super(WizardDialog,self).__init__(xMSF)
  59. self.__hid = hid_
  60. self.iButtonWidth = 50
  61. self.nNewStep = 1
  62. self.nOldStep = 1
  63. self.nMaxStep = 1
  64. self.bTerminateListenermustberemoved = True
  65. self.oRoadmap = None
  66. self.terminateListener = None
  67. def activate(self):
  68. try:
  69. self.xUnoDialog.toFront()
  70. except Exception:
  71. pass
  72. # do nothing;
  73. def itemStateChanged(self, itemEvent):
  74. try:
  75. self.nNewStep = itemEvent.ItemId
  76. self.nOldStep = int(self.xDialogModel.Step)
  77. if self.nNewStep != self.nOldStep:
  78. self.switchToStep()
  79. except Exception:
  80. traceback.print_exc()
  81. def setDialogProperties(self, closeable, height, moveable, position_x,
  82. position_Y, step, tabIndex, title, width):
  83. uno.invoke(self.xDialogModel, "setPropertyValues",
  84. ((PropertyNames.PROPERTY_CLOSEABLE,
  85. PropertyNames.PROPERTY_HEIGHT,
  86. PropertyNames.PROPERTY_MOVEABLE,
  87. PropertyNames.PROPERTY_POSITION_X,
  88. PropertyNames.PROPERTY_POSITION_Y,
  89. PropertyNames.PROPERTY_STEP,
  90. PropertyNames.PROPERTY_TABINDEX,
  91. PropertyNames.PROPERTY_TITLE,
  92. PropertyNames.PROPERTY_WIDTH),
  93. (closeable, height, moveable, position_x, position_Y, step,
  94. tabIndex, title, width)))
  95. def setRoadmapInteractive(self, _bInteractive):
  96. self.oRoadmap.Activated = _bInteractive
  97. def setRoadmapComplete(self, bComplete):
  98. self.oRoadmap.Complete = bComplete
  99. def isRoadmapComplete(self):
  100. try:
  101. return bool(self.oRoadmap.Complete)
  102. except Exception:
  103. traceback.print_exc()
  104. return False
  105. def setCurrentRoadmapItemID(self, ID):
  106. if self.oRoadmap is not None:
  107. nCurItemID = self.getCurrentRoadmapItemID()
  108. if nCurItemID != ID:
  109. self.oRoadmap.CurrentItemID = ID
  110. def getCurrentRoadmapItemID(self):
  111. try:
  112. return int(self.oRoadmap.CurrentItemID)
  113. except Exception:
  114. traceback.print_exc()
  115. return -1
  116. def initializePaths(self):
  117. xPropertySet = \
  118. self.xMSF.createInstance("com.sun.star.util.PathSettings")
  119. self.sUserTemplatePath = \
  120. xPropertySet.getPropertyValue("Template_writable")
  121. myFA = FileAccess(self.xMSF)
  122. aInternalPaths = xPropertySet.getPropertyValue("Template_internal")
  123. self.sTemplatePath = ""
  124. for path in aInternalPaths:
  125. if myFA.exists(path + "/wizard", False):
  126. self.sTemplatePath = path
  127. break
  128. if self.sTemplatePath == "":
  129. raise Exception("could not find wizard templates")
  130. def addRoadmap(self):
  131. try:
  132. iDialogHeight = self.xDialogModel.Height
  133. # the roadmap control has got no real TabIndex ever
  134. # that is not correct, but changing this would need time,
  135. # so it is used without TabIndex as before
  136. xRoadmapControl = self.insertControlModel(
  137. "com.sun.star.awt.UnoControlRoadmapModel",
  138. "rdmNavi",
  139. (PropertyNames.PROPERTY_HEIGHT,
  140. PropertyNames.PROPERTY_POSITION_X,
  141. PropertyNames.PROPERTY_POSITION_Y,
  142. PropertyNames.PROPERTY_STEP,
  143. PropertyNames.PROPERTY_TABINDEX, "Tabstop",
  144. PropertyNames.PROPERTY_WIDTH),
  145. ((iDialogHeight - 26), 0, 0, 0,
  146. 0, True, 85))
  147. self.oRoadmap = xRoadmapControl.Model
  148. method = getattr(self, "itemStateChanged")
  149. xRoadmapControl.addItemListener(
  150. ItemListenerProcAdapter(method))
  151. self.oRoadmap.Text = strings.RID_COMMON_START_16
  152. except NoSuchMethodException:
  153. from com.sun.star.awt.VclWindowPeerAttribute import OK
  154. from .SystemDialog import SystemDialog
  155. sError = "The files required could not be found.\n" + \
  156. "Please start the LibreOffice Setup and choose 'Repair'."
  157. SystemDialog.showMessageBox(super().xMSF, "ErrorBox", OK, sError)
  158. except Exception:
  159. traceback.print_exc()
  160. def getRoadmapItemByID(self, _ID):
  161. try:
  162. getByIndex = self.oRoadmap.getByIndex
  163. for i in list(range(self.oRoadmap.Count)):
  164. CurRoadmapItem = getByIndex(i)
  165. CurID = int(CurRoadmapItem.ID)
  166. if CurID == _ID:
  167. return CurRoadmapItem
  168. return None
  169. except Exception:
  170. traceback.print_exc()
  171. return None
  172. def switchToStep(self,_nOldStep=None, _nNewStep=None):
  173. if _nOldStep is not None and _nNewStep is not None:
  174. self.nOldStep = _nOldStep
  175. self.nNewStep = _nNewStep
  176. self.leaveStep(self.nOldStep, self.nNewStep)
  177. if self.nNewStep != self.nOldStep:
  178. if self.nNewStep == self.nMaxStep:
  179. self.xDialogModel.btnWizardNext.DefaultButton = False
  180. self.xDialogModel.btnWizardFinish.DefaultButton = True
  181. else:
  182. self.xDialogModel.btnWizardNext.DefaultButton = True
  183. self.xDialogModel.btnWizardFinish.DefaultButton = False
  184. self.changeToStep(self.nNewStep)
  185. self.enterStep(self.nOldStep, self.nNewStep)
  186. return True
  187. return False
  188. @abstractmethod
  189. def leaveStep(self, nOldStep, nNewStep):
  190. pass
  191. @abstractmethod
  192. def enterStep(self, nOldStep, nNewStep):
  193. pass
  194. def changeToStep(self, nNewStep):
  195. self.xDialogModel.Step = nNewStep
  196. self.setCurrentRoadmapItemID(nNewStep)
  197. self.enableNextButton(self.getNextAvailableStep() > 0)
  198. self.enableBackButton(nNewStep != 1)
  199. def drawNaviBar(self):
  200. try:
  201. curtabindex = UIConsts.SOFIRSTWIZARDNAVITABINDEX
  202. iButtonWidth = self.iButtonWidth
  203. iButtonHeight = 14
  204. iCurStep = 0
  205. iDialogHeight = self.xDialogModel.Height
  206. iDialogWidth = self.xDialogModel.Width
  207. iHelpPosX = 8
  208. iBtnPosY = iDialogHeight - iButtonHeight - 6
  209. iCancelPosX = iDialogWidth - self.iButtonWidth - 6
  210. iFinishPosX = iCancelPosX - 6 - self.iButtonWidth
  211. iNextPosX = iFinishPosX - 6 - self.iButtonWidth
  212. iBackPosX = iNextPosX - 3 - self.iButtonWidth
  213. self.insertControlModel(
  214. "com.sun.star.awt.UnoControlFixedLineModel",
  215. "lnNaviSep",
  216. (PropertyNames.PROPERTY_HEIGHT, "Orientation",
  217. PropertyNames.PROPERTY_POSITION_X,
  218. PropertyNames.PROPERTY_POSITION_Y,
  219. PropertyNames.PROPERTY_STEP,
  220. PropertyNames.PROPERTY_WIDTH),
  221. (1, 0, 0, iDialogHeight - 26, iCurStep, iDialogWidth))
  222. self.insertControlModel(
  223. "com.sun.star.awt.UnoControlFixedLineModel",
  224. "lnRoadSep",
  225. (PropertyNames.PROPERTY_HEIGHT,
  226. "Orientation",
  227. PropertyNames.PROPERTY_POSITION_X,
  228. PropertyNames.PROPERTY_POSITION_Y,
  229. PropertyNames.PROPERTY_STEP,
  230. PropertyNames.PROPERTY_WIDTH),
  231. (iBtnPosY - 6, 1, 85, 0, iCurStep, 1))
  232. propNames = (PropertyNames.PROPERTY_ENABLED,
  233. PropertyNames.PROPERTY_HEIGHT,
  234. PropertyNames.PROPERTY_HELPURL,
  235. PropertyNames.PROPERTY_LABEL,
  236. PropertyNames.PROPERTY_POSITION_X,
  237. PropertyNames.PROPERTY_POSITION_Y,
  238. "PushButtonType",
  239. PropertyNames.PROPERTY_STEP,
  240. PropertyNames.PROPERTY_TABINDEX,
  241. PropertyNames.PROPERTY_WIDTH)
  242. self.xDialogModel.HelpURL = HelpIds.getHelpIdString(self.__hid)
  243. self.insertButton("btnWizardHelp",
  244. WizardDialog.__HELP_ACTION_PERFORMED,
  245. (PropertyNames.PROPERTY_ENABLED,
  246. PropertyNames.PROPERTY_HEIGHT,
  247. PropertyNames.PROPERTY_LABEL,
  248. PropertyNames.PROPERTY_POSITION_X,
  249. PropertyNames.PROPERTY_POSITION_Y,
  250. "PushButtonType",
  251. PropertyNames.PROPERTY_STEP,
  252. PropertyNames.PROPERTY_TABINDEX,
  253. PropertyNames.PROPERTY_WIDTH),
  254. (True, iButtonHeight,
  255. strings.RID_COMMON_START_15,
  256. iHelpPosX, iBtnPosY,
  257. uno.Any("short",HELP), iCurStep,
  258. uno.Any("short",(curtabindex + 1)), iButtonWidth), self)
  259. self.insertButton("btnWizardBack",
  260. WizardDialog.__BACK_ACTION_PERFORMED, propNames,
  261. (False, iButtonHeight, HelpIds.getHelpIdString(self.__hid + 2),
  262. strings.RID_COMMON_START_13,
  263. iBackPosX, iBtnPosY, uno.Any("short",STANDARD), iCurStep,
  264. uno.Any("short",(curtabindex + 1)), iButtonWidth), self)
  265. self.insertButton("btnWizardNext",
  266. WizardDialog.__NEXT_ACTION_PERFORMED, propNames,
  267. (True, iButtonHeight, HelpIds.getHelpIdString(self.__hid + 3),
  268. strings.RID_COMMON_START_14,
  269. iNextPosX, iBtnPosY, uno.Any("short",STANDARD), iCurStep,
  270. uno.Any("short",(curtabindex + 1)), iButtonWidth), self)
  271. self.insertButton("btnWizardFinish",
  272. WizardDialog.__FINISH_ACTION_PERFORMED, propNames,
  273. (True, iButtonHeight, HelpIds.getHelpIdString(self.__hid + 4),
  274. strings.RID_COMMON_START_12,
  275. iFinishPosX, iBtnPosY, uno.Any("short",STANDARD),
  276. iCurStep,
  277. uno.Any("short",(curtabindex + 1)),
  278. iButtonWidth), self)
  279. self.insertButton("btnWizardCancel",
  280. WizardDialog.__CANCEL_ACTION_PERFORMED, propNames,
  281. (True, iButtonHeight, HelpIds.getHelpIdString(self.__hid + 5),
  282. strings.RID_COMMON_START_11,
  283. iCancelPosX, iBtnPosY, uno.Any("short",STANDARD), iCurStep,
  284. uno.Any("short",(curtabindex + 1)),
  285. iButtonWidth), self)
  286. self.xDialogModel.btnWizardNext.DefaultButton = True
  287. except Exception:
  288. traceback.print_exc()
  289. def insertRoadMapItems(self, items, enabled):
  290. for index, item in enumerate(items):
  291. try:
  292. oRoadmapItem = self.oRoadmap.createInstance()
  293. oRoadmapItem.Label = item
  294. oRoadmapItem.Enabled = enabled[index]
  295. oRoadmapItem.ID = index + 1
  296. self.oRoadmap.insertByIndex(index, oRoadmapItem)
  297. except Exception:
  298. traceback.print_exc()
  299. def enableBackButton(self, enabled):
  300. self.xDialogModel.btnWizardBack.Enabled = enabled
  301. def enableNextButton(self, enabled):
  302. self.xDialogModel.btnWizardNext.Enabled = enabled
  303. def enableFinishButton(self, enabled):
  304. self.xDialogModel.btnWizardFinish.Enabled = enabled
  305. def isStepEnabled(self, _nStep):
  306. try:
  307. xRoadmapItem = self.getRoadmapItemByID(_nStep)
  308. # Todo: In this case an exception should be thrown
  309. if xRoadmapItem is None:
  310. return False
  311. bIsEnabled = bool(xRoadmapItem.Enabled)
  312. return bIsEnabled
  313. except Exception:
  314. traceback.print_exc()
  315. return False
  316. def gotoPreviousAvailableStep(self):
  317. try:
  318. if self.nNewStep > 1:
  319. self.nOldStep = self.nNewStep
  320. self.nNewStep -= 1
  321. while self.nNewStep > 0:
  322. bIsEnabled = self.isStepEnabled(self.nNewStep)
  323. if bIsEnabled:
  324. break;
  325. self.nNewStep -= 1
  326. if (self.nNewStep == 0):
  327. self.nNewStep = self.nOldStep
  328. self.switchToStep()
  329. except Exception:
  330. traceback.print_exc()
  331. def getNextAvailableStep(self):
  332. if self.isRoadmapComplete():
  333. i = self.nNewStep + 1
  334. while i <= self.nMaxStep:
  335. if self.isStepEnabled(i):
  336. return i
  337. i += 1
  338. return -1
  339. def gotoNextAvailableStep(self):
  340. try:
  341. self.nOldStep = self.nNewStep
  342. self.nNewStep = self.getNextAvailableStep()
  343. if self.nNewStep > -1:
  344. self.switchToStep()
  345. except Exception:
  346. traceback.print_exc()
  347. @abstractmethod
  348. def finishWizard(self):
  349. pass
  350. def finishWizard_1(self):
  351. '''This function will call
  352. if the finish button is pressed on the UI'''
  353. try:
  354. self.enableFinishButton(False)
  355. success = False
  356. try:
  357. success = self.finishWizard()
  358. finally:
  359. if not success:
  360. self.enableFinishButton(True)
  361. if success:
  362. self.removeTerminateListener()
  363. except Exception:
  364. traceback.print_exc()
  365. def getCurrentStep(self):
  366. try:
  367. return int(self.xDialogModel.Step)
  368. except Exception:
  369. traceback.print_exc()
  370. return -1
  371. def cancelWizard(self):
  372. #can be overwritten by extending class
  373. self.xUnoDialog.endExecute()
  374. def removeTerminateListener(self):
  375. if self.bTerminateListenermustberemoved:
  376. Desktop.getDesktop(self.xMSF).removeTerminateListener(self.terminateListener)
  377. self.bTerminateListenermustberemoved = False
  378. '''
  379. called by the cancel button and
  380. by the window hidden event.
  381. if this method was not called before,
  382. perform a cancel.
  383. '''
  384. def cancelWizard_1(self):
  385. try:
  386. self.cancelWizard()
  387. self.removeTerminateListener()
  388. except Exception:
  389. traceback.print_exc()
  390. def windowHidden(self):
  391. self.cancelWizard_1()
  392. def queryTermination(self):
  393. self.activate()
  394. raise TerminationVetoException()
  395. def disposing(self, arg0):
  396. self.cancelWizard_1()
  397. def optCreateFromTemplateItemChanged(self):
  398. self.bEditTemplate = False
  399. def optMakeChangesItemChanged(self):
  400. self.bEditTemplate = True