diff --git a/gui/builtinContextMenus/factorReload.py b/gui/builtinContextMenus/factorReload.py index c70028efc..d759734a6 100644 --- a/gui/builtinContextMenus/factorReload.py +++ b/gui/builtinContextMenus/factorReload.py @@ -3,7 +3,6 @@ import gui.mainFrame import gui.globalEvents as GE # noinspection PyPackageRequirements import wx -from gui.bitmap_loader import BitmapLoader from service.fit import Fit from service.settings import ContextMenuSettings @@ -34,4 +33,5 @@ class FactorReload(ContextMenu): sFit = Fit.getInstance() return sFit.serviceFittingOptions["useGlobalForceReload"] + FactorReload.register() diff --git a/gui/builtinContextMenus/priceClear.py b/gui/builtinContextMenus/priceClear.py deleted file mode 100644 index 9afdb0815..000000000 --- a/gui/builtinContextMenus/priceClear.py +++ /dev/null @@ -1,30 +0,0 @@ -from gui.contextMenu import ContextMenu -import gui.mainFrame -# noinspection PyPackageRequirements -import wx -import gui.globalEvents as GE -from service.price import Price -from service.settings import ContextMenuSettings - - -class PriceClear(ContextMenu): - def __init__(self): - self.mainFrame = gui.mainFrame.MainFrame.getInstance() - self.settings = ContextMenuSettings.getInstance() - - def display(self, srcContext, selection): - if not self.settings.get('priceClear'): - return False - - return srcContext in ("priceViewFull", "priceViewMinimal") - - def getText(self, itmContext, selection): - return "Reset Price Cache" - - def activate(self, fullContext, selection, i): - sPrc = Price.getInstance() - sPrc.clearPriceCache() - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) - - -PriceClear.register() diff --git a/gui/builtinContextMenus/priceOptions.py b/gui/builtinContextMenus/priceOptions.py index c9cb7f74a..41736e4bc 100644 --- a/gui/builtinContextMenus/priceOptions.py +++ b/gui/builtinContextMenus/priceOptions.py @@ -1,50 +1,62 @@ +from abc import abstractmethod, ABCMeta + import wx import gui.globalEvents as GE import gui.mainFrame from gui.contextMenu import ContextMenu -from service.settings import PriceMenuSettings +from service.settings import MarketPriceSettings -class PriceOptions(ContextMenu): +class ItemGroupPrice(ContextMenu, metaclass=ABCMeta): + def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() - self.settings = PriceMenuSettings.getInstance() - self.optionList = ["Ship", "Modules", "Drones", "Cargo", "Character"] + self.settings = MarketPriceSettings.getInstance() + + @property + @abstractmethod + def label(self): + raise NotImplementedError() + + @property + @abstractmethod + def optionName(self): + raise NotImplementedError() def display(self, srcContext, selection): return srcContext in ("priceViewFull", "priceViewMinimal") def getText(self, itmContext, selection): - return "Include in total" - - def addOption(self, menu, option): - label = option - id = ContextMenu.nextID() - self.optionIds[id] = option - menuItem = wx.MenuItem(menu, id, label, kind=wx.ITEM_CHECK) - menu.Bind(wx.EVT_MENU, self.handleMode, menuItem) - return menuItem - - def getSubMenu(self, context, selection, rootMenu, i, pitem): - msw = True if "wxMSW" in wx.PlatformInfo else False - self.context = context - self.optionIds = {} - - sub = wx.Menu() - - for option in self.optionList: - menuItem = self.addOption(rootMenu if msw else sub, option) - sub.Append(menuItem) - menuItem.Check(self.settings.get(option.lower())) - - return sub - - def handleMode(self, event): - option = self.optionIds[event.Id] - self.settings.set(option.lower(), event.Int) + return self.label + def activate(self, fullContext, selection, i): + self.settings.set(self.optionName, not self.settings.get(self.optionName)) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + @property + def checked(self): + return self.settings.get(self.optionName) -PriceOptions.register() + +class DronesPrice(ItemGroupPrice): + + label = 'Drones' + optionName = 'drones' + + +class CargoPrice(ItemGroupPrice): + + label = 'Cargo' + optionName = 'cargo' + + +class ImplantBoosterPrice(ItemGroupPrice): + + label = 'Implants && Boosters' + optionName = 'character' + + +DronesPrice.register() +CargoPrice.register() +ImplantBoosterPrice.register() diff --git a/gui/builtinMarketBrowser/itemView.py b/gui/builtinMarketBrowser/itemView.py index 97db645d7..435845662 100644 --- a/gui/builtinMarketBrowser/itemView.py +++ b/gui/builtinMarketBrowser/itemView.py @@ -23,13 +23,12 @@ class ItemView(Display): def __init__(self, parent, marketBrowser): Display.__init__(self, parent) pyfalog.debug("Initialize ItemView") - marketBrowser.Bind(wx.EVT_TREE_SEL_CHANGED, self.selectionMade) + marketBrowser.Bind(wx.EVT_TREE_SEL_CHANGED, self.treeSelectionChanged) self.unfilteredStore = set() self.filteredStore = set() self.recentlyUsedModules = set() self.sMkt = marketBrowser.sMkt - self.searchMode = marketBrowser.searchMode self.sFit = Fit.getInstance() self.marketBrowser = marketBrowser @@ -98,8 +97,11 @@ class ItemView(Display): self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].append(itemID) - def selectionMade(self, event=None): - self.marketBrowser.searchMode = False + def treeSelectionChanged(self, event=None): + self.selectionMade('tree') + + def selectionMade(self, context): + self.marketBrowser.mode = 'normal' # Grab the threeview selection and check if it's fine sel = self.marketView.GetSelection() if sel.IsOk(): @@ -127,26 +129,47 @@ class ItemView(Display): self.updateItemStore(items) # Set toggle buttons / use search mode flag if recently used modules category is selected (in order to have all modules listed and not filtered) - if seldata is not RECENTLY_USED_MODULES: - self.setToggles() - else: - self.marketBrowser.searchMode = True - self.setToggles() + if seldata == RECENTLY_USED_MODULES: + self.marketBrowser.mode = 'recent' - # Update filtered items + self.setToggles() + if context == 'tree' and self.marketBrowser.settings.get('marketMGMarketSelectMode') == 1: + for btn in self.marketBrowser.metaButtons: + if not btn.GetValue(): + btn.setUserSelection(True) self.filterItemStore() def updateItemStore(self, items): self.unfilteredStore = items def filterItemStore(self): + filteredItems = self.filterItems() + if len(filteredItems) == 0 and len(self.unfilteredStore) > 0: + setting = self.marketBrowser.settings.get('marketMGEmptyMode') + # Enable leftmost available + if setting == 1: + for btn in self.marketBrowser.metaButtons: + if btn.IsEnabled() and not btn.userSelected: + btn.setUserSelection(True) + break + filteredItems = self.filterItems() + # Enable all + elif setting == 2: + for btn in self.marketBrowser.metaButtons: + if btn.IsEnabled() and not btn.userSelected: + btn.setUserSelection(True) + filteredItems = self.filterItems() + self.filteredStore = filteredItems + self.update(list(self.filteredStore)) + + def filterItems(self): sMkt = self.sMkt selectedMetas = set() for btn in self.marketBrowser.metaButtons: - if btn.GetValue(): + if btn.userSelected: selectedMetas.update(sMkt.META_MAP[btn.metaName]) - self.filteredStore = sMkt.filterItemsByMeta(self.unfilteredStore, selectedMetas) - self.update(list(self.filteredStore)) + filteredItems = sMkt.filterItemsByMeta(self.unfilteredStore, selectedMetas) + return filteredItems def setToggles(self): metaIDs = set() @@ -169,10 +192,10 @@ class ItemView(Display): realsearch = search.replace("*", "") # Re-select market group if search query has zero length if len(realsearch) == 0: - self.selectionMade() + self.selectionMade('search') return - self.marketBrowser.searchMode = True + self.marketBrowser.mode = 'search' self.sMkt.searchItems(search, self.populateSearch) def clearSearch(self, event=None): @@ -182,14 +205,15 @@ class ItemView(Display): if event: self.marketBrowser.search.Clear() - self.marketBrowser.searchMode = False - self.updateItemStore(set()) - self.setToggles() - self.filterItemStore() + if self.marketBrowser.mode == 'search': + self.marketBrowser.mode = 'normal' + self.updateItemStore(set()) + self.setToggles() + self.filterItemStore() def populateSearch(self, items): # If we're no longer searching, dump the results - if self.marketBrowser.searchMode is False: + if self.marketBrowser.mode != 'search': return self.updateItemStore(items) self.setToggles() @@ -220,7 +244,7 @@ class ItemView(Display): item = self.active[sel] sMkt = self.sMkt - sourceContext = "marketItemGroup" if self.marketBrowser.searchMode is False else "marketItemMisc" + sourceContext = "marketItemMisc" if self.marketBrowser.mode in ("search", "recent") else "marketItemGroup" itemContext = sMkt.getCategoryByItem(item).name menu = ContextMenu.getMenu((item,), (sourceContext, itemContext)) diff --git a/gui/builtinMarketBrowser/marketTree.py b/gui/builtinMarketBrowser/marketTree.py index f6c62732c..e4052356b 100644 --- a/gui/builtinMarketBrowser/marketTree.py +++ b/gui/builtinMarketBrowser/marketTree.py @@ -9,6 +9,7 @@ pyfalog = Logger(__name__) class MarketTree(wx.TreeCtrl): + def __init__(self, parent, marketBrowser): wx.TreeCtrl.__init__(self, parent, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT) pyfalog.debug("Initialize marketTree") @@ -72,7 +73,6 @@ class MarketTree(wx.TreeCtrl): def jump(self, item): """Open market group and meta tab of given item""" - self.marketBrowser.searchMode = False sMkt = self.sMkt mg = sMkt.getMarketGroupByItem(item) @@ -96,4 +96,3 @@ class MarketTree(wx.TreeCtrl): self.Expand(item) self.SelectItem(item) - self.marketBrowser.itemView.selectionMade() diff --git a/gui/builtinMarketBrowser/metaButton.py b/gui/builtinMarketBrowser/metaButton.py index 3d2762232..0603b4313 100644 --- a/gui/builtinMarketBrowser/metaButton.py +++ b/gui/builtinMarketBrowser/metaButton.py @@ -16,7 +16,7 @@ class MetaButton(wx.ToggleButton): def setMetaAvailable(self, isAvailable): self.Enable(isAvailable) # need to also SetValue(False) for windows because Enabled=False AND SetValue(True) looks enabled. - if not isAvailable: + if not isAvailable and "wxMSW" in wx.PlatformInfo: self.SetValue(False) def reset(self): diff --git a/gui/builtinPreferenceViews/__init__.py b/gui/builtinPreferenceViews/__init__.py index 32117a9ec..e3485d555 100644 --- a/gui/builtinPreferenceViews/__init__.py +++ b/gui/builtinPreferenceViews/__init__.py @@ -7,5 +7,6 @@ __all__ = [ "pyfaLoggingPreferences", "pyfaEnginePreferences", "pyfaEsiPreferences", - "pyfaStatViewPreferences"] + "pyfaStatViewPreferences", + "pyfaMarketPreferences"] diff --git a/gui/builtinPreferenceViews/pyfaGeneralPreferences.py b/gui/builtinPreferenceViews/pyfaGeneralPreferences.py index 8b1c0f27a..262b119a0 100644 --- a/gui/builtinPreferenceViews/pyfaGeneralPreferences.py +++ b/gui/builtinPreferenceViews/pyfaGeneralPreferences.py @@ -21,8 +21,6 @@ class PFGeneralPref(PreferenceView): self.openFitsSettings = SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []}) - helpCursor = wx.Cursor(wx.CURSOR_QUESTION_ARROW) - mainSizer = wx.BoxSizer(wx.VERTICAL) self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0) @@ -66,13 +64,9 @@ class PFGeneralPref(PreferenceView): labelSizer.Add(self.cbRackLabels, 0, wx.ALL | wx.EXPAND, 5) mainSizer.Add(labelSizer, 0, wx.LEFT | wx.EXPAND, 30) - self.cbShowTooltip = wx.CheckBox(panel, wx.ID_ANY, "Show tab tooltips", wx.DefaultPosition, wx.DefaultSize, 0) + self.cbShowTooltip = wx.CheckBox(panel, wx.ID_ANY, "Show fitting tab tooltips", wx.DefaultPosition, wx.DefaultSize, 0) mainSizer.Add(self.cbShowTooltip, 0, wx.ALL | wx.EXPAND, 5) - self.cbMarketShortcuts = wx.CheckBox(panel, wx.ID_ANY, "Show market shortcuts", wx.DefaultPosition, - wx.DefaultSize, 0) - mainSizer.Add(self.cbMarketShortcuts, 0, wx.ALL | wx.EXPAND, 5) - self.cbGaugeAnimation = wx.CheckBox(panel, wx.ID_ANY, "Animate gauges", wx.DefaultPosition, wx.DefaultSize, 0) mainSizer.Add(self.cbGaugeAnimation, 0, wx.ALL | wx.EXPAND, 5) @@ -84,38 +78,6 @@ class PFGeneralPref(PreferenceView): wx.DefaultPosition, wx.DefaultSize, 0) mainSizer.Add(self.cbShowShipBrowserTooltip, 0, wx.ALL | wx.EXPAND, 5) - priceSizer = wx.BoxSizer(wx.HORIZONTAL) - - self.stDefaultSystem = wx.StaticText(panel, wx.ID_ANY, "Default Market Prices:", wx.DefaultPosition, wx.DefaultSize, 0) - self.stDefaultSystem.Wrap(-1) - priceSizer.Add(self.stDefaultSystem, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) - self.stDefaultSystem.SetCursor(helpCursor) - self.stDefaultSystem.SetToolTip( - wx.ToolTip('The source you choose will be tried first, but subsequent sources will be used if the preferred ' - 'source fails. The system you choose is absolute and requests will not be made against other systems.')) - - self.chPriceSource = wx.Choice(panel, choices=sorted(Price.sources.keys())) - self.chPriceSystem = wx.Choice(panel, choices=list(Price.systemsList.keys())) - priceSizer.Add(self.chPriceSource, 1, wx.ALL | wx.EXPAND, 5) - priceSizer.Add(self.chPriceSystem, 1, wx.ALL | wx.EXPAND, 5) - - mainSizer.Add(priceSizer, 0, wx.ALL | wx.EXPAND, 0) - - delayTimer = wx.BoxSizer(wx.HORIZONTAL) - - self.stMarketDelay = wx.StaticText(panel, wx.ID_ANY, "Market Search Delay (ms):", wx.DefaultPosition, wx.DefaultSize, 0) - self.stMarketDelay.Wrap(-1) - self.stMarketDelay.SetCursor(helpCursor) - self.stMarketDelay.SetToolTip( - wx.ToolTip('The delay between a keystroke and the market search. Can help reduce lag when typing fast in the market search box.')) - - delayTimer.Add(self.stMarketDelay, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) - - self.intDelay = IntCtrl(panel, max=1000, limited=True) - delayTimer.Add(self.intDelay, 0, wx.ALL, 5) - - mainSizer.Add(delayTimer, 0, wx.ALL | wx.EXPAND, 0) - self.sFit = Fit.getInstance() self.cbGlobalChar.SetValue(self.sFit.serviceFittingOptions["useGlobalCharacter"]) @@ -127,13 +89,9 @@ class PFGeneralPref(PreferenceView): self.cbCompactSkills.SetValue(self.sFit.serviceFittingOptions["compactSkills"] or False) self.cbReopenFits.SetValue(self.openFitsSettings["enabled"]) self.cbShowTooltip.SetValue(self.sFit.serviceFittingOptions["showTooltip"] or False) - self.cbMarketShortcuts.SetValue(self.sFit.serviceFittingOptions["showMarketShortcuts"] or False) self.cbGaugeAnimation.SetValue(self.sFit.serviceFittingOptions["enableGaugeAnimation"]) self.cbOpenFitInNew.SetValue(self.sFit.serviceFittingOptions["openFitInNew"]) - self.chPriceSource.SetStringSelection(self.sFit.serviceFittingOptions["priceSource"]) - self.chPriceSystem.SetStringSelection(self.sFit.serviceFittingOptions["priceSystem"]) self.cbShowShipBrowserTooltip.SetValue(self.sFit.serviceFittingOptions["showShipBrowserTooltip"]) - self.intDelay.SetValue(self.sFit.serviceFittingOptions["marketSearchDelay"]) self.cbGlobalChar.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalCharStateChange) self.cbDefaultCharImplants.Bind(wx.EVT_CHECKBOX, self.OnCBDefaultCharImplantsStateChange) @@ -144,23 +102,15 @@ class PFGeneralPref(PreferenceView): self.cbCompactSkills.Bind(wx.EVT_CHECKBOX, self.onCBCompactSkills) self.cbReopenFits.Bind(wx.EVT_CHECKBOX, self.onCBReopenFits) self.cbShowTooltip.Bind(wx.EVT_CHECKBOX, self.onCBShowTooltip) - self.cbMarketShortcuts.Bind(wx.EVT_CHECKBOX, self.onCBShowShortcuts) self.cbGaugeAnimation.Bind(wx.EVT_CHECKBOX, self.onCBGaugeAnimation) self.cbOpenFitInNew.Bind(wx.EVT_CHECKBOX, self.onCBOpenFitInNew) - self.chPriceSource.Bind(wx.EVT_CHOICE, self.onPricesSourceSelection) - self.chPriceSystem.Bind(wx.EVT_CHOICE, self.onPriceSelection) self.cbShowShipBrowserTooltip.Bind(wx.EVT_CHECKBOX, self.onCBShowShipBrowserTooltip) - self.intDelay.Bind(wx.lib.intctrl.EVT_INT, self.onMarketDelayChange) self.cbRackLabels.Enable(self.sFit.serviceFittingOptions["rackSlots"] or False) panel.SetSizer(mainSizer) panel.Layout() - def onMarketDelayChange(self, event): - self.sFit.serviceFittingOptions["marketSearchDelay"] = self.intDelay.GetValue() - event.Skip() - def onCBGlobalColorBySlot(self, event): # todo: maybe create a SettingChanged event that we can fire, and have other things hook into, instead of having the preference panel itself handle the # updating of things related to settings. @@ -215,9 +165,6 @@ class PFGeneralPref(PreferenceView): def onCBShowTooltip(self, event): self.sFit.serviceFittingOptions["showTooltip"] = self.cbShowTooltip.GetValue() - def onCBShowShortcuts(self, event): - self.sFit.serviceFittingOptions["showMarketShortcuts"] = self.cbMarketShortcuts.GetValue() - def onCBGaugeAnimation(self, event): self.sFit.serviceFittingOptions["enableGaugeAnimation"] = self.cbGaugeAnimation.GetValue() @@ -230,19 +177,5 @@ class PFGeneralPref(PreferenceView): def getImage(self): return BitmapLoader.getBitmap("prefs_settings", "gui") - def onPriceSelection(self, event): - system = self.chPriceSystem.GetString(self.chPriceSystem.GetSelection()) - self.sFit.serviceFittingOptions["priceSystem"] = system - - fitID = self.mainFrame.getActiveFit() - - self.sFit.refreshFit(fitID) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) - event.Skip() - - def onPricesSourceSelection(self, event): - source = self.chPriceSource.GetString(self.chPriceSource.GetSelection()) - self.sFit.serviceFittingOptions["priceSource"] = source - PFGeneralPref.register() diff --git a/gui/builtinPreferenceViews/pyfaMarketPreferences.py b/gui/builtinPreferenceViews/pyfaMarketPreferences.py new file mode 100644 index 000000000..2afd3dcca --- /dev/null +++ b/gui/builtinPreferenceViews/pyfaMarketPreferences.py @@ -0,0 +1,159 @@ +# noinspection PyPackageRequirements +import wx +from wx.lib.intctrl import IntCtrl + +from gui.preferenceView import PreferenceView +from gui.bitmap_loader import BitmapLoader + +import gui.mainFrame +import gui.globalEvents as GE +from service.settings import MarketPriceSettings +from service.fit import Fit +from service.price import Price + + +class PFMarketPref(PreferenceView): + title = "Market & Prices" + + def __init__(self): + self.priceSettings = MarketPriceSettings.getInstance() + + def populatePanel(self, panel): + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.sFit = Fit.getInstance() + + helpCursor = wx.Cursor(wx.CURSOR_QUESTION_ARROW) + mainSizer = wx.BoxSizer(wx.VERTICAL) + + self.stTitle = wx.StaticText(panel, wx.ID_ANY, "Market && Prices", wx.DefaultPosition, wx.DefaultSize, 0) + self.stTitle.Wrap(-1) + self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString)) + + mainSizer.Add(self.stTitle, 0, wx.ALL, 5) + + self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) + mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) + + delayTimer = wx.BoxSizer(wx.HORIZONTAL) + self.stMarketDelay = wx.StaticText(panel, wx.ID_ANY, "Market Search Delay (ms):", wx.DefaultPosition, wx.DefaultSize, 0) + self.stMarketDelay.Wrap(-1) + self.stMarketDelay.SetCursor(helpCursor) + self.stMarketDelay.SetToolTip(wx.ToolTip('The delay between a keystroke and the market search. Can help reduce lag when typing fast in the market search box.')) + delayTimer.Add(self.stMarketDelay, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + self.intDelay = IntCtrl(panel, max=1000, limited=True) + delayTimer.Add(self.intDelay, 0, wx.ALL, 5) + mainSizer.Add(delayTimer, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10) + self.intDelay.SetValue(self.sFit.serviceFittingOptions["marketSearchDelay"]) + self.intDelay.Bind(wx.lib.intctrl.EVT_INT, self.onMarketDelayChange) + + self.cbMarketShortcuts = wx.CheckBox(panel, wx.ID_ANY, "Show market shortcuts", wx.DefaultPosition, wx.DefaultSize, 0) + mainSizer.Add(self.cbMarketShortcuts, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10) + self.cbMarketShortcuts.SetValue(self.sFit.serviceFittingOptions["showMarketShortcuts"] or False) + self.cbMarketShortcuts.Bind(wx.EVT_CHECKBOX, self.onCBShowShortcuts) + + priceSizer = wx.BoxSizer(wx.HORIZONTAL) + self.stDefaultSystem = wx.StaticText(panel, wx.ID_ANY, "Default Market Prices:", wx.DefaultPosition, wx.DefaultSize, 0) + self.stDefaultSystem.Wrap(-1) + priceSizer.Add(self.stDefaultSystem, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + self.stDefaultSystem.SetCursor(helpCursor) + self.stDefaultSystem.SetToolTip(wx.ToolTip( + 'The source you choose will be tried first, but subsequent sources will be used if the preferred source fails. ' + 'The system you choose will also be tried first, and if no data is available, global price will be used.')) + self.chPriceSource = wx.Choice(panel, choices=sorted(Price.sources.keys())) + self.chPriceSystem = wx.Choice(panel, choices=list(Price.systemsList.keys())) + priceSizer.Add(self.chPriceSource, 1, wx.ALL | wx.EXPAND, 5) + priceSizer.Add(self.chPriceSystem, 1, wx.ALL | wx.EXPAND, 5) + mainSizer.Add(priceSizer, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10) + self.chPriceSource.SetStringSelection(self.sFit.serviceFittingOptions["priceSource"]) + self.chPriceSource.Bind(wx.EVT_CHOICE, self.onPricesSourceSelection) + self.chPriceSystem.SetStringSelection(self.sFit.serviceFittingOptions["priceSystem"]) + self.chPriceSystem.Bind(wx.EVT_CHOICE, self.onPriceSelection) + + self.tbTotalPriceBox = wx.StaticBoxSizer(wx.VERTICAL, panel, "Total Price Includes") + self.tbTotalPriceDrones = wx.CheckBox(panel, -1, "Drones", wx.DefaultPosition, wx.DefaultSize, 1) + self.tbTotalPriceDrones.SetValue(self.priceSettings.get("drones")) + self.tbTotalPriceDrones.Bind(wx.EVT_CHECKBOX, self.OnTotalPriceDroneChange) + self.tbTotalPriceBox.Add(self.tbTotalPriceDrones, 0, wx.LEFT | wx.RIGHT | wx.TOP, 5) + self.tbTotalPriceCargo = wx.CheckBox(panel, -1, "Cargo", wx.DefaultPosition, wx.DefaultSize, 1) + self.tbTotalPriceCargo.SetValue(self.priceSettings.get("cargo")) + self.tbTotalPriceCargo.Bind(wx.EVT_CHECKBOX, self.OnTotalPriceCargoChange) + self.tbTotalPriceBox.Add(self.tbTotalPriceCargo, 0, wx.LEFT | wx.RIGHT, 5) + self.tbTotalPriceCharacter = wx.CheckBox(panel, -1, "Implants && Boosters", wx.DefaultPosition, wx.DefaultSize, 1) + self.tbTotalPriceCharacter.SetValue(self.priceSettings.get("character")) + self.tbTotalPriceCharacter.Bind(wx.EVT_CHECKBOX, self.OnTotalPriceCharacterChange) + self.tbTotalPriceBox.Add(self.tbTotalPriceCharacter, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) + mainSizer.Add(self.tbTotalPriceBox, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10) + + self.rbMarketSearch = wx.RadioBox(panel, -1, "Market Search && Recent Items", wx.DefaultPosition, wx.DefaultSize, ["No changes to meta buttons", "Enable all meta buttons for a duration of search / recents", "Enable all meta buttons"], 1, wx.RA_SPECIFY_COLS) + self.rbMarketSearch.SetSelection(self.priceSettings.get('marketMGSearchMode')) + mainSizer.Add(self.rbMarketSearch, 0, wx.RIGHT | wx.TOP | wx.EXPAND, 10) + self.rbMarketSearch.Bind(wx.EVT_RADIOBOX, self.OnMarketSearchChange) + + self.rbMarketEmpty = wx.RadioBox(panel, -1, "Market Group Selection", wx.DefaultPosition, wx.DefaultSize, ["No changes to meta buttons", "Enable all meta buttons"], 1, wx.RA_SPECIFY_COLS) + self.rbMarketEmpty.SetSelection(self.priceSettings.get('marketMGMarketSelectMode')) + mainSizer.Add(self.rbMarketEmpty, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10) + self.rbMarketEmpty.Bind(wx.EVT_RADIOBOX, self.OnMarketGroupSelectionChange) + + self.rbMarketEmpty = wx.RadioBox(panel, -1, "Empty Market View", wx.DefaultPosition, wx.DefaultSize, ["No changes to meta buttons", "Enable leftmost available meta button", "Enable all available meta buttons"], 1, wx.RA_SPECIFY_COLS) + self.rbMarketEmpty.SetSelection(self.priceSettings.get('marketMGEmptyMode')) + mainSizer.Add(self.rbMarketEmpty, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10) + self.rbMarketEmpty.Bind(wx.EVT_RADIOBOX, self.OnMarketEmptyChange) + + self.rbMarketJump = wx.RadioBox(panel, -1, "Item Market Group Jump", wx.DefaultPosition, wx.DefaultSize, ["No changes to meta buttons", "Enable item's meta button", "Enable item's meta button, disable others", "Enable all meta buttons"], 1, wx.RA_SPECIFY_COLS) + self.rbMarketJump.SetSelection(self.priceSettings.get('marketMGJumpMode')) + mainSizer.Add(self.rbMarketJump, 0, wx.EXPAND | wx.TOP | wx.RIGHT | wx.BOTTOM, 10) + self.rbMarketJump.Bind(wx.EVT_RADIOBOX, self.OnMarketJumpChange) + + panel.SetSizer(mainSizer) + panel.Layout() + + def onMarketDelayChange(self, event): + self.sFit.serviceFittingOptions["marketSearchDelay"] = self.intDelay.GetValue() + event.Skip() + + def onCBShowShortcuts(self, event): + self.sFit.serviceFittingOptions["showMarketShortcuts"] = self.cbMarketShortcuts.GetValue() + + def getImage(self): + return BitmapLoader.getBitmap("settings_market", "gui") + + def onPriceSelection(self, event): + system = self.chPriceSystem.GetString(self.chPriceSystem.GetSelection()) + self.sFit.serviceFittingOptions["priceSystem"] = system + + fitID = self.mainFrame.getActiveFit() + + self.sFit.refreshFit(fitID) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + event.Skip() + + def onPricesSourceSelection(self, event): + source = self.chPriceSource.GetString(self.chPriceSource.GetSelection()) + self.sFit.serviceFittingOptions["priceSource"] = source + + def OnTotalPriceDroneChange(self, event): + self.priceSettings.set('drones', event.GetInt()) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + + def OnTotalPriceCargoChange(self, event): + self.priceSettings.set('cargo', event.GetInt()) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + + def OnTotalPriceCharacterChange(self, event): + self.priceSettings.set('character', event.GetInt()) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + + def OnMarketJumpChange(self, event): + self.priceSettings.set('marketMGJumpMode', event.GetInt()) + + def OnMarketEmptyChange(self, event): + self.priceSettings.set('marketMGEmptyMode', event.GetInt()) + + def OnMarketSearchChange(self, event): + self.priceSettings.set('marketMGSearchMode', event.GetInt()) + + def OnMarketGroupSelectionChange(self, event): + self.priceSettings.set('marketMGMarketSelectMode', event.GetInt()) + + +PFMarketPref.register() diff --git a/gui/builtinPreferenceViews/pyfaStatViewPreferences.py b/gui/builtinPreferenceViews/pyfaStatViewPreferences.py index e9e0d8cb0..8ba24b088 100644 --- a/gui/builtinPreferenceViews/pyfaStatViewPreferences.py +++ b/gui/builtinPreferenceViews/pyfaStatViewPreferences.py @@ -99,20 +99,6 @@ class PFStatViewPref(PreferenceView): self.rbOutgoing.SetSelection(self.settings.get('outgoing')) rbSizerRow3.Add(self.rbOutgoing, 1, wx.TOP | wx.RIGHT, 5) self.rbOutgoing.Bind(wx.EVT_RADIOBOX, self.OnOutgoingChange) - # We don't have views for these.....yet - ''' - self.rbMining = wx.RadioBox(panel, -1, "Mining", wx.DefaultPosition, wx.DefaultSize, - ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) - self.rbMining.SetSelection(self.settings.get('miningyield')) - rbSizerRow3.Add(self.rbMining, 1, wx.ALL, 5) - self.rbMining.Bind(wx.EVT_RADIOBOX, self.OnMiningYieldChange) - - self.rbDrones = wx.RadioBox(panel, -1, "Drones", wx.DefaultPosition, wx.DefaultSize, - ['None', 'Minimal', 'Full'], 1, wx.RA_SPECIFY_COLS) - self.rbDrones.SetSelection(self.settings.get('drones')) - rbSizerRow3.Add(self.rbDrones, 1, wx.ALL, 5) - self.rbDrones.Bind(wx.EVT_RADIOBOX, self.OnDroneChange) - ''' mainSizer.Add(rbSizerRow3, 1, wx.ALL | wx.EXPAND, 0) diff --git a/gui/builtinStatsViews/priceViewFull.py b/gui/builtinStatsViews/priceViewFull.py index 92aea617f..f77e352fd 100644 --- a/gui/builtinStatsViews/priceViewFull.py +++ b/gui/builtinStatsViews/priceViewFull.py @@ -23,7 +23,7 @@ from gui.statsView import StatsView from gui.bitmap_loader import BitmapLoader from gui.utils.numberFormatter import formatAmount from service.price import Fit, Price -from service.settings import PriceMenuSettings +from service.settings import MarketPriceSettings class PriceViewFull(StatsView): @@ -32,7 +32,7 @@ class PriceViewFull(StatsView): def __init__(self, parent): StatsView.__init__(self) self.parent = parent - self.settings = PriceMenuSettings.getInstance() + self.settings = MarketPriceSettings.getInstance() def getHeaderText(self, fit): return "Price" @@ -125,11 +125,8 @@ class PriceViewFull(StatsView): implant_price += implant.item.price.price total_price = 0 - - if self.settings.get("ship"): - total_price += ship_price - if self.settings.get("modules"): - total_price += module_price + total_price += ship_price + total_price += module_price if self.settings.get("drones"): total_price += drone_price + fighter_price if self.settings.get("cargo"): @@ -138,23 +135,22 @@ class PriceViewFull(StatsView): total_price += booster_price + implant_price self.labelPriceShip.SetLabel("%s ISK" % formatAmount(ship_price, 3, 3, 9, currency=True)) - self.labelPriceShip.SetToolTip(wx.ToolTip('{:,.2f}'.format(ship_price))) + self.labelPriceShip.SetToolTip(wx.ToolTip('{:,.2f} ISK'.format(ship_price))) self.labelPriceFittings.SetLabel("%s ISK" % formatAmount(module_price, 3, 3, 9, currency=True)) - self.labelPriceFittings.SetToolTip(wx.ToolTip('{:,.2f}'.format(module_price))) - - self.labelPriceTotal.SetLabel("%s ISK" % formatAmount(total_price, 3, 3, 9, currency=True)) - self.labelPriceTotal.SetToolTip(wx.ToolTip('{:,.2f}'.format(total_price))) + self.labelPriceFittings.SetToolTip(wx.ToolTip('{:,.2f} ISK'.format(module_price))) self.labelPriceDrones.SetLabel("%s ISK" % formatAmount(drone_price + fighter_price, 3, 3, 9, currency=True)) - self.labelPriceDrones.SetToolTip(wx.ToolTip('{:,.2f}'.format(drone_price + fighter_price))) + self.labelPriceDrones.SetToolTip(wx.ToolTip('{:,.2f} ISK'.format(drone_price + fighter_price))) self.labelPriceCargobay.SetLabel("%s ISK" % formatAmount(cargo_price, 3, 3, 9, currency=True)) - self.labelPriceCargobay.SetToolTip(wx.ToolTip('{:,.2f}'.format(cargo_price))) + self.labelPriceCargobay.SetToolTip(wx.ToolTip('{:,.2f} ISK'.format(cargo_price))) - self.labelPriceCharacter.SetLabel( - "%s ISK" % formatAmount(booster_price + implant_price, 3, 3, 9, currency=True)) - self.labelPriceCharacter.SetToolTip(wx.ToolTip('{:,.2f}'.format(booster_price + implant_price))) + self.labelPriceCharacter.SetLabel("%s ISK" % formatAmount(booster_price + implant_price, 3, 3, 9, currency=True)) + self.labelPriceCharacter.SetToolTip(wx.ToolTip('{:,.2f} ISK'.format(booster_price + implant_price))) + + self.labelPriceTotal.SetLabel("%s ISK" % formatAmount(total_price, 3, 3, 9, currency=True)) + self.labelPriceTotal.SetToolTip(wx.ToolTip('{:,.2f} ISK'.format(total_price))) def processPrices(self, prices): self.refreshPanelPrices(self.fit) diff --git a/gui/builtinStatsViews/priceViewMinimal.py b/gui/builtinStatsViews/priceViewMinimal.py index 4506f2686..486bf00d5 100644 --- a/gui/builtinStatsViews/priceViewMinimal.py +++ b/gui/builtinStatsViews/priceViewMinimal.py @@ -23,7 +23,7 @@ from gui.statsView import StatsView from gui.bitmap_loader import BitmapLoader from gui.utils.numberFormatter import formatAmount from service.price import Fit, Price -from service.settings import PriceMenuSettings +from service.settings import MarketPriceSettings class PriceViewMinimal(StatsView): @@ -32,7 +32,7 @@ class PriceViewMinimal(StatsView): def __init__(self, parent): StatsView.__init__(self) self.parent = parent - self.settings = PriceMenuSettings.getInstance() + self.settings = MarketPriceSettings.getInstance() def getHeaderText(self, fit): return "Price" @@ -121,11 +121,8 @@ class PriceViewMinimal(StatsView): fitting_price = module_price total_price = 0 - - if self.settings.get("ship"): - total_price += ship_price - if self.settings.get("modules"): - total_price += module_price + total_price += ship_price + total_price += module_price if self.settings.get("drones"): total_price += drone_price + fighter_price if self.settings.get("cargo"): @@ -134,13 +131,13 @@ class PriceViewMinimal(StatsView): total_price += booster_price + implant_price self.labelPriceShip.SetLabel("%s ISK" % formatAmount(ship_price, 3, 3, 9, currency=True)) - self.labelPriceShip.SetToolTip(wx.ToolTip('{:,.2f}'.format(ship_price))) + self.labelPriceShip.SetToolTip(wx.ToolTip('{:,.2f} ISK'.format(ship_price))) self.labelPriceFittings.SetLabel("%s ISK" % formatAmount(fitting_price, 3, 3, 9, currency=True)) - self.labelPriceFittings.SetToolTip(wx.ToolTip('{:,.2f}'.format(fitting_price))) + self.labelPriceFittings.SetToolTip(wx.ToolTip('{:,.2f} ISK'.format(fitting_price))) self.labelPriceTotal.SetLabel("%s ISK" % formatAmount(total_price, 3, 3, 9, currency=True)) - self.labelPriceTotal.SetToolTip(wx.ToolTip('{:,.2f}'.format(total_price))) + self.labelPriceTotal.SetToolTip(wx.ToolTip('{:,.2f} ISK'.format(total_price))) def processPrices(self, prices): self.refreshPanelPrices(self.fit) diff --git a/gui/contextMenu.py b/gui/contextMenu.py index ec9048429..0625ff5ba 100644 --- a/gui/contextMenu.py +++ b/gui/contextMenu.py @@ -208,7 +208,6 @@ from gui.builtinContextMenus import ( # noqa: E402,F401 changeAffectingSkills, tacticalMode, targetResists, - priceClear, priceOptions, amount, cargoAmmo, diff --git a/gui/marketBrowser.py b/gui/marketBrowser.py index d39477523..ea24973de 100644 --- a/gui/marketBrowser.py +++ b/gui/marketBrowser.py @@ -20,12 +20,12 @@ # noinspection PyPackageRequirements import wx -from service.market import Market - from gui.builtinMarketBrowser.searchBox import SearchBox from gui.builtinMarketBrowser.itemView import ItemView from gui.builtinMarketBrowser.metaButton import MetaButton from gui.builtinMarketBrowser.marketTree import MarketTree +from service.market import Market +from service.settings import MarketPriceSettings from logbook import Logger @@ -33,8 +33,11 @@ pyfalog = Logger(__name__) class MarketBrowser(wx.Panel): + + def __init__(self, parent): wx.Panel.__init__(self, parent) + pyfalog.debug("Initialize marketBrowser") vbox = wx.BoxSizer(wx.VERTICAL) self.SetSizer(vbox) @@ -46,9 +49,11 @@ class MarketBrowser(wx.Panel): self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) vbox.Add(self.splitter, 1, wx.EXPAND) - # Grab market service instance and create child objects + # Grab service stuff and create child objects self.sMkt = Market.getInstance() - self.searchMode = False + self.settings = MarketPriceSettings.getInstance() + self.__mode = 'normal' + self.__normalBtnMap = {} self.marketView = MarketTree(self.splitter, self) self.itemView = ItemView(self.splitter, self) @@ -97,4 +102,60 @@ class MarketBrowser(wx.Panel): self.itemView.filterItemStore() def jump(self, item): + self.mode = 'normal' self.marketView.jump(item) + setting = self.settings.get('marketMGJumpMode') + itemMetaCat = self.sMkt.META_MAP_REVERSE[self.sMkt.getMetaGroupIdByItem(item)] + # Enable item meta category + if setting == 1: + btn = getattr(self, itemMetaCat) + if not btn.GetValue(): + btn.setUserSelection(True) + # Enable item meta category, disable others + elif setting == 2: + tgtBtn = getattr(self, itemMetaCat) + if not tgtBtn.GetValue(): + tgtBtn.setUserSelection(True) + for btn in self.metaButtons: + if btn is tgtBtn: + continue + if btn.GetValue: + btn.setUserSelection(False) + # Enable all meta categories + elif setting == 3: + for btn in self.metaButtons: + if not btn.GetValue(): + btn.setUserSelection(True) + self.itemView.selectionMade('jump') + + @property + def mode(self): + return self.__mode + + @mode.setter + def mode(self, newMode): + oldMode = self.__mode + if newMode == oldMode: + return + # Store meta button states when switching from normal + if oldMode == 'normal': + self.__normalBtnMap.clear() + for btn in self.metaButtons: + self.__normalBtnMap[btn] = btn.userSelected + if newMode == 'search': + self.marketView.UnselectAll() + setting = self.settings.get('marketMGSearchMode') + # We turn on all meta buttons for the duration of search/recents + if setting == 1: + if newMode in ('search', 'recent'): + for btn in self.metaButtons: + btn.setUserSelection(True) + if newMode == 'normal': + for btn, state in self.__normalBtnMap.items(): + btn.setUserSelection(state) + # We turn on all meta buttons permanently + if setting == 2: + for btn in self.metaButtons: + btn.setUserSelection(True) + self.__mode = newMode + diff --git a/gui/preferenceDialog.py b/gui/preferenceDialog.py index 37ca5ddaf..f65c8451f 100644 --- a/gui/preferenceDialog.py +++ b/gui/preferenceDialog.py @@ -66,12 +66,10 @@ class PreferenceDialog(wx.Dialog): self.listbook.AddPage(page, prefView.title, imageId=imgID) - minHeight = 550 bestFit = self.GetBestVirtualSize() - if minHeight > bestFit[1]: - self.SetSize(650, minHeight) - else: - self.SetSize(650, bestFit[1]) + width = max(bestFit[0], 800 if "wxGTK" in wx.PlatformInfo else 650) + height = max(bestFit[1], 550) + self.SetSize(width, height) self.Layout() diff --git a/gui/preferenceView.py b/gui/preferenceView.py index 9ce2e676d..0ee6230f5 100644 --- a/gui/preferenceView.py +++ b/gui/preferenceView.py @@ -46,6 +46,7 @@ from gui.builtinPreferenceViews import ( # noqa: E402, F401 pyfaEsiPreferences, pyfaContextMenuPreferences, pyfaStatViewPreferences, + pyfaMarketPreferences, pyfaUpdatePreferences, pyfaEnginePreferences, pyfaDatabasePreferences, diff --git a/imgs/gui/settings_market.png b/imgs/gui/settings_market.png new file mode 100644 index 000000000..3b656427a Binary files /dev/null and b/imgs/gui/settings_market.png differ diff --git a/service/market.py b/service/market.py index 085fef624..4457445e2 100644 --- a/service/market.py +++ b/service/market.py @@ -316,6 +316,7 @@ class Market(object): ("faction", frozenset((4, 3))), ("complex", frozenset((6,))), ("officer", frozenset((5,)))]) + self.META_MAP_REVERSE = {sv: k for k, v in self.META_MAP.items() for sv in v} self.SEARCH_CATEGORIES = ( "Drone", "Module", diff --git a/service/settings.py b/service/settings.py index b901b1d72..aa55f98d4 100644 --- a/service/settings.py +++ b/service/settings.py @@ -48,37 +48,6 @@ class SettingsProvider(object): if not os.path.exists(self.BASE_PATH): os.mkdir(self.BASE_PATH) - # def getSettings(self, area, defaults=None): - # # type: (basestring, dict) -> service.Settings - # # NOTE: needed to change for tests - # settings_obj = self.settings.get(area) - # - # if settings_obj is None and hasattr(self, 'BASE_PATH'): - # canonical_path = os.path.join(self.BASE_PATH, area) - # - # if not os.path.exists(canonical_path): - # info = {} - # if defaults: - # for item in defaults: - # info[item] = defaults[item] - # - # else: - # try: - # f = open(canonical_path, "rb") - # info = cPickle.load(f) - # for item in defaults: - # if item not in info: - # info[item] = defaults[item] - # - # except: - # info = {} - # if defaults: - # for item in defaults: - # info[item] = defaults[item] - # - # self.settings[area] = settings_obj = Settings(canonical_path, info) - # - # return settings_obj def getSettings(self, area, defaults=None): # type: (basestring, dict) -> service.Settings # NOTE: needed to change for tests @@ -438,12 +407,6 @@ class StatViewSettings(object): "outgoing" : 2, } - # We don't have these....yet - ''' - "miningyield": 2, - "drones": 2 - ''' - self.serviceStatViewDefaultSettings = SettingsProvider.getInstance().getSettings("pyfaServiceStatViewSettings", serviceStatViewDefaultSettings) def get(self, type): @@ -453,13 +416,13 @@ class StatViewSettings(object): self.serviceStatViewDefaultSettings[type] = value -class PriceMenuSettings(object): +class MarketPriceSettings(object): _instance = None @classmethod def getInstance(cls): if cls._instance is None: - cls._instance = PriceMenuSettings() + cls._instance = MarketPriceSettings() return cls._instance @@ -468,11 +431,13 @@ class PriceMenuSettings(object): # 0 - Do not add to total # 1 - Add to total PriceMenuDefaultSettings = { - "ship" : 1, - "modules" : 1, - "drones" : 0, - "cargo" : 0, - "character" : 0 + "drones" : 1, + "cargo" : 1, + "character" : 0, + "marketMGJumpMode": 0, + "marketMGEmptyMode": 1, + "marketMGSearchMode": 0, + "marketMGMarketSelectMode": 0 } self.PriceMenuDefaultSettings = SettingsProvider.getInstance().getSettings("pyfaPriceMenuSettings",