def showMoveHelper(self, visible=None): """show help text In empty HandBoards""" if visible is None: visible = not self.uiTiles if self.__moveHelper and not isAlive(self.__moveHelper): return if visible: if not self.__moveHelper: splitter = QGraphicsRectItem(self) hbCenter = self.rect().center() splitter.setRect( hbCenter.x() * 0.5, hbCenter.y(), hbCenter.x() * 1, 1) helpItems = [splitter] for name, yFactor in [(m18n('Move Exposed Tiles Here'), 0.5), (m18n('Move Concealed Tiles Here'), 1.5)]: helper = QGraphicsSimpleTextItem(name, self) helper.setScale(3) nameRect = QRectF() nameRect.setSize( helper.mapToParent(helper.boundingRect()).boundingRect().size()) center = QPointF(hbCenter) center.setY(center.y() * yFactor) helper.setPos(center - nameRect.center()) if self.sceneRotation() == 180: rotateCenter(helper, 180) helpItems.append(helper) self.__moveHelper = self.scene().createItemGroup(helpItems) self.__moveHelper.setVisible(True) else: if self.__moveHelper: self.__moveHelper.setVisible(False)
def toolTip(self, button, dummyTile): """decorate the action button which will send this message""" myself = button.client.game.myself maySay = myself.sayable[self] if not maySay: return '', False, '' txt = [] warn = False if myself.originalCall and myself.mayWin: warn = True txt.append(m18n('saying %1 violates Original Call', self.i18nName)) dangerousMelds = myself.maybeDangerous(self) if dangerousMelds: lastDiscard = myself.game.lastDiscard warn = True if Debug.dangerousGame and len(dangerousMelds) != len(maySay): button.client.game.debug( 'only some claimable melds are dangerous: %s' % dangerousMelds) if len(dangerousMelds) == 1: txt.append(m18n( 'claiming %1 is dangerous because you will have to discard a dangerous tile', lastDiscard.name())) else: for meld in dangerousMelds: txt.append(m18n( 'claiming %1 for %2 is dangerous because you will have to discard a dangerous tile', lastDiscard.name(), str(meld))) if not txt: txt = [m18n('You may say %1', self.i18nName)] return '<br><br>'.join(txt), warn, ''
def refresh(self): """refresh for new values""" lines = [] if self.game is None: lines.append(m18n("There is no active game")) else: i18nName = m18n(self.game.ruleset.name) lines.append(m18n("%1", i18nName)) lines.append("") for player in self.game.players: pLines = [] explainHand = player.explainHand() if explainHand.hasTiles(): total = explainHand.total() if total: pLines = ["%s - %s" % (player.localName, total)] for line in explainHand.explain(): pLines.append("- " + line) elif player.handTotal: pLines.append(m18n("Manual score for %1: %2 points", player.localName, player.handTotal)) if pLines: pLines.append("") lines.extend(pLines) if "xxx".join(lines) != "xxx".join(unicode(x) for x in self.model.stringList()): # QStringListModel does not optimize identical lists away, so we do self.model.setStringList(lines)
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 tooltip(self): """tooltip for rule: just the name of the ruleset""" ruleset = self.ruleset() if self.rawContent.description: return u'<b>' + m18n(ruleset.name) + u'</b><br><br>' + \ m18n(self.rawContent.description) else: return m18n(ruleset.name)
def __init__(self, swappers): QMessageBox.__init__(self) decorateWindow(self, m18n("Swap Seats")) self.setText( m18n("By the rules, %1 and %2 should now exchange their seats. ", swappers[0].name, swappers[1].name)) self.yesAnswer = QPushButton(m18n("&Exchange")) self.addButton(self.yesAnswer, QMessageBox.YesRole) self.noAnswer = QPushButton(m18n("&Keep seat")) self.addButton(self.noAnswer, QMessageBox.NoRole)
def name(self): """returns name of a single tile""" if self.group.lower() == Tile.wind: result = { East: m18n("East Wind"), South: m18n("South Wind"), West: m18n("West Wind"), North: m18n("North Wind"), }[self.value] else: result = m18nc("kajongg tile name", "{group} {value}") return result.format(value=self.valueName(), group=self.groupName())
def __init__(self, desktopFileName=None): if desktopFileName is None: desktopFileName = 'default' self.__svg = None self.__pmap = None QPixmapCache.setCacheLimit(20480) # the chinese landscape needs much self.defineCatalog() self.desktopFileName = desktopFileName self.path = locatebackground(desktopFileName + '.desktop') if self.path.isEmpty(): self.path = locatebackground('default.desktop') if self.path.isEmpty(): directories = '\n\n' + \ '\n'.join(str(x) for x in KGlobal.dirs().resourceDirs("kmahjonggbackground")) logException(BackgroundException(m18n( 'cannot find any background in the following directories, is libkmahjongg installed?') + directories)) else: logWarning( m18n( 'cannot find background %1, using default', desktopFileName)) self.desktopFileName = 'default' config = KConfig(self.path) group = config.group("KMahjonggBackground") self.name = group.readEntry("Name") or m18n("unknown background") # Version control backgroundversion = int(group.readEntry("VersionFormat")) or 0 # Format is increased when we have incompatible changes, meaning that # older clients are not able to use the remaining information safely if backgroundversion > BACKGROUNDVERSIONFORMAT: logException(BackgroundException('backgroundversion file / program: %d/%d' % (backgroundversion, BACKGROUNDVERSIONFORMAT))) self.tiled = group.readEntry('Tiled') == '1' if self.tiled: self.imageWidth, entryOk = group.readEntry('Width').toInt() if not entryOk: raise Exception('cannot scan Width from background file') self.imageHeight, entryOk = group.readEntry('Height').toInt() if not entryOk: raise Exception('cannot scan Height from background file') self.isPlain = bool(group.readEntry('Plain')) if not self.isPlain: graphName = QString(group.readEntry("FileName")) self.__graphicspath = locatebackground(graphName) if self.__graphicspath.isEmpty(): logException(BackgroundException( 'cannot find kmahjongglib/backgrounds/%s for %s' % (graphName, self.desktopFileName)))
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 toolTip(self, button, tile): """decorate the action button which will send this message""" assert isinstance(tile, Tile), tile myself = button.client.game.myself isCalling = bool((myself.hand - tile).callingHands) if not isCalling: txt = m18n( 'discarding %1 and declaring Original Call makes this hand unwinnable', tile.name()) return txt, True, txt else: return (m18n( 'Discard a tile, declaring Original Call meaning you need only one ' 'tile to complete the hand and will not alter the hand in any way (except bonus tiles)'), False, '')
def __init__(self, parent, name): # pylint: disable=super-init-not-called KConfigDialog.__init__( self, parent, QString(name), Internal.Preferences) StateSaver(self) self.pages = [ self.addPage( PlayConfigTab(self), m18nc('kajongg', 'Play'), "arrow-right"), self.addPage( TilesetSelector(self), m18n("Tiles"), "games-config-tiles"), self.addPage( BackgroundSelector(self), m18n("Backgrounds"), "games-config-background")]
def headerData(self, section, orientation, role): """tell the view about the wanted headers""" if role == Qt.TextAlignmentRole: if orientation == Qt.Horizontal: return toQVariant(int(Qt.AlignLeft | Qt.AlignVCenter)) if role != Qt.DisplayRole: return toQVariant() if orientation == Qt.Horizontal: if section == 0: return toQVariant(m18nc("Kajongg", "Rule")) if section == 1: return toQVariant(m18n(self.view.cbRuleset1.current.name)) if section == 2: return toQVariant(m18n(self.view.cbRuleset2.current.name)) return toQVariant()
def remote_tableRemoved(self, tableid, message, *args): """update table list""" Client.remote_tableRemoved(self, tableid, message, *args) self.__updateTableList() if message: if self.name not in args or not message.endswith('has logged out'): logWarning(m18n(message, *args))
def notifyAction(self, client, move): if client.beginQuestion or client.game: Sorry(m18n('%1 is not ready to start the game', move.player.name)) if client.beginQuestion: client.beginQuestion.cancel() elif client.game: return client.game.close()
def toolTip(self, button, dummyTile): """decorate the action button which will send this message""" myself = button.client.game.myself maySay = myself.sayable[self] if not maySay: return '', False, '' txt = [] warn = False if myself.originalCall and myself.mayWin: warn = True txt.append( m18n('saying Kong for %1 violates Original Call', Tile(maySay[0][0]).name())) if not txt: txt = [m18n('You may say Kong for %1', Tile(maySay[0][0]).name())] return '<br><br>'.join(txt), warn, ''
def _saveScores(self): """save computed values to database, update score table and balance in status line""" scoretime = datetime.datetime.now().replace(microsecond=0).isoformat() logMessage = u'' for player in self.players: if player.hand: manualrules = '||'.join(x.rule.name for x in player.hand.usedRules) else: manualrules = m18n('Score computed manually') Query( "INSERT INTO SCORE " "(game,hand,data,manualrules,player,scoretime,won,prevailing," "wind,points,payments, balance,rotated,notrotated) " "VALUES(%d,%d,?,?,%d,'%s',%d,'%s','%s',%d,%d,%d,%d,%d)" % (self.gameid, self.handctr, player.nameid, scoretime, int(player == self.__winner), self.roundWind.char, player.wind, player.handTotal, player.payment, player.balance, self.rotated, self.notRotated), (player.hand.string, manualrules)) logMessage += u'{player:<12} {hand:>4} {total:>5} {won} | '.format( player=unicode(player)[:12], hand=player.handTotal, total=player.balance, won='WON' if player == self.winner else ' ') for usedRule in player.hand.usedRules: rule = usedRule.rule if rule.score.limits: self.addCsvTag(rule.name.replace(' ', '')) if Debug.scores: self.debug(logMessage)
def __init__(self): SelectRuleset.__init__(self) Players.load() decorateWindow(self, m18n('Select four players')) self.names = None self.nameWidgets = [] for idx, wind in enumerate(Wind.all4): cbName = QComboBox() cbName.manualSelect = False # increase width, we want to see the full window title cbName.setMinimumWidth(350) # is this good for all platforms? cbName.addItems(list(Players.humanNames.values())) self.grid.addWidget(cbName, idx + 1, 1) self.nameWidgets.append(cbName) self.grid.addWidget(WindLabel(wind), idx + 1, 0) cbName.currentIndexChanged.connect(self.slotValidate) query = Query( "select p0,p1,p2,p3 from game where seed is null and game.id = (select max(id) from game)") if len(query.records): with BlockSignals(self.nameWidgets): for cbName, playerId in zip(self.nameWidgets, query.records[0]): try: playerName = Players.humanNames[playerId] playerIdx = cbName.findText(playerName) if playerIdx >= 0: cbName.setCurrentIndex(playerIdx) except KeyError: logError(u'database is inconsistent: player with id %d is in game but not in player' % playerId) self.slotValidate()
def __getName(playerid): """get name for playerid """ try: return Players.allNames[playerid] except KeyError: return m18n('Player %1 not known', playerid)
def __upgrade(self): """upgrade the structure of an existing kajongg database""" try: Internal.db = DBHandle(self.path) if isPython3: allVersions = list(['4.13.0', '8300']) else: allVersions = list(['4.13.0', '8200']) assert allVersions[-1] == str(Internal.defaultPort), '{} != {}'.format( allVersions[-1], str(Internal.defaultPort)) # skip versions before current db versions: currentVersion = self.__currentVersion() while allVersions and allVersions[0] <= currentVersion: allVersions = allVersions[1:] for version in allVersions: currentVersion = self.__currentVersion() with Internal.db: # transaction updateMethodName = 'updateToVersion{}'.format(version.replace('.', '_')) if hasattr(self, updateMethodName): getattr(self, updateMethodName)() Query('UPDATE general SET schemaversion=?', (version,)) logInfo(m18n('Database %1 updated from schema %2 to %3', Internal.db.path, currentVersion, version), showDialog=True) except sqlite3.Error as exc: logException( u'opening %s: %s' % (unicodeString(self.path), exc.message)) finally: Internal.db.close(silent=True)
def tableChanged(self, table): """update table list""" oldTable, newTable = Client.tableChanged(self, table) if oldTable and oldTable == self.table: # this happens if a table has more than one human player and # one of them leaves the table. In that case, the other players # need this code. self.table = newTable if len(newTable.playerNames) == 3: # only tell about the first player leaving, because the # others will then automatically leave too for name in oldTable.playerNames: if name != self.name and not newTable.isOnline(name): def sorried(dummy): """user ack""" game = self.game if game: self.game = None return game.close() if self.beginQuestion: self.beginQuestion.cancel() Sorry(m18n('Player %1 has left the table', name)).addCallback( sorried).addCallback(self.showTableList) break self.__updateTableList()
def data(self, index, role=Qt.DisplayRole): """score table""" result = toQVariant() if role == Qt.TextAlignmentRole: if index.column() == 1: return toQVariant(int(Qt.AlignRight)) else: return toQVariant(int(Qt.AlignLeft)) if index.isValid() and (0 <= index.row() < len(self.chatLines)): chatLine = self.chatLines[index.row()] if role == Qt.DisplayRole and index.column() == 0: local = chatLine.localtimestamp() result = toQVariant('%02d:%02d:%02d' % ( local.hour, local.minute, local.second)) elif role == Qt.DisplayRole and index.column() == 1: result = toQVariant(chatLine.fromUser) elif role == Qt.DisplayRole and index.column() == 2: result = toQVariant(m18n(chatLine.message)) elif role == Qt.ForegroundRole and index.column() == 2: palette = KApplication.palette() # pylint: disable=no-member color = 'blue' if chatLine.isStatusMessage else palette.windowText( ) result = toQVariant(QColor(color)) return result
def headerData(self, section, orientation, role=Qt.DisplayRole): # pylint: disable=no-self-use """show header""" if role == Qt.TextAlignmentRole: if orientation == Qt.Horizontal: if section == 1: return toQVariant(int(Qt.AlignRight)) else: return toQVariant(int(Qt.AlignLeft)) if orientation != Qt.Horizontal: return toQVariant(int(section + 1)) if role != Qt.DisplayRole: return toQVariant() result = '' if section < self.columnCount(): result = [m18n('Time'), m18n('Player'), m18n('Message')][section] return toQVariant(result)
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 __init__(self, scene=None, table=None): super(ChatWindow, self).__init__(None) self.scene = scene self.table = table or scene.game.client.table self.table.chatWindow = self self.setObjectName('chatWindow') title = m18n( 'Chat on table %1 at %2', self.table.tableid, self.table.client.connection.url) decorateWindow(self, title) self.messageView = ChatView() self.messageView.setModel(ChatModel()) self.messageView.setFocusPolicy(Qt.NoFocus) self.messageView.setShowGrid(False) self.messageView.setWordWrap(False) self.messageView.setSelectionMode(QAbstractItemView.NoSelection) if Debug.modelTest: self.debugModelTest = ModelTest( self.messageView.model(), self.messageView) self.edit = QLineEdit() layout = QVBoxLayout() layout.addWidget(self.messageView) layout.addWidget(self.edit) self.setLayout(layout) self.edit.returnPressed.connect(self.sendLine) self.edit.setFocus() self.show() StateSaver(self)
def renderer(self): """initialise the svg renderer with the selected svg file""" if self.__renderer is None: self.__renderer = QSvgRenderer(self.__graphicspath) if not self.__renderer.isValid(): logException(TileException( m18n( 'file <filename>%1</filename> contains no valid SVG'), self.__graphicspath)) distance = 0 if self.desktopFileName == 'classic': distance = 2 distanceSize = QSizeF(distance, distance) self.faceSize = self.__renderer.boundsOnElement( 'BAMBOO_1').size() + distanceSize self.tileSize = self.__renderer.boundsOnElement( 'TILE_2').size() + distanceSize if not Internal.scaleScene: self.faceSize /= 2 self.tileSize /= 2 shW = self.shadowWidth() shH = self.shadowHeight() self.__shadowOffsets = [ [(-shW, 0), (0, 0), (0, shH), (-shH, shW)], [(0, 0), (shH, 0), (shW, shH), (0, shW)], [(0, -shH), (shH, -shW), (shW, 0), (0, 0)], [(-shW, -shH), (0, -shW), (0, 0), (-shH, 0)]] return self.__renderer
def refresh(self): """load this game and this player. Keep parameter list identical with ExplainView""" if not self.game: # keep scores of previous game on display return if self.scoreModel: expandGroups = [self.viewLeft.isExpanded(self.scoreModel.index(x, 0, QModelIndex())) for x in range(4)] else: expandGroups = [True, False, True, True] gameid = str(self.game.seed or self.game.gameid) if self.game.finished(): title = m18n("Final scores for game <numid>%1</numid>", gameid) else: title = m18n("Scores for game <numid>%1</numid>", gameid) decorateWindow(self, title) self.ruleTree.rulesets = list([self.game.ruleset]) self.scoreModel = ScoreModel(self) if Debug.modelTest: self.scoreModelTest = ModelTest(self.scoreModel, self) for view in [self.viewLeft, self.viewRight]: view.setModel(self.scoreModel) header = view.header() header.setStretchLastSection(False) view.setAlternatingRowColors(True) if usingQt5: self.viewRight.header().setSectionResizeMode(QHeaderView.Fixed) else: self.viewRight.header().setResizeMode(QHeaderView.Fixed) for col in range(self.viewLeft.header().count()): self.viewLeft.header().setSectionHidden(col, col > 0) self.viewRight.header().setSectionHidden(col, col == 0) self.scoreLayout.setStretch(1, 100) self.scoreLayout.setSpacing(0) self.viewLeft.setFrameStyle(QFrame.NoFrame) self.viewRight.setFrameStyle(QFrame.NoFrame) self.viewLeft.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) for master, slave in ((self.viewRight, self.viewLeft), (self.viewLeft, self.viewRight)): master.expanded.connect(slave.expand) master.collapsed.connect(slave.collapse) master.verticalScrollBar().valueChanged.connect(slave.verticalScrollBar().setValue) for row, expand in enumerate(expandGroups): self.viewLeft.setExpanded(self.scoreModel.index(row, 0, QModelIndex()), expand) self.viewLeft.resizeColumnToContents(0) self.viewRight.setColWidth() # we need a timer since the scrollbar is not yet visible QTimer.singleShot(0, self.scrollRight)
def addManualRules(self): """those are actually winner rules but in the kajongg scoring mode they must be selected manually""" # applicable only if we have a concealed meld and a declared kong: self.winnerRules.createRule( 'Last Tile Taken from Dead Wall', 'FLastTileFromDeadWall||Olastsource=e', doubles=1, description=m18n('The dead wall is also called kong box: The last 16 tiles of the wall ' 'used as source of replacement tiles')) self.winnerRules.createRule( 'Last Tile is Last Tile of Wall', 'FIsLastTileFromWall||Olastsource=z', doubles=1, description=m18n('Winner said Mah Jong with the last tile taken from the living end of the wall')) self.winnerRules.createRule( 'Last Tile is Last Tile of Wall Discarded', 'FIsLastTileFromWallDiscarded||Olastsource=Z', doubles=1, description=m18n('Winner said Mah Jong by claiming the last tile taken from the living end of the ' 'wall, discarded by another player')) self.winnerRules.createRule( 'Robbing the Kong', r'FRobbingKong||Olastsource=k', doubles=1, description=m18n('Winner said Mah Jong by claiming the 4th tile of a kong another player ' 'just declared'), debug=True) self.winnerRules.createRule( 'Mah Jongg with Original Call', 'FMahJonggWithOriginalCall||Oannouncements=a', doubles=1, description=m18n( 'Just before the first discard, a player can declare Original Call meaning she needs only one ' 'tile to complete the hand and announces she will not alter the hand in any way (except bonus tiles)')) self.winnerRules.createRule( 'Dangerous Game', 'FDangerousGame||Opayforall', description=m18n('In some situations discarding a tile that has a high chance to help somebody to win ' 'is declared to be dangerous, and if that tile actually makes somebody win, the discarder ' 'pays the winner for all')) self.winnerRules.createRule( 'Twofold Fortune', 'FTwofoldFortune||Oannouncements=t', limits=1, description=m18n('Kong after Kong: Declare Kong and a second Kong with the replacement ' 'tile and Mah Jong with the second replacement tile')) # limit hands: self.winnerRules.createRule( 'Blessing of Heaven', 'FBlessingOfHeaven||Olastsource=1', limits=1, description=m18n('East says Mah Jong with the unmodified dealt tiles')) self.winnerRules.createRule( 'Blessing of Earth', 'FBlessingOfEarth||Olastsource=1', limits=1, description=m18n('South, West or North says Mah Jong with the first tile discarded by East')) self.winnerRules.createRule( 'East won nine times in a row', 'FEastWonNineTimesInARow||Orotate', limits=1, description=m18n('If that happens, East gets a limit score and the winds rotate'))
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 __noTilesetFound(): """No tilesets found""" directories = '\n'.join( str(x) for x in KGlobal.dirs().resourceDirs("kmahjonggtileset")) directories = '\n\n' + directories logException( TileException(m18n( 'cannot find any tileset in the following directories, ' 'is libkmahjongg installed?') + directories))
def __init__(self, scene): QListView.__init__(self) self.scene = scene decorateWindow(self, m18n("Explain Scores").replace("&", "")) self.setGeometry(0, 0, 300, 400) self.model = QStringListModel() self.setModel(self.model) StateSaver(self) self.refresh()