class VariableListBox(QWidget): def __init__(self, id, text, sep=","): QWidget.__init__(self) self.widget = QListWidget() self.widget.setToolTip(text) self.widget.setSelectionMode(QAbstractItemView.ExtendedSelection) label = QLabel(text) label.setBuddy(self.widget) vbox = VBoxLayout() vbox.addWidget(label) vbox.addWidget(self.widget) self.setLayout(vbox) self.id = id self.sep = sep def parameterValues(self): self.widget.selectAll() items = self.widget.selectedItems() first = True var = QString() for item in items: if first: var.append(item.text()) first = False else: var.append("%s%s" % (self.sep, item.text())) if var.isEmpty(): raise Exception("Error: Insufficient number of input variables") params = {self.id:var} return params
class RMirrorBrowser(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) kwargs = {"local.only":False} m = robjects.r.getCRANmirrors(all=False, **kwargs) names = QStringList(list(m.rx('Name')[0])) urls = list(m.rx('URL')[0]) self.links = dict(zip(names, urls)) names = QStringList(names) self.setWindowTitle("manageR - Choose CRAN Mirror") self.setWindowIcon(QIcon(":icon")) self.links = dict(zip(names, urls)) self.currentMirror = None self.mirrorList = QListWidget(self) self.mirrorList.setAlternatingRowColors(True) self.mirrorList.setEditTriggers(QAbstractItemView.NoEditTriggers) self.mirrorList.setSortingEnabled(True) self.mirrorList.setSelectionMode(QAbstractItemView.SingleSelection) self.mirrorList.setToolTip("Double-click to select mirror location") self.mirrorList.setWhatsThis("List of CRAN mirrors") self.mirrorList.insertItems(0, names) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) vbox = QVBoxLayout(self) vbox.addWidget(self.mirrorList) vbox.addWidget(buttonBox) self.connect(buttonBox, SIGNAL("accepted()"), self.accept) self.connect(buttonBox, SIGNAL("rejected()"), self.reject) self.connect(self.mirrorList, SIGNAL("itemDoubleClicked(QListWidgetItem*)"), self.accept) def currentMirror(self): return robjects.r("getOption('repos')")[0] def setCurrentMirror(self, mirror): robjects.r("options('repos'='%s')" % mirror) def accept(self): items = self.mirrorList.selectedItems() if len(items) > 0: name = items[0].text() url = self.links[name] self.setCurrentMirror(url) QDialog.accept(self) else: QMessageBox.warning(self, "manageR - Warning", "Please choose a valid CRAN mirror")
class ListParameterWidget(GenericParameterWidget): """Widget class for List parameter.""" def __init__(self, parameter, parent=None): """Constructor .. versionadded:: 2.2 :param parameter: A ListParameter object. :type parameter: ListParameter """ super(ListParameterWidget, self).__init__(parameter, parent) self._input = QListWidget() self._input.setSelectionMode(QAbstractItemView.MultiSelection) if self._parameter.maximum_item_count != \ self._parameter.minimum_item_count: tool_tip = 'Select between %d and %d items' % ( self._parameter.minimum_item_count, self._parameter.maximum_item_count) else: tool_tip = 'Select exactly %d items' % ( self._parameter.maximum_item_count) self._input.setToolTip(tool_tip) for opt in self._parameter.options_list: item = QListWidgetItem() item.setFlags(item.flags() | Qt.ItemIsEditable) item.setText(str(opt)) self._input.addItem(item) if opt in self._parameter.value: item.setSelected(True) self.inner_input_layout.addWidget(self._input) # override self._input_layout arrangement to make the label at the top # reset the layout self.input_layout.setParent(None) self.help_layout.setParent(None) self.label.setParent(None) self.inner_input_layout.setParent(None) self.input_layout = QVBoxLayout() self.input_layout.setSpacing(0) # put element into layout self.input_layout.addWidget(self.label) self.input_layout.addLayout(self.inner_input_layout) self.main_layout.addLayout(self.input_layout) self.main_layout.addLayout(self.help_layout) def raise_invalid_type_exception(self): message = 'Expecting element type of %s' % ( self._parameter.element_type.__name__) err = ValueError(message) return err def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A ListParameter from the current state of widget """ selected_value = [] for opt in self._input.selectedItems(): index = self._input.indexFromItem(opt) selected_value.append(self._parameter.options_list[index.row()]) try: self._parameter.value = selected_value except ValueError: err = self.raise_invalid_type_exception() raise err return self._parameter
class ProjectPropertiesDialog( QDialog, object ): """ project properties dialog implementation """ def __init__( self, project = None, parent = None ): QDialog.__init__( self, parent ) # The dialog caller reads this member if the dialog was finished # successfully. self.absProjectFileName = None self.__createLayout() self.__project = project if project is None: # It a new project creation self.setWindowTitle( "New Project Properties" ) userRecord = pwd.getpwuid( os.getuid() ) if not userRecord[ 5 ].endswith( os.path.sep ): self.dirEdit.setText( userRecord[ 5 ] + os.path.sep ) else: self.dirEdit.setText( userRecord[ 5 ] ) self.initialDirName = self.dirEdit.text() self.lastProjectName = "" if userRecord[ 4 ] != "": self.authorEdit.setText( userRecord[ 4 ].split( ',' )[ 0 ].strip() ) else: self.authorEdit.setText( userRecord[ 0 ] ) try: self.emailEdit.setText( userRecord[ 0 ] + "@" + socket.gethostname() ) except: pass self.versionEdit.setText( "0.0.1" ) self.licenseEdit.setText( "GPL v3" ) self.copyrightEdit.setText( "Copyright (c) " + self.authorEdit.text() + ", " + str( datetime.date.today().year ) ) self.creationDateEdit.setText( getLocaleDate() ) self.nameEdit.setFocus() elif type( project ) == type( "" ): self.setWindowTitle( "Viewing Project Properties" ) # This is viewing properties and the argument is the path to the # project file scriptName, importDirs, creationDate, author, lic, \ copy_right, description, \ version, email, uuid = getProjectProperties( project ) if not os.path.isabs( scriptName ) and scriptName != "": scriptName = os.path.normpath( os.path.dirname( project ) + os.path.sep + scriptName ) self.nameEdit.setText( os.path.basename( project ) ) self.nameEdit.setToolTip( "" ) self.dirEdit.setText( os.path.dirname( project ) ) self.dirEdit.setToolTip( "" ) self.scriptEdit.setText( scriptName ) self.versionEdit.setText( version ) self.authorEdit.setText( author ) self.emailEdit.setText( email ) self.licenseEdit.setText( lic ) self.copyrightEdit.setText( copy_right ) self.descriptionEdit.setText( description ) self.creationDateEdit.setText( creationDate ) self.uuidEdit.setText( str( uuid ) ) self.uuidEdit.setToolTip( settingsDir + str( uuid ) + os.path.sep + " (double click to copy path)" ) for item in importDirs: self.importDirList.addItem( item ) self.disableEditing() else: self.setWindowTitle( "Editing Project Properties" ) # This is editing the loaded project. self.nameEdit.setText( os.path.basename( project.fileName ) ) self.nameEdit.setToolTip( "" ) self.dirEdit.setText( project.getProjectDir() ) self.dirEdit.setToolTip( "" ) self.scriptEdit.setText( project.getProjectScript() ) self.versionEdit.setText( project.version ) self.authorEdit.setText( project.author ) self.emailEdit.setText( project.email ) self.licenseEdit.setText( project.license ) self.copyrightEdit.setText( project.copyright ) self.descriptionEdit.setText( project.description ) self.creationDateEdit.setText( project.creationDate ) self.uuidEdit.setText( str( project.uuid ) ) self.uuidEdit.setToolTip( project.userProjectDir + " (double click to copy path)" ) self.setReadOnly() for item in project.importDirs: self.importDirList.addItem( item ) if self.importDirList.count() > 0: self.importDirList.setCurrentRow( 0 ) self.delImportDirButton.setEnabled( True ) # The project could be the one belonging to another user # so there might be no write permissions. if not os.access( project.fileName, os.W_OK ): # Disable editing self.setWindowTitle( "Viewing Project Properties (no write permissions)" ) self.disableEditing() else: self.scriptEdit.setFocus() return def __createLayout( self ): """ Creates the dialog layout """ self.resize( 600, 400 ) self.setSizeGripEnabled( True ) verticalLayout = QVBoxLayout( self ) gridLayout = QGridLayout() # Project name nameLabel = QLabel( self ) nameLabel.setText( "Project name:" ) gridLayout.addWidget( nameLabel, 0, 0, 1, 1 ) self.nameEdit = QLineEdit( self ) self.nameEdit.setToolTip( "Type a project name without a path" ) self.nameEdit.installEventFilter( self ) gridLayout.addWidget( self.nameEdit, 0, 1, 1, 1 ) # Project dir dirLabel = QLabel( self ) dirLabel.setText( "Project directory:" ) gridLayout.addWidget( dirLabel, 1, 0, 1, 1 ) self.dirEdit = QLineEdit( self ) self.dirEdit.setToolTip( "Not existed directories will be created" ) gridLayout.addWidget( self.dirEdit, 1, 1, 1, 1 ) self.dirButton = QPushButton( self ) self.dirButton.setText( "..." ) gridLayout.addWidget( self.dirButton, 1, 2, 1, 1 ) self.dirCompleter = DirCompleter( self.dirEdit ) # Project script mainScriptLabel = QLabel( "Main script:", self ) gridLayout.addWidget( mainScriptLabel, 2, 0, 1, 1 ) self.scriptEdit = QLineEdit( self ) self.scriptEdit.setToolTip( "Project main script, " "used when the project is run" ) gridLayout.addWidget( self.scriptEdit, 2, 1, 1, 1 ) self.scriptButton = QPushButton( "...", self ) gridLayout.addWidget( self.scriptButton, 2, 2, 1, 1 ) self.fileCompleter = FileCompleter( self.scriptEdit ) # Import dirs importLabel = QLabel( self ) importLabel.setText( "Import directories:" ) importLabel.setAlignment( Qt.AlignTop ) gridLayout.addWidget( importLabel, 3, 0, 1, 1 ) self.importDirList = QListWidget( self ) self.importDirList.setAlternatingRowColors( True ) self.importDirList.setSelectionMode( QAbstractItemView.SingleSelection ) self.importDirList.setSelectionBehavior( QAbstractItemView.SelectRows ) self.importDirList.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.importDirList.setToolTip( "Directories where to look for " "project specific imports" ) gridLayout.addWidget( self.importDirList, 3, 1, 1, 1 ) self.addImportDirButton = QPushButton( self ) self.addImportDirButton.setText( "Add dir" ) self.delImportDirButton = QPushButton( self ) self.delImportDirButton.setText( "Delete dir" ) self.delImportDirButton.setEnabled( False ) vLayout = QVBoxLayout() vLayout.addWidget( self.addImportDirButton ) vLayout.addWidget( self.delImportDirButton ) vLayout.addStretch( 0 ) gridLayout.addLayout( vLayout, 3, 2, 1, 1 ) # Version versionLabel = QLabel( self ) versionLabel.setText( "Version:" ) gridLayout.addWidget( versionLabel, 4, 0, 1, 1 ) self.versionEdit = QLineEdit( self ) gridLayout.addWidget( self.versionEdit, 4, 1, 1, 1 ) # Author authorLabel = QLabel( self ) authorLabel.setText( "Author:" ) gridLayout.addWidget( authorLabel, 5, 0, 1, 1 ) self.authorEdit = QLineEdit( self ) gridLayout.addWidget( self.authorEdit, 5, 1, 1, 1 ) # E-mail emailLabel = QLabel( self ) emailLabel.setText( "E-mail:" ) gridLayout.addWidget( emailLabel, 6, 0, 1, 1 ) self.emailEdit = QLineEdit( self ) gridLayout.addWidget( self.emailEdit, 6, 1, 1, 1 ) # License licenseLabel = QLabel( self ) licenseLabel.setText( "License:" ) gridLayout.addWidget( licenseLabel, 7, 0, 1, 1 ) self.licenseEdit = QLineEdit( self ) gridLayout.addWidget( self.licenseEdit, 7, 1, 1, 1 ) # Copyright copyrightLabel = QLabel( self ) copyrightLabel.setText( "Copyright:" ) gridLayout.addWidget( copyrightLabel, 8, 0, 1, 1 ) self.copyrightEdit = QLineEdit( self ) gridLayout.addWidget( self.copyrightEdit, 8, 1, 1, 1 ) # Description descriptionLabel = QLabel( self ) descriptionLabel.setText( "Description:" ) descriptionLabel.setAlignment( Qt.AlignTop ) gridLayout.addWidget( descriptionLabel, 9, 0, 1, 1 ) self.descriptionEdit = QTextEdit( self ) self.descriptionEdit.setTabChangesFocus( True ) self.descriptionEdit.setAcceptRichText( False ) gridLayout.addWidget( self.descriptionEdit, 9, 1, 1, 1 ) # Creation date creationDateLabel = QLabel( self ) creationDateLabel.setText( "Creation date:" ) gridLayout.addWidget( creationDateLabel, 10, 0, 1, 1 ) self.creationDateEdit = FramedLabelWithDoubleClick() self.creationDateEdit.setToolTip( "Double click to copy" ) gridLayout.addWidget( self.creationDateEdit, 10, 1, 1, 1 ) # Project UUID uuidLabel = QLabel( self ) uuidLabel.setText( "UUID:" ) gridLayout.addWidget( uuidLabel, 11, 0, 1, 1 ) self.uuidEdit = FramedLabelWithDoubleClick( "", self.__copyProjectPath ) gridLayout.addWidget( self.uuidEdit, 11, 1, 1, 1 ) verticalLayout.addLayout( gridLayout ) # Buttons at the bottom buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Cancel | \ QDialogButtonBox.Ok ) verticalLayout.addWidget( buttonBox ) nameLabel.setBuddy( self.nameEdit ) dirLabel.setBuddy( self.dirEdit ) versionLabel.setBuddy( self.versionEdit ) authorLabel.setBuddy( self.authorEdit ) emailLabel.setBuddy( self.emailEdit ) licenseLabel.setBuddy( self.licenseEdit ) copyrightLabel.setBuddy( self.copyrightEdit ) descriptionLabel.setBuddy( self.descriptionEdit ) buttonBox.accepted.connect( self.onOKButton ) buttonBox.rejected.connect( self.reject ) self.dirButton.clicked.connect( self.onDirButton ) self.scriptButton.clicked.connect( self.onScriptButton ) self.importDirList.currentRowChanged.connect( self.onImportDirRowChanged ) self.addImportDirButton.clicked.connect( self.onAddImportDir ) self.delImportDirButton.clicked.connect( self.onDelImportDir ) self.nameEdit.textEdited.connect( self.onProjectNameChanged ) self.setTabOrder( self.nameEdit, self.dirEdit ) self.setTabOrder( self.dirEdit, self.dirButton ) self.setTabOrder( self.dirButton, self.scriptEdit ) self.setTabOrder( self.scriptEdit, self.scriptButton ) self.setTabOrder( self.scriptButton, self.importDirList ) self.setTabOrder( self.importDirList, self.addImportDirButton ) self.setTabOrder( self.addImportDirButton, self.delImportDirButton ) self.setTabOrder( self.delImportDirButton, self.versionEdit ) self.setTabOrder( self.versionEdit, self.authorEdit ) self.setTabOrder( self.authorEdit, self.emailEdit ) self.setTabOrder( self.emailEdit, self.licenseEdit ) self.setTabOrder( self.licenseEdit, self.copyrightEdit ) self.setTabOrder( self.copyrightEdit, self.descriptionEdit ) self.setTabOrder( self.descriptionEdit, buttonBox ) return def eventFilter( self, obj, event ): " Event filter for the project name field " # Do not allow path separators if event.type() == QEvent.KeyPress: if event.key() == ord( os.path.sep ): return True return QObject.eventFilter( self, obj, event ) def onDirButton( self ): " Displays a directory selection dialog " dirName = QFileDialog.getExistingDirectory( self, "Select project directory", self.dirEdit.text(), QFileDialog.Options( QFileDialog.ShowDirsOnly ) ) if dirName: self.dirEdit.setText( os.path.normpath( dirName ) ) return def onScriptButton( self ): " Displays a file selection dialog " scriptName = QFileDialog.getOpenFileName( self, "Select project main script", self.dirEdit.text() ) if scriptName: self.scriptEdit.setText( os.path.normpath( scriptName ) ) return def onImportDirRowChanged( self, row ): " Triggered when a current row in the import dirs is changed " self.delImportDirButton.setEnabled( row != -1 ) return def onAddImportDir( self ): " Displays a directory selection dialog " dirName = QFileDialog.getExistingDirectory( self, "Select import directory", self.dirEdit.text(), QFileDialog.Options( QFileDialog.ShowDirsOnly ) ) if not dirName: return # There are 2 cases: new project or # editing the existed project properties if self.__project is None: # It a new project; the project path could be editedd dirToInsert = dirName else: # This is an existed project; no way the project path is changed # Let's decide it a relative path should be used here if self.__project.isProjectDir( dirName ): dirToInsert = relpath( dirName, self.dirEdit.text() ) else: dirToInsert = dirName index = 0 while index < self.importDirList.count(): if self.importDirList.item( index ).text() == dirToInsert: logging.warning( "The directory '" + dirName + "' is already in the list of " "imported directories and is not added." ) return index += 1 self.importDirList.addItem( dirToInsert ) self.importDirList.setCurrentRow( self.importDirList.count() - 1 ) return def onDelImportDir( self ): " Triggered when an import dir should be deleted " rowToDelete = self.importDirList.currentRow() if rowToDelete == -1: self.delImportDirButton.setEnabled( False ) return self.importDirList.takeItem( rowToDelete ) if self.importDirList.count() == 0: self.delImportDirButton.setEnabled( False ) else: self.importDirList.setCurrentRow( self.importDirList.count() - 1 ) return def onOKButton( self ): " Checks that the mandatory fields are filled properly " # The checks must be done for a new project only if not self.nameEdit.isEnabled(): self.accept() return # Check that the project name does not have path separators and is not # empty if not self.nameEdit.text().strip(): QMessageBox.critical( self, "Error", "The project name must not be empty" ) return if os.path.sep in self.nameEdit.text(): QMessageBox.critical( self, "Error", "The project name must not " "contain path separators" ) return # Check that the project directory is given dirName = self.dirEdit.text().strip() if not dirName: QMessageBox.critical( self, "Error", "The project directory must not be empty" ) return dirName = os.path.abspath( dirName ) self.dirEdit.setText( dirName ) # Check that the project file does not exist projectFileName = dirName if not projectFileName.endswith( os.path.sep ): projectFileName += os.path.sep projectFileName += self.nameEdit.text().strip() if not projectFileName.endswith( ".cdm" ): projectFileName += ".cdm" if os.path.exists( projectFileName ): QMessageBox.critical( self, "Error", "The project file " + projectFileName + " exists. Please provide another " "directory / project name." ) return # Check that the project dir is not a file if os.path.exists( dirName ): # It might be a link, so read it first dirName = os.path.realpath( dirName ) if not os.path.exists( dirName ): QMessageBox.critical( self, "Error", "Broken link: " + dirName ) return if not os.path.isdir( dirName ): QMessageBox.critical( self, "Error", "The project directory " "may not be a file" ) return # Check that the dir is writable if not os.access( dirName, os.W_OK ): QMessageBox.critical( self, "Error", "You don't have write permissions on " + dirName ) return else: # Create the directory try: os.makedirs( dirName ) except OSError: QMessageBox.critical( self, "Error", "Cannot create the project directory" ) return # Save the absolute file name for further reading it by the caller self.absProjectFileName = projectFileName # The minimum is provided so we can accept it self.accept() return def onProjectNameChanged( self, newName ): " Called when the project name changed " if newName.endswith( ".cdm" ): newName = newName[ :-4 ] if self.dirEdit.text().strip() == (self.initialDirName + self.lastProjectName): self.dirEdit.setText( self.initialDirName + newName ) self.lastProjectName = newName return def setReadOnly( self ): """ Disables editing some fields """ self.dirEdit.setReadOnly( True ) self.dirEdit.setFocusPolicy( Qt.NoFocus ) self.dirEdit.setDisabled( True ) self.dirButton.setDisabled( True ) self.dirButton.setFocusPolicy( Qt.NoFocus ) self.nameEdit.setReadOnly( True ) self.nameEdit.setFocusPolicy( Qt.NoFocus ) self.nameEdit.setDisabled( True ) return def disableEditing( self ): " Disables all the editing " self.nameEdit.setDisabled( True ) self.dirEdit.setDisabled( True ) self.dirButton.setDisabled( True ) self.scriptEdit.setDisabled( True ) self.scriptButton.setDisabled( True ) self.importDirList.setDisabled( True ) self.addImportDirButton.setDisabled( True ) self.delImportDirButton.setDisabled( True ) self.versionEdit.setDisabled( True ) self.authorEdit.setDisabled( True ) self.emailEdit.setDisabled( True ) self.licenseEdit.setDisabled( True ) self.copyrightEdit.setDisabled( True ) self.descriptionEdit.setDisabled( True ) return def __copyProjectPath( self ): " Copies the project path when a label is double clicked " text = self.uuidEdit.text().strip() if text: path = settingsDir + text + os.path.sep QApplication.clipboard().setText( path ) return
class InputListParameterWidget(GenericParameterWidget): """Widget class for List parameter.""" def __init__(self, parameter, parent=None): """Constructor .. versionadded:: 2.2 :param parameter: A ListParameter object. :type parameter: InputListParameter """ super(InputListParameterWidget, self).__init__(parameter, parent) # value cache for self._parameter.value # copy the list so the original is unaffected self._value_cache = list(self._parameter.value) self._input = QListWidget() self._input.setSelectionMode(QAbstractItemView.SingleSelection) if self._parameter.maximum_item_count != \ self._parameter.minimum_item_count: tool_tip = 'Select between %d and %d items' % ( self._parameter.minimum_item_count, self._parameter.maximum_item_count) else: tool_tip = 'Select exactly %d items' % ( self._parameter.maximum_item_count) self._input.setToolTip(tool_tip) # arrange widget self._insert_item_input = QLineEdit() vbox_layout = QVBoxLayout() hbox_layout = QHBoxLayout() self._input_add_button = QPushButton('Add') self._input_remove_button = QPushButton('Remove') # arrange line edit, add button, remove button in horizontal layout hbox_layout.addWidget(self._insert_item_input) hbox_layout.addWidget(self._input_add_button) hbox_layout.addWidget(self._input_remove_button) # arrange vertical layout vbox_layout.addLayout(hbox_layout) vbox_layout.addWidget(self._input) self._inner_input_layout.addLayout(vbox_layout) # override self._input_layout arrangement to make the label at the top # reset the layout self._input_layout.setParent(None) self._help_layout.setParent(None) self._label.setParent(None) self._inner_input_layout.setParent(None) self._input_layout = QVBoxLayout() self._input_layout.setSpacing(0) # put element into layout self._input_layout.addWidget(self._label) self._input_layout.addLayout(self._inner_input_layout) self._main_layout.addLayout(self._input_layout) self._main_layout.addLayout(self._help_layout) # connect handler # noinspection PyUnresolvedReferences self._input_add_button.clicked.connect(self.on_add_button_click) # noinspection PyUnresolvedReferences self._input_remove_button.clicked.connect(self.on_remove_button_click) # noinspection PyUnresolvedReferences self._insert_item_input.returnPressed.connect( self._input_add_button.click) # noinspection PyUnresolvedReferences self._input.itemChanged.connect(self.on_row_changed) self.refresh_list() # init row add error handler self._add_row_error_handler = None @property def add_row_error_handler(self): """return error handler if user mistakenly add row of unexpected type :return: a function handler :rtype: () -> None """ return self._add_row_error_handler @add_row_error_handler.setter def add_row_error_handler(self, value): """Set error handler to handle user mistakenly add row of unexpected type """ self._add_row_error_handler = value def refresh_list(self): self._input.clear() if not self._parameter.ordering == InputListParameter.NotOrdered: self._value_cache.sort() if self._parameter.ordering == InputListParameter.DescendingOrder: self._value_cache.reverse() for opt in self._value_cache: item = QListWidgetItem() item.setText(str(opt)) item.setFlags(item.flags() | Qt.ItemIsEditable) self._input.addItem(item) def on_add_button_click(self): try: value = self._parameter.element_type( self._insert_item_input.text()) self._value_cache.append(value) self.refresh_list() except ValueError: err = self.raise_invalid_type_exception() if self.add_row_error_handler is not None: self.add_row_error_handler(err) else: raise err def on_remove_button_click(self): for opt in self._input.selectedItems(): index = self._input.indexFromItem(opt) del self._value_cache[index.row()] self.refresh_list() def on_row_changed(self, item): try: index = self._input.indexFromItem(item).row() prev_value = self._value_cache[index] self._value_cache[index] = self._parameter.element_type( item.text()) self.refresh_list() except ValueError: item.setText(str(prev_value)) self.raise_invalid_type_exception() def raise_invalid_type_exception(self): message = 'Expecting element type of %s' % ( self._parameter.element_type.__name__) err = ValueError(message) return err def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A ListParameter from the current state of widget """ try: self._parameter.value = self._value_cache except ValueError: err = self.raise_invalid_type_exception() raise err return self._parameter
class ListParameterWidget(GenericParameterWidget): """Widget class for List parameter.""" def __init__(self, parameter, parent=None): """Constructor .. versionadded:: 2.2 :param parameter: A ListParameter object. :type parameter: ListParameter """ super(ListParameterWidget, self).__init__(parameter, parent) self._input = QListWidget() self._input.setSelectionMode(QAbstractItemView.MultiSelection) if self._parameter.maximum_item_count != \ self._parameter.minimum_item_count: tool_tip = 'Select between %d and %d items' % ( self._parameter.minimum_item_count, self._parameter.maximum_item_count) else: tool_tip = 'Select exactly %d items' % ( self._parameter.maximum_item_count) self._input.setToolTip(tool_tip) for opt in self._parameter.options_list: item = QListWidgetItem() item.setFlags(item.flags() | Qt.ItemIsEditable) item.setText(str(opt)) self._input.addItem(item) if opt in self._parameter.value: item.setSelected(True) self._inner_input_layout.addWidget(self._input) # override self._input_layout arrangement to make the label at the top # reset the layout self._input_layout.setParent(None) self._help_layout.setParent(None) self._label.setParent(None) self._inner_input_layout.setParent(None) self._input_layout = QVBoxLayout() self._input_layout.setSpacing(0) # put element into layout self._input_layout.addWidget(self._label) self._input_layout.addLayout(self._inner_input_layout) self._main_layout.addLayout(self._input_layout) self._main_layout.addLayout(self._help_layout) def raise_invalid_type_exception(self): message = 'Expecting element type of %s' % ( self._parameter.element_type.__name__) err = ValueError(message) return err def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A ListParameter from the current state of widget """ selected_value = [] for opt in self._input.selectedItems(): index = self._input.indexFromItem(opt) selected_value.append(self._parameter.options_list[index.row()]) try: self._parameter.value = selected_value except ValueError: err = self.raise_invalid_type_exception() raise err return self._parameter
class RRepositoryBrowser(QDialog): def __init__(self, pipe, parent=None): QDialog.__init__(self, parent) mirror = robjects.r.getOption('repos') contrib_url = robjects.r.get('contrib.url', mode='function') available_packages = robjects.r.get('available.packages', mode='function') self.setWindowTitle("manageR - Install R Packages") self.setWindowIcon(QIcon(":icon")) p = available_packages() self.pipe = pipe self.names = QStringList(p.rownames) self.parent = parent self.packageList = QListWidget(self) self.packageList.setAlternatingRowColors(True) self.packageList.setEditTriggers(QAbstractItemView.NoEditTriggers) self.packageList.setSortingEnabled(True) self.packageList.setSelectionMode(QAbstractItemView.ExtendedSelection) self.packageList.setToolTip("Select packages to install") self.packageList.setWhatsThis("List of packages available on CRAN") self.packageList.insertItems(0, self.names) self.dependCheckbox = QCheckBox(self) self.dependCheckbox.setText("Install all dependencies") self.dependCheckbox.setChecked(True) self.closeCheckbox = QCheckBox(self) self.closeCheckbox.setText("Close dialog on completion") self.closeCheckbox.setChecked(False) filterEdit = QLineEdit(self) filterLabel = QLabel("Filter packages", self) self.outputEdit = QTextEdit(self) self.outputEdit.setReadOnly(True) self.outputEdit.setVisible(False) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Apply|QDialogButtonBox.Close) self.buttonBox.addButton("Details >>", QDialogButtonBox.ActionRole) vbox = QVBoxLayout(self) hbox = QHBoxLayout() hbox.addWidget(filterLabel) hbox.addWidget(filterEdit) vbox.addLayout(hbox) vbox.addWidget(self.dependCheckbox) vbox.addWidget(self.packageList) vbox.addWidget(self.closeCheckbox) vbox.addWidget(self.outputEdit) vbox.addWidget(self.buttonBox) self.started = False self.setMinimumSize(80,50) self.connect(filterEdit, SIGNAL("textChanged(QString)"), self.filterPackages) #self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject) self.connect(self.buttonBox, SIGNAL("clicked(QAbstractButton*)"), self.buttonClicked) def buttonClicked(self, button): if button.text() == "Details >>": self.showDetails() button.setText("Details <<") elif button.text() == "Details <<": self.hideDetails() button.setText("Details >>") if not self.started: if self.buttonBox.standardButton(button) == QDialogButtonBox.Apply: self.installPackages() else: self.reject() def showDetails(self): self.outputEdit.setVisible(True) def hideDetails(self): self.outputEdit.setVisible(False) def filterPackages(self, text): self.packageList.clear() self.packageList.insertItems(0, self.names.filter(QRegExp(r"^%s" % text))) firstItem = self.packageList.item(0) if firstItem.text().startsWith(text): self.packageList.setCurrentItem(firstItem) # else: # self.packageList.clearSelection() def currentPackages(self): return [unicode(item.text()) for item in self.packageList.selectedItems()] def installPackages(self): pkgs = self.currentPackages() count = len(pkgs) if count < 1: QMessageBox.warning(self, "manageR - Warning", "Please choose at least one valid package") return False pkgs = QStringList(pkgs).join("','") checked = self.dependCheckbox.isChecked() if checked: depends = "TRUE" else: depends = "FALSE" self.pipe.send("install.packages(c('%s'), dependencies=%s, repos=%s)" % (pkgs, depends, robjects.r.getOption("repos"))) self.started = True self.startTimer(30) return True def timerEvent(self, e): if self.started: try: output = self.pipe.recv() if output is None: self.started=False self.killTimer(e.timerId()) else: self.printOutput(output) except EOFError: pass QApplication.processEvents() def printOutput(self, output): self.outputEdit.insertPlainText(output) self.outputEdit.ensureCursorVisible()