| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564 |
- """
- This file is part of RuneOptimizer.
- RuneOptimizer is free software: you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
- RuneOptimizer is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
- You should have received a copy of the GNU General Public License along with
- RuneOptimizer. If not, see <https://www.gnu.org/licenses/>.
- """
- class PanelTeams(wx.Panel):
- """
- The team management Panel.
- Parameters
- ----------
- selectedTeamId : string
- Currently selected team ID (default None).
- selectedTeamName : string
- Currently selected team name (default None).
- selectedTeamPriority : int
- Currently selected team priority (default None).
- titleChangePending : boolean
- Indicates if there is any change on the selected team title to save in
- the database.
- priorityChangePending : boolean
- Indicates if there is any change on the selected team priority to save
- in the database.
- teamList : wx.ListCtrl
- Selectable list with all the teams.
- detailsSizer : wx.BoxSizer
- Holds all the details. Hidden until a team is selected.
- titleText : wx.TextCtrl
- Text editor to change the team name.
- priorityText : wx.TextCtrl
- Text editor to change the team priority.
- teamUnitList : wx.ListCtrl
- Selectable list with all the units in the selected team.
- allUnitList : wx.ListCtrl
- Selectable list with all the units not in the selected team.
- filterNameText : wx.TextCtrl
- Text input to filter units names.
- filterNameTexts : wx.CheckBox
- Checkbox to include or exclude units in storage.
- filterNoRunesCheck : wx.CheckBox
- Checkbox to include or exclude units without runes.
- filterNoTeamsCheck : wx.CheckBox
- Checkbox to include or exclude units in no teams.
- titleTimer : wx.Timer
- Timer to defer database updates on team name changes.
- priorityTimer : wx.Timer
- Timer to defer database updates on team priority changes.
- Methods
- -------
- """
- selectedTeamId = None
- selectedTeamName = None
- selectetdTeamPriority = None
- titleChangePending = False
- priorityChangePending = False
- teamList = None
- detailsSizer = None
- titleText = None
- priorityText = None
- teamUnitList = None
- allUnitList = None
- filterNameText = None
- filterNameTexts = None
- filterNoRunesCheck = None
- filterNoTeamsCheck = None
- titleTimer = None
- priorityTimer = None
- def __init__(self, parent, id=wx.ID_ANY):
- """Initializes the panel.
- Sets upt all the widgets.
- Parameters
- ----------
- parent : wx.*
- Panel parent.
- id : int, optional
- ID for the panel (default wx.ID_ANY).
- """
- # Parent constructor
- wx.Panel.__init__(self, parent=parent, id=id)
- wx.StaticText(
- parent=self, id=wx.ID_ANY,
- label="Name Prio.",
- pos=(10, 10), size=(240, 20)
- )
- self.teamList = wx.ListCtrl(
- parent=self, id=wx.ID_ANY, pos=(10, 30), size=(240, 460),
- style=wx.LC_REPORT|wx.LC_NO_HEADER
- )
- self.teamList.InsertColumn(0, "Name", width=200)
- self.teamList.InsertColumn(1, "Prio.", width=40)
- self.populateTeamList(event=None)
- self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.teamSelected, self.teamList)
- createTeamButton = wx.Button(
- parent=self, id=wx.ID_ANY, pos=(50, 500), size=(170, 40),
- style=wx.LC_REPORT, label="New team"
- )
- self.Bind(wx.EVT_BUTTON, self.createTeam, createTeamButton)
- # Sizer for all team details. Will be hidden until a team is selected
- self.detailsSizer = wx.BoxSizer(wx.VERTICAL)
- # Team title and priority editors
- self.titleText = wx.TextCtrl(
- parent=self, id=wx.ID_ANY,
- pos=(270, 30), size=(200, 25), style=wx.TE_RICH|wx.TE_MULTILINE
- )
- self.detailsSizer.Add(self.titleText)
- self.Bind(wx.EVT_TEXT, self.changeTitle, self.titleText);
- priortiyLabel = wx.StaticText(
- parent=self, id=wx.ID_ANY, label="Priority:",
- pos=(270, 80), size=(80, 30)
- )
- self.detailsSizer.Add(priortiyLabel)
- self.priorityText = wx.TextCtrl(
- parent=self, id=wx.ID_ANY,
- pos=(330, 80), size=(30, 25), style=wx.TE_RICH|wx.TE_MULTILINE)
- self.detailsSizer.Add(self.priorityText)
- self.Bind(wx.EVT_TEXT, self.changePriority, self.priorityText);
- # Team unit list
- self.teamUnitList = wx.ListCtrl(
- parent=self, id=wx.ID_ANY, pos=(270, 130), size=(140, 360),
- style=wx.LC_REPORT|wx.LC_NO_HEADER
- )
- self.detailsSizer.Add(self.teamUnitList)
- self.teamUnitList.InsertColumn(0, "Name", width=140)
- self.teamUnitList.InsertColumn(1, "Level", width=140)
- # All unit selector
- allUnitLabel = wx.StaticText(
- parent=self, id=wx.ID_ANY,
- label="Name Prio. Sto.",
- pos=(500, 10), size=(190, 20)
- )
- self.detailsSizer.Add(allUnitLabel)
- self.allUnitList = wx.ListCtrl(
- parent=self, id=wx.ID_ANY, pos=(500, 30), size=(190, 350),
- style=wx.LC_REPORT|wx.LC_NO_HEADER
- )
- self.detailsSizer.Add(self.allUnitList)
- self.allUnitList.InsertColumn(0, "Name", width=120)
- self.allUnitList.InsertColumn(1, "Prio.", width=40)
- self.allUnitList.InsertColumn(2, "Sto.", width=30)
- # List filters
- filterBox = wx.StaticBox(
- parent=self, label="Filters:",id=wx.ID_ANY,
- pos=(500, 390), size=(190, 150)
- )
- self.detailsSizer.Add(filterBox)
- wx.StaticText(
- parent=filterBox, label="Monster name", pos=(5, 5), size=(180, 20)
- )
- self.filterNameText = wx.TextCtrl(
- parent=filterBox, id=wx.ID_ANY, value="", pos=(5, 25),
- size=(177, 20), style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB
- )
- self.Bind(wx.EVT_TEXT, self.populateUnitList, self.filterNameText)
- self.filterStorageCheck = wx.CheckBox(
- parent=filterBox, id=wx.ID_ANY,
- label="Monsters in storage", pos=(5, 55), size=(180, 20)
- )
- self.filterStorageCheck.SetValue(True)
- self.Bind(
- wx.EVT_CHECKBOX, self.populateUnitList, self.filterStorageCheck
- )
- self.filterNoRunesCheck = wx.CheckBox(
- parent=filterBox, id=wx.ID_ANY,
- label="Monsters without runes", pos=(5, 75), size=(180, 20)
- )
- self.filterNoRunesCheck.SetValue(True)
- self.Bind(
- wx.EVT_CHECKBOX, self.populateUnitList, self.filterNoRunesCheck
- )
- self.filterNoTeamsCheck = wx.CheckBox(
- parent=filterBox, id=wx.ID_ANY,
- label="Monsters not in teams", pos=(5, 95), size=(180, 20)
- )
- self.filterNoTeamsCheck.SetValue(True)
- self.Bind(
- wx.EVT_CHECKBOX, self.populateUnitList, self.filterNoTeamsCheck
- )
- self.populateUnitList(None)
- addButton = wx.Button(
- parent=self, id=wx.ID_ANY, pos=(420, 300), size=(70, 40),
- style=wx.LC_REPORT, label="<<<"
- )
- self.detailsSizer.Add(addButton)
- self.Bind(wx.EVT_BUTTON, self.addToTeam, addButton)
- removeButton = wx.Button(
- parent=self, id=wx.ID_ANY, pos=(420, 350), size=(70, 40),
- style=wx.LC_REPORT, label=">>>"
- )
- self.detailsSizer.Add(removeButton)
- self.Bind(wx.EVT_BUTTON, self.removeFromTeam, removeButton)
- deleteButton = wx.Button(
- parent=self, id=wx.ID_ANY, pos=(270, 500), size=(140, 40),
- style=wx.LC_REPORT, label="Delete team"
- )
- self.detailsSizer.Add(deleteButton)
- self.Bind(wx.EVT_BUTTON, self.deleteTeam, deleteButton)
- # By default, hide all details
- self.detailsSizer.ShowItems(False)
- def populateTeamList(self, event=None):
- """Populates the team list.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- self.teamList.DeleteAllItems()
- query = """
- SELECT
- id,
- name,
- priority
- FROM teams
- ORDER BY priority DESC
- """
- cursor = conn.execute(query)
- i = 0
- for row in cursor:
- self.teamList.InsertItem(i, row[1])
- self.teamList.SetItem(i, 1, str(row[2]))
- self.teamList.SetItemData(i, int(row[0]))
- i = i + 1
- def populateUnitList(self, event=None):
- """Populates the list of all units.
- Uses the filters.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- # Get units from db
- name = self.filterNameText.GetValue()
- query = """
- SELECT
- id,
- name,
- (
- SELECT cast(total(teams.priority) as int)
- FROM teams, units_teams
- WHERE teams.id = units_teams.team AND units_teams.unit = units.id
- ) as priority,
- storage
- FROM units
- WHERE
- name LIKE '%""" + name + """%'
- """
- if self.filterStorageCheck.GetValue() == False:
- query += " AND storage = 0 "
- if self.filterNoRunesCheck.GetValue() == False:
- query += " AND id IN (SELECT DISTINCT unit FROM runes) "
- if self.filterNoTeamsCheck.GetValue() == False:
- query += " AND id IN (SELECT DISTINCT unit FROM units_teams) "
- query += " ORDER BY priority DESC; ";
- cursor = conn.execute(query)
- i = 0
- self.allUnitList.DeleteAllItems()
- for row in cursor:
- self.allUnitList.InsertItem(i, row[1])
- self.allUnitList.SetItem(i, 1, str(row[2]))
- self.allUnitList.SetItem(i, 2, "")
- self.allUnitList.SetItemData(i, int(row[0]))
- if (row[3] == 1):
- self.allUnitList.SetItem(i, 2, "X")
- else:
- self.allUnitList.SetItem(i, 2, " ")
- i = i + 1
- def populateTeamUnitList(self, event=None):
- """Populates the list of units in the selected team.
- Uses the filters.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- # Get units from db
- name = self.filterNameText.GetValue()
- query = """
- SELECT
- id,
- name,
- level
- FROM units
- WHERE id IN (SELECT DISTINCT unit FROM units_teams WHERE
- team = '""" + self.selectedTeamId + """')
- """
- cursor = conn.execute(query)
- i = 0
- self.teamUnitList.DeleteAllItems()
- for row in cursor:
- self.teamUnitList.InsertItem(i, row[1])
- self.teamUnitList.SetItem(i, 0, str(row[1]))
- self.teamUnitList.SetItem(i, 1, "Lv." + str(row[2]))
- self.teamUnitList.SetItemData(i, int(row[0]))
- i = i + 1
- def createTeam(self, event=None):
- """Opens a dialog to create a new team.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- with DialogNewTeam(parent=self) as dlg:
- if dlg.ShowModal() == wx.ID_OK:
- self.populateTeamList()
- def deleteTeam(self, event=None):
- """Deletes a team.
- Shows a confirmation dialog first.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- message = "Are you sure you want to delete the team " + \
- self.selectedTeamName + "?\n\nThis can't be undone."
- with DialogConfirm(parent=self, message=message) as dlg:
- if dlg.ShowModal() == wx.ID_OK:
- cursor = conn.execute(
- "DELETE FROM units_teams WHERE team = ?",
- (self.selectedTeamId,))
- cursor = conn.execute(
- "DELETE FROM teams WHERE id = ?", (self.selectedTeamId,)
- )
- conn.commit()
- # Clear the selection and hide the details
- self.selectedIndex = None
- self.detailsSizer.ShowItems(False)
- self.populateTeamList(event=None)
- self.GetParent().frameUnits.populateUnitList(event=None)
- def addToTeam(self, event=None):
- """Adds unit to the currently selected team.
- Adds all the units selected in self.allUnitList. Refreshes both unit
- lists and also the unit list in the units panel.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- selectedIndex = self.allUnitList.GetFirstSelected()
- while (selectedIndex != -1):
- unitId = self.allUnitList.GetItemData(selectedIndex)
- query = "INSERT INTO units_teams (team, unit) VALUES (?, ?)";
- cursor = conn.execute(query, (self.selectedTeamId, unitId))
- selectedIndex = self.allUnitList.GetNextSelected(selectedIndex)
- conn.commit()
- self.populateTeamUnitList(event=None)
- self.populateUnitList(event=None)
- self.GetParent().frameUnits.populateUnitList(event=None)
- def removeFromTeam(self, event=None):
- """Removes units the currently selected team.
- Removes all the units selected in self.teamUnitList. Refreshes both unit
- lists and also the unit list in the units panel.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- selectedIndex = self.teamUnitList.GetFirstSelected()
- while (selectedIndex != -1):
- unitId = self.teamUnitList.GetItemData(selectedIndex)
- query = "DELETE FROM units_teams WHERE team = ? AND unit = ?";
- cursor = conn.execute(query, (self.selectedTeamId, unitId))
- selectedIndex = self.teamUnitList.GetNextSelected(selectedIndex)
- conn.commit()
- self.populateTeamUnitList(event=None)
- self.populateUnitList(event=None)
- self.GetParent().frameUnits.populateUnitList(event=None)
- def teamSelected(self, event=None):
- """Shows the team details.
- Called when a team is selected.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- self.selectedTeamId = \
- str(self.teamList.GetItemData(self.teamList.GetFirstSelected()))
- self.selectedTeamName = \
- self.teamList.GetItem(self.teamList.GetFirstSelected(), 0).GetText()
- self.selectedTeamPriority = \
- self.teamList.GetItem(self.teamList.GetFirstSelected(), 1).GetText()
- self.populateTeamUnitList(event=None)
- # Unbind for the automatic change
- self.Unbind(wx.EVT_TEXT, self.titleText)
- self.titleText.SetValue(self.selectedTeamName)
- # Rebind
- self.Bind(wx.EVT_TEXT, self.changeTitle, self.titleText);
- # Unbind for the automatic change
- self.Unbind(wx.EVT_TEXT, self.priorityText);
- self.priorityText.SetValue(self.selectedTeamPriority)
- # Rebind
- self.Bind(wx.EVT_TEXT, self.changePriority, self.priorityText);
- # Show details
- self.detailsSizer.ShowItems(True)
- def changeTitle(self, event):
- """Prepares for a title change.
- Called everytime the selected team name is changed. It schedules a call
- to self.saveNewTitle in two seconds, to give the user time to enter the
- full title.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- newTitle = self.titleText.GetValue()
- self.titleChangePending = True
- self.titleTimer = wx.Timer(self)
- self.Bind(wx.EVT_TIMER, self.saveNewTitle, self.titleTimer)
- self.titleTimer.StartOnce(2000)
- def saveNewTitle(self, event=None):
- """Saves the team name to the database.
- Called two seconds after the last change in self.titleText. If the name
- is not valid (i.e. less than two characters), it doesn't apply the
- change and sets the font color to red to indicate error.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- if (self.titleChangePending):
- newTitle = self.titleText.GetValue().replace("\n", "").strip()
- self.titleChangePending = False
- if len(newTitle.replace(" ", "")) > 2:
- self.titleText.SetStyle(
- 0, len(self.titleText.GetValue()),
- wx.TextAttr(colText=wx.BLACK)
- )
- query = "UPDATE teams SET name = ? WHERE id = ?";
- cursor = conn.execute(query, (newTitle, self.selectedTeamId))
- conn.commit()
- self.populateTeamList(event=None)
- else:
- monospaceFont = wx.Font(
- pointSize=8, family=wx.FONTFAMILY_TELETYPE,
- style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL
- )
- self.titleText.SetStyle(
- 0, len(self.titleText.GetValue()), wx.TextAttr(colText=wx.RED)
- )
- def changePriority(self, event):
- """Prepares for a priority change.
- Called everytime the selected team priority is changed. It schedules a
- call to self.saveNewPriority in two seconds, to give the user time to
- enter the full text.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- newPriority = self.priorityText.GetValue()
- self.priorityChangePending = True
- self.priorityTimer = wx.Timer(self)
- self.Bind(wx.EVT_TIMER, self.saveNewPriority, self.priorityTimer)
- self.priorityTimer.StartOnce(2000)
- def saveNewPriority(self, event=None):
- """Saves the team priority to the database.
- Called two seconds after the last change in self.priorityText. If the
- priority is not valid (i.e. not a number, lower than 0 or greater than
- 50), it doesn't apply the change and sets the font color to red to
- indicate error.
- Parameters
- ----------
- event : wx.Event, optional
- The event that triggered the call (default is None).
- """
- if (self.priorityChangePending):
- newPriority = self.priorityText.GetValue().replace("\n", "").strip()
- self.priorityChangePending = False
- if newPriority.isnumeric() and \
- int(newPriority) >= 0 and int(newPriority) <= 50:
- self.priorityText.SetStyle(
- 0, len(self.priorityText.GetValue()),
- wx.TextAttr(colText=wx.BLACK)
- )
- query = "UPDATE teams SET priority = ? WHERE id = ?";
- cursor = conn.execute(query, (newPriority, self.selectedTeamId))
- conn.commit()
- self.populateTeamList(event=None)
- self.GetParent().frameUnits.populateUnitList(event=None)
- else:
- self.priorityText.SetStyle(
- 0, len(self.priorityText.GetValue()),
- wx.TextAttr(colText=wx.RED)
- )
|