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)