export.py (59302B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\export.py 2 import codecs 3 import operator 4 import os 5 import sys 6 import yaml 7 from player_messaging.client.ui_message import prompt_player_fsd_dialog 8 from xml.dom.minidom import getDOMImplementation, parse 9 import blue 10 import evetypes 11 import localization 12 import utillib 13 from carbon.common.script.util.commonutils import StripTags 14 from carbonui import uiconst 15 from carbonui.control.combo import Combo 16 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText 17 from carbonui.primitives.container import Container 18 from carbonui.primitives.containerAutoSize import ContainerAutoSize 19 from carbonui.util.stringManip import SanitizeFilename 20 import overviewPresets.overviewSettingsConst as osConst 21 from carbonui.button.group import ButtonGroup 22 from eve.client.script.ui.control.entries.checkbox import CheckboxEntry 23 from eve.client.script.ui.control.entries.generic import Generic 24 from eve.client.script.ui.control.entries.util import GetFromClass 25 from eve.client.script.ui.control.listgroup import ListGroup 26 from carbonui.control.button import Button 27 from carbonui.control.checkbox import Checkbox 28 from carbonui.control.window import Window 29 from eve.client.script.ui.control import eveLabel, eveScroll 30 from eve.client.script.ui.control.draggableShareContainer import DraggableShareContainer 31 from eveexceptions import UserError 32 from inventorycommon.util import IsShipFittable, IsSubsystemFlag, IsSubsystemFlagVisible 33 from overviewPresets import overviewSettingsConst 34 from overviewPresets.overviewPresetUtil import GetDeterministicListFromDict, GetDictFromList, ReplaceInnerListsWithDicts 35 from overviewPresets.overviewSettingsConst import SETTING_BRACKETS_SHOWNONE, SETTING_BRACKETS_SHOWSPECIALS, SETTING_BRACKETS_SHOWALL, TAB_SETTING_IDS, MAX_SHARED_PRESETS 36 from textImporting import StripImportantSymbol 37 INVALID_FLAG_STRING = 'invalid flag' 38 39 class ImportBaseWindow(Window): 40 __guid__ = 'form.ImportBaseWindow' 41 42 def ApplyAttributes(self, attributes): 43 Window.ApplyAttributes(self, attributes) 44 self.SetMinSize([450, 250]) 45 self.minWidth = 225 46 self.scrollWidth = 0 47 dirpath = attributes.get('dirpath', None) 48 if dirpath: 49 self.dirpath = dirpath 50 else: 51 self.dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'Overview') 52 self.ConstructLayout() 53 54 def ConstructLayout(self, *args): 55 self.sr.fileContainer = Container(name='fileContainer', align=uiconst.TOLEFT, parent=self.sr.main, padTop=const.defaultPadding, width=256) 56 self.sr.profilesContainer = Container(name='profilesContainer', align=uiconst.TOALL, parent=self.sr.main, pos=(0, 0, 0, 0)) 57 self.sr.fileHeader = eveLabel.CaptionLabel(text=localization.GetByLabel('UI/Common/Files/FileName'), parent=self.sr.fileContainer, left=const.defaultPadding, align=uiconst.TOTOP, fontsize=14) 58 fileScrollCont = Container(name='fileScrollCont', parent=self.sr.fileContainer, align=uiconst.TOALL) 59 self.sr.fileScroll = eveScroll.Scroll(name='fileScroll', parent=fileScrollCont, padding=(const.defaultPadding, 60 0, 61 const.defaultPadding, 62 const.defaultPadding)) 63 self.sr.refreshFileListBtn = ButtonGroup(btns=[[localization.GetByLabel('UI/Commands/Refresh'), 64 self.RefreshFileList, 65 (), 66 None]], parent=self.sr.fileContainer, idx=0) 67 profilesTopCont = Container(name='fileTopCont', parent=self.sr.profilesContainer, align=uiconst.TOTOP, height=40) 68 profilesScrollCont = Container(name='fileScrollCont', parent=self.sr.profilesContainer, align=uiconst.TOALL) 69 self.sr.profilesHeader = eveLabel.CaptionLabel(text=localization.GetByLabel('UI/Common/PleaseSelect'), parent=profilesTopCont, align=uiconst.TOPLEFT, left=4) 70 self.sr.profilesHeader.fontsize = 14 71 self.checkAllCB = Checkbox(text=localization.GetByLabel('UI/Shared/CheckAllOn'), parent=profilesTopCont, align=uiconst.TOBOTTOM, height=16, padLeft=const.defaultPadding, callback=self.CheckAll, checked=True) 72 self.sr.profilesScroll = eveScroll.Scroll(name='profilesScroll', parent=profilesScrollCont, padding=(const.defaultPadding, 73 0, 74 const.defaultPadding, 75 const.defaultPadding)) 76 self.sr.importProfilesBtnGroup = ButtonGroup(parent=self.sr.profilesContainer, idx=0, state=uiconst.UI_NORMAL) 77 self.sr.importProfilesBtn = self.sr.importProfilesBtnGroup.AddButton(localization.GetByLabel('UI/Commands/Import'), self.Import) 78 self.ChangeImportButtonDisplayState(display=False) 79 self.RefreshFileList() 80 81 def RefreshFileList(self, *args): 82 fileList = self.GetFilesByExt('.xml') 83 contentList = [] 84 for fileName in fileList: 85 contentList.append(GetFromClass(Generic, {'label': fileName, 86 'OnClick': self.OnFileSelected})) 87 88 self.sr.fileScroll.Load(contentList=contentList) 89 90 def GetFilesByExt(self, ext): 91 fileList = [] 92 if os.path.exists(self.dirpath): 93 for file in os.listdir(self.dirpath): 94 if file.endswith(ext): 95 fileList.append(file[:-len(ext)]) 96 97 return fileList 98 99 def OnChange(self, *args): 100 self.ChangeImportButtonState() 101 102 def ChangeImportButtonState(self): 103 anySelected = self.IsAnyEntrySelected() 104 self.ChangeImportButtonDisplayState(display=bool(anySelected)) 105 106 def ChangeImportButtonDisplayState(self, display): 107 self.sr.importProfilesBtnGroup.display = display 108 109 def IsAnyEntrySelected(self): 110 for entry in self.sr.profilesScroll.GetNodes(): 111 if entry.checked: 112 return True 113 114 return False 115 116 def Import(self, *args): 117 raise NotImplementedError('') 118 119 def OnFileSelected(self, entry): 120 raise NotImplementedError('') 121 122 def CheckAll(self, *args): 123 for entry in self.sr.profilesScroll.GetNodes(): 124 if entry.__guid__ == 'listentry.Checkbox': 125 entry.checked = self.checkAllCB.checked 126 if entry.panel: 127 entry.panel.Load(entry) 128 129 self.ChangeImportButtonState() 130 131 132 class ExportBaseWindow(Window): 133 __guid__ = 'form.ExportBaseWindow' 134 135 def ApplyAttributes(self, attributes): 136 Window.ApplyAttributes(self, attributes) 137 dirpath = attributes.get('dirpath', None) 138 if dirpath: 139 self.dirpath = dirpath 140 else: 141 self.dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'Overview') 142 self.SetMinSize([370, 270]) 143 self.ConstructLayout() 144 145 def ConstructLayout(self, *args): 146 self.ConstructTopCont() 147 left = const.defaultPadding 148 self.sr.buttonContainer = Container(name='buttonContainer', align=uiconst.TOBOTTOM, parent=self.sr.main) 149 self.sr.filenameLabel = eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Common/Files/FileName'), parent=self.sr.buttonContainer, top=const.defaultPadding, left=left, state=uiconst.UI_NORMAL) 150 left += self.sr.filenameLabel.width + const.defaultPadding 151 self.sr.filename = SingleLineEditText(name='filename', parent=self.sr.buttonContainer, pos=(left, 152 const.defaultPadding, 153 150, 154 0), align=uiconst.TOPLEFT) 155 self.sr.filename.SetMaxLength(32) 156 left += self.sr.filename.width + const.defaultPadding 157 self.sr.exportBtn = Button(parent=self.sr.buttonContainer, label=localization.GetByLabel('UI/Commands/Export'), func=self.Export, btn_default=1, idx=0, pos=(left, 158 const.defaultPadding, 159 0, 160 0)) 161 self.sr.buttonContainer.height = self.sr.filename.height + 10 162 self.sr.scrolllistcontainer = Container(name='scrolllistcontainer', align=uiconst.TOALL, parent=self.sr.main, pos=(0, 0, 0, 0)) 163 self.sr.scroll = eveScroll.Scroll(name='scroll', parent=self.sr.scrolllistcontainer, padding=(const.defaultPadding, 164 const.defaultPadding, 165 const.defaultPadding, 166 const.defaultPadding)) 167 self.ConstructScrollList() 168 169 def ConstructTopCont(self): 170 self.topCont = Container(name='topCont', align=uiconst.TOTOP, height=14, parent=self.sr.main) 171 self.checkAllCB = Checkbox(text=localization.GetByLabel('UI/Shared/CheckAllOn'), parent=self.topCont, align=uiconst.TOPLEFT, pos=(const.defaultPadding, 172 0, 173 100, 174 0), callback=self.CheckAll, checked=True) 175 176 def CheckAll(self, *args): 177 for entry in self.sr.scroll.GetNodes(): 178 if entry.__guid__ == 'listentry.Checkbox': 179 entry.checked = self.checkAllCB.checked 180 if entry.panel: 181 entry.panel.Load(entry) 182 183 self.ChangeExportButtonState() 184 185 def OnSelectionChanged(self, c, *args): 186 self.ChangeExportButtonState() 187 188 def ChangeExportButtonState(self): 189 anySelected = self.IsAnyEntrySelected() 190 if anySelected: 191 self.sr.exportBtn.state = uiconst.UI_NORMAL 192 else: 193 self.sr.exportBtn.state = uiconst.UI_HIDDEN 194 195 def IsAnyEntrySelected(self): 196 for entry in self.sr.scroll.GetNodes(): 197 if entry.checked: 198 return True 199 200 return False 201 202 203 class ExportFittingsWindow(ExportBaseWindow): 204 __guid__ = 'form.ExportFittingsWindow' 205 default_windowID = 'ExportFittingsWindow' 206 default_iconNum = 'res:/ui/Texture/WindowIcons/fitting.png' 207 208 def ApplyAttributes(self, attributes): 209 self.selectedOwnerID = attributes.ownerID 210 self.fittingSvc = sm.StartService('fittingSvc') 211 dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'Overview') 212 attributes.dirpath = dirpath 213 ExportBaseWindow.ApplyAttributes(self, attributes) 214 self.SetCaption(localization.GetByLabel('UI/Fitting/ExportFittings')) 215 216 def ConstructLayout(self, *args): 217 ExportBaseWindow.ConstructLayout(self, *args) 218 options = [(localization.GetByLabel('UI/Fitting/FittingWindow/FittingManagement/PersonalFittings'), session.charid), (localization.GetByLabel('UI/Fitting/FittingWindow/FittingManagement/CorporationFittings'), session.corpid)] 219 if session.allianceid: 220 options.append((localization.GetByLabel('UI/Fitting/FittingWindow/FittingManagement/AllianceFittings'), session.allianceid)) 221 if self.selectedOwnerID in [ x[1] for x in options ]: 222 selected = self.selectedOwnerID 223 else: 224 selected = session.charid 225 self.ownerCombo = Combo(label=None, parent=self.topCont, options=options, name='exportFitting_ownerCombo', select=selected, callback=self.ChangeOwnerFilter, align=uiconst.TOTOP, padding=4) 226 self.checkAllCB.SetAlign(uiconst.BOTTOMLEFT) 227 self.topCont.height = self.ownerCombo.height + self.checkAllCB.height + 5 228 229 def ChangeOwnerFilter(self, cb, key, value, *args): 230 self.selectedOwnerID = value 231 self.ConstructScrollList() 232 233 def ConstructScrollList(self): 234 fittings = self.fittingSvc.GetAllFittings() 235 scrolllist = [] 236 fittingList = [] 237 for fittingID, fitting in fittings.iteritems(): 238 if fitting.ownerID == self.selectedOwnerID: 239 fittingList.append((fitting.name, fitting)) 240 241 fittingList.sort() 242 for fittingName, fitting in fittingList: 243 scrolllist.append(GetFromClass(CheckboxEntry, {'label': fittingName, 244 'checked': True, 245 'cfgname': 'groups', 246 'retval': True, 247 'report': False, 248 'OnChange': self.OnSelectionChanged, 249 'fitting': fitting})) 250 251 self.sr.scroll.Load(contentList=scrolllist) 252 253 def Export(self, *args): 254 if self.sr.filename.GetValue().strip() == '': 255 raise UserError('NameInvalid') 256 impl = getDOMImplementation() 257 newdoc = impl.createDocument(None, 'fittings', None) 258 try: 259 docEl = newdoc.documentElement 260 export = {} 261 for entry in self.sr.scroll.GetNodes(): 262 if not entry.checked: 263 continue 264 profile = newdoc.createElement('fitting') 265 docEl.appendChild(profile) 266 profile.attributes['name'] = entry.fitting.name 267 element = newdoc.createElement('description') 268 element.attributes['value'] = entry.fitting.Get('description') 269 profile.appendChild(element) 270 element = newdoc.createElement('shipType') 271 shipType = evetypes.GetName(entry.fitting.Get('shipTypeID')) 272 element.attributes['value'] = shipType 273 profile.appendChild(element) 274 for typeID, flag, qty in entry.fitting.fitData: 275 typeName = evetypes.GetName(typeID) 276 hardWareElement = newdoc.createElement('hardware') 277 hardWareElement.attributes['type'] = typeName 278 slot = self.GetSlotFromFlag(flag) 279 if slot is None: 280 slot = INVALID_FLAG_STRING 281 hardWareElement.attributes['slot'] = slot 282 if flag in (const.flagDroneBay, const.flagCargo, const.flagFighterBay): 283 hardWareElement.attributes['qty'] = str(qty) 284 profile.appendChild(hardWareElement) 285 286 filename = self.sr.filename.GetValue() 287 illegalFileNameChars = ['?', 288 '*', 289 ':', 290 ';', 291 '~', 292 '\\', 293 '/', 294 '"', 295 '|'] 296 for char in illegalFileNameChars: 297 if char in filename: 298 prompt_player_fsd_dialog('IllegalFilename') 299 return 300 301 self.dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'fittings') 302 filepath = os.path.join(self.dirpath, self.sr.filename.GetValue() + '.xml') 303 if not os.path.exists(self.dirpath): 304 os.makedirs(self.dirpath) 305 if os.path.exists(filepath): 306 if prompt_player_fsd_dialog('FileExists', {}, uiconst.YESNO) == uiconst.ID_NO: 307 return 308 outfile = codecs.open(filepath, 'w', 'utf-8') 309 newdoc.writexml(outfile, indent='\t', addindent='\t', newl='\n') 310 self.CloseByUser() 311 prompt_player_fsd_dialog('FittingExportDone', {'filename': filepath}) 312 finally: 313 newdoc.unlink() 314 315 def GetSlotFromFlag(self, flag): 316 if flag in const.hiSlotFlags: 317 return 'hi slot ' + str(flag - const.flagHiSlot0) 318 if flag in const.medSlotFlags: 319 return 'med slot ' + str(flag - const.flagMedSlot0) 320 if flag in const.loSlotFlags: 321 return 'low slot ' + str(flag - const.flagLoSlot0) 322 if flag in const.rigSlotFlags: 323 return 'rig slot ' + str(flag - const.flagRigSlot0) 324 if IsSubsystemFlagVisible(flag): 325 return 'subsystem slot ' + str(flag - const.flagSubSystemSlot0) 326 if flag == const.flagCargo: 327 return 'cargo' 328 if flag == const.flagDroneBay: 329 return 'drone bay' 330 if flag == const.flagFighterBay: 331 return 'fighter bay' 332 if flag in const.serviceSlotFlags: 333 return 'service slot ' + str(flag - const.flagServiceSlot0) 334 335 336 class ImportFittingsWindow(ImportBaseWindow): 337 __guid__ = 'form.ImportFittingsWindow' 338 default_windowID = 'ImportFittingsWindow' 339 default_iconNum = 'res:/ui/Texture/WindowIcons/fitting.png' 340 341 def ApplyAttributes(self, attributes): 342 dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'Fittings') 343 attributes.dirpath = dirpath 344 ImportBaseWindow.ApplyAttributes(self, attributes) 345 self.sr.importProfilesBtn.LoadTooltipPanel = self.LoadImportTooltip 346 self.SetCaption(localization.GetByLabel('UI/Fitting/ImportFittings')) 347 self.fittingSvc = sm.StartService('fittingSvc') 348 349 def LoadImportTooltip(self, tooltipPanel, *args): 350 hasCorpRoles = bool(session.corprole & const.corpRoleFittingManager) 351 if not hasCorpRoles: 352 return 353 tooltipPanel.LoadGeneric1ColumnTemplate() 354 tooltipPanel.state = uiconst.UI_NORMAL 355 tooltipPanel.columns = 1 356 tooltipPanel.margin = (12, 12, 12, 12) 357 tooltipPanel.cellPadding = 0 358 tooltipPanel.cellSpacing = 10 359 saveAllianceBtn = None 360 if session.allianceid and sm.GetService('alliance').GetAlliance(session.allianceid).executorCorpID == session.corpid: 361 saveAllianceBtn = Button(parent=tooltipPanel, label=localization.GetByLabel('UI/Fitting/FittingWindow/SaveForAlliance'), func=self.ImportForOwner, args=(session.allianceid,), align=uiconst.CENTER) 362 importCorpBtn = Button(parent=tooltipPanel, label=localization.GetByLabel('UI/Fitting/FittingWindow/SaveForCorp'), func=self.ImportForOwner, args=(session.corpid,), align=uiconst.CENTER) 363 importPersonalBtn = Button(parent=tooltipPanel, label=localization.GetByLabel('UI/Fitting/FittingWindow/SaveForCharacter', charID=session.charid), func=self.ImportForOwner, args=(session.charid,), align=uiconst.CENTER) 364 maxWidth = max(importCorpBtn.width, importPersonalBtn.width) 365 if saveAllianceBtn: 366 maxWidth = max(maxWidth, saveAllianceBtn.width) 367 importCorpBtn.width = importPersonalBtn.width = maxWidth 368 if saveAllianceBtn: 369 saveAllianceBtn.width = maxWidth 370 371 def OnFileSelected(self, entry): 372 filepath = os.path.join(self.dirpath, entry.sr.node.label + '.xml') 373 self.sr.selectedFileName = entry.sr.node.label 374 profileCheckboxes = [] 375 try: 376 doc = parse(filepath) 377 try: 378 profiles = doc.documentElement.getElementsByTagName('fitting') 379 for x in profiles: 380 profileCheckboxes.append(GetFromClass(CheckboxEntry, {'label': x.attributes['name'].value, 381 'checked': True, 382 'cfgname': 'profiles', 383 'retval': True, 384 'OnChange': self.OnChange})) 385 386 self.ChangeImportButtonDisplayState(display=True) 387 finally: 388 doc.unlink() 389 390 except Exception as e: 391 raise 392 profileCheckboxes = [GetFromClass(Generic, {'label': localization.GetByLabel('UI/Common/Files/FileNotValid')})] 393 self.ChangeImportButtonDisplayState(display=False) 394 395 self.sr.profilesScroll.Load(contentList=profileCheckboxes) 396 self.OnChange() 397 398 def Import(self, *args): 399 return self.ImportForOwner() 400 401 def ImportForOwner(self, ownerID = None): 402 filepath = os.path.join(self.dirpath, self.sr.selectedFileName + '.xml') 403 godma = sm.GetService('godma') 404 doc = parse(filepath) 405 try: 406 fittings = doc.documentElement.getElementsByTagName('fitting') 407 fittingsDict = {} 408 borkedTypeNames = set() 409 borkedFlags = set() 410 obsoleteModules = set() 411 for checkbox in self.sr.profilesScroll.GetNodes(): 412 if not checkbox.checked: 413 continue 414 fittingName = checkbox.label 415 kv = utillib.KeyVal() 416 for fitting in fittings: 417 if fitting.attributes['name'].value != fittingName: 418 continue 419 descriptionElements = fitting.getElementsByTagName('description') 420 if descriptionElements > 0: 421 description = descriptionElements[0].attributes['value'].value 422 else: 423 description = '' 424 shipTypeName = fitting.getElementsByTagName('shipType')[0].attributes['value'].value 425 try: 426 cleanShipTypeName = StripTags(shipTypeName) 427 cleanShipTypeName = StripImportantSymbol(cleanShipTypeName) 428 importFittingUtil = sm.GetService('fittingSvc').GetImportFittingUtil() 429 shipTypeID = importFittingUtil.GetTypeIDFromName(cleanShipTypeName.lower()) 430 except evetypes.TypeNotFoundException: 431 sys.exc_clear() 432 borkedTypeNames.add(shipTypeName) 433 continue 434 435 shipTypeID = int(shipTypeID) 436 fitData = {} 437 for hardwareElement in fitting.getElementsByTagName('hardware'): 438 typeName = hardwareElement.attributes['type'].value 439 try: 440 cleanTypeName = StripTags(typeName) 441 cleanTypeName = StripImportantSymbol(cleanTypeName) 442 typeID = evetypes.GetTypeIDByName(cleanTypeName) 443 except evetypes.TypeNotFoundException: 444 borkedTypeNames.add(typeName) 445 sys.exc_clear() 446 continue 447 448 slot = hardwareElement.attributes['slot'].value 449 flag = self.GetFlagFromSlot(slot) 450 if flag is None: 451 borkedFlags.add(typeName) 452 continue 453 if IsShipFittable(evetypes.GetCategoryID(typeID)) and flag != const.flagCargo: 454 qty = 1 455 elif IsModuleObsolete(typeID): 456 obsoleteModules.add(typeName) 457 continue 458 else: 459 qty = hardwareElement.attributes['qty'].value 460 qty = int(qty) 461 fitData[typeID, flag] = (typeID, flag, qty) 462 463 kv.name = fittingName 464 kv.description = description 465 kv.shipTypeID = shipTypeID 466 kv.fitData = fitData.values() 467 kv.ownerID = None 468 kv.fittingID = fittingName 469 fittingsDict[fittingName] = kv 470 471 text = '' 472 if len(borkedTypeNames) > 0: 473 text += '<b>%s</b><br>' % localization.GetByLabel('UI/Fitting/MalformedXML') 474 for typeName in borkedTypeNames: 475 text += typeName + '<br>' 476 477 if len(borkedFlags) > 0: 478 if len(text) > 0: 479 text += '<br><br>' 480 text += '<b>%s</b><br>' % localization.GetByLabel('UI/Fitting/MalformedFlagInformation') 481 for typeName in borkedFlags: 482 text += typeName + '<br>' 483 484 if len(obsoleteModules) > 0: 485 if len(text) > 0: 486 text += '<br><br>' 487 text += '<b>%s</b><br>' % localization.GetByLabel('UI/Fitting/ObsoleteModules') 488 for typeName in obsoleteModules: 489 text += typeName + '<br>' 490 491 if len(text) > 0: 492 prompt_player_fsd_dialog('CustomInfo', {'info': text}) 493 fittingOwner = ownerID or session.charid 494 self.fittingSvc.PersistManyFittings(fittingOwner, fittingsDict.values()) 495 self.CloseByUser() 496 finally: 497 doc.unlink() 498 499 def GetFlagFromSlot(self, slot): 500 if slot == INVALID_FLAG_STRING: 501 return None 502 if slot == 'drone bay': 503 return const.flagDroneBay 504 if slot == 'fighter bay': 505 return const.flagFighterBay 506 if slot == 'cargo': 507 return const.flagCargo 508 offset = int(slot[-1]) 509 if slot.startswith('hi slot'): 510 return const.flagHiSlot0 + offset 511 if slot.startswith('med slot'): 512 return const.flagMedSlot0 + offset 513 if slot.startswith('low slot'): 514 return const.flagLoSlot0 + offset 515 if slot.startswith('rig slot'): 516 return const.flagRigSlot0 + offset 517 if slot.startswith('subsystem slot'): 518 return const.flagSubSystemSlot0 + offset 519 if slot.startswith('service slot'): 520 return const.flagServiceSlot0 + offset 521 522 523 class ImportOverviewWindow(ImportBaseWindow): 524 __guid__ = 'form.ImportOverviewWindow' 525 default_windowID = 'ImportOverviewWindow' 526 527 def ApplyAttributes(self, attributes): 528 dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'Overview') 529 self.presetsSelected = set() 530 ImportBaseWindow.ApplyAttributes(self, attributes) 531 self.SetCaption(localization.GetByLabel('UI/Overview/ImportOverviewSettings')) 532 self.sr.fileScroll.multiSelect = False 533 self.fileType = '' 534 self.yamlSettingsDict = {} 535 536 def RefreshFileList(self, *args): 537 legacyPresets = self.GetLegacyPresets() 538 fileList = self.GetFilesByExt('.yaml') 539 contentList = [] 540 for fileName in fileList: 541 contentList.append(GetFromClass(Generic, {'label': fileName, 542 'OnClick': self.OnFileSelected, 543 'ext': 'yaml'})) 544 545 contentList += legacyPresets 546 self.sr.fileScroll.Load(contentList=contentList) 547 548 def GetLegacyPresets(self): 549 filelist = self.GetFilesByExt('.xml') 550 if not filelist: 551 return [] 552 return [GetFromClass(ListGroup, {'GetSubContent': self.GetOldPresetSubContent, 553 'label': localization.GetByLabel('UI/Overview/OldOverviewSettings'), 554 'id': ('importOverview', 'oldPresets'), 555 'groupItems': filelist, 556 'showlen': 1, 557 'sublevel': 0, 558 'showicon': 'hide', 559 'state': 'locked'})] 560 561 def GetOldPresetSubContent(self, nodedata): 562 fileList = [] 563 for fileName in nodedata.groupItems: 564 fileList.append(GetFromClass(Generic, {'label': fileName, 565 'OnClick': self.OnFileSelected, 566 'sublevel': 1, 567 'ext': 'xml'})) 568 569 return fileList 570 571 def OnFileSelected(self, entry): 572 if entry.sr.node.ext == 'xml': 573 self.ShowXmlSettings(entry) 574 else: 575 self.yamlSettingsDict = {} 576 self.ShowYamlSettings(entry) 577 578 def ShowXmlSettings(self, entry): 579 self.fileType = 'xml' 580 filepath = os.path.join(self.dirpath, entry.sr.node.label + '.xml') 581 self.sr.selectedFileName = entry.sr.node.label 582 profileCheckboxes = [] 583 try: 584 doc = parse(filepath) 585 try: 586 profiles = doc.documentElement.getElementsByTagName('profile') 587 for x in profiles: 588 profileCheckboxes.append(GetFromClass(CheckboxEntry, {'label': x.attributes['name'].value, 589 'checked': True, 590 'cfgname': 'profiles', 591 'retval': True, 592 'OnChange': self.OnChange})) 593 594 if len(doc.documentElement.getElementsByTagName('globalSettings')): 595 profileCheckboxes.append(GetFromClass(CheckboxEntry, {'label': localization.GetByLabel('UI/Overview/GlobalOverviewSettings'), 596 'checked': True, 597 'cfgname': 'profiles', 598 'retval': True, 599 'OnChange': self.OnChange})) 600 self.ChangeImportButtonDisplayState(display=True) 601 finally: 602 doc.unlink() 603 604 except Exception as e: 605 profileCheckboxes = [GetFromClass(Generic, {'label': localization.GetByLabel('UI/Common/Files/FileNotValid')})] 606 self.ChangeImportButtonDisplayState(display=False) 607 608 self.sr.profilesScroll.Load(contentList=profileCheckboxes) 609 self.ChangeImportButtonState() 610 611 def ShowYamlSettings(self, entry): 612 self.fileType = 'yaml' 613 filepath = os.path.join(self.dirpath, entry.sr.node.label + '.yaml') 614 filestream = open(filepath) 615 settingDict = yaml.safe_load(filestream) 616 self.yamlSettingsDict = settingDict 617 self.ConstructScrollList(initPresetsSelected=True) 618 619 def ConstructScrollList(self, initPresetsSelected = False): 620 if self.fileType != 'yaml': 621 return 622 allChecked = True 623 settingDict = self.yamlSettingsDict 624 tabPresets = GetDictFromList(settingDict.get('presets', [])) 625 tabPresets = ReplaceInnerListsWithDicts(tabPresets) 626 tabSetup = sm.GetService('overviewPresetSvc').GetTabSetupToLoad(settingDict) 627 presetsInUseDict = sm.GetService('overviewPresetSvc').GetPresetsInUseFromTabSettings(tabSetup, tabPresets) 628 if initPresetsSelected: 629 self.InitPresetsSelected(presetsInUseDict) 630 checked = 'generalSettings' in self.presetsSelected 631 scrolllist = [GetGeneralOverviewSettingsEntry(onChangeFunc=self.OnChange, checked=checked)] 632 allChecked = allChecked and checked 633 checked = 'overviewProfile' in self.presetsSelected 634 profileEntry = GetOverviewProfileEntry(onChangeFunc=self.OnChange, checked=checked) 635 scrolllist.append(profileEntry) 636 allChecked = allChecked and checked 637 presetsInUseList = [] 638 for eachPresetName in presetsInUseDict: 639 lowerDisplayName = eachPresetName.lower() 640 presetsInUseList.append((lowerDisplayName, eachPresetName)) 641 642 presetsInUseList = [ x[1] for x in localization.util.Sort(presetsInUseList, key=operator.itemgetter(0)) ] 643 for eachPresetName in presetsInUseList: 644 checked = eachPresetName in self.presetsSelected 645 entry = GetTabPresetEntry(eachPresetName, onChangeFunc=self.OnChange, checked=checked) 646 scrolllist.append(entry) 647 allChecked = allChecked and checked 648 649 restOfPresets = [] 650 for eachPresetName in tabPresets: 651 if eachPresetName in presetsInUseList: 652 continue 653 lowerDisplayName = eachPresetName.lower() 654 restOfPresets.append((lowerDisplayName, eachPresetName)) 655 656 if restOfPresets: 657 restOfPresets = [ x[1] for x in localization.util.Sort(restOfPresets, key=operator.itemgetter(0)) ] 658 posttext, allSubPresetsChecked = GetPresetPostText(restOfPresets, self.presetsSelected) 659 allChecked = allChecked and allSubPresetsChecked 660 scrolllist.append(GetFromClass(ListGroup, {'GetSubContent': self.GetPresetSubContent, 661 'label': localization.GetByLabel('UI/Overview/OtherTabPresets'), 662 'id': ('importOverview', 'restOfPresets'), 663 'groupItems': restOfPresets, 664 'showlen': 0, 665 'sublevel': 0, 666 'showicon': 'hide', 667 'state': 'locked', 668 'posttext': posttext})) 669 self.sr.profilesScroll.Load(contentList=scrolllist) 670 self.ChangeImportButtonState() 671 self.checkAllCB.SetChecked(allChecked, report=False) 672 673 def InitPresetsSelected(self, presetsInUseDict): 674 self.presetsSelected = set(['generalSettings', 'overviewProfile']) 675 for eachPresetName in presetsInUseDict: 676 self.presetsSelected.add(eachPresetName) 677 678 def OnChange(self, c, *args): 679 OnOverviewCheckboxChange(c, self.presetsSelected) 680 if self.fileType == 'yaml': 681 self.ConstructScrollList() 682 ImportBaseWindow.OnChange(self, c) 683 684 def CheckAll(self, *args): 685 if self.fileType == 'xml': 686 return ImportBaseWindow.CheckAll(self) 687 if self.fileType == 'yaml': 688 checkAll = self.checkAllCB.checked 689 ModifyPresetSelectedDict(checkAll, self.sr.profilesScroll, self.presetsSelected) 690 self.ConstructScrollList() 691 self.ChangeImportButtonState() 692 693 def IsAnyEntrySelected(self): 694 if self.fileType == 'xml': 695 return ImportBaseWindow.IsAnyEntrySelected(self) 696 else: 697 return bool(self.presetsSelected) 698 699 def GetPresetSubContent(self, nodedata): 700 scrolllist = [] 701 for eachPresetName in nodedata.groupItems: 702 checked = eachPresetName in self.presetsSelected 703 entry = GetTabPresetEntry(eachPresetName, onChangeFunc=self.OnChange, checked=checked) 704 scrolllist.append(entry) 705 706 return scrolllist 707 708 def AddProfilesToSettings(self, profileName, profiles): 709 for profile in profiles: 710 groups = [] 711 filteredStates = [] 712 if profile.attributes['name'].value != profileName: 713 continue 714 for groupElement in profile.getElementsByTagName('groups')[0].getElementsByTagName('group'): 715 groups.append(int(groupElement.attributes['id'].value)) 716 717 for el in profile.getElementsByTagName('filteredStates')[0].getElementsByTagName('state'): 718 filteredStates.append(int(el.attributes['state'].value)) 719 720 profileValues = {overviewSettingsConst.PRESET_SETTINGS_GROUPS: groups, 721 overviewSettingsConst.PRESET_SETTINGS_FILTERED_STATES: filteredStates} 722 return (profileName, profileValues) 723 724 return (None, None) 725 726 def ImportGlobalSettings(self, doc, miscSettings): 727 settingsElement = doc.documentElement.getElementsByTagName('globalSettings')[0] 728 for setting in [osConst.SETTING_NAME_SMALL_TAGS, 729 osConst.SETTING_NAME_APPLY_STRUCTURE, 730 osConst.SETTING_NAME_APPLY_OTHER_OBJ, 731 osConst.SETTING_HIDE_CORP_TICKER, 732 osConst.SETTING_BROADCAST_TO_TOP]: 733 elements = settingsElement.getElementsByTagName(setting) 734 if not elements: 735 continue 736 element = elements[0] 737 value = bool(element.attributes['value']) 738 miscSettings[setting] = value 739 740 overviewColumns = [] 741 columnsElement = settingsElement.getElementsByTagName('columns')[0] 742 for columnElement in columnsElement.getElementsByTagName('column'): 743 overviewColumns.append(columnElement.attributes['id'].value) 744 745 shipLabels = [] 746 if len(settingsElement.getElementsByTagName('shipLabels')): 747 shipLabelsElement = settingsElement.getElementsByTagName('shipLabels')[0] 748 shipLabelElements = shipLabelsElement.getElementsByTagName('label') 749 for sle in shipLabelElements: 750 d = {} 751 for shipLabelPartElement in sle.getElementsByTagName('part'): 752 n = shipLabelPartElement.attributes['name'].value 753 v = shipLabelPartElement.attributes['value'].value 754 if n == 'state': 755 v = int(v) 756 if v == 'None': 757 v = None 758 d[n] = v 759 760 shipLabels.append(d) 761 762 stateService = sm.StartService('stateSvc') 763 if hasattr(stateService, 'shipLabels'): 764 delattr(stateService, 'shipLabels') 765 return (overviewColumns, shipLabels) 766 767 def GetTabData(self, selectedProfiles, tabElement): 768 overviewProfileName = tabElement.attributes['overview'].value 769 bracketProfileName = tabElement.attributes['bracket'].value 770 tabdata = {} 771 if overviewProfileName in selectedProfiles and bracketProfileName in selectedProfiles: 772 for attributeName in TAB_SETTING_IDS: 773 attribute = tabElement.getAttribute(attributeName) 774 if attribute: 775 if attribute in (SETTING_BRACKETS_SHOWNONE, SETTING_BRACKETS_SHOWSPECIALS, SETTING_BRACKETS_SHOWALL): 776 attribute = bool(attribute) 777 tabdata[attributeName] = attribute 778 779 return tabdata 780 781 def Import(self, *args): 782 if self.fileType == 'xml': 783 return self.ImportXml() 784 else: 785 return self.ImportYaml() 786 787 def ImportXml(self, *args): 788 dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'Overview') 789 filepath = os.path.join(dirpath, self.sr.selectedFileName + '.xml') 790 doc = parse(filepath) 791 try: 792 profiles = doc.documentElement.getElementsByTagName('profile') 793 ov = settings.user.overview.Get(osConst.SETTING_PROFILE_PRESETS, {}) 794 miscSettings = {} 795 selectedProfiles = [] 796 shipLabels = None 797 overviewColumns = None 798 closeWindow = True 799 profileUpdateDict = {} 800 for checkbox in self.sr.profilesScroll.GetNodes(): 801 if not checkbox.checked: 802 continue 803 profileName = checkbox.label 804 if profileName in ov and prompt_player_fsd_dialog('OverviewProfileExists', {'name': profileName}, uiconst.YESNO) != uiconst.ID_YES: 805 closeWindow = False 806 continue 807 if profileName == localization.GetByLabel('UI/Overview/GlobalOverviewSettings'): 808 overviewColumns, shipLabels = self.ImportGlobalSettings(doc, miscSettings) 809 continue 810 selectedProfiles.append(profileName) 811 profileName, profileValues = self.AddProfilesToSettings(profileName, profiles) 812 if profileValues: 813 profileUpdateDict[profileName] = profileValues 814 815 overviewPresetSvc = sm.GetService('overviewPresetSvc') 816 overviewPresetSvc.UpdateAllPresets(profileUpdateDict) 817 tabsChanged = False 818 tabsData = {} 819 tabIndex = 0 820 for tabElement in doc.documentElement.getElementsByTagName('tab'): 821 if tabIndex >= 5: 822 prompt_player_fsd_dialog('TooManyTabsImported') 823 break 824 dataForTab = self.GetTabData(selectedProfiles, tabElement) 825 if dataForTab: 826 tabsData[tabIndex] = dataForTab 827 tabIndex += 1 828 tabsChanged = True 829 830 if overviewColumns: 831 settings.user.overview.Set(osConst.SETTING_COLUMNS, overviewColumns) 832 if shipLabels: 833 settings.user.overview.Set(osConst.SETTINGS_SHIP_LABELS, shipLabels) 834 for k, v in miscSettings.items(): 835 settings.user.overview.Set(k, v) 836 837 overviewPresetSvc.LoadPresetsFromUserSettings() 838 if tabsChanged: 839 overviewPresetSvc.ImportOverviewSettings(tabsData) 840 if tabsChanged: 841 sm.ScatterEvent('OnOverviewPresetsChanged') 842 else: 843 sm.ScatterEvent('OnFullOverviewReload') 844 if closeWindow: 845 self.CloseByUser() 846 finally: 847 doc.unlink() 848 849 def ImportYaml(self): 850 tabPresetNamesToImport = [] 851 tabsChanged = False 852 for checkboxConfig in self.presetsSelected: 853 if checkboxConfig == 'generalSettings': 854 sm.GetService('overviewPresetSvc').LoadGeneralSettings(self.yamlSettingsDict) 855 elif checkboxConfig == 'overviewProfile': 856 tabSetup = sm.GetService('overviewPresetSvc').GetTabSetupToLoad(self.yamlSettingsDict) 857 sm.GetService('overviewPresetSvc').PersistSettingsByTabID(tabSetup) 858 tabsChanged = True 859 else: 860 tabPresetNamesToImport.append(checkboxConfig) 861 862 presetsDict = GetDictFromList(self.yamlSettingsDict.get('presets', [])) 863 presetsDict = ReplaceInnerListsWithDicts(presetsDict) 864 myPresets = {presetName:presetValue for presetName, presetValue in presetsDict.iteritems() if presetName in tabPresetNamesToImport} 865 sm.GetService('overviewPresetSvc').UpdateAllPresets(myPresets) 866 if tabsChanged: 867 sm.GetService('overviewPresetSvc').ImportOverviewSettings(tabSetup) 868 sm.ScatterEvent('OnReloadingOverviewProfile') 869 self.CloseByUser() 870 871 872 class ImportLegacyFittingsWindow(ExportBaseWindow): 873 __guid__ = 'form.ImportLegacyFittingsWindow' 874 default_windowID = 'ImportLegacyFittingsWindow' 875 default_iconNum = 'res:/ui/Texture/WindowIcons/fitting.png' 876 877 def OnSelectionChanged(self, c, *args): 878 checkedCount = 0 879 for entry in self.sr.scroll.GetNodes(): 880 if entry.checked: 881 checkedCount += 1 882 883 text = localization.GetByLabel('UI/Fitting/MovingCount', count=checkedCount, total=self.totalLocalFittings) 884 if self.fittingCount > 0: 885 text += ' (' + localization.GetByLabel('UI/Fitting/CurrentlySaved', count=self.fittingCount) + ')' 886 self.sr.countSelectedTextLabel.text = text 887 if not self.okBtn.disabled and self.fittingCount + checkedCount > const.maxCharFittings: 888 self.okBtn.Disable() 889 elif self.okBtn.disabled and self.fittingCount + checkedCount <= const.maxCharFittings: 890 self.okBtn.Enable() 891 892 def ApplyAttributes(self, attributes): 893 self.fittingSvc = sm.StartService('fittingSvc') 894 self.fittingCount = len(self.fittingSvc.GetFittingMgr(session.charid).GetFittings(session.charid)) 895 Window.ApplyAttributes(self, attributes) 896 self.SetMinSize([370, 270]) 897 self.SetCaption(localization.GetByLabel('UI/Fitting/MoveToServer')) 898 self.ConstructLayout() 899 900 def ConstructLayout(self, *args): 901 self.countSelectedText = '' 902 self.sr.textContainer = Container(name='textContainer', align=uiconst.TOTOP, parent=self.sr.main, height=65, padding=const.defaultPadding) 903 self.sr.textLabel = eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Fitting/LegacyImport', maxFittings=const.maxCharFittings), align=uiconst.TOTOP, parent=self.sr.textContainer) 904 self.sr.textContainer2 = Container(name='textContainer', align=uiconst.TOTOP, parent=self.sr.main, height=15, padding=const.defaultPadding) 905 self.sr.countSelectedTextLabel = eveLabel.EveLabelMedium(text=self.countSelectedText, align=uiconst.TOALL, parent=self.sr.textContainer2) 906 self.sr.buttonContainer = Container(name='buttonContainer', align=uiconst.TOBOTTOM, parent=self.sr.main) 907 btns = [[localization.GetByLabel('UI/Generic/Cancel'), 908 self.CloseByUser, 909 None, 910 81], [localization.GetByLabel('UI/Generic/OK'), 911 self.Import, 912 None, 913 81]] 914 self.buttonGroup = ButtonGroup(btns=btns, parent=self.sr.buttonContainer) 915 self.okBtn = self.buttonGroup.children[0].children[1] 916 self.sr.buttonContainer.height = 23 917 self.sr.scrolllistcontainer = Container(name='scrolllistcontainer', align=uiconst.TOALL, parent=self.sr.main, pos=(0, 0, 0, 0)) 918 self.sr.scroll = eveScroll.Scroll(name='scroll', parent=self.sr.scrolllistcontainer, padding=(const.defaultPadding, 919 const.defaultPadding, 920 const.defaultPadding, 921 const.defaultPadding)) 922 self.ConstructScrollList() 923 924 def ConstructScrollList(self): 925 fittings = self.fittingSvc.GetLegacyClientFittings() 926 scrolllist = [] 927 fittingList = [] 928 for fittingID, fitting in fittings.iteritems(): 929 fittingList.append((fitting.name, fitting)) 930 931 fittingList.sort() 932 self.emptyFittings = [] 933 for fittingName, fitting in fittingList: 934 if len(fitting.fitData) == 0: 935 self.emptyFittings.append(fitting) 936 continue 937 typeFlag = set() 938 for typeID, flag, qty in fitting.fitData[:]: 939 if (typeID, flag) in typeFlag: 940 fitting.fitData.remove((typeID, flag, qty)) 941 else: 942 typeFlag.add((typeID, flag)) 943 944 scrolllist.append(GetFromClass(CheckboxEntry, {'label': fittingName, 945 'checked': False, 946 'OnChange': self.OnSelectionChanged, 947 'cfgname': 'groups', 948 'retval': True, 949 'report': False, 950 'fitting': fitting})) 951 952 self.sr.scroll.Load(contentList=scrolllist) 953 self.totalLocalFittings = len(fittingList) 954 self.OnSelectionChanged(None) 955 956 def Import(self, *args): 957 impl = getDOMImplementation() 958 newdoc = impl.createDocument(None, 'fittings', None) 959 try: 960 docEl = newdoc.documentElement 961 fittings = [] 962 saveSomeToFile = False 963 for entry in self.sr.scroll.GetNodes(): 964 if entry.checked: 965 fittings.append(entry.fitting) 966 else: 967 saveSomeToFile = True 968 profile = newdoc.createElement('fitting') 969 docEl.appendChild(profile) 970 profile.attributes['name'] = entry.fitting.name 971 element = newdoc.createElement('description') 972 element.attributes['value'] = entry.fitting.Get('description') 973 profile.appendChild(element) 974 element = newdoc.createElement('shipType') 975 try: 976 shipType = evetypes.GetName(entry.fitting.Get('shipTypeID')) 977 except KeyError: 978 shipType = 'unknown type' 979 980 element.attributes['value'] = shipType 981 profile.appendChild(element) 982 for typeID, flag, qty in entry.fitting.fitData: 983 try: 984 typeName = evetypes.GetName(typeID) 985 except KeyError: 986 typeName = 'unknown type' 987 988 hardWareElement = newdoc.createElement('hardware') 989 hardWareElement.attributes['type'] = typeName 990 slot = self.GetSlotFromFlag(flag) 991 if slot is None: 992 slot = 'unknown slot' 993 hardWareElement.attributes['slot'] = slot 994 if flag == const.flagDroneBay: 995 hardWareElement.attributes['qty'] = str(qty) 996 profile.appendChild(hardWareElement) 997 998 for emptyFitting in self.emptyFittings: 999 saveSomeToFile = True 1000 profile = newdoc.createElement('fitting') 1001 docEl.appendChild(profile) 1002 profile.attributes['name'] = entry.fitting.name 1003 element = newdoc.createElement('description') 1004 element.attributes['value'] = entry.fitting.Get('description') 1005 profile.appendChild(element) 1006 element = newdoc.createElement('shipType') 1007 try: 1008 shipType = evetypes.GetName(entry.fitting.Get('shipTypeID')) 1009 except KeyError: 1010 shipType = 'unknown type' 1011 1012 element.attributes['value'] = shipType 1013 profile.appendChild(element) 1014 1015 if len(fittings) > 0: 1016 self.fittingSvc.PersistManyFittings(session.charid, fittings) 1017 if saveSomeToFile: 1018 self.dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'fittings') 1019 filename = cfg.eveowners.Get(session.charid).ownerName 1020 filename = filename.replace(' ', '') 1021 filename = SanitizeFilename(filename) 1022 dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'fittings') 1023 filename = os.path.join(dirpath, filename) 1024 extraEnding = '' 1025 while os.path.exists(filename + str(extraEnding) + '.xml'): 1026 if not isinstance(extraEnding, int): 1027 extraEnding = 1 1028 extraEnding += 1 1029 1030 filename += str(extraEnding) + '.xml' 1031 if not os.path.exists(self.dirpath): 1032 os.makedirs(self.dirpath) 1033 outfile = codecs.open(filename, 'w', 'utf-8') 1034 newdoc.writexml(outfile, indent='\t', addindent='\t', newl='\n') 1035 prompt_player_fsd_dialog('LegacyFittingExportDone', {'filename': filename}) 1036 self.fittingSvc.DeleteLegacyClientFittings() 1037 self.CloseByUser() 1038 finally: 1039 newdoc.unlink() 1040 1041 def GetSlotFromFlag(self, flag): 1042 if const.flagHiSlot0 <= flag <= const.flagHiSlot7: 1043 return 'hi slot ' + str(flag - const.flagHiSlot0) 1044 if const.flagMedSlot0 <= flag <= const.flagMedSlot7: 1045 return 'med slot ' + str(flag - const.flagMedSlot0) 1046 if const.flagLoSlot0 <= flag <= const.flagLoSlot7: 1047 return 'low slot ' + str(flag - const.flagLoSlot0) 1048 if const.flagRigSlot0 <= flag <= const.flagRigSlot7: 1049 return 'rig slot ' + str(flag - const.flagRigSlot0) 1050 if IsSubsystemFlag(flag): 1051 return 'subsystem slot ' + str(flag - const.flagSubSystemSlot0) 1052 if flag == const.flagDroneBay: 1053 return 'drone bay' 1054 if flag in const.serviceSlotFlags: 1055 return 'service slot ' + str(flag - const.flagServiceSlot0) 1056 1057 1058 class ExportOverviewWindow(ExportBaseWindow): 1059 __guid__ = 'form.ExportOverviewWindow' 1060 default_windowID = 'ExportOverviewWindow' 1061 __notifyevents__ = ['OnOverviewPresetSaved'] 1062 EXPORT_EVERYTHING = False 1063 1064 def ApplyAttributes(self, attributes): 1065 self.overviewPresetSvc = sm.StartService('overviewPresetSvc') 1066 dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'Overview') 1067 attributes.dirpath = dirpath 1068 self.InitPresetsSelected() 1069 ExportBaseWindow.ApplyAttributes(self, attributes) 1070 self.SetCaption(localization.GetByLabel('UI/Commands/ExportOverviewSettings')) 1071 1072 def ConstructTopCont(self): 1073 self.topCont = ContainerAutoSize(name='topCont', align=uiconst.TOTOP, padLeft=4, parent=self.sr.main) 1074 currentText = self.overviewPresetSvc.GetOverviewName() 1075 defaultText = localization.GetByLabel('UI/Overview/DefaultOverviewName', charID=session.charid) 1076 configName = 'overviewProfileNameInExport' 1077 getDragDataFunc = self.GetShareData 1078 shareContainer = DraggableShareContainer(parent=self.topCont, currentText=currentText, defaultText=defaultText, configName=configName, getDragDataFunc=getDragDataFunc, hintText=localization.GetByLabel('UI/Overview/SharableOverviewIconExportHint'), align=uiconst.TOTOP, padTop=4) 1079 self.topCont.height = shareContainer.sharedNameLabel.height + 10 1080 self.checkAllCB = Checkbox(text=localization.GetByLabel('UI/Shared/CheckAllOn'), parent=self.topCont, align=uiconst.TOTOP, callback=self.CheckAll, checked=True, padTop=6, padLeft=4) 1081 1082 def GetShareData(self, text): 1083 selected = self.presetsSelected.copy() 1084 for x in ('generalSettings', 'overviewProfile'): 1085 if x in selected: 1086 selected.remove(x) 1087 1088 if len(selected) > MAX_SHARED_PRESETS: 1089 prompt_player_fsd_dialog('CustomNotify', {'notify': localization.GetByLabel('UI/Overview/TryingToShareTooManyPresets')}) 1090 return [] 1091 return self.overviewPresetSvc.GetShareData(text=text, presetsToUse=selected) 1092 1093 def InitPresetsSelected(self): 1094 self.presetsSelected = set(['generalSettings', 'overviewProfile']) 1095 presetsInUse = self.overviewPresetSvc.GetPresetsInUse() 1096 for eachPresetName in presetsInUse: 1097 lowerDisplayName = eachPresetName.lower() 1098 self.presetsSelected.add(eachPresetName) 1099 1100 def ConstructScrollList(self): 1101 allChecked = True 1102 scrolllist = [] 1103 checked = 'generalSettings' in self.presetsSelected 1104 generalSettingsEntry = GetGeneralOverviewSettingsEntry(onChangeFunc=self.OnSelectionChanged, checked=checked) 1105 scrolllist.append(generalSettingsEntry) 1106 allChecked = allChecked and checked 1107 checked = 'overviewProfile' in self.presetsSelected 1108 profileEntry = GetOverviewProfileEntry(onChangeFunc=self.OnSelectionChanged, checked=checked) 1109 scrolllist.append(profileEntry) 1110 allChecked = allChecked and checked 1111 presetsInUse = self.overviewPresetSvc.GetPresetsInUse() 1112 presetsInUseList = [] 1113 for eachPresetName in presetsInUse: 1114 lowerDisplayName = eachPresetName.lower() 1115 presetsInUseList.append((lowerDisplayName, eachPresetName)) 1116 1117 presetsInUseList = [ x[1] for x in localization.util.Sort(presetsInUseList, key=operator.itemgetter(0)) ] 1118 for eachPresetName in presetsInUseList: 1119 checked = eachPresetName in self.presetsSelected 1120 entry = GetTabPresetEntry(eachPresetName, onChangeFunc=self.OnSelectionChanged, checked=checked) 1121 scrolllist.append(entry) 1122 allChecked = allChecked and checked 1123 1124 allPresets = self.overviewPresetSvc.GetAllPresets() 1125 restOfPresets = [] 1126 defaultProfileNames = self.overviewPresetSvc.GetDefaultOverviewPresetNames() 1127 for eachPresetName in allPresets: 1128 if not self.EXPORT_EVERYTHING: 1129 if eachPresetName in presetsInUse or eachPresetName in defaultProfileNames: 1130 continue 1131 lowerDisplayName = eachPresetName.lower() 1132 restOfPresets.append((lowerDisplayName, eachPresetName)) 1133 1134 if restOfPresets: 1135 restOfPresets = [ x[1] for x in localization.util.Sort(restOfPresets, key=operator.itemgetter(0)) ] 1136 posttext, allSubPresetsChecked = GetPresetPostText(restOfPresets, self.presetsSelected) 1137 allChecked = allChecked and allSubPresetsChecked 1138 scrolllist.append(GetFromClass(ListGroup, {'GetSubContent': self.GetPresetSubContent, 1139 'label': localization.GetByLabel('UI/Overview/OtherTabPresets'), 1140 'id': ('exportOverview', 'restOfPresets'), 1141 'groupItems': restOfPresets, 1142 'showlen': 0, 1143 'sublevel': 0, 1144 'showicon': 'hide', 1145 'state': 'locked', 1146 'posttext': posttext})) 1147 self.sr.scroll.Load(contentList=scrolllist) 1148 self.checkAllCB.SetChecked(allChecked, report=False) 1149 1150 def GetPresetSubContent(self, nodedata): 1151 scrolllist = [] 1152 for eachPresetName in nodedata.groupItems: 1153 checked = eachPresetName in self.presetsSelected 1154 entry = GetTabPresetEntry(eachPresetName, onChangeFunc=self.OnSelectionChanged, checked=checked) 1155 scrolllist.append(entry) 1156 1157 return scrolllist 1158 1159 def Export(self, *args): 1160 if self.sr.filename.GetValue().strip() == '': 1161 raise UserError('NameInvalid') 1162 exportData = {} 1163 presetList = [] 1164 allPresets = self.overviewPresetSvc.GetAllPresets() 1165 defaultProfileNames = self.overviewPresetSvc.GetDefaultOverviewPresetNames() 1166 for checkboxConfig in self.presetsSelected: 1167 if checkboxConfig == 'generalSettings': 1168 generalSettings = self.GetGeneralSettings() 1169 exportData.update(generalSettings) 1170 elif checkboxConfig == 'overviewProfile': 1171 overviewProfile = self.GetOverviewProfile() 1172 exportData['tabSetup'] = overviewProfile 1173 else: 1174 presetName = checkboxConfig 1175 if presetName in allPresets and (self.EXPORT_EVERYTHING or presetName not in defaultProfileNames): 1176 presetAsDict = allPresets[presetName] 1177 presetAsList = GetDeterministicListFromDict(presetAsDict) 1178 presetList.append((presetName, presetAsList)) 1179 1180 if presetList: 1181 exportData['presets'] = presetList 1182 dirpath = os.path.join(blue.sysinfo.GetUserDocumentsDirectory(), 'EVE', 'Overview') 1183 filepath = os.path.join(dirpath, self.sr.filename.GetValue().strip() + '.yaml') 1184 if not os.path.exists(dirpath): 1185 os.makedirs(dirpath) 1186 if os.path.exists(filepath): 1187 if prompt_player_fsd_dialog('FileExists', {}, uiconst.YESNO) != uiconst.ID_YES: 1188 return 1189 with open(filepath, 'w') as yamlFile: 1190 yaml.safe_dump(exportData, yamlFile, default_flow_style=False, allow_unicode=True) 1191 self.CloseByUser() 1192 prompt_player_fsd_dialog('OverviewExportDone', {'filename': filepath}) 1193 1194 def GetGeneralSettings(self): 1195 return self.overviewPresetSvc.GetGeneralSettings() 1196 1197 def GetOverviewProfile(self): 1198 return self.overviewPresetSvc.GetTabSettingsForSaving() 1199 1200 def OnSelectionChanged(self, c, *args): 1201 OnOverviewCheckboxChange(c, self.presetsSelected) 1202 self.ConstructScrollList() 1203 ExportBaseWindow.OnSelectionChanged(self, c) 1204 1205 def CheckAll(self, *args): 1206 checkAll = self.checkAllCB.checked 1207 ModifyPresetSelectedDict(checkAll, self.sr.scroll, self.presetsSelected) 1208 self.ConstructScrollList() 1209 self.ChangeExportButtonState() 1210 1211 def IsAnyEntrySelected(self): 1212 return bool(self.presetsSelected) 1213 1214 def OnOverviewPresetSaved(self, *args): 1215 self.ConstructScrollList() 1216 1217 1218 def GetGeneralOverviewSettingsEntry(onChangeFunc, checked = True): 1219 return GetFromClass(CheckboxEntry, {'label': localization.GetByLabel('UI/Overview/GeneralOverviewSettings'), 1220 'checked': checked, 1221 'cfgname': 'generalSettings', 1222 'retval': checked, 1223 'OnChange': onChangeFunc}) 1224 1225 1226 def GetOverviewProfileEntry(onChangeFunc, checked = True): 1227 return GetFromClass(CheckboxEntry, {'label': localization.GetByLabel('UI/Overview/OverviewProfile'), 1228 'checked': checked, 1229 'cfgname': 'overviewProfile', 1230 'retval': checked, 1231 'OnChange': onChangeFunc, 1232 'hint': localization.GetByLabel('UI/Overview/OverviewProfileHint')}) 1233 1234 1235 def GetTabPresetEntry(eachProfileName, onChangeFunc, checked = True): 1236 return GetFromClass(CheckboxEntry, {'label': localization.GetByLabel('UI/Overview/TabPresetName', presetName=eachProfileName), 1237 'checked': checked, 1238 'cfgname': eachProfileName, 1239 'presetName': eachProfileName, 1240 'retval': checked, 1241 'sublevel': 1, 1242 'OnChange': onChangeFunc}) 1243 1244 1245 def ModifyPresetSelectedDict(checkAll, scroll, presetSelectedDict): 1246 if checkAll: 1247 for entry in scroll.GetNodes(): 1248 guid = entry.__guid__ 1249 if guid == 'listentry.Checkbox': 1250 presetSelectedDict.add(entry.cfgname) 1251 elif guid == 'listentry.Group': 1252 for each in entry.groupItems: 1253 presetSelectedDict.add(each) 1254 1255 else: 1256 presetSelectedDict.clear() 1257 1258 1259 def OnOverviewCheckboxChange(c, presetSelectedDict): 1260 if c.checked: 1261 presetSelectedDict.add(c.GetSettingsKey()) 1262 elif c.GetSettingsKey() in presetSelectedDict: 1263 presetSelectedDict.remove(c.GetSettingsKey()) 1264 1265 1266 def GetPresetPostText(presetsList, presetSelectedDict): 1267 checkedPresets = [ p for p in presetsList if p in presetSelectedDict ] 1268 allChecked = len(checkedPresets) == len(presetsList) 1269 return ('[%s/%s]' % (len(checkedPresets), len(presetsList)), allChecked) 1270 1271 1272 def IsModuleObsolete(typeID): 1273 return bool(sm.GetService('clientDogmaStaticSvc').GetTypeAttribute(typeID, const.attributeModuleIsObsolete))