File indexing completed on 2024-04-21 04:01:52

0001 # -*- coding: utf-8 -*-
0002 
0003 """
0004 Copyright (C) 2008-2016 Wolfgang Rohdewald <wolfgang@rohdewald.de>
0005 
0006 SPDX-License-Identifier: GPL-2.0
0007 
0008 """
0009 
0010 from mi18n import i18n, i18nc
0011 from kde import KIcon
0012 from dialogs import Sorry, QuestionYesNo
0013 from qt import Qt
0014 from qt import QDialog, QHBoxLayout, QVBoxLayout, QDialogButtonBox, \
0015     QTableWidget, QTableWidgetItem
0016 
0017 from common import Internal
0018 from query import Query
0019 from guiutil import decorateWindow
0020 from statesaver import StateSaver
0021 
0022 
0023 class PlayerList(QDialog):
0024 
0025     """QtSQL Model view of the players"""
0026 
0027     def __init__(self, parent):
0028         QDialog.__init__(self)
0029         self.parent = parent
0030         self._data = {}
0031         self.table = QTableWidget(self)
0032         self.table.horizontalHeader().setStretchLastSection(True)
0033         self.table.verticalHeader().setVisible(False)
0034         self.table.setEditTriggers(QTableWidget.NoEditTriggers)
0035         self.table.itemChanged.connect(self.itemChanged)
0036         self.updateTable()
0037         self.buttonBox = QDialogButtonBox()
0038         self.buttonBox.setStandardButtons(
0039             QDialogButtonBox.Close)  # Close has the Rejected role
0040         self.buttonBox.rejected.connect(self.accept)
0041         self.newButton = self.buttonBox.addButton(
0042             i18nc('define a new player',
0043                   "&New"),
0044             QDialogButtonBox.ActionRole)
0045         self.newButton.setIcon(KIcon("document-new"))
0046         self.newButton.clicked.connect(self.slotInsert)
0047         self.deleteButton = self.buttonBox.addButton(
0048             i18n("&Delete"), QDialogButtonBox.ActionRole)
0049         self.deleteButton.setIcon(KIcon("edit-delete"))
0050         self.deleteButton.clicked.connect(self.delete)
0051 
0052         cmdLayout = QHBoxLayout()
0053         cmdLayout.addWidget(self.buttonBox)
0054         layout = QVBoxLayout()
0055         layout.addWidget(self.table)
0056         layout.addLayout(cmdLayout)
0057         self.setLayout(layout)
0058         decorateWindow(self, i18n("Players"))
0059         self.setObjectName('Players')
0060 
0061     def showEvent(self, unusedEvent):
0062         """adapt view to content"""
0063         StateSaver(self, self.table)
0064 
0065     @staticmethod
0066     def sortKey(text):
0067         """display order in Table"""
0068         return text.upper() if text else 'zzzzzzzzzzzz'
0069 
0070     def updateTable(self, data=None, currentName=None):
0071         """fills self.table from DB"""
0072         self.table.itemChanged.disconnect(self.itemChanged)
0073         table = self.table
0074         table.clear()
0075         if data is None:
0076             data = dict(
0077                 Query('select name, id from player where name not like "ROBOT %"').records)
0078         self._data = data
0079         table.setColumnCount(1)
0080         table.setRowCount(len(self._data))
0081         table.setHorizontalHeaderLabels([i18n("Player")])
0082         table.setSelectionBehavior(QTableWidget.SelectRows)
0083         table.setSelectionMode(QTableWidget.SingleSelection)
0084         selectedItem = None
0085         for row, name in enumerate(sorted(self._data, key=self.sortKey)):
0086             item = QTableWidgetItem(name)
0087             if selectedItem is None:
0088                 selectedItem = item
0089             table.setItem(row, 0, item)
0090             if name == currentName:
0091                 selectedItem = item
0092         if selectedItem:
0093             table.setCurrentItem(selectedItem)
0094             table.scrollToItem(selectedItem)
0095         self.table.itemChanged.connect(self.itemChanged)
0096 
0097     def itemChanged(self, item):
0098         """this must be new because editing is disabled for others"""
0099         currentName = item.text()
0100         if currentName in self._data:
0101             Sorry(i18n('Player %1 already exists', currentName))
0102             self.setFocus()
0103             del self._data[self.table.item(self.table.currentRow(), 0).text()]
0104             self.updateTable(currentName=currentName)
0105             return
0106         query = Query('insert into player(name) values(?)', (currentName, ))
0107         if query.failure:
0108             Sorry(
0109                 i18n(
0110                     'Error while adding player %1: %2',
0111                     currentName,
0112                     query.failure.message))
0113         self.updateTable(currentName=currentName)
0114 
0115     def slotInsert(self):
0116         """insert a record"""
0117         self._data[''] = 0
0118         self.updateTable(data=self._data, currentName='')
0119         for row in range(len(self._data)):
0120             item = self.table.item(row, 0)
0121             if not item.text():
0122                 self.table.editItem(item)
0123 
0124     @staticmethod
0125     def __deletePlayer(playerId):
0126         """delete this player and all associated games"""
0127         with Internal.db: # transaction
0128             Query("delete from score where player=?", (playerId, ))
0129             Query("delete from game where p0=? or p1=? or p2=? or p3=?", (playerId, ) * 4)
0130             Query("delete from player where id=?", (playerId,))
0131 
0132     def delete(self):
0133         """delete selected entry"""
0134         def answered(result):
0135             """coming from QuestionYesNo"""
0136             if result is True:
0137                 self.__deletePlayer(playerId)
0138             cleanup()
0139         def cleanup():
0140             """update table view"""
0141             self.updateTable()
0142             self.table.setCurrentCell(min(currentRow, len(self._data) - 1), 0)
0143             # the main window gets focus after QuestionYesNo
0144             self.activateWindow()
0145 
0146         items = self.table.selectedItems()
0147         if not items:
0148             return
0149         currentRow = self.table.currentRow()
0150         assert len(items) == 1
0151         name = items[0].text()
0152         playerId = self._data[name]
0153 
0154         fullCount = int(Query(
0155             "select count(1) from game where p0=? or p1=? or p2=? or p3=?",
0156             (playerId, ) * 4).records[0][0])
0157         if not fullCount:
0158             self.__deletePlayer(playerId)
0159             cleanup()
0160         else:
0161             finishedCount = int(Query(
0162                 "select count(1) from game where (p0=? or p1=? or p2=? or p3=?) and endtime is not null",
0163                 (playerId, ) * 4).records[0][0])
0164             QuestionYesNo(i18n(
0165                 'There are %1 finished and %2 unfinished games for %3, delete %3 anyway?'
0166                 '  This will also delete all games played by %3!',
0167                 finishedCount, fullCount - finishedCount, name)).addBoth(answered)
0168 
0169     def keyPressEvent(self, event):
0170         """use insert/delete keys for insert/delete"""
0171         key = event.key()
0172         if key == Qt.Key_Insert:
0173             self.slotInsert()
0174         elif key == Qt.Key_Delete:
0175             self.delete()
0176         else:
0177             QDialog.keyPressEvent(self, event)