class ValidatedDialog(QDialog): """ A dialog for creating a validated new value. Performs validation of name against a provided. Can be used to select from the list or for creating a new value that is not on the list. """ INVALID_COLOR = QColor(255, 235, 235) def __init__(self, title = "Title", description = "Description", unique_names = None, choose_from_list=False): QDialog.__init__(self) self.setModal(True) self.setWindowTitle(title) # self.setMinimumWidth(250) # self.setMinimumHeight(150) if unique_names is None: unique_names = [] self.unique_names = unique_names self.choose_from_list = choose_from_list self.layout = QFormLayout() self.layout.setSizeConstraint(QLayout.SetFixedSize) label = QLabel(description) label.setAlignment(Qt.AlignHCenter) self.layout.addRow(self.createSpace(5)) self.layout.addRow(label) self.layout.addRow(self.createSpace(10)) buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.ok_button = buttons.button(QDialogButtonBox.Ok) self.ok_button.setEnabled(False) if choose_from_list: self.param_name_combo = QComboBox() self.connect(self.param_name_combo, SIGNAL('currentIndexChanged(QString)'), self.validateChoice) for item in unique_names: self.param_name_combo.addItem(item) self.layout.addRow("Job:", self.param_name_combo) else: self.param_name = QLineEdit(self) self.param_name.setFocus() self.connect(self.param_name, SIGNAL('textChanged(QString)'), self.validateName) self.validColor = self.param_name.palette().color(self.param_name.backgroundRole()) self.layout.addRow("Name:", self.param_name) self.layout.addRow(self.createSpace(10)) self.layout.addRow(buttons) self.connect(buttons, SIGNAL('accepted()'), self.accept) self.connect(buttons, SIGNAL('rejected()'), self.reject) self.setLayout(self.layout) def notValid(self, msg): """Called when the name is not valid.""" self.ok_button.setEnabled(False) palette = self.param_name.palette() palette.setColor(self.param_name.backgroundRole(), self.INVALID_COLOR) self.param_name.setToolTip(msg) self.param_name.setPalette(palette) def valid(self): """Called when the name is valid.""" self.ok_button.setEnabled(True) palette = self.param_name.palette() palette.setColor(self.param_name.backgroundRole(), self.validColor) self.param_name.setToolTip("") self.param_name.setPalette(palette) def validateName(self, value): """Called to perform validation of a name. For specific needs override this function and call valid() and notValid(msg).""" value = str(value) if value == "": self.notValid("Can not be empty!") elif not value.find(" ") == -1: self.notValid("No spaces allowed!") elif value in self.unique_names: self.notValid("Name must be unique!") else: self.valid() def validateChoice(self, choice): """Only called when using selection mode.""" self.ok_button.setEnabled(not choice == "") def getName(self): """Return the new name chosen by the user""" if self.choose_from_list: return str(self.param_name_combo.currentText()) else: return str(self.param_name.text()) def showAndTell(self): """Shows the dialog and returns the result""" if self.exec_(): return str(self.getName()).strip() return "" def createSpace(self, size = 5): """Creates a widget that can be used as spacing on a panel.""" qw = QWidget() qw.setMinimumSize(QSize(size, size)) return qw
class ValidatedDialog(QDialog): """ A dialog for creating a validated new value. Performs validation of name against a provided. Can be used to select from the list or for creating a new value that is not on the list. """ INVALID_COLOR = QColor(255, 235, 235) def __init__(self, title="Title", description="Description", unique_names=None, choose_from_list=False): QDialog.__init__(self) self.setModal(True) self.setWindowTitle(title) # self.setMinimumWidth(250) # self.setMinimumHeight(150) if unique_names is None: unique_names = [] self.unique_names = unique_names self.choose_from_list = choose_from_list self.layout = QFormLayout() self.layout.setSizeConstraint(QLayout.SetFixedSize) label = QLabel(description) label.setAlignment(Qt.AlignHCenter) self.layout.addRow(self.createSpace(5)) self.layout.addRow(label) self.layout.addRow(self.createSpace(10)) buttons = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.ok_button = buttons.button(QDialogButtonBox.Ok) self.ok_button.setEnabled(False) if choose_from_list: self.param_name_combo = QComboBox() self.connect(self.param_name_combo, SIGNAL('currentIndexChanged(QString)'), self.validateChoice) for item in unique_names: self.param_name_combo.addItem(item) self.layout.addRow("Job:", self.param_name_combo) else: self.param_name = QLineEdit(self) self.param_name.setFocus() self.connect(self.param_name, SIGNAL('textChanged(QString)'), self.validateName) self.validColor = self.param_name.palette().color( self.param_name.backgroundRole()) self.layout.addRow("Name:", self.param_name) self.layout.addRow(self.createSpace(10)) self.layout.addRow(buttons) self.connect(buttons, SIGNAL('accepted()'), self.accept) self.connect(buttons, SIGNAL('rejected()'), self.reject) self.setLayout(self.layout) def notValid(self, msg): """Called when the name is not valid.""" self.ok_button.setEnabled(False) palette = self.param_name.palette() palette.setColor(self.param_name.backgroundRole(), self.INVALID_COLOR) self.param_name.setToolTip(msg) self.param_name.setPalette(palette) def valid(self): """Called when the name is valid.""" self.ok_button.setEnabled(True) palette = self.param_name.palette() palette.setColor(self.param_name.backgroundRole(), self.validColor) self.param_name.setToolTip("") self.param_name.setPalette(palette) def validateName(self, value): """Called to perform validation of a name. For specific needs override this function and call valid() and notValid(msg).""" value = str(value) if value == "": self.notValid("Can not be empty!") elif not value.find(" ") == -1: self.notValid("No spaces allowed!") elif value in self.unique_names: self.notValid("Name must be unique!") else: self.valid() def validateChoice(self, choice): """Only called when using selection mode.""" self.ok_button.setEnabled(not choice == "") def getName(self): """Return the new name chosen by the user""" if self.choose_from_list: return str(self.param_name_combo.currentText()) else: return str(self.param_name.text()) def showAndTell(self): """Shows the dialog and returns the result""" if self.exec_(): return str(self.getName()).strip() return "" def createSpace(self, size=5): """Creates a widget that can be used as spacing on a panel.""" qw = QWidget() qw.setMinimumSize(QSize(size, size)) return qw
class PathChooser(HelpedWidget): """ PathChooser: shows, enables choosing of and validates paths. The data structure expected and sent to the models getValue and setValue is a string. """ PATH_DOES_NOT_EXIST_MSG = "The specified path does not exist." FILE_IS_NOT_EXECUTABLE_MSG = "The specified file is not an executable." PATH_IS_NOT_A_FILE_MSG = "The specified path must be a file." PATH_IS_NOT_ABSOLUTE_MSG = "The specified path must be an absolute path." PATH_IS_NOT_A_DIRECTORY_MSG = "The specified path must be a directory." REQUIRED_FIELD_MSG = "A path is required." # UNDEFINED = 0 # REQUIRED = 1 # FILE = 2 # DIRECTORY = 4 # MUST_EXIST = 8 # EXECUTABLE = 16 def __init__(self, model, path_label="Path", help_link=""): HelpedWidget.__init__(self, path_label, help_link) self.__editing = True self.__valid = True self.path_line = QLineEdit() self.path_line.setMinimumWidth(250) self.addWidget(self.path_line) dialog_button = QToolButton(self) dialog_button.setIcon(resourceIcon("ide/small/folder")) dialog_button.setIconSize(QSize(16, 16)) self.connect(dialog_button, SIGNAL('clicked()'), self.selectPath) self.addWidget(dialog_button) self.valid_color = self.path_line.palette().color( self.path_line.backgroundRole()) self.path_line.setText(os.getcwd()) self.__editing = False assert isinstance(model, PathModelMixin) self.model = model model.observable().attach(PathModelMixin.PATH_CHANGED_EVENT, self.getPathFromModel) self.connect(self.path_line, SIGNAL('editingFinished()'), self.validatePath) self.connect(self.path_line, SIGNAL('editingFinished()'), self.contentsChanged) self.connect(self.path_line, SIGNAL('textChanged(QString)'), self.validatePath) self.getPathFromModel() def isPathValid(self, path): """ @rtype: tuple of (bool, str) """ path = path.strip() path_exists = os.path.exists(path) is_file = os.path.isfile(path) is_directory = os.path.isdir(path) is_executable = os.access(path, os.X_OK) is_absolute = os.path.isabs(path) valid = True message = "" if path == "": if self.model.pathIsRequired(): valid = False message = PathChooser.REQUIRED_FIELD_MSG elif not path_exists: if self.model.pathMustExist(): valid = False message = PathChooser.PATH_DOES_NOT_EXIST_MSG #todo: check if new (non-existing) file has directory or file format? elif path_exists: if self.model.pathMustBeExecutable( ) and is_file and not is_executable: valid = False message = PathChooser.FILE_IS_NOT_EXECUTABLE_MSG elif self.model.pathMustBeADirectory() and not is_directory: valid = False message = PathChooser.PATH_IS_NOT_A_DIRECTORY_MSG elif self.model.pathMustBeAbsolute() and not is_absolute: valid = False message = PathChooser.PATH_IS_NOT_ABSOLUTE_MSG elif self.model.pathMustBeAFile() and not is_file: valid = False message = PathChooser.PATH_IS_NOT_A_FILE_MSG return valid, message def validatePath(self): """Called whenever the path is modified""" palette = self.path_line.palette() valid, message = self.isPathValid(self.getPath()) validity_type = self.WARNING if not valid: color = self.ERROR_COLOR else: color = self.valid_color self.__valid = valid self.setValidationMessage(message, validity_type) self.path_line.setToolTip(message) palette.setColor(self.path_line.backgroundRole(), color) self.path_line.setPalette(palette) def getPath(self): """Returns the path""" return os.path.expanduser(str(self.path_line.text()).strip()) def pathExists(self): """Returns True if the entered path exists""" return os.path.exists(self.getPath()) def isValid(self): """Returns the validation value""" return self.__valid def selectPath(self): """Pops up the 'select a file/directory' dialog""" # todo: This probably needs some reworking to work properly with different scenarios... (file + dir) self.__editing = True current_directory = self.getPath() #if not os.path.exists(currentDirectory): # currentDirectory = "~" if self.model.pathMustBeAFile(): current_directory = QFileDialog.getOpenFileName( self, "Select a file path", current_directory) else: current_directory = QFileDialog.getExistingDirectory( self, "Select a directory", current_directory) if not current_directory == "": if not self.model.pathMustBeAbsolute(): cwd = os.getcwd() match = re.match(cwd + "/(.*)", current_directory) if match: current_directory = match.group(1) self.path_line.setText(current_directory) self.model.setPath(self.getPath()) self.__editing = False def contentsChanged(self): """Called whenever the path is changed.""" path_is_valid, message = self.isPathValid(self.getPath()) if not self.__editing and path_is_valid: self.model.setPath(self.getPath()) def getPathFromModel(self): """Retrieves data from the model and inserts it into the edit line""" self.__editing = True path = self.model.getPath() if path is None: path = "" self.path_line.setText("%s" % path) self.__editing = False def cleanup(self): self.model.observable().detach(PathModelMixin.PATH_CHANGED_EVENT, self.getPathFromModel)
class PathFormatChooser(HelpedWidget): """ PathChooser shows, enables choosing of and validates paths. The data structure expected and sent to the models getValue and setValue is a string. """ path_format_msg = "Must be a path format." # UNDEFINED = 0 # REQUIRED = 1 # FILE = 2 # DIRECTORY = 4 # MUST_EXIST = 8 # EXECUTABLE = 16 def __init__(self, model, path_label="Path", help_link=""): HelpedWidget.__init__(self, path_label, help_link) self.path_line = QLineEdit() #self.pathLine.setMinimumWidth(250) self.addWidget(self.path_line) self.validColor = self.path_line.palette().color(self.path_line.backgroundRole()) self.path_line.setText("Not initialized!") self.editing = False self.connect(self.path_line, SIGNAL('editingFinished()'), self.validatePathFormat) self.connect(self.path_line, SIGNAL('editingFinished()'), self.contentsChanged) self.connect(self.path_line, SIGNAL('textChanged(QString)'), self.validatePathFormat) assert isinstance(model, BasicModelMixin) self.model = model self.getPathFromModel() model.observable().attach(BasicModelMixin.VALUE_CHANGED_EVENT, self.getPathFromModel) def getValidationTypeAndColor(self): """Returns the type of validation message and the color that should be applied""" if self.must_be_set: color = self.ERROR_COLOR validity_type = self.WARNING else: color = self.INVALID_COLOR validity_type = self.EXCLAMATION return validity_type, color def validatePathFormat(self): """Called whenever the path is modified""" palette = self.path_line.palette() path = self.getPathFormat().strip() color = self.validColor message = "" validity_type = self.WARNING self.valid = True if not re.search("%[0-9]*d", path): message = self.path_format_msg color = self.ERROR_COLOR self.valid = False self.setValidationMessage(message, validity_type) self.path_line.setToolTip(message) palette.setColor(self.path_line.backgroundRole(), color) self.path_line.setPalette(palette) def getPathFormat(self): """Returns the path""" return str(self.path_line.text()) def isValid(self): """Returns the validation value""" return self.valid def contentsChanged(self): """Called whenever the path is changed.""" if not self.editing: self.model.setValue(self.getPathFormat()) def getPathFromModel(self): """Retrieves data from the model and inserts it into the edit line""" self.editing = True path = self.model.getValue() if path is None: path = "" self.path_line.setText("%s" % path) self.editing = False
class PathChooser(HelpedWidget): """ PathChooser shows, enables choosing of and validates paths. The data structure expected and sent to the models getValue and setValue is a string. """ file_does_not_exist_msg = "The specified path does not exist." file_is_not_executable_msg = "The specified file is not an executable." path_is_not_a_file_msg = "The specified path must be a file." required_field_msg = "A value is required." # UNDEFINED = 0 # REQUIRED = 1 # FILE = 2 # DIRECTORY = 4 # MUST_EXIST = 8 # EXECUTABLE = 16 def __init__(self, model, path_label="Path", help_link=""): HelpedWidget.__init__(self, path_label, help_link) self.__editing = True self.path_line = QLineEdit() self.addWidget(self.path_line) dialog_button = QToolButton(self) dialog_button.setIcon(resourceIcon("folder")) dialog_button.setIconSize(QSize(16, 16)) self.connect(dialog_button, SIGNAL('clicked()'), self.selectDirectory) self.addWidget(dialog_button) self.valid_color = self.path_line.palette().color(self.path_line.backgroundRole()) self.path_line.setText(os.getcwd()) self.__editing = False assert isinstance(model, PathModelMixin) self.model = model model.observable().attach(PathModelMixin.PATH_CHANGED_EVENT, self.getPathFromModel) self.getPathFromModel() self.connect(self.path_line, SIGNAL('editingFinished()'), self.validatePath) self.connect(self.path_line, SIGNAL('editingFinished()'), self.contentsChanged) self.connect(self.path_line, SIGNAL('textChanged(QString)'), self.validatePath) def getValidationTypeAndColor(self): """Returns the type of validation message and the color that should be applied""" if self.model.pathIsRequired(): color = self.ERROR_COLOR validity_type = self.WARNING else: color = self.INVALID_COLOR validity_type = self.EXCLAMATION return validity_type, color def validatePath(self): """Called whenever the path is modified""" palette = self.path_line.palette() path = self.getPath().strip() exists = os.path.exists(path) color = self.valid_color message = "" validity_type = self.WARNING self.valid = True if path == "" and self.model.pathIsRequired(): message = self.required_field_msg color = self.ERROR_COLOR self.valid = False elif not exists: if self.model.pathMustExist(): message = self.file_does_not_exist_msg self.valid = False validity_type, color = self.getValidationTypeAndColor() elif exists: if self.model.pathMustBeExecutable() and os.path.isfile(path) and not os.access(path, os.X_OK): validity_type, color = self.getValidationTypeAndColor() message = self.file_is_not_executable_msg self.valid = False elif self.model.pathMustBeExecutable() and not os.path.isfile(path): validity_type, color = self.getValidationTypeAndColor() message = self.path_is_not_a_file_msg self.valid = False self.setValidationMessage(message, validity_type) self.path_line.setToolTip(message) palette.setColor(self.path_line.backgroundRole(), color) self.path_line.setPalette(palette) def getPath(self): """Returns the path""" return str(self.path_line.text()) def pathExists(self): """Returns True if the entered path exists""" return os.path.exists(self.getPath()) def isValid(self): """Returns the validation value""" return self.valid def selectDirectory(self): """Pops up the 'select a directory' dialog""" self.__editing = True currentDirectory = self.getPath() #if not os.path.exists(currentDirectory): # currentDirectory = "~" if self.model.pathMustBeAFile(): currentDirectory = QFileDialog.getOpenFileName(self, "Select a path", currentDirectory) else: currentDirectory = QFileDialog.getExistingDirectory(self, "Select a directory", currentDirectory) if not currentDirectory == "": if not self.model.pathMustBeAbsolute(): cwd = os.getcwd() match = re.match(cwd + "/(.*)", currentDirectory) if match: currentDirectory = match.group(1) self.path_line.setText(currentDirectory) self.model.setPath(self.getPath()) self.__editing = False def contentsChanged(self): """Called whenever the path is changed.""" if not self.__editing: if self.model.pathIsRequired() and (self.model.pathMustExist() and self.pathExists()): # print("Pathchooser value set!") self.model.setPath(self.getPath()) #todo: FIX!!!! # else: # print("Pathchooser value not set!") def getPathFromModel(self): """Retrieves data from the model and inserts it into the edit line""" self.__editing = True path = self.model.getPath() if path is None: path = "" self.path_line.setText("%s" % path) self.__editing = False
class PathChooser(QWidget): """ PathChooser: shows, enables choosing of and validates paths. The data structure expected and sent to the models getValue and setValue is a string. """ PATH_DOES_NOT_EXIST_MSG = "The specified path does not exist." FILE_IS_NOT_EXECUTABLE_MSG = "The specified file is not an executable." PATH_IS_NOT_A_FILE_MSG = "The specified path must be a file." PATH_IS_NOT_ABSOLUTE_MSG = "The specified path must be an absolute path." PATH_IS_NOT_A_DIRECTORY_MSG = "The specified path must be a directory." REQUIRED_FIELD_MSG = "A path is required." # UNDEFINED = 0 # REQUIRED = 1 # FILE = 2 # DIRECTORY = 4 # MUST_EXIST = 8 # EXECUTABLE = 16 def __init__(self, model, help_link=""): """ :type model: ert_gui.ertwidgets.models.path_model.PathModel :param help_link: str """ QWidget.__init__(self) addHelpToWidget(self, help_link) self._validation_support = ValidationSupport(self) self._editing = True layout = QHBoxLayout() layout.setMargin(0) self._path_line = QLineEdit() self._path_line.setMinimumWidth(250) layout.addWidget(self._path_line) dialog_button = QToolButton(self) dialog_button.setIcon(resourceIcon("ide/small/folder")) dialog_button.setIconSize(QSize(16, 16)) dialog_button.clicked.connect(self.selectPath) layout.addWidget(dialog_button) self.valid_color = self._path_line.palette().color(self._path_line.backgroundRole()) self._path_line.setText(os.getcwd()) self._editing = False self._model = model self._model.valueChanged.connect(self.getPathFromModel) self._path_line.editingFinished.connect(self.validatePath) self._path_line.editingFinished.connect(self.contentsChanged) self._path_line.textChanged.connect(self.validatePath) self.setLayout(layout) self.getPathFromModel() def isPathValid(self, path): """ @rtype: tuple of (bool, str) """ path = path.strip() path_exists = os.path.exists(path) is_file = os.path.isfile(path) is_directory = os.path.isdir(path) is_executable = os.access(path, os.X_OK) is_absolute = os.path.isabs(path) valid = True message = "" if path == "": if self._model.pathIsRequired(): valid = False message = PathChooser.REQUIRED_FIELD_MSG elif not path_exists: if self._model.pathMustExist(): valid = False message = PathChooser.PATH_DOES_NOT_EXIST_MSG #todo: check if new (non-existing) file has directory or file format? elif path_exists: if self._model.pathMustBeExecutable() and is_file and not is_executable: valid = False message = PathChooser.FILE_IS_NOT_EXECUTABLE_MSG elif self._model.pathMustBeADirectory() and not is_directory: valid = False message = PathChooser.PATH_IS_NOT_A_DIRECTORY_MSG elif self._model.pathMustBeAbsolute() and not is_absolute: valid = False message = PathChooser.PATH_IS_NOT_ABSOLUTE_MSG elif self._model.pathMustBeAFile() and not is_file: valid = False message = PathChooser.PATH_IS_NOT_A_FILE_MSG return valid, message def validatePath(self): """Called whenever the path is modified""" palette = self._path_line.palette() valid, message = self.isPathValid(self.getPath()) validity_type = ValidationSupport.WARNING if not valid: color = ValidationSupport.ERROR_COLOR else: color = self.valid_color self._validation_support.setValidationMessage(message, validity_type) self._path_line.setToolTip(message) palette.setColor(self._path_line.backgroundRole(), color) self._path_line.setPalette(palette) def getPath(self): """Returns the path""" return os.path.expanduser(str(self._path_line.text()).strip()) def pathExists(self): """Returns True if the entered path exists""" return os.path.exists(self.getPath()) def selectPath(self): """Pops up the 'select a file/directory' dialog""" # todo: This probably needs some reworking to work properly with different scenarios... (file + dir) self._editing = True current_directory = self.getPath() #if not os.path.exists(currentDirectory): # currentDirectory = "~" if self._model.pathMustBeAFile(): current_directory = QFileDialog.getOpenFileName(self, "Select a file path", current_directory) else: current_directory = QFileDialog.getExistingDirectory(self, "Select a directory", current_directory) if not current_directory == "": if not self._model.pathMustBeAbsolute(): cwd = os.getcwd() match = re.match(cwd + "/(.*)", current_directory) if match: current_directory = match.group(1) self._path_line.setText(current_directory) self._model.setPath(self.getPath()) self._editing = False def contentsChanged(self): """Called whenever the path is changed.""" path_is_valid, message = self.isPathValid(self.getPath()) if not self._editing and path_is_valid: self._model.setPath(self.getPath()) def getPathFromModel(self): """Retrieves data from the model and inserts it into the edit line""" self._editing = True path = self._model.getPath() if path is None: path = "" self._path_line.setText("%s" % path) self._editing = False def getValidationSupport(self): return self._validation_support def isValid(self): return self._validation_support.isValid()
class PathChooser(HelpedWidget): """ PathChooser shows, enables choosing of and validates paths. The data structure expected and sent to the models getValue and setValue is a string. """ file_does_not_exist_msg = "The specified path does not exist." file_is_not_executable_msg = "The specified file is not an executable." path_is_not_a_file_msg = "The specified path must be a file." required_field_msg = "A value is required." # UNDEFINED = 0 # REQUIRED = 1 # FILE = 2 # DIRECTORY = 4 # MUST_EXIST = 8 # EXECUTABLE = 16 def __init__(self, model, path_label="Path", help_link=""): HelpedWidget.__init__(self, path_label, help_link) self.__editing = True self.path_line = QLineEdit() self.addWidget(self.path_line) dialog_button = QToolButton(self) dialog_button.setIcon(resourceIcon("folder")) dialog_button.setIconSize(QSize(16, 16)) self.connect(dialog_button, SIGNAL('clicked()'), self.selectDirectory) self.addWidget(dialog_button) self.valid_color = self.path_line.palette().color( self.path_line.backgroundRole()) self.path_line.setText(os.getcwd()) self.__editing = False assert isinstance(model, PathModelMixin) self.model = model model.observable().attach(PathModelMixin.PATH_CHANGED_EVENT, self.getPathFromModel) self.getPathFromModel() self.connect(self.path_line, SIGNAL('editingFinished()'), self.validatePath) self.connect(self.path_line, SIGNAL('editingFinished()'), self.contentsChanged) self.connect(self.path_line, SIGNAL('textChanged(QString)'), self.validatePath) def getValidationTypeAndColor(self): """Returns the type of validation message and the color that should be applied""" if self.model.pathIsRequired(): color = self.ERROR_COLOR validity_type = self.WARNING else: color = self.INVALID_COLOR validity_type = self.EXCLAMATION return validity_type, color def validatePath(self): """Called whenever the path is modified""" palette = self.path_line.palette() path = self.getPath().strip() exists = os.path.exists(path) color = self.valid_color message = "" validity_type = self.WARNING self.valid = True if path == "" and self.model.pathIsRequired(): message = self.required_field_msg color = self.ERROR_COLOR self.valid = False elif not exists: if self.model.pathMustExist(): message = self.file_does_not_exist_msg self.valid = False validity_type, color = self.getValidationTypeAndColor() elif exists: if self.model.pathMustBeExecutable() and os.path.isfile( path) and not os.access(path, os.X_OK): validity_type, color = self.getValidationTypeAndColor() message = self.file_is_not_executable_msg self.valid = False elif self.model.pathMustBeExecutable( ) and not os.path.isfile(path): validity_type, color = self.getValidationTypeAndColor() message = self.path_is_not_a_file_msg self.valid = False self.setValidationMessage(message, validity_type) self.path_line.setToolTip(message) palette.setColor(self.path_line.backgroundRole(), color) self.path_line.setPalette(palette) def getPath(self): """Returns the path""" return str(self.path_line.text()) def pathExists(self): """Returns True if the entered path exists""" return os.path.exists(self.getPath()) def isValid(self): """Returns the validation value""" return self.valid def selectDirectory(self): """Pops up the 'select a directory' dialog""" self.__editing = True currentDirectory = self.getPath() #if not os.path.exists(currentDirectory): # currentDirectory = "~" if self.model.pathMustBeAFile(): currentDirectory = QFileDialog.getOpenFileName( self, "Select a path", currentDirectory) else: currentDirectory = QFileDialog.getExistingDirectory( self, "Select a directory", currentDirectory) if not currentDirectory == "": if not self.model.pathMustBeAbsolute(): cwd = os.getcwd() match = re.match(cwd + "/(.*)", currentDirectory) if match: currentDirectory = match.group(1) self.path_line.setText(currentDirectory) self.model.setPath(self.getPath()) self.__editing = False def contentsChanged(self): """Called whenever the path is changed.""" if not self.__editing: if self.model.pathIsRequired() and (self.model.pathMustExist() and self.pathExists()): # print("Pathchooser value set!") self.model.setPath(self.getPath()) #todo: FIX!!!! # else: # print("Pathchooser value not set!") def getPathFromModel(self): """Retrieves data from the model and inserts it into the edit line""" self.__editing = True path = self.model.getPath() if path is None: path = "" self.path_line.setText("%s" % path) self.__editing = False
class PathFormatChooser(HelpedWidget): """ PathChooser shows, enables choosing of and validates paths. The data structure expected and sent to the models getValue and setValue is a string. """ path_format_msg = "Must be a path format." # UNDEFINED = 0 # REQUIRED = 1 # FILE = 2 # DIRECTORY = 4 # MUST_EXIST = 8 # EXECUTABLE = 16 def __init__(self, model, path_label="Path", help_link=""): HelpedWidget.__init__(self, path_label, help_link) self.path_line = QLineEdit() #self.pathLine.setMinimumWidth(250) self.addWidget(self.path_line) self.validColor = self.path_line.palette().color( self.path_line.backgroundRole()) self.path_line.setText("Not initialized!") self.editing = False self.connect(self.path_line, SIGNAL('editingFinished()'), self.validatePathFormat) self.connect(self.path_line, SIGNAL('editingFinished()'), self.contentsChanged) self.connect(self.path_line, SIGNAL('textChanged(QString)'), self.validatePathFormat) assert isinstance(model, BasicModelMixin) self.model = model self.getPathFromModel() model.observable().attach(BasicModelMixin.VALUE_CHANGED_EVENT, self.getPathFromModel) def getValidationTypeAndColor(self): """Returns the type of validation message and the color that should be applied""" if self.must_be_set: color = self.ERROR_COLOR validity_type = self.WARNING else: color = self.INVALID_COLOR validity_type = self.EXCLAMATION return validity_type, color def validatePathFormat(self): """Called whenever the path is modified""" palette = self.path_line.palette() path = self.getPathFormat().strip() color = self.validColor message = "" validity_type = self.WARNING self.valid = True if not re.search("%[0-9]*d", path): message = self.path_format_msg color = self.ERROR_COLOR self.valid = False self.setValidationMessage(message, validity_type) self.path_line.setToolTip(message) palette.setColor(self.path_line.backgroundRole(), color) self.path_line.setPalette(palette) def getPathFormat(self): """Returns the path""" return str(self.path_line.text()) def isValid(self): """Returns the validation value""" return self.valid def contentsChanged(self): """Called whenever the path is changed.""" if not self.editing: self.model.setValue(self.getPathFormat()) def getPathFromModel(self): """Retrieves data from the model and inserts it into the edit line""" self.editing = True path = self.model.getValue() if path is None: path = "" self.path_line.setText("%s" % path) self.editing = False