Пример #1
0
    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')
Пример #2
0
    def __init__(self):
        """self.servers is a list of tuples containing server and last playername"""
        QDialog.__init__(self, None)
        self.setWindowTitle(m18n('Login') + ' - Kajongg')
        self.setupUi()

        localName = m18nc('kajongg name for local game server', Query.localServerName)
        self.servers = Query('select url,lastname from server order by lasttime desc').records
        servers = [m18nc('kajongg name for local game server', x[0]) for x in self.servers]
        # the first server combobox item should be default: either the last used server
        # or localName for autoPlay
        if localName not in servers:
            servers.append(localName)
        if 'kajongg.org' not in servers:
            servers.append('kajongg.org')
            demoHost = Options.host or localName
            if demoHost in servers:
                servers.remove(demoHost)  # we want a unique list, it will be re-used for all following games
            servers.insert(0, demoHost)   # in this process but they will not be autoPlay
        self.cbServer.addItems(servers)
        self.passwords = Query('select url, p.name, passwords.password from passwords, player p '
            'where passwords.player=p.id').records
        Players.load()
        self.cbServer.editTextChanged.connect(self.serverChanged)
        self.cbUser.editTextChanged.connect(self.userChanged)
        self.serverChanged()
        StateSaver(self)
Пример #3
0
    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)
Пример #4
0
 def contentStr(self):
     """make score readable for humans, i18n"""
     parts = []
     if self.points:
         parts.append(m18nc('Kajongg', '%1 points', self.points))
     if self.doubles:
         parts.append(m18nc('Kajongg', '%1 doubles', self.doubles))
     if self.limits:
         parts.append(m18nc('Kajongg', '%1 limits', self.limits))
     return ' '.join(parts)
Пример #5
0
 def contentStr(self):
     """make score readable for humans, i18n"""
     parts = []
     if self.points:
         parts.append(m18nc('Kajongg', '%1 points', self.points))
     if self.doubles:
         parts.append(m18nc('Kajongg', '%1 doubles', self.doubles))
     if self.limits:
         parts.append(m18nc('Kajongg', '%1 limits', self.limits))
     return ' '.join(parts)
Пример #6
0
 def status(self):
     """a status string"""
     result = ''
     if self.suspendedAt:
         result = m18nc('table status', 'Suspended')
         result += ' ' + datetime.datetime.strptime(
             self.suspendedAt,
             '%Y-%m-%dT%H:%M:%S').strftime('%c').decode('utf-8')
     if self.running:
         result += ' ' + m18nc('table status', 'Running')
     return result or m18nc('table status', 'New')
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
0
 def setupUi(self):
     """create all Ui elements but do not fill them"""
     buttonBox = KDialogButtonBox(self)
     buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
     # Ubuntu 11.10 unity is a bit strange - without this, it sets focus on
     # the cancel button (which it shows on the left). I found no obvious
     # way to use setDefault and setAutoDefault for fixing this.
     buttonBox.button(QDialogButtonBox.Ok).setFocus(True)
     buttonBox.accepted.connect(self.accept)
     buttonBox.rejected.connect(self.reject)
     vbox = QVBoxLayout(self)
     self.grid = QFormLayout()
     self.cbServer = QComboBox()
     self.cbServer.setEditable(True)
     self.grid.addRow(m18n('Game server:'), self.cbServer)
     self.cbUser = QComboBox()
     self.cbUser.setEditable(True)
     self.grid.addRow(m18n('Username:'******'Password:'******'kajongg', 'Ruleset:'), self.cbRuleset)
     vbox.addLayout(self.grid)
     vbox.addWidget(buttonBox)
     pol = QSizePolicy()
     pol.setHorizontalPolicy(QSizePolicy.Expanding)
     self.cbUser.setSizePolicy(pol)
Пример #10
0
 def setupUi(self):
     """create all Ui elements but do not fill them"""
     buttonBox = KDialogButtonBox(self)
     buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                  | QDialogButtonBox.Ok)
     # Ubuntu 11.10 unity is a bit strange - without this, it sets focus on
     # the cancel button (which it shows on the left). I found no obvious
     # way to use setDefault and setAutoDefault for fixing this.
     buttonBox.button(QDialogButtonBox.Ok).setFocus(True)
     buttonBox.accepted.connect(self.accept)
     buttonBox.rejected.connect(self.reject)
     vbox = QVBoxLayout(self)
     self.grid = QFormLayout()
     self.cbServer = QComboBox()
     self.cbServer.setEditable(True)
     self.grid.addRow(m18n('Game server:'), self.cbServer)
     self.cbUser = QComboBox()
     self.cbUser.setEditable(True)
     self.grid.addRow(m18n('Username:'******'Password:'******'kajongg', 'Ruleset:'), self.cbRuleset)
     vbox.addLayout(self.grid)
     vbox.addWidget(buttonBox)
     pol = QSizePolicy()
     pol.setHorizontalPolicy(QSizePolicy.Expanding)
     self.cbUser.setSizePolicy(pol)
Пример #11
0
 def __navigateScoringGame(self, event):
     """keyboard navigation in a scoring game"""
     mod = event.modifiers()
     key = event.key()
     wind = chr(key % 128)
     moveCommands = m18nc('kajongg:keyboard commands for moving tiles to the players ' \
         'with wind ESWN or to the central tile selector (X)', 'ESWNX')
     tile = self.centralScene.focusItem().tile
     if wind in moveCommands:
         # translate i18n wind key to ESWN:
         wind = 'ESWNX'[moveCommands.index(wind)]
         self.__moveTile(tile, wind, mod & Qt.ShiftModifier)
         return True
     if key == Qt.Key_Tab and self.game:
         tabItems = [self.selectorBoard]
         tabItems.extend(
             list(p.handBoard for p in self.game.players
                  if p.handBoard.tiles))
         tabItems.append(tabItems[0])
         currentBoard = tile.board if isinstance(tile, Tile) else None
         currIdx = 0
         while tabItems[currIdx] != currentBoard and currIdx < len(
                 tabItems) - 2:
             currIdx += 1
         tabItems[currIdx + 1].hasFocus = True
         return True
Пример #12
0
 def validateParameter(self):
     """check for validity"""
     if 'min' in self.options:
         minValue = self.parType(self.options['min'])
         if self.parameter < minValue:
             return m18nc('wrong value for rule', '%1: %2 is too small, minimal value is %3',
                 m18n(self.name), self.parameter, minValue)
