Example #1
0
class PlayerList(QDialog):
    """QtSQL Model view of the players"""
    def __init__(self, parent):
        QDialog.__init__(self)
        self.parent = parent
        self.model = QSqlTableModel(self, DBHandle.default)
        self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.model.setTable("player")
        self.model.setSort(1, 0)
        self.model.setHeaderData(1, Qt.Horizontal, QVariant(m18nc("Player", "Name")))
        self.model.setFilter('name not like "ROBOT %" and name not like "Robot %"')
        self.view = MJTableView(self)
        self.view.verticalHeader().show()
        self.view.setModel(self.model)
        self.view.hideColumn(0)
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        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.view)
        layout.addLayout(cmdLayout)
        self.setLayout(layout)

        self.setWindowTitle(m18n("Players") + ' - Kajongg')
        self.setObjectName('Players')

    def showEvent(self, dummyEvent):
        """adapt view to content"""
        if not self.model.select():
            logError("PlayerList: select failed")
            sys.exit(1)
        self.view.initView()
        StateSaver(self, self.view.horizontalHeader())
        if not self.view.isColumnHidden(2):
            # we loaded a kajonggrc written by an older kajongg version where this table
            # still had more columns. This should happen only once.
            self.view.hideColumn(2)
            self.view.hideColumn(3)

    def accept(self):
        """commit all modifications"""
        self.view.selectRow(0) # if ALT-O is entered while editing a new row, this is one way
        # to end editing and to pass the new value to the model
        if not self.model.submitAll():
            Sorry(m18n('Cannot save this. Possibly the name already exists. <br><br>' \
                    'Message from database:<br><br><message>%1</message>',
                    self.model.lastError().text()))
            return
        QDialog.accept(self)

    def slotInsert(self):
        """insert a record"""
        self.model.insertRow(self.model.rowCount())
        self.view.selectRow(self.model.rowCount()-1)

    def delete(self):
        """delete selected entries"""
        sel = self.view.selectionModel()
        maxDel = self.view.currentIndex().row() - 1
        for idx in sel.selectedIndexes():
            if idx.column() != 1:
                continue
            # sqlite3 does not enforce referential integrity.
            # we could add a trigger to sqlite3 but if it raises an exception
            # it will be thrown away silently.
            # if anybody knows how to propagate sqlite3 exceptions via QtSql
            # into python please tell me (wrohdewald)
            player = self.model.createIndex(idx.row(), 0).data().toInt()[0]
            # no query preparation, we don't expect lots of data
            if Query("select 1 from game where p0==%d or p1==%d or p2==%d or p3==%d" % \
                (player, player, player, player)).records:
                Sorry(m18n('This player cannot be deleted. There are games associated with %1.',
                        idx.data().toString()))
            else:
                self.model.removeRow(idx.row())
                maxDel = max(maxDel, idx.row())
        self.view.selectRow(maxDel+1)

    def keyPressEvent(self, event):
        """use insert/delete keys for insert/delete"""
        key = event.key()
        if key == Qt.Key_Insert:
            self.slotInsert()
            return
        QDialog.keyPressEvent(self, event)
Example #2
0
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
        self.setWindowTitle(m18nc('kajongg', 'Games') + ' - Kajongg')
        self.setObjectName('Games')
        self.resize(700, 400)
        self.model = GamesModel(self)
        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 = "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.setQuery(query, DBHandle.default)
        self.model.setHeaderData(1, Qt.Horizontal, QVariant(m18n("Started")))
        self.model.setHeaderData(2, Qt.Horizontal, QVariant(m18n("Players")))
        self.view.hideColumn(0)

    def __idxForGame(self, game):
        """returns the model index for game"""
        for row in range(self.model.rowCount()):
            if self.model.record(row).field(0).value().toInt()[0] == game:
                return self.model.index(row, 0)
        return self.model.index(0, 0)

    def pendingOrNot(self, chosen):
        """do we want to see all games or only pending games?"""
        if self.onlyPending != chosen:
            self.onlyPending = chosen
            idx = self.view.currentIndex()
            selectedGame = self.model.record(idx.row()).value(0).toInt()[0]
            self.setQuery()
            idx = self.__idxForGame(selectedGame)
            self.view.selectRow(idx.row())
        self.view.setFocus()

    def loadGame(self):
        """load a game"""
        selnum = len(self.selection.selectedRows())
        if selnum != 1:
            # should never happen
            logException('loadGame: %d rows selected' % selnum)
        idx = self.view.currentIndex()
        self.selectedGame = self.model.record(idx.row()).value(0).toInt()[0]
        self.buttonBox.accepted.emit()

    def delete(self):
        """delete a game"""
        def answered(result, games):
            """question answered, result is True or False"""
            if result:
                cmdList = []
                for game in games:
                    cmdList.append("DELETE FROM score WHERE game = %d" % game)
                    cmdList.append("DELETE FROM game WHERE id = %d" % game)
                Query(cmdList)
                self.setQuery()  # just reload entire table

        deleteGames = list(x.data().toInt()[0]
                           for x in self.view.selectionModel().selectedRows(0))
        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)
