diff --git a/po/de_pysol.po b/po/de_pysol.po index f8a57fae..0d5b4f94 100644 --- a/po/de_pysol.po +++ b/po/de_pysol.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: PySol 0.0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-10 10:19-0500\n" -"PO-Revision-Date: 2022-07-28 18:52-0400\n" +"PO-Revision-Date: 2022-08-13 11:50-0400\n" "Last-Translator: H. Schaekel \n" "Language-Team: German\n" "Language: de\n" @@ -3322,6 +3322,12 @@ msgstr "Decks:" msgid "Redeals:" msgstr "Neue Karten:" +msgid "Compatibility:" +msgstr "" + +msgid "Inventor:" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:122 pysollib/tile/selectgame.py:400 #: pysollib/tk/selectgame.py:400 msgid "Played:" @@ -3360,6 +3366,30 @@ msgstr "&Regeln" msgid "Playable Preview - %(game)s" msgstr "Spielbare Vorschau - %(game)s" +msgid "Advanced search" +msgstr "" + +msgid "Check alternate names" +msgstr "" + +msgid "Children's" +msgstr "" + +msgid "Scored" +msgstr "" + +msgid "Stripped Deck" +msgstr "" + +msgid "Separate Decks" +msgstr "" + +msgid "Relaxed" +msgstr "" + +msgid "Original" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:480 pysollib/tile/selectgame.py:569 #: pysollib/tk/selectgame.py:569 msgid "variable" @@ -3769,10 +3799,16 @@ msgstr "&Info / Einstellungen..." msgid "About cardset" msgstr "Über Kartensets" +msgid "Style:" +msgstr "" + #: pysollib/tile/selectcardset.py:455 pysollib/tk/selectcardset.py:446 msgid "Styles:" msgstr "Stile:" +msgid "Date:" +msgstr "" + #: pysollib/tile/selectcardset.py:456 pysollib/tk/selectcardset.py:447 msgid "Nationality:" msgstr "Nationalität:" @@ -3805,7 +3841,7 @@ msgstr "Benutzerdef. Spiel" msgid "Solid Colors" msgstr "Einfache Farben" -msgid "Textures" +msgid "Tiles" msgstr "" msgid "Images" diff --git a/po/fr_pysol.po b/po/fr_pysol.po index be46f4df..b2d86d7c 100644 --- a/po/fr_pysol.po +++ b/po/fr_pysol.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: 1.02\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-10 10:19-0500\n" -"PO-Revision-Date: 2022-07-28 18:52-0400\n" +"PO-Revision-Date: 2022-08-13 11:49-0400\n" "Last-Translator: Eric Rausch \n" "Language-Team: French\n" "Language: fr\n" @@ -3368,6 +3368,12 @@ msgstr "Jeux:" msgid "Redeals:" msgstr "Donnes:" +msgid "Compatibility:" +msgstr "" + +msgid "Inventor:" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:122 pysollib/tile/selectgame.py:400 #: pysollib/tk/selectgame.py:400 msgid "Played:" @@ -3406,6 +3412,30 @@ msgstr "&Règles" msgid "Playable Preview - %(game)s" msgstr "Démo jouable - %(game)s" +msgid "Advanced search" +msgstr "" + +msgid "Check alternate names" +msgstr "" + +msgid "Children's" +msgstr "" + +msgid "Scored" +msgstr "" + +msgid "Stripped Deck" +msgstr "" + +msgid "Separate Decks" +msgstr "" + +msgid "Relaxed" +msgstr "" + +msgid "Original" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:480 pysollib/tile/selectgame.py:569 #: pysollib/tk/selectgame.py:569 msgid "variable" @@ -3821,10 +3851,16 @@ msgstr "&Info / Options..." msgid "About cardset" msgstr "A-propos du style de carte" +msgid "Style:" +msgstr "" + #: pysollib/tile/selectcardset.py:455 pysollib/tk/selectcardset.py:446 msgid "Styles:" msgstr "Styles:" +msgid "Date:" +msgstr "" + #: pysollib/tile/selectcardset.py:456 pysollib/tk/selectcardset.py:447 msgid "Nationality:" msgstr "Origine:" @@ -3857,7 +3893,7 @@ msgstr "Jeux persos" msgid "Solid Colors" msgstr "Couleurs unies" -msgid "Textures" +msgid "Tiles" msgstr "" msgid "Images" diff --git a/po/it_pysol.po b/po/it_pysol.po index 9049fd63..b79c4196 100644 --- a/po/it_pysol.po +++ b/po/it_pysol.po @@ -12,7 +12,7 @@ msgstr "" "Project-Id-Version: it_pysol\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-10 10:19-0500\n" -"PO-Revision-Date: 2022-07-28 18:52-0400\n" +"PO-Revision-Date: 2022-08-13 11:49-0400\n" "Last-Translator: Giuliano Colla \n" "Language-Team: Italiano \n" "Language: it\n" @@ -3429,6 +3429,12 @@ msgstr "Mazzi:" msgid "Redeals:" msgstr "Ridistribuzioni:" +msgid "Compatibility:" +msgstr "" + +msgid "Inventor:" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:122 pysollib/tile/selectgame.py:400 #: pysollib/tk/selectgame.py:400 msgid "Played:" @@ -3467,6 +3473,30 @@ msgstr "&Regole" msgid "Playable Preview - %(game)s" msgstr "Anteprima giocabile - %(game)s" +msgid "Advanced search" +msgstr "" + +msgid "Check alternate names" +msgstr "" + +msgid "Children's" +msgstr "" + +msgid "Scored" +msgstr "" + +msgid "Stripped Deck" +msgstr "" + +msgid "Separate Decks" +msgstr "" + +msgid "Relaxed" +msgstr "" + +msgid "Original" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:480 pysollib/tile/selectgame.py:569 #: pysollib/tk/selectgame.py:569 msgid "variable" @@ -3883,10 +3913,16 @@ msgstr "" msgid "About cardset" msgstr "Descrizione dei mazzi" +msgid "Style:" +msgstr "" + #: pysollib/tile/selectcardset.py:455 pysollib/tk/selectcardset.py:446 msgid "Styles:" msgstr "Stili:" +msgid "Date:" +msgstr "" + #: pysollib/tile/selectcardset.py:456 pysollib/tk/selectcardset.py:447 msgid "Nationality:" msgstr "Nazionalità:" @@ -3920,7 +3956,7 @@ msgstr "Giochi Personali" msgid "Solid Colors" msgstr "Colori pieni" -msgid "Textures" +msgid "Tiles" msgstr "" msgid "Images" diff --git a/po/pl_pysol.po b/po/pl_pysol.po index 5cd150dc..df421b0e 100644 --- a/po/pl_pysol.po +++ b/po/pl_pysol.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-10 10:19-0500\n" -"PO-Revision-Date: 2022-07-28 18:53-0400\n" +"PO-Revision-Date: 2022-08-13 11:48-0400\n" "Last-Translator: Jerzy Trzeciak \n" "Language-Team: Polish \n" "Language: pl\n" @@ -3468,6 +3468,12 @@ msgstr "Talie:" msgid "Redeals:" msgstr "Ponowne rozdania:" +msgid "Compatibility:" +msgstr "" + +msgid "Inventor:" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:122 pysollib/tile/selectgame.py:400 #: pysollib/tk/selectgame.py:400 msgid "Played:" @@ -3506,6 +3512,30 @@ msgstr "Zasady" msgid "Playable Preview - %(game)s" msgstr "Podgląd z aktywną grą - " +msgid "Advanced search" +msgstr "" + +msgid "Check alternate names" +msgstr "" + +msgid "Children's" +msgstr "" + +msgid "Scored" +msgstr "" + +msgid "Stripped Deck" +msgstr "" + +msgid "Separate Decks" +msgstr "" + +msgid "Relaxed" +msgstr "" + +msgid "Original" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:480 pysollib/tile/selectgame.py:569 #: pysollib/tk/selectgame.py:569 msgid "variable" @@ -3924,10 +3954,16 @@ msgstr "" msgid "About cardset" msgstr "O zestawie kart" +msgid "Style:" +msgstr "" + #: pysollib/tile/selectcardset.py:455 pysollib/tk/selectcardset.py:446 msgid "Styles:" msgstr "Style:" +msgid "Date:" +msgstr "" + #: pysollib/tile/selectcardset.py:456 pysollib/tk/selectcardset.py:447 msgid "Nationality:" msgstr "Narodowość:" @@ -3961,7 +3997,7 @@ msgstr "Własne gry" msgid "Solid Colors" msgstr "Kolory jednorodne" -msgid "Textures" +msgid "Tiles" msgstr "" msgid "Images" diff --git a/po/pysol.pot b/po/pysol.pot index e488497a..682e768c 100644 --- a/po/pysol.pot +++ b/po/pysol.pot @@ -3194,6 +3194,12 @@ msgstr "" msgid "Redeals:" msgstr "" +msgid "Compatibility:" +msgstr "" + +msgid "Inventor:" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:122 pysollib/tile/selectgame.py:400 #: pysollib/tk/selectgame.py:400 msgid "Played:" @@ -3232,6 +3238,30 @@ msgstr "" msgid "Playable Preview - %(game)s" msgstr "" +msgid "Advanced search" +msgstr "" + +msgid "Check alternate names" +msgstr "" + +msgid "Children's" +msgstr "" + +msgid "Scored" +msgstr "" + +msgid "Stripped Deck" +msgstr "" + +msgid "Separate Decks" +msgstr "" + +msgid "Relaxed" +msgstr "" + +msgid "Original" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:480 pysollib/tile/selectgame.py:569 #: pysollib/tk/selectgame.py:569 msgid "variable" @@ -3629,10 +3659,16 @@ msgstr "" msgid "About cardset" msgstr "" +msgid "Style:" +msgstr "" + #: pysollib/tile/selectcardset.py:455 pysollib/tk/selectcardset.py:446 msgid "Styles:" msgstr "" +msgid "Date:" +msgstr "" + #: pysollib/tile/selectcardset.py:456 pysollib/tk/selectcardset.py:447 msgid "Nationality:" msgstr "" @@ -3665,7 +3701,7 @@ msgstr "" msgid "Solid Colors" msgstr "" -msgid "Textures" +msgid "Tiles" msgstr "" msgid "Images" diff --git a/po/ru_pysol.po b/po/ru_pysol.po index b074c26e..e120912e 100644 --- a/po/ru_pysol.po +++ b/po/ru_pysol.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-10 10:19-0500\n" -"PO-Revision-Date: 2022-07-28 18:53-0400\n" +"PO-Revision-Date: 2022-08-13 11:47-0400\n" "Last-Translator: Skomoroh \n" "Language-Team: Russian \n" "Language: ru\n" @@ -3440,6 +3440,12 @@ msgstr "Колод:" msgid "Redeals:" msgstr "Пересдач:" +msgid "Compatibility:" +msgstr "" + +msgid "Inventor:" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:122 pysollib/tile/selectgame.py:400 #: pysollib/tk/selectgame.py:400 msgid "Played:" @@ -3478,6 +3484,30 @@ msgstr "&Правила" msgid "Playable Preview - %(game)s" msgstr "Играемый предпросмотр - %(game)s" +msgid "Advanced search" +msgstr "" + +msgid "Check alternate names" +msgstr "" + +msgid "Children's" +msgstr "" + +msgid "Scored" +msgstr "" + +msgid "Stripped Deck" +msgstr "" + +msgid "Separate Decks" +msgstr "" + +msgid "Relaxed" +msgstr "" + +msgid "Original" +msgstr "" + #: pysollib/pysolgtk/selectgame.py:480 pysollib/tile/selectgame.py:569 #: pysollib/tk/selectgame.py:569 msgid "variable" @@ -3893,10 +3923,16 @@ msgstr "" msgid "About cardset" msgstr "О наборе карт" +msgid "Style:" +msgstr "" + #: pysollib/tile/selectcardset.py:455 pysollib/tk/selectcardset.py:446 msgid "Styles:" msgstr "Стиль:" +msgid "Date:" +msgstr "" + #: pysollib/tile/selectcardset.py:456 pysollib/tk/selectcardset.py:447 msgid "Nationality:" msgstr "Национальность:" @@ -3930,7 +3966,7 @@ msgstr "Самодельные игры" msgid "Solid Colors" msgstr "Монотонный цвет" -msgid "Textures" +msgid "Tiles" msgstr "" msgid "Images" diff --git a/pysollib/gamedb.py b/pysollib/gamedb.py index bf6b62e6..687d76f9 100644 --- a/pysollib/gamedb.py +++ b/pysollib/gamedb.py @@ -155,6 +155,14 @@ class GI: GT_CUSTOM: n_("Custom"), } + SKILL_LEVELS = { + SL_LUCK: _('Luck only'), + SL_MOSTLY_LUCK: _('Mostly luck'), + SL_BALANCED: _('Balanced'), + SL_MOSTLY_SKILL: _('Mostly skill'), + SL_SKILL: _('Skill only'), + } + # SELECT_GAME_BY_TYPE = [] # for gt, name in TYPE_NAMES.items(): # if not name.endswith('games'): diff --git a/pysollib/kivy/menubar.py b/pysollib/kivy/menubar.py index f721a3ad..30c3b375 100644 --- a/pysollib/kivy/menubar.py +++ b/pysollib/kivy/menubar.py @@ -885,7 +885,7 @@ class OptionsMenuDialog(LMenuDialog): self.menubar.mOptTableColor) rg1 = tv.add_node( - LTreeNode(text=_('Textures')), rg) + LTreeNode(text=_('Tiles')), rg) rg2 = tv.add_node( LTreeNode(text=_('Images')), rg) diff --git a/pysollib/pysolgtk/selectgame.py b/pysollib/pysolgtk/selectgame.py index afce1222..9519dc99 100644 --- a/pysollib/pysolgtk/selectgame.py +++ b/pysollib/pysolgtk/selectgame.py @@ -483,14 +483,7 @@ class SelectGameDialogWithPreview(MfxDialog): type = '' if gi.si.game_type in GI.TYPE_NAMES: type = _(GI.TYPE_NAMES[gi.si.game_type]) - sl = { - GI.SL_LUCK: _('Luck only'), - GI.SL_MOSTLY_LUCK: _('Mostly luck'), - GI.SL_BALANCED: _('Balanced'), - GI.SL_MOSTLY_SKILL: _('Mostly skill'), - GI.SL_SKILL: _('Skill only'), - } - skill_level = sl.get(gi.skill_level) + skill_level = GI.SKILL_LEVELS.get(gi.skill_level) if gi.redeals == -2: redeals = _('variable') elif gi.redeals == -1: diff --git a/pysollib/tile/selectcardset.py b/pysollib/tile/selectcardset.py index 6915969d..17acd374 100644 --- a/pysollib/tile/selectcardset.py +++ b/pysollib/tile/selectcardset.py @@ -36,7 +36,7 @@ from six.moves import tkinter_ttk as ttk from .selecttree import SelectDialogTreeCanvas from .selecttree import SelectDialogTreeLeaf, SelectDialogTreeNode -from .tkwidget import MfxDialog, MfxScrolledCanvas, PysolScale +from .tkwidget import MfxDialog, MfxScrolledCanvas, PysolCombo, PysolScale # ************************************************************************ @@ -220,6 +220,7 @@ class SelectCardsetDialogWithPreview(MfxDialog): self.manager = manager self.key = key self.app = app + self.criteria = SearchCriteria() self.cardset_values = None # padx, pady = kw.padx, kw.pady padx, pady = 4, 4 @@ -263,15 +264,23 @@ class SelectCardsetDialogWithPreview(MfxDialog): self.tree.frame.pack(padx=padx, pady=pady, expand=True, fill='both') # Search + searchbox = ttk.Frame(search_frame) searchText = tkinter.StringVar() - self.list_searchlabel = tkinter.Label(search_frame, text="Search:", + self.list_searchlabel = tkinter.Label(searchbox, text="Search:", justify='left', anchor='w') self.list_searchlabel.pack(side="top", fill='both', ipadx=1) - self.list_searchtext = tkinter.Entry(search_frame, + self.list_searchtext = tkinter.Entry(searchbox, textvariable=searchText) + + self.advSearch = tkinter.Button(searchbox, text='...', + command=self.advancedSearch) + self.advSearch.pack(side="right") + self.list_searchtext.pack(side="top", fill='both', padx=padx, pady=pady, ipadx=1) - searchText.trace('w', self.performSearch) + searchText.trace('w', self.basicSearch) + + searchbox.pack(side="top", fill="both") self.list_scrollbar = tkinter.Scrollbar(search_frame) self.list_scrollbar.pack(side="right", fill='both') @@ -471,17 +480,44 @@ class SelectCardsetDialogWithPreview(MfxDialog): def _updateScale(self, v): self.updatePreview() - def performSearch(self, *args): + def basicSearch(self, *args): self.updateSearchList(self.list_searchtext.get()) def updateSearchList(self, searchString): + self.criteria.name = searchString + self.performSearch() + + def performSearch(self): self.list.delete(0, "end") self.list.vbar_show = True cardsets = self.manager.getAllSortedByName() results = [] for cardset in cardsets: - if self.app.checkSearchString(searchString, cardset.name): + if (self.criteria.size != "" + and self.criteria.sizeOptions[self.criteria.size] + != cardset.si.size): + continue + if (self.criteria.type != "" + and self.criteria.typeOptions[self.criteria.type] + != cardset.si.type): + continue + + if (self.criteria.style != "" + and self.criteria.styleOptions[self.criteria.style] + not in cardset.si.styles): + continue + if (self.criteria.date != "" + and self.criteria.dateOptions[self.criteria.date] + not in cardset.si.dates): + continue + if (self.criteria.nationality != "" + and self.criteria.natOptions[self.criteria.nationality] + not in cardset.si.nationalities): + continue + + if self.app.checkSearchString(self.criteria.name, + cardset.name): results.append(cardset.name) results.sort() pos = 0 @@ -489,6 +525,23 @@ class SelectCardsetDialogWithPreview(MfxDialog): self.list.insert(pos, result) pos += 1 + def advancedSearch(self): + d = SelectCardsetAdvancedSearch(self.top, _("Advanced search"), + self.criteria) + if d.status == 0 and d.button == 0: + self.criteria.name = d.name.get() + + self.list_searchtext.delete(0, "end") + self.list_searchtext.insert(0, d.name.get()) + + self.criteria.size = d.size.get() + self.criteria.type = d.type.get() + self.criteria.style = d.style.get() + self.criteria.date = d.date.get() + self.criteria.nationality = d.nationality.get() + + self.performSearch() + def selectSearchResult(self, event): if self.list.size() <= 0: return @@ -656,3 +709,141 @@ class CardsetInfoDialog(MfxDialog): focus = self.createButtons(bottom_frame, kw) # focus = text_w self.mainloop(focus, kw.timeout) + + +class SearchCriteria: + def __init__(self): + self.name = "" + self.size = "" + self.type = "" + self.style = "" + self.date = "" + self.nationality = "" + + self.sizeOptions = {"": -1, + "Tiny cardsets": CSI.SIZE_TINY, + "Small cardsets": CSI.SIZE_SMALL, + "Medium cardsets": CSI.SIZE_MEDIUM, + "Large cardsets": CSI.SIZE_LARGE, + "Extra Large cardsets": CSI.SIZE_XLARGE, + "Hi-Res cardsets": CSI.SIZE_HIRES} + + typeOptions = {-1: ""} + typeOptions.update(CSI.TYPE_NAME) + del typeOptions[7] # Navagraha Ganjifa is unused. + self.typeOptions = dict((v, k) for k, v in typeOptions.items()) + + styleOptions = {-1: ""} + styleOptions.update(CSI.STYLE) + self.styleOptions = dict((v, k) for k, v in styleOptions.items()) + + dateOptions = {-1: ""} + dateOptions.update(CSI.DATE) + self.dateOptions = dict((v, k) for k, v in dateOptions.items()) + + natOptions = {-1: ""} + natOptions.update(CSI.NATIONALITY) + self.natOptions = dict((v, k) for k, v in natOptions.items()) + + +class SelectCardsetAdvancedSearch(MfxDialog): + def __init__(self, parent, title, criteria, **kw): + kw = self.initKw(kw) + MfxDialog.__init__(self, parent, title, kw.resizable, kw.default) + top_frame, bottom_frame = self.createFrames(kw) + + self.createBitmaps(top_frame, kw) + # + self.name = tkinter.StringVar() + self.name.set(criteria.name) + self.size = tkinter.StringVar() + self.size.set(criteria.size) + self.type = tkinter.StringVar() + self.type.set(criteria.type) + self.style = tkinter.StringVar() + self.style.set(criteria.style) + self.date = tkinter.StringVar() + self.date.set(criteria.date) + self.nationality = tkinter.StringVar() + self.nationality.set(criteria.nationality) + # + row = 0 + + labelName = tkinter.Label(top_frame, text="Name:", anchor="w") + labelName.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textName = tkinter.Entry(top_frame, textvariable=self.name) + textName.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + sizeValues = list(criteria.sizeOptions.keys()) + + labelSize = tkinter.Label(top_frame, text="Size:", anchor="w") + labelSize.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textSize = PysolCombo(top_frame, values=sizeValues, + textvariable=self.size) + textSize.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + typeValues = list(criteria.typeOptions.keys()) + typeValues.sort() + + labelType = tkinter.Label(top_frame, text="Type:", anchor="w") + labelType.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textType = PysolCombo(top_frame, values=typeValues, + textvariable=self.type) + textType.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + styleValues = list(criteria.styleOptions.keys()) + styleValues.sort() + + labelStyle = tkinter.Label(top_frame, text="Style:", anchor="w") + labelStyle.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textStyle = PysolCombo(top_frame, values=styleValues, + textvariable=self.style) + textStyle.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + dateValues = list(criteria.dateOptions.keys()) + dateValues.sort() + + labelDate = tkinter.Label(top_frame, text="Date:", anchor="w") + labelDate.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textDate = PysolCombo(top_frame, values=dateValues, + textvariable=self.date) + textDate.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + natValues = list(criteria.natOptions.keys()) + natValues.sort() + + labelNationality = tkinter.Label(top_frame, text="Nationality:", + anchor="w") + labelNationality.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textNationality = PysolCombo(top_frame, values=natValues, + textvariable=self.nationality) + textNationality.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + focus = self.createButtons(bottom_frame, kw) + # focus = text_w + self.mainloop(focus, kw.timeout) + + def initKw(self, kw): + kw = KwStruct(kw, + strings=(_("&OK"), _("&Cancel")), default=0, + padx=10, pady=10, + ) + return MfxDialog.initKw(self, kw) diff --git a/pysollib/tile/selectgame.py b/pysollib/tile/selectgame.py index dce9ed2f..3a39c1cc 100644 --- a/pysollib/tile/selectgame.py +++ b/pysollib/tile/selectgame.py @@ -37,7 +37,7 @@ from six.moves import tkinter_ttk as ttk from .selecttree import SelectDialogTreeCanvas from .selecttree import SelectDialogTreeLeaf, SelectDialogTreeNode -from .tkwidget import MfxDialog, MfxScrolledCanvas +from .tkwidget import MfxDialog, MfxScrolledCanvas, PysolCombo # ************************************************************************ # * Nodes @@ -354,6 +354,7 @@ class SelectGameDialogWithPreview(SelectGameDialog): self.app = app self.gameid = gameid self.bookmark = bookmark + self.criteria = SearchCriteria() self.random = None if self.TreeDataHolder_Class.data is None: self.TreeDataHolder_Class.data = self.TreeData_Class(app) @@ -401,15 +402,23 @@ class SelectGameDialogWithPreview(SelectGameDialog): self.tree.frame.pack(padx=padx, pady=pady, expand=True, fill='both') # Search + searchbox = ttk.Frame(search_frame) searchText = tkinter.StringVar() - self.list_searchlabel = tkinter.Label(search_frame, text="Search:", + self.list_searchlabel = tkinter.Label(searchbox, text="Search:", justify='left', anchor='w') self.list_searchlabel.pack(side="top", fill='both', ipadx=1) - self.list_searchtext = tkinter.Entry(search_frame, + self.list_searchtext = tkinter.Entry(searchbox, textvariable=searchText) + + self.advSearch = tkinter.Button(searchbox, text='...', + command=self.advancedSearch) + self.advSearch.pack(side="right") + self.list_searchtext.pack(side="top", fill='both', padx=padx, pady=pady, ipadx=1) - searchText.trace('w', self.performSearch) + searchText.trace('w', self.basicSearch) + + searchbox.pack(side="top", fill="both") self.list_scrollbar = tkinter.Scrollbar(search_frame) self.list_scrollbar.pack(side="right", fill='both') @@ -514,27 +523,125 @@ class SelectGameDialogWithPreview(SelectGameDialog): destruct(self.preview_app) self.preview_app = None - def performSearch(self, *args): + def basicSearch(self, *args): self.updateSearchList(self.list_searchtext.get()) def updateSearchList(self, searchString): + self.criteria.name = searchString + self.performSearch() + + def performSearch(self): self.list.delete(0, "end") self.list.vbar_show = True games = self.app.gdb.getAllGames() results = [] for game in games: - if self.app.checkSearchString(searchString, game.name): + if (self.criteria.category != "" and + self.criteria.categoryOptions[self.criteria.category] + != game.category): + continue + if (self.criteria.type != "" + and self.criteria.typeOptions[self.criteria.type] + != game.si.game_type): + continue + if (self.criteria.skill != "" + and self.criteria.skillOptions[self.criteria.skill] + != game.skill_level): + continue + if (self.criteria.decks != "" + and self.criteria.deckOptions[self.criteria.decks] + != game.decks): + continue + if (self.criteria.redeals != "" and + self.criteria.redeals != "Other number of redeals" + and self.criteria.redealOptions[self.criteria.redeals] + != game.redeals): + continue + if self.criteria.redeals == "Other number of redeals"\ + and game.redeals < 4: + continue + + compat_okay = True + for name, games in GI.GAMES_BY_COMPATIBILITY: + if self.criteria.compat == name: + if game.id not in games: + compat_okay = False + break + + if not compat_okay: + continue + + invent_okay = True + for name, games in GI.GAMES_BY_INVENTORS: + if self.criteria.inventor == name: + if game.id not in games: + invent_okay = False + break + + if not invent_okay: + continue + + if (self.criteria.children and + not (game.si.game_flags & GI.GT_CHILDREN)): + continue + if (self.criteria.scoring and + not (game.si.game_flags & GI.GT_SCORE)): + continue + if (self.criteria.stripped and + not (game.si.game_flags & GI.GT_STRIPPED)): + continue + if (self.criteria.separate and + not (game.si.game_flags & GI.GT_SEPARATE_DECKS)): + continue + if (self.criteria.open and not (game.si.game_flags & GI.GT_OPEN)): + continue + if (self.criteria.relaxed and + not (game.si.game_flags & GI.GT_RELAXED)): + continue + if (self.criteria.original and + not (game.si.game_flags & GI.GT_ORIGINAL)): + continue + + if self.app.checkSearchString(self.criteria.name, game.name): results.append(game.name) - for altname in game.altnames: - if self.app.checkSearchString(searchString, altname): - results.append(altname) + if self.criteria.usealt: + for altname in game.altnames: + if self.app.checkSearchString(self.criteria.name, altname): + results.append(altname) results.sort() pos = 0 for result in results: self.list.insert(pos, result) pos += 1 + def advancedSearch(self): + d = SelectGameAdvancedSearch(self.top, _("Advanced search"), + self.criteria) + if d.status == 0 and d.button == 0: + self.criteria.name = d.name.get() + + self.list_searchtext.delete(0, "end") + self.list_searchtext.insert(0, d.name.get()) + + self.criteria.usealt = d.usealt.get() + self.criteria.category = d.category.get() + self.criteria.type = d.type.get() + self.criteria.skill = d.skill.get() + self.criteria.decks = d.decks.get() + self.criteria.redeals = d.redeals.get() + self.criteria.compat = d.compat.get() + self.criteria.inventor = d.inventor.get() + + self.criteria.children = d.children.get() + self.criteria.scoring = d.scoring.get() + self.criteria.stripped = d.stripped.get() + self.criteria.separate = d.separate.get() + self.criteria.open = d.open.get() + self.criteria.relaxed = d.relaxed.get() + self.criteria.original = d.original.get() + self.performSearch() + def selectSearchResult(self, event): if self.list.size() <= 0: return @@ -651,14 +758,7 @@ class SelectGameDialogWithPreview(SelectGameDialog): type = '' if gi.si.game_type in GI.TYPE_NAMES: type = _(GI.TYPE_NAMES[gi.si.game_type]) - sl = { - GI.SL_LUCK: _('Luck only'), - GI.SL_MOSTLY_LUCK: _('Mostly luck'), - GI.SL_BALANCED: _('Balanced'), - GI.SL_MOSTLY_SKILL: _('Mostly skill'), - GI.SL_SKILL: _('Skill only'), - } - skill_level = sl.get(gi.skill_level) + skill_level = GI.SKILL_LEVELS.get(gi.skill_level) if gi.redeals == -2: redeals = _('Variable') elif gi.redeals == -1: @@ -697,3 +797,254 @@ class SelectGameDialogWithPreview(SelectGameDialog): title_label.grid() text_label.grid() text_label.config(text=t) + + +class SearchCriteria: + def __init__(self): + self.name = "" + self.usealt = True + self.category = "" + self.type = "" + self.skill = "" + self.decks = "" + self.redeals = "" + self.compat = "" + self.inventor = "" + + self.children = False + self.scoring = False + self.stripped = False + self.separate = False + self.open = False + self.relaxed = False + self.original = False + + categoryOptions = {-1: ""} + categoryOptions.update(CSI.TYPE_NAME) + del categoryOptions[7] # Navagraha Ganjifa is unused. + self.categoryOptions = dict((v, k) for k, v in categoryOptions.items()) + + typeOptions = {-1: ""} + typeOptions.update(GI.TYPE_NAMES) + del typeOptions[29] # Simple games type is unused. + self.typeOptions = dict((v, k) for k, v in typeOptions.items()) + + skillOptions = {-1: ""} + skillOptions.update(GI.SKILL_LEVELS) + self.skillOptions = dict((v, k) for k, v in skillOptions.items()) + + self.deckOptions = {"": 0, + "1 deck games": 1, + "2 deck games": 2, + "3 deck games": 3, + "4 deck games": 4} + + self.redealOptions = {"": -3, + "No redeal": 0, + "1 redeal": 1, + "2 redeals": 2, + "3 redeals": 3, + "Unlimited redeals": -1, + "Variable redeals": -2, + "Other number of redeals": 4} + + +class SelectGameAdvancedSearch(MfxDialog): + def __init__(self, parent, title, criteria, **kw): + kw = self.initKw(kw) + MfxDialog.__init__(self, parent, title, kw.resizable, kw.default) + top_frame, bottom_frame = self.createFrames(kw) + + self.createBitmaps(top_frame, kw) + # + self.name = tkinter.StringVar() + self.name.set(criteria.name) + self.usealt = tkinter.BooleanVar() + self.usealt.set(criteria.usealt) + self.category = tkinter.StringVar() + self.category.set(criteria.category) + self.type = tkinter.StringVar() + self.type.set(criteria.type) + self.skill = tkinter.StringVar() + self.skill.set(criteria.skill) + self.decks = tkinter.StringVar() + self.decks.set(criteria.decks) + self.redeals = tkinter.StringVar() + self.redeals.set(criteria.redeals) + self.compat = tkinter.StringVar() + self.compat.set(criteria.compat) + self.inventor = tkinter.StringVar() + self.inventor.set(criteria.inventor) + + self.children = tkinter.BooleanVar() + self.children.set(criteria.children) + self.scoring = tkinter.BooleanVar() + self.scoring.set(criteria.scoring) + self.stripped = tkinter.BooleanVar() + self.stripped.set(criteria.stripped) + self.separate = tkinter.BooleanVar() + self.separate.set(criteria.separate) + self.open = tkinter.BooleanVar() + self.open.set(criteria.open) + self.relaxed = tkinter.BooleanVar() + self.relaxed.set(criteria.relaxed) + self.original = tkinter.BooleanVar() + self.original.set(criteria.original) + # + row = 0 + + labelName = tkinter.Label(top_frame, text="Name:", anchor="w") + labelName.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textName = tkinter.Entry(top_frame, textvariable=self.name) + textName.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + altCheck = tkinter.Checkbutton(top_frame, variable=self.usealt, + text=_("Check alternate names"), + anchor="w") + altCheck.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + categoryValues = list(criteria.categoryOptions.keys()) + categoryValues.sort() + + labelCategory = tkinter.Label(top_frame, text="Category:", anchor="w") + labelCategory.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textCategory = PysolCombo(top_frame, values=categoryValues, + textvariable=self.category) + textCategory.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + typeValues = list(criteria.typeOptions.keys()) + typeValues.sort() + + labelType = tkinter.Label(top_frame, text="Type:", anchor="w") + labelType.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textType = PysolCombo(top_frame, values=typeValues, + textvariable=self.type) + textType.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + skillValues = list(criteria.skillOptions.keys()) + + labelSkill = tkinter.Label(top_frame, text="Skill level:", anchor="w") + labelSkill.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textSkill = PysolCombo(top_frame, values=skillValues, + textvariable=self.skill) + textSkill.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + deckValues = list(criteria.deckOptions.keys()) + + labelDecks = tkinter.Label(top_frame, text="Decks:", anchor="w") + labelDecks.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textDecks = PysolCombo(top_frame, values=deckValues, + textvariable=self.decks) + textDecks.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + redealValues = list(criteria.redealOptions.keys()) + + labelRedeals = tkinter.Label(top_frame, text="Redeals:", anchor="w") + labelRedeals.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textRedeals = PysolCombo(top_frame, values=redealValues, + textvariable=self.redeals) + textRedeals.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + compatValues = list() + compatValues.append("") + for name, games in GI.GAMES_BY_COMPATIBILITY: + compatValues.append(name) + + labelCompat = tkinter.Label(top_frame, text="Compatibility:", + anchor="w") + labelCompat.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textCompat = PysolCombo(top_frame, values=compatValues, + textvariable=self.compat) + textCompat.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + inventorValues = list() + inventorValues.append("") + for name, games in GI.GAMES_BY_INVENTORS: + inventorValues.append(name) + + labelInventor = tkinter.Label(top_frame, text="Inventor:", anchor="w") + labelInventor.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textInventor = PysolCombo(top_frame, values=inventorValues, + textvariable=self.inventor) + textInventor.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + col = 0 + childCheck = tkinter.Checkbutton(top_frame, variable=self.children, + text=_("Children's"), anchor="w") + childCheck.grid(row=row, column=col, columnspan=1, sticky='ew', + padx=1, pady=1) + col += 1 + + scoreCheck = tkinter.Checkbutton(top_frame, variable=self.scoring, + text=_("Scored"), anchor="w") + scoreCheck.grid(row=row, column=col, columnspan=1, sticky='ew', + padx=1, pady=1) + col += 1 + + stripCheck = tkinter.Checkbutton(top_frame, variable=self.stripped, + text=_("Stripped Deck"), anchor="w") + stripCheck.grid(row=row, column=col, columnspan=1, sticky='ew', + padx=1, pady=1) + col += 1 + + sepCheck = tkinter.Checkbutton(top_frame, variable=self.separate, + text=_("Separate Decks"), anchor="w") + sepCheck.grid(row=row, column=col, columnspan=1, sticky='ew', + padx=1, pady=1) + row += 1 + col = 0 + + openCheck = tkinter.Checkbutton(top_frame, variable=self.open, + text=_("Open"), anchor="w") + openCheck.grid(row=row, column=col, columnspan=1, sticky='ew', + padx=1, pady=1) + col += 1 + + relaxedCheck = tkinter.Checkbutton(top_frame, variable=self.relaxed, + text=_("Relaxed"), anchor="w") + relaxedCheck.grid(row=row, column=col, columnspan=1, sticky='ew', + padx=1, pady=1) + col += 1 + + originalCheck = tkinter.Checkbutton(top_frame, variable=self.original, + text=_("Original"), anchor="w") + originalCheck.grid(row=row, column=col, columnspan=1, sticky='ew', + padx=1, pady=1) + col += 1 + + focus = self.createButtons(bottom_frame, kw) + # focus = text_w + self.mainloop(focus, kw.timeout) + + def initKw(self, kw): + kw = KwStruct(kw, + strings=(_("&OK"), _("&Cancel")), default=0, + padx=10, pady=10, + ) + return MfxDialog.initKw(self, kw) diff --git a/pysollib/tile/selecttile.py b/pysollib/tile/selecttile.py index a9b2fd46..105961fa 100644 --- a/pysollib/tile/selecttile.py +++ b/pysollib/tile/selecttile.py @@ -35,7 +35,7 @@ from six.moves import tkinter_ttk as ttk from .selecttree import SelectDialogTreeCanvas from .selecttree import SelectDialogTreeLeaf, SelectDialogTreeNode -from .tkwidget import MfxDialog, MfxScrolledCanvas +from .tkwidget import MfxDialog, MfxScrolledCanvas, PysolCombo # ************************************************************************ @@ -77,13 +77,13 @@ class SelectTileData(SelectDialogTreeData): None, _("All Backgrounds"), lambda tile: 1, expanded=0), SelectTileNode( - None, _("Textures"), + None, _("Tiles"), lambda tile: os.path.basename( os.path.dirname(tile.filename)) == 'tiles', expanded=0), SelectTileNode( None, _("Images"), lambda tile: (os.path.basename( - os.path.dirname(tile.filename)) in + os.path.dirname(tile.filename)) in ('stretch', 'save-aspect')), expanded=0), SelectTileNode(None, _("Solid Colors"), ( SelectTileLeaf(None, None, _("Blue"), key="#0082df"), @@ -123,6 +123,7 @@ class SelectTileDialogWithPreview(MfxDialog): key = manager.getSelected() self.app = app self.manager = manager + self.criteria = SearchCriteria() self.key = key self.table_color = app.opt.colors['table'] if self.TreeDataHolder_Class.data is None: @@ -166,15 +167,23 @@ class SelectTileDialogWithPreview(MfxDialog): self.tree.frame.pack(padx=padx, pady=pady, expand=True, fill='both') # Search + searchbox = ttk.Frame(search_frame) searchText = tkinter.StringVar() - self.list_searchlabel = tkinter.Label(search_frame, text="Search:", + self.list_searchlabel = tkinter.Label(searchbox, text="Search:", justify='left', anchor='w') self.list_searchlabel.pack(side="top", fill='both', ipadx=1) - self.list_searchtext = tkinter.Entry(search_frame, + self.list_searchtext = tkinter.Entry(searchbox, textvariable=searchText) + + self.advSearch = tkinter.Button(searchbox, text='...', + command=self.advancedSearch) + self.advSearch.pack(side="right") + self.list_searchtext.pack(side="top", fill='both', padx=padx, pady=pady, ipadx=1) - searchText.trace('w', self.performSearch) + searchText.trace('w', self.basicSearch) + + searchbox.pack(side="top", fill="both") self.list_scrollbar = tkinter.Scrollbar(search_frame) self.list_scrollbar.pack(side="right", fill='both') @@ -223,13 +232,13 @@ class SelectTileDialogWithPreview(MfxDialog): return MfxDialog.initKw(self, kw) def mDone(self, button): - if button == 0: # "OK" or double click + if button == 0: # "OK" or double click if isinstance(self.tree.selection_key, six.string_types): self.key = str(self.tree.selection_key) else: self.key = self.tree.selection_key self.tree.n_expansions = 1 # save xyview in any case - if button == 10: # "Solid color..." + if button == 10: # "Solid color..." try: c = tkinter_colorchooser.askcolor( master=self.top, @@ -247,10 +256,14 @@ class SelectTileDialogWithPreview(MfxDialog): return MfxDialog.mDone(self, button) - def performSearch(self, *args): + def basicSearch(self, *args): self.updateSearchList(self.list_searchtext.get()) def updateSearchList(self, searchString): + self.criteria.name = searchString + self.performSearch() + + def performSearch(self): self.list.delete(0, "end") self.list.vbar_show = True tiles = self.manager.getAllSortedByName() @@ -259,7 +272,18 @@ class SelectTileDialogWithPreview(MfxDialog): for tile in tiles: if tile.name == 'None': continue - if self.app.checkSearchString(searchString, tile.name): + + if (self.criteria.type == "Images" and os.path.basename( + os.path.dirname(tile.filename)) not in + ('stretch', 'save-aspect')): + continue + + if (self.criteria.type == "Tiles" and os.path.basename( + os.path.dirname(tile.filename)) != 'tiles'): + continue + + if self.app.checkSearchString(self.criteria.name, + tile.name): results.append(tile.name) results.sort() pos = 0 @@ -267,6 +291,19 @@ class SelectTileDialogWithPreview(MfxDialog): self.list.insert(pos, result) pos += 1 + def advancedSearch(self): + d = SelectTileAdvancedSearch(self.top, _("Advanced search"), + self.criteria) + if d.status == 0 and d.button == 0: + self.criteria.name = d.name.get() + + self.list_searchtext.delete(0, "end") + self.list_searchtext.insert(0, d.name.get()) + + self.criteria.type = d.type.get() + + self.performSearch() + def selectSearchResult(self, event): if self.list.size() <= 0: return @@ -299,3 +336,56 @@ class SelectTileDialogWithPreview(MfxDialog): if self.preview.setTile(self.app, key): return self.preview_key = -1 + + +class SearchCriteria: + def __init__(self): + self.name = "" + self.type = "" + self.typeOptions = ("", "Images", "Tiles") + + +class SelectTileAdvancedSearch(MfxDialog): + def __init__(self, parent, title, criteria, **kw): + kw = self.initKw(kw) + MfxDialog.__init__(self, parent, title, kw.resizable, kw.default) + top_frame, bottom_frame = self.createFrames(kw) + + self.createBitmaps(top_frame, kw) + # + self.name = tkinter.StringVar() + self.name.set(criteria.name) + self.type = tkinter.StringVar() + self.type.set(criteria.type) + # + row = 0 + + labelName = tkinter.Label(top_frame, text="Name:", anchor="w") + labelName.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textName = tkinter.Entry(top_frame, textvariable=self.name) + textName.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + typeValues = list(criteria.typeOptions) + + labelType = tkinter.Label(top_frame, text="Type:", anchor="w") + labelType.grid(row=row, column=0, columnspan=1, sticky='ew', + padx=1, pady=1) + textType = PysolCombo(top_frame, values=typeValues, + textvariable=self.type) + textType.grid(row=row, column=1, columnspan=4, sticky='ew', + padx=1, pady=1) + row += 1 + + focus = self.createButtons(bottom_frame, kw) + # focus = text_w + self.mainloop(focus, kw.timeout) + + def initKw(self, kw): + kw = KwStruct(kw, + strings=(_("&OK"), _("&Cancel")), default=0, + padx=10, pady=10, + ) + return MfxDialog.initKw(self, kw) diff --git a/pysollib/tk/selectgame.py b/pysollib/tk/selectgame.py index c4085c32..431065a4 100644 --- a/pysollib/tk/selectgame.py +++ b/pysollib/tk/selectgame.py @@ -574,14 +574,7 @@ class SelectGameDialogWithPreview(SelectGameDialog): type = '' if gi.si.game_type in GI.TYPE_NAMES: type = _(GI.TYPE_NAMES[gi.si.game_type]) - sl = { - GI.SL_LUCK: _('Luck only'), - GI.SL_MOSTLY_LUCK: _('Mostly luck'), - GI.SL_BALANCED: _('Balanced'), - GI.SL_MOSTLY_SKILL: _('Mostly skill'), - GI.SL_SKILL: _('Skill only'), - } - skill_level = sl.get(gi.skill_level) + skill_level = GI.SKILL_LEVELS.get(gi.skill_level) if gi.redeals == -2: redeals = _('variable') elif gi.redeals == -1: