class CustomizationView(QWidget): def __init__(self): QWidget.__init__(self) self._layout = QFormLayout() self.setLayout(self._layout) self._widgets = {} def addRow(self, title, widget): self._layout.addRow(title, widget) def addLineEdit(self, attribute_name, title, tool_tip=None, placeholder=""): self[attribute_name] = ClearableLineEdit(placeholder=placeholder) self.addRow(title, self[attribute_name]) if tool_tip is not None: self[attribute_name].setToolTip(tool_tip) def getter(self): value = str(self[attribute_name].text()) if value == "": value = None return value def setter(self, value): if value is None: value = "" self[attribute_name].setText(str(value)) self.updateProperty(attribute_name, getter, setter) def addCheckBox(self, attribute_name, title, tool_tip=None): self[attribute_name] = QCheckBox() self.addRow(title, self[attribute_name]) if tool_tip is not None: self[attribute_name].setToolTip(tool_tip) def getter(self): return self[attribute_name].isChecked() def setter(self, value): self[attribute_name].setChecked(value) self.updateProperty(attribute_name, getter, setter) def addSpinBox(self, attribute_name, title, tool_tip=None, min_value=1, max_value=10, single_step=1): sb = QSpinBox() self[attribute_name] = sb sb.setMaximumHeight(25) sb_layout = QHBoxLayout() sb_layout.addWidget(sb) sb_layout.addStretch() self.addRow(title, sb_layout) if tool_tip is not None: sb.setToolTip(tool_tip) sb.setMinimum(min_value) sb.setMaximum(max_value) sb.setSingleStep(single_step) def getter(self): return self[attribute_name].value() def setter(self, value): self[attribute_name].setValue(value) self.updateProperty(attribute_name, getter, setter) return sb def addStyleChooser(self, attribute_name, title, tool_tip=None, area_supported=False): style_chooser = StyleChooser(area_supported=area_supported) self[attribute_name] = style_chooser self.addRow(title, self[attribute_name]) if tool_tip is not None: self[attribute_name].setToolTip(tool_tip) def getter(self): return self[attribute_name].getStyle() def setter(self, style): self[attribute_name].setStyle(style) self.updateProperty(attribute_name, getter, setter) def updateProperty(self, attribute_name, getter, setter): setattr(self.__class__, attribute_name, property(getter, setter)) def setWidgetEnabled(self, attribute_name, enabled): widget = self[attribute_name] widget.setEnabled(enabled) widget.setHidden(enabled) label = self._layout.labelForField(widget) label.setEnabled(enabled) label.setHidden(enabled) def addSpacing(self, pixels=10): self._layout.addItem(QSpacerItem(1, pixels)) def addHeading(self, title): self.addSpacing(10) self._layout.addRow(title, None) self.addSpacing(1) def __getitem__(self, item): """ @rtype: QWidget """ return self._widgets[item] def __setitem__(self, key, value): self._widgets[key] = value def applyCustomization(self, plot_config): """ @type plot_config: PlotConfig """ raise NotImplementedError("Class '%s' has not implemented the applyCustomization() function!" % self.__class__.__name__) def revertCustomization(self, plot_config): """ @type plot_config: PlotConfig """ raise NotImplementedError("Class '%s' has not implemented the revertCustomization() function!" % self.__class__.__name__)
class LoginDlg(QDialog): """login dialog for server""" 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) def returns(self, dummyButton=None): """maybe we should return an class ServerConnection""" return (self.useSocket, self.url, self.username, self.__defineRuleset()) 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) def serverChanged(self, dummyText=None): """the user selected a different server""" records = Query('select player.name from player, passwords ' 'where passwords.url=? and passwords.player = player.id', list([self.url])).records players = list(x[0] for x in records) preferPlayer = Options.player if preferPlayer: if preferPlayer in players: players.remove(preferPlayer) players.insert(0, preferPlayer) self.cbUser.clear() self.cbUser.addItems(players) if not self.cbUser.count(): user = KUser() if os.name == 'nt' else KUser(os.geteuid()) self.cbUser.addItem(user.fullName() or user.loginName()) if not preferPlayer: userNames = [x[1] for x in self.servers if x[0] == self.url] if userNames: userIdx = self.cbUser.findText(userNames[0]) if userIdx >= 0: self.cbUser.setCurrentIndex(userIdx) showPW = self.url != Query.localServerName self.grid.labelForField(self.edPassword).setVisible(showPW) self.edPassword.setVisible(showPW) self.grid.labelForField(self.cbRuleset).setVisible(not showPW and not Options.ruleset) self.cbRuleset.setVisible(not showPW and not Options.ruleset) if not showPW: self.cbRuleset.clear() if Options.ruleset: self.cbRuleset.items = [Options.ruleset] else: self.cbRuleset.items = Ruleset.selectableRulesets(self.url) def __defineRuleset(self): """find out what ruleset to use""" if Options.ruleset: return Options.ruleset elif Internal.autoPlay or bool(Options.host): return Ruleset.selectableRulesets()[0] else: return self.cbRuleset.current def userChanged(self, text): """the username has been changed, lookup password""" if text == '': self.edPassword.clear() return passw = None for entry in self.passwords: if entry[0] == self.url and entry[1] == unicode(text): passw = entry[2] if passw: self.edPassword.setText(passw) else: self.edPassword.clear() @property def url(self): """abstracts the url of the dialog""" return english(unicode(self.cbServer.currentText())) @property def host(self): """abstracts the host of the dialog""" return self.url.partition(':')[0] @property def useSocket(self): """do we use socket for current host?""" return self.host == Query.localServerName @property def port(self): """abstracts the port of the dialog""" try: return int(self.url.partition(':')[2]) except ValueError: return Options.defaultPort() @property def username(self): """abstracts the username of the dialog""" return unicode(self.cbUser.currentText()) @property def password(self): """abstracts the password of the dialog""" return unicode(self.edPassword.text()) @password.setter def password(self, password): """abstracts the password of the dialog""" self.edPassword.setText(password) def updateServerInfoInDatabase(self): """we are online. Update table server.""" lasttime = datetime.datetime.now().replace(microsecond=0).isoformat() url = english(self.url) # use unique name for Local Game with Transaction(): serverKnown = Query('update server set lastname=?,lasttime=? where url=?', list([self.username, lasttime, url])).rowcount() == 1 if not serverKnown: Query('insert into server(url,lastname,lasttime) values(?,?,?)', list([url, self.username, lasttime])) # needed if the server knows our name but our local data base does not: Players.createIfUnknown(self.username) playerId = Players.allIds[self.username] with Transaction(): if Query('update passwords set password=? where url=? and player=?', list([self.password, url, playerId])).rowcount() == 0: Query('insert into passwords(url,player,password) values(?,?,?)', list([url, playerId, self.password]))
class CustomizationView(QWidget): def __init__(self): QWidget.__init__(self) self._layout = QFormLayout() self.setLayout(self._layout) self._widgets = {} def addRow(self, title, widget): self._layout.addRow(title, widget) def addLineEdit(self, attribute_name, title, tool_tip=None, placeholder=""): self[attribute_name] = ClearableLineEdit(placeholder=placeholder) self.addRow(title, self[attribute_name]) if tool_tip is not None: self[attribute_name].setToolTip(tool_tip) def getter(self): value = str(self[attribute_name].text()) if value == "": value = None return value def setter(self, value): if value is None: value = "" self[attribute_name].setText(str(value)) self.updateProperty(attribute_name, getter, setter) def addCheckBox(self, attribute_name, title, tool_tip=None): self[attribute_name] = QCheckBox() self.addRow(title, self[attribute_name]) if tool_tip is not None: self[attribute_name].setToolTip(tool_tip) def getter(self): return self[attribute_name].isChecked() def setter(self, value): self[attribute_name].setChecked(value) self.updateProperty(attribute_name, getter, setter) def addSpinBox(self, attribute_name, title, tool_tip=None, min_value=1, max_value=10, single_step=1): sb = QSpinBox() self[attribute_name] = sb sb.setMaximumHeight(25) sb_layout = QHBoxLayout() sb_layout.addWidget(sb) sb_layout.addStretch() self.addRow(title, sb_layout) if tool_tip is not None: sb.setToolTip(tool_tip) sb.setMinimum(min_value) sb.setMaximum(max_value) sb.setSingleStep(single_step) def getter(self): return self[attribute_name].value() def setter(self, value): self[attribute_name].setValue(value) self.updateProperty(attribute_name, getter, setter) return sb def addStyleChooser(self, attribute_name, title, tool_tip=None, line_style_set=sc.STYLESET_DEFAULT): style_chooser = StyleChooser(line_style_set=line_style_set) self[attribute_name] = style_chooser self.addRow(title, self[attribute_name]) if tool_tip is not None: self[attribute_name].setToolTip(tool_tip) def getter(self): return self[attribute_name].getStyle() def setter(self, style): self[attribute_name].setStyle(style) self.updateProperty(attribute_name, getter, setter) def updateProperty(self, attribute_name, getter, setter): setattr(self.__class__, attribute_name, property(getter, setter)) def setWidgetEnabled(self, attribute_name, enabled): widget = self[attribute_name] widget.setEnabled(enabled) widget.setHidden(enabled) label = self._layout.labelForField(widget) label.setEnabled(enabled) label.setHidden(enabled) def addSpacing(self, pixels=10): self._layout.addItem(QSpacerItem(1, pixels)) def addHeading(self, title): self.addSpacing(10) self._layout.addRow(title, None) self.addSpacing(1) def __getitem__(self, item): """ @rtype: QWidget """ return self._widgets[item] def __setitem__(self, key, value): self._widgets[key] = value def applyCustomization(self, plot_config): """ @type plot_config: PlotConfig """ raise NotImplementedError( "Class '%s' has not implemented the applyCustomization() function!" % self.__class__.__name__) def revertCustomization(self, plot_config): """ @type plot_config: PlotConfig """ raise NotImplementedError( "Class '%s' has not implemented the revertCustomization() function!" % self.__class__.__name__)
class LoginDlg(QDialog): """login dialog for server""" 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) def returns(self, dummyButton=None): """maybe we should return an class ServerConnection""" return (self.useSocket, self.url, self.username, self.__defineRuleset()) 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) def serverChanged(self, dummyText=None): """the user selected a different server""" records = Query( 'select player.name from player, passwords ' 'where passwords.url=? and passwords.player = player.id', list([self.url])).records players = list(x[0] for x in records) preferPlayer = Options.player if preferPlayer: if preferPlayer in players: players.remove(preferPlayer) players.insert(0, preferPlayer) self.cbUser.clear() self.cbUser.addItems(players) if not self.cbUser.count(): user = KUser() if os.name == 'nt' else KUser(os.geteuid()) self.cbUser.addItem(user.fullName() or user.loginName()) if not preferPlayer: userNames = [x[1] for x in self.servers if x[0] == self.url] if userNames: userIdx = self.cbUser.findText(userNames[0]) if userIdx >= 0: self.cbUser.setCurrentIndex(userIdx) showPW = self.url != Query.localServerName self.grid.labelForField(self.edPassword).setVisible(showPW) self.edPassword.setVisible(showPW) self.grid.labelForField(self.cbRuleset).setVisible( not showPW and not Options.ruleset) self.cbRuleset.setVisible(not showPW and not Options.ruleset) if not showPW: self.cbRuleset.clear() if Options.ruleset: self.cbRuleset.items = [Options.ruleset] else: self.cbRuleset.items = Ruleset.selectableRulesets(self.url) def __defineRuleset(self): """find out what ruleset to use""" if Options.ruleset: return Options.ruleset elif Internal.autoPlay or bool(Options.host): return Ruleset.selectableRulesets()[0] else: return self.cbRuleset.current def userChanged(self, text): """the username has been changed, lookup password""" if text == '': self.edPassword.clear() return passw = None for entry in self.passwords: if entry[0] == self.url and entry[1] == unicode(text): passw = entry[2] if passw: self.edPassword.setText(passw) else: self.edPassword.clear() @property def url(self): """abstracts the url of the dialog""" return english(unicode(self.cbServer.currentText())) @property def host(self): """abstracts the host of the dialog""" return self.url.partition(':')[0] @property def useSocket(self): """do we use socket for current host?""" return self.host == Query.localServerName @property def port(self): """abstracts the port of the dialog""" try: return int(self.url.partition(':')[2]) except ValueError: return Options.defaultPort() @property def username(self): """abstracts the username of the dialog""" return unicode(self.cbUser.currentText()) @property def password(self): """abstracts the password of the dialog""" return unicode(self.edPassword.text()) @password.setter def password(self, password): """abstracts the password of the dialog""" self.edPassword.setText(password) def updateServerInfoInDatabase(self): """we are online. Update table server.""" lasttime = datetime.datetime.now().replace(microsecond=0).isoformat() url = english(self.url) # use unique name for Local Game with Transaction(): serverKnown = Query( 'update server set lastname=?,lasttime=? where url=?', list([self.username, lasttime, url])).rowcount() == 1 if not serverKnown: Query( 'insert into server(url,lastname,lasttime) values(?,?,?)', list([url, self.username, lasttime])) # needed if the server knows our name but our local data base does not: Players.createIfUnknown(self.username) playerId = Players.allIds[self.username] with Transaction(): if Query( 'update passwords set password=? where url=? and player=?', list([self.password, url, playerId])).rowcount() == 0: Query( 'insert into passwords(url,player,password) values(?,?,?)', list([url, playerId, self.password]))