Пример #13
0
 def updateButtonsForTable(self, table):
     """update button status for the currently selected table"""
     hasTable = bool(table)
     suspended = hasTable and bool(table.suspendedAt)
     running = hasTable and table.running
     suspendedLocalGame = suspended and table.gameid and self.client.hasLocalServer()
     self.joinButton.setEnabled(hasTable and
         not running and
         not table.isOnline(self.client.name) and
         (self.client.name in table.playerNames) == suspended)
     self.leaveButton.setVisible(not (suspendedLocalGame))
     self.compareButton.setVisible(not (suspendedLocalGame))
     self.startButton.setVisible(not suspended)
     if suspendedLocalGame:
         self.newButton.setToolTip(m18n("Start a new game"))
         self.joinButton.setText(m18nc('resuming a local suspended game', '&Resume'))
         self.joinButton.setToolTip(m18n("Resume the selected suspended game"))
     else:
         self.newButton.setToolTip(m18n("Allocate a new table"))
         self.joinButton.setText(m18n('&Join'))
         self.joinButton.setToolTip(m18n("Join a table"))
     self.leaveButton.setEnabled(hasTable and not running and not self.joinButton.isEnabled())
     self.startButton.setEnabled(not running and not suspendedLocalGame and hasTable \
         and self.client.name == table.playerNames[0])
     self.compareButton.setEnabled(hasTable and table.myRuleset is None)
     self.chatButton.setVisible(not self.client.hasLocalServer())
     self.chatButton.setEnabled(not running and hasTable and self.client.name in table.playerNames
         and sum(x.startswith('Robot ') for x in table.playerNames) < 3)
     if self.chatButton.isEnabled():
         self.chatButton.setToolTip(m18n("Chat with others on this table"))
     else:
         self.chatButton.setToolTip(m18n("For chatting with others on this table, please first take a seat"))
Пример #14
0
 def setupUi(self):
     """layout the window"""
     self.setWindowTitle(m18n('Customize rulesets') + ' - Kajongg')
     self.setObjectName('Rulesets')
     hlayout = QHBoxLayout(self)
     v1layout = QVBoxLayout()
     self.v1widget = QWidget()
     v1layout = QVBoxLayout(self.v1widget)
     v2layout = QVBoxLayout()
     hlayout.addWidget(self.v1widget)
     hlayout.addLayout(v2layout)
     for widget in [self.v1widget, hlayout, v1layout, v2layout]:
         widget.setContentsMargins(0, 0, 0, 0)
     hlayout.setStretchFactor(self.v1widget, 10)
     self.btnCopy = QPushButton()
     self.btnRemove = QPushButton()
     self.btnCompare = QPushButton()
     self.btnClose = QPushButton()
     self.rulesetView = RuleTreeView(m18nc('kajongg','Rule'), self.btnCopy, self.btnRemove, self.btnCompare)
     v1layout.addWidget(self.rulesetView)
     self.rulesetView.setWordWrap(True)
     self.rulesetView.setMouseTracking(True)
     spacerItem = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
     v2layout.addWidget(self.btnCopy)
     v2layout.addWidget(self.btnRemove)
     v2layout.addWidget(self.btnCompare)
     self.btnCopy.clicked.connect(self.rulesetView.copyRow)
     self.btnRemove.clicked.connect(self.rulesetView.removeRow)
     self.btnCompare.clicked.connect(self.rulesetView.compareRow)
     self.btnClose.clicked.connect(self.hide)
     v2layout.addItem(spacerItem)
     v2layout.addWidget(self.btnClose)
     self.retranslateUi()
     StateSaver(self)
     self.show()
Пример #15
0
 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)
Пример #16
0
 def formattedDiffs(self):
     """a list of tuples with 3 values: name, left, right"""
     formatted = []
     leftRuleset = self.cbRuleset1.current
     rightRuleset = self.cbRuleset2.current
     assert rightRuleset, self.cbRuleset2.count()
     leftRuleset.load()
     rightRuleset.load()
     for rule1, rule2 in leftRuleset.diff(rightRuleset):
         name = m18n(rule1.name if rule1 else rule2.name)
         left = rule1.contentStr() if rule1 else m18nc("Kajongg-Rule", "not defined")
         right = rule2.contentStr() if rule2 else m18nc("Kajongg-Rule", "not defined")
         formatted.append((name, left, right))
         if rule1 and rule2 and rule1.definition != rule2.definition:
             formatted.append(("", rule1.definition, rule2.definition))
     return formatted
Пример #17
0
 def setupUi(self):
     """setup UI elements"""
     self.viewLeft = ScoreViewLeft(self)
     self.viewRight = ScoreViewRight(self)
     self.viewRight.setHorizontalScrollBar(HorizontalScrollBar(self))
     self.viewRight.setHorizontalScrollMode(QAbstractItemView.ScrollPerItem)
     self.viewRight.setFocusPolicy(Qt.NoFocus)
     self.viewRight.header().setClickable(False)
     self.viewRight.header().setMovable(False)
     self.viewRight.setSelectionMode(QAbstractItemView.NoSelection)
     windowLayout = QVBoxLayout(self)
     self.splitter = QSplitter(Qt.Vertical)
     self.splitter.setObjectName('ScoreTableSplitter')
     windowLayout.addWidget(self.splitter)
     scoreWidget = QWidget()
     self.scoreLayout = QHBoxLayout(scoreWidget)
     leftLayout = QVBoxLayout()
     leftLayout.addWidget(self.viewLeft)
     self.leftLayout = leftLayout
     self.scoreLayout.addLayout(leftLayout)
     self.scoreLayout.addWidget(self.viewRight)
     self.splitter.addWidget(scoreWidget)
     self.ruleTree = RuleTreeView(m18nc('kajongg','Used Rules'))
     self.splitter.addWidget(self.ruleTree)
     # this shows just one line for the ruleTree - so we just see the
     # name of the ruleset:
     self.splitter.setSizes(list([1000, 1]))
Пример #18
0
 def validateDefinition(self, prevDefinition):
     """check for validity. If wrong, restore prevDefinition."""
     payers = int(self.options.get('payers', 1))
     payees = int(self.options.get('payees', 1))
     if not 2 <= payers + payees <= 4:
         self.definition = prevDefinition
         logException(m18nc('%1 can be a sentence', '%4 have impossible values %2/%3 in rule "%1"',
                               self.name, payers, payees, 'payers/payees'))
Пример #19
0
 def validateParameter(self):
     """check for validity"""
     if 'min' in self.options:
         minValue = self.parType(self.options['min'])
         if self.parameter < minValue:
             return m18nc('wrong value for rule',
                          '%1: %2 is too small, minimal value is %3',
                          m18n(self.name), self.parameter, minValue)
Пример #20
0
 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)
Пример #21
0
 def formattedDiffs(self):
     """a list of tuples with 3 values: name, left, right"""
     formatted = []
     leftRuleset = self.cbRuleset1.current
     rightRuleset = self.cbRuleset2.current
     assert rightRuleset, self.cbRuleset2.count()
     leftRuleset.load()
     rightRuleset.load()
     for rule1, rule2 in leftRuleset.diff(rightRuleset):
         name = m18n(rule1.name if rule1 else rule2.name)
         left = rule1.contentStr() if rule1 else m18nc(
             'Kajongg-Rule', 'not defined')
         right = rule2.contentStr() if rule2 else m18nc(
             'Kajongg-Rule', 'not defined')
         formatted.append((name, left, right))
         if rule1 and rule2 and rule1.definition != rule2.definition:
             formatted.append(('', rule1.definition, rule2.definition))
     return formatted
Пример #22
0
 def validateDefinition(self, prevDefinition):
     """check for validity. If wrong, restore prevDefinition."""
     payers = int(self.options.get('payers', 1))
     payees = int(self.options.get('payees', 1))
     if not 2 <= payers + payees <= 4:
         self.definition = prevDefinition
         logException(
             m18nc('%1 can be a sentence',
                   '%4 have impossible values %2/%3 in rule "%1"',
                   self.name, payers, payees, 'payers/payees'))
Пример #23
0
 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
Пример #24
0
 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
Пример #25
0
 def __init__(self, parent, name):
     super(ConfigDialog, self).__init__(parent, QString(name), Preferences)
     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")]
     StateSaver(self)
Пример #26
0
    def __init__(self, name):
        """name may be:
            - an integer: ruleset.id from the sql table
            - a list: the full ruleset specification (probably sent from the server)
            - a string: The hash value of a ruleset"""
        self.name = name
        self.rulesetId = 0
        self.__hash = None
        self.allRules = []
        self.__dirty = False  # only the ruleset editor is supposed to make us dirty
        self.__loaded = False
        self.__filteredLists = {}
        self.description = None
        self.rawRules = None  # used when we get the rules over the network
        self.splitRules = []
        self.doublingMeldRules = []
        self.doublingHandRules = []
        self.meldRules = RuleList(
            1, m18n('Meld Rules'),
            m18n(
                'Meld rules are applied to single melds independent of the rest of the hand'
            ))
        self.handRules = RuleList(
            2, m18n('Hand Rules'),
            m18n('Hand rules are applied to the entire hand, for all players'))
        self.winnerRules = RuleList(
            3, m18n('Winner Rules'),
            m18n(
                'Winner rules are applied to the entire hand but only for the winner'
            ))
        self.loserRules = RuleList(
            33, m18n('Loser Rules'),
            m18n(
                'Loser rules are applied to the entire hand but only for non-winners'
            ))
        self.mjRules = RuleList(
            4, m18n('Mah Jongg Rules'),
            m18n('Only hands matching a Mah Jongg rule can win'))
        self.parameterRules = RuleList(
            999, m18nc('kajongg', 'Options'),
            m18n('Here we have several special game related options'))
        self.penaltyRules = RuleList(
            9999, m18n('Penalties'),
            m18n(
                """Penalties are applied manually by the user. They are only used for scoring games.
When playing against the computer or over the net, Kajongg will never let you get
into a situation where you have to pay a penalty"""))
        self.ruleLists = list([
            self.meldRules, self.handRules, self.mjRules, self.winnerRules,
            self.loserRules, self.parameterRules, self.penaltyRules
        ])
        # the order of ruleLists is the order in which the lists appear in the ruleset editor
        # if you ever want to remove an entry from ruleLists: make sure its listId is not reused or you get
        # in trouble when updating
        self._initRuleset()
Пример #27
0
 def __init__(self, parent, name):
     super(ConfigDialog, self).__init__(parent, QString(name), Preferences)
     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")
     ]
     StateSaver(self)
Пример #28
0
 def data(self, index, role=Qt.DisplayRole):
     """score table"""
     # pylint: disable=R0912,R0914
     # pylint too many branches
     result = QVariant()
     if role == Qt.TextAlignmentRole:
         if index.column() == 0:
             result = QVariant(int(Qt.AlignHCenter | Qt.AlignVCenter))
         else:
             result = QVariant(int(Qt.AlignLeft | Qt.AlignVCenter))
     if index.isValid() and (0 <= index.row() < len(self.tables)):
         table = self.tables[index.row()]
         if role == Qt.DisplayRole and index.column() in (0, 1):
             result = QVariant(table.tableid)
         elif role == Qt.DisplayRole and index.column() == 2:
             players = []
             zipped = zip(table.playerNames, table.playersOnline)
             for idx, pair in enumerate(zipped):
                 name, online = pair[0], pair[1]
                 if idx < len(zipped) - 1:
                     name += ', '
                 palette = KApplication.palette()
                 if online:
                     color = palette.color(QPalette.Active,
                                           QPalette.WindowText).name()
                     style = 'font-weight:normal;font-style:normal;color:%s' % color
                 else:
                     color = palette.color(QPalette.Disabled,
                                           QPalette.WindowText).name()
                     style = 'font-weight:100;font-style:italic;color:%s' % color
                 players.append('<nobr style="%s">' % style + name +
                                '</nobr>')
             names = ''.join(players)
             result = QVariant(names)
         elif role == Qt.DisplayRole and index.column() == 3:
             status = table.status()
             if table.suspendedAt:
                 dateVal = ' ' + datetime.datetime.strptime(
                     table.suspendedAt,
                     '%Y-%m-%dT%H:%M:%S').strftime('%c').decode('utf-8')
                 status = 'Suspended'
             else:
                 dateVal = ''
             result = QVariant(m18nc('table status', status) + dateVal)
         elif index.column() == 4:
             if role == Qt.DisplayRole:
                 result = QVariant(
                     m18n((table.myRuleset
                           if table.myRuleset else table.ruleset).name))
             elif role == Qt.ForegroundRole:
                 palette = KApplication.palette()
                 color = palette.windowText() if table.myRuleset else 'red'
                 result = QVariant(QColor(color))
     return result
Пример #29
0
 def __init__(self, game):
     QWidget.__init__(self, None)
     self.game = None
     self.setWindowTitle(m18n('Scoring for this Hand') + ' - Kajongg')
     self.nameLabels = [None] * 4
     self.spValues = [None] * 4
     self.windLabels = [None] * 4
     self.wonBoxes = [None] * 4
     self.detailsLayout = [None] * 4
     self.details = [None] * 4
     self.__tilePixMaps = []
     self.__meldPixMaps = []
     grid = QGridLayout(self)
     pGrid = QGridLayout()
     grid.addLayout(pGrid, 0, 0, 2, 1)
     pGrid.addWidget(QLabel(m18nc('kajongg', "Player")), 0, 0)
     pGrid.addWidget(QLabel(m18nc('kajongg', "Wind")), 0, 1)
     pGrid.addWidget(QLabel(m18nc('kajongg', 'Score')), 0, 2)
     pGrid.addWidget(QLabel(m18n("Winner")), 0, 3)
     self.detailTabs = QTabWidget()
     self.detailTabs.setDocumentMode(True)
     pGrid.addWidget(self.detailTabs, 0, 4, 8, 1)
     for idx in range(4):
         self.setupUiForPlayer(pGrid, idx)
     self.draw = QCheckBox(m18nc('kajongg','Draw'))
     self.draw.clicked.connect(self.wonChanged)
     btnPenalties = QPushButton(m18n("&Penalties"))
     btnPenalties.clicked.connect(self.penalty)
     self.btnSave = QPushButton(m18n('&Save Hand'))
     self.btnSave.setEnabled(False)
     self.setupUILastTileMeld(pGrid)
     pGrid.setRowStretch(87, 10)
     pGrid.addWidget(self.draw, 7, 3)
     self.cbLastTile.currentIndexChanged.connect(self.slotLastTile)
     self.cbLastMeld.currentIndexChanged.connect(self.slotInputChanged)
     btnBox = QHBoxLayout()
     btnBox.addWidget(btnPenalties)
     btnBox.addWidget(self.btnSave)
     pGrid.addLayout(btnBox, 8, 4)
     StateSaver(self)
     self.refresh(game)
Пример #30
0
 def penaltyChanged(self):
     """total has changed, update payments"""
     # normally value is only validated when leaving the field
     self.spPenalty.interpretText()
     offense = self.cbCrime.current
     penalty = self.spPenalty.value()
     payers = int(offense.options.get('payers', 1))
     payees = int(offense.options.get('payees', 1))
     payerAmount = -penalty // payers
     payeeAmount = penalty // payees
     for pList, amount, count in ((self.payers, payerAmount, payers), (self.payees, payeeAmount, payees)):
         for idx, player in enumerate(pList):
             player.setVisible(idx<count)
             player.lblPayment.setVisible(idx<count)
             if idx < count:
                 if pList == self.payers:
                     player.lblPayment.setText(m18nc('penalty dialog, appears behind paying player combobox',
                         'pays %1 points', -amount))
                 else:
                     player.lblPayment.setText(m18nc('penalty dialog, appears behind profiting player combobox',
                         'gets %1 points', amount))
Пример #31
0
 def _newKey(self, minus=False):
     """generate a new id and a new name if the name already exists"""
     newId = self.newId(minus=minus)
     newName = self.name
     if minus:
         copyNr = 1
         while self.nameExists(newName):
             copyStr = ' ' + str(copyNr) if copyNr > 1 else ''
             newName = m18nc('Ruleset._newKey:%1 is empty or space plus number',
                 'Copy%1 of %2', copyStr, m18n(self.name))
             copyNr += 1
     return newId, newName
Пример #32
0
 def loadData(self):
     """loads all data from the data base into a 2D matrix formatted like the wanted tree"""
     game = self.scoreTable.game
     data = []
     records = Query(
             'select player,rotated,notrotated,penalty,won,prevailing,wind,points,payments,balance,manualrules'
             ' from score where game=? order by player,hand',
             list([game.gameid])).records
     # pylint: disable=W0142
     # pylint * magic
     data = list(tuple([player.localName, [HandResult(*x[1:]) for x in records \
             if x[0] == player.nameid]]) for player in game.players)
     self.__findMinMaxChartPoints(data)
     parent = QModelIndex()
     groupIndex = self.index(self.rootItem.childCount(), 0, parent)
     groupNames = [m18nc('kajongg','Score'), m18nc('kajongg','Payments'),
             m18nc('kajongg','Balance'), m18nc('kajongg', 'Chart')]
     for idx, groupName in enumerate(groupNames):
         self.insertRows(idx, list([ScoreGroupItem(groupName)]), groupIndex)
         listIndex = self.index(idx, 0, groupIndex)
         for idx1, item in enumerate(data):
             self.insertRows(idx1, list([ScorePlayerItem(item)]), listIndex)
Пример #33
0
 def _newKey(self, minus=False):
     """generate a new id and a new name if the name already exists"""
     newId = self.newId(minus=minus)
     newName = self.name
     if minus:
         copyNr = 1
         while self.nameExists(newName):
             copyStr = ' ' + str(copyNr) if copyNr > 1 else ''
             newName = m18nc(
                 'Ruleset._newKey:%1 is empty or space plus number',
                 'Copy%1 of %2', copyStr, m18n(self.name))
             copyNr += 1
     return newId, newName
Пример #34
0
 def data(self, index, role=Qt.DisplayRole):
     """score table"""
     # pylint: disable=R0912,R0914
     # pylint too many branches
     result = QVariant()
     if role == Qt.TextAlignmentRole:
         if index.column() == 0:
             result = QVariant(int(Qt.AlignHCenter|Qt.AlignVCenter))
         else:
             result = QVariant(int(Qt.AlignLeft|Qt.AlignVCenter))
     if index.isValid() and (0 <= index.row() < len(self.tables)):
         table = self.tables[index.row()]
         if role == Qt.DisplayRole and index.column() == 1:
             result = QVariant(table.tableid)
         elif role == Qt.DisplayRole and index.column() == 0:
             if not table.status.startswith('Suspended'):
                 result = QVariant(table.tableid)
         elif role == Qt.DisplayRole and index.column() == 2:
             players = []
             zipped = zip(table.playerNames, table.playersOnline)
             for idx, pair in enumerate(zipped):
                 name, online = pair[0], pair[1]
                 if idx < len(zipped) - 1:
                     name += ', '
                 palette = KApplication.palette()
                 if online:
                     color = palette.color(QPalette.Active, QPalette.WindowText).name()
                     style = 'font-weight:normal;font-style:normal;color:%s' % color
                 else:
                     color = palette.color(QPalette.Disabled, QPalette.WindowText).name()
                     style = 'font-weight:100;font-style:italic;color:%s' % color
                 players.append('<nobr style="%s">' % style + name + '</nobr>')
             names = ''.join(players)
             result = QVariant(names)
         elif role == Qt.DisplayRole and index.column() == 3:
             status = table.status
             if status.startswith('Suspended'):
                 dateVal = ' ' + datetime.datetime.strptime(status.replace('Suspended', ''),
                     '%Y-%m-%dT%H:%M:%S').strftime('%c').decode('utf-8')
                 status = 'Suspended'
             else:
                 dateVal = ''
             result = QVariant(m18nc('table status', status) + dateVal)
         elif index.column() == 4:
             if role == Qt.DisplayRole:
                 result = QVariant(m18n(table.ruleset.name))
             elif role == Qt.ForegroundRole:
                 palette = KApplication.palette()
                 color = palette.windowText() if table.myRuleset else 'red'
                 result = QVariant(QColor(color))
     return result
Пример #35
0
    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')
Пример #36
0
 def __init__(self, game):
     super(ScoreTable, self).__init__(None)
     self.setObjectName('ScoreTable')
     self.game = None
     self.scoreModel = None
     self.scoreModelTest = None
     self.setWindowTitle(m18nc('kajongg', 'Scores') + ' - Kajongg')
     self.setAttribute(Qt.WA_AlwaysShowToolTips)
     self.setMouseTracking(True)
     self.__tableFields = ['prevailing', 'won', 'wind',
                             'points', 'payments', 'balance', 'hand', 'manualrules']
     self.setupUi()
     self.refresh(game)
     StateSaver(self, self.splitter)
Пример #37
0
 def headerData(self, section, orientation, role):
     """tell the view about the wanted headers"""
     if role == Qt.TextAlignmentRole:
         if orientation == Qt.Horizontal:
             return QVariant(int(Qt.AlignLeft | Qt.AlignVCenter))
     if role != Qt.DisplayRole:
         return QVariant()
     if orientation == Qt.Horizontal:
         if section == 0:
             return QVariant(m18nc('Kajongg', 'Rule'))
         if section == 1:
             return QVariant(m18n(self.view.cbRuleset1.current.name))
         if section == 2:
             return QVariant(m18n(self.view.cbRuleset2.current.name))
         return QVariant()
Пример #38
0
 def headerData(self, section, orientation, role):
     """tell the view about the wanted headers"""
     if role == Qt.TextAlignmentRole:
         if orientation == Qt.Horizontal:
             return QVariant(int(Qt.AlignLeft | Qt.AlignVCenter))
     if role != Qt.DisplayRole:
         return QVariant()
     if orientation == Qt.Horizontal:
         if section == 0:
             return QVariant(m18nc("Kajongg", "Rule"))
         if section == 1:
             return QVariant(m18n(self.view.cbRuleset1.current.name))
         if section == 2:
             return QVariant(m18n(self.view.cbRuleset2.current.name))
         return QVariant()
Пример #39
0
    def __init__(self):
        """self.servers is a list of tuples containing server and last playername"""
        QDialog.__init__(self, None)
        self.setWindowTitle(m18n('Login') + ' - Kajongg')
        self.setupUi()

        localName = m18nc('kajongg name for local game server',
                          Query.localServerName)
        self.servers = Query(
            'select url,lastname from server order by lasttime desc').records
        servers = [
            m18nc('kajongg name for local game server', x[0])
            for x in self.servers
        ]
        # the first server combobox item should be default: either the last used server
        # or localName for autoPlay
        if localName not in servers:
            servers.append(localName)
        if 'kajongg.org' not in servers:
            servers.append('kajongg.org')
            demoHost = Options.host or localName
            if demoHost in servers:
                servers.remove(
                    demoHost
                )  # we want a unique list, it will be re-used for all following games
            servers.insert(
                0, demoHost)  # in this process but they will not be autoPlay
        self.cbServer.addItems(servers)
        self.passwords = Query(
            'select url, p.name, passwords.password from passwords, player p '
            'where passwords.player=p.id').records
        Players.load()
        self.cbServer.editTextChanged.connect(self.serverChanged)
        self.cbUser.editTextChanged.connect(self.userChanged)
        self.serverChanged()
        StateSaver(self)
Пример #40
0
 def headerData(self, section, orientation, role=Qt.DisplayRole): # pylint: disable=R0201
     """show header"""
     if role == Qt.TextAlignmentRole:
         if orientation == Qt.Horizontal:
             if section in [3, 4]:
                 return QVariant(int(Qt.AlignLeft))
             else:
                 return QVariant(int(Qt.AlignHCenter|Qt.AlignVCenter))
     if role != Qt.DisplayRole:
         return QVariant()
     if orientation != Qt.Horizontal:
         return QVariant(int(section+1))
     result = ''
     if section < 5:
         result = [m18n('Table'), '', m18n('Players'), m18nc('table status', 'Status'), m18n('Ruleset')][section]
     return QVariant(result)
Пример #41
0
 def _loginFailed(self, failure):
     """login failed"""
     def answered(result):
         """user finally answered our question"""
         if result:
             return self.__adduser()
         else:
             return Failure(CancelledError)
     message = failure.getErrorMessage()
     if 'Wrong username' in message:
         if self.dlg.host == Query.localServerName:
             return answered(True)
         else:
             msg = m18nc('USER is not known on SERVER',
                 '%1 is not known on %2, do you want to open an account?', self.dlg.username, self.dlg.host)
             return QuestionYesNo(msg).addCallback(answered)
     else:
         return self._loginReallyFailed(failure)
Пример #42
0
 def headerData(self, section, orientation, role=Qt.DisplayRole):  # pylint: disable=R0201
     """show header"""
     if role == Qt.TextAlignmentRole:
         if orientation == Qt.Horizontal:
             if section in [3, 4]:
                 return QVariant(int(Qt.AlignLeft))
             else:
                 return QVariant(int(Qt.AlignHCenter | Qt.AlignVCenter))
     if role != Qt.DisplayRole:
         return QVariant()
     if orientation != Qt.Horizontal:
         return QVariant(int(section + 1))
     result = ''
     if section < 5:
         result = [
             m18n('Table'), '',
             m18n('Players'),
             m18nc('table status', 'Status'),
             m18n('Ruleset')
         ][section]
     return QVariant(result)
Пример #43
0
    def _loginFailed(self, failure):
        """login failed"""
        def answered(result):
            """user finally answered our question"""
            if result:
                return self.__adduser()
            else:
                return Failure(CancelledError)

        message = failure.getErrorMessage()
        if 'Wrong username' in message:
            if self.dlg.host == Query.localServerName:
                return answered(True)
            else:
                msg = m18nc(
                    'USER is not known on SERVER',
                    '%1 is not known on %2, do you want to open an account?',
                    self.dlg.username, self.dlg.host)
                return QuestionYesNo(msg).addCallback(answered)
        else:
            return self._loginReallyFailed(failure)
Пример #44
0
 def updateButtonsForTable(self, table):
     """update button status for the currently selected table"""
     hasTable = bool(table)
     suspended = hasTable and bool(table.suspendedAt)
     running = hasTable and table.running
     suspendedLocalGame = suspended and table.gameid and self.client.hasLocalServer(
     )
     self.joinButton.setEnabled(
         hasTable and not running and not table.isOnline(self.client.name)
         and (self.client.name in table.playerNames) == suspended)
     self.leaveButton.setVisible(not (suspendedLocalGame))
     self.compareButton.setVisible(not (suspendedLocalGame))
     self.startButton.setVisible(not suspended)
     if suspendedLocalGame:
         self.newButton.setToolTip(m18n("Start a new game"))
         self.joinButton.setText(
             m18nc('resuming a local suspended game', '&Resume'))
         self.joinButton.setToolTip(
             m18n("Resume the selected suspended game"))
     else:
         self.newButton.setToolTip(m18n("Allocate a new table"))
         self.joinButton.setText(m18n('&Join'))
         self.joinButton.setToolTip(m18n("Join a table"))
     self.leaveButton.setEnabled(hasTable and not running
                                 and not self.joinButton.isEnabled())
     self.startButton.setEnabled(not running and not suspendedLocalGame and hasTable \
         and self.client.name == table.playerNames[0])
     self.compareButton.setEnabled(hasTable and table.myRuleset is None)
     self.chatButton.setVisible(not self.client.hasLocalServer())
     self.chatButton.setEnabled(
         not running and hasTable and self.client.name in table.playerNames
         and sum(x.startswith('Robot ') for x in table.playerNames) < 3)
     if self.chatButton.isEnabled():
         self.chatButton.setToolTip(m18n("Chat with others on this table"))
     else:
         self.chatButton.setToolTip(
             m18n(
                 "For chatting with others on this table, please first take a seat"
             ))
Пример #45
0
    def __init__(self, name):
        """name may be:
            - an integer: ruleset.id from the sql table
            - a list: the full ruleset specification (probably sent from the server)
            - a string: The hash value of a ruleset"""
        self.name = name
        self.rulesetId = 0
        self.__hash = None
        self.allRules = []
        self.__dirty = False # only the ruleset editor is supposed to make us dirty
        self.__loaded = False
        self.__filteredLists = {}
        self.description = None
        self.rawRules = None # used when we get the rules over the network
        self.splitRules = []
        self.doublingMeldRules = []
        self.doublingHandRules = []
        self.meldRules = RuleList(1, m18n('Meld Rules'),
            m18n('Meld rules are applied to single melds independent of the rest of the hand'))
        self.handRules = RuleList(2, m18n('Hand Rules'),
            m18n('Hand rules are applied to the entire hand, for all players'))
        self.winnerRules = RuleList(3, m18n('Winner Rules'),
            m18n('Winner rules are applied to the entire hand but only for the winner'))
        self.loserRules = RuleList(33, m18n('Loser Rules'),
            m18n('Loser rules are applied to the entire hand but only for non-winners'))
        self.mjRules = RuleList(4, m18n('Mah Jongg Rules'),
            m18n('Only hands matching a Mah Jongg rule can win'))
        self.parameterRules = RuleList(999, m18nc('kajongg','Options'),
            m18n('Here we have several special game related options'))
        self.penaltyRules = RuleList(9999, m18n('Penalties'), m18n(
            """Penalties are applied manually by the user. They are only used for scoring games.
When playing against the computer or over the net, Kajongg will never let you get
into a situation where you have to pay a penalty"""))
        self.ruleLists = list([self.meldRules, self.handRules, self.mjRules, self.winnerRules,
            self.loserRules, self.parameterRules, self.penaltyRules])
        # the order of ruleLists is the order in which the lists appear in the ruleset editor
        # if you ever want to remove an entry from ruleLists: make sure its listId is not reused or you get
        # in trouble when updating
        self._initRuleset()
Пример #46
0
 def __navigateScoringGame(self, event):
     """keyboard navigation in a scoring game"""
     mod = event.modifiers()
     key = event.key()
     wind = chr(key%128)
     moveCommands = m18nc('kajongg:keyboard commands for moving tiles to the players ' \
         'with wind ESWN or to the central tile selector (X)', 'ESWNX')
     tile = self.centralScene.focusItem().tile
     if wind in moveCommands:
         # translate i18n wind key to ESWN:
         wind = 'ESWNX'[moveCommands.index(wind)]
         self.__moveTile(tile, wind, mod &Qt.ShiftModifier)
         return True
     if key == Qt.Key_Tab and self.game:
         tabItems = [self.selectorBoard]
         tabItems.extend(list(p.handBoard for p in self.game.players if p.handBoard.tiles))
         tabItems.append(tabItems[0])
         currentBoard = tile.board if isinstance(tile, Tile) else None
         currIdx = 0
         while tabItems[currIdx] != currentBoard and currIdx < len(tabItems) -2:
             currIdx += 1
         tabItems[currIdx+1].hasFocus = True
         return True
Пример #47
0
def shortcuttedMeldName(meld):
    """convert int to speaking name with shortcut"""
    if meld == ALLMELDS or meld == REST or meld == 0:
        return ''
    parts = []
    if SINGLE & meld:
        parts.append(m18nc('kajongg meld type','&single'))
    if PAIR & meld:
        parts.append(m18nc('kajongg meld type','&pair'))
    if CHOW & meld:
        parts.append(m18nc('kajongg meld type','&chow'))
    if PUNG & meld:
        parts.append(m18nc('kajongg meld type','p&ung'))
    if KONG & meld:
        parts.append(m18nc('kajongg meld type','k&ong'))
    if CLAIMEDKONG & meld:
        parts.append(m18nc('kajongg meld type','c&laimed kong'))
    return '|'.join(parts)
Пример #48
0
 def setupUi(self):
     """layout the window"""
     self.setWindowTitle(m18n('Customize rulesets') + ' - Kajongg')
     self.setObjectName('Rulesets')
     hlayout = QHBoxLayout(self)
     v1layout = QVBoxLayout()
     self.v1widget = QWidget()
     v1layout = QVBoxLayout(self.v1widget)
     v2layout = QVBoxLayout()
     hlayout.addWidget(self.v1widget)
     hlayout.addLayout(v2layout)
     for widget in [self.v1widget, hlayout, v1layout, v2layout]:
         widget.setContentsMargins(0, 0, 0, 0)
     hlayout.setStretchFactor(self.v1widget, 10)
     self.btnCopy = QPushButton()
     self.btnRemove = QPushButton()
     self.btnCompare = QPushButton()
     self.btnClose = QPushButton()
     self.rulesetView = RuleTreeView(m18nc('kajongg', 'Rule'), self.btnCopy,
                                     self.btnRemove, self.btnCompare)
     v1layout.addWidget(self.rulesetView)
     self.rulesetView.setWordWrap(True)
     self.rulesetView.setMouseTracking(True)
     spacerItem = QSpacerItem(20, 20, QSizePolicy.Minimum,
                              QSizePolicy.Expanding)
     v2layout.addWidget(self.btnCopy)
     v2layout.addWidget(self.btnRemove)
     v2layout.addWidget(self.btnCompare)
     self.btnCopy.clicked.connect(self.rulesetView.copyRow)
     self.btnRemove.clicked.connect(self.rulesetView.removeRow)
     self.btnCompare.clicked.connect(self.rulesetView.compareRow)
     self.btnClose.clicked.connect(self.hide)
     v2layout.addItem(spacerItem)
     v2layout.addWidget(self.btnClose)
     self.retranslateUi()
     StateSaver(self)
     self.show()
Пример #49
0
def shortcuttedMeldName(meld):
    """convert int to speaking name with shortcut"""
    if meld == ALLMELDS or meld == REST or meld == 0:
        return ''
    parts = []
    if SINGLE & meld:
        parts.append(m18nc('kajongg meld type', '&single'))
    if PAIR & meld:
        parts.append(m18nc('kajongg meld type', '&pair'))
    if CHOW & meld:
        parts.append(m18nc('kajongg meld type', '&chow'))
    if PUNG & meld:
        parts.append(m18nc('kajongg meld type', 'p&ung'))
    if KONG & meld:
        parts.append(m18nc('kajongg meld type', 'k&ong'))
    if CLAIMEDKONG & meld:
        parts.append(m18nc('kajongg meld type', 'c&laimed kong'))
    return '|'.join(parts)
