def mkSslBox(self): group = QGroupBox(tr("Check server certificate")) group.setCheckable(True) box = QVBoxLayout(group) #id 0 nupki = QRadioButton(tr("Upload certificate")) #id 1 custom = QRadioButton(tr("Use an internal PKI")) hbox = QHBoxLayout() box.addLayout(hbox) self.nupki_or_custom = QButtonGroup() self.connect(self.nupki_or_custom, SIGNAL('buttonClicked(int)'), self.toggleCustomOrNupki) for index, radio in enumerate((custom, nupki)): hbox.addWidget(radio) self.nupki_or_custom.addButton(radio, index) self.file_selector_widget = QWidget() vbox = QVBoxLayout(self.file_selector_widget) selector_label = QLabel(tr("Manually uploaded LDAP certificate")) vbox.addWidget(selector_label) add_cert_trigger = AddButton(text=tr("Upload a certificate")) vbox.addWidget(add_cert_trigger) vbox.addWidget(separator()) self.has_cert_message = QLabel( tr("There is no manually uploaded server certificate") ) self.del_cert = RemButton( tr("Delete certificate file from server") ) vbox.addWidget(self.has_cert_message) vbox.addWidget(self.del_cert) self.connect(add_cert_trigger, SIGNAL('clicked()'), self.upload_server_cert) self.connect(self.del_cert, SIGNAL('clicked()'), self.delete_server_cert) self.nupki_message = MessageArea() self.nupki_message.setMessage(tr("Warning"), tr( "There is no server certificate in the internal PKI.<br/>" "Please import or generate one using an internal PKI." ) ) for anti_button, widget in ((custom, self.nupki_message), (nupki, self.file_selector_widget)): box.addWidget(widget) self.connect(anti_button, SIGNAL('toggled(bool)'), widget.setVisible) self.selectCustomOrNupki(CUSTOM) return group
def __init__(self, parent=None, isChild=False): QWidget.__init__(self, parent) QGridLayout(self) # FIXME: call self.setLayout(layout)? self._readonly = False self.up_down = QFrame() self.up = UpButton() self.down = DownButton() self.add = AddButton() self.rem = RemButton() self.listEditView = ListEditView(isChild, parent=self) self.connect(self.listEditView, SIGNAL('itemAdded'), SIGNAL('itemAdded')) self.connect(self.listEditView, SIGNAL('itemModified'), SIGNAL('itemModified')) self.connect(self.listEditView.model, SIGNAL('dataChanged(QModelIndex,QModelIndex)'), SIGNAL('dataChanged(QModelIndex,QModelIndex)')) self.connect(self.listEditView.model, SIGNAL('rowsRemoved(QModelIndex,int,int)'), SIGNAL('rowsRemoved(QModelIndex,int,int)')) self.connect(self.listEditView.model, SIGNAL('headerDataChanged(Qt::Orientation,int,int)'), SIGNAL('headerDataChanged(Qt::Orientation,int,int)')) self.connect(self.listEditView, SIGNAL('itemDeleted'), SIGNAL('itemDeleted')) self.connect(self.listEditView, SIGNAL('itemSorted'), SIGNAL('itemSorted')) self.connect(self.listEditView.horizontalHeader(), SIGNAL('sectionClicked(int)'), SIGNAL('sectionClicked(int)')) self.connect(self.listEditView, SIGNAL('clicked(QModelIndex)'), SIGNAL('clicked(QModelIndex)')) self.layout().addWidget(self.listEditView, 0, 0) self.buildUpDown() if not isChild: self.buildAddRem() self.setDisplayUpDown(False) self.setReadOnly(False)
class LdapWidget(DirectoryWidget): def __init__(self, config, specific_config, mainwindow, parent=None): assert config is not None assert specific_config is not None DirectoryWidget.__init__(self, config, specific_config, mainwindow, parent) self.buildInterface(config) self.updateView(self.specific_config) def buildInterface(self, config): #<server uri> self.uri = QLineEdit() self.texts.add(self.uri) self.connect(self.uri, SIGNAL('textChanged(QString)'), self.setUri) self.connect(self.uri, SIGNAL('textChanged(QString)'), self.signalModified) self.connect(self.uri, SIGNAL('textEdited(QString)'), self.helpURI) self.connect(self.uri, SIGNAL('editingFinished()'), self.noHelpURI) self.connect(self.uri, SIGNAL('editingFinished()'), self.updateUri) self.form.addRow(tr('LDAP Server(s) uri'), self.uri) self.uri.setToolTip(help_uri_tooltip) self.connect(self.uri, SIGNAL('returnPressed()'), self.signalModified) self.uri_message_area = MessageArea() self.empty_uri_label = QLabel() self.form.addRow(self.empty_uri_label, self.uri_message_area) self.empty_uri_label.hide() self.uri_message_area.hide() self.uri_message_area.setMessage(help_uri_title, help_uri_message_area) self.numeric_uri_warning = MessageArea() empty = QLabel() self.form.addRow(empty, self.numeric_uri_warning) empty.hide() self.numeric_uri_warning.hide() self.numeric_uri_warning.warning(numeric_warning_title, numeric_warning) self.numeric_uri_warning.setWidth(60) #</server uri> #<other fields> for args in self._genTextFieldsData(): text_input = self.addTextInput(*args[1:]) setattr(self, args[0], text_input) self.connect(text_input, SIGNAL('editingFinished(QString)'), self.valid) #</other fields> self.ssl_box = self.mkSslBox() self.connect(self.ssl_box, SIGNAL('toggled(bool)'), self.toggleSsl) self.form.addRow(self.ssl_box) self.form.addRow(separator()) test_widget = QPushButton(tr("Test this configuration")) self.form.addRow("", test_widget) test_widget.connect(test_widget, SIGNAL('clicked()'), self.test_ldap) def _genTextFieldsData(self): return ( ('dn_users', tr('LDAP DN for users'), self.setDnUsers), ('dn_groups', tr('LDAP DN for groups'), self.setDnGroups), ('user', tr('DN used to log in on the LDAP server'), self.setUser), ('password', tr('Password used to log in on the LDAP server'), self.setPassword, False) ) def test_ldap(self): dc, base, uri, filter, password = self.specific_config.generateTest() if uri is None or uri == '': QMessageBox.critical( self, "Missing data", "Please fill URI field" ) return if dc is None: dc == '' filter, ok = QInputDialog.getText( self, tr("LDAP Filter"), tr("Please enter a filter:"), QLineEdit.Normal, filter ) if not ok: return async = self.mainwindow.client.async() async.call( 'nuauth', 'testLDAP', dc, base, uri, unicode(filter), password, callback = self.success_test, errback = self.error_test ) def success_test(self, result): ans_no = tr("OK") ans_yes = tr("Show the server's answer") show_details = QMessageBox.question( self, tr('LDAP test results'), tr('LDAP test completed without error'), ans_no, ans_yes ) if show_details == 0: return title = tr('LDAP test results') QMessageBox.information( self, title, '<span><h2>%s</h2><pre>%s</pre></span>' % (title, unicode(result)) ) def error_test(self, result): basic_text = tr('LDAP test completed with an error') formatted_text = u"""\ <span> %s <pre> %s </pre> </span> """ % (basic_text, unicode(result)) QMessageBox.warning( self, tr('LDAP test results'), formatted_text ) def helpURI(self, text): self.uri_message_area.show() def noHelpURI(self): self.uri_message_area.hide() def toggleSsl(self, value): if value: self.selectCustomOrNupki(NUPKI) else: self.specific_config.custom_or_nupki = SSL_DISABLED self.signalModified() def setUri(self, uris_text): self.specific_config.setUri(self.readString(uris_text)) self.signalModified() self.numeric_uri_warning.setVisible(ip_in_ldapuri(self.specific_config.uri)) def setUser(self, user): self.specific_config.user = self.readString(user) def setPassword(self, password): self.specific_config.password = self.readString(password) def setDnUsers(self, dn): self.specific_config.dn_users = self.readString(dn) def setDnGroups(self, dn): self.specific_config.dn_groups = self.readString(dn) def mkSslBox(self): group = QGroupBox(tr("Check server certificate")) group.setCheckable(True) box = QVBoxLayout(group) #id 0 nupki = QRadioButton(tr("Upload certificate")) #id 1 custom = QRadioButton(tr("Use an internal PKI")) hbox = QHBoxLayout() box.addLayout(hbox) self.nupki_or_custom = QButtonGroup() self.connect(self.nupki_or_custom, SIGNAL('buttonClicked(int)'), self.toggleCustomOrNupki) for index, radio in enumerate((custom, nupki)): hbox.addWidget(radio) self.nupki_or_custom.addButton(radio, index) self.file_selector_widget = QWidget() vbox = QVBoxLayout(self.file_selector_widget) selector_label = QLabel(tr("Manually uploaded LDAP certificate")) vbox.addWidget(selector_label) add_cert_trigger = AddButton(text=tr("Upload a certificate")) vbox.addWidget(add_cert_trigger) vbox.addWidget(separator()) self.has_cert_message = QLabel( tr("There is no manually uploaded server certificate") ) self.del_cert = RemButton( tr("Delete certificate file from server") ) vbox.addWidget(self.has_cert_message) vbox.addWidget(self.del_cert) self.connect(add_cert_trigger, SIGNAL('clicked()'), self.upload_server_cert) self.connect(self.del_cert, SIGNAL('clicked()'), self.delete_server_cert) self.nupki_message = MessageArea() self.nupki_message.setMessage(tr("Warning"), tr( "There is no server certificate in the internal PKI.<br/>" "Please import or generate one using an internal PKI." ) ) for anti_button, widget in ((custom, self.nupki_message), (nupki, self.file_selector_widget)): box.addWidget(widget) self.connect(anti_button, SIGNAL('toggled(bool)'), widget.setVisible) self.selectCustomOrNupki(CUSTOM) return group def upload_server_cert(self): dialog = UploadDialog( selector_label=tr("LDAP certificate"), filter=tr("Certificate file (*.crt *.pem *)") ) accepted = dialog.exec_() if accepted != QDialog.Accepted: return filename = dialog.filename if not filename: return with open(filename, 'rb') as fd: content = fd.read() content = encodeFileContent(content) self.mainwindow.addToInfoArea(tr('Uploading of a certificate file for the ldap server')) async = self.mainwindow.client.async() async.call("nuauth", "upload_ldap_server_cert", content, callback = self.success_upload, errback = self.error_upload ) def success_upload(self, value): self.mainwindow.addToInfoArea(tr('[LDAP server cert upload] Success!')) self.specific_config.server_cert_set = True self.setServerCert() self.signalModified() def error_upload(self, value): self.mainwindow.addToInfoArea(tr('[LDAP server cert upload] Error!'), COLOR_ERROR) self.mainwindow.addToInfoArea(tr('[LDAP server cert upload] %s') % value, COLOR_ERROR) def setServerCert(self): if self.specific_config.server_cert_set: self.del_cert.show() self.has_cert_message.hide() else: self.del_cert.hide() self.has_cert_message.show() def delete_server_cert(self): confirm_box = QMessageBox(self) confirm_box.setText( tr( "Please confirm the deletion of the " "manually uploaded LDAP server certificate." ) ) confirm_box.setInformativeText( tr("Do you really want to delete the certificate file?") ) confirm_box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) confirm_box.setDefaultButton(QMessageBox.Cancel) confirm = confirm_box.exec_() if confirm != QMessageBox.Ok: return async = self.mainwindow.client.async() async.call("nuauth", "delete_ldap_server_cert", callback = self.success_delete, errback = self.error_delete ) def success_delete(self, value): self.mainwindow.addToInfoArea(tr('[LDAP server cert deletion] Success!')) self.specific_config.server_cert_set = False self.setServerCert() self.signalModified() def error_delete(self, value): self.mainwindow.addToInfoArea(tr('[LDAP server cert deletion] Error!'), COLOR_ERROR) self.mainwindow.addToInfoArea(tr('[LDAP server cert deletion] %s') % value, COLOR_ERROR) def toggleCustomOrNupki(self, id): if id == 0: self.specific_config.custom_or_nupki = NUPKI else: self.specific_config.custom_or_nupki = CUSTOM self.signalModified() def selectCustomOrNupki(self, custom_or_nupki): if custom_or_nupki == CUSTOM: self.file_selector_widget.setEnabled(True) self.nupki_message.hide() id = 1 else: custom_or_nupki = NUPKI self.file_selector_widget.hide() id = 0 self.nupki_or_custom.button(id).setChecked(True) def setSslData(self, config): ssl_enabled = (SSL_DISABLED != config.custom_or_nupki) self.ssl_box.setChecked(ssl_enabled) if ssl_enabled: self.selectCustomOrNupki(config.custom_or_nupki) def updateUri(self, config=None): if config is None: config = self.specific_config self.setText(self.uri, config.uri) def updateView(self, config=None): if config is None: config = self.specific_config self.updateUri(config=config) self.setSslData(config) #never copy this one: self.setDefaultText(self.dn_users, self.specific_config.dn_users) self.setDefaultText(self.dn_groups, self.specific_config.dn_groups) self.setDefaultText(self.user, config.user) self.setDefaultText(self.password, config.password) self.setServerCert()
class ListEdit(QWidget): def __init__(self, parent=None, isChild=False): QWidget.__init__(self, parent) QGridLayout(self) # FIXME: call self.setLayout(layout)? self._readonly = False self.up_down = QFrame() self.up = UpButton() self.down = DownButton() self.add = AddButton() self.rem = RemButton() self.listEditView = ListEditView(isChild, parent=self) self.connect(self.listEditView, SIGNAL('itemAdded'), SIGNAL('itemAdded')) self.connect(self.listEditView, SIGNAL('itemModified'), SIGNAL('itemModified')) self.connect(self.listEditView.model, SIGNAL('dataChanged(QModelIndex,QModelIndex)'), SIGNAL('dataChanged(QModelIndex,QModelIndex)')) self.connect(self.listEditView.model, SIGNAL('rowsRemoved(QModelIndex,int,int)'), SIGNAL('rowsRemoved(QModelIndex,int,int)')) self.connect(self.listEditView.model, SIGNAL('headerDataChanged(Qt::Orientation,int,int)'), SIGNAL('headerDataChanged(Qt::Orientation,int,int)')) self.connect(self.listEditView, SIGNAL('itemDeleted'), SIGNAL('itemDeleted')) self.connect(self.listEditView, SIGNAL('itemSorted'), SIGNAL('itemSorted')) self.connect(self.listEditView.horizontalHeader(), SIGNAL('sectionClicked(int)'), SIGNAL('sectionClicked(int)')) self.connect(self.listEditView, SIGNAL('clicked(QModelIndex)'), SIGNAL('clicked(QModelIndex)')) self.layout().addWidget(self.listEditView, 0, 0) self.buildUpDown() if not isChild: self.buildAddRem() self.setDisplayUpDown(False) self.setReadOnly(False) # Qt Properties ... def getReadOnly(self): return self._readonly def setReadOnly(self, readonly): self._readonly = readonly self.up.setEnabled(not self.readOnly) self.down.setEnabled(not self.readOnly) self.add.setEnabled(not self.readOnly) self.rem.setEnabled(not self.readOnly) self.listEditView.setReadOnly(self.readOnly) def resetReadOnly(self): self._readonly = False readOnly = pyqtProperty('bool', getReadOnly, setReadOnly, resetReadOnly) def getAcceptDrops(self): return self.listEditView.acceptDrops() def setAcceptDrops(self, mode): self.listEditView.setAcceptDrops(mode) flags = self.listEditView.model.getFlags() if mode: flags |= Qt.ItemIsDropEnabled else: flags &= ~Qt.ItemIsDropEnabled self.listEditView.model.setFlags(flags) def resetAcceptDrops(self): self.setAcceptDrops(False) acceptDrops = pyqtProperty('bool', getAcceptDrops, setAcceptDrops, resetAcceptDrops) def getDragDropMode(self): return self.listEditView.dragDropMode() Q_ENUMS('QAbstractItemView.DragDropMode') def setDragDropMode(self, mode): self.listEditView.setDragDropMode(mode) def resetDragDropMode(self): self.listEditView.setDragDropMode(QAbstractItemView.NoDragDrop) dragDropMode = pyqtProperty('QAbstractItemView::DragDropMode', getDragDropMode, setDragDropMode, resetDragDropMode) def getShowDropIndicator(self): return self.listEditView.showDropIndicator() def setShowDropIndicator(self, mode): self.listEditView.setShowDropIndicator(mode) def resetShowDropIndicator(self): self.listEditView.setShowDropIndicator(False) showDropIndicator = pyqtProperty('bool', getShowDropIndicator, setShowDropIndicator, resetShowDropIndicator) def getDisplayUpDown(self): return self.up_down.isVisible() def setDisplayUpDown(self, displayUpDown): self.up_down.setVisible(displayUpDown) def resetDisplayUpDown(self): self.up_down.setVisible(False) displayUpDown = pyqtProperty('bool', getDisplayUpDown, setDisplayUpDown, resetDisplayUpDown) def getEditBoxDescription(self): return self.listEditView.getEditBoxDescription() def setEditBoxDescription(self, description): self.listEditView.setEditBoxDescription(description) def resetEditBoxDescription(self): self.listEditView.resetEditBoxDescription() editBoxDescription = pyqtProperty('QString', getEditBoxDescription, setEditBoxDescription, resetEditBoxDescription) def getHeaders(self): return self.listEditView.getHeaders() def setHeaders(self, headers): self.listEditView.setHeaders(headers) def resetHeaders(self): self.listEditView.resetHeaders() headers = pyqtProperty('QStringList', getHeaders, setHeaders, resetHeaders) def getEditInPopup(self): return self.listEditView.editInPopup def setEditInPopup(self, in_popup): self.listEditView.editInPopup = in_popup def resetEditInPopup(self): self.listEditView.editInPopup = True editInPopup = pyqtProperty('bool', getEditInPopup, setEditInPopup, resetEditInPopup) def getEditInPlace(self): return self.listEditView.editInPlace def setEditInPlace(self, edit_in_place): self.listEditView.editInPlace = edit_in_place def resetEditInPlace(self): self.listEditView.editInPlace = False editInPlace = pyqtProperty('bool', getEditInPlace, setEditInPlace, resetEditInPlace) # ... Qt Properties def setDropMimeData(self, callback): self.listEditView.model.dropMimeData_cb = callback def setEditBox(self, editBox): """allow to customize edit popup""" # box = editBox([row1, row2, row3], listEditOption, windowTitle) # ret = box.exec_() # if QDialog.Accepted == ret: # newData = box.getData() # # newData : [ modifiedRow1, modifiedRow2, modifiedRow3 ] # box must return QDialog.Accepted if data have been modified / created # then data must be returned by box.getData() self.listEditView.editBox = editBox def setColDelegate(self, callback): """callback prototype: createDelegate(view, column)""" self.listEditView.setColDelegate(callback) def buildUpDown(self): up_down_layout = QVBoxLayout(self.up_down) up_down_layout.addWidget(self.up) up_down_layout.addWidget(self.down) up_down_layout.insertStretch(0) up_down_layout.insertStretch(-1) self.layout().addWidget(self.up_down, 0, 1) self.connect(self.up, SIGNAL('clicked()'), self.listEditView.upItem) self.connect(self.down, SIGNAL('clicked()'), self.listEditView.downItem) def buildAddRem(self): buttons = QFrame() buttons_layout = QHBoxLayout(buttons) buttons_layout.insertStretch(1) self.connect(self.add, SIGNAL('clicked()'), self.listEditView.addItem) self.connect(self.rem, SIGNAL('clicked()'), self.listEditView.removeItem) buttons_layout.addWidget(self.add) buttons_layout.addWidget(self.rem) self.layout().addWidget(buttons, 1, 0) def hideRow(self, row): self.listEditView.verticalHeader().setSectionHidden(row, True) def showRow(self, row): self.listEditView.verticalHeader().setSectionHidden(row, False) def hideColumn(self, col): self.listEditView.horizontalHeader().setSectionHidden(col, True) def showColumn(self, col): self.listEditView.horizontalHeader().setSectionHidden(col, False) def reset(self, data): """ TODO call clean & setData & reset """ self.listEditView.model.newData(data) self.listEditView.model.emit(SIGNAL("modelReset()")) def rawData(self): # TODO use model.data(...) return deepcopy(self.listEditView.model._data)