Source code for qudi.util.widgets.path_line_edit

# -*- coding: utf-8 -*-

"""
This file contains a QWidget very similar to QLineEdit that can also open a file dialog to select
directories and files and display them in the QLineEdit.

.. Copyright (c) 2021, the qudi developers. See the AUTHORS.md file at the top-level directory of this
.. distribution and on <https://github.com/Ulm-IQO/qudi-core/>
..
.. This file is part of qudi.
..
.. Qudi is free software: you can redistribute it and/or modify it under the terms of
.. the GNU Lesser General Public License as published by the Free Software Foundation,
.. either version 3 of the License, or (at your option) any later version.
..
.. Qudi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
.. without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.. See the GNU Lesser General Public License for more details.
..
.. You should have received a copy of the GNU Lesser General Public License along with qudi.
.. If not, see <https://www.gnu.org/licenses/>.
"""

__all__ = ['PathLineEdit']

import os
from PySide2 import QtCore, QtWidgets, QtGui
from typing import Optional, Any, List

from qudi.util.paths import get_artwork_dir as _get_artwork_dir


[docs] class PathLineEdit(QtWidgets.QWidget): """QLineEdit for editing file system paths directly or via QFileDialog. No validation is performed on the entered string. Multiple paths are separated by single semicolon, e.g. '<path1>;<path2>;<path3>' Specify multiple filters by separating them with double(!) semicolons, e.g.: Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml) """
[docs] def __init__( self, text: Optional[str] = None, parent: Optional[QtWidgets.QWidget] = None, dialog_caption: Optional[str] = None, root_directory: Optional[str] = None, filters: Optional[str] = None, select_directory: Optional[bool] = False, follow_symlinks: Optional[bool] = False, ) -> None: super().__init__(parent=parent) self._line_edit = QtWidgets.QLineEdit(text) self._tool_button = QtWidgets.QToolButton() self._tool_button.setIcon( QtGui.QIcon( os.path.join(os.path.join(_get_artwork_dir(), 'icons', 'document-open')) ) ) self._tool_button.setToolTip('Open file dialog') self._tool_button.clicked.connect(self._exec_file_dialog) layout = QtWidgets.QHBoxLayout() layout.addWidget(self._line_edit) layout.addWidget(self._tool_button) layout.setStretch(0, 1) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self._filters = '' if filters is None else filters self._select_directory = bool(select_directory) self._follow_symlinks = bool(follow_symlinks) self._root_directory = ( os.path.abspath(os.sep) if root_directory is None else root_directory ) if dialog_caption is None: self._dialog_caption = ( 'Select Directory' if self._select_directory else 'Select Files' ) else: self._dialog_caption = dialog_caption
def __getattr__(self, item: str) -> Any: try: return getattr(self._line_edit, item) except AttributeError: pass raise AttributeError( f"'{self.__class__.__name__}' object has not attribute '{item}'" ) @property def paths(self) -> List[str]: paths = (p.strip() for p in self._line_edit.text().split(';')) return [p for p in paths if p] @QtCore.Slot() def _exec_file_dialog(self) -> None: self._line_edit.clearFocus() dialog = QtWidgets.QFileDialog( parent=self, caption=self._dialog_caption, directory=self._root_directory, filter=self._filters, ) options = QtWidgets.QFileDialog.Option.ReadOnly if not self._follow_symlinks: options |= QtWidgets.QFileDialog.Option.DontResolveSymlinks if self._select_directory: dialog.setFileMode(QtWidgets.QFileDialog.FileMode.Directory) options |= QtWidgets.QFileDialog.Option.ShowDirsOnly else: dialog.setFileMode(QtWidgets.QFileDialog.FileMode.ExistingFiles) dialog.setOptions(options) if dialog.exec_() == QtWidgets.QFileDialog.Accepted: paths = dialog.selectedFiles() if paths: text = ';'.join(p for p in paths if p) if text and text != self._line_edit.text(): self._line_edit.setText(text) self._line_edit.textEdited.emit(text) self._line_edit.editingFinished.emit() dialog.setParent(None) dialog.deleteLater()