bookmarksPanel.py (34344B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\neocom\addressBook\bookmarksPanel.py 2 import itertools 3 import eve.common.lib.appConst as appConst 4 import blue 5 import eveicon 6 import localization 7 import telemetry 8 import threadutils 9 import uthread 10 from carbonui import TextColor, uiconst 11 from carbonui.primitives.containerAutoSize import ContainerAutoSize 12 from carbonui.util.color import Color 13 from eve.client.script.ui import eveColor 14 from eve.client.script.ui.control.entries.util import GetFromClass 15 from eve.client.script.ui.shared.addressBookEntries import PlaceEntry 16 from eve.client.script.ui.shared.bookmarks.standaloneBookmarkWnd import StandaloneBookmarkWnd 17 from menu import MenuLabel 18 from caching.memoize import Memoize 19 from carbon.common.script.sys.serviceConst import ROLE_GML, ROLE_WORLDMOD 20 from carbon.common.script.util.format import FmtDate 21 from carbonui.control.scrollentries import SE_GenericCore 22 from carbonui.primitives.container import Container 23 from carbonui.primitives.sprite import Sprite 24 from carbonui.control.buttonIcon import ButtonIcon 25 from eve.client.script.ui.control.entries.generic import Generic 26 from eve.client.script.ui.control.listgroup import ListGroup 27 from eve.client.script.ui.shared.bookmarks.bookmarkContainerWindow import BookmarkContainerWindow 28 from eve.client.script.ui.shared.bookmarks.bookmarkSubfolderWindow import BookmarkSubfolderWindow 29 from eve.client.script.util.bookmarkUtil import IsCoordinateBookmark, IsBookmarkAvailable, ConvertSubfolderName 30 from inventorycommon.const import ownerSystem 31 from localization import GetByLabel, GetByMessageID 32 from localization.util import Sort 33 from player_messaging.client.ui_message import prompt_player_fsd_dialog 34 from sensorsuite.overlay.bookmarkvisibilitymanager import GetBookmarkFolderVisibilityManager 35 from eve.client.script.ui.control import eveIcon, eveScroll 36 from evePathfinder.core import IsUnreachableJumpCount 37 import evetypes 38 from carbonui.uicore import uicore 39 from utillib import KeyVal 40 import inventorycommon.const as invConst 41 COLOR_SELECTED = eveColor.LEAFY_GREEN 42 COLOR_POSTTEXT = Color(*TextColor.SECONDARY).GetHex() 43 COLOR_WARNING_POSTTEXT = Color(*TextColor.WARNING).GetHex() 44 MAX_BOOKMARKS_DISPLAYED_IN_GROUP = 3000 45 placesHeaders = [GetByLabel('UI/PeopleAndPlaces/Label'), 46 GetByLabel('UI/Common/Type'), 47 GetByLabel('UI/PeopleAndPlaces/Jumps'), 48 GetByLabel('UI/PeopleAndPlaces/Sol'), 49 GetByLabel('UI/PeopleAndPlaces/Con'), 50 GetByLabel('UI/PeopleAndPlaces/Reg'), 51 GetByLabel('UI/Common/Date'), 52 GetByLabel('UI/AclBookmarks/Expiry'), 53 GetByLabel('UI/PeopleAndPlaces/Creator')] 54 55 class BookmarksPanel(Container): 56 __guid__ = 'BookmarksPanel' 57 default_name = 'BookmarksPanel' 58 59 def ApplyAttributes(self, attributes): 60 Container.ApplyAttributes(self, attributes) 61 self.semaphore = uthread.Semaphore() 62 self.scroll = BookmarksScroll(parent=self, id='bookmarksPanelScroll', pushContent=True) 63 self.adminFolderId = ('bookmarks', 'adminFolders') 64 uicore.registry.SetListGroupOpenState(self.adminFolderId, 0) 65 66 def Setup(self): 67 self.ShowPlaces() 68 69 def DropInPlacesFolder(self, folderKey, nodes, *args): 70 folderID, subfolderID = folderKey[1] 71 forceCopy = uicore.uilib.Key(uiconst.VK_SHIFT) 72 bookmarkIDsToMove = set() 73 for node in nodes: 74 guid = getattr(node, '__guid__', None) 75 if guid == 'listentry.PlaceEntry': 76 if node.bm is not None: 77 bookmarkIDsToMove.add(node.bm.bookmarkID) 78 79 if bookmarkIDsToMove: 80 sm.GetService('bookmarkSvc').MoveOrCopyBookmarks(folderID, subfolderID, bookmarkIDsToMove, forceCopy) 81 82 def BookmarkCurrentLocation(self, *args): 83 sm.GetService('addressbook').BookmarkCurrentLocation(*args) 84 85 def RefreshScroll(self): 86 if not self.destroyed: 87 self.ShowPlaces() 88 89 @threadutils.threaded 90 def ShowPlaces(self): 91 with self.semaphore: 92 self.scroll.ShowLoading() 93 locations = set() 94 for bm in sm.GetService('bookmarkSvc').GetAllBookmarks().itervalues(): 95 if bm.itemID is not None: 96 locations.add(bm.itemID) 97 if bm.locationID is not None: 98 locations.add(bm.locationID) 99 100 if len(locations): 101 cfg.evelocations.Prime(locations, 0) 102 scrolllist = self.GetFolderSectionList() 103 scrolllist.extend(self.GetAgentPlacesScrollList()) 104 self.scroll.sr.iconMargin = 18 105 scrollToProportion = self.scroll.GetScrollProportion() 106 self.scroll.Load(contentList=scrolllist, fixedEntryHeight=None, headers=placesHeaders, scrollTo=scrollToProportion, noContentHint=GetByLabel('UI/PeopleAndPlaces/NoKnownPlaces'), showCollapseIcon=True) 107 self.scroll.HideLoading() 108 109 def GetAgentPlacesScrollList(self): 110 missiongroupState = uicore.registry.GetListGroupOpenState(('missiongroups', 'agentmissions')) 111 agentGroup = uicore.registry.GetLockedGroup('missiongroups', 'agentmissions', GetByLabel('UI/PeopleAndPlaces/AgentMissions'), openState=missiongroupState) 112 groupEntry = GetFromClass(ListGroup, {'GetSubContent': self.GetPlacesSubContent_AgentMissions, 113 'RefreshScroll': self.RefreshScroll, 114 'label': agentGroup['label'], 115 'id': agentGroup['id'], 116 'groupItems': sm.GetService('bookmarkSvc').GetAgentBookmarks(), 117 'headers': placesHeaders, 118 'showlen': 0, 119 'state': 'locked', 120 'showicon': eveicon.agent_mission}) 121 scrolllist = [] 122 Sort(scrolllist, key=lambda x: x.label) 123 return [groupEntry] + scrolllist 124 125 def GetPlacesSubContent_AgentMissions(self, nodedata, newitems = 0): 126 if newitems: 127 nodedata.groupItems = sm.GetService('bookmarkSvc').GetAgentBookmarks() 128 agentMenu = sm.GetService('journal').GetMyAgentJournalBookmarks() 129 scrolllist = [] 130 headers = [GetByLabel('UI/PeopleAndPlaces/Label'), 131 GetByLabel('UI/Common/Type'), 132 GetByLabel('UI/Common/Date'), 133 GetByLabel('UI/PeopleAndPlaces/Sol'), 134 GetByLabel('UI/PeopleAndPlaces/Con'), 135 GetByLabel('UI/PeopleAndPlaces/Reg')] 136 if agentMenu: 137 for missionNameID, bms, agentID in agentMenu: 138 if bms: 139 if isinstance(missionNameID, basestring): 140 missionName = missionNameID 141 else: 142 missionName = GetByMessageID(missionNameID) 143 missionID = unicode(missionNameID) + unicode(agentID) 144 scrolllist.append(GetFromClass(ListGroup, {'GetSubContent': self.GetPlacesSubContent_AgentMissions2, 145 'RefreshScroll': self.RefreshScroll, 146 'label': missionName, 147 'id': (missionID, missionName), 148 'groupItems': nodedata.groupItems, 149 'headers': headers, 150 'iconMargin': 18, 151 'showlen': 0, 152 'state': 'locked', 153 'sublevel': 1, 154 'showicon': None})) 155 156 return scrolllist 157 158 def GetPlacesSubContent_AgentMissions2(self, nodedata, newitems = 0): 159 if newitems: 160 nodedata.groupItems = sm.GetService('bookmarkSvc').GetAgentBookmarks() 161 groupID = nodedata.id 162 places = [ bm for bm in nodedata.groupItems.itervalues() if bm.missionName == groupID[0] ] 163 return self.GetPlacesScrollList(places, groupID, sublevel=2) 164 165 @telemetry.ZONE_METHOD 166 def GetFolderSectionList(self): 167 contList = [] 168 self.bookmarksBySubfolderByFolder = sm.GetService('bookmarkSvc').GetBookmarksBySubfolderByFolder() 169 folders = sm.GetService('bookmarkSvc').GetFolders().values() 170 personalBookmarkCount = 0 171 sharedBookmarkCount = 0 172 for folder in folders: 173 if not folder.isActive: 174 continue 175 if folder.isPersonal: 176 personalBookmarkCount += sum((len(subfolder) for subfolder in self.bookmarksBySubfolderByFolder[folder.folderID].itervalues())) 177 else: 178 sharedBookmarkCount += sum((len(subfolder) for subfolder in self.bookmarksBySubfolderByFolder[folder.folderID].itervalues())) 179 180 contList.append(GetFromClass(LocalLocationsFolder, {'label': GetByLabel('UI/AclBookmarks/LocationsInSystem', system=cfg.evelocations.Get(session.solarsystemid2).name), 181 'id': ('myPlaces', 'localLocations'), 182 'headers': placesHeaders, 183 'GetSubContent': self.GetLocalLocationsScrollList, 184 'open': False, 185 'state': 'locked', 186 'showicon': eveicon.folder, 187 'showlen': False})) 188 for isPersonal in [True, False]: 189 if isPersonal: 190 iconPath = eveicon.folder 191 label = GetByLabel('UI/PeopleAndPlaces/PersonalLocations') 192 id = ('myPlaces', 'personalFolders') 193 count = personalBookmarkCount 194 else: 195 iconPath = eveicon.shared_folder 196 label = GetByLabel('UI/PeopleAndPlaces/SharedLocations') 197 id = ('myPlaces', 'sharedFolders') 198 count = sharedBookmarkCount 199 groupEntry = GetFromClass(ListGroup, {'GetSubContent': self.GetLocationFolderScrollList, 200 'label': label, 201 'id': id, 202 'groupItems': [], 203 'folders': folders, 204 'isPersonal': isPersonal, 205 'headers': placesHeaders, 206 'open': False, 207 'posttext': '<color=%s>[%d]</color>' % (COLOR_POSTTEXT, count), 208 'showlen': False, 209 'state': 'locked', 210 'showicon': iconPath}) 211 contList.append(groupEntry) 212 213 return contList 214 215 def GetLocalLocationsScrollList(self, nodedata, newitems = 0): 216 bookmark_service = sm.GetService('bookmarkSvc') 217 bookmarks = bookmark_service.GetBookmarksForLocationID(session.solarsystemid2) 218 return self.GetPlacesScrollList(places=bookmarks, groupID=nodedata.id, sublevel=1, isGroupPersonal=True) 219 220 @telemetry.ZONE_METHOD 221 def GetLocationFolderScrollList(self, nodedata, newitems = 0): 222 if newitems: 223 self.bookmarksBySubfolderByFolder = sm.GetService('bookmarkSvc').GetBookmarksBySubfolderByFolder() 224 contList = [] 225 folders = nodedata.folders 226 isPersonal = nodedata.isPersonal 227 maxCount = appConst.MAX_BOOKMARKS_IN_PERSONAL_FOLDER if isPersonal else appConst.MAX_BOOKMARKS_IN_SHARED_FOLDER 228 activeFolders = [ f for f in folders if f.isActive ] 229 activeFolders.sort(key=lambda fld: (-fld.isPersonal, fld.folderName.lower())) 230 for folder in activeFolders: 231 if folder.isPersonal != isPersonal: 232 continue 233 folderID = folder.folderID 234 count = sum((len(subfolder) for subfolder in self.bookmarksBySubfolderByFolder[folderID].itervalues())) 235 if count > maxCount: 236 postText = '<color=%s>[%d]</color>' % (COLOR_WARNING_POSTTEXT, count) 237 hint = GetByLabel('UI/AclBookmarks/TooManyBookmarksInFolderHint', currentBookmarks=count, maxBookmarks=maxCount) 238 else: 239 postText = '<color=%s>[%d]</color>' % (COLOR_POSTTEXT, count) 240 hint = None 241 if isPersonal: 242 iconPath = eveicon.folder 243 else: 244 iconPath = eveicon.shared_folder 245 entry = GetFromClass(BookmarkFolderGroup, {'GetSubContent': self.GetPlacesSubfolders, 246 'DropData': self.DropInPlacesFolder, 247 'hint': hint, 248 'label': folder.folderName, 249 'folderName': folder.folderName, 250 'posttext': postText, 251 'id': ('myPlaces', (folderID, None)), 252 'groupItems': self.bookmarksBySubfolderByFolder[folderID], 253 'folderID': folderID, 254 'folder': folder, 255 'state': 'locked', 256 'showicon': iconPath, 257 'showlen': False, 258 'sublevel': 1, 259 'isDragObject': True, 260 'MenuFunction': self.BookmarkACLFolderMenu, 261 'allowGuids': ['listentry.PlaceEntry', 'xtriui.InvItem', 'listentry.InvItem']}) 262 contList.append(entry) 263 264 inactiveFolders = [ x for x in folders if not x.isActive and x.isPersonal == isPersonal ] 265 if inactiveFolders: 266 inactiveFolders.sort(key=lambda fl: fl.folderName.lower()) 267 inactiveFoldersEntry = self._GetEntryForInactiveFolders(inactiveFolders, self.bookmarksBySubfolderByFolder) 268 contList.append(inactiveFoldersEntry) 269 if not isPersonal: 270 contList.extend(self.GetAdminFoldersScrollList()) 271 return contList 272 273 def _GetEntryForInactiveFolders(self, inactiveFolders, bookmarksBySubfolderByFolder): 274 entry = GetFromClass(ListGroup, {'GetSubContent': self._GetInactiveFolders, 275 'label': GetByLabel('UI/AclBookmarks/InactiveFolders'), 276 'id': ('inactiveFolders', None), 277 'groupItems': inactiveFolders, 278 'bookmarksBySubfolderByFolder': bookmarksBySubfolderByFolder, 279 'state': 'locked', 280 'showicon': 'hide', 281 'showlen': False, 282 'sublevel': 1}) 283 return entry 284 285 def _GetInactiveFolders(self, nodedata, newitems = 0): 286 scrollList = [] 287 for folder in nodedata.groupItems: 288 if folder.isPersonal: 289 texturePath = eveicon.folder 290 iconHint = GetByLabel('UI/AclBookmarks/PersonalFolderType') 291 else: 292 texturePath = eveicon.shared_folder 293 iconHint = GetByLabel('UI/AclBookmarks/SharedFolderType') 294 entry = GetFromClass(InactiveFolderEntry, {'label': folder.folderName, 295 'folderName': folder.folderName, 296 'id': ('inactiveFolder_%s' % folder.folderID, None), 297 'folderID': folder.folderID, 298 'folder': folder, 299 'state': 'locked', 300 'texturePath': texturePath, 301 'iconHint': iconHint, 302 'GetMenu': self.GetMenuForInactiveFolders, 303 'sublevel': 2}) 304 scrollList.append(entry) 305 306 return scrollList 307 308 def GetMenuForInactiveFolders(self, entry): 309 return self.BookmarkACLFolderMenu(entry.sr.node) 310 311 def BookmarkACLFolderMenu(self, node): 312 menuList = [(MenuLabel('UI/AclBookmarks/FolderInformation'), self.ShowBookmarkFolderInfo, (node.folderID,))] 313 if node.folder.accessLevel in (appConst.ACCESS_PERSONAL, appConst.ACCESS_ADMIN): 314 menuList.append((MenuLabel('UI/AclBookmarks/EditBookmarkFolder'), self.EditACLFolder, (node.folderID,))) 315 menuList.append((MenuLabel('UI/AclBookmarks/DeleteBookmarkFolder'), self.DeleteACLFolder, (node.folderID,))) 316 if not node.folder.isPersonal: 317 menuList.append((MenuLabel('UI/AclBookmarks/ForgetBookmarkFolder'), self.ForgetFolder, (node.folderID,))) 318 if node.folder.isActive: 319 menuList.append((MenuLabel('UI/AclBookmarks/MarkFolderAsInactive'), self.MarkFolderAsInactive, (node.folderID,))) 320 if node.folder.accessLevel != appConst.ACCESS_VIEW: 321 menuList.append((MenuLabel('UI/AclBookmarks/CreateSubfolder'), self.CreateSubFolderInFolder, (node.folderID,))) 322 else: 323 menuList.append((MenuLabel('UI/AclBookmarks/MarkFolderActive'), self.MarkFolderAsActive, (node.folderID,))) 324 if session.role & (ROLE_GML | ROLE_WORLDMOD): 325 menuList.append(('GM: FolderID: ' + str(node.folderID), blue.pyos.SetClipboardData, (str(node.folderID),))) 326 return menuList 327 328 @telemetry.ZONE_METHOD 329 def GetSubfolderEntry(self, subfolder, folderID, bookmarks, isPersonal): 330 if isPersonal: 331 iconPath = eveicon.folder 332 else: 333 iconPath = eveicon.shared_folder 334 if subfolder.creatorID is not None: 335 if subfolder.creatorID == invConst.ownerSystem: 336 label = GetByLabel(subfolder.subfolderName) 337 else: 338 label = GetByLabel('UI/PeopleAndPlaces/FolderName', folderName=subfolder.subfolderName, creator=subfolder.creatorID) 339 else: 340 label = subfolder.subfolderName 341 count = len(bookmarks) 342 maxCount = MAX_BOOKMARKS_DISPLAYED_IN_GROUP 343 if count > maxCount: 344 text = GetByLabel('UI/AclBookmarks/TruncatedBookmarksInSubfolder', maxBookmarks=maxCount, currentBookmarks=count) 345 postText = '<color=%s>[%s]</color>' % (COLOR_WARNING_POSTTEXT, text) 346 hint = GetByLabel('UI/AclBookmarks/TooManyBookmarksInSubfolderHint', currentBookmarks=count, maxBookmarks=maxCount) 347 else: 348 postText = '<color=%s>[%d]</color>' % (COLOR_POSTTEXT, count) 349 hint = None 350 return GetFromClass(BaseFolderGroup, {'GetSubContent': self.GetPlacesSubEntries, 351 'DropData': self.DropInPlacesFolder, 352 'hint': hint, 353 'label': label, 354 'id': ('myPlaces', (folderID, subfolder.subfolderID)), 355 'folderID': folderID, 356 'groupItems': bookmarks, 357 'posttext': postText, 358 'showlen': False, 359 'sublevel': 2, 360 'subfolderID': subfolder.subfolderID, 361 'subfolder': subfolder, 362 'MenuFunction': self.BookmarkSubfolderMenu, 363 'state': 'locked', 364 'showicon': iconPath, 365 'isPersonal': isPersonal, 366 'allowGuids': ['listentry.PlaceEntry', 'xtriui.InvItem', 'listentry.InvItem']}) 367 368 @telemetry.ZONE_METHOD 369 def GetPlacesSubEntries(self, nodedata, newitems = 0): 370 if newitems: 371 places = sm.GetService('bookmarkSvc').GetBookmarksBySubfolderByFolder()[nodedata.folderID][nodedata.subfolderID] 372 else: 373 places = nodedata.groupItems 374 isPersonal = nodedata.isPersonal 375 return self.GetPlacesScrollList(places, nodedata.subfolderID, sublevel=3, isGroupPersonal=isPersonal) 376 377 @telemetry.ZONE_METHOD 378 def GetPlacesSubfolders(self, nodedata, newitems = 0): 379 folderID = nodedata.folderID 380 bookmarkSvc = sm.GetService('bookmarkSvc') 381 subfolders = bookmarkSvc.GetSubfoldersInFolder(folderID) 382 if newitems: 383 bookmarksBySubfolder = bookmarkSvc.GetBookmarksBySubfolderByFolder()[folderID] 384 else: 385 bookmarksBySubfolder = nodedata.groupItems 386 entries = [] 387 isPersonal = nodedata.folder.isPersonal 388 for subfolder in Sort(subfolders.values(), key=ConvertSubfolderName): 389 entry = self.GetSubfolderEntry(subfolder, folderID, bookmarksBySubfolder[subfolder.subfolderID], isPersonal) 390 entries.append(entry) 391 392 entries.extend(self.GetPlacesScrollList(bookmarksBySubfolder[None], (folderID, None), sublevel=2, isGroupPersonal=isPersonal)) 393 return entries 394 395 def BookmarkSubfolderMenu(self, node): 396 folder = sm.GetService('bookmarkSvc').GetBookmarkFolder(node.subfolder.folderID) 397 m = [] 398 if folder.accessLevel != appConst.ACCESS_VIEW and (folder.accessLevel != appConst.ACCESS_USE or node.subfolder.creatorID == session.charid): 399 if node.subfolder.creatorID != ownerSystem: 400 m += [(MenuLabel('UI/AclBookmarks/EditSubfolder'), self.EditSubfolder, (node.subfolderID,))] 401 m += [(MenuLabel('UI/AclBookmarks/DeleteSubfolder'), self.DeleteSubfolder, (node.subfolderID,))] 402 if session.role & (ROLE_GML | ROLE_WORLDMOD): 403 m += [('GM: subfolderID: ' + str(node.subfolderID), blue.pyos.SetClipboardData, (str(node.subfolderID),))] 404 return m 405 406 def CreateACLFolder(self, *args): 407 wnd = BookmarkContainerWindow.Open() 408 wnd.Maximize() 409 410 def ShowBookmarkFolderInfo(self, folderID): 411 sm.GetService('bookmarkSvc').ShowBookmarkFolderInfo(folderID) 412 413 def EditACLFolder(self, folderID): 414 folder = sm.GetService('bookmarkSvc').GetBookmarkFolder(folderID, refresh=True) 415 windowID = '%s_%s' % (BookmarkContainerWindow.default_windowID, folderID) 416 wnd = BookmarkContainerWindow.Open(folder=folder, windowID=windowID) 417 wnd.Maximize() 418 419 def DeleteACLFolder(self, folderID): 420 if sm.GetService('bookmarkSvc').onlyPartiallyLoaded: 421 msg = 'ConfirmDeleteFolderPartiallyLoaded' 422 else: 423 msg = 'ConfirmDeleteFolder' 424 if prompt_player_fsd_dialog(msg, {}, uiconst.YESNO, uiconst.ID_YES) == uiconst.ID_YES: 425 sm.GetService('bookmarkSvc').DeleteBookmarkFolder(folderID) 426 427 def ForgetFolder(self, folderID): 428 if prompt_player_fsd_dialog('ConfirmForgetFolder', {}, uiconst.YESNO, uiconst.ID_YES) == uiconst.ID_YES: 429 sm.GetService('bookmarkSvc').RemoveFromKnownFolders(folderID) 430 431 def MarkFolderAsInactive(self, folderID): 432 sm.GetService('bookmarkSvc').UpdateFolderActiveState(folderID, False) 433 434 def MarkFolderAsActive(self, folderID): 435 sm.GetService('bookmarkSvc').UpdateFolderActiveState(folderID, True) 436 437 def CreateSubFolderInFolder(self, folderID): 438 windowID = '%s_newSub_%s' % (BookmarkSubfolderWindow.default_windowID, folderID) 439 wnd = BookmarkSubfolderWindow.Open(folderID=folderID, windowID=windowID) 440 wnd.Maximize() 441 442 def CreateSubfolder(self, *args): 443 validFolders = sm.GetService('bookmarkSvc').GetFilteredFolders() 444 if len(validFolders) == 0: 445 if prompt_player_fsd_dialog('CreateBookmarkFolderAsNoneValid', {}, uiconst.YESNO, uiconst.ID_YES) == uiconst.ID_YES: 446 wnd = BookmarkContainerWindow.Open() 447 wnd.Maximize() 448 return 449 wnd = BookmarkSubfolderWindow.Open() 450 wnd.Maximize() 451 452 def EditSubfolder(self, subfolderID): 453 subfolder = sm.GetService('bookmarkSvc').GetSubfolder(subfolderID) 454 windowID = '%s_%s' % (BookmarkSubfolderWindow.default_windowID, subfolderID) 455 wnd = BookmarkSubfolderWindow.Open(subfolder=subfolder, windowID=windowID) 456 wnd.Maximize() 457 458 def DeleteSubfolder(self, subfolderID): 459 if sm.GetService('bookmarkSvc').onlyPartiallyLoaded: 460 msg = 'ConfirmDeleteSubfolderPartiallyLoaded' 461 else: 462 msg = 'ConfirmDeleteSubfolder' 463 if prompt_player_fsd_dialog(msg, {}, uiconst.YESNO, uiconst.ID_YES) == uiconst.ID_YES: 464 sm.GetService('bookmarkSvc').DeleteSubfolder(subfolderID) 465 466 @telemetry.ZONE_METHOD 467 def GetPlacesScrollList(self, places, groupID, sublevel, isGroupPersonal = False): 468 addressbook = sm.GetService('addressbook') 469 bookmarkSvc = sm.GetService('bookmarkSvc') 470 scrolllist = [] 471 unreachabelText = GetByLabel('UI/Common/unreachable') 472 coordinateText = GetByLabel('UI/PeopleAndPlaces/Coordinate') 473 now = blue.os.GetWallclockTime() 474 maxCount = MAX_BOOKMARKS_DISPLAYED_IN_GROUP 475 if len(places) > maxCount: 476 places = itertools.islice(places, maxCount) 477 for bookmark in places: 478 hint, comment = bookmarkSvc.UnzipMemo(bookmark.memo) 479 sol, con, reg = addressbook.GetSolConReg(bookmark) 480 typename = self.GetGroupName(bookmark.typeID) 481 date = FmtDate(bookmark.created, 'ls') 482 expiry = FmtDate(bookmark.expiry, 'ls') if bookmark.expiry else '-' 483 if bookmark and IsCoordinateBookmark(bookmark): 484 typename = coordinateText 485 jumps = 0 486 if 40000000 > bookmark.itemID > 30000000: 487 jumps = self.GetJumpCount(session.solarsystemid2, bookmark.itemID) 488 if IsUnreachableJumpCount(jumps): 489 jumps = sm.GetService('clientPathfinderService').GetNoRouteFoundText(bookmark.itemID) 490 elif 40000000 > bookmark.locationID > 30000000: 491 jumps = self.GetJumpCount(session.solarsystemid2, bookmark.locationID) 492 if IsUnreachableJumpCount(jumps): 493 jumps = sm.GetService('clientPathfinderService').GetNoRouteFoundText(bookmark.locationID) 494 creatorID = getattr(bookmark, 'creatorID', None) 495 creatorName = self.GetCreatorName(creatorID) 496 isBookmarkAvailable = IsBookmarkAvailable(creatorID, bookmark.created, now) 497 folderID = getattr(bookmark, 'folderID', None) 498 if folderID is not None: 499 _, isPersonal = bookmarkSvc.GetFolderNamesAndType(folderID, subfolderID=getattr(bookmark, 'subfolderID', None)) 500 else: 501 isPersonal = creatorID == session.charid 502 text = '<t>'.join((unicode(x) for x in (hint, 503 typename, 504 jumps, 505 sol, 506 con, 507 reg, 508 date, 509 expiry, 510 creatorName))) 511 hintForBookmark = hint 512 if getattr(bookmark, 'note', None): 513 truncatedNote = bookmark.note[:50] + '...' if len(bookmark.note) > 50 else bookmark.note 514 hintForBookmark += '<br>- %s' % truncatedNote 515 scrolllist.append(GetFromClass(PlaceEntry, {'bm': bookmark, 516 'DropData': lambda *args: self.DropOnBookmark(bookmark, *args), 517 'itemID': bookmark.bookmarkID, 518 'tabs': [], 519 'hint': hintForBookmark, 520 'comment': comment, 521 'label': text, 522 'sublevel': sublevel, 523 'listGroupID': groupID, 524 'isGroupPersonal': isPersonal, 525 'isBookmarkAvailable': isBookmarkAvailable, 526 'GetSortValue': self.GetLocationSortValue})) 527 blue.pyos.BeNice() 528 529 return scrolllist 530 531 def GetLocationSortValue(self, node, by, sortDirection, idx): 532 label = node.label 533 strings = label.split('<t>') 534 if idx is not None and len(strings) > idx: 535 value = strings[idx].lower() 536 try: 537 value = float(value) 538 return value 539 except ValueError: 540 return value 541 542 val = label.lower() 543 return val 544 545 @Memoize 546 def GetCreatorName(self, creatorID): 547 if creatorID is not None: 548 creatorName = cfg.eveowners.Get(creatorID).name 549 else: 550 creatorName = '' 551 return creatorName 552 553 @Memoize 554 def GetGroupName(self, typeID): 555 return evetypes.GetGroupName(typeID) 556 557 @Memoize(2) 558 def GetJumpCount(self, solarsystemID, itemID): 559 pathfinder = sm.GetService('clientPathfinderService') 560 return pathfinder.GetAutopilotJumpCount(solarsystemID, itemID) 561 562 def DropOnBookmark(self, bookmark, dragNode, nodes, *args): 563 if not hasattr(bookmark, 'folderID'): 564 return 565 groupKey = (None, (bookmark.folderID, bookmark.subfolderID)) 566 self.DropInPlacesFolder(groupKey, nodes) 567 568 @telemetry.ZONE_METHOD 569 def GetAdminFoldersScrollList(self): 570 iconPath = eveicon.corporation_folder 571 id = self.adminFolderId 572 hint = GetByLabel('UI/AclBookmarks/AdminFolderHint') 573 groupEntry = GetFromClass(ListGroup, {'GetSubContent': self.GetAdminFolders, 574 'RefreshScroll': self.RefreshScroll, 575 'label': GetByLabel('UI/AclBookmarks/FolderWithAdminAccess'), 576 'id': id, 577 'groupItems': [], 578 'headers': placesHeaders, 579 'hint': hint, 580 'open': False, 581 'showlen': 0, 582 'state': 'locked', 583 'showicon': iconPath, 584 'sublevel': 1}) 585 return [groupEntry] 586 587 @telemetry.ZONE_METHOD 588 def GetAdminFolders(self, *args): 589 searchResults = self.FetchAdminSearchResults() 590 scrollList = [] 591 knownFolders = sm.GetService('bookmarkSvc').foldersNew 592 for folder in searchResults: 593 name = folder.folderName 594 if folder.folderID in knownFolders: 595 isKnown = True 596 if knownFolders[folder.folderID].isActive: 597 postText = GetByLabel('UI/AclBookmarks/SubscribedActive') 598 else: 599 postText = GetByLabel('UI/AclBookmarks/SubscribedInactive') 600 else: 601 isKnown = False 602 postText = GetByLabel('UI/AclBookmarks/NotSubscribed') 603 label = '%s <color=%s>[%s]</color>' % (name, COLOR_POSTTEXT, postText) 604 scrollList.append(GetFromClass(AdminFolder, {'hint': postText, 605 'label': label, 606 'OnDblClick': self.OnDblClickAdminFolder, 607 'OnGetMenu': self.ShowMenuAdminFolders, 608 'folderID': folder.folderID, 609 'folderName': folder.folderName, 610 'isKnown': isKnown, 611 'sublevel': 2})) 612 613 if not scrollList: 614 scrollList.append(GetFromClass(SE_GenericCore, {'label': GetByLabel('UI/AclBookmarks/NoAdminFolderFound'), 615 'sublevel': 2})) 616 return scrollList 617 618 def FetchAdminSearchResults(self): 619 bookmarkSvc = sm.GetService('bookmarkSvc') 620 resultFolders = bookmarkSvc.SearchFoldersWithAdminAccess() 621 return resultFolders 622 623 def OnDblClickAdminFolder(self, entry): 624 node = entry.sr.node 625 if node.isKnown: 626 self.EditACLFolder(node.folderID) 627 else: 628 sm.GetService('bookmarkSvc').ShowBookmarkFolderInfo(node.folderID) 629 630 def ShowMenuAdminFolders(self, entry): 631 node = entry.sr.node 632 menuList = [] 633 if node.isKnown: 634 menuList += [(MenuLabel('UI/AclBookmarks/FolderInformation'), self.ShowBookmarkFolderInfo, (node.folderID,)), (MenuLabel('UI/AclBookmarks/ForgetBookmarkFolder'), self.ForgetFolder, (node.folderID,))] 635 else: 636 menuList += [(MenuLabel('UI/AclBookmarks/AddFolder'), self.ShowBookmarkFolderInfo, (node.folderID,))] 637 if session.role & (ROLE_GML | ROLE_WORLDMOD): 638 menuList += [('GM: FolderID: ' + str(node.folderID), blue.pyos.SetClipboardData, (str(node.folderID),))] 639 return menuList 640 641 642 class BookmarksScroll(eveScroll.Scroll): 643 644 def CollectSubNodes(self, node, nodes = None, clear = 1): 645 if nodes is None: 646 nodes = [] 647 for subnode in node.get('subNodes', []): 648 if subnode is None: 649 continue 650 self.CollectSubNodes(subnode, nodes, clear) 651 nodes.append(subnode) 652 653 if clear: 654 node.subNodes = [] 655 return nodes 656 657 658 class BaseFolderGroup(ListGroup): 659 660 def Startup(self, *etc): 661 ListGroup.Startup(self, *etc) 662 self.overlayButton = ButtonIcon(name='overlayButton', parent=self.sr.labelClipper, align=uiconst.CENTERLEFT, width=14, height=14, iconSize=16, left=200, texturePath=eveicon.visibility, func=self.OnChangeSensorOverlayVisibility, colorSelected=COLOR_SELECTED, isSelectedBgUsed=False) 663 664 def Load(self, node): 665 ListGroup.Load(self, node) 666 self.folderKey = node.id[1] 667 self.overlayButton.left = self.sr.label.width + self.sr.label.left + 8 668 self.SetIsVisible(GetBookmarkFolderVisibilityManager().IsFolderVisible(self.folderKey)) 669 670 def OnChangeSensorOverlayVisibility(self): 671 bmVisibilityMgr = GetBookmarkFolderVisibilityManager() 672 isVisible = not bmVisibilityMgr.IsFolderVisible(self.folderKey) 673 bmVisibilityMgr.SetFolderVisibility(self.folderKey, isVisible) 674 sm.ScatterEvent('OnRefreshBookmarks') 675 self.SetIsVisible(isVisible) 676 677 def SetIsVisible(self, isVisible): 678 if isVisible: 679 hint = GetByLabel('UI/PeopleAndPlaces/RemoveLocationFolderFromSensorOverlay') 680 self.overlayButton.SetSelected() 681 else: 682 hint = GetByLabel('UI/PeopleAndPlaces/ShowLocationFolderInSensorOverlay') 683 self.overlayButton.SetDeselected() 684 self.overlayButton.hint = hint 685 686 687 class BookmarkFolderGroup(BaseFolderGroup): 688 isDragObject = True 689 690 def GetDragData(self): 691 if self.sr.node.folder.isPersonal: 692 return [] 693 ret = KeyVal(nodeType='BookmarkFolderEntry', folderID=self.sr.node.folderID, label=self.sr.node.folderName) 694 return [ret] 695 696 697 class InactiveFolderEntry(Generic): 698 isDragObject = True 699 700 def Startup(self, *args): 701 Generic.Startup(self, *args) 702 self.icon = Sprite(parent=self, align=uiconst.CENTERLEFT, pos=(60, 0, 16, 16), state=uiconst.UI_DISABLED) 703 704 def Load(self, node): 705 Generic.Load(self, node) 706 sublevelCorrection = self.sr.node.scroll.sr.get('sublevelCorrection', 0) 707 sublevel = max(0, node.Get('sublevel', 0) - sublevelCorrection) 708 iconLeft = 5 + 16 * sublevel 709 self.icon.texturePath = node.texturePath 710 self.icon.hint = node.iconHint 711 self.icon.left = iconLeft 712 self.sr.label.left = self.icon.left + 20 713 self.sr.label.opacity = self.icon.opacity = 0.6 714 715 def GetDragData(self): 716 if self.sr.node.folder.isPersonal: 717 return [] 718 ret = KeyVal(nodeType='BookmarkFolderEntry', folderID=self.sr.node.folderID, label=self.sr.node.folderName) 719 return [ret] 720 721 722 class AdminFolder(SE_GenericCore): 723 isDragObject = True 724 725 def ApplyAttributes(self, attributes): 726 SE_GenericCore.ApplyAttributes(self, attributes) 727 self.sr.icon = eveIcon.Icon(icon=eveicon.corporation_folder, parent=self, pos=(37, 2, 16, 16), align=uiconst.RELATIVE, ignoreSize=True, state=uiconst.UI_DISABLED) 728 729 def Load(self, node): 730 SE_GenericCore.Load(self, node) 731 sublevelCorrection = self.sr.node.scroll.sr.get('sublevelCorrection', 0) 732 sublevel = max(0, node.Get('sublevel', 0) - sublevelCorrection) 733 self.sr.icon.left = 5 + 16 * sublevel 734 self.sr.label.left = self.sr.icon.left + 20 735 736 def GetDragData(self): 737 ret = KeyVal(nodeType='BookmarkFolderEntry', folderID=self.sr.node.folderID, label=self.sr.node.folderName) 738 return [ret] 739 740 741 class LocalLocationsFolder(ListGroup): 742 743 def Startup(self, *etc): 744 super(LocalLocationsFolder, self).Startup(*etc) 745 ButtonIcon(parent=ContainerAutoSize(parent=self, align=uiconst.TORIGHT, idx=self.sr.labelClipper.GetOrder()), align=uiconst.CENTER, texturePath=eveicon.open_window, hint=localization.GetByLabel('UI/Common/OpenInWindow'), func=StandaloneBookmarkWnd.Open, args=())