sellMulti.py (28772B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\market\sellMulti.py 2 import blue 3 import eveLocalization 4 import localization 5 import uthread 6 import uthread2 7 from carbon.common.script.util.format import FmtAmt 8 from carbon.common.script.util.mathCommon import FloatCloseEnough 9 from carbonui import const as uiconst 10 from carbonui.control.combo import Combo 11 from carbonui.primitives.container import Container 12 from carbonui.primitives.layoutGrid import LayoutGrid 13 from carbonui.uicore import uicore 14 from carbonui.util.various_unsorted import GetClipboardData 15 from eve.client.script.ui import eveColor 16 from eve.client.script.ui.control.eveLabel import EveLabelSmall, EveLabelMedium, EveLabelMediumBold, EveLabelLargeBold 17 from eve.client.script.ui.control.eveLoadingWheel import LoadingWheel 18 from eve.client.script.ui.services.menuSvcExtras.invItemFunctions import CheckRepackageItems 19 from eve.client.script.ui.shared.market import INVENTORY_GUIDS 20 from eve.client.script.ui.shared.market.buySellMultiBase import SellBuyItemsWindow, COL_RED, COL_GREEN, COL_WHITE 21 from eve.client.script.ui.shared.market.sellItemEntry import SellItemContainer 22 from eve.client.script.ui.tooltips.tooltipUtil import SetTooltipHeaderAndDescription 23 from eve.client.script.ui.util.qtyTooltipUtil import AssignQtyTooltipFunc 24 from eve.common.script.sys.idCheckers import IsStation 25 from eve.common.script.util.eveFormat import FmtISK 26 from eveexceptions import UserError 27 from inventorycommon import const as invconst 28 from inventorycommon.const import flagCorpSAGs, flagHangar, typePlex 29 from localization import GetByLabel 30 from marketutil.const import MAX_ORDER_PRICE 31 from menucheckers import ItemChecker 32 from menucheckers.sessionChecker import SessionChecker 33 from player_messaging.client.ui_message import message_player, prompt_player_fsd_dialog 34 from plex.common.const import InvoiceType 35 from qtyTooltip.qtyConst import EDIT_INPUT_TYPE_FLOAT 36 from textImporting import GetNameFunc, CleanText 37 from textImporting.importMultiSell import ImportMultiSell 38 from utillib import KeyVal 39 from vgs.common.listeners import PlexWithdrawalListener 40 from eveuniverse.security import get_solar_system_security_class, securityClassSafeSec 41 from security.common.const import MARKET_SECURITY_TAX_RATE 42 ACTION_ICON = 'res:/UI/Texture/classes/UtilMenu/BulletIcon.png' 43 44 class SellItems(SellBuyItemsWindow): 45 default_windowID = 'SellItemsWindow' 46 default_name = 'SellItems' 47 default_iconNum = 'res:/ui/Texture/WindowIcons/market.png' 48 captionTextPath = 'UI/Inventory/ItemActions/MultiSell' 49 scrollId = 'MultiSellScroll' 50 durationSettingConfig = 'multiSellDuration' 51 tradeForCorpSettingConfig = 'sellUseCorp' 52 tradeTextPath = 'UI/Market/MarketQuote/CommandSell' 53 orderCap = 'MultiSellOrderCap' 54 badDeltaWarningPath = 'UI/Market/MarketQuote/MultiSellTypesBelowAverage' 55 salesButtonCantAffordBrokersFeeTooltipHeaderLabelPath = 'UI/Market/MarketQuote/SalesButtonCantAffordBrokersFeeTooltipHeader' 56 salesButtonCantAffordBrokersFeeDescriptionLabelPath = 'UI/Market/MarketQuote/SalesButtonCantAffordBrokersFeeTooltipDescription' 57 importHintLabelPath = 'UI/Market/MarketQuote/ImportPrices' 58 exportHintLabelPath = 'UI/Market/MarketQuote/ExportItems' 59 60 def __init__(self, **kwargs): 61 self.orderCountLabel = None 62 self.maxCount = None 63 self.myOrderCount = None 64 self.itemDict = {} 65 self.sellItemList = None 66 self.itemAlreadyInList = None 67 self.baseStationID = None 68 self.durationCombo = None 69 self.errorItemList = None 70 self.itemsNeedRepackaging = [] 71 super(SellItems, self).__init__(**kwargs) 72 73 def ApplyAttributes(self, attributes): 74 super(SellItems, self).ApplyAttributes(attributes) 75 top = 62 if self.useCorp else 44 76 self.orderCountLabel = EveLabelSmall(parent=self.bottomLeft, top=top, left=2) 77 self.maxCount = self.GetMaxOrderCount() 78 self.myOrderCount = self.GetCurrentOrderCount() 79 self.UpdateOrderCount() 80 self.DrawDurationCombo() 81 self.StartAddItemsThread() 82 83 def InitializeVariables(self, attributes): 84 SellBuyItemsWindow.InitializeVariables(self, attributes) 85 self.itemDict = {} 86 self.sellItemList = [] 87 self.itemAlreadyInList = [] 88 self.itemsNeedRepackaging = [] 89 90 def DrawNumbers(self): 91 self.numbersGrid = LayoutGrid(parent=self.bottomRight, columns=2, align=uiconst.TORIGHT, top=self.numbersGridTop, state=uiconst.UI_PICKCHILDREN) 92 self.sccRow = self.numbersGrid.AddRow(name='sccRow') 93 self.sccSurchargeLabel = EveLabelMedium(parent=self.sccRow, text='', padRight=4, state=uiconst.UI_NORMAL) 94 self.sccSurchargeAmtLabel = EveLabelMediumBold(parent=self.sccRow, text='', align=uiconst.CENTERRIGHT, padLeft=4, state=uiconst.UI_NORMAL) 95 self.brokersFee = EveLabelMedium(text='', padRight=4, state=uiconst.UI_NORMAL) 96 self.numbersGrid.AddCell(self.brokersFee) 97 self.brokersFeeAmt = EveLabelMediumBold(text='', align=uiconst.CENTERRIGHT, padLeft=4, state=uiconst.UI_NORMAL) 98 self.numbersGrid.AddCell(self.brokersFeeAmt) 99 self.salesTax = EveLabelMedium(text='', padRight=4, state=uiconst.UI_NORMAL) 100 self.numbersGrid.AddCell(self.salesTax) 101 self.salesTaxAmt = EveLabelMediumBold(text='', align=uiconst.CENTERRIGHT, padLeft=4, state=uiconst.UI_NORMAL) 102 self.numbersGrid.AddCell(self.salesTaxAmt) 103 self.securityTax = EveLabelMedium(text='', padRight=4, state=uiconst.UI_NORMAL) 104 self.numbersGrid.AddCell(self.securityTax) 105 self.securityTaxAmt = EveLabelMediumBold(text='', align=uiconst.CENTERRIGHT, padLeft=4, state=uiconst.UI_NORMAL) 106 self.numbersGrid.AddCell(self.securityTaxAmt) 107 self.SetupSalesTaxTooltips() 108 self.SetupBrokersFeeTooltips() 109 spacer = Container(align=uiconst.TOTOP, height=12) 110 self.numbersGrid.AddCell(spacer, colSpan=2) 111 self.totalAmt = EveLabelLargeBold(text='', align=uiconst.CENTERRIGHT, padLeft=4, state=uiconst.UI_NORMAL) 112 self.numbersGrid.AddCell(self.totalAmt, colSpan=2) 113 114 def AddPreItems(self, preItems): 115 itemLocations = set([]) 116 preItems = self.CheckOrderAvailability(preItems) 117 for item in preItems: 118 itemStationID = sm.GetService('invCache').GetStationIDOfItem(item) 119 itemLocations.add(itemStationID) 120 121 if len(itemLocations) > 1: 122 prompt_player_fsd_dialog('CustomNotify', {'notify': GetByLabel('UI/Market/MarketQuote/AddingFromDifferentLocations')}) 123 return 124 for item in preItems: 125 if self.CheckItemLocation(item): 126 self.AddItem(item) 127 128 def CheckItemLocation(self, item): 129 if not self.CheckStation(item) and len(self.itemList) > 0: 130 prompt_player_fsd_dialog('CustomNotify', {'notify': GetByLabel('UI/Market/MarketQuote/LocationNotShared')}) 131 return False 132 if item.flagID not in flagCorpSAGs + (flagHangar,): 133 prompt_player_fsd_dialog('CustomNotify', {'notify': GetByLabel('UI/Market/MarketQuote/NotValidLocation')}) 134 return False 135 return True 136 137 def GetErrorHints(self): 138 hintTextList = SellBuyItemsWindow.GetErrorHints(self) 139 alreadyInList = self.BuildHintTextList(self.itemAlreadyInList, 'UI/Market/MarketQuote/AlreadyInList') 140 if hintTextList and alreadyInList: 141 hintTextList.append('') 142 hintTextList += alreadyInList 143 needsRepackaging = self.BuildHintTextList(self.itemsNeedRepackaging, 'UI/Market/MarketQuote/NeedsRepackaging') 144 if hintTextList and needsRepackaging: 145 hintTextList.append('') 146 hintTextList += needsRepackaging 147 return hintTextList 148 149 def AddItems(self, items): 150 self.ClearErrorLists() 151 items = self.CheckOrderAvailability(items) 152 sellItems = [] 153 OkWithDumpingStuff = None 154 for item in items: 155 if item.singleton and cfg.IsContainer(item): 156 try: 157 itemsInside = {i for i in sm.GetService('invCache').GetInventoryFromId(item.itemID).List() if i.flagID != invconst.flagHiddenModifers} 158 except UserError: 159 continue 160 161 if itemsInside: 162 if item.categoryID == invconst.categoryShip: 163 rigs = {i for i in itemsInside if const.flagRigSlot0 <= i.flagID <= const.flagRigSlot7} 164 if rigs: 165 self.itemsNeedRepackaging.append(item) 166 continue 167 if OkWithDumpingStuff is None: 168 if prompt_player_fsd_dialog('RepackageContainers', {}, uiconst.YESNO) != uiconst.ID_YES: 169 OkWithDumpingStuff = False 170 continue 171 OkWithDumpingStuff = True 172 if OkWithDumpingStuff is False: 173 continue 174 sellItems.append(item) 175 176 sellItems = CheckRepackageItems(sellItems, OkWithDumpingStuff is None) 177 for item in sellItems: 178 self.AddItem(item) 179 180 self.DisplayErrorHints() 181 182 def AddItem(self, item): 183 plex_being_added = item.typeID == typePlex 184 order_empty = len(self.itemList) == 0 185 order_already_contains_plex = any((x.typeID == typePlex for x in self.itemList)) 186 if plex_being_added and order_already_contains_plex: 187 prompt_player_fsd_dialog('StackPlexBeforeSelling') 188 return 189 if plex_being_added and not order_empty or order_already_contains_plex: 190 prompt_player_fsd_dialog('CannotPutPlexInMarketMultiSell') 191 return 192 if not self.IsSellable(item): 193 return 194 self.itemDict[item.itemID] = item 195 itemEntry = self.DoAddItem(item) 196 if len(self.itemList) == 1: 197 self.UpdateStationInfo(itemEntry.stationID) 198 self.CheckItemSize() 199 uicore.registry.SetFocus(itemEntry.priceEdit) 200 201 def GetItemEntry(self, item): 202 solarSystemID = self._GetSolarSystemIDForItem(item) 203 marketQuote = sm.GetService('marketQuote') 204 bestPrice = marketQuote.GetBestPrice(item.typeID, item, item.stacksize, solarSystemID) 205 bestBid = marketQuote.GetBestBidWithStationID(item, locationID=solarSystemID) 206 stationID = sm.GetService('invCache').GetStationIDOfItem(item) 207 itemEntry = SellItemContainer(item=item, editFunc=self.OnEntryEdit, align=uiconst.TOTOP, parentFunc=self.RemoveItem, bestPrice=bestPrice, bestBid=bestBid, stationID=stationID, solarSystemID=solarSystemID, isReadOnly=self.isReadOnly) 208 return itemEntry 209 210 @staticmethod 211 def _GetSolarSystemIDForItem(item): 212 if IsStation(item.locationID): 213 station = sm.StartService('ui').GetStationStaticInfo(item.locationID) 214 return station.solarSystemID 215 structureInfo = sm.GetService('structureDirectory').GetStructureInfo(item.locationID) 216 if structureInfo and structureInfo.solarSystemID: 217 return structureInfo.solarSystemID 218 return session.solarsystemid2 219 220 def AddItemToCollection(self, item, itemEntry): 221 self.itemDict[item.itemID] = item 222 223 def CheckItemSize(self): 224 if not len(self.itemList): 225 return 226 firstItem = self.itemList[0] 227 if len(self.itemList) == 1: 228 firstItem.MakeSingle() 229 elif len(self.itemList) == 2: 230 firstItem.RemoveSingle() 231 232 def UpdateStationInfo(self, stationID): 233 self.baseStationID = stationID 234 if self.baseStationID: 235 self.UpdateHeaderCount() 236 else: 237 self.SetCaption(GetByLabel(self.captionTextPath)) 238 if not self.baseStationID or IsStation(self.baseStationID): 239 self.sccRow.Hide() 240 else: 241 self.sccRow.Show() 242 243 def RemoveItem(self, itemEntry): 244 SellBuyItemsWindow.RemoveItem(self, itemEntry) 245 self.CheckItemSize() 246 if len(self.itemList) == 0: 247 self.baseStationID = None 248 self.UpdateStationInfo(None) 249 250 def RemoveItemFromCollection(self, itemEntry): 251 self.itemDict.pop(itemEntry.itemID) 252 253 def CheckStation(self, item): 254 itemStationID = sm.GetService('invCache').GetStationIDOfItem(item) 255 if itemStationID != self.baseStationID: 256 return False 257 return True 258 259 def ClearErrorLists(self): 260 SellBuyItemsWindow.ClearErrorLists(self) 261 self.itemsNeedRepackaging = [] 262 self.itemAlreadyInList = [] 263 264 def IsSellable(self, item): 265 if item.itemID in self.itemDict: 266 self.itemAlreadyInList.append(item) 267 return False 268 sessionChecker = SessionChecker(session, sm) 269 itemChecker = ItemChecker(item, sessionChecker) 270 if not itemChecker.OfferSellThisItem(): 271 self.cannotTradeItemList.append(item) 272 return False 273 return True 274 275 def OnEntryEdit(self, *args): 276 uthread.new(self.UpdateNumbers) 277 278 def DropItems(self, dragObj, nodes): 279 if not self.IsAllowedDragData(nodes): 280 return 281 if not self.CheckItemLocation(self.GetDragNodeItem(nodes[0])): 282 return 283 self.AddItems([ self.GetDragNodeItem(n) for n in nodes ]) 284 285 @staticmethod 286 def GetDragNodeItem(node): 287 if hasattr(node, 'WithdrawPlex') and callable(node.WithdrawPlex): 288 item = node.item 289 item.locationID = session.stationid or session.structureid 290 item.flagID = invconst.flagHangar 291 return item 292 else: 293 return node.item 294 295 def DrawDurationCombo(self): 296 if self.isReadOnly: 297 durations = [[GetByLabel('UI/Market/MarketQuote/Immediate'), 0]] 298 else: 299 durations = [[GetByLabel('UI/Market/MarketQuote/Immediate'), 0], 300 [GetByLabel('UI/Common/DateWords/Day'), 1], 301 [GetByLabel('UI/Market/MarketQuote/ThreeDays'), 3], 302 [GetByLabel('UI/Common/DateWords/Week'), 7], 303 [GetByLabel('UI/Market/MarketQuote/TwoWeeks'), 14], 304 [GetByLabel('UI/Common/DateWords/Month'), 30], 305 [GetByLabel('UI/Market/MarketQuote/ThreeMonths'), 90]] 306 durationValue = settings.user.ui.Get(self.durationSettingConfig, 0) 307 self.durationCombo = Combo(parent=self.bottomLeft, options=durations, select=durationValue, top=6, callback=self.OnDurationChange, maxVisibleEntries=len(durations)) 308 309 def UpdateNumbers(self): 310 brokersFee, sccSurchargeFee, salesTax, totalSum = self.GetSums() 311 totalShown = totalSum - salesTax - brokersFee - sccSurchargeFee 312 if totalSum > 0: 313 brokersPerc = round(brokersFee / totalSum * 100, 2) 314 sccSurcharge = round(sccSurchargeFee / totalSum * 100, 2) 315 salesPerc = round(salesTax / totalSum * 100, 2) 316 else: 317 brokersPerc = 0.0 318 sccSurcharge = 0.0 319 salesPerc = 0.0 320 useCorp = self.TradingForCorp() 321 walletAmount = sm.GetService('wallet').GetWealth() 322 if useCorp: 323 walletAmount = sm.GetService('wallet').GetCorpWealth(None) 324 self.brokersFeeAmt.text = FmtISK(-brokersFee) 325 self._ConfigureFeeLabelBasedOnFee(walletAmount, brokersFee, self.brokersFee, self.brokersFeeAmt) 326 self.brokersFee.text = GetByLabel('UI/Market/MarketQuote/BrokersFeePerc', percentage=brokersPerc) 327 self.sccSurchargeAmtLabel.text = FmtISK(-sccSurchargeFee) 328 self._ConfigureFeeLabelBasedOnFee(walletAmount, sccSurchargeFee, self.sccSurchargeLabel, self.sccSurchargeAmtLabel) 329 self.sccSurchargeLabel.text = GetByLabel('UI/Market/MarketQuote/SccSurchargeFeePerc', percentage=sccSurcharge) 330 self._ConfigureTradeButtonBasedOnFees(walletAmount, brokersFee + sccSurchargeFee) 331 if sccSurchargeFee: 332 self.sccRow.Show() 333 self.salesTaxAmt.text = FmtISK(-salesTax) 334 self.salesTax.text = GetByLabel('UI/Market/MarketQuote/SalesTaxPerc', percentage=salesPerc) 335 securityTax = 0.0 336 isImmediate = self.durationCombo.GetValue() == 0 337 if not isImmediate and totalSum > 0 and self.itemList: 338 solarSystemID = self.itemList[0].solarSystemID 339 if solarSystemID and get_solar_system_security_class(solarSystemID) == securityClassSafeSec: 340 securityTax = round(totalSum * MARKET_SECURITY_TAX_RATE, 2) 341 totalShown -= securityTax 342 if totalSum > 0: 343 securityPerc = round(securityTax / totalSum * 100, 2) 344 else: 345 securityPerc = 0.0 346 self.securityTax.text = '%s (%.2f%%)' % (GetByLabel('UI/Market/MarketQuote/MarketSecurityTax'), securityPerc) 347 self.securityTaxAmt.text = FmtISK(-securityTax) 348 self.totalAmt.text = FmtISK(totalShown) 349 AssignQtyTooltipFunc(self.totalAmt, totalShown, inputType=EDIT_INPUT_TYPE_FLOAT) 350 if totalShown < 0: 351 self.totalAmt.SetRGB(*COL_RED) 352 else: 353 self.totalAmt.SetRGB(*COL_GREEN) 354 355 def _ConfigureFeeLabelBasedOnFee(self, walletAmt, feeAmt, feeLabel, amtLabel): 356 color = COL_RED if walletAmt < feeAmt else COL_WHITE 357 feeLabel.SetRGB(*color) 358 amtLabel.SetRGB(*color) 359 360 def _ConfigureTradeButtonBasedOnFees(self, walletAmt, feeAmt): 361 if walletAmt < feeAmt: 362 cantAffordText = GetByLabel(self.salesButtonCantAffordBrokersFeeDescriptionLabelPath, walletBalance=walletAmt, brokersFee=feeAmt) 363 SetTooltipHeaderAndDescription(self.tradeButton, GetByLabel(self.salesButtonCantAffordBrokersFeeTooltipHeaderLabelPath), cantAffordText) 364 self.tradeButton.Disable() 365 else: 366 self.tradeButton.Enable() 367 self.tradeButton.tooltipPanelClassInfo = None 368 369 def GetSums(self): 370 brokersFee = 0.0 371 sccSurcharge = 0.0 372 salesTax = 0 373 totalSum = 0 374 isImmediate = self.durationCombo.GetValue() == 0 375 for item in self.GetItems(): 376 if item: 377 if not isImmediate: 378 brokersFee += item.brokersFee 379 sccSurcharge += item.sccSurcharge 380 if isImmediate and item.bestBid is None: 381 pass 382 else: 383 salesTax += item.salesTax 384 totalSum += item.totalSum 385 386 return (brokersFee, 387 sccSurcharge, 388 salesTax, 389 totalSum) 390 391 def PerformTrade(self, *args): 392 return self._PerformTrade() 393 394 def _PerformTrade(self): 395 self.sellItemList = [] 396 unitCount = self.GetUnitCount() 397 allItems = self.GetItems() 398 if unitCount == 0: 399 prompt_player_fsd_dialog('uiwarning03') 400 return 401 if prompt_player_fsd_dialog('ConfirmSellingItems', {'noOfItems': int(unitCount)}, uiconst.OKCANCEL, suppress=uiconst.ID_OK) != uiconst.ID_OK: 402 return 403 self.errorItemList = [] 404 useCorp = self.TradingForCorp() 405 duration = self.durationCombo.GetValue() 406 expectedBrokerFeePercentage = None 407 for item in allItems: 408 if duration == 0: 409 if item.bestBid: 410 validatedItem = self.GetValidatedItem(item) 411 else: 412 continue 413 else: 414 validatedItem = self.GetValidatedItem(item) 415 if validatedItem: 416 if duration != 0: 417 if expectedBrokerFeePercentage is None: 418 expectedBrokerFeePercentage = validatedItem.rawBrokerFeePercentage 419 elif not FloatCloseEnough(expectedBrokerFeePercentage, validatedItem.rawBrokerFeePercentage): 420 brokerFeeNow = sm.GetService('marketQuote').GetBrokersFeeCommissionFromStationID(validatedItem.stationID) 421 raise UserError('MktBrokersFeeUnexpected2', {'actualBrokerFeePerc': 100 * brokerFeeNow}) 422 self.sellItemList.append(validatedItem) 423 424 if not len(self.sellItemList): 425 return 426 if duration > 0: 427 brokerFeeNow = sm.GetService('marketQuote').GetBrokersFeeCommissionFromStationID(self.sellItemList[0].stationID) 428 if not FloatCloseEnough(brokerFeeNow, expectedBrokerFeePercentage): 429 raise UserError('MktBrokersFeeUnexpected2', {'actualBrokerFeePerc': 100 * brokerFeeNow, 430 'expectedBrokerFeePercentage': expectedBrokerFeePercentage}) 431 if not self.ContinueAfterWarning(self.sellItemList): 432 return 433 selling_plex = any((x.typeID == typePlex for x in self.sellItemList)) 434 single_sell = len(self.sellItemList) == 1 435 if not selling_plex: 436 wereOrdersCreated = sm.GetService('marketQuote').SellMulti(self.sellItemList, useCorp, duration, expectedBrokerFeePercentage) 437 elif single_sell: 438 wereOrdersCreated = sm.GetService('marketQuote').SellPlex(self.sellItemList[0], useCorp, duration, expectedBrokerFeePercentage) 439 else: 440 wereOrdersCreated = False 441 prompt_player_fsd_dialog('CannotPutPlexInMarketMultiSell') 442 if wereOrdersCreated: 443 self.Close() 444 445 def GetUnitCount(self): 446 unitCount = 0 447 isImmediate = self.durationCombo.GetValue() == 0 448 for item in self.itemList: 449 if isImmediate: 450 unitCount += item.estimatedSellCount 451 else: 452 unitCount += item.GetQtyToSell() 453 454 return unitCount 455 456 def GetValidatedItem(self, item): 457 invItem = item.item 458 if item.isUpdating: 459 return 460 price = round(item.GetPrice(), 2) 461 if price > MAX_ORDER_PRICE: 462 return 463 if self.durationCombo.GetValue() == 0: 464 if not item.bestBid: 465 return 466 if not item.estimatedSellCount: 467 return 468 self.CheckAndHandlePlexVaultItem(item) 469 qty = item.GetQtyToSell() 470 officeID = None 471 if invItem.locationID != item.stationID and invItem.flagID in invconst.flagCorpSAGs: 472 officeID = invItem.locationID 473 validatedItem = KeyVal(stationID=int(item.stationID), typeID=int(item.typeID), itemID=item.itemID, price=price, quantity=int(qty), officeID=officeID, delta=item.GetDelta(), rawBrokerFeePercentage=item.rawBrokerFeePercentage) 474 return validatedItem 475 476 def CheckAndHandlePlexVaultItem(self, item): 477 if item.typeID != invconst.typePlex or item.itemID is not None: 478 return 479 quantity = item.GetQtyToSell() 480 item.locationID = session.stationid or session.structureid 481 reference = sm.GetService('invCache').GetInventoryMgr().WithdrawPlexFromVault(quantity, item.locationID, InvoiceType.VaultToMarket, item.item.flagID) 482 listener = PlexWithdrawalListener(session.userid, quantity, reference) 483 loading_wheel = LoadingWheel(parent=self.mainCont, align=uiconst.CENTER) 484 loading_wheel.Show() 485 while not listener.received_event: 486 uthread2.Sleep(1) 487 488 loading_wheel.Hide() 489 if listener.received_item_id: 490 item.itemID = listener.received_item_id 491 492 def IsAllowedDragData(self, dragData): 493 for entry in dragData: 494 guid = getattr(entry, '__guid__', None) 495 if guid is not None and guid not in INVENTORY_GUIDS: 496 return False 497 498 return True 499 500 def OnDurationChange(self, *args): 501 newDuration = self.durationCombo.GetValue() 502 settings.user.ui.Set(self.durationSettingConfig, newDuration) 503 self.UpdateNumbers() 504 for item in self.GetItems(): 505 item.OnDurationChanged(newDuration) 506 507 def UpdateOrderCount(self): 508 self.orderCountLabel.text = GetByLabel('UI/Market/MarketQuote/OpenOrdersRemaining', orders=FmtAmt(self.maxCount - self.myOrderCount), maxOrders=FmtAmt(self.maxCount)) 509 510 def OnUseCorp(self, *args): 511 SellBuyItemsWindow.OnUseCorp(self, *args) 512 self.UpdateOrderCount() 513 514 def GetMaxOrderCount(self): 515 limits = self.marketQuoteSvc.GetSkillLimits(self.baseStationID) 516 maxCount = limits['cnt'] 517 return maxCount 518 519 def GetCurrentOrderCount(self): 520 myOrders = self.marketQuoteSvc.GetMyOrders() 521 return len(myOrders) 522 523 def GetItemsWithBadDelta(self, buyItemList): 524 lowItems = [] 525 for item in buyItemList: 526 if item.delta < -0.5: 527 lowItems.append((item.delta, item)) 528 529 return lowItems 530 531 def GetImportMenu(self, menuParent): 532 localizedDecimal = eveLocalization.GetDecimalSeparator(localization.SYSTEM_LANGUAGE) 533 localizedSeparator = eveLocalization.GetThousandSeparator(localization.SYSTEM_LANGUAGE) 534 for decimalType, decimal, separator in (('UI/Market/MarketQuote/DecimalPoint', '.', ','), ('UI/Market/MarketQuote/DecimalComma', ',', '.')): 535 if localizedDecimal == decimal and localizedSeparator == separator: 536 extraHint = GetByLabel('UI/Market/MarketQuote/SameAsYourNumberFormat', hexColor=eveColor.LEAFY_GREEN_HEX) 537 else: 538 extraHint = GetByLabel('UI/Market/MarketQuote/NotSameAsYourNumberFormat', hexColor=eveColor.WARNING_ORANGE_HEX) 539 colorText = '<color=%s>' % eveColor.CRYO_BLUE_HEX 540 veldsparPrice = '2<b>%s%s</color></b>01' % (colorText, decimal) 541 priceRifter = '400<b>%s%s</color></b>000<b>%s%s</color></b>01' % (colorText, 542 separator, 543 colorText, 544 decimal) 545 hint = GetByLabel('UI/Market/MarketQuote/ImportItemPriceListOptionHint', type1=const.typeVeldspar, type2=587, priceType1=veldsparPrice, priceType2=priceRifter) 546 hint += '<br><br>%s' % extraHint 547 text = '%s (%s) ' % (GetByLabel('UI/Market/MarketQuote/ImportPricesFromClipboard'), GetByLabel(decimalType)) 548 menuParent.AddIconEntry(icon=ACTION_ICON, text=text, hint=hint, callback=lambda d = decimal, s = separator: self.ImportItemPrices(d, s)) 549 550 def GetExportMenu(self, menuParent): 551 menuParent.AddIconEntry(icon=ACTION_ICON, text=GetByLabel('UI/Market/MarketQuote/CopyItemsToClipboard'), callback=self.CopyContentToClipboardLocalized) 552 if self.AreExtraExportOptionsAvailable(): 553 menuParent.AddIconEntry(icon=ACTION_ICON, text=GetByLabel('UI/Market/MarketQuote/CopyItemsToClipboardEnglish'), callback=self.CopyContentToClipboard) 554 555 def ImportItemPrices(self, decimal, separator): 556 marketImporter = sm.GetService('marketutils').GetMarketTypeIDFinder() 557 multiSellImporter = ImportMultiSell(marketImporter, decimal, separator) 558 text = GetClipboardData() 559 newPrices, failedLines = multiSellImporter.GetTypesAndPrice(text) 560 self.UpdatePrices(newPrices) 561 if failedLines: 562 text = '%s<br>' % GetByLabel('UI/SkillQueue/CouldNotReadLines') 563 text += '<br>'.join(failedLines) 564 prompt_player_fsd_dialog('CustomInfo', {'info': text}, modal=False) 565 566 def UpdatePrices(self, newPrices): 567 itemsUpdated = 0 568 for item in self.GetItemsIterator(): 569 newTypePrice = newPrices.get(item.typeID, None) 570 if newTypePrice: 571 item.SetPrice(newTypePrice) 572 itemsUpdated += 1 573 574 if itemsUpdated > 0: 575 text = GetByLabel('UI/Market/MarketQuote/UpdatedPriceForItems', numItems=itemsUpdated) 576 else: 577 text = GetByLabel('UI/Market/MarketQuote/UpdatedNoPriceForItems') 578 message_player(text) 579 580 def CopyContentToClipboard(self, *args): 581 self._CopyContentToClipboard(isLocalized=False) 582 583 def CopyContentToClipboardLocalized(self, *args): 584 self._CopyContentToClipboard() 585 586 def _CopyContentToClipboard(self, isLocalized = True, *args): 587 listOfLines = [] 588 nameFunc = GetNameFunc(isLocalized) 589 for item in self.GetItemsIterator(): 590 line = self._GetExportLine(item.typeID, item.GetQty(), item.GetPrice(), nameFunc) 591 listOfLines.append(line) 592 593 listOfLines.reverse() 594 exportText = '\r\n'.join(listOfLines) 595 blue.pyos.SetClipboardData(exportText) 596 597 def _GetExportLine(self, typeID, qty, price, nameFunc): 598 decimals = 2 599 if not price: 600 itemPriceText = '-' 601 totalPriceText = '-' 602 else: 603 itemPriceText = unicode(round(price, decimals)) 604 totalPriceText = unicode(round(qty * price, decimals)) 605 lineParts = [unicode(typeID), 606 CleanText(nameFunc(typeID)), 607 str(qty), 608 itemPriceText, 609 totalPriceText] 610 line = '\t'.join(lineParts) 611 return line