Пример #50
0
    def retranslateUi(self):
        """retranslate"""
        self.actionScoreGame.setText(
            m18nc('@action:inmenu', "&Score Manual Game"))
        self.actionScoreGame.setIconText(
            m18nc('@action:intoolbar', 'Manual Game'))
        self.actionScoreGame.setHelpText(
            m18nc('kajongg @info:tooltip', '&Score a manual game.'))

        self.actionPlayGame.setText(m18nc('@action:intoolbar', "&Play"))
        self.actionPlayGame.setPriority(QAction.LowPriority)
        self.actionPlayGame.setHelpText(
            m18nc('kajongg @info:tooltip', 'Start a new game.'))

        self.actionAbortGame.setText(m18nc('@action:inmenu', "&Abort Game"))
        self.actionAbortGame.setPriority(QAction.LowPriority)
        self.actionAbortGame.setHelpText(
            m18nc('kajongg @info:tooltip', 'Abort the current game.'))

        self.actionQuit.setText(m18nc('@action:inmenu', "&Quit Kajongg"))
        self.actionQuit.setPriority(QAction.LowPriority)

        self.actionPlayers.setText(m18nc('@action:intoolbar', "&Players"))
        self.actionPlayers.setHelpText(
            m18nc('kajongg @info:tooltip', 'define your players.'))

        self.actionRulesets.setText(m18nc('@action:intoolbar', "&Rulesets"))
        self.actionRulesets.setHelpText(
            m18nc('kajongg @info:tooltip', 'customize rulesets.'))

        self.actionAngle.setText(
            m18nc('@action:inmenu', "&Change Visual Angle"))
        self.actionAngle.setIconText(m18nc('@action:intoolbar', "Angle"))
        self.actionAngle.setHelpText(
            m18nc('kajongg @info:tooltip',
                  "Change the visual appearance of the tiles."))

        self.actionScoring.setText(
            m18nc('@action:inmenu', "&Show Scoring Editor"))
        self.actionScoring.setIconText(m18nc('@action:intoolbar', "&Scoring"))
        self.actionScoring.setHelpText(
            m18nc('kajongg @info:tooltip',
                  "Show or hide the scoring editor for a manual game."))

        self.actionScoreTable.setText(
            m18nc('kajongg @action:inmenu', "&Score Table"))
        self.actionScoreTable.setIconText(
            m18nc('kajongg @action:intoolbar', "&Scores"))
        self.actionScoreTable.setHelpText(
            m18nc('kajongg @info:tooltip',
                  "Show or hide the score table for the current game."))

        self.actionExplain.setText(m18nc('@action:inmenu', "&Explain Scores"))
        self.actionExplain.setIconText(m18nc('@action:intoolbar', "&Explain"))
        self.actionExplain.setHelpText(
            m18nc('kajongg @info:tooltip',
                  'Explain the scoring for all players in the current game.'))

        self.actionAutoPlay.setText(m18nc('@action:inmenu', "&Demo Mode"))
        self.actionAutoPlay.setPriority(QAction.LowPriority)
        self.actionAutoPlay.setHelpText(
            m18nc(
                'kajongg @info:tooltip',
                'Let the computer take over for you. Start a new local game if needed.'
            ))

        self.actionChat.setText(m18n("C&hat"))
        self.actionChat.setHelpText(
            m18nc('kajongg @info:tooltip', 'Chat with the other players.'))
Пример #51
0
 def localName(self):
     """the localized name of this player"""
     return m18nc('kajongg, name of robot player, to be translated', self.name)
Пример #52
0
class Meld(object):
    """represents a meld. Can be empty. Many Meld methods will
    raise exceptions if the meld is empty. But we do not care,
    those methods are not supposed to be called on empty melds.
    Meld firstly holds the tile elements like 's1','s2','s3' but its
    attribute tiles can also hold references to the visual tile objects.
    The name of the tile element in the meld does not have to be
    identical with the name of the corresponding real tile while tiles
    are added or removed. See end of SelectorBoard.meldVariants()."""

    colorNames = {
        'x': m18nc('kajongg', 'hidden'),
        's': m18nc('kajongg', 'stone'),
        'b': m18nc('kajongg', 'bamboo'),
        'c': m18nc('kajongg', 'character'),
        'w': m18nc('kajongg', 'wind'),
        'd': m18nc('kajongg', 'dragon'),
        'f': m18nc('kajongg', 'flower'),
        'y': m18nc('kajongg', 'season')
    }
    valueNames = {
        'y': m18nc('kajongg', 'tile'),
        'b': m18nc('kajongg', 'white'),
        'r': m18nc('kajongg', 'red'),
        'g': m18nc('kajongg', 'green'),
        'e': m18nc('kajongg', 'east'),
        's': m18nc('kajongg', 'south'),
        'w': m18nc('kajongg', 'west'),
        'n': m18nc('kajongg', 'north'),
        'O': m18nc('kajongg', 'own wind'),
        'R': m18nc('kajongg', 'round wind')
    }
    for valNameIdx in range(1, 10):
        valueNames[str(valNameIdx)] = str(valNameIdx)

    @staticmethod
    def tileName(element):
        """returns translated name of a single tile"""
        return Meld.colorNames[element[0].lower()] + ' ' + Meld.valueNames[
            element[1]]

    __hash__ = None

    def __init__(self, newContent=None):
        """init the meld: content can be either
        - a single string with 2 chars for every tile
        - a list containing such strings
        - another meld. Its tiles are not passed.
        - a list of Tile objects"""
        self.__pairs = Pairs()
        self.__valid = False
        self.meldType = None
        self.tiles = []
        if isinstance(newContent, list) and newContent and hasattr(
                newContent[0], 'focusable'):
            self.joined = ''.join(x.element for x in newContent)
            self.tiles = newContent
        elif isinstance(newContent, Meld):
            self.joined = newContent.joined
            self.tiles = newContent.tiles
        elif isinstance(newContent, Tile):
            self.joined = newContent.element
            self.tiles = [newContent]
        else:
            self.joined = newContent

    def __len__(self):
        """how many tiles do we have?"""
        return len(self.tiles) if self.tiles else len(self.__pairs)

    def __getitem__(self, index):
        """Meld[x] returns Tile # x """
        return self.tiles[index]

    def __setitem__(self, index, value):
        """sets a tile in the meld. Not currently used but pylint
        wants the container to be perfect"""
        raise Exception("Assigning a tile to a Meld is not supported")

    def __delitem__(self, index):
        """removes a tile from the meld. Not currently used but pylint
        wants the container to be perfect"""
        raise Exception("removing a tile from a Meld is not supported")

    def __eq__(self, other):
        return isinstance(other, Meld) and self.pairs == other.pairs

    def isValid(self):
        """is it valid?"""
        return self.__valid

    def __isChow(self):
        """expensive, but this is only computed once per meld"""
        if len(self.__pairs) == 3:
            starts = set(self.__pairs.startChars())
            if len(starts) == 1:
                if starts & set('sbcSBC'):
                    values = self.__pairs.values()
                    if values[1] == values[0] + 1 and values[
                            2] == values[0] + 2:
                        return True
        return False

    @property
    def state(self):
        """meld state"""
        firsts = self.__pairs.startChars()
        if ''.join(firsts).islower():
            return EXPOSED
        elif len(self) == 4 and firsts[1].isupper() and firsts[2].isupper():
            return CONCEALED
        elif len(self) == 4:
            return EXPOSED
        else:
            return CONCEALED

    @state.setter
    def state(self, state):
        """meld state"""
        if state == EXPOSED:
            self.__pairs.toLower()
            if self.meldType == CLAIMEDKONG:
                self.__pairs.toUpper(3)
        elif state == CONCEALED:
            self.__pairs.toUpper()
            if len(self.__pairs) == 4:
                self.__pairs.toLower(0)
                self.__pairs.toLower(3)
        else:
            raise Exception('meld.setState: illegal state %d' % state)
        for idx, tile in enumerate(self.tiles):
            tile.element = self.__pairs[idx]

    def _getMeldType(self):
        """compute meld type"""
        # pylint: disable=R0912
        # too many branches
        length = len(self.__pairs)
        if not length:
            return EMPTY
        assert self.__pairs[0][0].lower() in 'xdwsbcfy', self.__pairs
        if 'Xy' in self.__pairs:
            return REST
        elif length == 1:
            return SINGLE
        elif length == 2:
            result = PAIR
        elif length == 4:
            if self.__pairs.isUpper():
                result = REST
                self.__valid = False
            elif self.__pairs.isLower(0, 3) and self.__pairs.isUpper(3):
                result = CLAIMEDKONG
            else:
                result = KONG
        elif self.__isChow():
            result = CHOW
        elif length == 3:
            result = PUNG
        else:
            result = REST
        if result not in [CHOW, REST]:
            if len(set(x.lower() for x in self.__pairs)) > 1:
                result = REST
        return result

    def tileType(self):
        """return one of d w s b c f y"""
        return self.__pairs[0][0].lower()

    def isPair(self):
        """is this meld a pair?"""
        return self.meldType == PAIR

    def isChow(self):
        """is this meld a pair?"""
        return self.meldType == CHOW

    def isPung(self):
        """is this meld a pair?"""
        return self.meldType == PUNG

    def isKong(self):
        """is it a kong?"""
        return self.meldType in (KONG, CLAIMEDKONG)

    @property
    def pairs(self):
        """make them readonly"""
        return self.__pairs

    @property
    def joined(self):
        """content"""
        return ''.join(self.__pairs)

    @joined.setter
    def joined(self, newContent):
        """content"""
        assert not self.tiles
        self.__pairs = Pairs(newContent)
        self.__valid = True
        self.meldType = self._getMeldType()

    def expose(self, isClaiming):
        """expose this meld. For kungs, leave one or two concealed,
        showing how the kung was built"""
        assert self.__pairs.isUpper(), self.joined
        if len(self.__pairs) < 4:
            self.__pairs.toLower()
        else:
            if isClaiming:
                self.__pairs.toLower(0, 3)
                self.__pairs.toUpper(3)
            else:  # concealed kong
                self.__pairs.toLower(0)
                self.__pairs.toUpper(1, 3)
                self.__pairs.toLower(3)
        self.meldType = self._getMeldType()

    def conceal(self):
        """conceal this meld again"""
        self.__pairs.toUpper()
        self.meldType = self._getMeldType()

    def __repr__(self):
        """the default representation"""
        return 'Meld(%s)' % self.joined
