def __init__(self, client): super(TableList, self).__init__(None) self.autoStarted = False self.client = client self.setObjectName('TableList') self.resize(700, 400) self.view = MJTableView(self) self.differ = None self.debugModelTest = None self.requestedNewTable = False self.view.setItemDelegateForColumn(2, RichTextColumnDelegate(self.view)) buttonBox = QDialogButtonBox(self) self.newButton = buttonBox.addButton( i18nc('allocate a new table', "&New"), QDialogButtonBox.ActionRole) self.newButton.setIcon(KIcon("document-new")) self.newButton.setToolTip(i18n("Allocate a new table")) self.newButton.clicked.connect(self.client.newTable) self.joinButton = buttonBox.addButton(i18n("&Join"), QDialogButtonBox.AcceptRole) self.joinButton.clicked.connect(client.joinTable) self.joinButton.setIcon(KIcon("list-add-user")) self.joinButton.setToolTip(i18n("Join a table")) self.leaveButton = buttonBox.addButton(i18n("&Leave"), QDialogButtonBox.AcceptRole) self.leaveButton.clicked.connect(self.leaveTable) self.leaveButton.setIcon(KIcon("list-remove-user")) self.leaveButton.setToolTip(i18n("Leave a table")) self.compareButton = buttonBox.addButton( i18nc('Kajongg-Ruleset', 'Compare'), QDialogButtonBox.AcceptRole) self.compareButton.clicked.connect(self.compareRuleset) self.compareButton.setIcon(KIcon("preferences-plugin-script")) self.compareButton.setToolTip( i18n('Compare the rules of this table with my own rulesets')) self.chatButton = buttonBox.addButton(i18n('&Chat'), QDialogButtonBox.AcceptRole) self.chatButton.setIcon(KIcon("call-start")) self.chatButton.clicked.connect(self.chat) self.startButton = buttonBox.addButton(i18n('&Start'), QDialogButtonBox.AcceptRole) self.startButton.clicked.connect(self.startGame) self.startButton.setIcon(KIcon("arrow-right")) self.startButton.setToolTip( i18n("Start playing on a table. " "Empty seats will be taken by robot players.")) cmdLayout = QHBoxLayout() cmdLayout.addWidget(buttonBox) layout = QVBoxLayout() layout.addWidget(self.view) layout.addLayout(cmdLayout) self.setLayout(layout) self.view.doubleClicked.connect(client.joinTable) StateSaver(self, self.view.horizontalHeader()) self.updateButtonsForTable(None)
class PlayerList(QDialog): """QtSQL Model view of the players""" def __init__(self, parent): QDialog.__init__(self) self.parent = parent self._data = {} self.table = QTableWidget(self) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) self.table.setEditTriggers(QTableWidget.NoEditTriggers) self.table.itemChanged.connect(self.itemChanged) self.updateTable() self.buttonBox = QDialogButtonBox() self.buttonBox.setStandardButtons( QDialogButtonBox.Close) # Close has the Rejected role self.buttonBox.rejected.connect(self.accept) self.newButton = self.buttonBox.addButton( m18nc('define a new player', "&New"), QDialogButtonBox.ActionRole) self.newButton.setIcon(KIcon("document-new")) self.newButton.clicked.connect(self.slotInsert) self.deleteButton = self.buttonBox.addButton( m18n("&Delete"), QDialogButtonBox.ActionRole) self.deleteButton.setIcon(KIcon("edit-delete")) self.deleteButton.clicked.connect(self.delete) cmdLayout = QHBoxLayout() cmdLayout.addWidget(self.buttonBox) layout = QVBoxLayout() layout.addWidget(self.table) layout.addLayout(cmdLayout) self.setLayout(layout) decorateWindow(self, m18n("Players")) self.setObjectName('Players') def showEvent(self, dummyEvent): """adapt view to content""" StateSaver(self, self.table) @staticmethod def sortKey(text): """display order in Table""" if len(text) == 0: return 'zzzzzzzzzzzz' else: return text.upper() def updateTable(self, data=None, currentName=None): """fills self.table from DB""" self.table.itemChanged.disconnect(self.itemChanged) table = self.table table.clear() if data is None: data = dict( Query('select name, id from player where name not like "ROBOT %"').records) self._data = data table.setColumnCount(1) table.setRowCount(len(self._data)) table.setHorizontalHeaderLabels([m18n("Player")]) table.setSelectionBehavior(QTableWidget.SelectRows) table.setSelectionMode(QTableWidget.SingleSelection) selectedItem = None for row, name in enumerate(sorted(self._data, key=self.sortKey)): item = QTableWidgetItem(name) if selectedItem is None: selectedItem = item table.setItem(row, 0, item) if name == currentName: selectedItem = item if selectedItem: table.setCurrentItem(selectedItem) table.scrollToItem(selectedItem) self.table.itemChanged.connect(self.itemChanged) def itemChanged(self, item): """this must be new because editing is disabled for others""" currentName = unicode(item.text()) if currentName in self._data: Sorry(m18n('Player %1 already exists', currentName)) self.setFocus() del self._data[ unicode(self.table.item(self.table.currentRow(), 0).text())] self.updateTable(currentName=currentName) return query = Query('insert into player(name) values(?)', (currentName, )) if query.failure: Sorry( m18n( 'Error while adding player %1: %2', currentName, query.failure.message)) self.updateTable(currentName=currentName) def slotInsert(self): """insert a record""" self._data[''] = 0 self.updateTable(data=self._data, currentName='') for row in range(len(self._data)): item = self.table.item(row, 0) if len(item.text()) == 0: self.table.editItem(item) def delete(self): """delete selected entries""" items = self.table.selectedItems() currentRow = self.table.currentRow() if len(items): name = unicode(items[0].text()) playerId = self._data[name] query = Query( "select 1 from game where p0=? or p1=? or p2=? or p3=?", (playerId, ) * 4) if len(query.records): Sorry( m18n('This player cannot be deleted. There are games associated with %1.', name)) return Query("delete from player where name=?", (name,)) self.updateTable() self.table.setCurrentCell(min(currentRow, len(self._data) - 1), 0) def keyPressEvent(self, event): """use insert/delete keys for insert/delete""" key = event.key() if key == Qt.Key_Insert: self.slotInsert() elif key == Qt.Key_Delete: self.delete() else: QDialog.keyPressEvent(self, event)
class PlayerList(QDialog): """QtSQL Model view of the players""" def __init__(self, parent): QDialog.__init__(self) self.parent = parent self._data = {} self.table = QTableWidget(self) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) self.table.setEditTriggers(QTableWidget.NoEditTriggers) self.table.itemChanged.connect(self.itemChanged) self.updateTable() self.buttonBox = QDialogButtonBox() self.buttonBox.setStandardButtons( QDialogButtonBox.Close) # Close has the Rejected role self.buttonBox.rejected.connect(self.accept) self.newButton = self.buttonBox.addButton( i18nc('define a new player', "&New"), QDialogButtonBox.ActionRole) self.newButton.setIcon(KIcon("document-new")) self.newButton.clicked.connect(self.slotInsert) self.deleteButton = self.buttonBox.addButton( i18n("&Delete"), QDialogButtonBox.ActionRole) self.deleteButton.setIcon(KIcon("edit-delete")) self.deleteButton.clicked.connect(self.delete) cmdLayout = QHBoxLayout() cmdLayout.addWidget(self.buttonBox) layout = QVBoxLayout() layout.addWidget(self.table) layout.addLayout(cmdLayout) self.setLayout(layout) decorateWindow(self, i18n("Players")) self.setObjectName('Players') def showEvent(self, dummyEvent): """adapt view to content""" StateSaver(self, self.table) @staticmethod def sortKey(text): """display order in Table""" if len(text) == 0: return 'zzzzzzzzzzzz' else: return text.upper() def updateTable(self, data=None, currentName=None): """fills self.table from DB""" self.table.itemChanged.disconnect(self.itemChanged) table = self.table table.clear() if data is None: data = dict( Query('select name, id from player where name not like "ROBOT %"').records) self._data = data table.setColumnCount(1) table.setRowCount(len(self._data)) table.setHorizontalHeaderLabels([i18n("Player")]) table.setSelectionBehavior(QTableWidget.SelectRows) table.setSelectionMode(QTableWidget.SingleSelection) selectedItem = None for row, name in enumerate(sorted(self._data, key=self.sortKey)): item = QTableWidgetItem(name) if selectedItem is None: selectedItem = item table.setItem(row, 0, item) if name == currentName: selectedItem = item if selectedItem: table.setCurrentItem(selectedItem) table.scrollToItem(selectedItem) self.table.itemChanged.connect(self.itemChanged) def itemChanged(self, item): """this must be new because editing is disabled for others""" currentName = item.text() if currentName in self._data: Sorry(i18n('Player %1 already exists', currentName)) self.setFocus() del self._data[self.table.item(self.table.currentRow(), 0).text()] self.updateTable(currentName=currentName) return query = Query('insert into player(name) values(?)', (currentName, )) if query.failure: Sorry( i18n( 'Error while adding player %1: %2', currentName, query.failure.message)) self.updateTable(currentName=currentName) def slotInsert(self): """insert a record""" self._data[''] = 0 self.updateTable(data=self._data, currentName='') for row in range(len(self._data)): item = self.table.item(row, 0) if len(item.text()) == 0: self.table.editItem(item) def delete(self): """delete selected entries""" items = self.table.selectedItems() currentRow = self.table.currentRow() if len(items): name = items[0].text() playerId = self._data[name] query = Query( "select 1 from game where p0=? or p1=? or p2=? or p3=?", (playerId, ) * 4) if len(query.records): Sorry( i18n('This player cannot be deleted. There are games associated with %1.', name)) return Query("delete from player where name=?", (name,)) self.updateTable() self.table.setCurrentCell(min(currentRow, len(self._data) - 1), 0) def keyPressEvent(self, event): """use insert/delete keys for insert/delete""" key = event.key() if key == Qt.Key_Insert: self.slotInsert() elif key == Qt.Key_Delete: self.delete() else: QDialog.keyPressEvent(self, event)
class Games(QDialog): """a dialog for selecting a game""" def __init__(self, parent=None): super(Games, self).__init__(parent) self.selectedGame = None self.onlyPending = True decorateWindow(self, i18nc('kajongg', 'Games')) self.setObjectName('Games') self.resize(700, 400) self.model = GamesModel() if Debug.modelTest: self.modelTest = ModelTest(self.model, self) self.view = MJTableView(self) self.view.setModel(self.model) self.selection = QItemSelectionModel(self.model, self.view) self.view.setSelectionModel(self.selection) self.view.setSelectionBehavior(QAbstractItemView.SelectRows) self.view.setSelectionMode(QAbstractItemView.SingleSelection) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel) self.newButton = self.buttonBox.addButton( i18nc('start a new game', "&New"), QDialogButtonBox.ActionRole) self.newButton.setIcon(KIcon("document-new")) self.newButton.clicked.connect(self.accept) self.loadButton = self.buttonBox.addButton( i18n("&Load"), QDialogButtonBox.AcceptRole) self.loadButton.clicked.connect(self.loadGame) self.loadButton.setIcon(KIcon("document-open")) self.deleteButton = self.buttonBox.addButton( i18n("&Delete"), QDialogButtonBox.ActionRole) self.deleteButton.setIcon(KIcon("edit-delete")) self.deleteButton.clicked.connect(self.delete) chkPending = QCheckBox(i18n("Show only pending games"), self) chkPending.setChecked(True) cmdLayout = QHBoxLayout() cmdLayout.addWidget(chkPending) cmdLayout.addWidget(self.buttonBox) layout = QVBoxLayout() layout.addWidget(self.view) layout.addLayout(cmdLayout) self.setLayout(layout) StateSaver(self) self.selection.selectionChanged.connect(self.selectionChanged) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.view.doubleClicked.connect(self.loadGame) chkPending.stateChanged.connect(self.pendingOrNot) def showEvent(self, dummyEvent): """only now get the data set. Not doing this in__init__ would eventually make it easier to subclass from some generic TableEditor class""" self.setQuery() self.view.initView() self.selectionChanged() def keyPressEvent(self, event): """use insert/delete keys for insert/delete""" key = event.key() if key == Qt.Key_Insert: self.newEntry() return if key == Qt.Key_Delete: self.delete() event.ignore() return QDialog.keyPressEvent(self, event) def selectionChanged(self): """update button states according to selection""" selectedRows = len(self.selection.selectedRows()) self.loadButton.setEnabled(selectedRows == 1) self.deleteButton.setEnabled(selectedRows >= 1) def setQuery(self): """define the query depending on self.OnlyPending""" query = Query( "select g.id, g.starttime, " "p0.name||'///'||p1.name||'///'||p2.name||'///'||p3.name " "from game g, player p0," "player p1, player p2, player p3 " "where seed is null" " and p0.id=g.p0 and p1.id=g.p1 " " and p2.id=g.p2 and p3.id=g.p3 " "%s" "and exists(select 1 from score where game=g.id)" % ("and g.endtime is null " if self.onlyPending else "")) self.model.setResultset(query.records) self.view.hideColumn(0) def __idxForGame(self, game): """returns the model index for game""" for row in range(self.model.rowCount()): idx = self.model.index(row, 0) if self.model.data(idx, 0) == game: return idx return self.model.index(0, 0) def __getSelectedGame(self): """returns the game id of the selected game""" rows = self.selection.selectedRows() if rows: return self.model.data(rows[0], 0) else: return 0 def pendingOrNot(self, chosen): """do we want to see all games or only pending games?""" if self.onlyPending != chosen: self.onlyPending = chosen prevSelected = self.__getSelectedGame() self.setQuery() idx = self.__idxForGame(prevSelected) self.view.selectRow(idx.row()) self.view.setFocus() def loadGame(self): """load a game""" self.selectedGame = self.__getSelectedGame() self.buttonBox.accepted.emit() def delete(self): """delete a game""" def answered(result, games): """question answered, result is True or False""" if result: for game in games: Query("DELETE FROM score WHERE game = ?", (game, )) Query("DELETE FROM game WHERE id = ?", (game, )) self.setQuery() # just reload entire table allGames = self.view.selectionModel().selectedRows(0) deleteGames = list(x.data() for x in allGames) if len(deleteGames) == 0: # should never happen logException('delete: 0 rows selected') WarningYesNo( i18n( "Do you really want to delete <numid>%1</numid> games?<br>" "This will be final, you cannot cancel it with " "the cancel button", len(deleteGames))).addCallback(answered, deleteGames)
class Games(QDialog): """a dialog for selecting a game""" def __init__(self, parent=None): super(Games, self).__init__(parent) self.selectedGame = None self.onlyPending = True decorateWindow(self, m18nc('kajongg', 'Games')) self.setObjectName('Games') self.resize(700, 400) self.model = GamesModel() if Debug.modelTest: self.modelTest = ModelTest(self.model, self) self.view = MJTableView(self) self.view.setModel(self.model) self.selection = QItemSelectionModel(self.model, self.view) self.view.setSelectionModel(self.selection) self.view.setSelectionBehavior(QAbstractItemView.SelectRows) self.view.setSelectionMode(QAbstractItemView.SingleSelection) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel) self.newButton = self.buttonBox.addButton( m18nc('start a new game', "&New"), QDialogButtonBox.ActionRole) self.newButton.setIcon(KIcon("document-new")) self.newButton.clicked.connect(self.accept) self.loadButton = self.buttonBox.addButton( m18n("&Load"), QDialogButtonBox.AcceptRole) self.loadButton.clicked.connect(self.loadGame) self.loadButton.setIcon(KIcon("document-open")) self.deleteButton = self.buttonBox.addButton( m18n("&Delete"), QDialogButtonBox.ActionRole) self.deleteButton.setIcon(KIcon("edit-delete")) self.deleteButton.clicked.connect(self.delete) chkPending = QCheckBox(m18n("Show only pending games"), self) chkPending.setChecked(True) cmdLayout = QHBoxLayout() cmdLayout.addWidget(chkPending) cmdLayout.addWidget(self.buttonBox) layout = QVBoxLayout() layout.addWidget(self.view) layout.addLayout(cmdLayout) self.setLayout(layout) StateSaver(self) self.selection.selectionChanged.connect(self.selectionChanged) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.view.doubleClicked.connect(self.loadGame) chkPending.stateChanged.connect(self.pendingOrNot) def showEvent(self, dummyEvent): """only now get the data set. Not doing this in__init__ would eventually make it easier to subclass from some generic TableEditor class""" self.setQuery() self.view.initView() self.selectionChanged() def keyPressEvent(self, event): """use insert/delete keys for insert/delete""" key = event.key() if key == Qt.Key_Insert: self.newEntry() return if key == Qt.Key_Delete: self.delete() event.ignore() return QDialog.keyPressEvent(self, event) def selectionChanged(self): """update button states according to selection""" selectedRows = len(self.selection.selectedRows()) self.loadButton.setEnabled(selectedRows == 1) self.deleteButton.setEnabled(selectedRows >= 1) def setQuery(self): """define the query depending on self.OnlyPending""" query = Query( "select g.id, g.starttime, " "p0.name||'///'||p1.name||'///'||p2.name||'///'||p3.name " "from game g, player p0," "player p1, player p2, player p3 " "where seed is null" " and p0.id=g.p0 and p1.id=g.p1 " " and p2.id=g.p2 and p3.id=g.p3 " "%s" "and exists(select 1 from score where game=g.id)" % ("and g.endtime is null " if self.onlyPending else "")) self.model.setResultset(query.records) self.view.hideColumn(0) def __idxForGame(self, game): """returns the model index for game""" for row in range(self.model.rowCount()): idx = self.model.index(row, 0) if variantValue(self.model.data(idx, 0)) == game: return idx return self.model.index(0, 0) def __getSelectedGame(self): """returns the game id of the selected game""" rows = self.selection.selectedRows() if rows: return variantValue(self.model.data(rows[0], 0)) else: return 0 def pendingOrNot(self, chosen): """do we want to see all games or only pending games?""" if self.onlyPending != chosen: self.onlyPending = chosen prevSelected = self.__getSelectedGame() self.setQuery() idx = self.__idxForGame(prevSelected) self.view.selectRow(idx.row()) self.view.setFocus() def loadGame(self): """load a game""" self.selectedGame = self.__getSelectedGame() self.buttonBox.accepted.emit() def delete(self): """delete a game""" def answered(result, games): """question answered, result is True or False""" if result: for game in games: Query("DELETE FROM score WHERE game = ?", (game, )) Query("DELETE FROM game WHERE id = ?", (game, )) self.setQuery() # just reload entire table allGames = self.view.selectionModel().selectedRows(0) deleteGames = list(variantValue(x.data()) for x in allGames) if len(deleteGames) == 0: # should never happen logException('delete: 0 rows selected') WarningYesNo( m18n( "Do you really want to delete <numid>%1</numid> games?<br>" "This will be final, you cannot cancel it with " "the cancel button", len(deleteGames))).addCallback(answered, deleteGames)
def __init__(self, client): super(TableList, self).__init__(None) self.autoStarted = False self.client = client self.setObjectName('TableList') self.resize(700, 400) self.view = MJTableView(self) self.differ = None self.debugModelTest = None self.requestedNewTable = False self.view.setItemDelegateForColumn( 2, RichTextColumnDelegate(self.view)) buttonBox = QDialogButtonBox(self) self.newButton = buttonBox.addButton( m18nc('allocate a new table', "&New"), QDialogButtonBox.ActionRole) self.newButton.setIcon(KIcon("document-new")) self.newButton.setToolTip(m18n("Allocate a new table")) self.newButton.clicked.connect(self.client.newTable) self.joinButton = buttonBox.addButton( m18n("&Join"), QDialogButtonBox.AcceptRole) self.joinButton.clicked.connect(client.joinTable) self.joinButton.setIcon(KIcon("list-add-user")) self.joinButton.setToolTip(m18n("Join a table")) self.leaveButton = buttonBox.addButton( m18n("&Leave"), QDialogButtonBox.AcceptRole) self.leaveButton.clicked.connect(self.leaveTable) self.leaveButton.setIcon(KIcon("list-remove-user")) self.leaveButton.setToolTip(m18n("Leave a table")) self.compareButton = buttonBox.addButton( m18nc('Kajongg-Ruleset', 'Compare'), QDialogButtonBox.AcceptRole) self.compareButton.clicked.connect(self.compareRuleset) self.compareButton.setIcon(KIcon("preferences-plugin-script")) self.compareButton.setToolTip( m18n('Compare the rules of this table with my own rulesets')) self.chatButton = buttonBox.addButton( m18n('&Chat'), QDialogButtonBox.AcceptRole) self.chatButton.setIcon(KIcon("call-start")) self.chatButton.clicked.connect(self.chat) self.startButton = buttonBox.addButton( m18n('&Start'), QDialogButtonBox.AcceptRole) self.startButton.clicked.connect(self.startGame) self.startButton.setIcon(KIcon("arrow-right")) self.startButton.setToolTip( m18n("Start playing on a table. " "Empty seats will be taken by robot players.")) cmdLayout = QHBoxLayout() cmdLayout.addWidget(buttonBox) layout = QVBoxLayout() layout.addWidget(self.view) layout.addLayout(cmdLayout) self.setLayout(layout) self.view.doubleClicked.connect(client.joinTable) StateSaver(self, self.view.horizontalHeader()) self.updateButtonsForTable(None)