def __init__(self, admin, field_attributes, parent=None, flags=QtCore.Qt.Dialog): super(ChangeFieldDialog, self).__init__("", parent, flags) from camelot.view.controls.editors import ChoicesEditor self.field_attributes = field_attributes self.field = None self.value = None self.setWindowTitle(admin.get_verbose_name_plural()) self.set_banner_title(_("Replace field contents")) self.set_banner_subtitle(_("Select the field to update and enter its new value")) self.banner_widget().setStyleSheet("background-color: white;") editor = ChoicesEditor(parent=self) editor.setObjectName("field_choice") layout = QtGui.QVBoxLayout() layout.addWidget(editor) self.main_widget().setLayout(layout) def filter(attributes): if not attributes["editable"]: return False if attributes["delegate"] in (delegates.One2ManyDelegate,): return False return True choices = [ (field, unicode(attributes["name"])) for field, attributes in field_attributes.items() if filter(attributes) ] choices.sort(key=lambda choice: choice[1]) editor.set_choices(choices + [(None, "")]) editor.set_value(None) self.field_changed(0) editor.currentIndexChanged.connect(self.field_changed) self.set_default_buttons()
def __init__( self, admin, field_attributes, parent = None, flags=QtCore.Qt.Dialog ): super(ChangeFieldDialog, self).__init__( '', parent, flags ) from camelot.view.controls.editors import ChoicesEditor self.field_attributes = field_attributes self.field = None self.value = None self.setWindowTitle( admin.get_verbose_name_plural() ) self.set_banner_title( _('Replace field contents') ) self.set_banner_subtitle( _('Select the field to update and enter its new value') ) self.banner_widget().setStyleSheet('background-color: white;') editor = ChoicesEditor( parent=self ) editor.setObjectName( 'field_choice' ) layout = QtGui.QVBoxLayout() layout.addWidget( editor ) self.main_widget().setLayout( layout ) def filter(attributes): if not attributes['editable']: return False if attributes['delegate'] in (delegates.One2ManyDelegate,): return False return True choices = [(field, unicode(attributes['name'])) for field, attributes in field_attributes.items() if filter(attributes)] choices.sort( key = lambda choice:choice[1] ) editor.set_choices( choices + [(None,'')] ) editor.set_value( None ) self.field_changed( 0 ) editor.currentIndexChanged.connect( self.field_changed ) self.set_default_buttons()
def __init__( self, admin, field_attributes, parent = None, flags=QtCore.Qt.Dialog ): super(ChangeFieldDialog, self).__init__( '', parent, flags ) from camelot.view.controls.editors import ChoicesEditor self.field_attributes = field_attributes self.field = None self.value = None self.setWindowTitle( admin.get_verbose_name_plural() ) self.set_banner_title( _('Replace field contents') ) self.set_banner_subtitle( _('Select the field to update and enter its new value') ) self.banner_widget().setStyleSheet('background-color: white;') editor = ChoicesEditor( parent=self ) editor.setObjectName( 'field_choice' ) layout = QtGui.QVBoxLayout() layout.addWidget( editor ) self.main_widget().setLayout( layout ) def filter(attributes): if not attributes['editable']: return False if attributes['delegate'] in (delegates.One2ManyDelegate,): return False return True choices = [(field, attributes['name']) for field, attributes in field_attributes.items() if filter(attributes)] choices.sort( key = lambda choice:choice[1] ) editor.set_choices( choices ) editor.set_value( ( choices+[(None,None)] )[-1][0] ) self.field_changed( 0 ) editor.currentIndexChanged.connect( self.field_changed ) cancel_button = QtGui.QPushButton( ugettext('Cancel') ) ok_button = QtGui.QPushButton( ugettext('OK') ) ok_button.setObjectName( 'ok' ) layout = QtGui.QHBoxLayout() layout.setDirection( QtGui.QBoxLayout.RightToLeft ) layout.addWidget( ok_button ) layout.addWidget( cancel_button ) layout.addStretch() self.buttons_widget().setLayout( layout ) cancel_button.pressed.connect( self.reject ) ok_button.pressed.connect( self.accept )
class ProfileSelection(StandaloneWizardPage): def __init__(self, parent=None): super(ProfileSelection, self).__init__(parent) self._connection_valid = False self.profiles = fetch_profiles() logger.debug("original profiles fetched:\n%s" % self.profiles) self.profiles_choices = set() for profile in self.profiles: if "profilename" in profile and profile["profilename"]: self.profiles_choices.add((profile["profilename"], profile["profilename"])) logger.debug("original profiles choices:\n%s" % self.profiles_choices) self.setWindowTitle(_("Profile Selection")) self.set_banner_logo_pixmap(art.Icon("tango/22x22/categories/preferences-system.png").getQPixmap()) self.set_banner_title(_("Database Settings")) self.set_banner_subtitle(_("Connect with an existing profile")) self.banner_widget().setStyleSheet("background-color: white;") self.create_labels_and_widgets() self.set_widgets_values() self.connect_widgets() self.create_buttons() self.connect_buttons() def create_labels_and_widgets(self): self.profile_label = QLabel(_("Profile Name:")) self.dialect_label = QLabel(_("Driver:")) self.host_label = QLabel(_("Server Host:")) self.port_label = QLabel(_("Port:")) self.database_name_label = QLabel(_("Database Name:")) self.username_label = QLabel(_("Username:"******"Password:"******"Cancel")) # self.clear_button = QPushButton(_('Clear')) self.ok_button = QPushButton(_("OK")) self.new_button = QPushButton(art.Icon("tango/16x16/actions/list-add.png").getQIcon(), "") self.new_button.setToolTip(_("Add a new profile name")) layout = QHBoxLayout() layout.setDirection(QBoxLayout.RightToLeft) layout.addWidget(self.cancel_button) # layout.addWidget(self.clear_button) layout.addWidget(self.ok_button) layout.addStretch() self.main_widget().layout().addWidget(self.new_button, 0, 5, 1, 1) self.buttons_widget().setLayout(layout) def connect_buttons(self): self.cancel_button.pressed.connect(self.reject) self.ok_button.pressed.connect(self.proceed) # self.clear_button.pressed.connect(self.clear_fields) self.new_button.pressed.connect(self.add_new_profile_name) # def clear_fields(self): # self.host_editor.clear() # self.port_editor.clear() # self.database_name_editor.clear() # self.username_editor.clear() # self.password_editor.clear() def proceed(self): if self.is_connection_valid(): info = self.collect_info() self.add_new_profile(info) logger.debug("storing new profile:\n%s" % self.profiles) store_profiles(self.profiles) use_chosen_profile(info) self.accept() def is_connection_valid(self): info = self.collect_info() mt = SignalSlotModelThread(lambda: None) mt.start() progress = ProgressDialog(_("Verifying database settings")) mt.post( lambda: self.test_connection(info["dialect"], info["host"], info["user"], info["pass"], info["database"]), progress.finished, progress.exception, ) progress.exec_() return self._connection_valid def test_connection(self, dialect, host, user, passwd, db): self._connection_valid = False connection_string = "%s://%s:%s@%s/%s" % (dialect, user, passwd, host, db) engine = create_engine(connection_string, pool_recycle=True) connection = engine.raw_connection() cursor = connection.cursor() cursor.close() connection.close() self._connection_valid = True def add_new_profile(self, info): logger.info("adding a new profile") for profile in self.profiles: if info["profilename"] == profile["profilename"]: profile.update(info) return self.profiles.append(info) def add_new_profile_name(self): logger.info("adding a new profile name") name, ok = QInputDialog.getText(self, _("New Profile Name"), _("Enter a value:")) if ok and name: name = str(name) self.profiles_choices.add((name, name)) self.profile_editor.set_choices(self.profiles_choices) self.profile_editor.set_value(name) def current_profile(self): return self.profile_editor.get_value() def update_profile(self): self.dialect_editor.set_value(self.get_profile_value("dialect") or "mysql") self.host_editor.setText(self.get_profile_value("host") or "localhost") self.port_editor.setText(self.get_profile_value("port") or "3306") self.database_name_editor.setText(self.get_profile_value("database")) self.username_editor.setText(self.get_profile_value("user")) self.password_editor.setText(self.get_profile_value("pass")) def get_profile_value(self, key): current = self.current_profile() for profile in self.profiles: if profile["profilename"] == current: return profile[key] return "" def collect_info(self): logger.info("collecting new database profile info") info = {} info["profilename"] = self.current_profile() info["dialect"] = self.dialect_editor.get_value() info["host"] = self.host_editor.text() info["port"] = self.port_editor.text() info["database"] = self.database_name_editor.text() info["user"] = self.username_editor.text() info["pass"] = self.password_editor.text() return info
class ProfileWizard(StandaloneWizardPage): """Wizard for the creation of a new database profile. .. attribute:: languages .. attribute:: dialects A list of languages allowed in the profile selection, an empty list will allow all languages """ languages = [] dialects = [] def __init__(self, profiles, parent=None): super(ProfileWizard, self).__init__(parent) self._connection_valid = False self.network_reply = None self.profiles = profiles self.setWindowTitle(_('Profile Wizard')) self.set_banner_logo_pixmap(art.Icon('tango/22x22/categories/preferences-system.png').getQPixmap()) self.set_banner_title(_('Create New/Edit Profile')) self.set_banner_subtitle(_('Please enter the database settings')) self.banner_widget().setStyleSheet('background-color: white;') self.manager = QtNetwork.QNetworkAccessManager( self ) self.manager.finished.connect( self.update_network_status ) #self.manager.networkAccessibleChanged.connect( self.network_accessible_changed ) self.manager.proxyAuthenticationRequired.connect( self.proxy_authentication_required ) self.create_labels_and_widgets() self.create_buttons() self.set_tab_order() self.set_widgets_values() # note: connections come after labels and widgets are created # and have default values self.connect_widgets() self.connect_buttons() timer = QtCore.QTimer(self) timer.timeout.connect( self.new_network_request ) timer.setInterval( 3000 ) timer.start() self.new_network_request() def create_labels_and_widgets(self): assert object_thread( self ) self.profile_label = QLabel(_('Profile Name:')) self.dialect_label = QLabel(_('Driver:')) self.host_label = QLabel(_('Server Host:')) self.port_label = QLabel(_('Port:')) self.database_name_label = QLabel(_('Database Name:')) self.username_label = QLabel(_('Username:'******'Password:'******'Media Location:')) self.language_label = QLabel(_('Language:')) self.proxy_host_label = QLabel(_('Proxy Host:')) self.proxy_port_label = QLabel(_('Port:')) self.proxy_username_label = QLabel(_('Proxy Username:'******'Proxy Password:'******'Media location path '\ 'is not accessible.')) self.not_accessible_media_path_label.setStyleSheet('color: red') self.not_writable_media_path_label = QLabel(_('Media location path '\ 'is not writable.')) self.not_writable_media_path_label.setStyleSheet('color: red') layout = QGridLayout() layout.addWidget(self.profile_label, 0, 0, Qt.AlignRight) layout.addWidget(self.dialect_label, 1, 0, Qt.AlignRight) layout.addWidget(self.host_label, 2, 0, Qt.AlignRight) layout.addWidget(self.port_label, 2, 3, Qt.AlignRight) layout.addWidget(self.database_name_label, 3, 0, Qt.AlignRight) layout.addWidget(self.username_label, 4, 0, Qt.AlignRight) layout.addWidget(self.password_label, 5, 0, Qt.AlignRight) layout.addWidget(self.media_location_label, 7, 0, Qt.AlignRight) layout.addWidget(self.language_label, 8, 0, Qt.AlignRight) layout.addWidget(self.proxy_host_label, 10, 0, Qt.AlignRight) layout.addWidget(self.proxy_port_label, 10, 3, Qt.AlignRight) layout.addWidget(self.proxy_username_label, 11, 0, Qt.AlignRight) layout.addWidget(self.proxy_password_label, 12, 0, Qt.AlignRight) self.profile_editor = QComboBox(self) self.profile_editor.setEditable(True) # 32767 is Qt max length for string # should be more than enough for folders # http://doc.qt.nokia.com/latest/qlineedit.html#maxLength-prop self.dialect_editor = ChoicesEditor(parent=self) self.host_editor = TextLineEditor(self, length=32767) self.host_editor.set_value('') self.port_editor = TextLineEditor(self) self.port_editor.setFixedWidth(60) self.port_editor.set_value('') self.database_name_editor = TextLineEditor(self, length=32767) self.database_name_editor.set_value('') self.username_editor = TextLineEditor(self) self.username_editor.set_value('') self.password_editor = TextLineEditor(self) self.password_editor.setEchoMode(QLineEdit.Password) self.password_editor.set_value('') self.media_location_editor = TextLineEditor(self, length=32767) self.media_location_editor.set_value('') self.language_editor = LanguageEditor(languages=self.languages, parent=self) # # try to find a default language # system_language = QtCore.QLocale.system().name() if self.languages: if system_language in self.languages: self.language_editor.set_value( system_language ) else: self.language_editor.set_value( self.languages[0] ) else: self.language_editor.set_value( system_language ) self.proxy_host_editor = TextLineEditor(self, length=32767) self.proxy_host_editor.set_value('') self.proxy_port_editor = TextLineEditor(self) self.proxy_port_editor.setFixedWidth(60) self.proxy_port_editor.set_value('') self.proxy_username_editor = TextLineEditor(self) self.proxy_username_editor.set_value('') self.proxy_password_editor = TextLineEditor(self) self.proxy_password_editor.set_value('') self.proxy_password_editor.setEchoMode(QLineEdit.Password) layout.addWidget(self.profile_editor, 0, 1, 1, 1) layout.addWidget(self.dialect_editor, 1, 1, 1, 1) layout.addWidget(self.host_editor, 2, 1, 1, 1) layout.addWidget(self.port_editor, 2, 4, 1, 1) layout.addWidget(self.database_name_editor, 3, 1, 1, 1) layout.addWidget(self.username_editor, 4, 1, 1, 1) layout.addWidget(self.password_editor, 5, 1, 1, 1) layout.addWidget(HSeparator(), 6, 0, 1, 5) layout.addWidget(self.media_location_editor, 7, 1, 1, 1) layout.addWidget(self.language_editor, 8, 1, 1, 1) layout.addWidget(HSeparator(), 9, 0, 1, 5) layout.addWidget(self.proxy_host_editor, 10, 1, 1, 1) layout.addWidget(self.proxy_port_editor, 10, 4, 1, 1) layout.addWidget(self.proxy_username_editor, 11, 1, 1, 1) layout.addWidget(self.proxy_password_editor, 12, 1, 1, 1) layout.addWidget(self.network_status_label, 13, 1, 1, 4) self.main_widget().setLayout(layout) def set_widgets_values(self): self.dialect_editor.clear() self.profile_editor.clear() if self.dialects: dialects = self.dialects else: import sqlalchemy.dialects dialects = [name for _importer, name, is_package in \ pkgutil.iter_modules(sqlalchemy.dialects.__path__) \ if is_package] self.dialect_editor.set_choices([(dialect, dialect.capitalize()) \ for dialect in dialects]) self.profile_editor.insertItems(1, [''] + \ [item for item in fetch_profiles()]) self.profile_editor.setFocus() self.update_wizard_values() def connect_widgets(self): self.profile_editor.editTextChanged.connect(self.update_wizard_values) # self.dialect_editor.currentIndexChanged.connect(self.update_wizard_values) def create_buttons(self): self.more_button = QPushButton(_('More')) self.more_button.setCheckable(True) self.more_button.setAutoDefault(False) self.cancel_button = QPushButton(_('Cancel')) self.ok_button = QPushButton(_('OK')) layout = QHBoxLayout() layout.setDirection(QBoxLayout.RightToLeft) layout.addWidget(self.cancel_button) layout.addWidget(self.ok_button) layout.addStretch() layout.addWidget(self.more_button) self.buttons_widget().setLayout(layout) self.browse_button = QPushButton(_('Browse')) self.main_widget().layout().addWidget(self.browse_button, 7, 2, 1, 3) self.setup_extension() def setup_extension(self): self.extension = QWidget() self.load_button = QPushButton(_('Load profiles')) self.save_button = QPushButton(_('Save profiles')) extension_buttons_layout = QHBoxLayout() extension_buttons_layout.setContentsMargins(0, 0, 0, 0) extension_buttons_layout.addWidget(self.load_button) extension_buttons_layout.addWidget(self.save_button) extension_buttons_layout.addStretch() extension_layout = QVBoxLayout() extension_layout.setContentsMargins(0, 0, 0, 0) extension_layout.addWidget(HSeparator()) extension_layout.addLayout(extension_buttons_layout) self.extension.setLayout(extension_layout) self.main_widget().layout().addWidget(self.extension, 15, 0, 1, 5) self.extension.hide() def set_tab_order(self): all_widgets = [self.profile_editor, self.dialect_editor, self.host_editor, self.port_editor, self.database_name_editor, self.username_editor, self.password_editor, self.media_location_editor, self.browse_button, self.language_editor, self.proxy_host_editor, self.proxy_port_editor, self.proxy_username_editor, self.proxy_password_editor, self.ok_button, self.cancel_button] i = 1 while i != len(all_widgets): self.setTabOrder(all_widgets[i-1], all_widgets[i]) i += 1 def connect_buttons(self): self.cancel_button.pressed.connect(self.reject) self.ok_button.pressed.connect(self.proceed) self.browse_button.pressed.connect(self.fill_media_location) self.more_button.toggled.connect(self.extension.setVisible) self.save_button.pressed.connect(self.save_profiles_to_file) self.load_button.pressed.connect(self.load_profiles_from_file) def proceed(self): if self.is_connection_valid(): profilename, info = self.collect_info() if profilename in self.profiles: self.profiles[profilename].update(info) else: self.profiles[profilename] = info store_profiles(self.profiles) use_chosen_profile(profilename) self.accept() def is_connection_valid(self): profilename, info = self.collect_info() mt = SignalSlotModelThread(lambda:None) mt.start() progress = ProgressDialog(_('Verifying database settings')) mt.post(lambda:self.test_connection( info ), progress.finished, progress.exception) progress.exec_() return self._connection_valid def test_connection(self, profile): self._connection_valid = False connection_string = connection_string_from_profile( profile ) engine = create_engine(connection_string, pool_recycle=True) try: connection = engine.raw_connection() cursor = connection.cursor() cursor.close() connection.close() self._connection_valid = True except Exception, e: self._connection_valid = False raise UserException( _('Could not connect to database, please check host and port'), resolution = _('Verify driver, host and port or contact your system administrator'), detail = unicode(e) )
class ProfileWizard(StandaloneWizardPage): """Wizard for the creation of a new database profile. .. attribute:: languages .. attribute:: dialects A list of languages allowed in the profile selection, an empty list will allow all languages """ languages = [] dialects = [] def __init__(self, profiles, parent=None): super(ProfileWizard, self).__init__(parent) self._connection_valid = False self.network_reply = None self.profiles = profiles self.setWindowTitle(_('Profile Wizard')) self.set_banner_logo_pixmap( art.Icon( 'tango/22x22/categories/preferences-system.png').getQPixmap()) self.set_banner_title(_('Create New/Edit Profile')) self.set_banner_subtitle(_('Please enter the database settings')) self.banner_widget().setStyleSheet('background-color: white;') self.manager = QtNetwork.QNetworkAccessManager(self) self.manager.finished.connect(self.update_network_status) #self.manager.networkAccessibleChanged.connect( self.network_accessible_changed ) self.manager.proxyAuthenticationRequired.connect( self.proxy_authentication_required) self.create_labels_and_widgets() self.create_buttons() self.set_tab_order() self.set_widgets_values() # note: connections come after labels and widgets are created # and have default values self.connect_widgets() self.connect_buttons() timer = QtCore.QTimer(self) timer.timeout.connect(self.new_network_request) timer.setInterval(3000) timer.start() self.new_network_request() def create_labels_and_widgets(self): assert object_thread(self) self.profile_label = QLabel(_('Profile Name:')) self.dialect_label = QLabel(_('Driver:')) self.host_label = QLabel(_('Server Host:')) self.port_label = QLabel(_('Port:')) self.database_name_label = QLabel(_('Database Name:')) self.username_label = QLabel(_('Username:'******'Password:'******'Media Location:')) self.language_label = QLabel(_('Language:')) self.proxy_host_label = QLabel(_('Proxy Host:')) self.proxy_port_label = QLabel(_('Port:')) self.proxy_username_label = QLabel(_('Proxy Username:'******'Proxy Password:'******'Media location path '\ 'is not accessible.')) self.not_accessible_media_path_label.setStyleSheet('color: red') self.not_writable_media_path_label = QLabel(_('Media location path '\ 'is not writable.')) self.not_writable_media_path_label.setStyleSheet('color: red') layout = QGridLayout() layout.addWidget(self.profile_label, 0, 0, Qt.AlignRight) layout.addWidget(self.dialect_label, 1, 0, Qt.AlignRight) layout.addWidget(self.host_label, 2, 0, Qt.AlignRight) layout.addWidget(self.port_label, 2, 3, Qt.AlignRight) layout.addWidget(self.database_name_label, 3, 0, Qt.AlignRight) layout.addWidget(self.username_label, 4, 0, Qt.AlignRight) layout.addWidget(self.password_label, 5, 0, Qt.AlignRight) layout.addWidget(self.media_location_label, 7, 0, Qt.AlignRight) layout.addWidget(self.language_label, 8, 0, Qt.AlignRight) layout.addWidget(self.proxy_host_label, 10, 0, Qt.AlignRight) layout.addWidget(self.proxy_port_label, 10, 3, Qt.AlignRight) layout.addWidget(self.proxy_username_label, 11, 0, Qt.AlignRight) layout.addWidget(self.proxy_password_label, 12, 0, Qt.AlignRight) self.profile_editor = QComboBox(self) self.profile_editor.setEditable(True) # 32767 is Qt max length for string # should be more than enough for folders # http://doc.qt.nokia.com/latest/qlineedit.html#maxLength-prop self.dialect_editor = ChoicesEditor(parent=self) self.host_editor = TextLineEditor(self, length=32767) self.host_editor.set_value('') self.port_editor = TextLineEditor(self) self.port_editor.setFixedWidth(60) self.port_editor.set_value('') self.database_name_editor = TextLineEditor(self, length=32767) self.database_name_editor.set_value('') self.username_editor = TextLineEditor(self) self.username_editor.set_value('') self.password_editor = TextLineEditor(self) self.password_editor.setEchoMode(QLineEdit.Password) self.password_editor.set_value('') self.media_location_editor = TextLineEditor(self, length=32767) self.media_location_editor.set_value('') self.language_editor = LanguageEditor(languages=self.languages, parent=self) # # try to find a default language # system_language = QtCore.QLocale.system().name() if self.languages: if system_language in self.languages: self.language_editor.set_value(system_language) else: self.language_editor.set_value(self.languages[0]) else: self.language_editor.set_value(system_language) self.proxy_host_editor = TextLineEditor(self, length=32767) self.proxy_host_editor.set_value('') self.proxy_port_editor = TextLineEditor(self) self.proxy_port_editor.setFixedWidth(60) self.proxy_port_editor.set_value('') self.proxy_username_editor = TextLineEditor(self) self.proxy_username_editor.set_value('') self.proxy_password_editor = TextLineEditor(self) self.proxy_password_editor.set_value('') self.proxy_password_editor.setEchoMode(QLineEdit.Password) layout.addWidget(self.profile_editor, 0, 1, 1, 1) layout.addWidget(self.dialect_editor, 1, 1, 1, 1) layout.addWidget(self.host_editor, 2, 1, 1, 1) layout.addWidget(self.port_editor, 2, 4, 1, 1) layout.addWidget(self.database_name_editor, 3, 1, 1, 1) layout.addWidget(self.username_editor, 4, 1, 1, 1) layout.addWidget(self.password_editor, 5, 1, 1, 1) layout.addWidget(HSeparator(), 6, 0, 1, 5) layout.addWidget(self.media_location_editor, 7, 1, 1, 1) layout.addWidget(self.language_editor, 8, 1, 1, 1) layout.addWidget(HSeparator(), 9, 0, 1, 5) layout.addWidget(self.proxy_host_editor, 10, 1, 1, 1) layout.addWidget(self.proxy_port_editor, 10, 4, 1, 1) layout.addWidget(self.proxy_username_editor, 11, 1, 1, 1) layout.addWidget(self.proxy_password_editor, 12, 1, 1, 1) layout.addWidget(self.network_status_label, 13, 1, 1, 4) self.main_widget().setLayout(layout) def set_widgets_values(self): self.dialect_editor.clear() self.profile_editor.clear() if self.dialects: dialects = self.dialects else: import sqlalchemy.dialects dialects = [name for _importer, name, is_package in \ pkgutil.iter_modules(sqlalchemy.dialects.__path__) \ if is_package] self.dialect_editor.set_choices([(dialect, dialect.capitalize()) \ for dialect in dialects]) self.profile_editor.insertItems(1, [''] + \ [item for item in fetch_profiles()]) self.profile_editor.setFocus() self.update_wizard_values() def connect_widgets(self): self.profile_editor.editTextChanged.connect(self.update_wizard_values) # self.dialect_editor.currentIndexChanged.connect(self.update_wizard_values) def create_buttons(self): self.more_button = QPushButton(_('More')) self.more_button.setCheckable(True) self.more_button.setAutoDefault(False) self.cancel_button = QPushButton(_('Cancel')) self.ok_button = QPushButton(_('OK')) layout = QHBoxLayout() layout.setDirection(QBoxLayout.RightToLeft) layout.addWidget(self.cancel_button) layout.addWidget(self.ok_button) layout.addStretch() layout.addWidget(self.more_button) self.buttons_widget().setLayout(layout) self.browse_button = QPushButton(_('Browse')) self.main_widget().layout().addWidget(self.browse_button, 7, 2, 1, 3) self.setup_extension() def setup_extension(self): self.extension = QWidget() self.load_button = QPushButton(_('Load profiles')) self.save_button = QPushButton(_('Save profiles')) extension_buttons_layout = QHBoxLayout() extension_buttons_layout.setContentsMargins(0, 0, 0, 0) extension_buttons_layout.addWidget(self.load_button) extension_buttons_layout.addWidget(self.save_button) extension_buttons_layout.addStretch() extension_layout = QVBoxLayout() extension_layout.setContentsMargins(0, 0, 0, 0) extension_layout.addWidget(HSeparator()) extension_layout.addLayout(extension_buttons_layout) self.extension.setLayout(extension_layout) self.main_widget().layout().addWidget(self.extension, 15, 0, 1, 5) self.extension.hide() def set_tab_order(self): all_widgets = [ self.profile_editor, self.dialect_editor, self.host_editor, self.port_editor, self.database_name_editor, self.username_editor, self.password_editor, self.media_location_editor, self.browse_button, self.language_editor, self.proxy_host_editor, self.proxy_port_editor, self.proxy_username_editor, self.proxy_password_editor, self.ok_button, self.cancel_button ] i = 1 while i != len(all_widgets): self.setTabOrder(all_widgets[i - 1], all_widgets[i]) i += 1 def connect_buttons(self): self.cancel_button.pressed.connect(self.reject) self.ok_button.pressed.connect(self.proceed) self.browse_button.pressed.connect(self.fill_media_location) self.more_button.toggled.connect(self.extension.setVisible) self.save_button.pressed.connect(self.save_profiles_to_file) self.load_button.pressed.connect(self.load_profiles_from_file) def proceed(self): if self.is_connection_valid(): profilename, info = self.collect_info() if profilename in self.profiles: self.profiles[profilename].update(info) else: self.profiles[profilename] = info store_profiles(self.profiles) use_chosen_profile(profilename) self.accept() def is_connection_valid(self): profilename, info = self.collect_info() mt = SignalSlotModelThread(lambda: None) mt.start() progress = ProgressDialog(_('Verifying database settings')) mt.post(lambda: self.test_connection(info), progress.finished, progress.exception) progress.exec_() return self._connection_valid def test_connection(self, profile): self._connection_valid = False connection_string = connection_string_from_profile(profile) engine = create_engine(connection_string, pool_recycle=True) try: connection = engine.raw_connection() cursor = connection.cursor() cursor.close() connection.close() self._connection_valid = True except Exception, e: self._connection_valid = False raise UserException( _('Could not connect to database, please check host and port'), resolution= _('Verify driver, host and port or contact your system administrator' ), detail=unicode(e))
class ProfileSelection(StandaloneWizardPage): def __init__(self, parent=None): super(ProfileSelection, self).__init__(parent) self._connection_valid = False self.profiles = fetch_profiles() logger.debug('original profiles fetched:\n%s' % self.profiles) self.profiles_choices = set() for profile in self.profiles: if 'profilename' in profile and profile['profilename']: self.profiles_choices.add( (profile['profilename'], profile['profilename'])) logger.debug('original profiles choices:\n%s' % self.profiles_choices) self.setWindowTitle(_('Profile Selection')) self.set_banner_logo_pixmap( art.Icon( 'tango/22x22/categories/preferences-system.png').getQPixmap()) self.set_banner_title(_('Database Settings')) self.set_banner_subtitle(_('Connect with an existing profile')) self.banner_widget().setStyleSheet('background-color: white;') self.create_labels_and_widgets() self.set_widgets_values() self.connect_widgets() self.create_buttons() self.connect_buttons() def create_labels_and_widgets(self): self.profile_label = QLabel(_('Profile Name:')) self.dialect_label = QLabel(_('Driver:')) self.host_label = QLabel(_('Server Host:')) self.port_label = QLabel(_('Port:')) self.database_name_label = QLabel(_('Database Name:')) self.username_label = QLabel(_('Username:'******'Password:'******'Cancel')) #self.clear_button = QPushButton(_('Clear')) self.ok_button = QPushButton(_('OK')) self.new_button = QPushButton( art.Icon('tango/16x16/actions/list-add.png').getQIcon(), '') self.new_button.setToolTip(_('Add a new profile name')) layout = QHBoxLayout() layout.setDirection(QBoxLayout.RightToLeft) layout.addWidget(self.cancel_button) #layout.addWidget(self.clear_button) layout.addWidget(self.ok_button) layout.addStretch() self.main_widget().layout().addWidget(self.new_button, 0, 5, 1, 1) self.buttons_widget().setLayout(layout) def connect_buttons(self): self.cancel_button.pressed.connect(self.reject) self.ok_button.pressed.connect(self.proceed) #self.clear_button.pressed.connect(self.clear_fields) self.new_button.pressed.connect(self.add_new_profile_name) #def clear_fields(self): # self.host_editor.clear() # self.port_editor.clear() # self.database_name_editor.clear() # self.username_editor.clear() # self.password_editor.clear() def proceed(self): if self.is_connection_valid(): info = self.collect_info() self.add_new_profile(info) logger.debug('storing new profile:\n%s' % self.profiles) store_profiles(self.profiles) use_chosen_profile(info) self.accept() def is_connection_valid(self): info = self.collect_info() mt = SignalSlotModelThread(lambda: None) mt.start() progress = ProgressDialog(_('Verifying database settings')) mt.post( lambda: self.test_connection(info['dialect'], info['host'], info[ 'user'], info['pass'], info['database']), progress.finished, progress.exception) progress.exec_() return self._connection_valid def test_connection(self, dialect, host, user, passwd, db): self._connection_valid = False connection_string = '%s://%s:%s@%s/%s' % (dialect, user, passwd, host, db) engine = create_engine(connection_string, pool_recycle=True) connection = engine.raw_connection() cursor = connection.cursor() cursor.close() connection.close() self._connection_valid = True def add_new_profile(self, info): logger.info('adding a new profile') for profile in self.profiles: if info['profilename'] == profile['profilename']: profile.update(info) return self.profiles.append(info) def add_new_profile_name(self): logger.info('adding a new profile name') name, ok = QInputDialog.getText(self, _('New Profile Name'), _('Enter a value:')) if ok and name: name = str(name) self.profiles_choices.add((name, name)) self.profile_editor.set_choices(self.profiles_choices) self.profile_editor.set_value(name) def current_profile(self): return self.profile_editor.get_value() def update_profile(self): self.dialect_editor.set_value( self.get_profile_value('dialect') or 'mysql') self.host_editor.setText(self.get_profile_value('host') or 'localhost') self.port_editor.setText(self.get_profile_value('port') or '3306') self.database_name_editor.setText(self.get_profile_value('database')) self.username_editor.setText(self.get_profile_value('user')) self.password_editor.setText(self.get_profile_value('pass')) def get_profile_value(self, key): current = self.current_profile() for profile in self.profiles: if profile['profilename'] == current: return profile[key] return '' def collect_info(self): logger.info('collecting new database profile info') info = {} info['profilename'] = self.current_profile() info['dialect'] = self.dialect_editor.get_value() info['host'] = self.host_editor.text() info['port'] = self.port_editor.text() info['database'] = self.database_name_editor.text() info['user'] = self.username_editor.text() info['pass'] = self.password_editor.text() return info
class SelectValuePage(QtGui.QWizardPage): """Page to select a value to update""" title = _('Replace field contents') sub_title = _('Select the field to update and enter its new value') def __init__(self, parent, admin, data): super(SelectValuePage, self).__init__(parent) self.setTitle( unicode(self.title) ) self.setSubTitle( unicode(self.sub_title) ) self.editor = ChoicesEditor() layout = QtGui.QVBoxLayout() layout.addWidget(self.editor) self.setLayout(layout) self._fields = {} self._data = data self.editor.currentIndexChanged.connect( self.field_changed ) self._value_editor = None post(admin.get_all_fields_and_attributes, self.set_fields) def set_fields(self, fields): self._fields = fields def filter(attributes): if not attributes['editable']: return False if attributes['delegate'] in (delegates.One2ManyDelegate, delegates.ManyToManyDelegate): return False return True choices = [(field, attributes['name']) for field, attributes in fields.items() if filter(attributes)] self.editor.set_choices(choices) self.editor.set_value((choices+[(None,None)])[1][0]) self.field_changed(0) def value_changed(self): if self._value_editor: self._data.value = self._value_editor.get_value() @QtCore.pyqtSlot(int) def field_changed(self, index): if self._value_editor: self.layout().removeWidget(self._value_editor) self._value_editor.deleteLater() self._value_editor = None selected_field = self.editor.get_value() if selected_field!=ValueLoading: self._data.field = selected_field self._data.value = None field_attributes = self._fields[selected_field] delegate = field_attributes['delegate'](**field_attributes) option = QtGui.QStyleOptionViewItem() option.version = 5 self._value_editor = delegate.createEditor( self, option, None ) self._value_editor.editingFinished.connect( self.value_changed ) self.layout().addWidget(self._value_editor) if isinstance(delegate, delegates.Many2OneDelegate): self._value_editor.set_value(lambda:None) else: self._value_editor.set_value(None)
class ProfileWizard(StandaloneWizardPage): """Wizard for the creation of a new database profile. .. attribute:: languages .. attribute:: dialects A list of languages allowed in the profile selection, an empty list will allow all languages """ languages = [] dialects = [] def __init__(self, profiles, parent=None): super(ProfileWizard, self).__init__(parent) self._connection_valid = False self.network_reply = None self.profiles = dict((profile.name, profile) for profile in profiles) self.setWindowTitle(_('Profile Wizard')) self.set_banner_logo_pixmap( art.Icon( 'tango/22x22/categories/preferences-system.png').getQPixmap()) self.set_banner_title(_('Create New/Edit Profile')) self.set_banner_subtitle(_('Please enter the database settings')) self.banner_widget().setStyleSheet('background-color: white;') self.manager = QtNetwork.QNetworkAccessManager(self) self.manager.finished.connect(self.update_network_status) self.create_labels_and_widgets() self.create_buttons() self.set_tab_order() self.set_widgets_values() # note: connections come after labels and widgets are created # and have default values self.connect_widgets() self.connect_buttons() self.toggle_ok_button() timer = QtCore.QTimer(self) timer.timeout.connect(self.new_network_request) timer.setInterval(3000) timer.start() self.new_network_request() def create_labels_and_widgets(self): self.profile_label = QtWidgets.QLabel(_('Profile Name:')) self.dialect_label = QtWidgets.QLabel(_('Driver:')) self.host_label = QtWidgets.QLabel(_('Server Host:')) self.port_label = QtWidgets.QLabel(_('Port:')) self.database_name_label = QtWidgets.QLabel(_('Database Name:')) self.username_label = QtWidgets.QLabel(_('Username:'******'Password:'******'Media Location:')) self.language_label = QtWidgets.QLabel(_('Language:')) self.proxy_host_label = QtWidgets.QLabel(_('Proxy Host:')) self.proxy_port_label = QtWidgets.QLabel(_('Port:')) self.proxy_username_label = QtWidgets.QLabel(_('Proxy Username:'******'Proxy Password:'******'Media location path '\ 'is not accessible.')) self.not_accessible_media_path_label.setStyleSheet('color: red') self.not_writable_media_path_label = QtWidgets.QLabel(_('Media location path '\ 'is not writable.')) self.not_writable_media_path_label.setStyleSheet('color: red') layout = QtGui.QGridLayout() layout.addWidget(self.profile_label, 0, 0, Qt.AlignRight) layout.addWidget(self.dialect_label, 1, 0, Qt.AlignRight) layout.addWidget(self.host_label, 2, 0, Qt.AlignRight) layout.addWidget(self.port_label, 2, 3, Qt.AlignRight) layout.addWidget(self.database_name_label, 3, 0, Qt.AlignRight) layout.addWidget(self.username_label, 4, 0, Qt.AlignRight) layout.addWidget(self.password_label, 5, 0, Qt.AlignRight) layout.addWidget(self.media_location_label, 7, 0, Qt.AlignRight) layout.addWidget(self.language_label, 8, 0, Qt.AlignRight) layout.addWidget(self.proxy_host_label, 10, 0, Qt.AlignRight) layout.addWidget(self.proxy_port_label, 10, 3, Qt.AlignRight) layout.addWidget(self.proxy_username_label, 11, 0, Qt.AlignRight) layout.addWidget(self.proxy_password_label, 12, 0, Qt.AlignRight) self.profile_editor = QtWidgets.QComboBox(self) self.profile_editor.setEditable(True) # 32767 is Qt max length for string # should be more than enough for folders # http://doc.qt.nokia.com/latest/qlineedit.html#maxLength-prop self.dialect_editor = ChoicesEditor(parent=self) self.dialect_editor.set_value(None) self.host_editor = TextLineEditor(self, length=32767) self.host_editor.set_value('') self.port_editor = TextLineEditor(self) self.port_editor.setFixedWidth(60) self.port_editor.set_value('') self.database_name_editor = TextLineEditor(self, length=32767) self.database_name_editor.set_value('') self.username_editor = TextLineEditor(self) self.username_editor.set_value('') self.password_editor = TextLineEditor( echo_mode=QtWidgets.QLineEdit.Password, parent=self) self.password_editor.set_value('') self.media_location_editor = TextLineEditor(self, length=32767) self.media_location_editor.set_value('') self.language_editor = LanguageEditor(languages=self.languages, parent=self) # # try to find a default language # system_language = QtCore.QLocale.system().name() if self.languages: if system_language in self.languages: self.language_editor.set_value(system_language) else: self.language_editor.set_value(self.languages[0]) else: self.language_editor.set_value(system_language) self.proxy_host_editor = TextLineEditor(self, length=32767) self.proxy_host_editor.set_value('') self.proxy_port_editor = TextLineEditor(self) self.proxy_port_editor.setFixedWidth(60) self.proxy_port_editor.set_value('') self.proxy_username_editor = TextLineEditor(self) self.proxy_username_editor.set_value('') self.proxy_password_editor = TextLineEditor( echo_mode=QtWidgets.QLineEdit.Password, parent=self) self.proxy_password_editor.set_value('') layout.addWidget(self.profile_editor, 0, 1, 1, 1) layout.addWidget(self.dialect_editor, 1, 1, 1, 1) layout.addWidget(self.host_editor, 2, 1, 1, 1) layout.addWidget(self.port_editor, 2, 4, 1, 1) layout.addWidget(self.database_name_editor, 3, 1, 1, 1) layout.addWidget(self.username_editor, 4, 1, 1, 1) layout.addWidget(self.password_editor, 5, 1, 1, 1) layout.addWidget(HSeparator(), 6, 0, 1, 5) layout.addWidget(self.media_location_editor, 7, 1, 1, 1) layout.addWidget(self.language_editor, 8, 1, 1, 1) layout.addWidget(HSeparator(), 9, 0, 1, 5) layout.addWidget(self.proxy_host_editor, 10, 1, 1, 1) layout.addWidget(self.proxy_port_editor, 10, 4, 1, 1) layout.addWidget(self.proxy_username_editor, 11, 1, 1, 1) layout.addWidget(self.proxy_password_editor, 12, 1, 1, 1) layout.addWidget(self.network_status_label, 13, 1, 1, 4) self.main_widget().setLayout(layout) def set_widgets_values(self): self.profile_editor.clear() self.dialect_editor.set_value(None) if self.dialects: dialects = self.dialects else: import sqlalchemy.dialects dialects = [name for _importer, name, is_package in \ pkgutil.iter_modules(sqlalchemy.dialects.__path__) \ if is_package] self.dialect_editor.set_choices([(dialect, dialect.capitalize()) \ for dialect in dialects]) self.profile_editor.insertItems(1, [''] + list(self.profiles.keys())) self.profile_editor.setFocus() self.update_wizard_values() def connect_widgets(self): self.profile_editor.editTextChanged.connect(self.toggle_ok_button) self.profile_editor.currentIndexChanged.connect( self.update_wizard_values) self.dialect_editor.editingFinished.connect(self.toggle_ok_button) def create_buttons(self): self.cancel_button = QtWidgets.QPushButton(_('Cancel')) self.ok_button = QtWidgets.QPushButton(_('OK')) layout = QtWidgets.QHBoxLayout() layout.setDirection(QtWidgets.QBoxLayout.RightToLeft) layout.addWidget(self.cancel_button) layout.addWidget(self.ok_button) layout.addStretch() self.buttons_widget().setLayout(layout) self.browse_button = QtWidgets.QPushButton(_('Browse')) self.main_widget().layout().addWidget(self.browse_button, 7, 2, 1, 3) def set_tab_order(self): all_widgets = [ self.profile_editor, self.dialect_editor, self.host_editor, self.port_editor, self.database_name_editor, self.username_editor, self.password_editor, self.media_location_editor, self.browse_button, self.language_editor, self.proxy_host_editor, self.proxy_port_editor, self.proxy_username_editor, self.proxy_password_editor, self.ok_button, self.cancel_button ] i = 1 while i != len(all_widgets): self.setTabOrder(all_widgets[i - 1], all_widgets[i]) i += 1 def connect_buttons(self): self.cancel_button.pressed.connect(self.reject) self.ok_button.pressed.connect(self.accept) self.browse_button.pressed.connect(self.fill_media_location) @QtCore.qt_slot() def toggle_ok_button(self): enabled = bool(self.profile_editor.currentText()) and bool( self.dialect_editor.get_value()) self.ok_button.setEnabled(enabled) def current_profile(self): text = six.text_type(self.profile_editor.currentText()) return text def set_current_profile(self, profile_name): self.profile_editor.lineEdit().setText(profile_name) self.update_wizard_values() def update_wizard_values(self): #network_proxy = get_network_proxy() # self.dialect_editor.set_value(self.get_profile_value('dialect') or 'mysql') # self.host_editor.setText(self.get_profile_value('host') or '127.0.0.1') # self.port_editor.setText(self.get_profile_value('port') or '3306') self.dialect_editor.set_value( self.get_profile_value('dialect') or None) self.host_editor.set_value(self.get_profile_value('host')) self.port_editor.set_value(self.get_profile_value('port')) # self.port_editor.setText(self.get_profile_value('port') or self._related_default_port(self.dialect_editor)) self.database_name_editor.set_value(self.get_profile_value('database')) self.username_editor.set_value(self.get_profile_value('user')) self.password_editor.set_value(self.get_profile_value('password')) self.media_location_editor.set_value( self.get_profile_value('media_location')) self.language_editor.set_value( self.get_profile_value('locale_language')) self.proxy_host_editor.set_value(self.get_profile_value('proxy_host')) self.proxy_port_editor.set_value(self.get_profile_value('proxy_port')) self.proxy_username_editor.set_value( self.get_profile_value('proxy_username')) self.proxy_password_editor.set_value( self.get_profile_value('proxy_password')) self.network_status_label.setText('') self.network_status_label.setStyleSheet('') self.toggle_ok_button() # this line segfaults on OSX using Python 3.3 #@QtCore.qt_slot(QtNetwork.QNetworkReply) def update_network_status(self, reply): if reply.isFinished(): error = reply.error() if error == QtNetwork.QNetworkReply.NoError: self.network_status_label.setText(_('Internet available.')) self.network_status_label.setStyleSheet('color: green') return self.network_status_label.setText( _('Internet not available.\n%s.' % reply.errorString())) self.network_status_label.setStyleSheet('color: red') @QtCore.qt_slot() def new_network_request(self): if self.network_reply and not self.network_reply.isFinished(): self.network_reply.abort() if self.proxy_host_editor.get_value( ) and self.proxy_port_editor.get_value(): proxy = QtNetwork.QNetworkProxy( QtNetwork.QNetworkProxy.HttpProxy, self.proxy_host_editor.get_value(), int(str(self.proxy_port_editor.get_value()))) #, #self.proxy_username_editor.text(), #self.proxy_password_editor.text() ) self.manager.setProxy(proxy) else: self.manager.setProxy(QtNetwork.QNetworkProxy()) self.network_reply = self.manager.get( QtNetwork.QNetworkRequest(QtCore.QUrl('http://aws.amazon.com'))) def get_profile_value(self, key): current = self.current_profile() if current in self.profiles: return getattr(self.profiles[current], key) return '' def get_profile_info(self): logger.info('collecting new database profile info') info = {} info['name'] = self.current_profile() info['dialect'] = self.dialect_editor.get_value() info['host'] = self.host_editor.get_value() info['port'] = self.port_editor.get_value() info['database'] = self.database_name_editor.get_value() info['user'] = self.username_editor.get_value() info['password'] = self.password_editor.get_value() info['media_location'] = self.media_location_editor.get_value() info['locale_language'] = self.language_editor.get_value() info['proxy_host'] = self.proxy_host_editor.get_value() info['proxy_port'] = self.proxy_port_editor.get_value() info['proxy_username'] = self.proxy_username_editor.get_value() info['proxy_password'] = self.proxy_password_editor.get_value() return info def fill_media_location(self): caption = _('Select media location') selected = six.text_type( QtGui.QFileDialog.getExistingDirectory(self, caption)) if not selected: return info = QtCore.QFileInfo(selected) if not info.isReadable(): self.main_widget().layout().addWidget( self.not_accessible_media_path_label, 13, 1, 1, 4) return if not info.isWritable(): self.main_widget().layout().addWidget( self.not_writable_media_path_label, 13, 1, 1, 4) return self.media_location_editor.set_value(selected)