Example #3
0
class PlayerList(QDialog):
    """QtSQL Model view of the players"""
    def __init__(self, parent):
        QDialog.__init__(self)
        self.parent = parent
        self.model = QSqlTableModel(self, DBHandle.default)
        self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.model.setTable("player")
        self.model.setSort(1, 0)
        self.model.setHeaderData(1, Qt.Horizontal,
                                 QVariant(m18nc("Player", "Name")))
        self.model.setFilter(
            'name not like "ROBOT %" and name not like "Robot %"')
        self.view = MJTableView(self)
        self.view.verticalHeader().show()
        self.view.setModel(self.model)
        self.view.hideColumn(0)
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        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.view)
        layout.addLayout(cmdLayout)
        self.setLayout(layout)

        self.setWindowTitle(m18n("Players") + ' - Kajongg')
        self.setObjectName('Players')

    def showEvent(self, dummyEvent):
        """adapt view to content"""
        if not self.model.select():
            logError("PlayerList: select failed")
            sys.exit(1)
        self.view.initView()
        StateSaver(self, self.view.horizontalHeader())
        if not self.view.isColumnHidden(2):
            # we loaded a kajonggrc written by an older kajongg version where this table
            # still had more columns. This should happen only once.
            self.view.hideColumn(2)
            self.view.hideColumn(3)

    def accept(self):
        """commit all modifications"""
        self.view.selectRow(
            0)  # if ALT-O is entered while editing a new row, this is one way
        # to end editing and to pass the new value to the model
        if not self.model.submitAll():
            Sorry(m18n('Cannot save this. Possibly the name already exists. <br><br>' \
                    'Message from database:<br><br><message>%1</message>',
                    self.model.lastError().text()))
            return
        QDialog.accept(self)

    def slotInsert(self):
        """insert a record"""
        self.model.insertRow(self.model.rowCount())
        self.view.selectRow(self.model.rowCount() - 1)

    def delete(self):
        """delete selected entries"""
        sel = self.view.selectionModel()
        maxDel = self.view.currentIndex().row() - 1
        for idx in sel.selectedIndexes():
            if idx.column() != 1:
                continue
            # sqlite3 does not enforce referential integrity.
            # we could add a trigger to sqlite3 but if it raises an exception
            # it will be thrown away silently.
            # if anybody knows how to propagate sqlite3 exceptions via QtSql
            # into python please tell me (wrohdewald)
            player = self.model.createIndex(idx.row(), 0).data().toInt()[0]
            # no query preparation, we don't expect lots of data
            if Query("select 1 from game where p0==%d or p1==%d or p2==%d or p3==%d" % \
                (player, player, player, player)).records:
                Sorry(
                    m18n(
                        'This player cannot be deleted. There are games associated with %1.',
                        idx.data().toString()))
            else:
                self.model.removeRow(idx.row())
                maxDel = max(maxDel, idx.row())
        self.view.selectRow(maxDel + 1)

    def keyPressEvent(self, event):
        """use insert/delete keys for insert/delete"""
        key = event.key()
        if key == Qt.Key_Insert:
            self.slotInsert()
            return
        QDialog.keyPressEvent(self, event)