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