buyMultiFromBase.py (28465B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\market\buyMultiFromBase.py 2 from carbonui.control.buttonIcon import ButtonIcon 3 from carbonui.control.combo import Combo 4 from collections import Counter 5 import blue 6 import eveLocalization 7 import evetypes 8 import localization 9 import locks 10 import log 11 import uthread 12 from carbon.common.script.util.format import FmtAmt 13 from carbon.common.script.util.timerstuff import AutoTimer 14 from carbonui import uiconst 15 from carbonui.control.combo import Combo 16 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger 17 from carbonui.primitives.layoutGrid import LayoutGrid 18 from carbonui.primitives.sprite import Sprite 19 from carbonui.uicore import uicore 20 from carbonui.util.various_unsorted import GetClipboardData 21 from carbonui.util.various_unsorted import SortListOfTuples 22 from collections import Counter 23 from eve.client.script.ui.control.eveLabel import EveLabelLargeBold 24 from eve.client.script.ui.control.eveLoadingWheel import LoadingWheel 25 from eve.client.script.ui.control.infoIcon import MoreExtraInfoInTooltip 26 from eve.client.script.ui.shared.fitting.fittingInfoTooltip import LoadFittingInfoTooltip 27 from eve.client.script.ui.shared.market import GetTypeIDFromDragItem 28 from eve.client.script.ui.shared.market.buySellMultiBase import SellBuyItemsWindow, COL_RED 29 from eve.client.script.ui.shared.market.buytItemEntry import BuyItemContainer 30 from eve.client.script.util.contractutils import FmtISKWithDescription 31 from eve.common.lib import appConst as const 32 from eve.common.script.util.eveFormat import FmtISK 33 from eveexceptions.exceptionEater import ExceptionEater 34 from inventorycommon.const import typePlex 35 from inventorycommon.util import GetPackagedVolume 36 from localization import GetByLabel 37 from marketutil.const import MAX_ORDER_PRICE 38 from marketutil.orderInfo import GetBuyItemInfo 39 from player_messaging.client.ui_message import prompt_player_fsd_dialog 40 from textImporting import CleanText, GetNameFunc 41 from textImporting.importMultibuy import ImportMultibuy 42 from uthread2 import BufferedCall 43 from utillib import KeyVal 44 ACTION_ICON = 'res:/UI/Texture/classes/UtilMenu/BulletIcon.png' 45 MILLION = 1000000 46 47 class MultiBuy(SellBuyItemsWindow): 48 __guid__ = 'form.BuyItems' 49 default_iconNum = 'res:/UI/Texture/classes/MultiSell/multiBuy.png' 50 default_windowID = 'MultiBuy' 51 default_name = 'multiBuy' 52 captionTextPath = 'UI/Inventory/ItemActions/MultiBuy' 53 scrollId = 'MultiBuyScroll' 54 tradeForCorpSettingConfig = 'buyUseCorp' 55 tradeTextPath = 'UI/Market/MarketQuote/CommandBuy' 56 orderCap = 'MultiBuyOrderCap' 57 tradeOnConfirm = False 58 dropLabelPath = 'UI/Market/Marketbase/DropItemsToAddToBuy' 59 cannotBeTradeLabelPath = 'UI/Market/MarketQuote/CannotBeBought' 60 badDeltaWarningPath = 'UI/Market/MarketQuote/MultiBuyTypesAboveAverage' 61 importHintLabelPath = 'UI/Market/MarketQuote/ImportShoppingListHint' 62 exportHintLabelPath = 'UI/Market/MarketQuote/ExportShoppingListHint' 63 corpCheckboxTop = 0 64 numbersGridTop = 1 65 belowColor = '<color=0xff00ff00>' 66 aboveColor = '<color=0xffff5050>' 67 __notifyevents__ = ['OnOwnOrdersChanged', 'OnSessionChanged'] 68 69 def ApplyAttributes(self, attributes): 70 self.blinkEditBG = None 71 SellBuyItemsWindow.ApplyAttributes(self, attributes) 72 self.AddBuyAndFitBtn() 73 self.dropCont.OnDropData = self.DropItems 74 self.infoCont.height = 44 75 self.totalAmt.LoadTooltipPanel = self.LoadTotalTooltip 76 self.itemsScroll.OnDropData = self.DropItems 77 self.AddLoadingWheel() 78 self.DrawStationWarning() 79 self.AddToLocationCont() 80 self.StartAddItemsThread() 81 82 def AddBuyAndFitBtn(self): 83 self.buyAndFitBtn = self.btnGroup.AddButton(GetByLabel('UI/Market/MarketQuote/BuyAndFit'), self.BuyAndFit) 84 self.buyAndFitBtn.SetOrder(0) 85 self.buyAndFitBtn.LoadTooltipPanel = lambda tooltipPanel, *args: LoadFittingInfoTooltip(tooltipPanel, self.fitting) 86 if not self.fitting: 87 self.buyAndFitBtn.display = False 88 self.btnGroup.ResetLayout() 89 90 def InitializeVariables(self, attributes): 91 SellBuyItemsWindow.InitializeVariables(self, attributes) 92 self.entriesInScrollByTypeID = {} 93 self.orderMultiplier = 1 94 self.activeOrders = set() 95 self.orderDisabled = False 96 self.preItems = self.GetKeyValsForWantedTypes(attributes.get('wantToBuy')) 97 self.reloadingItemsCounter = 0 98 self.verifyMultiplierTimer = None 99 self.expiredOrders = {} 100 self.fitting = attributes.fitting 101 self.buyAndFitClicked = None 102 self.fittingPending = False 103 104 def DrawNumbers(self): 105 self.numbersGrid = LayoutGrid(parent=self.bottomRight, columns=2, align=uiconst.TORIGHT, top=self.numbersGridTop, state=uiconst.UI_PICKCHILDREN, cellSpacing=(10, 0)) 106 self.totalAmt = EveLabelLargeBold(parent=self.numbersGrid, text='', align=uiconst.CENTERRIGHT, padLeft=4, state=uiconst.UI_NORMAL) 107 self.moreInfoIcon = MoreExtraInfoInTooltip(parent=self.numbersGrid, align=uiconst.CENTERLEFT) 108 self.moreInfoIcon.LoadTooltipPanel = self.LoadTotalTooltip 109 110 def GetKeyValsForWantedTypes(self, wantToBuy): 111 keyVals = [] 112 for typeID, qty in wantToBuy.iteritems(): 113 keyVals.append(KeyVal(typeID=typeID, qty=qty)) 114 115 return keyVals 116 117 def AddToLocationCont(self): 118 self.locationCont.padTop = 24 119 self.locationCont.height = 32 120 self.orderMultiplierEdit = SingleLineEditInteger(name='orderMultiplierEdit', parent=self.locationCont, align=uiconst.TOPRIGHT, label=GetByLabel('UI/Market/MarketQuote/NumberOfOrders'), adjustWidth=True, minValue=1, maxValue=1000, OnChange=self.OnMultiplierEditChange) 121 self.stationCombo = Combo(parent=self.locationCont, callback=self.OnStationChanged, width=200, noChoiceLabel=GetByLabel('UI/Market/MarketQuote/NotStationsAvailable')) 122 self.LoadStationOptions() 123 124 def _AddImportButton(self): 125 hint = '%s<br><br>%s' % (GetByLabel('UI/Market/MarketQuote/ImportShoppingListOption'), GetByLabel('UI/Market/MarketQuote/ImportShoppingListOptionHint', type1=const.typeVeldspar, type2=const.typeTritanium)) 126 ButtonIcon(name='importMenu', menuAlign=uiconst.TOPLEFT, parent=self.mainCont, align=uiconst.TOPLEFT, pos=(0, 0, 32, 32), func=self.ImportShoppingList, texturePath='res:/UI/Texture/Shared/pasteFrom.png', iconSize=28, hint=hint) 127 128 def ImportShoppingList(self, *args): 129 localizedDecimal = eveLocalization.GetDecimalSeparator(localization.SYSTEM_LANGUAGE) 130 localizedSeparator = eveLocalization.GetThousandSeparator(localization.SYSTEM_LANGUAGE) 131 marketImporter = sm.GetService('marketutils').GetMarketTypeIDFinder() 132 multibuyImporter = ImportMultibuy(marketImporter, localizedDecimal, localizedSeparator) 133 text = GetClipboardData() 134 toAdd, failedLines = multibuyImporter.GetTypesAndQty(text) 135 self.AddToOrder(toAdd) 136 if failedLines: 137 text = '%s<br>' % GetByLabel('UI/SkillQueue/CouldNotReadLines') 138 text += '<br>'.join(failedLines) 139 prompt_player_fsd_dialog('CustomInfo', {'info': text}, modal=False) 140 141 def GetExportMenu(self, menuParent): 142 menuParent.AddIconEntry(icon=ACTION_ICON, text=GetByLabel('UI/Market/MarketQuote/CopyOrderToClipboard'), callback=self.ExportShoppingListLocalized) 143 if self.AreExtraExportOptionsAvailable(): 144 menuParent.AddIconEntry(icon=ACTION_ICON, text=GetByLabel('UI/Market/MarketQuote/CopyOrderToClipboardEnglish'), callback=self.ExportShoppingList) 145 menuParent.AddIconEntry(icon=ACTION_ICON, text=GetByLabel('UI/Market/MarketQuote/AddOrderToQuickbar'), callback=self.AddToQuickbar) 146 147 def ExportShoppingList(self, *args): 148 self._ExportShoppingList(isLocalized=False) 149 150 def ExportShoppingListLocalized(self, *args): 151 self._ExportShoppingList() 152 153 def _ExportShoppingList(self, isLocalized = True, *args): 154 listOfLines = [] 155 nameFunc = GetNameFunc(isLocalized) 156 for item in self.GetItemsIterator(): 157 line = self._GetExportLine(item.typeID, item.GetTotalQty(), item.GetPrice(), nameFunc) 158 listOfLines.append(line) 159 160 totalLine = self._GetTotalLine(isLocalized) 161 listOfLines.append(totalLine) 162 exportText = '\r\n'.join(listOfLines) 163 blue.pyos.SetClipboardData(exportText) 164 165 def _GetExportLine(self, typeID, qty, price, nameFunc): 166 decimals = 2 167 if not price: 168 itemPriceText = '-' 169 totalPriceText = '-' 170 else: 171 itemPrice = round(price, decimals) 172 itemPriceText = FmtAmt(itemPrice, showFraction=decimals) 173 totalPrice = qty * price 174 totalPrice = round(totalPrice, decimals) 175 totalPriceText = FmtAmt(totalPrice, showFraction=decimals) 176 lineParts = [CleanText(nameFunc(typeID)), 177 str(qty), 178 itemPriceText, 179 totalPriceText] 180 line = '\t'.join(lineParts) 181 return line 182 183 def _GetTotalLine(self, isLocalized = True): 184 totalSum = self.GetSum() 185 totalSumText = FmtAmt(totalSum, showFraction=2) 186 if isLocalized or not self.AreExtraExportOptionsAvailable(): 187 totalText = GetByLabel('UI/Market/MarketQuote/TotalPrice') 188 else: 189 totalText = GetByLabel('UI/Market/MarketQuote/TotalPrice', languageID='en') 190 totalLine = '\t'.join([totalText, 191 '', 192 '', 193 totalSumText]) 194 return totalLine 195 196 def AddToQuickbar(self): 197 newFolder = sm.GetService('marketutils').AddNewQuickbarFolder() 198 if newFolder: 199 for item in self.GetItemsIterator(): 200 sm.GetService('marketutils').AddTypeToQuickBar(item.typeID, newFolder.id, fromMarket=False, extraText=item.GetTotalQty()) 201 202 def LoadStationOptions(self): 203 currentSelection = self.stationCombo.GetValue() 204 stations = self.GetStations() 205 if currentSelection: 206 select = currentSelection 207 elif session.stationid: 208 select = session.stationid 209 elif stations: 210 select = stations[0][1] 211 else: 212 select = None 213 self.stationCombo.LoadOptions(stations, select) 214 self.stationCombo.Confirm() 215 216 def DrawStationWarning(self): 217 self.stationWarning = EveLabelLargeBold(parent=self.infoCont, text='', align=uiconst.CENTERBOTTOM) 218 self.stationWarning.SetRGB(*COL_RED) 219 self.stationWarning.display = False 220 221 def AddToOrder(self, wantToBuy, fitting = None): 222 if fitting: 223 self.fitting = fitting 224 self.buyAndFitBtn.display = True 225 self.btnGroup.ResetLayout() 226 wantedTypes = self.GetKeyValsForWantedTypes(wantToBuy) 227 self.AddItems(wantedTypes) 228 229 def AddPreItems(self, preItems): 230 self.AddItems(preItems) 231 232 def AddItems(self, itemsToAdd): 233 self.reloadingItemsCounter += 1 234 items = self.CheckOrderAvailability(itemsToAdd) 235 self.ClearErrorLists() 236 self.loadingWheel.Show() 237 for item in items: 238 self.AddItem(item) 239 240 self.DisplayErrorHints() 241 self.reloadingItemsCounter -= 1 242 if self.reloadingItemsCounter < 1: 243 self.loadingWheel.Hide() 244 245 def AddItem(self, itemKeyVal): 246 if not self.IsBuyable(itemKeyVal): 247 if itemKeyVal.typeID == typePlex: 248 prompt_player_fsd_dialog('CannotPutPlexInMarketMultiBuy') 249 return 250 existingEntry = self.entriesInScrollByTypeID.get(itemKeyVal.typeID, None) 251 if existingEntry and not existingEntry.destroyed: 252 existingEntry.AddQtyToEntry(itemKeyVal.qty) 253 else: 254 self.DoAddItem(itemKeyVal) 255 256 def AddItemToCollection(self, itemKeyVal, itemEntry): 257 self.entriesInScrollByTypeID[itemKeyVal.typeID] = itemEntry 258 259 def GetItemEntry(self, itemKeyVal): 260 itemEntry = BuyItemContainer(typeID=itemKeyVal.typeID, qty=int(itemKeyVal.qty), parentFunc=self.RemoveItem, editFunc=self.OnEntryEdit, stationID=self.baseStationID, orderMultiplier=self.orderMultiplier, dropParentFunc=self.DropItems) 261 return itemEntry 262 263 def BuyAndFit(self, *args): 264 self.buyAndFitClicked = True 265 return self._PerformTrade() 266 267 def Cancel(self, *args): 268 self.buyAndFitClicked = False 269 SellBuyItemsWindow.Cancel(self, *args) 270 271 def PerformTrade(self, *args): 272 self.buyAndFitClicked = False 273 return self._PerformTrade() 274 275 def _PerformTrade(self): 276 useCorp = self.TradingForCorp() 277 buyItemList, failedItems = self.GetValidatedAndFailedTypes() 278 if not len(buyItemList): 279 prompt_player_fsd_dialog('uiwarning03') 280 return 281 if not self.ContinueAfterWarning(buyItemList): 282 return 283 with ExceptionEater(): 284 self.LogBuy(buyItemList) 285 ordersCreated = sm.GetService('marketQuote').BuyMulti(self.baseStationID, buyItemList, useCorp) 286 orderIDs = {order.orderID for order in ordersCreated} 287 self.activeOrders.update(orderIDs) 288 self.CreateNewBuyOrder(failedItems) 289 self.VerifyExpiredOrders() 290 291 def GetItemsWithBadDelta(self, buyItemList): 292 highItems = [] 293 for item in buyItemList: 294 if item.delta > 1.0: 295 highItems.append((item.delta, item)) 296 297 return highItems 298 299 def GetOrderDeltaTextForWarning(self): 300 orderPercentage = self.GetOrderDelta() 301 orderText = '' 302 if orderPercentage > 1.0: 303 percText = GetByLabel('UI/Common/Percentage', percentage=FmtAmt(abs(orderPercentage * 100), showFraction=0)) 304 orderText = GetByLabel('UI/Market/MarketQuote/MultiBuyAboveAverage', percentage=percText) 305 return orderText 306 307 def GetValidatedAndFailedTypes(self): 308 allItems = self.GetItems() 309 failedItemsList = [] 310 buyItemsList = [] 311 for item in allItems: 312 if item.isUpdating: 313 return ([], []) 314 if item.newBestPrice: 315 validatedItem = self.GetValidatedItem(item) 316 if validatedItem: 317 buyItemsList.append(validatedItem) 318 continue 319 failedBuyInfo = KeyVal(typeID=item.typeID, qty=item.GetTotalQty()) 320 failedItemsList.append(failedBuyInfo) 321 322 return (buyItemsList, failedItemsList) 323 324 def GetValidatedItem(self, item): 325 if item.isUpdating: 326 return 327 price = item.GetPrice() 328 if not price: 329 return 330 if price > MAX_ORDER_PRICE: 331 return 332 price = round(price, 2) 333 qty = item.GetTotalQty() 334 if qty < 1: 335 return 336 validatedItem = GetBuyItemInfo(stationID=item.stationID, typeID=item.typeID, price=price, quantity=qty, minVolume=1, delta=item.GetDelta()) 337 return validatedItem 338 339 def CreateNewBuyOrder(self, failedItems): 340 self.ChangeOrderUIState(disable=True) 341 self.RemoveAllItem() 342 if self.orderMultiplierEdit.GetValue() != 1: 343 self.BlinkNumOrdersEdit() 344 self.orderMultiplierEdit.SetValue(1) 345 if failedItems: 346 self.AddItems(failedItems) 347 348 def ChangeOrderUIState(self, disable): 349 if disable: 350 opacity = 0.5 351 else: 352 opacity = 1.0 353 mainArea = self.GetMainArea() 354 mainArea.opacity = opacity 355 self.orderDisabled = disable 356 357 def GetStations(self): 358 marketDockableLocationsInRegion = sm.GetService('structureDirectory').GetMarketDockableLocationsInRegion() 359 solarsystemItems = sm.GetService('map').GetSolarsystemItems(session.solarsystemid2, True, False) 360 marketDockableLocations = {i for i in solarsystemItems if i.itemID in marketDockableLocationsInRegion} 361 currentStation = session.stationid or session.structureid 362 stationList = [] 363 for eachStation in marketDockableLocations: 364 if eachStation.itemID == currentStation: 365 continue 366 sortValue = (eachStation.celestialIndex, eachStation.orbitIndex, eachStation.itemName) 367 stationList.append((sortValue, (eachStation.itemName, eachStation.itemID))) 368 369 stationList = SortListOfTuples(stationList) 370 if currentStation: 371 stationName = cfg.evelocations.Get(currentStation).name 372 currentStationOption = (GetByLabel('UI/Market/MarketQuote/CurrentStation', stationName=stationName), currentStation) 373 stationList = [currentStationOption] + stationList 374 return stationList 375 376 def RemoveItemFromCollection(self, itemEntry): 377 self.entriesInScrollByTypeID.pop(itemEntry.typeID, None) 378 379 def OnMultiplierEditChange(self, *args): 380 self.UpdateOrderMultiplierInEntries() 381 if self.verifyMultiplierTimer: 382 self.verifyMultiplierTimer.KillTimer() 383 self.verifyMultiplierTimer = AutoTimer(2000, self.VerifyOrderMultiplier_thread) 384 385 def UpdateOrderMultiplierInEntries(self, force = True): 386 self.orderMultiplier = self.orderMultiplierEdit.GetValue() 387 for item in self.GetItemsIterator(): 388 if force or item.orderMultiplier != self.orderMultiplier: 389 item.UpdateOrderMultiplier(self.orderMultiplier) 390 391 def VerifyOrderMultiplier_thread(self): 392 self.verifyMultiplierTimer = None 393 self.UpdateOrderMultiplierInEntries(force=False) 394 395 def OnEntryEdit(self, *args): 396 uthread.new(self.UpdateNumbers) 397 398 def UpdateNumbers(self): 399 totalShown = self.GetSum() 400 if totalShown >= MILLION: 401 totalAmtText = '%s (%s)' % (FmtISK(totalShown), FmtISKWithDescription(totalShown, justDesc=True)) 402 else: 403 totalAmtText = FmtISK(totalShown) 404 self.moreInfoIcon.display = bool(totalShown) 405 self.totalAmt.text = totalAmtText 406 self.totalAmt.SetRGB(*COL_RED) 407 self.ShowOrHideStationWarning() 408 409 def ShowOrHideStationWarning(self): 410 currentStation = session.stationid or session.structureid 411 if self.baseStationID is None: 412 self.stationWarning.text = GetByLabel('UI/Market/MarketQuote/NoStationSelected') 413 self.stationWarning.display = True 414 elif self.baseStationID == currentStation: 415 self.stationWarning.display = False 416 else: 417 self.stationWarning.text = GetByLabel('UI/Market/MarketQuote/StationWarning') 418 self.stationWarning.display = True 419 420 def GetSum(self): 421 totalSum = 0 422 for item in self.GetItemsIterator(): 423 totalSum += item.GetTotalSum() 424 425 return totalSum 426 427 def LoadTotalTooltip(self, tooltipPanel, *args): 428 totalShown = self.GetSum() 429 if not totalShown or not self.orderMultiplier: 430 return 431 numTypes, numAvailableTypes, volume = self.GetNumTypesAndNumAvailableTypesAndVolume() 432 pricePerOrder = totalShown / float(self.orderMultiplier) 433 tooltipPanel.LoadGeneric2ColumnTemplate() 434 tooltipPanel.cellPadding = (4, 1, 4, 1) 435 tooltipPanel.AddLabelMedium(text=GetByLabel('UI/Market/MarketQuote/NumOrders')) 436 tooltipPanel.AddLabelMedium(text=FmtAmt(self.orderMultiplier), align=uiconst.CENTERRIGHT) 437 tooltipPanel.AddLabelMedium(text=GetByLabel('UI/Market/MarketQuote/PricePerOrder')) 438 tooltipPanel.AddLabelMedium(text=FmtISK(pricePerOrder), align=uiconst.CENTERRIGHT) 439 if pricePerOrder >= MILLION: 440 tooltipPanel.AddCell() 441 tooltipPanel.AddLabelMedium(text='=%s' % FmtISKWithDescription(pricePerOrder, justDesc=True), align=uiconst.CENTERRIGHT) 442 buyingText = GetByLabel('UI/Market/MarketQuote/TypesAvailableAndTotalInOrder', numAvailable=numAvailableTypes, numTypes=numTypes) 443 buyingLabel = tooltipPanel.AddLabelSmall(text=buyingText, align=uiconst.CENTERRIGHT, colSpan=tooltipPanel.columns) 444 buyingLabel.SetAlpha(0.6) 445 tooltipPanel.AddSpacer(1, 8, colSpan=tooltipPanel.columns) 446 deltaText = self.GetOrderDeltaText() 447 if deltaText: 448 tooltipPanel.AddLabelMedium(text=deltaText, colSpan=tooltipPanel.columns) 449 if volume: 450 tooltipPanel.AddSpacer(1, 8, colSpan=tooltipPanel.columns) 451 tooltipPanel.AddLabelMedium(text=GetByLabel('UI/Common/Volume')) 452 tooltipPanel.AddLabelMedium(text=GetByLabel('UI/Inventory/ContainerCapacity', capacity=volume), align=uiconst.CENTERRIGHT) 453 454 def GetOrderDelta(self): 455 totalPrice = sum((i.GetTotalSum() for i in self.GetItemsIterator(onlyValid=True))) 456 change = 0 457 for item in self.GetItemsIterator(onlyValid=True): 458 price = item.GetTotalSum() 459 qty = item.GetTotalQty() 460 avgPriceForQty = qty * item.averagePrice 461 change += (price - avgPriceForQty) / avgPriceForQty * price / totalPrice 462 463 return change 464 465 def GetOrderDeltaText(self): 466 percentage = self.GetOrderDelta() 467 if percentage == 0: 468 return '' 469 if percentage < 0: 470 percColor = self.belowColor 471 devLabelPath = 'UI/Market/MarketQuote/BelowRegionalAverageWithPercentage' 472 else: 473 percColor = self.aboveColor 474 devLabelPath = 'UI/Market/MarketQuote/AboveRegionalAverageWithPercentage' 475 percentage = abs(percentage) 476 percentageText = FmtAmt(percentage * 100, showFraction=1) 477 percText = '%s%s</color>' % (percColor, GetByLabel('UI/Common/Percentage', percentage=percentageText)) 478 return GetByLabel(devLabelPath, percentage=percText) 479 480 def GetNumTypesAndNumAvailableTypesAndVolume(self): 481 numTypes = 0 482 numAvailableTypes = 0 483 totalVolume = 0 484 for item in self.GetItemsIterator(): 485 numTypes += 1 486 if item.GetPrice(): 487 numAvailableTypes += 1 488 vol = item.GetTotalQty() * GetPackagedVolume(item.typeID) 489 totalVolume += vol 490 491 return (numTypes, numAvailableTypes, totalVolume) 492 493 def DropItems(self, dragObj, nodes): 494 if dragObj is None: 495 return 496 itemsToAdd = [] 497 for node in nodes: 498 typeID = GetTypeIDFromDragItem(node) 499 if typeID: 500 itemsToAdd.append(KeyVal(typeID=typeID, qty=1)) 501 502 self.AddItems(itemsToAdd) 503 504 def GetTypeIDFromDragItem(self, node): 505 return GetTypeIDFromDragItem(node) 506 507 def OnStationChanged(self, combo, key, value): 508 self.baseStationID = value 509 self.UpdateStationID() 510 511 def UpdateStationID(self): 512 for item in self.GetItemsIterator(): 513 item.UpdateStationID(self.baseStationID) 514 515 self.UpdateHeaderCount() 516 self.UpdateNumbers() 517 518 def OnOwnOrdersChanged(self, orders, reason, isCorp): 519 if reason != 'Expiry': 520 return 521 orderIDs = set() 522 for eachOrder in orders: 523 self.expiredOrders[eachOrder.orderID] = eachOrder 524 orderIDs.add(eachOrder.orderID) 525 526 self._ProccessExpiredOrders(orderIDs) 527 528 def _ProccessExpiredOrders(self, orderIDs): 529 failedItems = [] 530 for eachOrderID in orderIDs: 531 if eachOrderID not in self.activeOrders: 532 continue 533 eachOrder = self.expiredOrders.get(eachOrderID, None) 534 if eachOrder and eachOrder.volRemaining != 0: 535 failedBuyInfo = KeyVal(typeID=eachOrder.typeID, qty=eachOrder.volRemaining) 536 failedItems.append(failedBuyInfo) 537 self.activeOrders.discard(eachOrderID) 538 self.TryApplyFittingToBuffer() 539 540 if failedItems: 541 self.AddItems(failedItems) 542 if not failedItems and not self.AreStillItemsInWindow(): 543 self.CloseWnd() 544 return 545 if self.orderDisabled and not self.activeOrders: 546 self.ChangeOrderUIState(disable=False) 547 548 def CloseWnd(self): 549 if self.buyAndFitClicked and self.fitting: 550 uthread.new(self.TryApplyFittingOnClosing) 551 self.Close() 552 553 def VerifyExpiredOrders(self): 554 expiredOrders = set(self.expiredOrders.keys()) 555 expiredOrdersNotProcessed = self.activeOrders.intersection(expiredOrders) 556 if expiredOrdersNotProcessed: 557 self._ProccessExpiredOrders(expiredOrdersNotProcessed) 558 559 def AreStillItemsInWindow(self): 560 if self.activeOrders: 561 return True 562 if self.reloadingItemsCounter > 0: 563 return True 564 if self.itemList: 565 return True 566 return False 567 568 def RemoveAllItem(self): 569 self.itemsScroll.Flush() 570 self.itemList = [] 571 self.entriesInScrollByTypeID = {} 572 self.UpdateNumbers() 573 self.UpdateHeaderCount() 574 self.ClearErrorLists() 575 576 def OnSessionChanged(self, isRemote, session, change): 577 if 'solarsystemid2' in change or 'stationid' in change or 'structureid' in change: 578 self.LoadStationOptions() 579 580 def IsBuyable(self, itemKeyVal): 581 buyable = True 582 if evetypes.GetMarketGroupID(itemKeyVal.typeID) is None: 583 self.cannotTradeItemList.append(itemKeyVal) 584 buyable = False 585 if itemKeyVal.typeID == typePlex: 586 buyable = False 587 return buyable 588 589 def BlinkNumOrdersEdit(self): 590 self.ConstructBlinkBG() 591 uicore.animations.FadeTo(self.blinkEditBG, 0.0, 0.5, duration=0.5, curveType=uiconst.ANIM_WAVE, loops=2) 592 593 def ConstructBlinkBG(self): 594 if self.blinkEditBG is None: 595 self.blinkEditBG = Sprite(name='blinkEditBG', bgParent=self.orderMultiplierEdit, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath='res:/UI/Texture/classes/InvItem/bgSelected.png', opacity=0.0, idx=0) 596 597 def LogBuy(self, buyItemList): 598 totalDisplayed = self.totalAmt.text 599 totalSum = self.GetSum() 600 multiplier = self.orderMultiplierEdit.GetValue() 601 buyTextList = [] 602 for eachItem in buyItemList: 603 text = '[typeID=%s, price=%s, qty=%s]' % (eachItem.typeID, eachItem.price, eachItem.quantity) 604 buyTextList.append(text) 605 606 buyText = ','.join(buyTextList) 607 logInfo = 'Multibuy: totalDisplayed=%s, totalSum=%s, multiplier=%s, buyText=%s' % (totalDisplayed, 608 totalSum, 609 multiplier, 610 buyText) 611 log.LogNotice(logInfo) 612 613 def Close(self, *args, **kwds): 614 self.verifyMultiplierTimer = None 615 return SellBuyItemsWindow.Close(self, *args, **kwds) 616 617 def DisplayErrorHints(self): 618 hintTextList = self.GetErrorHints() 619 if hintTextList: 620 hintText = '<br>'.join(hintTextList) 621 prompt_player_fsd_dialog('CustomInfo', {'info': hintText}) 622 623 def AddLoadingWheel(self): 624 self.loadingWheel = LoadingWheel(parent=self.scrollCont, align=uiconst.CENTER, state=uiconst.UI_DISABLED) 625 self.loadingWheel.Hide() 626 627 def TryApplyFittingToBuffer(self): 628 if not self.buyAndFitClicked or not self.fitting: 629 return 630 if self.fittingPending: 631 return 632 self.fittingPending = True 633 sm.GetService('loading').ProgressWnd(GetByLabel('UI/Market/MarketQuote/AttemptingToFitShip'), '', 1, 2) 634 self._TryApplyFittingBuffered() 635 636 @BufferedCall(2000) 637 def _TryApplyFittingBuffered(self): 638 self.TryApplyFitting() 639 640 def TryApplyFittingOnClosing(self): 641 blue.pyos.synchro.SleepWallclock(500) 642 if self.fittingPending: 643 return 644 self.TryApplyFitting() 645 646 def TryApplyFitting(self): 647 sm.GetService('loading').ProgressWnd(GetByLabel('UI/Market/MarketQuote/AttemptingToFitShip'), '', 1, 2) 648 with locks.TempLock('FitShipFromBuyAll'): 649 self.fittingPending = False 650 self._TryApplyFitting() 651 652 def _TryApplyFitting(self): 653 failedToLoad = sm.GetService('fittingSvc').LoadFitting(self.fitting, getFailedDict=True) 654 failedToLoadCounter = Counter({x[0]:x[1] for x in failedToLoad}) 655 if failedToLoadCounter: 656 prompt_player_fsd_dialog('CustomNotify', {'notify': GetByLabel('UI/Market/MarketQuote/SomeItemsCouldNotBeFitted')}) 657 else: 658 sm.GetService('ghostFittingSvc').TryExitSimulation() 659 sm.GetService('loading').ProgressWnd(GetByLabel('UI/Market/MarketQuote/AttemptingToFitShip'), '', 2, 2)