Пример #53
0
 def retranslateUi(self):
     """translate to current language"""
     self.btnCopy.setText(m18n("Copy"))
     self.btnCompare.setText(m18nc('Kajongg ruleset comparer', 'Compare'))
     self.btnRemove.setText(m18n("Remove"))
     self.btnClose.setText(m18n('Close'))
Пример #54
0
 def retranslateUi(self):
     """translate to current language"""
     self.btnCopy.setText(m18n("Copy"))
     self.btnCompare.setText(m18nc('Kajongg ruleset comparer', 'Compare'))
     self.btnRemove.setText(m18n("Remove"))
     self.btnClose.setText(m18n('Close'))
Пример #55
0
    def retranslateUi(self):
        """retranslate"""
        self.actionScoreGame.setText(m18nc('@action:inmenu', "&Score Manual Game"))
        self.actionScoreGame.setIconText(m18nc('@action:intoolbar', 'Manual Game'))
        self.actionScoreGame.setHelpText(m18nc('kajongg @info:tooltip', '&Score a manual game.'))

        self.actionPlayGame.setText(m18nc('@action:intoolbar', "&Play"))
        self.actionPlayGame.setPriority(QAction.LowPriority)
        self.actionPlayGame.setHelpText(m18nc('kajongg @info:tooltip', 'Start a new game.'))

        self.actionAbortGame.setText(m18nc('@action:inmenu', "&Abort Game"))
        self.actionAbortGame.setPriority(QAction.LowPriority)
        self.actionAbortGame.setHelpText(m18nc('kajongg @info:tooltip', 'Abort the current game.'))

        self.actionQuit.setText(m18nc('@action:inmenu', "&Quit Kajongg"))
        self.actionQuit.setPriority(QAction.LowPriority)

        self.actionPlayers.setText(m18nc('@action:intoolbar', "&Players"))
        self.actionPlayers.setHelpText(m18nc('kajongg @info:tooltip', 'define your players.'))

        self.actionRulesets.setText(m18nc('@action:intoolbar', "&Rulesets"))
        self.actionRulesets.setHelpText(m18nc('kajongg @info:tooltip', 'customize rulesets.'))

        self.actionAngle.setText(m18nc('@action:inmenu', "&Change Visual Angle"))
        self.actionAngle.setIconText(m18nc('@action:intoolbar', "Angle"))
        self.actionAngle.setHelpText(m18nc('kajongg @info:tooltip', "Change the visual appearance of the tiles."))

        self.actionScoring.setText(m18nc('@action:inmenu', "&Show Scoring Editor"))
        self.actionScoring.setIconText(m18nc('@action:intoolbar', "&Scoring"))
        self.actionScoring.setHelpText(m18nc('kajongg @info:tooltip',
                "Show or hide the scoring editor for a manual game."))

        self.actionScoreTable.setText(m18nc('kajongg @action:inmenu', "&Score Table"))
        self.actionScoreTable.setIconText(m18nc('kajongg @action:intoolbar', "&Scores"))
        self.actionScoreTable.setHelpText(m18nc('kajongg @info:tooltip',
                "Show or hide the score table for the current game."))

        self.actionExplain.setText(m18nc('@action:inmenu', "&Explain Scores"))
        self.actionExplain.setIconText(m18nc('@action:intoolbar', "&Explain"))
        self.actionExplain.setHelpText(m18nc('kajongg @info:tooltip',
                'Explain the scoring for all players in the current game.'))

        self.actionAutoPlay.setText(m18nc('@action:inmenu', "&Demo Mode"))
        self.actionAutoPlay.setPriority(QAction.LowPriority)
        self.actionAutoPlay.setHelpText(m18nc('kajongg @info:tooltip',
                'Let the computer take over for you. Start a new local game if needed.'))

        self.actionChat.setText(m18n("C&hat"))
        self.actionChat.setHelpText(m18nc('kajongg @info:tooltip', 'Chat with the other players.'))
Пример #56
0
 def __init__(self, name=None, shortcut=None):
     Message.__init__(self, name, shortcut)
     self.i18nName = m18nc('kajongg', self.name)
Пример #57
0
 def buttonCaption(self):
     """localized, with a & for the shortcut"""
     i18nShortcut = m18nc('kajongg game dialog:Key for '+self.name, self.shortcut)
     return self.i18nName.replace(i18nShortcut, '&'+i18nShortcut, 1)