diff -r c9982bcd00f8 -r c7951eb9d525 E5Gui/E5PathPicker.py --- a/E5Gui/E5PathPicker.py Sun Dec 06 19:09:32 2015 +0100 +++ b/E5Gui/E5PathPicker.py Sat Dec 12 12:38:50 2015 +0100 @@ -40,15 +40,16 @@ CustomMode = 99 NoMode = 100 -# TODO: Refactor the classes using a base class with common functions - -class E5PathPicker(QWidget): +class E5PathPickerBase(QWidget): """ - Class implementing a path picker widget consisting of a line edit and a - tool button to open a file dialog. + Class implementing the base of a path picker widget consisting of a + line edit or combo box and a tool button to open a file dialog. @signal textChanged(path) emitted when the entered path has changed + (line edit based widget) + @signal editTextChanged(path) emitted when the entered path has changed + (combo box based widget) @signal pathSelected(path) emitted after a path has been selected via the file dialog @signal aboutToShowPathPickerDialog emitted before the file dialog is shown @@ -58,23 +59,28 @@ DefaultMode = E5PathPickerModes.NoMode textChanged = pyqtSignal(str) + editTextChanged = pyqtSignal(str) pathSelected = pyqtSignal(str) aboutToShowPathPickerDialog = pyqtSignal() pickerButtonClicked = pyqtSignal() - def __init__(self, parent=None): + def __init__(self, parent=None, useLineEdit=True): """ Constructor @param parent reference to the parent widget @type QWidget + @param useLineEdit flag indicating the use of a line edit + @type bool """ - super(E5PathPicker, self).__init__(parent) + super(E5PathPickerBase, self).__init__(parent) + + self.__lineEditKind = useLineEdit self.__mode = E5PathPicker.DefaultMode self.__editorEnabled = True - self.__completer = None + self._completer = None self.__filters = "" self.__defaultDirectory = "" self.__windowTitle = "" @@ -84,20 +90,28 @@ self.__layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.__layout) - self.__editor = E5ClearableLineEdit(self, self.tr("Enter Path Name")) + if useLineEdit: + self._editor = E5ClearableLineEdit( + self, self.tr("Enter Path Name")) + else: + self._editor = E5ClearableComboBox( + self, self.tr("Enter Path Name")) self.__button = QToolButton(self) self.__button.setToolButtonStyle(Qt.ToolButtonIconOnly) self.__button.setIcon(UI.PixmapCache.getIcon("open.png")) - self.__layout.addWidget(self.__editor) + self.__layout.addWidget(self._editor) self.__layout.addWidget(self.__button) self.__button.clicked.connect(self.__showPathPickerDialog) - self.__editor.textEdited.connect(self.__pathEdited) - self.__editor.textChanged.connect(self.textChanged) + if useLineEdit: + self._editor.textEdited.connect(self.__pathEdited) + self._editor.textChanged.connect(self.textChanged) + else: + self._editor.editTextChanged.connect(self.editTextChanged) - self.setFocusProxy(self.__editor) + self.setFocusProxy(self._editor) self.setFocusPolicy(Qt.StrongFocus) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) @@ -110,8 +124,8 @@ @param path current text of the path line edit @type str """ - if self.__completer and not self.__completer.popup().isVisible(): - self.__completer.setRootPath(Utilities.toNativeSeparators(path)) + if self._completer and not self._completer.popup().isVisible(): + self._completer.setRootPath(Utilities.toNativeSeparators(path)) def setMode(self, mode): """ @@ -125,25 +139,26 @@ oldMode = self.__mode self.__mode = mode - if mode != oldMode or not self.__completer: - if self.__completer: + if mode != oldMode or (self.__lineEditKind and not self._completer): + if self.__lineEditKind and self._completer: # Remove current completer - self.__editor.setCompleter(None) - self.__completer = None + self._editor.setCompleter(None) + self._completer = None if mode != E5PathPickerModes.NoMode: - # Set a new completer - if mode == E5PathPickerModes.DirectoryMode: - self.__completer = E5DirCompleter(self.__editor) - else: - self.__completer = E5FileCompleter(self.__editor) + if self.__lineEditKind: + # Set a new completer + if mode == E5PathPickerModes.DirectoryMode: + self._completer = E5DirCompleter(self._editor) + else: + self._completer = E5FileCompleter(self._editor) # set inactive text if mode == E5PathPickerModes.OpenFilesMode: - self.__editor.setInactiveText( + self._editor.setInactiveText( self.tr("Enter Path Names separated by ';'")) else: - self.__editor.setInactiveText( + self._editor.setInactiveText( self.tr("Enter Path Name")) self.__button.setEnabled(self.__mode != E5PathPickerModes.NoMode) @@ -176,9 +191,40 @@ def clear(self): """ + Public method to clear the current path or list of paths. + """ + self._editor.clear() + + def clearEditText(self): + """ Public method to clear the current path. """ - self.__editor.clear() + if not self.__lineEditKind: + self._editor.clearEditText() + + def _setEditorText(self, text): + """ + Protected method to set the text of the editor. + + @param text text to set + @type str + """ + if self.__lineEditKind: + self._editor.setText(text) + else: + self._editor.setEditText(text) + + def _editorText(self): + """ + Protected method to get the text of the editor. + + @return text of the editor + @rtype str + """ + if self.__lineEditKind: + return self._editor.text() + else: + return self._editor.currentText() def setText(self, path): """ @@ -188,12 +234,12 @@ @type str """ if self.__mode == E5PathPickerModes.OpenFilesMode: - self.__editor.setText(path) + self._setEditorText(path) else: path = Utilities.toNativeSeparators(path) - self.__editor.setText(path) - if self.__completer: - self.__completer.setRootPath(path) + self._setEditorText(path) + if self._completer: + self._completer.setRootPath(path) def text(self): """ @@ -205,10 +251,28 @@ if self.__mode == E5PathPickerModes.OpenFilesMode: return ";".join( [Utilities.toNativeSeparators(path) - for path in self.__editor.text().split(";")]) + for path in self._editorText().split(";")]) else: return os.path.expanduser( - Utilities.toNativeSeparators(self.__editor.text())) + Utilities.toNativeSeparators(self._editorText())) + + def setEditText(self, path): + """ + Public method to set the current path. + + @param path path to be set + @type str + """ + self.setText(path) + + def currentText(self): + """ + Public method to get the current path. + + @return current path + @rtype str + """ + return self.text() def setPath(self, path): """ @@ -247,10 +311,7 @@ @return first path @rtype str """ - if self.__mode == E5PathPickerModes.OpenFilesMode: - return self.path().split(";")[0] - else: - return self.path() + self.paths()[0] def lastPath(self): """ @@ -259,10 +320,7 @@ @return first path @rtype str """ - if self.__mode == E5PathPickerModes.OpenFilesMode: - return self.path().split(";")[-1] - else: - return self.path() + self.paths()[-1] def setEditorEnabled(self, enable): """ @@ -271,9 +329,9 @@ @param enable flag indicating the enable state @type bool """ - if enable != self.__editorEnabled: - self.__editorEnabled = enable - self.__editor.setEnabled(enable) + if enable != self._editorEnabled: + self._editorEnabled = enable + self._editor.setEnabled(enable) def editorEnabled(self): """ @@ -282,7 +340,7 @@ @return flag indicating the enabled state @rtype bool """ - return self.__editorEnabled + return self._editorEnabled def setDefaultDirectory(self, directory): """ @@ -347,7 +405,8 @@ @param filters list of file name filters @type list of str """ - self.__editor.completer().model().setNameFilters(filters) + if self._completer: + self._completer.model().setNameFilters(filters) def setButtonToolTip(self, tooltip): """ @@ -374,7 +433,7 @@ @param tooltip text to be set as a tool tip @type str """ - self.__editor.setToolTip(tooltip) + self._editor.setToolTip(tooltip) def editorToolTip(self): """ @@ -383,7 +442,7 @@ @return tool tip text @rtype str """ - return self.__editor.toolTip() + return self._editor.toolTip() def __showPathPickerDialog(self): """ @@ -411,7 +470,7 @@ elif self.__mode == E5PathPickerModes.DirectoryMode: windowTitle = self.tr("Choose a directory") - directory = self.__editor.text() + directory = self._editorText() if not directory and self.__defaultDirectory: directory = self.__defaultDirectory if self.__mode == E5PathPickerModes.OpenFilesMode: @@ -471,210 +530,12 @@ path = path[:-1] if path: - self.__editor.setText(path) + self._setEditorText(path) self.pathSelected.emit(path) - - -class E5ComboPathPicker(QWidget): - """ - Class implementing a path picker widget consisting of a combobox and a - tool button to open a file dialog. - - @signal editTextChanged(path) emitted when the entered path has changed - @signal pathSelected(path) emitted after a path has been selected via the - file dialog - @signal aboutToShowPathPickerDialog emitted before the file dialog is shown - @signal pickerButtonClicked emitted when the picker button was pressed and - the widget mode is custom - """ - DefaultMode = E5PathPickerModes.NoMode - - editTextChanged = pyqtSignal(str) - pathSelected = pyqtSignal(str) - aboutToShowPathPickerDialog = pyqtSignal() - pickerButtonClicked = pyqtSignal() - - def __init__(self, parent=None): - """ - Constructor - - @param parent reference to the parent widget - @type QWidget - """ - super(E5ComboPathPicker, self).__init__(parent) - - self.__mode = E5PathPicker.DefaultMode - self.__editorEnabled = True - - self.__filters = "" - self.__defaultDirectory = "" - self.__windowTitle = "" - - self.__layout = QHBoxLayout() - self.__layout.setSpacing(0) - self.__layout.setContentsMargins(0, 0, 0, 0) - self.setLayout(self.__layout) - - self.__editor = E5ClearableComboBox(self, self.tr("Enter Path Name")) - - self.__button = QToolButton(self) - self.__button.setToolButtonStyle(Qt.ToolButtonIconOnly) - self.__button.setIcon(UI.PixmapCache.getIcon("open.png")) - - self.__layout.addWidget(self.__editor) - self.__layout.addWidget(self.__button) - - self.__button.clicked.connect(self.__showPathPickerDialog) - self.__editor.editTextChanged.connect(self.editTextChanged) - - self.setFocusProxy(self.__editor) - self.setFocusPolicy(Qt.StrongFocus) - self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) - - self.__button.setEnabled(self.__mode != E5PathPickerModes.NoMode) - - def setMode(self, mode): - """ - Public method to set the path picker mode. - - @param mode picker mode - @type E5PathPickerModes - """ - assert mode in E5PathPickerModes - - oldMode = self.__mode - self.__mode = mode - - if mode != oldMode: - if mode != E5PathPickerModes.NoMode: - # set inactive text - if mode == E5PathPickerModes.OpenFilesMode: - self.__editor.setInactiveText( - self.tr("Enter Path Names separated by ';'")) - else: - self.__editor.setInactiveText( - self.tr("Enter Path Name")) - self.__button.setEnabled(self.__mode != E5PathPickerModes.NoMode) - - def mode(self): - """ - Public method to get the path picker mode. - - @return path picker mode - @rtype E5PathPickerModes - """ - return self.__mode - def setPickerEnabled(self, enable): - """ - Public method to set the enabled state of the file dialog button. - - @param enable flag indicating the enabled state - @type bool - """ - self.__button.setEnabled(enable) - - def isPickerEnabled(self): - """ - Public method to get the file dialog button enabled state. - - @return flag indicating the enabled state - @rtype bool - """ - return self.__button.isEnabled() - - def clear(self): - """ - Public method to clear the list of paths. - """ - self.__editor.clear() - - def clearEditText(self): - """ - Public method to clear the current path. - """ - self.__editor.clearEditText() - - def setEditText(self, path): - """ - Public method to set the current path. - - @param path path to be set - @type str - """ - if self.__mode == E5PathPickerModes.OpenFilesMode: - self.__editor.setEditText(path) - else: - self.__editor.setEditText(Utilities.toNativeSeparators(path)) - - def currentText(self): - """ - Public method to get the current path. - - @return current path - @rtype str - """ - if self.__mode == E5PathPickerModes.OpenFilesMode: - return ";".join( - [Utilities.toNativeSeparators(path) - for path in self.__editor.currentText().split(";")]) - else: - return os.path.expanduser( - Utilities.toNativeSeparators(self.__editor.currentText())) - - def setPath(self, path): - """ - Public method to set the current path. - - @param path path to be set - @type str - """ - self.setEditText(path) - - def path(self): - """ - Public method to get the current path. - - @return current path - @rtype str - """ - return self.currentText() - - def paths(self): - """ - Public method to get the list of entered paths. - - @return entered paths - @rtype list of str - """ - if self.__mode == E5PathPickerModes.OpenFilesMode: - return self.path().split(";") - else: - return [self.path()] - - def firstPath(self): - """ - Public method to get the first path of a list of entered paths. - - @return first path - @rtype str - """ - if self.__mode == E5PathPickerModes.OpenFilesMode: - return self.path().split(";")[0] - else: - return self.path() - - def lastPath(self): - """ - Public method to get the last path of a list of entered paths. - - @return first path - @rtype str - """ - if self.__mode == E5PathPickerModes.OpenFilesMode: - return self.path().split(";")[-1] - else: - return self.path() + ################################################################## + ## Methods below emulate some of the QComboBox API + ################################################################## def addItems(self, pathsList): """ @@ -683,7 +544,7 @@ @param pathsList list of paths to add @type list of str """ - self.__editor.addItems(pathsList) + self._editor.addItems(pathsList) def addItem(self, path): """ @@ -692,7 +553,7 @@ @param path path to add @type str """ - self.__editor.addItem(path) + self._editor.addItem(path) def setPathsList(self, pathsList): """ @@ -711,119 +572,7 @@ @param index index of the item to set current @type int """ - self.__editor.setCurrentIndex(index) - - def setEditorEnabled(self, enable): - """ - Public method to set the path editor's enabled state. - - @param enable flag indicating the enable state - @type bool - """ - if enable != self.__editorEnabled: - self.__editorEnabled = enable - self.__editor.setEnabled(enable) - - def editorEnabled(self): - """ - Public method to get the path editor's enabled state. - - @return flag indicating the enabled state - @rtype bool - """ - return self.__editorEnabled - - def setDefaultDirectory(self, directory): - """ - Public method to set the default directory. - - @param directory default directory - @type str - """ - self.__defaultDirectory = directory - - def defaultDirectory(self): - """ - Public method to get the default directory. - - @return default directory - @rtype str - """ - return self.__defaultDirectory - - def setWindowTitle(self, title): - """ - Public method to set the path picker dialog window title. - - @param title window title - @type str - """ - self.__windowTitle = title - - def windowTitle(self): - """ - Public method to get the path picker dialog's window title. - - @return window title - @rtype str - """ - return self.__windowTitle - - def setFilters(self, filters): - """ - Public method to set the filters for the path picker dialog. - - Note: Multiple filters must be separated by ';;'. - - @param filters string containing the file filters - @type str - """ - self.__filters = filters - - def filters(self): - """ - Public methods to get the filter string. - - @return filter string - @rtype str - """ - return self.__filters - - def setButtonToolTip(self, tooltip): - """ - Public method to set the tool button tool tip. - - @param tooltip text to be set as a tool tip - @type str - """ - self.__button.setToolTip(tooltip) - - def buttonToolTip(self): - """ - Public method to get the tool button tool tip. - - @return tool tip text - @rtype str - """ - return self.__button.toolTip() - - def setEditorToolTip(self, tooltip): - """ - Public method to set the editor tool tip. - - @param tooltip text to be set as a tool tip - @type str - """ - self.__editor.setToolTip(tooltip) - - def editorToolTip(self): - """ - Public method to get the editor tool tip. - - @return tool tip text - @rtype str - """ - return self.__editor.toolTip() + self._editor.setCurrentIndex(index) def setInsertPolicy(self, policy): """ @@ -832,7 +581,7 @@ @param policy insertion policy @type QComboBox.InsertPolicy """ - self.__editor.setInsertPolicy(policy) + self._editor.setInsertPolicy(policy) def setSizeAdjustPolicy(self, policy): """ @@ -841,91 +590,48 @@ @param policy size adjust policy @type QComboBox.SizeAdjustPolicy """ - self.__editor.setSizeAdjustPolicy(policy) + self._editor.setSizeAdjustPolicy(policy) + + +class E5PathPicker(E5PathPickerBase): + """ + Class implementing a path picker widget consisting of a line edit and a + tool button to open a file dialog. - def __showPathPickerDialog(self): - """ - Private slot to show the path picker dialog. + @signal textChanged(path) emitted when the entered path has changed + @signal pathSelected(path) emitted after a path has been selected via the + file dialog + @signal aboutToShowPathPickerDialog emitted before the file dialog is shown + @signal pickerButtonClicked emitted when the picker button was pressed and + the widget mode is custom + """ + def __init__(self, parent=None): """ - if self.__mode == E5PathPickerModes.NoMode: - return - - if self.__mode == E5PathPickerModes.CustomMode: - self.pickerButtonClicked.emit() - return - - self.aboutToShowPathPickerDialog.emit() - - windowTitle = self.__windowTitle - if not windowTitle: - if self.__mode == E5PathPickerModes.OpenFileMode: - windowTitle = self.tr("Choose a file to open") - elif self.__mode == E5PathPickerModes.OpenFilesMode: - windowTitle = self.tr("Choose files to open") - elif self.__mode == E5PathPickerModes.SaveFileMode: - windowTitle = self.tr("Choose a file to save") - elif self.__mode == E5PathPickerModes.DirectoryMode: - windowTitle = self.tr("Choose a directory") - - directory = self.__editor.currentText() - if not directory and self.__defaultDirectory: - directory = self.__defaultDirectory - if self.__mode == E5PathPickerModes.OpenFilesMode: - directory = os.path.expanduser(directory.split(";")[0]) - else: - directory = os.path.expanduser(directory) - if not os.path.isabs(directory) and self.__defaultDirectory: - directory = os.path.join(self.__defaultDirectory, directory) - directory = Utilities.fromNativeSeparators(directory) + Constructor - if self.__mode == E5PathPickerModes.OpenFileMode: - path = E5FileDialog.getOpenFileName( - self, - windowTitle, - directory, - self.__filters) - path = Utilities.toNativeSeparators(path) - elif self.__mode == E5PathPickerModes.OpenFilesMode: - paths = E5FileDialog.getOpenFileNames( - self, - windowTitle, - directory, - self.__filters) - path = ";".join([Utilities.toNativeSeparators(path) - for path in paths]) - elif self.__mode == E5PathPickerModes.SaveFileMode: - path = E5FileDialog.getSaveFileName( - self, - windowTitle, - directory, - self.__filters, - E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) - path = Utilities.toNativeSeparators(path) - elif self.__mode == E5PathPickerModes.SaveFileEnsureExtensionMode: - path, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( - self, - windowTitle, - directory, - self.__filters, - None, - E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) - path = Utilities.toNativeSeparators(path) - if path: - ext = QFileInfo(path).suffix() - if not ext: - ex = selectedFilter.split("(*")[1].split(")")[0] - if ex: - path += ex - elif self.__mode == E5PathPickerModes.DirectoryMode: - path = E5FileDialog.getExistingDirectory( - self, - windowTitle, - directory, - E5FileDialog.Options(E5FileDialog.ShowDirsOnly)) - path = Utilities.toNativeSeparators(path) - while path.endswith(os.sep): - path = path[:-1] + @param parent reference to the parent widget + @type QWidget + """ + super(E5PathPicker, self).__init__(parent, useLineEdit=True) + + +class E5ComboPathPicker(E5PathPickerBase): + """ + Class implementing a path picker widget consisting of a combobox and a + tool button to open a file dialog. + + @signal editTextChanged(path) emitted when the entered path has changed + @signal pathSelected(path) emitted after a path has been selected via the + file dialog + @signal aboutToShowPathPickerDialog emitted before the file dialog is shown + @signal pickerButtonClicked emitted when the picker button was pressed and + the widget mode is custom + """ + def __init__(self, parent=None): + """ + Constructor - if path: - self.__editor.setEditText(path) - self.pathSelected.emit(path) + @param parent reference to the parent widget + @type QWidget + """ + super(E5ComboPathPicker, self).__init__(parent, useLineEdit=False)