marketbase.py (157259B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\market\marketbase.py 2 import sys 3 from collections import defaultdict 4 import eveicon 5 import blue 6 import telemetry 7 import carbonui.const as uiconst 8 import dogma.data 9 import utillib 10 from carbon.common.script.sys.serviceConst import ROLEMASK_ELEVATEDPLAYER 11 from carbon.common.script.util.commonutils import StripTags 12 from carbon.common.script.util.format import FmtAmt 13 from carbonui import AxisAlignment, ButtonVariant, Density, fontconst, TextColor 14 from carbonui.control.dragdrop.dragdata import TypeDragData 15 from carbonui.control.scroll_const import SortDirection 16 from carbonui.control.singlelineedits.singleLineEditFloat import SingleLineEditFloat 17 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger 18 from carbonui.decorative.divider_line import DividerLine 19 from carbonui.decorative.panelUnderlay import PanelUnderlay 20 from carbonui.primitives.sprite import Sprite 21 from carbonui.util.bunch import Bunch 22 from carbonui.util.various_unsorted import ConvertDecimal, GetClipboardData 23 from dogma.const import attributeDataTypeTypeMirror 24 from carbonui.button.group import ButtonGroup 25 from carbonui.control.buttonIcon import ButtonIcon 26 from carbonui.control.checkbox import Checkbox 27 from carbonui.control.radioButton import RadioButton 28 from eve.client.script.ui.comparison import comparisonUtil 29 from eve.client.script.ui.control.divider import Divider 30 from eve.client.script.ui.control.entries.generic import Generic 31 from eve.client.script.ui.control.entries.util import GetFromClass 32 from eve.client.script.ui.control.eveTabgroupUtil import FixedTabName 33 from carbonui.control.window import Window 34 from eve.client.script.ui.control.listgroup import ListGroup 35 from carbonui.control.tabGroup import TabGroup, GetTabData 36 from eve.client.script.ui.control.utilMenu import UtilMenu 37 from eve.client.script.ui.quickFilter import QuickFilterEdit 38 from eve.client.script.ui.shared.cloneGrade import ORIGIN_MARKET 39 from eve.client.script.ui.shared.cloneGrade.omegaCloneOverlayIcon import OmegaCloneOverlayIcon 40 from eve.client.script.ui.shared.market.marketOrdersUtil import DumpOrdersForType 41 from eve.client.script.ui.shared.market.util import does_global_market_apply, get_best_price_in_place_text, get_units_available_text 42 import evetypes 43 import inventorycommon.typeHelpers 44 import localization 45 import log 46 import threadutils 47 from eve.client.script.ui.shared.market.entries import GenericMarketItem, MarketMetaGroupEntry, MarketOrder, QuickbarGroup, QuickbarItem, MarketListGroup 48 from eve.client.script.ui.shared.market.qa import add_qa_menu, SETTING_SHOULD_SEE_PLEX_ORDERS_LOCATION_INFO, SETTING_SHOULD_SEE_ORDER_REGION 49 from eve.client.script.ui.shared.market.util import should_show_location_info, should_show_region 50 from eve.client.script.ui.shared.market.wallet_balance import get_wallet_balance_options_menu, WalletBalance 51 from eve.client.script.ui.util import uix, utilWindows 52 import uthread 53 import uthread2 54 from carbonui.control.scrollContainer import ScrollContainer 55 from carbonui.primitives.container import Container 56 from carbonui.primitives.containerAutoSize import ContainerAutoSize 57 from carbonui.primitives.layoutGrid import LayoutGrid 58 from eve.client.script.ui.control import eveLabel, eveScroll 59 from eve.client.script.ui.control.eveImage import Image 60 from eve.client.script.ui.control.eveLabel import EveLabelSmall 61 from eve.client.script.ui.control.infoIcon import InfoIcon 62 from eve.client.script.ui.control.listwindow import ListWindow 63 from carbonui.control.button import Button 64 from eve.client.script.ui.shared.fitting.fittingUtil import FITKEYS 65 from eve.client.script.ui.shared.market import GetTypeIDFromDragItem 66 from eve.client.script.ui.shared.market.requirements import RequirementsContainer 67 from eve.client.script.ui.shared.market.ticker import MarketTicker, ticker_enabled_setting 68 from eve.client.script.ui.shared.traits import TraitsContainer, HasTraits 69 from eve.common.lib import appConst as const 70 from eve.common.script.sys import eveCfg, idCheckers 71 from eve.common.script.util import industryCommon 72 from eve.common.script.util.eveFormat import FmtISK 73 from eveexceptions import ExceptionEater, UserError 74 import expertSystems.client 75 from eveuniverse.security import is_high_sec_or_higher, is_zero_sec 76 from fastcheckout.client.purchasepanels.purchaseButton import PurchaseButton 77 from fsdBuiltData.common.iconIDs import GetIconFile 78 from inventorycommon.const import typePlex 79 from inventoryrestrictions import can_view_market_details 80 from localization import GetByLabel 81 from marketgroups.data import MarketGroupObject 82 from marketutil import ConvertTuplesToBestByOrders 83 from marketutil.const import MAX_ORDER_PRICE 84 from marketutil.feature_flags.client import is_global_plex_market_experiment_enabled_changed, is_global_plex_market_experiment_enabled 85 from marketutil.quickbarUtil import TICKER_SETTING_NAME 86 import metaGroups 87 from omega.client.clone_grade_svc import get_clone_grade_svc 88 from player_messaging.client.ui_message import prompt_player_fsd_dialog 89 from shipfitting.multiBuyUtil import BuyMultipleTypesWithQty 90 from fastcheckout.const import FROM_MARKET_WINDOW, FROM_PLEX_MARKET_GROUP 91 from carbonui.uicore import uicore 92 from eveservices.menu import GetMenuService 93 from menu import MenuLabel 94 from eveprefs import boot 95 from textImporting import IsUsingDefaultLanguage 96 from textImporting.exportQuickbar import QuickbarExporter 97 from textImporting.importQuickbar import QuickbarImporter 98 from textImporting.textToTypeIDFinder import SEARCH_LOCALIZED, SEARCH_BOTH 99 import eve.client.script.ui.shared.pointerTool.pointerToolConst as pConst 100 ACTION_ICON = 'res:/UI/Texture/classes/UtilMenu/BulletIcon.png' 101 INFINITY = 999999999999999999L 102 MARKET_NES_BUTTON_ANALYTIC_ID = 'MarketNESButton' 103 CATEGORIES_WITH_FACTION_AND_STORYLINE_SUBFOLDERS = (const.categoryModule, 104 const.categoryStructureModule, 105 const.categoryDrone, 106 const.categoryStarbase, 107 const.categoryFighter) 108 109 def GetNumericValueFromSetting(configName, defaultValue = 0): 110 value = settings.user.ui.Get(configName, defaultValue) 111 if value == '-': 112 return defaultValue 113 return value 114 115 116 class RegionalMarket(Window): 117 __guid__ = 'form.RegionalMarket' 118 __notifyevents__ = ['OnSessionChanged'] 119 default_width = 900 120 default_height = 768 121 default_windowID = 'market' 122 default_captionLabelPath = 'Tooltips/StationServices/Market' 123 default_descriptionLabelPath = 'Tooltips/StationServices/Market_description' 124 default_iconNum = 'res:/ui/Texture/WindowIcons/market.png' 125 default_minSize = (650, 435) 126 default_apply_content_padding = False 127 128 def ApplyAttributes(self, attributes): 129 Window.ApplyAttributes(self, attributes) 130 typeID = attributes.typeID 131 marketGroupID = attributes.marketGroupID 132 WalletBalance(parent=self.header.extra_content, align=uiconst.TORIGHT) 133 self.sr.market = MarketBase(name='marketbase', parent=self.sr.main, state=uiconst.UI_PICKCHILDREN, content_padding=self.content_padding) 134 self.sr.market.Startup(marketGroupID=marketGroupID) 135 self.on_content_padding_changed.connect(self._on_content_padding_changed) 136 if typeID: 137 self.LoadTypeID_Ext(typeID) 138 sm.RegisterNotify(self) 139 140 def InitializeCaption(self, attributes): 141 self.caption = self._get_caption() 142 143 @staticmethod 144 def _get_caption(): 145 return GetByLabel('UI/Market/MarketQuote/RegionalMarket', regionName=cfg.evelocations.Get(session.regionid).name) 146 147 def OnSessionChanged(self, isRemove, session, change): 148 if self.destroyed: 149 return 150 if 'solarsystemid2' in change: 151 self.caption = self._get_caption() 152 153 def LoadTypeID_Ext(self, typeID): 154 self.sr.market.LoadTypeID_Ext(typeID) 155 self.sr.market.OpenOnTypeID(typeID) 156 self.SetOrder(0) 157 158 def LoadMarketGroup(self, marketGroupID): 159 self.sr.market.LoadMarketGroup(marketGroupID) 160 161 def OnBack(self, *args): 162 self.sr.market.GoBack() 163 164 def OnForward(self, *args): 165 self.sr.market.GoForward() 166 167 @classmethod 168 def OpenAndSearch(cls, searchString): 169 window = cls.Open() 170 market = window.sr.market 171 market.sr.searchInput.SetValue(searchString) 172 market.sr.sbTabs.SelectByIdx(0) 173 market.ReloadMarketListTab() 174 175 def GetMenuMoreOptions(self): 176 menu = super(RegionalMarket, self).GetMenuMoreOptions() 177 wallet_balance_menu = get_wallet_balance_options_menu() 178 if wallet_balance_menu: 179 menu += wallet_balance_menu 180 menu.AddCheckbox(text=localization.GetByLabel('UI/Market/ShowMarketTicker'), setting=ticker_enabled_setting, hint=localization.GetByLabel('UI/Market/TickerHint')) 181 add_qa_menu(menu) 182 return menu 183 184 def _on_content_padding_changed(self, window): 185 self.sr.market.content_padding = self.content_padding 186 187 188 class MarketBase(Container): 189 __guid__ = 'form.Market' 190 __nonpersistvars__ = [] 191 __notifyevents__ = ['OnMarketQuickbarChange', 'OnOwnOrdersChanged', 'OnSessionChanged'] 192 __update_on_reload__ = 1 193 194 def __init__(self, content_padding = (0, 195 0, 196 0, 197 0), **kwargs): 198 self._content_padding = content_padding 199 self._details_panel = None 200 self._group_panel = None 201 self._left_side = None 202 self._left_side_divider = None 203 self._left_side_fill = None 204 self._main_tab_container = None 205 self._ticker = None 206 self._typeID = None 207 super(MarketBase, self).__init__(**kwargs) 208 is_global_plex_market_experiment_enabled_changed.connect(self._OnRefreshPlexOrdersRequired) 209 SETTING_SHOULD_SEE_PLEX_ORDERS_LOCATION_INFO.on_change.connect(self._OnRefreshPlexOrdersRequired) 210 SETTING_SHOULD_SEE_ORDER_REGION.on_change.connect(self._OnShowRegionChanged) 211 212 def ApplyAttributes(self, attributes): 213 super(MarketBase, self).ApplyAttributes(attributes) 214 self.inited = 0 215 self.searchAsksForMyRange = None 216 self.pendingType = None 217 self.loadingType = 0 218 self.loadingMarketData = None 219 self.lastdetailTab = localization.GetByLabel('UI/Market/MarketData') 220 self.lastOnOrderChangeTime = None 221 self.refreshOrdersTimer = None 222 self.groupListData = None 223 self.sr.lastSearchResult = [] 224 self.sr.lastBrowseResult = [] 225 self.sr.marketgroups = None 226 self.sr.quickType = None 227 self.sr.pricehistory = None 228 self.sr.grouplist = None 229 self.sr.marketdata = None 230 self.detailsInited = 0 231 self.updatingGroupsThread = None 232 self.settingsInited = 0 233 self.OnChangeFuncs = {} 234 self.SetChangeFuncs() 235 self.lastid = 0 236 self.marketItemList = [] 237 self.name = 'MarketBase' 238 self.sr.detailTypeID = None 239 self.parentDictionary = {} 240 self.historyData = [] 241 self.historyIdx = None 242 243 @property 244 def content_padding(self): 245 return self._content_padding 246 247 @content_padding.setter 248 def content_padding(self, value): 249 if value != self._content_padding: 250 self._content_padding = value 251 self._update_content_padding() 252 253 def _update_content_padding(self): 254 self._left_side.padding = self._get_left_side_padding() 255 self._left_side_divider.padding = self._get_left_side_divider_padding() 256 self._main_tab_container.padding = self._get_main_tab_container_padding() 257 self._group_panel.padding = self._get_group_panel_padding() 258 self._details_panel.padding = self._get_details_panel_padding() 259 self._left_side_fill.padding = self._get_left_side_fill_padding() 260 261 def _get_left_side_padding(self): 262 pad_left, pad_top, _, _ = self.content_padding 263 return (pad_left, 264 pad_top, 265 0, 266 0) 267 268 def _get_left_side_divider_padding(self): 269 _, pad_top, _, _ = self.content_padding 270 return (0, 271 pad_top, 272 8, 273 0) 274 275 def _get_main_tab_container_padding(self): 276 _, pad_top, pad_right, _ = self.content_padding 277 return (0, 278 pad_top, 279 pad_right, 280 8) 281 282 def _get_group_panel_padding(self): 283 _, _, pad_right, pad_bottom = self.content_padding 284 if ticker_enabled_setting.is_enabled(): 285 pad_bottom = 0 286 return (0, 287 0, 288 pad_right, 289 pad_bottom) 290 291 def _get_details_panel_padding(self): 292 _, _, pad_right, pad_bottom = self.content_padding 293 if ticker_enabled_setting.is_enabled(): 294 pad_bottom = 0 295 return (0, 296 0, 297 pad_right, 298 pad_bottom) 299 300 def _get_left_side_fill_padding(self): 301 pad_left, pad_top, _, _ = self.content_padding 302 return (-pad_left, 303 -pad_top, 304 0, 305 0) 306 307 def _OnClose(self, *args): 308 if self.groupListData is not None: 309 settings.char.ui.Set('marketGroupID_groupList', self.groupListData.marketGroupID) 310 if self._left_side is not None: 311 settings.user.ui.Set('marketselectorwidth_%s' % self.idName, self._left_side.width) 312 settings.user.ui.Set('quickbar_lastid', self.lastid) 313 settings.user.ui.Set('quickbar', self.folders) 314 sm.UnregisterNotify(self) 315 is_global_plex_market_experiment_enabled_changed.disconnect(self._OnRefreshPlexOrdersRequired) 316 SETTING_SHOULD_SEE_PLEX_ORDERS_LOCATION_INFO.on_change.disconnect(self._OnRefreshPlexOrdersRequired) 317 SETTING_SHOULD_SEE_ORDER_REGION.on_change.disconnect(self._OnShowRegionChanged) 318 319 def Startup(self, isStationMarket = 0, marketGroupID = None): 320 self.idName = 'region' 321 if marketGroupID: 322 self.groupListData = sm.GetService('marketutils').GetMarketGroupByID(marketGroupID) 323 else: 324 marketGroupID = settings.char.ui.Get('marketGroupID_groupList', None) 325 if marketGroupID: 326 try: 327 self.groupListData = MarketGroupObject(marketGroupID) 328 except Exception: 329 self.groupListData = None 330 331 else: 332 self.groupListData = None 333 with ExceptionEater('AddMarketTicker'): 334 self.AddMarketTicker() 335 self._left_side = Container(name='leftSide', parent=self, align=uiconst.TOLEFT, width=settings.user.ui.Get('marketselectorwidth_%s' % self.idName, 180), padding=self._get_left_side_padding()) 336 self._left_side_divider = Divider(name='divider', parent=self, align=uiconst.TOLEFT, state=uiconst.UI_NORMAL, width=8, padding=self._get_left_side_divider_padding(), cross_axis_alignment=AxisAlignment.START) 337 self._left_side_divider.Startup(self._left_side, 'width', 'x', 180, 450) 338 tabs = TabGroup(name='tabparent', parent=self._left_side, padding=0) 339 self.sr.sbTabs = tabs 340 self._main_tab_container = Container(parent=self, align=uiconst.TOTOP, height=32, padding=self._get_main_tab_container_padding()) 341 self.sr.tabs = TabGroup(name='tabparent', parent=self._main_tab_container, align=uiconst.TOLEFT, padBottom=0, auto_size=True) 342 button_group = ButtonGroup(parent=self._main_tab_container, align=uiconst.TOBOTTOM, padLeft=24, density=Density.COMPACT, button_alignment=AxisAlignment.END) 343 self.marketNESButton = Button(parent=button_group, label=GetByLabel('UI/VirtualGoodsStore/VgsName'), hint=GetByLabel('Tooltips/Neocom/Vgs_description'), func=uicore.cmd.ToggleAurumStore, variant=ButtonVariant.GHOST) 344 self.marketNESButton.analyticID = MARKET_NES_BUTTON_ANALYTIC_ID 345 Button(parent=button_group, label=GetByLabel('Tooltips/StationServices/MarketOrders'), hint=GetByLabel('Tooltips/StationServices/MarketOrders_description'), func=uicore.cmd.OpenMarketOrders, variant=ButtonVariant.GHOST) 346 multiBuyBtn = Button(parent=button_group, label=GetByLabel('UI/Market/Multibuy'), hint=GetByLabel('UI/Market/Multibuy_description'), func=self.OnOpenMultiBuyBtn, variant=ButtonVariant.GHOST) 347 multiBuyBtn.OnDropData = self.OnDropOnMultibuyBtn 348 self._group_panel = ScrollContainer(name='groupScroll', parent=self, align=uiconst.TOALL, padding=self._get_group_panel_padding()) 349 searchAndSettingParent = Container(name='searchAndSettingParent', parent=self._left_side, align=uiconst.TOTOP, height=24, padding=(0, 8, 8, 8)) 350 collapseParent = ContainerAutoSize(parent=searchAndSettingParent, align=uiconst.TORIGHT) 351 ButtonIcon(name='collapse', parent=collapseParent, align=uiconst.CENTER, pos=(0, 0, 24, 24), iconSize=12, texturePath='res:/UI/Texture/classes/Scroll/Collapse.png', func=self.CollapseAll, hint=localization.GetByLabel('UI/Common/Buttons/CollapseAll')) 352 searchparent = Container(name='searchparent', parent=searchAndSettingParent, align=uiconst.TOALL) 353 filterParent = ContainerAutoSize(parent=searchAndSettingParent, align=uiconst.TORIGHT, idx=0) 354 self.sr.filtericon = UtilMenu(parent=filterParent, align=uiconst.CENTER, GetUtilMenu=self.SettingMenu, texturePath=eveicon.tune, width=24, height=24, iconSize=16, uniqueUiName=pConst.UNIQUE_NAME_MARKET_BROWSE_SETTINGS) 355 padRight = self.sr.filtericon.width + 4 356 searchText = settings.char.ui.Get('market_searchText', '') 357 inpt = QuickFilterEdit(name='searchField', parent=searchparent, setvalue=searchText, hintText=localization.GetByLabel('UI/Common/Search'), pos=(0, 0, 0, 18), padRight=4, maxLength=64, align=uiconst.TOALL, OnClearFilter=self.LoadMarketListOrSearch, isTypeField=True, triggerFilterOnCreation=False) 358 inpt.ReloadFunction = self.OnSearchFieldChanged 359 inpt.OnReturn = self.LoadMarketListOrSearch 360 self.sr.searchInput = inpt 361 self.sr.searchparent = searchparent 362 self.sr.quickbarBtnsParent = Container(name='quickbarBtnsParent', parent=searchAndSettingParent, align=uiconst.TOALL) 363 self.sr.quickbarBtnsParent.display = False 364 ButtonIcon(parent=ContainerAutoSize(parent=self.sr.quickbarBtnsParent, align=uiconst.TOLEFT), align=uiconst.CENTER, width=24, height=24, texturePath=eveicon.add_folder, iconSize=16, hint=localization.GetByLabel('Tooltips/Market/MarketQuickbarNewFolder'), func=self.NewFolder, args=()) 365 importMenuParent = ContainerAutoSize(parent=self.sr.quickbarBtnsParent, align=uiconst.TOLEFT) 366 UtilMenu(name='importMenu', menuAlign=uiconst.TOPLEFT, parent=importMenuParent, align=uiconst.CENTER, pos=(0, 0, 24, 24), GetUtilMenu=self.GetImportMenu, texturePath=eveicon.load, iconSize=16, hint=GetByLabel('UI/Market/Marketbase/ImportQuickbar')) 367 exportMenuParent = ContainerAutoSize(parent=self.sr.quickbarBtnsParent, align=uiconst.TOLEFT) 368 UtilMenu(name='exportMenu', menuAlign=uiconst.TOPLEFT, parent=exportMenuParent, align=uiconst.CENTER, pos=(0, 0, 24, 24), GetUtilMenu=self.GetExportMenu, texturePath=eveicon.export, iconSize=16, hint=GetByLabel('UI/Market/Marketbase/ExportQuickbar')) 369 ButtonIcon(parent=ContainerAutoSize(parent=self.sr.quickbarBtnsParent, align=uiconst.TOLEFT), align=uiconst.CENTER, width=24, height=24, texturePath=eveicon.trashcan, iconSize=16, hint=localization.GetByLabel('Tooltips/Market/MarketQuickbarReset'), func=self.ResetQuickbar, args=()) 370 self._details_panel = Container(name='details', parent=self, padding=self._get_details_panel_padding(), clipChildren=True) 371 maintabs = [GetTabData(label=localization.GetByLabel('UI/Market/Browse'), code=self, tabID='browse', hint=localization.GetByLabel('Tooltips/Market/MarketBrowseTab')), GetTabData(label=localization.GetByLabel('UI/Market/QuickBar'), code=self, tabID='quickbar', hint=localization.GetByLabel('Tooltips/Market/MarketQuickbarTab'))] 372 subtabs = [GetTabData(label=FixedTabName('UI/Common/Details'), panel=self._details_panel, code=self, tabID='details', hint=localization.GetByLabel('Tooltips/Market/MarketDetailsTab'), uniqueName=pConst.UNIQUE_NAME_MARKET_DETAILS), GetTabData(label=FixedTabName('UI/Common/Groups'), panel=self._group_panel, code=self, tabID='groups', hint=localization.GetByLabel('Tooltips/Market/MarketGroupsTab'))] 373 if self.destroyed: 374 return 375 scrollParent = Container(parent=self._left_side, align=uiconst.TOALL) 376 self._left_side_fill = PanelUnderlay(bgParent=self._left_side, padding=self._get_left_side_fill_padding()) 377 self.sr.typescroll = eveScroll.Scroll(name='typescroll', parent=scrollParent, multiSelect=False, innerPadding=(0, 0, 0, 16)) 378 self.sr.typescroll.OnSelectionChange = self.CheckTypeScrollSelection 379 self.sr.typescroll.GetContentContainer().OnDropData = self.OnScrollDrop 380 self.sr.sbTabs.Startup(maintabs, 'tbselectortabs_%s' % self.idName, autoselecttab=1, UIIDPrefix='marketTab') 381 quickbarTab = self.sr.sbTabs.GetTabs()[1] 382 quickbarTab.OnTabDropData = self.OnQuickbarScrollDrop 383 autoSelect = marketGroupID is None 384 self.sr.tabs.Startup(subtabs, 'marketsubtabs_%s' % self.idName, autoselecttab=autoSelect, UIIDPrefix='marketTab') 385 sm.RegisterNotify(self) 386 self.inited = 1 387 self.folders = settings.user.ui.Get('quickbar', {}) 388 self.lastid = settings.user.ui.Get('quickbar_lastid', 0) 389 self.SetupFilters() 390 self.SetFilterHint() 391 self.maxdepth = 99 392 if marketGroupID: 393 uthread.new(self.sr.tabs.ShowPanelByName, localization.GetByLabel('UI/Common/Groups')) 394 395 def ConstructTopContainer(self): 396 pass 397 398 def AddMarketTicker(self): 399 self._ticker = MarketTicker(parent=self, align=uiconst.TOBOTTOM, height=28 * fontconst.fontSizeFactor) 400 ticker_enabled_setting.on_change.connect(self._on_ticker_toggled) 401 402 def _on_ticker_toggled(self, enabled): 403 self._update_content_padding() 404 405 def OnDropOnMultibuyBtn(self, dragObj, nodes): 406 buyDict = {} 407 for node in nodes: 408 typeID = GetTypeIDFromDragItem(node) 409 if not typeID: 410 continue 411 try: 412 qty = int(node.extraText) 413 except: 414 qty = 1 415 416 buyDict[typeID] = qty 417 418 if buyDict: 419 self.OpenMultiBuy(buyDict) 420 421 def OnOpenMultiBuyBtn(self, *args): 422 self.OpenMultiBuy({}) 423 424 def OpenMultiBuy(self, buyDict = None): 425 if buyDict is None: 426 buyDict = {} 427 wnd = BuyMultipleTypesWithQty(buyDict) 428 if wnd: 429 wnd.Maximize() 430 431 def CollapseAll(self, *args): 432 self.sr.typescroll.CollapseAll() 433 434 def SettingMenu(self, menuParent): 435 menuParent.AddCheckBox(text=localization.GetByLabel('UI/Market/ShowOnlyAvailable'), checked=bool(settings.user.ui.Get('showonlyavailable', 1)), callback=(self.OnCheckboxChange, 'showonlyavailable')) 436 menuParent.AddSpace() 437 menuParent.AddText(text=localization.GetByLabel('UI/Market/RangeFilter')) 438 if session.stationid or session.structureid: 439 menuParent.AddRadioButton(text=localization.GetByLabel('UI/Common/LocationTypes/Station'), checked=self.GetRange() == const.rangeStation, callback=(self.OnComboChange, const.rangeStation)) 440 menuParent.AddRadioButton(text=localization.GetByLabel('UI/Common/LocationTypes/SolarSystem'), checked=self.GetRange() == const.rangeSolarSystem, callback=(self.OnComboChange, const.rangeSolarSystem)) 441 menuParent.AddRadioButton(text=localization.GetByLabel('UI/Common/LocationTypes/Region'), checked=self.GetRange() == const.rangeRegion, callback=(self.OnComboChange, const.rangeRegion)) 442 menuParent.AddSpace() 443 menuParent.AddCheckBox(text=localization.GetByLabel('UI/Market/Marketbase/FilterBySkills'), checked=bool(settings.user.ui.Get('showonlyskillsfor', 0)), callback=(self.OnCheckboxChange, 'showonlyskillsfor')) 444 menuParent.AddCheckBox(text=localization.GetByLabel('UI/Market/Marketbase/FilterByCPUAndPowergrid'), checked=bool(settings.user.ui.Get('showhavecpuandpower', 0)), callback=(self.OnCheckboxChange, 'showhavecpuandpower')) 445 menuParent.AddCheckBox(text=localization.GetByLabel('UI/Market/Marketbase/FilterByUntrainedSkills'), checked=bool(settings.user.ui.Get('shownewskills', 0)), callback=(self.OnCheckboxChange, 'shownewskills')) 446 menuParent.AddSpace() 447 menuParent.AddButton(text=GetByLabel('UI/Browser/BrowserSettings/ResetCacheLocation'), callback=self.ResetFilterSettings) 448 449 def CheckTypeScrollSelection(self, sel): 450 if len(sel) == 1: 451 entry = sel[0] 452 if entry.__guid__ == 'listentry.GenericMarketItem' or entry.__guid__ == 'listentry.QuickbarItem': 453 self.OnTypeClick(entry.typeID) 454 455 def GetOptions(self): 456 if session.stationid: 457 options = [(localization.GetByLabel('UI/Common/LocationTypes/Station'), const.rangeStation), (localization.GetByLabel('UI/Common/LocationTypes/SolarSystem'), const.rangeSolarSystem), (localization.GetByLabel('UI/Common/LocationTypes/Region'), const.rangeRegion)] 458 else: 459 options = [(localization.GetByLabel('UI/Common/LocationTypes/SolarSystem'), const.rangeSolarSystem), (localization.GetByLabel('UI/Common/LocationTypes/Region'), const.rangeRegion)] 460 return options 461 462 def GetRange(self): 463 return sm.StartService('marketutils').GetMarketRange() 464 465 def OnComboChange(self, value, *args): 466 if self.inited: 467 sm.GetService('marketutils').SetMarketRange(value) 468 self.sr.lastSearchResult = [] 469 uthread.new(self.ReloadMarketListTab) 470 471 def ReloadMarketListTab(self, *args): 472 if self.sr.sbTabs.GetSelectedArgs() == 'browse': 473 self.LoadMarketListOrSearch() 474 self.sr.tabs.ReloadVisible() 475 476 def SetFilterHint(self, *args): 477 filtersInUse, filterUsed = self.FiltersInUse1() 478 self.sr.filtericon.hint = filtersInUse 479 480 def OnCheckboxChange(self, sender, *args): 481 c = settings.user.ui.Get(sender, 0) 482 settings.user.ui.Set(sender, not c) 483 self.SetFilterHint() 484 if self.sr.sbTabs.GetSelectedArgs() == 'browse': 485 self.LoadMarketListOrSearch() 486 if self.sr.tabs.GetSelectedArgs() == 'browse': 487 self.LoadMarketListOrSearch() 488 489 def OnCheckboxChangeSett(self, sender, *args): 490 settings.user.ui.Set(sender.name, bool(sender.checked)) 491 self.LoadMarketData() 492 self.ShowFiltersInUse() 493 494 def OnMarketQuickbarChange(self, fromMarket = 0, *args): 495 if self and not self.destroyed: 496 if not fromMarket: 497 self.lastid = settings.user.ui.Get('quickbar_lastid', 0) 498 self.folders = settings.user.ui.Get('quickbar', {}) 499 if self.sr.sbTabs.GetSelectedArgs() == 'quickbar': 500 self.LoadQuickBar() 501 502 def OnOwnOrdersChanged(self, orders, reason, isCorp): 503 if self and not self.destroyed: 504 showAutoRefresh = False 505 for order in orders: 506 if not settings.user.ui.Get('autorefresh', True) and self.sr.detailTypeID: 507 if order.typeID == self.sr.detailTypeID: 508 showAutoRefresh = True 509 if reason != 'Expiry': 510 self._OnOwnOrderChanged() 511 512 if showAutoRefresh: 513 self.sr.reloadBtn.display = True 514 515 @threadutils.throttled(5) 516 def _OnOwnOrderChanged(self): 517 if self and not self.destroyed: 518 try: 519 if settings.user.ui.Get('autorefresh', True): 520 if self.sr.sbTabs.GetSelectedArgs() == 'browse': 521 self.LoadMarketListOrSearch() 522 self.sr.tabs.ReloadVisible() 523 except AttributeError: 524 if not self or self.destoyed: 525 return 526 raise 527 528 def OnSessionChanged(self, isremote, session, change): 529 if 'solarsystemid' in change and self and not self.destroyed: 530 combo = self.FindChild('marketComboRangeFilter') 531 if combo: 532 oldValue = combo.GetValue() 533 newValue = self.GetRange() 534 combo.LoadOptions(self.GetOptions(), newValue) 535 if oldValue != newValue: 536 self.ReloadMarketListTab() 537 538 def GetQuickItemMenu(self, btn, *args): 539 if btn.sr.node.extraText: 540 menuText = 'UI/Market/Marketbase/EditAdditionalText' 541 else: 542 menuText = 'UI/Market/Marketbase/AddAdditionalText' 543 m = [(MenuLabel(menuText), self.EditExtraText, (btn.sr.node.id, btn.sr.node.extraText, btn.sr.node.label))] 544 m += [None] 545 m += [(MenuLabel('UI/Market/Remove'), self.RemoveFromQuickBar, (btn.sr.node,))] 546 if session.role & ROLEMASK_ELEVATEDPLAYER: 547 m.append(None) 548 m += sm.GetService('menu').GetGMTypeMenu(btn.sr.node.typeID) 549 return m 550 551 def RemoveFromQuickBar(self, node): 552 nodes = node.scroll.GetSelectedNodes(node) 553 for each in nodes: 554 GetMenuService().RemoveFromQuickBar(each) 555 556 def EditExtraText(self, groupID, extraText, label, *args): 557 typeNewTextLabel = localization.GetByLabel('UI/Market/Marketbase/TypeInAdditionalText') 558 extraText = utilWindows.NamePopup(label, typeNewTextLabel, setvalue=unicode(extraText), maxLength=25, validator=self.ValidateExtraText) 559 if extraText is None: 560 return 561 self.folders[groupID[1]].extraText = extraText 562 sm.ScatterEvent('OnMarketQuickbarChange') 563 564 def ValidateExtraText(self, *args): 565 pass 566 567 def OnSearchFieldChanged(self, *args): 568 inputValue = self.sr.searchInput.GetValue().strip() 569 if inputValue == '': 570 return self.LoadMarketListOrSearch() 571 if len(inputValue) > 1: 572 self.DoSearch() 573 574 def DoSearch(self): 575 if self.destroyed: 576 return 577 self.PopulateSeachAsksForMyRange() 578 settings.char.ui.Set('market_searchText', self.sr.searchInput.GetValue()) 579 self.Search() 580 581 def LoadMarketListOrSearch(self): 582 if self.destroyed: 583 return 584 settings.char.ui.Set('market_searchText', self.sr.searchInput.GetValue()) 585 self.SetFilterHint() 586 self.mine = self.GetMySkills() 587 self.PopulateAsksForMyRange() 588 if self.sr.searchInput.GetValue().strip(): 589 self.Search() 590 else: 591 if not self.sr.filtericon.enabled: 592 self.sr.filtericon.Enable() 593 self.SetFilterHint() 594 self.LoadMarketList() 595 596 def LoadMarketList(self): 597 scrolllist = self.GetGroupListForBrowse() 598 if self.destroyed: 599 return 600 self.sr.typescroll.Load(contentList=scrolllist, scrollTo=self.sr.typescroll.GetScrollProportion()) 601 602 @telemetry.ZONE_METHOD 603 def PopulateAsksForMyRange(self): 604 asksForMyRange = self._GetAsksForRange() 605 self.searchAsksForMyRange = asksForMyRange 606 marketRange = self.GetRange() 607 if marketRange in (const.rangeStation, const.rangeSolarSystem) or idCheckers.IsWormholeRegion(session.regionid): 608 asksForMyRange = ConvertTuplesToBestByOrders(asksForMyRange) 609 self.asksForMyRange = asksForMyRange 610 611 def _GetAsksForRange(self): 612 quote = sm.StartService('marketQuote') 613 marketRange = self.GetRange() 614 if marketRange == const.rangeStation: 615 asksForMyRange = quote.GetStationAsks() 616 elif marketRange == const.rangeSolarSystem or idCheckers.IsWormholeRegion(session.regionid): 617 asksForMyRange = quote.GetSystemAsks() 618 else: 619 asksForMyRange = quote.GetRegionBest() 620 return asksForMyRange 621 622 def _GetPlexAsks(self): 623 return sm.StartService('marketQuote').GetPlexBest() 624 625 def PopulateSeachAsksForMyRange(self): 626 self.searchAsksForMyRange = self._GetAsksForRange() 627 628 def GetScrollListFromTypeList(self, nodedata, *args): 629 typeIDs = nodedata.invTypes 630 sublevel = nodedata.sublevel 631 return self._GetScrollListFromTypeList(typeIDs, sublevel) 632 633 def _GetScrollListFromTypeList(self, typeIDs, sublevel): 634 subList = [] 635 for typeID in typeIDs: 636 typeName = evetypes.GetName(typeID) 637 subList.append((typeName, GetFromClass(GenericMarketItem, {'label': typeName, 638 'invtype': typeID, 639 'sublevel': sublevel + 1, 640 'GetMenu': self.OnTypeMenu, 641 'ignoreRightClick': 1, 642 'showinfo': 1, 643 'typeID': typeID}))) 644 645 subList = [ item[1] for item in localization.util.Sort(subList, key=lambda x: x[0]) ] 646 return subList 647 648 def GetTypesByMetaGroups(self, typeIDs): 649 typesByMetaGroupID = defaultdict(list) 650 for typeID in typeIDs: 651 if evetypes.GetVariationParentTypeIDOrNone(typeID) is None: 652 metaGroupID = None 653 else: 654 metaGroupID = evetypes.GetMetaGroupID(typeID) 655 if metaGroupID == const.metaGroupStoryline: 656 metaGroupID = const.metaGroupFaction 657 typesByMetaGroupID[metaGroupID].append(typeID) 658 659 return typesByMetaGroupID 660 661 def OnMetaGroupClicked(self, *args): 662 self.sr.tabs.ShowPanelByName(localization.GetByLabel('UI/Common/Groups')) 663 664 def GetGroupListForBrowse(self, nodedata = None, newitems = 0): 665 scrolllist = [] 666 if nodedata and nodedata.marketGroupInfo.hasTypes: 667 typesByMetaGroupID = self.GetTypesByMetaGroups(nodedata.typeIDs) 668 for metaGroupID, types in sorted(typesByMetaGroupID.items()): 669 subList = [] 670 if len(types) == 0: 671 continue 672 categoryID = evetypes.GetCategoryID(types[0]) 673 if metaGroupID in (const.metaGroupStoryline, 674 const.metaGroupFaction, 675 const.metaGroupOfficer, 676 const.metaGroupDeadspace) and categoryID in CATEGORIES_WITH_FACTION_AND_STORYLINE_SUBFOLDERS: 677 if metaGroupID in (const.metaGroupStoryline, const.metaGroupFaction): 678 label = localization.GetByLabel('UI/Market/FactionAndStoryline') 679 else: 680 label = metaGroups.get_name(metaGroupID) 681 marketGroupID = nodedata.marketGroupInfo.marketGroupID if nodedata is not None else None 682 subList.append((label, GetFromClass(MarketMetaGroupEntry, {'GetSubContent': self.GetScrollListFromTypeList, 683 'label': label, 684 'id': (marketGroupID, metaGroupID), 685 'showlen': 0, 686 'metaGroupID': metaGroupID, 687 'invTypes': types, 688 'sublevel': nodedata.sublevel + 1, 689 'showicon': GetIconFile(metaGroups.get_icon_id(metaGroupID)), 690 'state': 'locked', 691 'BlockOpenWindow': True, 692 'OnToggle': self.OnMetaGroupClicked, 693 'typeIDs': types}))) 694 subList = [ item[1] for item in localization.util.Sort(subList, key=lambda x: x[0]) ] 695 else: 696 subList = self._GetScrollListFromTypeList(types, nodedata.sublevel) 697 scrolllist += subList 698 699 else: 700 marketGroupID = None 701 level = 0 702 if nodedata: 703 marketGroupID = nodedata.marketGroupInfo.marketGroupID 704 level = nodedata.sublevel + 1 705 grouplist = sm.GetService('marketutils').GetMarketGroups()[marketGroupID] 706 for marketGroupInfo in grouplist: 707 if not len(marketGroupInfo.types): 708 continue 709 if self.destroyed: 710 return 711 typeIDs = self.FilterItemsForBrowse(marketGroupInfo) 712 if len(typeIDs) == 0: 713 continue 714 if level in (0, 1): 715 groupHint = marketGroupInfo.description 716 else: 717 groupHint = '' 718 groupID = (marketGroupInfo.marketGroupName, marketGroupInfo.marketGroupID) 719 data = {'GetSubContent': self.GetGroupListForBrowse, 720 'label': marketGroupInfo.marketGroupName, 721 'id': groupID, 722 'typeIDs': typeIDs, 723 'iconMargin': 18, 724 'showlen': 0, 725 'marketGroupInfo': marketGroupInfo, 726 'sublevel': level, 727 'state': 'locked', 728 'OnClick': self.OnMarketGroupClicked, 729 'showicon': None if not marketGroupInfo.hasTypes else 'hide', 730 'iconID': marketGroupInfo.iconID, 731 'selected': False, 732 'BlockOpenWindow': 1, 733 'MenuFunction': self.SelectFolderMenu, 734 'hint': groupHint} 735 if not level and marketGroupInfo.description: 736 data['hint'] = marketGroupInfo.description 737 if marketGroupInfo.hasTypes and getattr(self, 'groupListData', None) and self.groupListData.marketGroupID != marketGroupInfo.marketGroupID: 738 uicore.registry.SetListGroupOpenState(groupID, 0) 739 scrolllist.append((marketGroupInfo.marketGroupName, GetFromClass(MarketListGroup, data))) 740 741 scrolllist = [ item[1] for item in localization.util.Sort(scrolllist, key=lambda x: x[0]) ] 742 return scrolllist 743 744 def OnMarketGroupClicked(self, entry, openGroup = True): 745 if not openGroup: 746 return 747 marketGroup = entry.sr.node.marketGroupInfo 748 self._LoadMarketGroup(marketGroup) 749 750 def LoadMarketGroup(self, marketGroupID): 751 self.groupListData = sm.GetService('marketutils').GetMarketGroupByID(marketGroupID) 752 self.sr.tabs.ShowPanelByName(localization.GetByLabel('UI/Common/Groups')) 753 754 def _LoadMarketGroup(self, marketGroup): 755 self.state = uiconst.UI_DISABLED 756 try: 757 if marketGroup.hasTypes: 758 groupID = marketGroup.marketGroupID 759 for entry in self.sr.typescroll.GetNodes(): 760 if not (entry.marketGroupInfo and entry.marketGroupInfo.hasTypes): 761 continue 762 if entry.marketGroupInfo.marketGroupID == groupID: 763 if not entry.panel: 764 entry.open = 1 765 self.sr.typescroll.PrepareSubContent(entry) 766 self.sr.typescroll.SelectNode(entry) 767 self.sr.typescroll.ShowNodeIdx(entry.idx) 768 if entry.open or self.groupListData is None or self.groupListData.marketGroupID != groupID: 769 self.groupListData = entry.marketGroupInfo 770 self.sr.tabs.ShowPanelByName(localization.GetByLabel('UI/Common/Groups')) 771 else: 772 if not entry.open: 773 continue 774 if entry.panel: 775 entry.panel.Toggle() 776 else: 777 entry.open = 0 778 if entry.subNodes: 779 rm = entry.subNodes 780 entry.subNodes = [] 781 entry.open = 0 782 self.sr.typescroll.RemoveEntries(rm) 783 784 finally: 785 self.state = uiconst.UI_PICKCHILDREN 786 787 def GetAttrDict(self, typeID): 788 ret = {} 789 for each in dogma.data.get_type_attributes(typeID): 790 attribute = dogma.data.get_attribute(each.attributeID) 791 if attribute.dataType == attributeDataTypeTypeMirror: 792 ret[each.attributeID] = evetypes.GetAttributeForType(typeID, attribute.name) 793 else: 794 ret[each.attributeID] = each.value 795 796 if const.attributeCapacity not in ret and evetypes.GetCapacity(typeID): 797 ret[const.attributeCapacity] = evetypes.GetCapacity(typeID) 798 attrInfo = sm.GetService('godma').GetType(typeID) 799 for each in attrInfo.displayAttributes: 800 ret[each.attributeID] = each.value 801 802 return ret 803 804 def GetActiveShipSlots(self): 805 ship = sm.GetService('godma').GetItem(session.shipid) 806 if ship is None: 807 return 0 808 hiSlots = getattr(ship, 'hiSlots', 0) 809 medSlots = getattr(ship, 'medSlots', 0) 810 lowSlots = getattr(ship, 'lowSlots', 0) 811 rigSlots = getattr(ship, 'rigSlots', 0) 812 flags = [] 813 for gidx in xrange(3): 814 for sidx in xrange(8): 815 flags.append(getattr(const, 'flag%sSlot%s' % (FITKEYS[gidx], sidx))) 816 817 for module in ship.modules: 818 if module.flagID not in flags: 819 continue 820 for effect in module.effects.itervalues(): 821 if effect.effectID == const.effectHiPower: 822 hiSlots -= 1 823 elif effect.effectID == const.effectMedPower: 824 medSlots -= 1 825 elif effect.effectID == const.effectLoPower: 826 lowSlots -= 1 827 elif effect.effectID == const.effectRigSlot: 828 rigSlots -= 1 829 830 return (hiSlots, 831 medSlots, 832 lowSlots, 833 rigSlots) 834 835 def GetMySkills(self): 836 return sm.GetService('skills').MyEffectiveSkillLevelsByID() 837 838 def KillGroupPageThread(self): 839 if self.updatingGroupsThread and self.updatingGroupsThread.IsAlive(): 840 self.updatingGroupsThread.Kill() 841 842 @telemetry.ZONE_METHOD 843 def ShowGroupPage(self, *args): 844 self.KillGroupPageThread() 845 self.updatingGroupsThread = uthread2.StartTasklet(self.ShowGroupPage_thread) 846 847 def ShowGroupPage_thread(self, *args): 848 self.PopulateAsksForMyRange() 849 try: 850 self._group_panel.Flush() 851 group = self.groupListData 852 if group: 853 self._group_panel.ShowNoContentHint(localization.GetByLabel('UI/Market/Marketbase/Loading')) 854 freeslots = self.GetActiveShipSlots() 855 self.mine = mySkills = self.GetMySkills() 856 dataByTypeID = {data.typeID:data for data in self.FilterItemsForGroupPage(group)} 857 typesByMetaGroupID = self.GetTypesByMetaGroups(dataByTypeID.keys()) 858 scrolllist = [] 859 for _, typeIDs in sorted(typesByMetaGroupID.iteritems()): 860 subList = [] 861 if len(typeIDs) == 0: 862 continue 863 for typeID in typeIDs: 864 subList.append((evetypes.GetName(typeID), dataByTypeID[typeID])) 865 866 subList = [ item[1] for item in localization.util.Sort(subList, key=lambda x: x[0]) ] 867 scrolllist += subList 868 869 if not scrolllist: 870 noItemsText = localization.GetByLabel('UI/Market/Marketbase/NoItemsAvailable') 871 if settings.user.ui.Get('showonlyavailable', 1): 872 noItemsText += '<br><br>' + localization.GetByLabel('UI/Market/Marketbase/DisableShowOnlyAvailable') 873 self._group_panel.ShowNoContentHint(noItemsText) 874 marketRange = self.GetRange() 875 if marketRange == const.rangeStation: 876 bestPriceLocation = localization.GetByLabel('UI/Common/LocationTypes/Station') 877 elif marketRange == const.rangeSolarSystem: 878 bestPriceLocation = localization.GetByLabel('UI/Common/LocationTypes/System') 879 else: 880 bestPriceLocation = localization.GetByLabel('UI/Common/LocationTypes/Region') 881 for data in scrolllist: 882 entryData = Bunch() 883 entryData.marketData = data 884 entryData.invType = data.typeID 885 entryData.typeImageAttributes = Bunch(width=64, height=64, src='typeicon:%s' % data.typeID, bumped=True, showfitting=True, showtechlevel=True) 886 entryData.freeslots = freeslots 887 entryData.mySkills = mySkills 888 desc = evetypes.GetDescription(data.typeID).replace('\r\n', '<br>').strip() 889 if desc.endswith('<br>'): 890 desc = desc[:len(desc) - 4] 891 entryData.description = desc 892 jump = '' 893 if data.qty: 894 jumps = int(data.jumps) 895 if jumps == 0: 896 jump = localization.GetByLabel('UI/Market/Marketbase/InThisSystem') 897 elif jumps == -1: 898 jump = localization.GetByLabel('UI/Market/Marketbase/InThisStation') 899 else: 900 jump = localization.GetByLabel('UI/Market/Marketbase/JumpsAway', jumps=data.jumps) 901 if data.qty > 0: 902 entryData.unitsAvailable = get_units_available_text(data.typeID, int(data.qty), jump) 903 entryData.bestPrice = get_best_price_in_place_text(data.typeID, bestPriceLocation) 904 MarketGroupEntry(parent=self._group_panel, data=entryData) 905 blue.pyos.BeNice() 906 907 self._group_panel.HideNoContentHint() 908 else: 909 self._group_panel.ShowNoContentHint(localization.GetByLabel('UI/Market/Marketbase/SelectGroupToBrowse')) 910 finally: 911 if self.destroyed: 912 return 913 914 def Load(self, key): 915 if key == 'marketdata': 916 self.lastdetailTab = localization.GetByLabel('UI/Market/MarketData') 917 self.LoadMarketData() 918 elif key == 'quickbar': 919 self.sr.searchparent.display = False 920 self.sr.quickbarBtnsParent.display = True 921 self.sr.typescroll.multiSelect = 1 922 self.LoadQuickBar() 923 elif key == 'details': 924 self.KillGroupPageThread() 925 self.LoadDetails() 926 elif key == 'pricehistory': 927 self.lastdetailTab = localization.GetByLabel('UI/Market/Marketbase/PriceHistory') 928 self.LoadPriceHistory() 929 elif key == 'browse': 930 self.sr.searchparent.display = True 931 self.sr.quickbarBtnsParent.display = False 932 self.sr.typescroll.multiSelect = 0 933 self.LoadMarketListOrSearch() 934 elif key == 'groups': 935 self.ShowGroupPage() 936 937 def Search(self, *args): 938 self.sr.searchInput.RegisterHistory() 939 self.sr.filtericon.Disable() 940 self.sr.filtericon.hint = localization.GetByLabel('UI/Market/FiltersDontApply') 941 search = self.sr.searchInput.GetValue().lower() 942 if not search or search == ' ': 943 self.LoadMarketListOrSearch() 944 return 945 self.sr.typescroll.Load(contentList=[]) 946 self.sr.typescroll.ShowHint(localization.GetByLabel('UI/Common/Searching')) 947 t = uix.TakeTime('Market::GetSearchResult', self.GetSearchResult) 948 if not t: 949 t = [GetFromClass(Generic, {'label': localization.GetByLabel('UI/Market/NothingFoundWithSearch', search=search)})] 950 self.sr.typescroll.ShowHint() 951 self.sr.typescroll.Load(contentList=t) 952 953 def SetChangeFuncs(self): 954 self.OnChangeFuncs['market_filter_price_min'] = self.OnChange_minEdit_market_filter_price 955 self.OnChangeFuncs['market_filter_price_max'] = self.OnChange_maxEdit_market_filter_price 956 self.OnChangeFuncs['market_filter_jumps_min'] = self.OnChange_minEdit_market_filter_jump 957 self.OnChangeFuncs['market_filter_jumps_max'] = self.OnChange_maxEdit_market_filter_jumps 958 self.OnChangeFuncs['market_filter_quantity_min'] = self.OnChange_minEdit_market_filter_quantity 959 self.OnChangeFuncs['market_filter_quantity_max'] = self.OnChange_maxEdit_market_filter_quantity 960 self.OnChangeFuncs['market_filters_sellorderdev_min'] = self.OnChange_minEdit_market_filters_sellorderdev 961 self.OnChangeFuncs['market_filters_sellorderdev_max'] = self.OnChange_maxEdit_market_filters_sellorderdev 962 self.OnChangeFuncs['market_filters_buyorderdev_min'] = self.OnChange_minEdit_market_filters_buyorderdev 963 self.OnChangeFuncs['market_filters_buyorderdev_max'] = self.OnChange_maxEdit_market_filters_buyorderdev 964 965 def LoadDetails(self): 966 if not self.detailsInited: 967 topPar = ContainerAutoSize(name='topCont', parent=self._details_panel, align=uiconst.TOTOP, alignMode=uiconst.TOTOP) 968 buttons = ContainerAutoSize(parent=topPar, align=uiconst.TORIGHT, padLeft=4) 969 self.goBackBtn = ButtonIcon(parent=ContainerAutoSize(parent=buttons, align=uiconst.TOLEFT), align=uiconst.TOPLEFT, width=24, height=24, iconSize=16, texturePath=eveicon.navigate_back, func=self.GoBack, hint=localization.GetByLabel('UI/Control/EveWindow/Previous')) 970 self.DisableArrow(self.goBackBtn) 971 self.goForwardBtn = ButtonIcon(parent=ContainerAutoSize(parent=buttons, align=uiconst.TOLEFT), align=uiconst.TOPLEFT, width=24, height=24, iconSize=16, texturePath=eveicon.navigate_forward, func=self.GoForward, hint=localization.GetByLabel('UI/Control/EveWindow/Next')) 972 self.DisableArrow(self.goForwardBtn) 973 self.sr.reloadBtn = ButtonIcon(parent=ContainerAutoSize(parent=buttons, align=uiconst.TOLEFT), align=uiconst.TOPLEFT, width=24, height=24, iconSize=16, texturePath=eveicon.arrow_rotate_right, func=self.OnReload, hint=localization.GetByLabel('UI/Market/Marketbase/Reload')) 974 self.sr.reloadBtn.display = False 975 self.settingsIcon = UtilMenu(parent=ContainerAutoSize(parent=buttons, align=uiconst.TOLEFT), align=uiconst.TOPLEFT, GetUtilMenu=self.DetailsSettingsMenu, texturePath=eveicon.tune, width=24, height=24, iconSize=16) 976 top = ContainerAutoSize(name='typeNameCont', align=uiconst.TOTOP, parent=topPar) 977 topDetailsCont = ContainerAutoSize(parent=top, align=uiconst.TOTOP, alignMode=uiconst.TOTOP, minHeight=64) 978 self.mainIconContainer = Container(name='mainIconContainer', parent=Container(parent=topDetailsCont, align=uiconst.TOLEFT, width=64, padRight=8), align=uiconst.TOTOP, height=64) 979 self.sr.detailIcon = MarketGroupItemImage(parent=self.mainIconContainer, align=uiconst.TOALL, name='detailIcon', height=64, width=64) 980 self.sr.detailIcon.Hide() 981 self.sr.detailGroupTrace = eveLabel.EveLabelMedium(parent=topDetailsCont, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, text='', color=TextColor.SECONDARY) 982 self.sr.detailGroupTrace.OnClick = (self.ClickGroupTrace, self.sr.detailGroupTrace) 983 captionGrid = LayoutGrid(parent=ContainerAutoSize(parent=topDetailsCont, align=uiconst.TOTOP), align=uiconst.TOPLEFT, columns=3, cellSpacing=(8, 0)) 984 self.sr.detailTop = eveLabel.EveCaptionMedium(parent=captionGrid, align=uiconst.CENTERLEFT, text=localization.GetByLabel('UI/Market/Marketbase/NoTypeSelected'), state=uiconst.UI_NORMAL) 985 self.sr.detailInfoicon = InfoIcon(parent=captionGrid, align=uiconst.CENTER, state=uiconst.UI_HIDDEN) 986 self.sr.detailInfoicon.OnClick = self.ShowInfoFromDetails 987 self.sr.detailTypeID = None 988 self.browseBtn = ButtonIcon(name='browseBtn', parent=captionGrid, align=uiconst.CENTER, width=16, height=16, iconSize=16, texturePath='res:/UI/Texture/classes/MapView/focusIcon.png', hint=localization.GetByLabel('UI/Market/Marketbase/FindInBrowseTab'), func=self.OpenOnType, args=self.sr.detailGroupTrace, uniqueUiName=pConst.UNIQUE_NAME_MARKET_FIND_IN_BROWSER) 989 self.browseBtn.display = False 990 self.sr.requirements = RequirementsContainer(parent=ContainerAutoSize(parent=topDetailsCont, align=uiconst.TOTOP), align=uiconst.TOPLEFT, top=4, width=200) 991 self.buyPlexButton = PurchaseButton(name='buyPlexButton', parent=ContainerAutoSize(parent=topDetailsCont, align=uiconst.TOTOP), align=uiconst.TOPLEFT, state=uiconst.UI_HIDDEN, top=4, width=70, height=20, fontsize=12, func=lambda *args: uicore.cmd.CmdBuyPlex(logContext=FROM_MARKET_WINDOW), text=localization.GetByLabel('UI/VirtualGoodsStore/Buttons/BuyPlex')) 992 self.sr.filtersText = eveLabel.EveLabelMedium(parent=top, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, padding=(0, 8, 0, 0)) 993 self.ShowFiltersInUse() 994 self.sr.detailtabs = TabGroup(name='tabparent', parent=self._details_panel) 995 self.sr.marketdata = Container(name='marketinfo', parent=self._details_panel, pos=(0, 0, 0, 0)) 996 from eve.client.script.ui.shared.market.pricehistorychart import PriceHistoryParent 997 self.sr.pricehistory = PriceHistoryParent(name='pricehistory', parent=self._details_panel, pos=(0, 0, 0, 0)) 998 detailtabs = [GetTabData(label=localization.GetByLabel('UI/Market/MarketData'), panel=self.sr.marketdata, code=self, tabID='marketdata', hint=localization.GetByLabel('Tooltips/Market/MarketDetailsData'), uniqueName=pConst.UNIQUE_NAME_MARKET_DATA), GetTabData(label=FixedTabName('UI/Market/Marketbase/PriceHistory'), panel=self.sr.pricehistory, code=self, tabID='pricehistory', hint=localization.GetByLabel('Tooltips/Market/MarketDetailsHistory'), uniqueName=pConst.UNIQUE_NAME_MARKET_PRICE_HISTORY)] 999 self.sr.detailtabs.Startup(detailtabs, 'marketdetailtabs', autoselecttab=1, UIIDPrefix='marketDetailsTab') 1000 self.detailsInited = 1 1001 return 1002 if self.lastdetailTab: 1003 self.sr.detailtabs.ShowPanelByName(self.lastdetailTab) 1004 self.ShowFiltersInUse() 1005 1006 def ShowFiltersInUse(self): 1007 filtersInUse = self.FiltersInUse2() 1008 if filtersInUse: 1009 self.sr.filtersText.display = True 1010 self.sr.filtersText.text = localization.GetByLabel('UI/Market/Marketbase/MarketFilters') 1011 self.sr.filtersText.hint = filtersInUse 1012 else: 1013 self.sr.filtersText.display = False 1014 self.sr.filtersText.text = '' 1015 self.sr.filtersText.hint = None 1016 1017 def DetailsSettingsMenu(self, menuParent): 1018 grid = menuParent.AddLayoutGrid(columns=4, cellPadding=4) 1019 priceConfig = settings.user.ui.Get('market_filter_price', 0) 1020 Checkbox(text=GetByLabel('UI/Market/Marketbase/Price'), settingsKey='market_filter_price', checked=priceConfig, parent=grid, align=uiconst.TOPLEFT, callback=self.OnCheckboxChangeSett, wrapLabel=False) 1021 self.MakeFloatEdit('market_filter_price', isMin=True, parent=grid) 1022 eveLabel.EveLabelSmall(text='-', parent=grid, align=uiconst.CENTER) 1023 self.MakeFloatEdit('market_filter_price', isMin=False, parent=grid) 1024 if not does_global_market_apply(self._typeID): 1025 jumpsConfig = settings.user.ui.Get('market_filter_jumps', 0) 1026 Checkbox(text=GetByLabel('UI/Market/Marketbase/Jumps'), settingsKey='market_filter_jumps', checked=jumpsConfig, parent=grid, align=uiconst.TOPLEFT, callback=self.OnCheckboxChangeSett, wrapLabel=False) 1027 self.MakeIntEdit('market_filter_jumps', isMin=True, parent=grid, ints=[0, None]) 1028 eveLabel.EveLabelSmall(text='-', parent=grid, align=uiconst.CENTER) 1029 self.MakeIntEdit('market_filter_jumps', isMin=False, parent=grid, ints=[0, None]) 1030 qtyConfig = settings.user.ui.Get('market_filter_quantity', 0) 1031 Checkbox(text=GetByLabel('UI/Common/Quantity'), settingsKey='market_filter_quantity', checked=qtyConfig, parent=grid, align=uiconst.TOPLEFT, callback=self.OnCheckboxChangeSett, wrapLabel=False) 1032 self.MakeIntEdit('market_filter_quantity', isMin=True, parent=grid, ints=[0, None]) 1033 eveLabel.EveLabelSmall(text='-', parent=grid, align=uiconst.CENTER) 1034 self.MakeIntEdit('market_filter_quantity', isMin=False, parent=grid, ints=[0, None]) 1035 if not does_global_market_apply(self._typeID): 1036 subGrid = LayoutGrid(columns=3, cellPadding=(0, 0, 20, 0)) 1037 showOrdersLabel = EveLabelSmall(text=GetByLabel('UI/Market/Marketbase/ShowOrdersIn'), left=2) 1038 subGrid.AddCell(cellObject=showOrdersLabel, colSpan=3) 1039 boxes = self.GetSecStatusBoxes() 1040 for label, configname, retval, checked, hint in boxes: 1041 Checkbox(text='%s' % label, parent=subGrid, settingsKey=configname, checked=checked, callback=self.OnCheckboxChangeSett, align=uiconst.TOPLEFT, wrapLabel=False) 1042 1043 subGrid.RefreshGridLayout() 1044 grid.AddCell(cellObject=subGrid, colSpan=4) 1045 sellConfig = settings.user.ui.Get('market_filters_sellorderdev', 0) 1046 Checkbox(text=GetByLabel('UI/Market/Marketbase/SellOrdersDeviation'), settingsKey='market_filters_sellorderdev', checked=sellConfig, parent=grid, align=uiconst.TOPLEFT, hint=GetByLabel('UI/Market/Marketbase/SellOrdersDeviationToolTip'), callback=self.OnCheckboxChangeSett, wrapLabel=False) 1047 self.MakeIntEdit('market_filters_sellorderdev', isMin=True, parent=grid, ints=[-100, None]) 1048 eveLabel.EveLabelSmall(text='-', parent=grid, align=uiconst.CENTER) 1049 self.MakeIntEdit('market_filters_sellorderdev', isMin=False, parent=grid, ints=[-100, None]) 1050 buyConfig = settings.user.ui.Get('market_filters_buyorderdev', 0) 1051 Checkbox(text=GetByLabel('UI/Market/Marketbase/BuyOrdersDeviation'), settingsKey='market_filters_buyorderdev', checked=buyConfig, parent=grid, align=uiconst.TOPLEFT, hint=GetByLabel('UI/Market/Marketbase/BuyOrdersDeviationToolTip'), callback=self.OnCheckboxChangeSett, wrapLabel=False) 1052 self.MakeIntEdit('market_filters_buyorderdev', isMin=True, parent=grid, ints=[-100, None]) 1053 eveLabel.EveLabelSmall(text='-', parent=grid, align=uiconst.CENTER) 1054 self.MakeIntEdit('market_filters_buyorderdev', isMin=False, parent=grid, ints=[-100, None]) 1055 currentMyOrdersValue = settings.user.ui.Get('hilitemyorders', True) 1056 mmo = Checkbox(text=GetByLabel('UI/Market/Marketbase/MarkMyOrders'), settingsKey='hilitemyorders', checked=currentMyOrdersValue, hint=GetByLabel('UI/Market/Marketbase/MarkMyOrdersHint'), callback=self.OnCheckboxChangeSett) 1057 grid.AddCell(cellObject=mmo, colSpan=4) 1058 menuParent.AddCheckBox(text=localization.GetByLabel('UI/Market/Marketbase/AutoRefresh'), checked=bool(settings.user.ui.Get('autorefresh', 0)), callback=(self.OnCheckboxChange, 'autorefresh')) 1059 menuParent.AddButton(text=GetByLabel('UI/Browser/BrowserSettings/ResetCacheLocation'), callback=self.ResetDetailsSettings) 1060 1061 def MakeIntEdit(self, configName, isMin, parent, ints): 1062 if isMin: 1063 funcKey = '%s_min' % configName 1064 editName = 'minEdit_%s' % configName 1065 else: 1066 funcKey = '%s_max' % configName 1067 editName = 'maxEdit_%s' % configName 1068 edit = SingleLineEditInteger(name=editName, setvalue=GetNumericValueFromSetting(editName), parent=parent, minValue=ints[0], maxValue=ints[1], OnChange=self.OnChangeFuncs[funcKey]) 1069 edit.AutoFitToText(FmtAmt(sys.maxint)) 1070 return edit 1071 1072 def MakeFloatEdit(self, configName, isMin, parent): 1073 if isMin: 1074 funcKey = '%s_min' % configName 1075 editName = 'minEdit_%s' % configName 1076 else: 1077 funcKey = '%s_max' % configName 1078 editName = 'maxEdit_%s' % configName 1079 edit = SingleLineEditFloat(name=editName, setvalue=GetNumericValueFromSetting(editName), parent=parent, maxValue=MAX_ORDER_PRICE, decimalPlaces=2, OnChange=self.OnChangeFuncs[funcKey]) 1080 edit.AutoFitToText(FmtAmt(sys.maxint)) 1081 return edit 1082 1083 def GetSecStatusBoxes(self): 1084 highSecurityLabel = GetByLabel('UI/Common/HighSec') 1085 highSecurityToolTipLabel = GetByLabel('UI/Market/Marketbase/FilterHighSecurityToolTip') 1086 lowSecurityLabel = GetByLabel('UI/Common/LowSec') 1087 lowSecurityToolTipLabel = GetByLabel('UI/Market/Marketbase/FilterLowSecurityToolTip') 1088 zeroSecurityLabel = GetByLabel('UI/Common/NullSec') 1089 zeroSecurityToolTipLabel = GetByLabel('UI/Market/Marketbase/FilterZeroSecurityToolTip') 1090 boxes = [(highSecurityLabel, 1091 'market_filter_highsec', 1092 settings.user.ui.Get('market_filter_highsec', 0) == 1, 1093 settings.user.ui.Get('market_filter_highsec', 0), 1094 highSecurityToolTipLabel), (lowSecurityLabel, 1095 'market_filter_lowsec', 1096 settings.user.ui.Get('market_filter_lowsec', 0) == 1, 1097 settings.user.ui.Get('market_filter_lowsec', 0), 1098 lowSecurityToolTipLabel), (zeroSecurityLabel, 1099 'market_filter_zerosec', 1100 settings.user.ui.Get('market_filter_zerosec', 0) == 1, 1101 settings.user.ui.Get('market_filter_zerosec', 0), 1102 zeroSecurityToolTipLabel)] 1103 return boxes 1104 1105 def OnReload(self, *args): 1106 self.sr.reloadBtn.display = False 1107 self.sr.marketdata.children[0].OnReload() 1108 if self.sr.sbTabs.GetSelectedArgs() == 'browse': 1109 self.LoadMarketListOrSearch() 1110 self.OnOrderChangeTimer = None 1111 self.lastOnOrderChangeTime = blue.os.GetWallclockTime() 1112 1113 def _OnRefreshPlexOrdersRequired(self, *args): 1114 typeID = self.GetSelection() 1115 if typeID and typeID == typePlex: 1116 self.ReloadType() 1117 1118 def _OnShowRegionChanged(self, *args): 1119 self.ReloadType() 1120 1121 def ShowInfoFromDetails(self, *args): 1122 typeID = self.GetTypeIDFromDetails() 1123 if typeID is not None: 1124 sm.GetService('info').ShowInfo(typeID) 1125 1126 def PreviewFromDetails(self, *args): 1127 typeID = self.GetTypeIDFromDetails() 1128 if typeID is not None: 1129 sm.GetService('preview').PreviewType(typeID) 1130 1131 def GetTypeIDFromDetails(self): 1132 typeID = None 1133 invtype = self.GetSelection() 1134 if invtype: 1135 typeID = invtype 1136 if typeID is None: 1137 if self.sr.Get('detailTypeID'): 1138 typeID = self.sr.detailTypeID 1139 return typeID 1140 1141 def ClickGroupTrace(self, trace, *args): 1142 if trace.sr.marketGroupInfo: 1143 self.groupListData = trace.sr.marketGroupInfo 1144 self.sr.tabs.ShowPanelByName(localization.GetByLabel('UI/Common/Groups')) 1145 1146 def OpenOnType(self, trace, *args): 1147 typeID = trace.typeID 1148 if trace.sr.marketGroupInfo: 1149 self.groupListData = trace.sr.marketGroupInfo 1150 searchValueBefore = self.sr.searchInput.GetValue().strip() 1151 if searchValueBefore: 1152 self.sr.searchInput.SetText('') 1153 self.sr.searchInput.caretIndex = (0, 0) 1154 self.sr.searchInput.CheckHintText() 1155 self.sr.searchInput.RefreshCaretPosition() 1156 reloadingDone = False 1157 if not self.sr.sbTabs.GetSelectedArgs() == 'browse': 1158 self.sr.sbTabs.ShowPanelByName(localization.GetByLabel('UI/Market/Browse')) 1159 reloadingDone = True 1160 if settings.user.ui.Get('showonlyavailable', True): 1161 settings.user.ui.Set('showonlyavailable', False) 1162 self.LoadMarketListOrSearch() 1163 reloadingDone = True 1164 if searchValueBefore and not reloadingDone: 1165 self.LoadMarketListOrSearch() 1166 if self.sr.typescroll: 1167 self.OpenOnTypeID(typeID) 1168 1169 def OpenOnTypeID(self, typeID, groupsToSkip = [], *args): 1170 for node in self.sr.typescroll.GetNodes(): 1171 if typeID in node.get('typeIDs', []) and node.id not in groupsToSkip: 1172 if self.sr.typescroll.scrollingRange: 1173 position = node.scroll_positionFromTop / float(self.sr.typescroll.scrollingRange) 1174 self.sr.typescroll.ScrollToProportion(position, threaded=False) 1175 groupsToSkipCopy = groupsToSkip[:] + [node.id] 1176 if not node.open: 1177 if node.panel is not None: 1178 node.panel.OnClick(openGroup=False) 1179 else: 1180 uicore.registry.SetListGroupOpenState(node.id, True) 1181 blue.synchro.Yield() 1182 return self.OpenOnTypeID(typeID, groupsToSkipCopy) 1183 elif node.get('typeID', None) == typeID: 1184 self.sr.typescroll.SelectNode(node) 1185 break 1186 1187 def LoadQuickBar(self, selectFolder = 0, *args): 1188 self.selectFolder = selectFolder 1189 self.folders = settings.user.ui.Get('quickbar', {}) 1190 if not self.folders: 1191 if settings.user.ui.Get('marketquickbar', 0): 1192 self.LoadOldQuickBar() 1193 scrolllist = self.LoadQuickBarItems(selectFolder) 1194 if self.selectFolder: 1195 selectAFolderLabel = localization.GetByLabel('UI/Market/Marketbase/SelectAFolder') 1196 result = self.ListWnd([], 'item', selectAFolderLabel, None, 1, contentList=scrolllist) 1197 if not result: 1198 return False 1199 id, parentDepth = result 1200 if self.depth + 1 + parentDepth + 1 > 7: 1201 msg = localization.GetByLabel('UI/Market/Marketbase/DeepQuickbarFolder', folderDepth=self.depth + 1 + parentDepth + 1) 1202 yesNo = prompt_player_fsd_dialog('AskAreYouSure', {'cons': msg}, uiconst.YESNO) 1203 return [False, id][yesNo == uiconst.ID_YES] 1204 return id 1205 self.sr.typescroll.Load(contentList=scrolllist, noContentHint=localization.GetByLabel('UI/Common/NothingFound')) 1206 1207 def LoadOldQuickBar(self): 1208 items = settings.user.ui.Get('marketquickbar', []) 1209 for each in items: 1210 n = utillib.KeyVal() 1211 n.parent = 0 1212 n.id = self.lastid 1213 n.label = each 1214 self.folders[n.id] = n 1215 self.lastid += 1 1216 1217 settings.user.ui.Delete('marketquickbar') 1218 1219 def LoadMarketData(self, *args): 1220 invtype = self.GetSelection() 1221 if self.sr.marketdata: 1222 if not len(self.sr.marketdata.children): 1223 MarketData(name='marketdata', parent=self.sr.marketdata, pos=(0, 0, 0, 0)) 1224 marketDataChild = self.sr.marketdata.children[0] 1225 self.loadingMarketData = marketDataChild.GetInvTypeID() 1226 if invtype: 1227 marketDataChild.LoadType(invtype) 1228 self.StoreTypeInHistory(invtype) 1229 else: 1230 marketDataChild.ReloadType() 1231 self.sr.reloadBtn.display = False 1232 self.loadingMarketData = None 1233 1234 def LoadPriceHistory(self, invtype = None, *args): 1235 invtype = invtype or self.GetSelection() 1236 if not invtype: 1237 return 1238 if self.sr.pricehistory: 1239 self.sr.reloadBtn.display = False 1240 if not self.sr.pricehistory.inited: 1241 self.sr.pricehistory.Startup() 1242 self.sr.pricehistory.LoadType(invtype) 1243 self.StoreTypeInHistory(invtype) 1244 1245 @telemetry.ZONE_METHOD 1246 def GetSearchResult(self): 1247 search = self.sr.searchInput.GetValue().lower() 1248 showOnlyAvailable = settings.user.ui.Get('showonlyavailable', 1) 1249 if self.sr.lastSearchResult and self.sr.lastSearchResult[0] == search and self.sr.lastSearchResult[2] == showOnlyAvailable: 1250 scrollList = self.sr.lastSearchResult[1][:] 1251 else: 1252 scrollList = [] 1253 byCategories = {} 1254 if search: 1255 searchWhat = SEARCH_LOCALIZED 1256 if not IsUsingDefaultLanguage(session): 1257 bilingualSettings = localization.settings.bilingualSettings 1258 importantNameSetting = bilingualSettings.GetValue('localizationImportantNames') 1259 if importantNameSetting == bilingualSettings.IMPORTANT_NAME_ENGLISH: 1260 searchWhat = SEARCH_BOTH 1261 elif bilingualSettings.GetValue('languageTooltip'): 1262 searchWhat = SEARCH_BOTH 1263 typeIDFinder = sm.GetService('marketutils').GetMarketTypeIDFinder() 1264 res = typeIDFinder.FindTypeIDsWithPartialMatch(search, searchWhat) 1265 allMarketGroups = sm.GetService('marketutils').GetMarketGroups()[None] 1266 myCategories = {} 1267 for typeID in res: 1268 for mg in allMarketGroups: 1269 if typeID in mg.types: 1270 topMarketCategory = mg 1271 break 1272 else: 1273 topMarketCategory = None 1274 1275 if topMarketCategory is None: 1276 continue 1277 if topMarketCategory.marketGroupID in byCategories: 1278 byCategories[topMarketCategory.marketGroupID].append(typeID) 1279 else: 1280 byCategories[topMarketCategory.marketGroupID] = [typeID] 1281 myCategories[topMarketCategory.marketGroupID] = topMarketCategory 1282 1283 if len(byCategories) > 1: 1284 for categoryID, categoryTypeIDs in byCategories.iteritems(): 1285 category = myCategories[categoryID] 1286 group = GetFromClass(ListGroup, {'GetSubContent': self.GetSeachCategory, 1287 'label': category.marketGroupName, 1288 'id': ('searchGroups', categoryID), 1289 'showlen': 0, 1290 'sublevel': 0, 1291 'state': 'locked', 1292 'BlockOpenWindow': True, 1293 'categoryID': category.marketGroupID, 1294 'typeIDs': categoryTypeIDs, 1295 'iconID': category.iconID, 1296 'hint': category.description}) 1297 scrollList.append(group) 1298 1299 else: 1300 for categoryID, categoryTypeIDs in byCategories.iteritems(): 1301 fakeNodeData = utillib.KeyVal(typeIDs=categoryTypeIDs, sublevel=-1, categoryID=categoryID) 1302 results = self.GetSeachCategory(fakeNodeData) 1303 scrollList.extend(results) 1304 1305 self.sr.lastSearchResult = (search, scrollList[:], showOnlyAvailable) 1306 return scrollList 1307 1308 def GetSeachCategory(self, nodedata, *args): 1309 types = nodedata.typeIDs 1310 typesByMetaGroupID = self.GetTypesByMetaGroups(types) 1311 sublevel = nodedata.sublevel 1312 categoryID = nodedata.categoryID 1313 scrollList = [] 1314 for metaGroupID, types in sorted(typesByMetaGroupID.items()): 1315 specialItemGroups = (const.metaGroupStoryline, 1316 const.metaGroupFaction, 1317 const.metaGroupOfficer, 1318 const.metaGroupDeadspace) 1319 if metaGroupID in specialItemGroups: 1320 searchGroup = self.GetSearchSubGroup(metaGroupID, types, sublevel=sublevel + 1, categoryID=categoryID) 1321 scrollList.append((searchGroup.label, searchGroup)) 1322 else: 1323 for typeID in types: 1324 searchEntry = self.GetSearchEntry(typeID, sublevel=sublevel + 1) 1325 scrollList.append((' ' + evetypes.GetName(typeID), searchEntry)) 1326 blue.pyos.BeNice() 1327 1328 scrollList = [ item[1] for item in localization.util.Sort(scrollList, key=lambda x: x[0]) ] 1329 return scrollList 1330 1331 def GetSearchSubGroup(self, metaGroupID, types, sublevel = 0, categoryID = -1, *args): 1332 if metaGroupID in (const.metaGroupStoryline, const.metaGroupFaction): 1333 label = localization.GetByLabel('UI/Market/FactionAndStoryline') 1334 else: 1335 label = metaGroups.get_name(metaGroupID) 1336 groupEntry = GetFromClass(MarketMetaGroupEntry, {'GetSubContent': self.GetSearchScrollListFromTypeList, 1337 'label': label, 1338 'id': ('searchGroups', (metaGroupID, categoryID)), 1339 'showlen': 0, 1340 'metaGroupID': metaGroupID, 1341 'invTypes': types, 1342 'sublevel': sublevel, 1343 'showicon': GetIconFile(metaGroups.get_icon_id(metaGroupID)), 1344 'state': 'locked', 1345 'BlockOpenWindow': True, 1346 'OnToggle': self.OnMetaGroupClicked, 1347 'typeIDs': types}) 1348 return groupEntry 1349 1350 def GetSearchScrollListFromTypeList(self, nodedata): 1351 subList = [] 1352 invTypes = nodedata.invTypes 1353 sublevel = nodedata.sublevel 1354 for typeID in invTypes: 1355 searchEntry = self.GetSearchEntry(typeID, sublevel=sublevel + 1) 1356 subList.append((evetypes.GetName(typeID), searchEntry)) 1357 1358 subList = [ item[1] for item in localization.util.Sort(subList, key=lambda x: x[0]) ] 1359 return subList 1360 1361 def GetSearchEntry(self, typeID, sublevel = 0, *args): 1362 data = utillib.KeyVal() 1363 data.label = evetypes.GetName(typeID) 1364 data.GetMenu = self.OnTypeMenu 1365 data.invtype = typeID 1366 data.showinfo = 1 1367 data.sublevel = sublevel 1368 data.typeID = typeID 1369 data.ignoreRightClick = 1 1370 onlyShowAvailable = settings.user.ui.Get('showonlyavailable', 0) 1371 if onlyShowAvailable and not self.IsTypeIdInCurrentRange(typeID): 1372 data.inRange = False 1373 else: 1374 data.inRange = True 1375 entry = GetFromClass(GenericMarketItem, data) 1376 return entry 1377 1378 def IsTypeIdInCurrentRange(self, typeID): 1379 if self.searchAsksForMyRange: 1380 return typeID in self.searchAsksForMyRange 1381 return False 1382 1383 def OnTypeClick(self, typeID, *args): 1384 if not self.sr.typescroll.GetSelected(): 1385 return 1386 if self.loadingType: 1387 self.pendingType = 1 1388 return 1389 self.sr.quickType = typeID 1390 self.ReloadType() 1391 1392 def OnTypeMenu(self, entry): 1393 typeID = entry.sr.node.invtype 1394 categoryID = evetypes.GetCategoryID(typeID) 1395 menu = [(MenuLabel('UI/Inventory/ItemActions/AddTypeToMarketQuickbar'), self.AddTypeToQuickBar, (entry.sr.node.typeID,)), (MenuLabel('UI/Commands/ShowInfo'), self.ShowInfo, (typeID,))] 1396 if categoryID in const.previewCategories and inventorycommon.typeHelpers.GetIcon(typeID) and inventorycommon.typeHelpers.GetIcon(typeID).iconFile != '': 1397 previewLabel = MenuLabel('UI/Market/Marketbase/Preview') 1398 menu.append((previewLabel, sm.GetService('preview').PreviewType, (typeID,))) 1399 if industryCommon.IsBlueprintCategory(categoryID): 1400 from eve.client.script.ui.shared.industry.industryWnd import Industry 1401 menu.append((localization.GetByLabel('UI/Industry/ViewInIndustry'), Industry.OpenOrShowBlueprint, (None, typeID))) 1402 if session.role & ROLEMASK_ELEVATEDPLAYER: 1403 menu.append(None) 1404 menu += sm.GetService('menu').GetGMTypeMenu(typeID) 1405 return menu 1406 1407 def ShowInfo(self, typeID): 1408 sm.GetService('info').ShowInfo(typeID) 1409 1410 def AddTypeToQuickBar(self, typeID, parent = 0, extraText = ''): 1411 settings.user.ui.Set('quickbar', self.folders) 1412 settings.user.ui.Set('quickbar_lastid', self.lastid) 1413 sm.GetService('marketutils').AddTypeToQuickBar(typeID, parent, fromMarket=True, extraText=extraText) 1414 self.lastid = settings.user.ui.Get('quickbar_lastid', 0) 1415 self.folders = settings.user.ui.Get('quickbar', {}) 1416 1417 def LoadQuickType(self, quick = None, *args): 1418 if quick: 1419 self.sr.quickType = quick.invType 1420 self.ReloadType() 1421 1422 def LoadTypeID_Ext(self, typeID): 1423 self.sr.quickType = typeID 1424 self.ReloadType() 1425 1426 def ReloadType(self): 1427 self._typeID = self.GetSelection() 1428 sm.ScatterEvent('OnMarketTypeSelectionChanged', self._typeID) 1429 if not self._typeID: 1430 self.loadingType = 0 1431 return 1432 self.KillGroupPageThread() 1433 marketTypes = sm.GetService('marketutils').GetMarketTypes() 1434 if self._typeID not in marketTypes: 1435 self.loadingType = 0 1436 return 1437 if self.loadingMarketData and self.loadingMarketData != self._typeID: 1438 uthread2.call_after_wallclocktime_delay(self.ReloadType, 0.1) 1439 return 1440 self.pendingType = 0 1441 self.loadingType = 1 1442 blue.pyos.synchro.Yield() 1443 try: 1444 self.sr.tabs.ShowPanelByName(localization.GetByLabel('UI/Common/Details')) 1445 except Exception as e: 1446 self.loadingType = 0 1447 raise e 1448 1449 blue.pyos.synchro.Yield() 1450 typeName = evetypes.GetName(self._typeID) 1451 self.sr.detailTop.text = typeName 1452 self.sr.detailIcon.attrs = Bunch(width=64, height=64, src='typeicon:%s' % self._typeID, bumped=True, showfitting=True, showtechlevel=True) 1453 self.sr.detailIcon.typeName = typeName 1454 self.sr.detailIcon.LoadTypeIcon(self._typeID) 1455 self.sr.detailIcon.SetOmegaIconState(self._typeID) 1456 self.sr.detailIcon.SetState(uiconst.UI_NORMAL) 1457 self.sr.detailIcon.Show() 1458 self.sr.detailInfoicon.state = uiconst.UI_NORMAL 1459 self.browseBtn.display = True 1460 self.sr.detailTypeID = self._typeID 1461 self.sr.requirements.LoadTypeRequirements(self.sr.detailTypeID) 1462 if self._typeID == const.typePlex: 1463 self.buyPlexButton.Show() 1464 else: 1465 self.buyPlexButton.Hide() 1466 marketGroup, trace = sm.GetService('marketutils').FindMarketGroup(self._typeID) 1467 if marketGroup: 1468 self.sr.detailGroupTrace.sr.marketGroupInfo = marketGroup 1469 self.sr.detailGroupTrace.text = trace 1470 self.sr.detailGroupTrace.typeID = self._typeID 1471 self.sr.detailGroupTrace.display = True 1472 else: 1473 self.sr.detailGroupTrace.display = False 1474 self.sr.detailGroupTrace.sr.marketGroupInfo = None 1475 self.sr.detailGroupTrace.typeID = None 1476 self.loadingType = 0 1477 if self.pendingType: 1478 self.ReloadType() 1479 1480 def GetSelection(self): 1481 if self.sr.quickType: 1482 return self.sr.quickType 1483 selection = self.sr.typescroll.GetSelected() 1484 if not selection: 1485 return None 1486 if hasattr(selection[0], 'invtype'): 1487 return selection[0].invtype 1488 1489 def ResetQuickbar(self): 1490 if prompt_player_fsd_dialog('ResetQuickbar', buttons=uiconst.YESNO) != uiconst.ID_YES: 1491 return 1492 self.folders = {} 1493 settings.user.ui.Set('quickbar', self.folders) 1494 self.lastid = 0 1495 settings.user.ui.Set('quickbar_lastid', self.lastid) 1496 sm.ScatterEvent('OnMarketQuickbarChange') 1497 1498 def ResetFilterSettings(self): 1499 settings.user.ui.Set('showonlyskillsfor', False) 1500 settings.user.ui.Set('showhavecpuandpower', False) 1501 settings.user.ui.Set('shownewskills', False) 1502 settings.user.ui.Set('showonlyavailable', True) 1503 settings.user.ui.Set('autorefresh', True) 1504 if self.sr.sbTabs.GetSelectedArgs() == 'browse': 1505 self.LoadMarketListOrSearch() 1506 1507 def ResetDetailsSettings(self): 1508 settings.user.ui.Set('market_filter_price', False) 1509 settings.user.ui.Set('minEdit_market_filter_price', 0) 1510 settings.user.ui.Set('maxEdit_market_filter_price', 100000) 1511 settings.user.ui.Set('market_filter_jumps', False) 1512 settings.user.ui.Set('minEdit_market_filter_jumps', 0) 1513 settings.user.ui.Set('maxEdit_market_filter_jumps', 20) 1514 settings.user.ui.Set('market_filter_quantity', False) 1515 settings.user.ui.Set('minEdit_market_filter_quantity', 0) 1516 settings.user.ui.Set('maxEdit_market_filter_quantity', 1000) 1517 settings.user.ui.Set('market_filter_zerosec', True) 1518 settings.user.ui.Set('market_filter_lowsec', True) 1519 settings.user.ui.Set('market_filter_highsec', True) 1520 settings.user.ui.Set('market_filters_sellorderdev', False) 1521 settings.user.ui.Set('minEdit_market_filters_sellorderdev', 0) 1522 settings.user.ui.Set('maxEdit_market_filters_sellorderdev', 0) 1523 settings.user.ui.Set('market_filters_buyorderdev', False) 1524 settings.user.ui.Set('minEdit_market_filters_buyorderdev', 0) 1525 settings.user.ui.Set('maxEdit_market_filters_buyorderdev', 0) 1526 self.LoadMarketData() 1527 self.ShowFiltersInUse() 1528 1529 def LoadQuickBarItems(self, selectFolder = 0, *args): 1530 import types 1531 scrolllist = [] 1532 notes = self.GetItems(parent=0) 1533 tickerFolderID = settings.char.ui.Get(TICKER_SETTING_NAME, 0) 1534 for id, n in notes.items(): 1535 try: 1536 if type(n.label) == types.UnicodeType: 1537 groupID = ('quickbar', id) 1538 data = {'GetSubContent': self.GetGroupSubContent, 1539 'label': n.label, 1540 'id': groupID, 1541 'groupItems': self.GroupGetContentIDList(groupID), 1542 'iconMargin': 18, 1543 'showlen': 0, 1544 'state': 0, 1545 'sublevel': 0, 1546 'MenuFunction': [self.GroupMenu, self.SelectFolderMenu][self.selectFolder], 1547 'BlockOpenWindow': 1, 1548 'DropData': self.GroupDropNode, 1549 'ChangeLabel': self.GroupChangeLabel, 1550 'DeleteFolder': self.GroupDeleteFolder, 1551 'selected': 1, 1552 'hideNoItem': self.selectFolder, 1553 'allowGuids': ['listentry.QuickbarGroup', 'listentry.QuickbarItem'], 1554 'selectGroup': selectFolder, 1555 'isTickerFolder': tickerFolderID == id} 1556 if self.selectFolder: 1557 data['OnDblClick'] = self.OnDblClick 1558 if data.get('sublevel', 0) + self.depth >= self.maxdepth: 1559 return [] 1560 scrolllist.append((n.label, GetFromClass(QuickbarGroup, data))) 1561 except Exception as e: 1562 log.LogWarn('Failed to load quickbar folder, reason: ', e) 1563 continue 1564 1565 if scrolllist: 1566 scrolllist = [ item[1] for item in localization.util.Sort(scrolllist, key=lambda x: x[0]) ] 1567 tempScrolllist = [] 1568 if not self.selectFolder: 1569 for id, n in notes.items(): 1570 try: 1571 if type(n.label) == types.IntType: 1572 groupID = ('quickbar', id) 1573 tempScrolllist.append((evetypes.GetName(n.label), GetFromClass(QuickbarItem, {'label': evetypes.GetName(n.label), 1574 'typeID': n.label, 1575 'id': groupID, 1576 'itemID': None, 1577 'getIcon': 0, 1578 'sublevel': 0, 1579 'showinfo': 1, 1580 'GetMenu': self.GetQuickItemMenu, 1581 'DropData': self.GroupDropNode, 1582 'parent': n.parent, 1583 'selected': 1, 1584 'invtype': n.label, 1585 'extraText': n.get('extraText', '')}))) 1586 except Exception as e: 1587 log.LogWarn('Failed to load_ quickbar type, reason: ', e) 1588 continue 1589 1590 if tempScrolllist: 1591 tempScrolllist = [ item[1] for item in localization.util.Sort(tempScrolllist, key=lambda x: x[0]) ] 1592 scrolllist.extend(tempScrolllist) 1593 return scrolllist 1594 1595 def GroupMenu(self, node): 1596 m = [] 1597 if node.sublevel < self.maxdepth: 1598 m.append((MenuLabel('UI/Market/NewFolder'), self.NewFolder, (node.id[1], node))) 1599 return m 1600 1601 def QuickbarHasFolder(self): 1602 import types 1603 if settings.user.ui.Get('quickbar', {}): 1604 for id, node in settings.user.ui.Get('quickbar', {}).items(): 1605 if type(node.label) == types.UnicodeType: 1606 return True 1607 1608 return False 1609 1610 def SelectFolderMenu(self, node): 1611 m = [] 1612 if node.sublevel < self.maxdepth: 1613 if self.QuickbarHasFolder(): 1614 m.append((MenuLabel('UI/Market/Marketbase/AddGroupToQuickbarFolder'), self.FolderPopUp, (node,))) 1615 m.append((MenuLabel('UI/Market/Marketbase/AddGroupToQuickbarRoot'), self.FolderPopUp, (node, True))) 1616 return m 1617 1618 def FolderPopUp(self, node, root = False): 1619 self.tempLastid = self.lastid 1620 self.tempFolders = {} 1621 self.depth, firstID = self.AddGroupParent(nodedata=node) 1622 if root: 1623 id = 0 1624 else: 1625 id = self.LoadQuickBar(selectFolder=1) 1626 if id is not None and id is not False: 1627 self.tempFolders[firstID].parent = id 1628 for each in range(firstID, self.tempLastid + 1): 1629 self.folders[each] = self.tempFolders[each] 1630 1631 self.lastid = self.tempLastid 1632 settings.user.ui.Set('quickbar_lastid', self.lastid) 1633 1634 def GetGroupSubContent(self, nodedata, newitems = 0): 1635 scrolllist = [] 1636 notelist = self.GetItems(nodedata.id[1]) 1637 if len(notelist): 1638 qi = 1 1639 NoteListLength = len(notelist) 1640 import types 1641 for id, note in notelist.items(): 1642 if type(note.label) == types.UnicodeType: 1643 entry = self.GroupCreateEntry((note.label, id), nodedata.sublevel + 1, selectGroup=self.selectFolder) 1644 if entry: 1645 scrolllist.append((note.label, entry)) 1646 1647 if scrolllist: 1648 scrolllist = [ item[1] for item in localization.util.Sort(scrolllist, key=lambda x: x[0]) ] 1649 tempScrolllist = [] 1650 if not self.selectFolder: 1651 for id, note in notelist.items(): 1652 if type(note.label) == types.IntType: 1653 entry = self.GroupCreateEntry((note.label, id), nodedata.sublevel + 1) 1654 if entry: 1655 tempScrolllist.append((evetypes.GetName(note.label), entry)) 1656 1657 if tempScrolllist: 1658 tempScrolllist = [ item[1] for item in localization.util.Sort(tempScrolllist, key=lambda x: x[0]) ] 1659 scrolllist.extend(tempScrolllist) 1660 if len(nodedata.groupItems) != len(scrolllist): 1661 nodedata.groupItems = self.GroupGetContentIDList(nodedata.id) 1662 return scrolllist 1663 1664 def GroupCreateEntry(self, id, sublevel, selectGroup = 0): 1665 note, id = self.folders[id[1]], id[1] 1666 import types 1667 tickerFolderID = settings.char.ui.Get(TICKER_SETTING_NAME, 0) 1668 if type(note.label) == types.UnicodeType: 1669 groupID = ('quickbar', id) 1670 data = {'GetSubContent': self.GetGroupSubContent, 1671 'label': note.label, 1672 'id': groupID, 1673 'groupItems': self.GroupGetContentIDList(groupID), 1674 'iconMargin': 18, 1675 'showlen': 0, 1676 'state': 0, 1677 'sublevel': sublevel, 1678 'BlockOpenWindow': 1, 1679 'parent': note.parent, 1680 'MenuFunction': self.GroupMenu, 1681 'ChangeLabel': self.GroupChangeLabel, 1682 'DeleteFolder': self.GroupDeleteFolder, 1683 'selected': 1, 1684 'DropData': self.GroupDropNode, 1685 'hideNoItem': self.selectFolder, 1686 'allowGuids': ['listentry.QuickbarGroup', 'listentry.QuickbarItem'], 1687 'selectGroup': selectGroup, 1688 'isTickerFolder': tickerFolderID == id} 1689 if self.selectFolder: 1690 data['OnDblClick'] = self.OnDblClick 1691 if data.get('sublevel', 0) + self.depth >= self.maxdepth: 1692 return [] 1693 return GetFromClass(QuickbarGroup, data) 1694 if type(note.label) == types.IntType: 1695 groupID = ('quickbar', id) 1696 return GetFromClass(QuickbarItem, {'label': evetypes.GetName(note.label), 1697 'typeID': note.label, 1698 'id': groupID, 1699 'itemID': None, 1700 'getIcon': 0, 1701 'sublevel': sublevel, 1702 'showinfo': 1, 1703 'GetMenu': self.GetQuickItemMenu, 1704 'DropData': self.GroupDropNode, 1705 'parent': note.parent, 1706 'selected': 1, 1707 'invtype': note.label, 1708 'extraText': note.get('extraText', '')}) 1709 del self.folders[id] 1710 1711 def OnDblClick(self, *args): 1712 pass 1713 1714 def GroupGetContentIDList(self, id): 1715 ids = self.GetItems(id[1]) 1716 test = [ (self.folders[id].label, id) for id in ids ] 1717 return test 1718 1719 def GetItems(self, parent): 1720 dict = {} 1721 for id in self.folders: 1722 if self.folders[id].parent == parent: 1723 dict[id] = self.folders[id] 1724 1725 return dict 1726 1727 def NewFolderClick(self, *args): 1728 self.NewFolder(0) 1729 1730 def GroupChangeLabel(self, id, newname): 1731 self.RenameFolder(id[1], name=newname) 1732 1733 def RenameFolder(self, folderID = 0, entry = None, name = None, *args): 1734 if name is None: 1735 folderNameLabel = localization.GetByLabel('UI/Market/Marketbase/FolderName') 1736 typeNewFolderNameLabel = localization.GetByLabel('UI/Market/Marketbase/TypeNewFolderName') 1737 ret = utilWindows.NamePopup(folderNameLabel, typeNewFolderNameLabel, maxLength=20) 1738 if ret is None: 1739 return self.folders[folderID].label 1740 name = ret 1741 self.folders[folderID].label = name 1742 sm.ScatterEvent('OnMarketQuickbarChange') 1743 return name 1744 1745 def NewFolder(self, folderID = 0, node = None, *args): 1746 folderNameLabel = localization.GetByLabel('UI/Market/Marketbase/FolderName') 1747 typeFolderNameLabel = localization.GetByLabel('UI/Market/Marketbase/TypeFolderName') 1748 ret = utilWindows.NamePopup(folderNameLabel, typeFolderNameLabel, maxLength=20) 1749 if ret is not None: 1750 self.lastid += 1 1751 n = utillib.KeyVal() 1752 n.parent = folderID 1753 n.id = self.lastid 1754 n.label = ret 1755 self.folders[n.id] = n 1756 settings.user.ui.Set('quickbar', self.folders) 1757 settings.user.ui.Set('quickbar_lastid', self.lastid) 1758 sm.ScatterEvent('OnMarketQuickbarChange') 1759 return n 1760 1761 def GroupDeleteFolder(self, id): 1762 import types 1763 noteID = id[1] 1764 notes = self.GetItems(noteID) 1765 for id, note in notes.items(): 1766 if type(note.label) == types.UnicodeType: 1767 self.GroupDeleteFolder((0, id)) 1768 continue 1769 self.DeleteFolderNote(id) 1770 1771 self.DeleteFolderNote(noteID) 1772 sm.ScatterEvent('OnMarketQuickbarChange') 1773 1774 def DeleteFolderNote(self, noteID): 1775 del self.folders[noteID] 1776 1777 def GroupDropNode(self, id, nodes): 1778 for node in nodes: 1779 if getattr(node, 'id', None) and id[1] in self.folders: 1780 parent = self.folders[id[1]].parent 1781 shouldContinue = False 1782 while parent: 1783 if node.id[1] == parent or node.id[1] == id[1]: 1784 shouldContinue = True 1785 break 1786 parent = self.folders[parent].parent 1787 1788 if shouldContinue: 1789 continue 1790 guid = getattr(node, '__guid__', None) 1791 if guid in ('listentry.FittingEntry',): 1792 self.AddFittingFolder(node, id[1]) 1793 continue 1794 shouldContinue = False 1795 for folderID, data in self.folders.items(): 1796 if data.label == node.typeID and data.parent == id[1]: 1797 shouldContinue = True 1798 break 1799 1800 if shouldContinue: 1801 continue 1802 if guid in ('listentry.QuickbarItem', 'listentry.QuickbarGroup'): 1803 noteID = node.id[1] 1804 if uicore.uilib.Key(uiconst.VK_CONTROL): 1805 self.AddTypeToQuickBar(node.typeID, parent=id[1]) 1806 elif noteID in self.folders and noteID != id[1]: 1807 self.folders[noteID].parent = id[1] 1808 elif guid == 'listentry.GenericMarketItem': 1809 self.AddTypeToQuickBar(node.typeID, parent=id[1]) 1810 elif guid in ('xtriui.ShipUIModule', 'xtriui.InvItem', 'listentry.InvItem', 'listentry.InvAssetItem'): 1811 self.AddTypeToQuickBar(node.rec.typeID, parent=id[1]) 1812 elif isinstance(node, TypeDragData): 1813 typeID = node.typeID 1814 if can_view_market_details(typeID): 1815 self.AddTypeToQuickBar(typeID, parent=id[1]) 1816 1817 sm.ScatterEvent('OnMarketQuickbarChange') 1818 1819 def OnScrollDrop(self, dropObj, nodes): 1820 if self.sr.sbTabs.GetSelectedArgs() != 'quickbar': 1821 return 1822 self.OnQuickbarScrollDrop(dropObj, nodes) 1823 1824 def OnQuickbarScrollDrop(self, dropObj, nodes): 1825 for node in nodes: 1826 guid = getattr(node, '__guid__', None) 1827 if isinstance(node, TypeDragData): 1828 typeID = node.typeID 1829 if can_view_market_details(typeID): 1830 self.AddTypeToQuickBar(typeID) 1831 elif guid == 'listentry.GenericMarketItem': 1832 self.AddTypeToQuickBar(node.typeID) 1833 elif guid in ('xtriui.ShipUIModule', 'xtriui.InvItem', 'listentry.InvItem', 'listentry.InvAssetItem'): 1834 self.AddTypeToQuickBar(node.rec.typeID) 1835 elif guid in ('listentry.QuickbarItem', 'listentry.QuickbarGroup'): 1836 self.folders[node.id[1]].parent = 0 1837 sm.ScatterEvent('OnMarketQuickbarChange') 1838 elif guid == 'listentry.FittingEntry': 1839 self.AddFittingFolder(node) 1840 1841 def AddFittingFolder(self, node, parent = 0): 1842 self.lastid += 1 1843 fittingGroup = utillib.KeyVal() 1844 fittingGroup.parent = parent 1845 fittingGroup.id = self.lastid 1846 fittingGroup.label = node.label 1847 self.folders[fittingGroup.id] = fittingGroup 1848 settings.user.ui.Set('quickbar', self.folders) 1849 settings.user.ui.Set('quickbar_lastid', self.lastid) 1850 rackTypes = sm.GetService('fittingSvc').GetTypesByRack(node.fitting) 1851 rackNames = {'hiSlots': const.effectHiPower, 1852 'medSlots': const.effectMedPower, 1853 'lowSlots': const.effectLoPower, 1854 'rigSlots': const.effectRigSlot, 1855 'subSystems': const.effectSubSystem, 1856 'serviceSlots': const.effectServiceSlot} 1857 for rack, contents in rackTypes.iteritems(): 1858 if len(contents): 1859 name = None 1860 if rack == 'drones': 1861 name = localization.GetByLabel('UI/Drones/Drones') 1862 elif rack == 'charges': 1863 name = localization.GetByLabel('UI/Generic/Charges') 1864 elif rack == 'ice': 1865 name = localization.GetByLabel('UI/Market/Marketbase/IceProducts') 1866 elif rack in rackNames: 1867 name = dogma.data.get_effect_display_name(rackNames[rack]) 1868 self.lastid += 1 1869 n = utillib.KeyVal() 1870 n.parent = fittingGroup.id 1871 n.id = self.lastid 1872 n.label = name 1873 self.folders[n.id] = n 1874 cannotAddToQuickbar = [] 1875 for typeID, count in contents.iteritems(): 1876 if count > 1: 1877 extraText = count 1878 else: 1879 extraText = '' 1880 try: 1881 self.AddTypeToQuickBar(typeID, parent=n.id, extraText=extraText) 1882 except UserError as e: 1883 if e.msg == 'cannotTradeOnMarket': 1884 cannotAddToQuickbar.append(typeID) 1885 else: 1886 raise 1887 1888 settings.user.ui.Set('quickbar', self.folders) 1889 settings.user.ui.Set('quickbar_lastid', self.lastid) 1890 1891 self.AddTypeToQuickBar(node.fitting.shipTypeID, parent=fittingGroup.id) 1892 sm.ScatterEvent('OnMarketQuickbarChange') 1893 1894 def ShouldShowType(self, typeID): 1895 filterSkills = settings.user.ui.Get('showonlyskillsfor', 0) 1896 filterCpuPower = settings.user.ui.Get('showhavecpuandpower', 0) 1897 filterKnownSkills = settings.user.ui.Get('shownewskills', 0) 1898 doesMeetReq = True 1899 if filterSkills or filterCpuPower or filterKnownSkills: 1900 currShip = sm.StartService('godma').GetItem(session.shipid) 1901 doesMeetReq, hasSkills, hasPower, hasCpu, hasSkill = self.MeetsRequirements(typeID, ship=currShip, reqTypeSkills=filterSkills, reqTypeCpuPower=filterCpuPower, hasSkill=filterKnownSkills) 1902 return doesMeetReq 1903 1904 def FilterItemsForBrowse(self, marketGroupInfo): 1905 filterNone = settings.user.ui.Get('showonlyavailable', 0) 1906 ret = [] 1907 for typeID in marketGroupInfo.types: 1908 ask = self.asksForMyRange.get(typeID, None) 1909 if (not filterNone or ask) and self.ShouldShowType(typeID): 1910 ret.append(typeID) 1911 elif typeID == typePlex and is_global_plex_market_experiment_enabled(): 1912 ret.append(typeID) 1913 1914 return ret 1915 1916 def FilterItemsForGroupPage(self, marketGroupInfo): 1917 filterNone = settings.user.ui.Get('showonlyavailable', 0) 1918 marketSvc = sm.StartService('marketQuote') 1919 ret = [] 1920 marketGroupID = marketGroupInfo.marketGroupID 1921 for typeID in evetypes.GetTypeIDsByMarketGroup(marketGroupID): 1922 if not evetypes.IsPublished(typeID): 1923 continue 1924 ask = self.asksForMyRange.get(typeID, None) 1925 if ask is None and typeID == typePlex and is_global_plex_market_experiment_enabled(): 1926 plexAsks = self._GetPlexAsks() 1927 if typePlex in plexAsks: 1928 self.asksForMyRange[typePlex] = plexAsks[typePlex] 1929 if ask is None and filterNone: 1930 continue 1931 shouldShow = self.ShouldShowType(typeID) 1932 if not shouldShow: 1933 continue 1934 data = utillib.KeyVal() 1935 data.typeID = typeID 1936 data.price = getattr(ask, 'price', 0) 1937 data.qty = getattr(ask, 'volRemaining', 0) 1938 data.fmt_price = FmtISK(data.price) if data.price else localization.GetByLabel('UI/Market/Marketbase/NoneAvailable') 1939 data.fmt_qty = FmtAmt(data.qty) if data.qty else '0' 1940 data.jumps = marketSvc.GetStationDistance(ask.stationID, False) if ask else None 1941 ret.append(data) 1942 1943 return ret 1944 1945 def MeetsRequirements(self, typeID, ship = None, reqTypeSkills = 0, reqTypeCpuPower = 0, hasSkill = 0): 1946 haveReqSkill = True 1947 haveReqPower = True 1948 haveReqCpu = True 1949 haveSkillAlready = True 1950 categoryID = evetypes.GetCategoryID(typeID) 1951 if hasSkill: 1952 isSkill = categoryID == const.categorySkill 1953 if isSkill: 1954 if self.mine.get(typeID, None) is not None: 1955 haveSkillAlready = False 1956 if reqTypeSkills: 1957 requiredSkills = sm.GetService('clientDogmaStaticSvc').GetRequiredSkills(typeID) 1958 if requiredSkills: 1959 for skillID, level in requiredSkills.iteritems(): 1960 if skillID not in self.mine or self.mine[skillID] < level: 1961 haveReqSkill = False 1962 break 1963 1964 else: 1965 haveReqSkill = True 1966 if reqTypeCpuPower: 1967 havePower = 0 1968 haveCpu = 0 1969 isHardware = evetypes.IsCategoryHardwareByCategory(categoryID) 1970 if isHardware: 1971 powerEffect = None 1972 powerIdx = None 1973 powerEffects = [const.effectHiPower, const.effectMedPower, const.effectLoPower] 1974 for effect in dogma.data.get_type_effects(typeID): 1975 if effect.effectID in powerEffects: 1976 powerEffect = dogma.data.get_effect(effect.effectID) 1977 powerIdx = powerEffects.index(effect.effectID) 1978 break 1979 1980 powerLoad = 0 1981 cpuLoad = 0 1982 shipID = eveCfg.GetActiveShip() 1983 if shipID is not None and powerIdx is not None: 1984 dgmAttr = sm.GetService('godma').GetType(typeID) 1985 for attribute in dgmAttr.displayAttributes: 1986 if attribute.attributeID in (const.attributeCpuLoad, const.attributeCpu): 1987 cpuLoad += attribute.value 1988 elif attribute.attributeID in (const.attributePowerLoad, const.attributePower): 1989 powerLoad += attribute.value 1990 1991 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 1992 havePower = dogmaLocation.GetAttributeValue(shipID, const.attributePowerOutput) > powerLoad 1993 haveCpu = dogmaLocation.GetAttributeValue(shipID, const.attributeCpuOutput) > cpuLoad 1994 if powerEffect: 1995 haveReqPower = havePower 1996 haveReqCpu = haveCpu 1997 meetsReq = haveReqSkill and haveReqPower and haveReqCpu and haveSkillAlready 1998 return (meetsReq, 1999 haveReqSkill, 2000 haveReqPower, 2001 haveReqCpu, 2002 haveSkillAlready) 2003 2004 def OnChange_minEdit_market_filter_price(self, value, *args): 2005 newValue = self.ConvertInput(value, 2) 2006 settings.user.ui.Set('minEdit_market_filter_price', newValue) 2007 2008 def OnChange_maxEdit_market_filter_price(self, value, *args): 2009 newValue = self.ConvertInput(value, 2) 2010 settings.user.ui.Set('maxEdit_market_filter_price', newValue) 2011 2012 def OnChange_minEdit_market_filter_jump(self, value, *args): 2013 newValue = self.ConvertInput(value) 2014 settings.user.ui.Set('minEdit_market_filter_jumps', newValue) 2015 2016 def OnChange_maxEdit_market_filter_jumps(self, value, *args): 2017 newValue = self.ConvertInput(value) 2018 settings.user.ui.Set('maxEdit_market_filter_jumps', newValue) 2019 2020 def OnChange_minEdit_market_filter_quantity(self, value, *args): 2021 newValue = self.ConvertInput(value) 2022 settings.user.ui.Set('minEdit_market_filter_quantity', newValue) 2023 2024 def OnChange_maxEdit_market_filter_quantity(self, value, *args): 2025 newValue = self.ConvertInput(value) 2026 settings.user.ui.Set('maxEdit_market_filter_quantity', newValue) 2027 2028 def OnChange_minEdit_market_filters_sellorderdev(self, value, *args): 2029 newValue = self.ConvertInput(value) 2030 settings.user.ui.Set('minEdit_market_filters_sellorderdev', newValue) 2031 2032 def OnChange_maxEdit_market_filters_sellorderdev(self, value, *args): 2033 newValue = self.ConvertInput(value) 2034 settings.user.ui.Set('maxEdit_market_filters_sellorderdev', newValue) 2035 2036 def OnChange_minEdit_market_filters_buyorderdev(self, value, *args): 2037 newValue = self.ConvertInput(value) 2038 settings.user.ui.Set('minEdit_market_filters_buyorderdev', newValue) 2039 2040 def OnChange_maxEdit_market_filters_buyorderdev(self, value, *args): 2041 newValue = self.ConvertInput(value) 2042 settings.user.ui.Set('maxEdit_market_filters_buyorderdev', newValue) 2043 2044 def ConvertInput(self, value, numDecimals = None): 2045 if not value or value == '-': 2046 value = 0 2047 value = self.ConvertToPoint(value, numDecimals) 2048 return value 2049 2050 def FiltersInUse1(self): 2051 filterUsed = False 2052 browseFilters = [(localization.GetByLabel('UI/Market/ShowOnlyAvailable'), 'showonlyavailable'), 2053 (localization.GetByLabel('UI/Market/Marketbase/FilterBySkills'), 'showonlyskillsfor'), 2054 (localization.GetByLabel('UI/Market/Marketbase/FilterByCPUAndPowergrid'), 'showhavecpuandpower'), 2055 (localization.GetByLabel('UI/Market/Marketbase/FilterByUntrainedSkills'), 'shownewskills')] 2056 retBrowse = '' 2057 for label, filter in browseFilters: 2058 if settings.user.ui.Get('%s' % filter, 0): 2059 filterUsed = True 2060 temp = '%s<br>' % label 2061 retBrowse += temp 2062 2063 if retBrowse == '' and not settings.user.ui.Get('showonlyavailable', 0): 2064 temp = '%s<br>' % localization.GetByLabel('UI/Common/Show all') 2065 retBrowse += temp 2066 if retBrowse: 2067 retBrowse = '%s<br>%s' % (localization.GetByLabel('UI/Market/Marketbase/BrowseFilters'), retBrowse) 2068 retBrowse = retBrowse[:-1] 2069 return (retBrowse, filterUsed) 2070 2071 def FiltersInUse2(self, *args): 2072 ret = '' 2073 jumpFilter = [(localization.GetByLabel('UI/Market/Marketbase/Jumps'), 'market_filter_jumps')] 2074 detailFilters = [(localization.GetByLabel('UI/Common/Quantity'), 'market_filter_quantity'), 2075 (localization.GetByLabel('UI/Market/Marketbase/Price'), 'market_filter_price'), 2076 (localization.GetByLabel('UI/Market/Marketbase/SellOrdersDeviation'), 'market_filters_sellorderdev'), 2077 (localization.GetByLabel('UI/Market/Marketbase/BuyOrdersDeviation'), 'market_filters_buyorderdev')] 2078 secFilters = [(localization.GetByLabel('UI/Market/Marketbase/NoHighSecurity'), 'market_filter_highsec'), (localization.GetByLabel('UI/Market/Marketbase/NoLowSecurity'), 'market_filter_lowsec'), (localization.GetByLabel('UI/Market/Marketbase/NoZeroSecurity'), 'market_filter_zerosec')] 2079 retJump = '' 2080 if not does_global_market_apply(self._typeID): 2081 for label, filter in jumpFilter: 2082 if settings.user.ui.Get('%s' % filter, 0): 2083 min = float(GetNumericValueFromSetting('minEdit_%s' % filter)) 2084 max = float(GetNumericValueFromSetting('maxEdit_%s' % filter)) 2085 andUp = False 2086 if min > max: 2087 andUp = True 2088 temp = '%s<br>' % localization.GetByLabel('UI/Market/Marketbase/FilterRangeAndUp', filterType=label, minValue=min) 2089 else: 2090 temp = '%s<br>' % localization.GetByLabel('UI/Market/Marketbase/FilterRangeTo', filterType=label, minValue=min, maxValue=max) 2091 retJump += temp 2092 2093 retDetail = retJump 2094 for label, filter in detailFilters: 2095 if settings.user.ui.Get('%s' % filter, 0): 2096 min = float(GetNumericValueFromSetting('minEdit_%s' % filter)) 2097 max = float(GetNumericValueFromSetting('maxEdit_%s' % filter)) 2098 andUp = False 2099 if min >= max: 2100 andUp = filter not in ('market_filters_sellorderdev', 'market_filters_buyorderdev') 2101 if andUp: 2102 temp = '%s<br>' % localization.GetByLabel('UI/Market/Marketbase/FilterRangeAndUp', filterType=label, minValue=min) 2103 if not andUp: 2104 temp = '%s<br>' % localization.GetByLabel('UI/Market/Marketbase/FilterRangeTo', filterType=label, minValue=min, maxValue=max) 2105 retDetail += temp 2106 2107 if retDetail: 2108 retDetail = '%s<br>%s' % (localization.GetByLabel('UI/Market/Marketbase/DetailFilters'), retDetail) 2109 retSecurity = '' 2110 if not does_global_market_apply(self._typeID): 2111 for label, filter in secFilters: 2112 if not settings.user.ui.Get('%s' % filter, 0): 2113 temp = '%s<br>' % label 2114 retSecurity += temp 2115 2116 if retSecurity: 2117 retSecurity = '%s<br>%s' % (localization.GetByLabel('UI/Market/Marketbase/SecurityFilters'), retSecurity) 2118 for each in [retDetail, retSecurity]: 2119 if each: 2120 ret += '%s<br>' % each 2121 2122 if ret: 2123 ret = ret[:-1] 2124 return ret 2125 2126 def CheckboxRange(self, boxes, container): 2127 for height, label, configname, retval, checked, groupname, numRange, hint, isFloat in boxes: 2128 box = Container(name='checkbox_%s' % configname, parent=container, align=uiconst.TOTOP, padBottom=const.defaultPadding) 2129 rbox = Container(name='checkbox_%s' % configname, parent=box, align=uiconst.TORIGHT, width=180) 2130 cb = RadioButton(text='%s' % label, parent=box, settingsKey=configname, retval=retval, checked=checked, groupname=groupname, callback=self.OnCheckboxChangeSett, align=uiconst.TOPLEFT, height=height, width=150) 2131 if numRange: 2132 funcKey = '%s_min' % configname 2133 fromLabel = localization.GetByLabel('UI/Common/FromNumber') 2134 minText = eveLabel.EveLabelMedium(text=fromLabel, parent=rbox, align=uiconst.CENTERLEFT, state=uiconst.UI_NORMAL) 2135 minSetValue = GetNumericValueFromSetting('minEdit_%s' % configname) 2136 if not isFloat: 2137 minEdit = SingleLineEditInteger(name='minEdit_%s' % configname, setvalue=minSetValue, parent=rbox, left=minText.left + minText.textwidth + const.defaultPadding, top=0, align=uiconst.CENTERLEFT, minValue=numRange[0], maxValue=numRange[1], OnChange=self.OnChangeFuncs[funcKey]) 2138 minEdit.AutoFitToText(FmtAmt(sys.maxint)) 2139 else: 2140 minEdit = SingleLineEditFloat(name='minEdit_%s' % configname, setvalue=minSetValue, parent=rbox, left=minText.left + minText.textwidth + const.defaultPadding, top=0, align=uiconst.CENTERLEFT, minValue=numRange[0], maxValue=numRange[1], decimalPlaces=2, OnChange=self.OnChangeFuncs[funcKey]) 2141 minEdit.AutoFitToText(FmtAmt(float(MAX_ORDER_PRICE), showFraction=2)) 2142 funcKey = '%s_max' % configname 2143 maxText = eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Common/ToNumber'), parent=rbox, left=minEdit.left + minEdit.width + const.defaultPadding, align=uiconst.CENTERLEFT, state=uiconst.UI_NORMAL) 2144 maxSetValue = GetNumericValueFromSetting('maxEdit_%s' % configname) 2145 if not isFloat: 2146 maxEdit = SingleLineEditInteger(name='maxEdit_%s' % configname, setvalue=maxSetValue, parent=rbox, left=maxText.left + maxText.textwidth + const.defaultPadding, top=0, align=uiconst.CENTERLEFT, minValue=numRange[0], maxValue=numRange[1], OnChange=self.OnChangeFuncs[funcKey]) 2147 maxEdit.AutoFitToText(FmtAmt(sys.maxint)) 2148 else: 2149 maxEdit = SingleLineEditFloat(name='maxEdit_%s' % configname, setvalue=maxSetValue, parent=rbox, left=maxText.left + maxText.textwidth + const.defaultPadding, top=0, align=uiconst.CENTERLEFT, minValue=numRange[0], maxValue=numRange[1], decimalPlaces=2, OnChange=self.OnChangeFuncs[funcKey]) 2150 maxEdit.AutoFitToText(FmtAmt(float(MAX_ORDER_PRICE), showFraction=2)) 2151 rbox.width = maxEdit.left + maxEdit.width + const.defaultPadding 2152 box.height = rbox.height = max(cb.height, minEdit.height, minText.height, maxEdit.height, maxText.height) 2153 if hint: 2154 cb.hint = hint 2155 2156 def SetupFilters(self): 2157 settings.user.ui.Set('showonlyavailable', settings.user.ui.Get('showonlyavailable', True)) 2158 settings.user.ui.Set('showonlyskillsfor', settings.user.ui.Get('showonlyskillsfor', False)) 2159 settings.user.ui.Set('showhavecpuandpower', settings.user.ui.Get('showhavecpuandpower', False)) 2160 settings.user.ui.Set('shownewskills', settings.user.ui.Get('shownewskills', False)) 2161 settings.user.ui.Set('market_filter_price', settings.user.ui.Get('market_filter_price', False)) 2162 settings.user.ui.Set('minEdit_market_filter_price', GetNumericValueFromSetting('minEdit_market_filter_price')) 2163 settings.user.ui.Set('maxEdit_market_filter_price', GetNumericValueFromSetting('maxEdit_market_filter_price', 100000)) 2164 settings.user.ui.Set('market_filter_jumps', settings.user.ui.Get('market_filter_jumps', False)) 2165 settings.user.ui.Set('minEdit_market_filter_jumps', GetNumericValueFromSetting('minEdit_market_filter_jumps')) 2166 settings.user.ui.Set('maxEdit_market_filter_jumps', GetNumericValueFromSetting('maxEdit_market_filter_jumps', 20)) 2167 settings.user.ui.Set('market_filter_quantity', settings.user.ui.Get('market_filter_quantity', False)) 2168 settings.user.ui.Set('minEdit_market_filter_quantity', GetNumericValueFromSetting('minEdit_market_filter_quantity')) 2169 settings.user.ui.Set('maxEdit_market_filter_quantity', GetNumericValueFromSetting('maxEdit_market_filter_quantity', 1000)) 2170 settings.user.ui.Set('market_filter_zerosec', settings.user.ui.Get('market_filter_zerosec', True)) 2171 settings.user.ui.Set('market_filter_lowsec', settings.user.ui.Get('market_filter_lowsec', True)) 2172 settings.user.ui.Set('market_filter_highsec', settings.user.ui.Get('market_filter_highsec', True)) 2173 settings.user.ui.Set('market_filters_sellorderdev', settings.user.ui.Get('market_filters_sellorderdev', False)) 2174 settings.user.ui.Set('minEdit_market_filters_sellorderdev', GetNumericValueFromSetting('minEdit_market_filters_sellorderdev')) 2175 settings.user.ui.Set('maxEdit_market_filters_sellorderdev', GetNumericValueFromSetting('maxEdit_market_filters_sellorderdev')) 2176 settings.user.ui.Set('market_filters_buyorderdev', settings.user.ui.Get('market_filters_buyorderdev', False)) 2177 settings.user.ui.Set('minEdit_market_filters_buyorderdev', GetNumericValueFromSetting('minEdit_market_filters_buyorderdev')) 2178 settings.user.ui.Set('maxEdit_market_filters_buyorderdev', GetNumericValueFromSetting('maxEdit_market_filters_buyorderdev')) 2179 settings.user.ui.Set('quickbar', settings.user.ui.Get('quickbar', {})) 2180 settings.user.ui.Set('autorefresh', settings.user.ui.Get('autorefresh', True)) 2181 2182 def AddGroupParent(self, nodedata = None, newitems = 0): 2183 marketGroupID = None 2184 self.parentDictionary = {} 2185 if nodedata: 2186 marketGroupID = nodedata.marketGroupInfo.marketGroupID 2187 firstID = self.InsertQuickbarGroupItem(nodedata.marketGroupInfo.marketGroupName, 0) 2188 self.parentDictionary[marketGroupID] = self.tempLastid 2189 scrolllist = self.AddGroupChildren(nodedata=nodedata) 2190 self.test = QuickbarEntries() 2191 depth = self.test.Load(contentList=scrolllist, maxDepth=5, parentDepth=nodedata.sublevel) 2192 self.test.Close() 2193 return (depth, firstID) 2194 2195 def AddGroupChildren(self, nodedata = None): 2196 scrolllist = [] 2197 if nodedata and nodedata.marketGroupInfo.hasTypes: 2198 parent = self.parentDictionary.get(nodedata.marketGroupInfo.marketGroupID, 0) 2199 for typeID in nodedata.typeIDs: 2200 self.InsertQuickbarGroupItem(typeID, parent) 2201 2202 else: 2203 marketGroupID = None 2204 level = 0 2205 if nodedata: 2206 marketGroupID = nodedata.marketGroupInfo.marketGroupID 2207 level = nodedata.sublevel + 1 2208 grouplist = sm.GetService('marketutils').GetMarketGroups()[marketGroupID] 2209 for marketGroupInfo in grouplist: 2210 if not len(marketGroupInfo.types): 2211 continue 2212 if self.destroyed: 2213 return 2214 items = [ typeID for typeID in marketGroupInfo.types ] 2215 groupID = (marketGroupInfo.marketGroupName, marketGroupInfo.marketGroupID) 2216 data = {'GetSubContent': self.AddGroupChildren, 2217 'id': groupID, 2218 'typeIDs': items, 2219 'marketGroupInfo': marketGroupInfo, 2220 'sublevel': level} 2221 parent = self.parentDictionary.get(marketGroupInfo.parentGroupID, 0) 2222 self.InsertQuickbarGroupItem(marketGroupInfo.marketGroupName, parent) 2223 self.parentDictionary[marketGroupInfo.marketGroupID] = self.tempLastid 2224 scrolllist.append(((marketGroupInfo.hasTypes, marketGroupInfo.marketGroupName.lower()), GetFromClass(QuickbarGroup, data))) 2225 2226 return scrolllist 2227 2228 def InsertQuickbarGroupItem(self, label, parent, extraText = ''): 2229 self.tempLastid += 1 2230 n = utillib.KeyVal() 2231 n.parent = parent 2232 n.id = self.tempLastid 2233 n.label = label 2234 n.extraText = extraText 2235 self.tempFolders[n.id] = n 2236 return n.id 2237 2238 def ListWnd(self, lst, listtype = None, caption = None, hint = None, ordered = 0, minw = 200, minh = 256, minChoices = 1, maxChoices = 1, initChoices = [], validator = None, isModal = 1, scrollHeaders = [], iconMargin = 0, contentList = None): 2239 if caption is None: 2240 caption = localization.GetByLabel('UI/Market/Marketbase/SelectAFolder') 2241 if not isModal: 2242 SelectFolderWindow.CloseIfOpen() 2243 wnd = SelectFolderWindow.Open(lst=[], listtype=listtype, ordered=ordered, minw=minw, minh=minh, caption=caption, minChoices=minChoices, maxChoices=maxChoices, initChoices=initChoices, validator=validator, scrollHeaders=scrollHeaders, iconMargin=iconMargin) 2244 wnd.scroll.Load(contentList=contentList) 2245 wnd.Error(wnd.GetError(checkNumber=0)) 2246 if hint: 2247 wnd.SetHint('<center>' + hint) 2248 if isModal: 2249 wnd.DefineButtons(uiconst.OKCANCEL) 2250 if wnd.ShowModal() == uiconst.ID_OK: 2251 return wnd.result 2252 else: 2253 return 2254 else: 2255 wnd.DefineButtons(uiconst.CLOSE) 2256 wnd.Maximize() 2257 2258 def ConvertToPoint(self, value, numDigits = 0): 2259 ret = ConvertDecimal(value, ',', '.', numDigits) 2260 if numDigits is not None: 2261 ret = '%.*f' % (numDigits, float(ret)) 2262 return ret 2263 2264 def StoreTypeInHistory(self, typeID): 2265 if len(self.historyData) > 0: 2266 newHistory = self.historyData[:self.historyIdx + 1] 2267 lastTypeID = newHistory[min(self.historyIdx, len(self.historyData) - 1)] 2268 if lastTypeID != typeID: 2269 newHistory.append(typeID) 2270 self.historyIdx += 1 2271 self.historyData = newHistory 2272 else: 2273 self.historyData.append(typeID) 2274 self.historyIdx = 0 2275 self.ChangeBackAndForwardButtons() 2276 2277 def GoBack(self, *args): 2278 if len(self.historyData) > 1 and self.historyIdx > 0: 2279 self.historyIdx = max(0, self.historyIdx - 1) 2280 typeID = self.historyData[min(self.historyIdx, len(self.historyData) - 1)] 2281 marketWnd = RegionalMarket.GetIfOpen() 2282 if marketWnd: 2283 marketWnd.LoadTypeID_Ext(typeID) 2284 2285 def GoForward(self, *args): 2286 if self.historyIdx is None: 2287 return 2288 if len(self.historyData) > self.historyIdx + 1: 2289 self.historyIdx = max(0, self.historyIdx + 1) 2290 typeID = self.historyData[min(self.historyIdx, len(self.historyData) - 1)] 2291 marketWnd = RegionalMarket.GetIfOpen() 2292 if marketWnd: 2293 marketWnd.LoadTypeID_Ext(typeID) 2294 2295 def ChangeBackAndForwardButtons(self): 2296 if self.historyIdx == 0: 2297 self.DisableArrow(self.goBackBtn) 2298 else: 2299 self.EnableArrow(self.goBackBtn) 2300 if self.historyIdx >= len(self.historyData) - 1: 2301 self.DisableArrow(self.goForwardBtn) 2302 else: 2303 self.EnableArrow(self.goForwardBtn) 2304 2305 def DisableArrow(self, btn): 2306 btn.Disable() 2307 2308 def EnableArrow(self, btn): 2309 btn.Enable() 2310 2311 def GetImportMenu(self, menuParent): 2312 hint = GetByLabel('UI/Market/Marketbase/ImportQuickbarFormatHint', typeID=const.typeSpaceshipCommand) 2313 menuParent.AddIconEntry(icon=ACTION_ICON, text=GetByLabel('UI/Market/Marketbase/ImportNewQuickbar'), callback=self.ImportQuickbar, hint=hint) 2314 menuParent.AddIconEntry(icon=ACTION_ICON, text=GetByLabel('UI/Market/Marketbase/ImportQuickbarReplace'), callback=self.ImportQuickbarReplace, hint=hint) 2315 2316 def ImportQuickbarReplace(self): 2317 self.ImportQuickbar(replace=True) 2318 2319 def ImportQuickbar(self, replace = False): 2320 typeIDFinder = sm.GetService('marketutils').GetMarketTypeIDFinder() 2321 quickbarImporter = QuickbarImporter(typeIDFinder) 2322 text = GetClipboardData() 2323 if replace: 2324 lastID = 0 2325 else: 2326 lastID = self.lastid 2327 bundleDict = quickbarImporter.ImportText(text, lastID + 1) 2328 if bundleDict: 2329 quickbar = {} if replace else settings.user.ui.Get('quickbar', {}) 2330 newQuickbarItems = {k:utillib.KeyVal(v) for k, v in bundleDict.iteritems()} 2331 quickbar.update(newQuickbarItems) 2332 settings.user.ui.Set('quickbar', quickbar) 2333 settings.user.ui.Set('quickbar_lastid', max(bundleDict)) 2334 sm.ScatterEvent('OnMarketQuickbarChange') 2335 2336 def GetExportMenu(self, menuParent): 2337 menuParent.AddIconEntry(icon=ACTION_ICON, text=GetByLabel('UI/Market/Marketbase/CopyQuickbarToClipboard'), callback=self.GetExportedQuickbarLocalized) 2338 if self.AreExtraExportOptionsAvailable(): 2339 menuParent.AddIconEntry(icon=ACTION_ICON, text=GetByLabel('UI/Market/Marketbase/CopyQuickbarToClipboardInEnglish'), callback=self.GetExportedQuickbar) 2340 2341 def GetExportedQuickbarLocalized(self): 2342 return self._GetExportedQuickbar(True) 2343 2344 def GetExportedQuickbar(self, *args): 2345 return self._GetExportedQuickbar(False) 2346 2347 def _GetExportedQuickbar(self, isLocalized = True): 2348 quickbar = settings.user.ui.Get('quickbar', {}) 2349 exporter = QuickbarExporter() 2350 exportText = exporter.ExportQuickbarToClipboard(quickbar, isLocalized) 2351 blue.pyos.SetClipboardData(exportText) 2352 2353 def AreExtraExportOptionsAvailable(self): 2354 extraOptions = boot.region != 'optic' and session.languageID != 'EN' 2355 return extraOptions 2356 2357 2358 class MarketGroupEntry(ContainerAutoSize): 2359 default_name = 'MarketGroupEntry' 2360 default_align = uiconst.TOTOP 2361 PADDING_GENERIC = const.defaultPadding * 2 2362 2363 def ApplyAttributes(self, attributes): 2364 ContainerAutoSize.ApplyAttributes(self, attributes) 2365 data = attributes.data 2366 typeID = data.invType 2367 self.topCont = ContainerAutoSize(name='topCont', parent=self, align=uiconst.TOTOP) 2368 typeImage = MarketGroupItemImage(parent=self.topCont, align=uiconst.TOPLEFT, width=64, height=64, state=uiconst.UI_NORMAL) 2369 typeImage.attrs = data.typeImageAttributes 2370 typeImage.typeName = evetypes.GetName(typeID) 2371 typeImage.LoadTypeIcon(typeID) 2372 typeImage.SetOmegaIconState(typeID) 2373 typeNameLabel = eveLabel.EveCaptionMedium(parent=self.topCont, align=uiconst.TOPLEFT, left=typeImage.left + typeImage.width + self.PADDING_GENERIC, text=typeImage.typeName, name='typeNameLabel') 2374 InfoIcon(parent=self.topCont, align=uiconst.TOPLEFT, typeID=typeID, left=typeNameLabel.left + typeNameLabel.width + const.defaultPadding, top=typeNameLabel.top + (typeNameLabel.height - 16) / 2) 2375 RequirementsContainer(parent=self.topCont, align=uiconst.TOPLEFT, top=typeNameLabel.top + typeNameLabel.height + const.defaultPadding, left=typeNameLabel.left, width=200, typeID=typeID) 2376 if typeID == const.typePlex: 2377 PurchaseButton(name='buyPlexButton', parent=self.topCont, align=uiconst.TOPLEFT, top=typeNameLabel.top + typeNameLabel.height + 8, left=typeNameLabel.left, width=70, height=20, fontsize=12, func=lambda *args: uicore.cmd.CmdBuyPlex(logContext=FROM_PLEX_MARKET_GROUP), text=localization.GetByLabel('UI/VirtualGoodsStore/Buttons/BuyPlex')) 2378 combinedDescription = data.bestPrice + '<br><fontsize=16><b>' + data.marketData.fmt_price + '</b></fontsize>' 2379 if data.unitsAvailable: 2380 combinedDescription += '<br>' + data.unitsAvailable 2381 if HasTraits(data.invType): 2382 TraitsContainer(parent=self, typeID=data.invType, align=uiconst.TOTOP, padding=(self.PADDING_GENERIC, 2383 4, 2384 self.PADDING_GENERIC, 2385 self.PADDING_GENERIC)) 2386 elif data.description: 2387 combinedDescription = data.description + '<br><br>' + combinedDescription 2388 eveLabel.Label(parent=self, align=uiconst.TOTOP, padding=(0, 2389 4, 2390 self.PADDING_GENERIC, 2391 0), state=uiconst.UI_NORMAL, name='descriptionLabel', text=combinedDescription) 2392 button_group = ButtonGroup(name='buttonCont', parent=self, align=uiconst.TOTOP, top=16, button_alignment=AxisAlignment.START, density=Density.COMPACT) 2393 Button(parent=button_group, label=localization.GetByLabel('UI/Market/Marketbase/CommandViewDetails'), func=sm.GetService('marketutils').ShowMarketDetails, args=(typeID, None), hint=localization.GetByLabel('Tooltips/Market/MarketGroupsViewDetails'), variant=ButtonVariant.GHOST) 2394 if comparisonUtil.is_comparable(typeID): 2395 Button(parent=button_group, label=localization.GetByLabel('UI/Compare/CompareButton'), func=sm.GetService('menu').CompareType, args=(typeID, None), variant=ButtonVariant.GHOST) 2396 if data.marketData.qty: 2397 buyLabel = localization.GetByLabel('UI/Market/MarketQuote/CommandBuy') 2398 buttonName = 'Buy_Btn' 2399 else: 2400 buyLabel = localization.GetByLabel('UI/Market/Marketbase/CommandPlaceBuyOrder') 2401 buttonName = 'Place Buy Order_Btn' 2402 if data.marketData.qty: 2403 buyHint = localization.GetByLabel('Tooltips/Market/MarketGroupsBuyButton') 2404 else: 2405 buyHint = localization.GetByLabel('Tooltips/Market/MarketGroupsPlaceBuy') 2406 Button(parent=button_group, name=buttonName, label=buyLabel, func=sm.GetService('marketutils').Buy, args=(typeID, None), hint=buyHint, variant=ButtonVariant.NORMAL) 2407 if industryCommon.IsBlueprintCategory(evetypes.GetCategoryID(typeID)): 2408 from eve.client.script.ui.shared.industry.industryWnd import Industry 2409 Button(parent=button_group, label=localization.GetByLabel('UI/Industry/ViewInIndustry'), func=Industry.OpenOrShowBlueprint, args=(None, typeID), variant=ButtonVariant.GHOST) 2410 DividerLine(parent=self, align=uiconst.TOTOP, top=16, padBottom=16) 2411 2412 2413 class MarketData(Container): 2414 __guid__ = 'form.MarketData' 2415 __notifyevents__ = ['OnPathfinderSettingsChange', 'OnSessionChanged'] 2416 2417 def ApplyAttributes(self, attributes): 2418 Container.ApplyAttributes(self, attributes) 2419 self.name = 'marketQuote' 2420 self.caption = 'Market Data' 2421 self.prefs = 'marketquote' 2422 self.invType = None 2423 self.loading = None 2424 self.scrollHeight = 0 2425 self.allMyOrderIDs = set() 2426 self.buyheadersPointers = {localization.GetByLabel('UI/Market/Marketbase/Jumps'): pConst.UNIQUE_NAME_MARKET_SELLERS_JUMP_COL, 2427 localization.GetByLabel('UI/Common/Quantity'): pConst.UNIQUE_NAME_MARKET_SELLERS_QTY_COL, 2428 localization.GetByLabel('UI/Market/Marketbase/Price'): pConst.UNIQUE_NAME_MARKET_SELLERS_PRICE_COL} 2429 self.sellheadersPointers = {localization.GetByLabel('UI/Market/Marketbase/Jumps'): pConst.UNIQUE_NAME_MARKET_BUYERS_JUMP_COL, 2430 localization.GetByLabel('UI/Common/Quantity'): pConst.UNIQUE_NAME_MARKET_BUYERS_QTY_COL, 2431 localization.GetByLabel('UI/Market/Marketbase/Price'): pConst.UNIQUE_NAME_MARKET_BUYERS_PRICE_COL} 2432 self.avgSellPrice = None 2433 self.avgBuyPrice = None 2434 self.sr.buyParent = Container(name='buyParent', parent=self, align=uiconst.TOTOP, height=64, uniqueUiName=pConst.UNIQUE_NAME_MARKET_SELLER_LIST) 2435 buyLeft = Container(name='buyLeft', parent=self.sr.buyParent, align=uiconst.TOTOP, height=20) 2436 sellersLabel = localization.GetByLabel('UI/Market/Marketbase/Sellers') 2437 cap = eveLabel.EveCaptionMedium(text=sellersLabel, parent=buyLeft, align=uiconst.TOPLEFT) 2438 buyLeft.height = max(buyLeft.height, cap.textheight) 2439 a = eveLabel.EveLabelSmall(text='', parent=buyLeft, left=24, top=0, state=uiconst.UI_NORMAL, align=uiconst.TOPRIGHT) 2440 a.OnClick = self.BuyClick 2441 a.GetMenu = None 2442 self.buyFiltersActive1 = a 2443 a = eveLabel.EveLabelSmall(text='', parent=buyLeft, left=24, top=14, state=uiconst.UI_NORMAL, align=uiconst.TOPRIGHT) 2444 a.OnClick = self.BuyClick 2445 a.GetMenu = None 2446 self.buyFiltersActive2 = a 2447 self.sr.buyIcon = Sprite(name='buyIcon', parent=buyLeft, width=16, height=16, left=6, top=0, align=uiconst.TOPRIGHT) 2448 self.sr.buyIcon.OnClick = self.BuyClick 2449 self.sr.buyIcon.state = uiconst.UI_HIDDEN 2450 button_group = ButtonGroup(parent=self, align=uiconst.TOBOTTOM, padTop=16, button_alignment=AxisAlignment.END) 2451 Button(parent=button_group, name='Place Buy Order_Btn', label=localization.GetByLabel('UI/Market/Marketbase/CommandPlaceBuyOrder'), func=self.PlaceOrder, args=('buy',), variant=ButtonVariant.PRIMARY, texturePath=eveicon.isk) 2452 Button(parent=button_group, label=localization.GetByLabel('UI/Inventory/ItemActions/FindInContracts'), func=self.FindInContracts, args=()) 2453 Button(parent=button_group, label=localization.GetByLabel('UI/Market/Marketbase/ExportToFile'), func=self.ExportToFile, hint=localization.GetByLabel('Tooltips/Market/MarketDetailsExportFile'), variant=ButtonVariant.GHOST) 2454 divider = Divider(name='divider', parent=self, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, height=16, show_line=True) 2455 divider.Startup(self.sr.buyParent, 'height', 'y', 64, self.scrollHeight) 2456 divider.OnSizeChanged = self.OnDetailScrollSizeChanged 2457 self.sr.divider = divider 2458 self.sr.buyscroll = eveScroll.Scroll(name='buyscroll', parent=self.sr.buyParent, rowPadding=1) 2459 self.sr.buyscroll.multiSelect = 0 2460 self.sr.buyscroll.smartSort = 1 2461 self.sr.buyscroll.ignoreHeaderWidths = 1 2462 self.sr.buyscroll.sr.id = '%sBuyScroll' % self.prefs 2463 self.sr.buyscroll.OnColumnChanged = self.OnBuyColumnChanged 2464 self.sr.buyscroll.SetDefaultSmartSorting(GetByLabel('UI/Market/MarketQuote/headerPrice'), SortDirection.ASCENDING, self._get_buy_headers(self.invType)) 2465 Container(name='divider', align=uiconst.TOTOP, height=const.defaultPadding, parent=self) 2466 self.sr.sellParent = Container(name='sellParent', parent=self, align=uiconst.TOALL, uniqueUiName=pConst.UNIQUE_NAME_MARKET_BUYER_LIST) 2467 sellLeft = Container(name='sellLeft', parent=self.sr.sellParent, align=uiconst.TOTOP, height=20) 2468 buyersLabel = localization.GetByLabel('UI/Market/Marketbase/Buyers') 2469 cap = eveLabel.EveCaptionMedium(text=buyersLabel, parent=sellLeft, align=uiconst.TOPLEFT) 2470 sellLeft.height = max(sellLeft.height, cap.textheight) 2471 a = eveLabel.EveLabelSmall(text='', parent=sellLeft, left=24, top=0, align=uiconst.TOPRIGHT, state=uiconst.UI_NORMAL) 2472 a.OnClick = self.SellClick 2473 a.GetMenu = None 2474 self.sellFiltersActive1 = a 2475 a = eveLabel.EveLabelSmall(text='', parent=sellLeft, left=24, top=14, state=uiconst.UI_NORMAL, align=uiconst.TOPRIGHT) 2476 a.OnClick = self.SellClick 2477 a.GetMenu = None 2478 self.sellFiltersActive2 = a 2479 self.sr.sellIcon = Sprite(name='sellIcon', parent=sellLeft, width=16, height=16, left=6, top=0, align=uiconst.TOPRIGHT) 2480 self.sr.sellIcon.OnClick = self.SellClick 2481 self.sr.sellIcon.state = uiconst.UI_HIDDEN 2482 self.sr.sellscroll = eveScroll.Scroll(name='sellscroll', parent=self.sr.sellParent, rowPadding=1) 2483 self.sr.sellscroll.multiSelect = 0 2484 self.sr.sellscroll.smartSort = 1 2485 self.sr.sellscroll.ignoreHeaderWidths = 1 2486 self.sr.sellscroll.sr.id = '%sSellScroll' % self.prefs 2487 self.sr.sellscroll.OnColumnChanged = self.OnSellColumnChanged 2488 self.sr.sellscroll.SetDefaultSmartSorting(GetByLabel('UI/Market/MarketQuote/headerPrice'), SortDirection.DESCENDING, self._get_sell_headers(self.invType)) 2489 self._OnResize() 2490 sm.RegisterNotify(self) 2491 self.inited = 1 2492 self.sr.buy_ActiveFilters = 1 2493 self.sr.sell_ActiveFilters = 1 2494 2495 def _GetButtonDataForExportToFile(self): 2496 return (localization.GetByLabel('UI/Market/Marketbase/ExportToFile'), 2497 self.ExportToFile, 2498 (), 2499 84, 2500 False, 2501 False, 2502 False, 2503 localization.GetByLabel('Tooltips/Market/MarketDetailsExportFile'), 2504 None, 2505 Button, 2506 'ExportToFileButton') 2507 2508 def _GetButtonDataForPlaceOrder(self): 2509 return (localization.GetByLabel('UI/Market/Marketbase/CommandPlaceBuyOrder'), 2510 self.PlaceOrder, 2511 ('buy',), 2512 84, 2513 False, 2514 False, 2515 False, 2516 localization.GetByLabel('Tooltips/Market/MarketDetailsPlaceBuyOrder'), 2517 None, 2518 Button, 2519 'Place Buy Order_Btn') 2520 2521 def OnDetailScrollSizeChanged(self): 2522 h = self.sr.buyParent.height 2523 absHeight = self.absoluteBottom - self.absoluteTop 2524 if h > absHeight - self.height - 64: 2525 h = absHeight - self.height - 64 2526 ratio = float(h) / absHeight 2527 settings.user.ui.Set('detailScrollHeight', ratio) 2528 self._OnResize() 2529 return 2530 ratio = float(h) / absHeight 2531 settings.user.ui.Set('detailScrollHeight', ratio) 2532 2533 def SellClick(self, *args): 2534 self.sr.sell_ActiveFilters = not self.sr.sell_ActiveFilters 2535 self.Reload('sell') 2536 2537 def BuyClick(self, *args): 2538 self.sr.buy_ActiveFilters = not self.sr.buy_ActiveFilters 2539 self.Reload('buy') 2540 2541 def ExportToFile(self, *args): 2542 if not self.invType: 2543 return 2544 DumpOrdersForType(self.invType) 2545 2546 def OnPathfinderSettingsChange(self, *args): 2547 self.ReloadType() 2548 2549 def OnSessionChanged(self, isremote, session, change): 2550 if 'solarsystemid' in change: 2551 self.ReloadType() 2552 2553 def _OnResize(self, *args): 2554 if self and not self.destroyed and self.sr.buyParent: 2555 self.scrollHeight = self.absoluteBottom - self.absoluteTop - 34 - 64 2556 height = (self.absoluteBottom - self.absoluteTop - 46) / 2 2557 absHeight = self.absoluteBottom - self.absoluteTop 2558 ratio = settings.user.ui.Get('detailScrollHeight', 0.5) 2559 h = int(ratio * absHeight) 2560 if h > self.scrollHeight: 2561 h = self.scrollHeight 2562 self.sr.buyParent.height = max(64, h) 2563 self.sr.divider.max = self.scrollHeight 2564 2565 def OnBuyColumnChanged(self, tabstops): 2566 if self.loading != 'buy': 2567 self.Reload('buy') 2568 2569 def OnSellColumnChanged(self, tabstops): 2570 if self.loading != 'sell': 2571 self.Reload('sell') 2572 2573 def PlaceOrder(self, what, *args): 2574 if not self.invType: 2575 prompt_player_fsd_dialog('CustomNotify', {'notify': localization.GetByLabel('UI/Market/Marketbase/NoTypeToBuy')}) 2576 return 2577 if what == 'buy': 2578 sm.GetService('marketutils').Buy(self.invType, placeOrder=True) 2579 elif what == 'sell': 2580 uicore.cmd.OpenAssets() 2581 2582 def FindInContracts(self): 2583 sm.GetService('contracts').FindRelated(self.invType, None, None, None, None, None) 2584 2585 def Reload(self, what): 2586 records = self.sr.Get('%sItems' % what, None) 2587 scrollList = [] 2588 scroll = self.sr.Get('%sscroll' % what, None) 2589 self.loading = what 2590 if what == 'sell': 2591 headers = self._get_sell_headers(self.invType) 2592 columnNameAndPointersDict = self.sellheadersPointers 2593 else: 2594 headers = self._get_buy_headers(self.invType) 2595 columnNameAndPointersDict = self.buyheadersPointers 2596 marketUtil = sm.GetService('marketutils') 2597 marketQuoteSvc = sm.GetService('marketQuote') 2598 funcs = marketUtil.GetFuncMaps() 2599 2600 def IsOrderASellWithinReach(order): 2601 if what != 'sell': 2602 return False 2603 dockedLocationID = session.stationid or session.structureid 2604 if marketQuoteSvc.SkipBidDueToStructureRestrictions(order, dockedLocationID): 2605 return False 2606 if does_global_market_apply(order.typeID): 2607 return True 2608 if order.jumps <= order.range: 2609 return True 2610 if session.stationid and order.range == -1 and order.stationID == session.stationid: 2611 return True 2612 if session.solarsystemid and order.jumps == 0: 2613 return True 2614 return False 2615 2616 usingFilters = self.GetFilters2()[0] 2617 foundCounter = 0 2618 destPathList = sm.GetService('starmap').GetDestinationPath() 2619 if self.invType and records: 2620 dataList = [] 2621 scroll.sr.headers = headers 2622 visibleHeaders = scroll.GetColumns() 2623 accumPrice = 0 2624 count = 0 2625 hasMarker = False 2626 for order in records[0]: 2627 data = utillib.KeyVal() 2628 data.label = '' 2629 data.typeID = order.typeID 2630 data.order = order 2631 data.mode = what 2632 data.inMyPath = self._IsInMyPath(destPathList, order.solarSystemID, order.stationID) 2633 accumPrice += order.price * order.volRemaining 2634 count += order.volRemaining 2635 data.flag = IsOrderASellWithinReach(order) 2636 data.markAsMine = order.orderID in self.allMyOrderIDs 2637 if data.flag or data.markAsMine or data.inMyPath: 2638 hasMarker = True 2639 expires = order.issueDate + order.duration * const.DAY - blue.os.GetWallclockTime() 2640 if expires < 0: 2641 continue 2642 for header in visibleHeaders: 2643 header = StripTags(header, stripOnly=['localized']) 2644 funcName = funcs.get(header, None) 2645 if funcName and hasattr(marketUtil, funcName): 2646 getattr(marketUtil, funcName, None)(order, data) 2647 else: 2648 log.LogWarn('Unsupported header in record', header, order) 2649 data.label += '###<t>' 2650 2651 self.SetDataValues(order, data) 2652 data.label = data.label[:-3] 2653 dataList.append(data) 2654 2655 avg = None 2656 if count > 0: 2657 avg = round(float(accumPrice / count), 2) 2658 if what == 'sell': 2659 self.avgSellPrice = avg 2660 else: 2661 self.avgBuyPrice = avg 2662 for data in dataList: 2663 if self.ApplyDetailFilters(data, self.sr.Get('%s_ActiveFilters' % what, None)): 2664 data.isLabelOffset = hasMarker 2665 scrollList.append(GetFromClass(MarketOrder, data)) 2666 else: 2667 foundCounter += 1 2668 2669 hintText = '' 2670 if not scrollList: 2671 if self.invType: 2672 if (usingFilters or settings.user.ui.Get('market_filters_%sorderdev' % ['buy', 'sell'][what == 'buy'], 0)) and self.sr.Get('%s_ActiveFilters' % what, None): 2673 hintText = localization.GetByLabel('UI/Market/Marketbase/NoOrdersMatched') 2674 else: 2675 hintText = localization.GetByLabel('UI/Market/Orders/NoOrdersFound') 2676 else: 2677 hintText = localization.GetByLabel('UI/Market/Marketbase/NoTypeToBuy') 2678 self.sr.filtersText.text = '' 2679 self.sr.filtersText.hint = '' 2680 scroll.Load(contentList=scrollList, headers=headers, noContentHint=hintText) 2681 pConst.SetUniqueNamesForColumns(scroll, columnNameAndPointersDict) 2682 if what == 'buy': 2683 if usingFilters or settings.user.ui.Get('market_filters_sellorderdev', 0): 2684 if self.sr.buy_ActiveFilters: 2685 text1 = localization.GetByLabel('UI/Market/Marketbase/AdditionalEntriesFound', foundCounter=foundCounter) 2686 text2 = localization.GetByLabel('UI/Market/Marketbase/TurnFiltersOff') 2687 else: 2688 text1 = localization.GetByLabel('UI/Market/Marketbase/TurnFiltersOn') 2689 text2 = '' 2690 self.buyFiltersActive1.text = text1 2691 self.buyFiltersActive2.text = text2 2692 self.sr.buyIcon.state = uiconst.UI_NORMAL 2693 self.SetFilterIcon2(self.sr.buyIcon, on=bool(self.sr.buy_ActiveFilters)) 2694 else: 2695 self.buyFiltersActive1.text = '' 2696 self.buyFiltersActive2.text = '' 2697 self.sr.buyIcon.state = uiconst.UI_HIDDEN 2698 if what == 'sell': 2699 if usingFilters or settings.user.ui.Get('market_filters_buyorderdev', 0): 2700 if self.sr.sell_ActiveFilters: 2701 text1 = localization.GetByLabel('UI/Market/Marketbase/AdditionalEntriesFound', foundCounter=foundCounter) 2702 text2 = localization.GetByLabel('UI/Market/Marketbase/TurnFiltersOff') 2703 else: 2704 text1 = localization.GetByLabel('UI/Market/Marketbase/TurnFiltersOn') 2705 text2 = '' 2706 self.sellFiltersActive1.text = text1 2707 self.sellFiltersActive2.text = text2 2708 self.sr.sellIcon.state = uiconst.UI_NORMAL 2709 self.SetFilterIcon2(self.sr.sellIcon, on=bool(self.sr.sell_ActiveFilters)) 2710 else: 2711 self.sellFiltersActive1.text = '' 2712 self.sellFiltersActive2.text = '' 2713 self.sr.sellIcon.state = uiconst.UI_HIDDEN 2714 self.loading = None 2715 2716 def _IsInMyPath(self, path, solarsystemID, locationID): 2717 if solarsystemID in path: 2718 return True 2719 if locationID in path: 2720 return True 2721 if not eveCfg.IsDocked() and solarsystemID == session.solarsystemid2: 2722 return True 2723 return False 2724 2725 def SetFilterIcon2(self, icon, on, *args): 2726 if on: 2727 iconNo = 'ui_38_16_205' 2728 else: 2729 iconNo = 'ui_38_16_204' 2730 icon.LoadIcon(iconNo) 2731 2732 def SetDataValues(self, record, data): 2733 data.Set('filter_Price', record.price) 2734 filterJumps = record.jumps 2735 if record.jumps == 0: 2736 filterJumps = -1 2737 data.Set('filter_Jumps', filterJumps) 2738 data.Set('filter_Quantity', int(record.volRemaining)) 2739 2740 def GetFilters2(self): 2741 self.filter_jumps_min = int(GetNumericValueFromSetting('minEdit_market_filter_jumps')) 2742 self.filter_jumps_max = int(GetNumericValueFromSetting('maxEdit_market_filter_jumps')) 2743 if self.filter_jumps_min == None or self.filter_jumps_min == '': 2744 self.filter_jumps_min = 0 2745 if self.filter_jumps_max == None or self.filter_jumps_max == '': 2746 self.filter_jumps_max = INFINITY 2747 if self.filter_jumps_min > self.filter_jumps_max: 2748 self.filter_jumps_max = INFINITY 2749 self.filter_quantity_min = int(GetNumericValueFromSetting('minEdit_market_filter_quantity')) 2750 self.filter_quantity_max = int(GetNumericValueFromSetting('maxEdit_market_filter_quantity')) 2751 if self.filter_quantity_min == None or self.filter_quantity_min == '': 2752 self.filter_quantity_min = 0 2753 if self.filter_quantity_max == None or self.filter_quantity_max == '': 2754 self.filter_quantity_max = INFINITY 2755 if self.filter_quantity_min >= self.filter_quantity_max: 2756 self.filter_quantity_max = INFINITY 2757 self.filter_price_min = float(GetNumericValueFromSetting('minEdit_market_filter_price')) 2758 self.filter_price_max = float(GetNumericValueFromSetting('maxEdit_market_filter_price')) 2759 if self.filter_price_min == None or self.filter_price_min == '': 2760 self.filter_price_min = 0 2761 if self.filter_price_max == None or self.filter_price_max == '': 2762 self.filter_price_max = INFINITY 2763 if self.filter_price_min >= self.filter_price_max: 2764 self.filter_price_max = INFINITY 2765 self.ignore_sellorder_min = GetNumericValueFromSetting('minEdit_market_filters_sellorderdev') 2766 if self.ignore_sellorder_min == None or self.ignore_sellorder_min == '': 2767 self.ignore_sellorder_min = 0 2768 self.ignore_sellorder_max = GetNumericValueFromSetting('maxEdit_market_filters_sellorderdev') 2769 if self.ignore_sellorder_max == None or self.ignore_sellorder_max == '': 2770 self.ignore_sellorder_max = 0 2771 self.ignore_buyorder_min = GetNumericValueFromSetting('minEdit_market_filters_buyorderdev') 2772 if self.ignore_buyorder_min == None or self.ignore_buyorder_min == '': 2773 self.ignore_buyorder_min = 0 2774 self.ignore_buyorder_max = GetNumericValueFromSetting('maxEdit_market_filters_buyorderdev') 2775 if self.ignore_buyorder_max == None or self.ignore_buyorder_max == '': 2776 self.ignore_buyorder_max = 0 2777 filters = [settings.user.ui.Get('market_filter_jumps', 0), 2778 settings.user.ui.Get('market_filter_quantity', 0), 2779 settings.user.ui.Get('market_filter_price', 0), 2780 not settings.user.ui.Get('market_filter_zerosec', 0), 2781 not settings.user.ui.Get('market_filter_highsec', 0), 2782 not settings.user.ui.Get('market_filter_lowsec', 0)] 2783 usingFilters = False 2784 for each in filters: 2785 if each: 2786 usingFilters = True 2787 break 2788 2789 return [usingFilters, 2790 self.filter_jumps_min, 2791 self.filter_jumps_max, 2792 self.filter_quantity_min, 2793 self.filter_quantity_max, 2794 self.filter_price_min, 2795 self.filter_price_max, 2796 self.ignore_sellorder_min, 2797 self.ignore_sellorder_max, 2798 self.ignore_buyorder_min, 2799 self.ignore_buyorder_max] 2800 2801 def ApplyDetailFilters(self, data, activeFilters = 1): 2802 if not activeFilters: 2803 return True 2804 if not does_global_market_apply(self.invType): 2805 if settings.user.ui.Get('market_filter_jumps', 0): 2806 if data.filter_Jumps: 2807 if self.filter_jumps_min > data.filter_Jumps or self.filter_jumps_max < data.filter_Jumps: 2808 if not (self.filter_jumps_min == 0 and data.filter_Jumps == -1): 2809 return False 2810 if settings.user.ui.Get('market_filter_quantity', 0): 2811 if data.filter_Quantity: 2812 if self.filter_quantity_min > data.filter_Quantity or self.filter_quantity_max < data.filter_Quantity: 2813 return False 2814 if settings.user.ui.Get('market_filter_price', 0): 2815 if data.filter_Price: 2816 if self.filter_price_min > data.filter_Price or self.filter_price_max < data.filter_Price: 2817 return False 2818 if not does_global_market_apply(self.invType): 2819 secClass = sm.GetService('securitySvc').get_modified_security_class(data.order.solarSystemID) 2820 if is_zero_sec(secClass): 2821 if not settings.user.ui.Get('market_filter_zerosec', 0): 2822 return False 2823 elif is_high_sec_or_higher(secClass): 2824 if not settings.user.ui.Get('market_filter_highsec', 0): 2825 return False 2826 elif not settings.user.ui.Get('market_filter_lowsec', 0): 2827 return False 2828 if data.filter_Price: 2829 if settings.user.ui.Get('market_filters_sellorderdev', 0) and data.mode == 'buy': 2830 if self.avgBuyPrice: 2831 percentage = (data.filter_Price - self.avgBuyPrice) / self.avgBuyPrice 2832 if float(self.ignore_sellorder_max) < percentage * 100 or float(self.ignore_sellorder_min) > percentage * 100: 2833 return False 2834 if settings.user.ui.Get('market_filters_buyorderdev', 0) and data.mode == 'sell': 2835 if self.avgSellPrice: 2836 percentage = (data.filter_Price - self.avgSellPrice) / self.avgSellPrice 2837 if float(self.ignore_buyorder_max) < percentage * 100 or float(self.ignore_buyorder_min) > percentage * 100: 2838 return False 2839 return True 2840 2841 def LoadType(self, invType): 2842 self.invType = invType 2843 self.ReloadType() 2844 2845 def OnReload(self): 2846 self.ReloadType() 2847 2848 def GetInvTypeID(self): 2849 return self.invType 2850 2851 def ReloadType(self, *args): 2852 if self.invType: 2853 self.sr.sellscroll.Load(contentList=[], fixedEntryHeight=18, headers=self._get_sell_headers(self.invType)) 2854 self.sr.buyscroll.Load(contentList=[], fixedEntryHeight=18, headers=self._get_buy_headers(self.invType)) 2855 self.sr.sellscroll.ShowHint(localization.GetByLabel('UI/Market/Marketbase/FetchingOrders')) 2856 self.sr.buyscroll.ShowHint(localization.GetByLabel('UI/Market/Marketbase/FetchingOrders')) 2857 self.sr.buyItems, self.sr.sellItems = sm.GetService('marketQuote').GetOrders(self.invType) 2858 if settings.user.ui.Get('hilitemyorders', True): 2859 self.allMyOrderIDs = {order.orderID for order in sm.GetService('marketQuote').GetMyOrders()} 2860 else: 2861 self.allMyOrderIDs = set() 2862 self.Reload('buy') 2863 self.Reload('sell') 2864 else: 2865 self.sr.sellscroll.Load(contentList=[], fixedEntryHeight=18) 2866 self.sr.buyscroll.Load(contentList=[], fixedEntryHeight=18) 2867 2868 @staticmethod 2869 def _get_buy_headers(type_id): 2870 if not should_show_location_info(type_id): 2871 headers = [localization.GetByLabel('UI/Common/Quantity'), localization.GetByLabel('UI/Market/Marketbase/Price'), localization.GetByLabel('UI/Market/Marketbase/ExpiresIn')] 2872 else: 2873 headers = [localization.GetByLabel('UI/Market/Marketbase/Jumps'), 2874 localization.GetByLabel('UI/Common/Quantity'), 2875 localization.GetByLabel('UI/Market/Marketbase/Price'), 2876 localization.GetByLabel('UI/Common/Location'), 2877 localization.GetByLabel('UI/Market/Marketbase/ExpiresIn')] 2878 if should_show_region(): 2879 headers.append(localization.GetByLabel('UI/Common/LocationTypes/Region')) 2880 return headers 2881 2882 @staticmethod 2883 def _get_sell_headers(type_id): 2884 if not should_show_location_info(type_id): 2885 headers = [localization.GetByLabel('UI/Common/Quantity'), 2886 localization.GetByLabel('UI/Market/Marketbase/Price'), 2887 localization.GetByLabel('UI/Market/MarketQuote/HeaderMinVolumn'), 2888 localization.GetByLabel('UI/Market/Marketbase/ExpiresIn')] 2889 else: 2890 headers = [localization.GetByLabel('UI/Market/Marketbase/Jumps'), 2891 localization.GetByLabel('UI/Common/Quantity'), 2892 localization.GetByLabel('UI/Market/Marketbase/Price'), 2893 localization.GetByLabel('UI/Common/Location'), 2894 localization.GetByLabel('UI/Common/Range'), 2895 localization.GetByLabel('UI/Market/MarketQuote/HeaderMinVolumn'), 2896 localization.GetByLabel('UI/Market/Marketbase/ExpiresIn')] 2897 if should_show_region(): 2898 headers.append(localization.GetByLabel('UI/Common/LocationTypes/Region')) 2899 return headers 2900 2901 2902 class QuickbarEntries(Container): 2903 __guid__ = 'xtriui.QuickbarEntries' 2904 __nonpersistvars__ = [] 2905 2906 def ApplyAttributes(self, attributes): 2907 Container.ApplyAttributes(self, attributes) 2908 self.sr.nodes = [] 2909 self.tooDeep = False 2910 2911 def __Load(self, contentList = [], maxDepth = 99, parentDepth = 0): 2912 if self.destroyed: 2913 return 2914 self.sr.nodes = [] 2915 self.maxDepth = maxDepth 2916 self.parentDepth = parentDepth 2917 self.depth = 0 2918 self.AddEntries(0, contentList) 2919 if self.destroyed: 2920 return 2921 return [0, self.depth - parentDepth][bool(self.depth)] 2922 2923 Load = LoadContent = __Load 2924 2925 def AddEntry(self, idx, entry, update = 0, isSub = 0, fromW = None): 2926 _idx = idx 2927 if idx == -1: 2928 idx = len(self.GetNodes()) 2929 entry.idx = idx 2930 if not self or not getattr(self, 'sr', None): 2931 return 2932 self.ReloadEntry(entry) 2933 return entry 2934 2935 def ReloadEntry(self, entry): 2936 if entry.id and entry.GetSubContent: 2937 self.depth = max(self.depth, entry.sublevel) 2938 subcontent = entry.GetSubContent(entry) 2939 if self.destroyed: 2940 return 2941 self.AddEntries(entry.idx + 1, subcontent, entry) 2942 2943 def AddEntries(self, fromIdx, entriesData, parentEntry = None): 2944 if self.parentDepth > self.maxDepth: 2945 self.tooDeep = True 2946 return 2947 if fromIdx == -1: 2948 fromIdx = len(self.GetNodes()) 2949 isSub = 0 2950 if parentEntry: 2951 isSub = getattr(parentEntry, 'sublevel', 0) + 1 2952 entries = [] 2953 idx = fromIdx 2954 for crap, data in entriesData: 2955 newentry = self.AddEntry(idx, data, isSub=isSub) 2956 if newentry is None: 2957 continue 2958 idx = newentry.idx + 1 2959 entries.append(newentry) 2960 2961 if self.destroyed: 2962 return 2963 2964 def _OnClose(self): 2965 for each in self.GetNodes(): 2966 each.scroll = None 2967 each.data = None 2968 2969 self.sr.nodes = [] 2970 2971 def GetNodes(self): 2972 return self.sr.nodes 2973 2974 2975 class SelectFolderWindow(ListWindow): 2976 default_windowID = 'SelectFolderWindow' 2977 2978 def GetError(self, checkNumber = 1): 2979 result = None 2980 if self.scroll.GetSelected(): 2981 result = [self.scroll.GetSelected()[0].id[1], self.scroll.GetSelected()[0].sublevel] 2982 if hasattr(self, 'customValidator'): 2983 ret = self.customValidator and self.customValidator(result) or '' 2984 if ret: 2985 return ret 2986 try: 2987 if checkNumber: 2988 if result == None: 2989 if self.minChoices == self.maxChoices: 2990 label = localization.GetByLabel('UI/Control/ListWindow/MustSelectError', num=self.minChoices) 2991 else: 2992 label = localization.GetByLabel('UI/Control/ListWindow/SelectTooFewError', num=self.minChoices) 2993 return label 2994 except ValueError as e: 2995 log.LogException() 2996 sys.exc_clear() 2997 return 2998 2999 return '' 3000 3001 def Confirm(self, *etc): 3002 if not self.isModal: 3003 return 3004 self.Error(self.GetError(checkNumber=0)) 3005 if not self.GetError(): 3006 if self.scroll.GetSelected(): 3007 if hasattr(self.scroll.GetSelected()[0], 'id'): 3008 self.result = [self.scroll.GetSelected()[0].id[1], self.scroll.GetSelected()[0].sublevel] 3009 self.SetModalResult(uiconst.ID_OK) 3010 3011 def Error(self, error): 3012 ep = self.GetChild('errorParent') 3013 ep.Flush() 3014 if error: 3015 t = eveLabel.EveLabelMedium(text='<center>' + error, top=-3, parent=ep, width=self.minsize[0] - 32, state=uiconst.UI_DISABLED, color=(1.0, 0.0, 0.0, 1.0), align=uiconst.CENTER) 3016 ep.state = uiconst.UI_DISABLED 3017 ep.height = t.height + 8 3018 else: 3019 ep.state = uiconst.UI_HIDDEN 3020 3021 3022 class MarketGroupItemImage(Image): 3023 isDragObject = True 3024 3025 def ApplyAttributes(self, attributes): 3026 super(MarketGroupItemImage, self).ApplyAttributes(attributes) 3027 self.omegaIcon = OmegaCloneOverlayIcon(name='OmegaIcon', parent=self, state=uiconst.UI_DISABLED, align=uiconst.TOALL, opacity=0, origin=ORIGIN_MARKET) 3028 3029 def LoadTypeIcon(self, typeID): 3030 Image.LoadTypeIcon(self) 3031 self.SetOmegaIconState(typeID) 3032 self.typeID = typeID 3033 self.omegaIcon.reason = typeID 3034 self.isUnlockedWithExpertSystem = sm.GetService('skills').IsUnlockedWithExpertSystem(self.typeID) 3035 3036 def GetDragData(self, *args): 3037 return [Bunch(typeID=self.typeID, __guid__='listentry.GenericMarketItem', label=self.typeName, invtype=self.typeID)] 3038 3039 def OnMouseMove(self, *args): 3040 if self.IsBeingDragged(): 3041 self.cursor = self.default_cursor 3042 Container.OnMouseMove(self) 3043 3044 def OnMouseEnter(self, *args): 3045 self.omegaIcon.OnMouseEnter() 3046 if eveCfg.IsPreviewable(self.typeID): 3047 self.cursor = uiconst.UICURSOR_MAGNIFIER 3048 else: 3049 self.cursor = self.default_cursor 3050 if evetypes.GetGroupID(self.typeID) == const.groupSkillInjectors: 3051 sm.ScatterEvent('OnSkillInjectorMouseEnter', self.typeID) 3052 3053 def OnMouseExit(self, *args): 3054 self.omegaIcon.OnMouseExit() 3055 self.cursor = self.default_cursor 3056 if evetypes.GetGroupID(self.typeID) == const.groupSkillInjectors: 3057 sm.ScatterEvent('OnSkillInjectorMouseExit') 3058 3059 def OnClick(self, *args): 3060 if eveCfg.IsPreviewable(self.typeID): 3061 sm.GetService('preview').PreviewType(self.typeID) 3062 3063 def SetOmegaIconState(self, typeID): 3064 if get_clone_grade_svc().is_restricted_for_alpha(typeID): 3065 self.omegaIcon.SetOpacity(1) 3066 else: 3067 self.omegaIcon.SetOpacity(0) 3068 3069 def LoadTooltipPanel(self, tooltipPanel, *args): 3070 if get_clone_grade_svc().is_restricted(self.typeID): 3071 self.omegaIcon.LoadTooltipPanel(tooltipPanel, args) 3072 else: 3073 tooltipPanel.LoadGeneric1ColumnTemplate() 3074 expertSystems.add_type_unlocked_by_expert_systems(tooltipPanel, self.typeID)