def slotValidate(self): """try to find 4 different players and update status of the Ok button""" changedCombo = self.sender() if not isinstance(changedCombo, QComboBox): changedCombo = self.nameWidgets[0] changedCombo.manualSelect = True allNames = set(Players.humanNames.values()) unusedNames = allNames - self.__selectedNames() with BlockSignals(self.nameWidgets): used = set([unicode(x.currentText()) for x in self.nameWidgets if x.manualSelect]) for combo in self.nameWidgets: if not combo.manualSelect: if unicode(combo.currentText()) in used: comboName = unusedNames.pop() combo.clear() combo.addItems([comboName]) used.add(unicode(combo.currentText())) for combo in self.nameWidgets: comboName = unicode(combo.currentText()) combo.clear() combo.addItems([comboName]) combo.addItems(sorted( allNames - self.__selectedNames() - set([comboName]))) combo.setCurrentIndex(0) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled( len(self.__selectedNames()) == 4) self.names = list(unicode(cbName.currentText()) for cbName in self.nameWidgets)
def __setRuleData(self, column, content, value): """change rule data in the model""" dirty, message = False, None if column == 0: name = unicode(value) if content.name != english(name): dirty = True content.name = english(name) elif column == 1 and isinstance(content, ParameterRule): oldParameter = content.parameter if isinstance(content, IntRule): if content.parameter != value.toInt()[0]: dirty = True content.parameter = value.toInt()[0] elif isinstance(content, BoolRule): return False, '' elif isinstance(content, StrRule): if content.parameter != unicode(value): dirty = True content.parameter = unicode(value) else: if content.parameter != unicode(value): dirty = True content.parameter = unicode(value) message = content.validate() if message: content.parameter = oldParameter dirty = False else: unitName = str(self.rootItem.content(column).toString()) dirty, message = content.score.change(unitName, value) return dirty, message
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 __unicode__(self): return u'%s requests=%s outstanding=%d %s callback=%s' % ( self.debugPrefix(), u'[' + u','.join(unicode(x) for x in self.requests) + u']', self.outstanding, u'is completed' if self.completed else u'not completed', self.prettyCallback())
def remote_newTables(self, tables): """update table list""" newTables = list(ClientTable(self, *x) for x in tables) self.tables.extend(newTables) if Debug.table: _ = u', '.join(unicode(ClientTable(self, *x)) for x in tables) logDebug(u'%s got new tables:%s' % (self.name, _))
def stopGamesWithRegex(): """we do not support Regex rules anymore. Mark all games using them as finished - until somebody complains. So for now always return False""" if not Internal.db.hasTable('usedrule'): return usedRegexRulesets = Query("select distinct ruleset from usedrule " "where definition not like 'F%' " "and definition not like 'O%' " "and definition not like 'int%' " "and definition not like 'bool%' " "and definition<>'' " "and definition not like 'XEAST9X%'").records usedRegexRulesets = list(unicode(x[0]) for x in usedRegexRulesets) if not usedRegexRulesets: return openRegexGames = Query("select id from game " "where endtime is null " "and ruleset in (%s)" % ','.join(usedRegexRulesets)).records openRegexGames = list(x[0] for x in openRegexGames) if not openRegexGames: return logInfo( 'Marking games using rules with regular expressions as finished: %s' % openRegexGames) for openGame in openRegexGames: endtime = datetime.datetime.now().replace( microsecond=0).isoformat() Query('update game set endtime=? where id=?', (endtime, openGame))
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 removeRequest(self, request): """we do not want this request anymore""" self.requests.remove(request) if not request.answer: self.outstanding -= 1 if Debug.deferredBlock: self.debug(u'-:%d' % self.outstanding, unicode(request)) self.callbackIfDone()
def popupMsg(self, msg): """shows a yellow message from player""" if msg != Message.NoClaim: self.speak(msg.name.lower()) yellow = self.front.message yellow.setText( ' '.join([unicode(yellow.msg), m18nc('kajongg', msg.name)])) yellow.setVisible(True)
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 __unicode__(self): local = self.localtimestamp() # pylint: disable=no-member # pylint says something about NotImplemented, check with later versions return u'statusMessage=%s %02d:%02d:%02d %s: %s' % ( unicode(self.isStatusMessage), local.hour, local.minute, local.second, self.fromUser, m18n(self.message))
def mapChar2Arrow(event): """maps the keys hjkl to arrows like in vi and konqueror""" key = event.key() if key in Board.arrows: return key charArrows = m18nc( 'kajongg:arrow keys hjkl like in konqueror', 'hjklHJKL') key = unicode(event.text()) if key and key in charArrows: key = Board.arrows[charArrows.index(key) % 4] return key
def xToUtf8(msg, args=None): """makes sure msg and all args are utf-8""" if isPython3: if args is not None: return msg, args else: return msg if isinstance(msg, unicode): msg = msg.encode('utf-8') elif not isinstance(msg, str): msg = unicode(msg).encode('utf-8') if args is not None: args = list(args[:]) for idx, arg in enumerate(args): if isinstance(arg, unicode): args[idx] = arg.encode('utf-8') elif not isinstance(arg, str): args[idx] = unicode(arg).encode('utf-8') return msg, args else: return msg
def cacheDir(): """the cache directory for this user""" if Internal.isServer: result = os.path.join(appdataDir(), 'cache') else: result = os.path.dirname( unicode(KGlobal.dirs().locateLocal("cache", ""))) result = os.path.join(result, 'kajongg') if not os.path.exists(result): try: os.makedirs(result) except OSError: pass return result
def sendLine(self, line=None, isStatusMessage=False): """send line to others. Either the edited line or parameter line.""" if line is None: line = unicode(self.edit.text()) self.edit.clear() if line: if Debug.chat: logDebug(u'sending line %s to others' % line) msg = ChatMessage( self.table.tableid, self.table.client.name, line, isStatusMessage) self.table.client.sendChat(msg).addErrback(self.chatError)
def __unicode__(self): cmd = self.deferred.command if self.answer: answer = unicode(self.answer) else: answer = u'OPEN' result = u'' if Debug.deferredBlock: result += u'[{id:>4}] '.format(id=id(self) % 10000) result += u'{cmd}->{cls}({receiver:<10}): {answer}'.format( cls=self.user.__class__.__name__, cmd=cmd, receiver=self.user.name, answer=answer) if self.age(): result += u' after {} sec'.format(self.age()) return result
def content(self, column): """return the content stored in this node""" colNames = self.parent.parent.parent.rawContent content = self.rawContent if column == 0: return m18n(content.name) else: if isinstance(content, ParameterRule): if column == 1: return content.parameter else: if not hasattr(content.score, str(column)): column = colNames[column] return unicode(getattr(content.score, column)) return ''
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 setData(self, index, value, role=Qt.EditRole): """change data in the model""" # pylint: disable=too-many-branches if not index.isValid(): return False try: dirty = False column = index.column() item = index.internalPointer() ruleset = item.ruleset() content = item.rawContent if role == Qt.EditRole: if isinstance(content, Ruleset) and column == 0: name = unicode(value) oldName = content.name content.rename(english(name)) dirty = oldName != content.name elif isinstance(content, RuleBase): dirty, message = self.__setRuleData(column, content, value) if message: Sorry(message) return False else: return False elif role == Qt.CheckStateRole: if isinstance(content, BoolRule) and column == 1: if not isinstance(ruleset, PredefinedRuleset): newValue = value == Qt.Checked if content.parameter != newValue: dirty = True content.parameter = newValue else: return False if dirty: if isinstance(content, RuleBase): ruleset.updateRule(content) self.dataChanged.emit(index, index) return True except BaseException: return False
def data(self, index, role=None): """get score table from view""" if role is None: role = Qt.DisplayRole if not (index.isValid() and role == Qt.DisplayRole): return toQVariant() if role == Qt.DisplayRole: unformatted = unicode( self._resultRows[index.row()][index.column()]) if index.column() == 2: # we do not yet use this for listing remote games but if we do # this translation is needed for robot players names = [m18n(name) for name in unformatted.split('///')] return toQVariant(', '.join(names)) elif index.column() == 1: dateVal = datetime.datetime.strptime( unformatted, '%Y-%m-%dT%H:%M:%S') return toQVariant(nativeString(dateVal.strftime('%c'))) elif index.column() == 0: return toQVariant(int(unformatted)) with RealQVariant(): return QAbstractTableModel.data(self, index, role)
def decoratePlayer(self, player): """show player info on the wall""" side = player.front sideCenter = side.center() name = side.nameLabel name.setText( ' - '.join([player.localName, unicode(player.explainHand().total())])) name.resetTransform() if side.rotation() == 180: rotateCenter(name, 180) nameRect = QRectF() nameRect.setSize( name.mapToParent(name.boundingRect()).boundingRect().size()) name.setPos(sideCenter - nameRect.center()) player.colorizeName() side.windTile.setWind(player.wind, self.game.roundsFinished) side.windTile.resetTransform() side.windTile.setPos( sideCenter.x() * 1.63, sideCenter.y() - side.windTile.rect().height() / 2.5) side.nameLabel.show() side.windTile.show()
def appdataDir(): """ The per user directory with kajongg application information like the database. @return: The directory path. @rtype: C{str}. """ serverDir = os.path.expanduser('~/.kajonggserver/') if Internal.isServer: # the server might or might not have KDE installed, so to be on # the safe side we use our own .kajonggserver directory # the following code moves an existing kajonggserver.db to .kajonggserver # but only if .kajonggserver does not yet exist kdehome = os.environ.get('KDEHOME', '~/.kde') oldPath = os.path.expanduser( kdehome + '/share/apps/kajongg/kajonggserver.db') if not os.path.exists(oldPath): oldPath = os.path.expanduser( '~/.kde4/share/apps/kajongg/kajonggserver.db') if os.path.exists(oldPath) and not os.path.exists(serverDir): # upgrading an old kajonggserver installation os.makedirs(serverDir) shutil.move(oldPath, serverDir) if not os.path.exists(serverDir): try: os.makedirs(serverDir) except OSError: pass return serverDir else: if not os.path.exists(serverDir): # the client wants to place the socket in serverDir os.makedirs(serverDir) result = os.path.dirname( unicode(KGlobal.dirs().locateLocal("appdata", ""))) + '/' return result
def __exceptionToString(exception): """ Convert exception into a useful string for logging. @param exception: The exception to be logged. @type exception: C{Exception} @rtype: C{unicode} """ parts = [] for arg in exception.args: if hasattr(arg, 'strerror'): # when using pykde4, this is already translated at this point # but I do not know what it does differently with gettext and if # I can do the same with the python gettext module parts.append( u'[Errno {}] {}'.format(arg.errno, m18n(arg.strerror))) elif arg is None: pass else: parts.append(unicode(arg)) if hasattr(exception, 'filename'): parts.append(exception.filename) return u' '.join(parts)
def __unicode__(self): return unicode(self.char)
RULESETS = [] # test each of those rulesets twice: once with limit, once with roof off for testRuleset in [ClassicalChineseDMJL, ClassicalChineseBMJA] * 2: _ = testRuleset() _.load() RULESETS.append(_) for _ in RULESETS[2:]: _.roofOff = True # Do not create our test players in the data base: Players.createIfUnknown = str # RULESETS=RULESETS[:1] GAMES = list([PlayingGame(list(tuple([wind, unicode(wind.char)]) for wind in Wind.all4), x) for x in RULESETS]) PROGRAM = None class Expected(object): """define what we expect from test""" def __init__(self, won, points, doubles, limits): self.won = won self.score = Score(points, doubles, limits) def __str__(self): if self.won: return 'Won with %s' % self.score
def logBug(self, msg): """log msg and raise exception""" for request in self.requests: logDebug(unicode(request)) logException(msg)
def __selectedNames(self): """A set with the currently selected names""" return set(list(unicode(cbName.currentText()) for cbName in self.nameWidgets))