class FileWidget(QWidget): on_open = pyqtSignal(str) # TODO consider removing directory_aliases since it is not used any more def __init__(self, dialog_title='', dialog_format='', start_dir=os.path.expanduser('~/'), icon_size=(12, 20), minimal_width=200, browse_label='Browse', on_open=None, reload_button=True, reload_label='Reload', recent_files=None, directory_aliases=None, allow_empty=True, empty_file_label='(none)'): """ Creates a widget with a button for file loading and an optional combo box for recent files and reload buttons. Args: dialog_title (str): The title of the dialog. dialog_format (str): Formats for the dialog. start_dir (str): A directory to start from. icon_size (int, int): The size of buttons' icons. on_open (callable): A callback function that accepts filepath as the only argument. reload_button (bool): Whether to show reload button. reload_label (str): The text displayed on the reload button. recent_files (List[str]): List of recent files. directory_aliases (dict): An {alias: dir} dictionary for fast directories' access. allow_empty (bool): Whether empty path is allowed. """ super().__init__() self.dialog_title = dialog_title self.dialog_format = dialog_format self.start_dir = start_dir # Recent files should also contain `empty_file_label` so # when (none) is selected this is stored in settings. self.recent_files = recent_files if recent_files is not None else [] self.directory_aliases = directory_aliases or {} self.allow_empty = allow_empty self.empty_file_label = empty_file_label if self.empty_file_label not in self.recent_files \ and (self.allow_empty or not self.recent_files): self.recent_files.append(self.empty_file_label) self.check_existence() self.on_open.connect(on_open) layout = QHBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) if recent_files is not None: self.file_combo = QComboBox() self.file_combo.setMinimumWidth(minimal_width) self.file_combo.activated[int].connect(self.select) self.update_combo() layout.addWidget(self.file_combo) self.browse_button = QPushButton(browse_label) self.browse_button.setFocusPolicy(Qt.NoFocus) self.browse_button.clicked.connect(self.browse) self.browse_button.setIcon(self.style().standardIcon( QStyle.SP_DirOpenIcon)) self.browse_button.setIconSize(QSize(*icon_size)) self.browse_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) layout.addWidget(self.browse_button) if reload_button: self.reload_button = QPushButton(reload_label) self.reload_button.setFocusPolicy(Qt.NoFocus) self.reload_button.clicked.connect(self.reload) self.reload_button.setIcon(self.style().standardIcon( QStyle.SP_BrowserReload)) self.reload_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.reload_button.setIconSize(QSize(*icon_size)) layout.addWidget(self.reload_button) def browse(self, start_dir=None): start_dir = start_dir or self.start_dir path, _ = QFileDialog().getOpenFileName(self, self.dialog_title, start_dir, self.dialog_format) if path and self.recent_files is not None: if path in self.recent_files: self.recent_files.remove(path) self.recent_files.insert(0, path) self.update_combo() if path: self.open_file(path) def select(self, n): name = self.file_combo.currentText() if name == self.empty_file_label: del self.recent_files[n] self.recent_files.insert(0, self.empty_file_label) self.update_combo() self.open_file(self.empty_file_label) elif name in self.directory_aliases: self.browse(self.directory_aliases[name]) elif n < len(self.recent_files): name = self.recent_files[n] del self.recent_files[n] self.recent_files.insert(0, name) self.update_combo() self.open_file(self.recent_files[0]) def update_combo(self): """ Sync combo values to the changes in self.recent_files. """ if self.recent_files is not None: self.file_combo.clear() for i, file in enumerate(self.recent_files): # remove (none) when we have some files and allow_empty=False if file == self.empty_file_label and \ not self.allow_empty and len(self.recent_files) > 1: del self.recent_files[i] else: self.file_combo.addItem(os.path.split(file)[1]) for alias in self.directory_aliases.keys(): self.file_combo.addItem(alias) def reload(self): if self.recent_files: self.select(0) def check_existence(self): if self.recent_files: to_remove = [] for file in self.recent_files: doc_path = os.path.join(get_sample_corpora_dir(), file) exists = any(os.path.exists(f) for f in [file, doc_path]) if file != self.empty_file_label and not exists: to_remove.append(file) for file in to_remove: self.recent_files.remove(file) def open_file(self, path): self.on_open.emit(path if path != self.empty_file_label else '') def get_selected_filename(self): if self.recent_files: return self.recent_files[0] else: return self.empty_file_label
class ControlButton(ControlBase): def __init__(self, *args, **kwargs): self._checkable = kwargs.get('checkable', False) super(ControlButton, self).__init__(*args, **kwargs) default = kwargs.get('default', None) if default: self.value = default def init_form(self): self._form = QPushButton() self._form.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self._form.setCheckable(self._checkable) self.label = self._label self._form.setToolTip(self.help) def click(self): self._form.click() def load_form(self, data, path=None): pass def save_form(self, data, path=None): pass ########################################################################## @property def label(self): return ControlBase.label.fget(self) @label.setter def label(self, value): ControlBase.label.fset(self, value) self._form.setText(self._label) @property def icon(self): return self._form.icon() @icon.setter def icon(self, value): if isinstance(value, (str, bytes)): self._form.setIcon(QIcon(value)) else: self._form.setIcon(value) ########################################################################## @property def value(self): return None @value.setter def value(self, value): try: self._form.clicked.disconnect() # ignore previous signals if any except TypeError as err: # http://stackoverflow.com/questions/21586643/pyqt-widget-connect-and-disconnect pass self._form.clicked[bool].connect(value) @property def checked(self): return self._form.isChecked() @checked.setter def checked(self, value): self._form.setChecked(value)
class FileLoader(QWidget): activated = pyqtSignal() file_loaded = pyqtSignal() def __init__(self): super().__init__() self.recent_paths = [] self.file_combo = QComboBox() self.file_combo.setMinimumWidth(80) self.file_combo.activated.connect(self._activate) self.browse_btn = QPushButton("...") icon = self.style().standardIcon(QStyle.SP_DirOpenIcon) self.browse_btn.setIcon(icon) self.browse_btn.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) self.browse_btn.clicked.connect(self.browse) self.load_btn = QPushButton("") icon = self.style().standardIcon(QStyle.SP_BrowserReload) self.load_btn.setIcon(icon) self.load_btn.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) self.load_btn.setAutoDefault(True) self.load_btn.clicked.connect(self.file_loaded) def browse(self): start_file = self.last_path() or os.path.expanduser("~/") formats = ["Text files (*.txt)", "All files (*)"] file_name, _ = QFileDialog.getOpenFileName(None, "Open...", start_file, ";;".join(formats), formats[0]) if not file_name: return self.add_path(file_name) self._activate() def _activate(self): self.activated.emit() self.file_loaded.emit() def set_current_file(self, path: str): if path: self.add_path(path) self.file_combo.setCurrentText(path) else: self.file_combo.setCurrentText("(none)") def get_current_file(self) -> Optional[RecentPath]: index = self.file_combo.currentIndex() if index >= len(self.recent_paths) or index < 0: return None path = self.recent_paths[index] return path if isinstance(path, RecentPath) else None def add_path(self, filename: str): recent = RecentPath.create(filename, []) if recent in self.recent_paths: self.recent_paths.remove(recent) self.recent_paths.insert(0, recent) self.set_file_list() def set_file_list(self): self.file_combo.clear() for i, recent in enumerate(self.recent_paths): self.file_combo.addItem(recent.basename) self.file_combo.model().item(i).setToolTip(recent.abspath) if not os.path.exists(recent.abspath): self.file_combo.setItemData(i, QBrush(Qt.red), Qt.TextColorRole) self.file_combo.addItem(_DEFAULT_NONE) def last_path(self) -> Optional[str]: return self.recent_paths[0].abspath if self.recent_paths else None
class FileWidget(QWidget): on_open = pyqtSignal(str) def __init__(self, dialog_title='', dialog_format='', start_dir=os.path.expanduser('~/'), icon_size=(12, 20), minimal_width=200, browse_label='Browse', on_open=None, reload_button=True, reload_label='Reload', recent_files=None, directory_aliases=None, allow_empty=True, empty_file_label='(none)'): """ Creates a widget with a button for file loading and an optional combo box for recent files and reload buttons. Args: dialog_title (str): The title of the dialog. dialog_format (str): Formats for the dialog. start_dir (str): A directory to start from. icon_size (int, int): The size of buttons' icons. on_open (callable): A callback function that accepts filepath as the only argument. reload_button (bool): Whether to show reload button. reload_label (str): The text displayed on the reload button. recent_files (List[str]): List of recent files. directory_aliases (dict): An {alias: dir} dictionary for fast directories' access. allow_empty (bool): Whether empty path is allowed. """ super().__init__() self.dialog_title = dialog_title self.dialog_format = dialog_format self.start_dir = start_dir self.recent_files = recent_files self.directory_aliases = directory_aliases or {} self.check_existence() self.on_open.connect(on_open) self.allow_empty = allow_empty self.empty_file_label = empty_file_label layout = QHBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) if recent_files is not None: self.file_combo = QComboBox() self.file_combo.setMinimumWidth(minimal_width) self.file_combo.activated[int].connect(self.select) self.update_combo() layout.addWidget(self.file_combo) self.browse_button = QPushButton(browse_label) self.browse_button.setFocusPolicy(Qt.NoFocus) self.browse_button.clicked.connect(self.browse) self.browse_button.setIcon(self.style().standardIcon( QStyle.SP_DirOpenIcon)) self.browse_button.setIconSize(QSize(*icon_size)) self.browse_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) layout.addWidget(self.browse_button) if reload_button: self.reload_button = QPushButton(reload_label) self.reload_button.setFocusPolicy(Qt.NoFocus) self.reload_button.clicked.connect(self.reload) self.reload_button.setIcon(self.style().standardIcon( QStyle.SP_BrowserReload)) self.reload_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.reload_button.setIconSize(QSize(*icon_size)) layout.addWidget(self.reload_button) def browse(self, start_dir=None): start_dir = start_dir or self.start_dir path, _ = QFileDialog().getOpenFileName(self, self.dialog_title, start_dir, self.dialog_format) if path and self.recent_files is not None: if path in self.recent_files: self.recent_files.remove(path) self.recent_files.insert(0, path) self.update_combo() self.open_file(path) def select(self, n): name = self.file_combo.currentText() if n < len(self.recent_files): name = self.recent_files[n] del self.recent_files[n] self.recent_files.insert(0, name) self.open_file(self.recent_files[0]) self.update_combo() elif name == self.empty_file_label: self.open_file(self.empty_file_label) elif name in self.directory_aliases: self.browse(self.directory_aliases[name]) def update_combo(self): if self.recent_files is not None: self.file_combo.clear() for file in self.recent_files: self.file_combo.addItem(os.path.split(file)[1]) if self.allow_empty or not self.recent_files: self.file_combo.addItem(self.empty_file_label) for alias in self.directory_aliases.keys(): self.file_combo.addItem(alias) def reload(self): if self.recent_files: self.select(0) def check_existence(self): if self.recent_files: to_remove = [ file for file in self.recent_files if not os.path.exists(file) ] for file in to_remove: self.recent_files.remove(file) def open_file(self, path): try: self.on_open.emit(path if path != self.empty_file_label else '') except (OSError, IOError): self.loading_error_signal.emit('Could not open "{}".'.format(path))
class FileWidget(QWidget): on_open = pyqtSignal(str) def __init__(self, dialog_title='', dialog_format='', start_dir=os.path.expanduser('~/'), icon_size=(12, 20), minimal_width=200, browse_label='Browse', on_open=None, reload_button=True, reload_label='Reload', recent_files=None, directory_aliases=None, allow_empty=True, empty_file_label='(none)'): """ Creates a widget with a button for file loading and an optional combo box for recent files and reload buttons. Args: dialog_title (str): The title of the dialog. dialog_format (str): Formats for the dialog. start_dir (str): A directory to start from. icon_size (int, int): The size of buttons' icons. on_open (callable): A callback function that accepts filepath as the only argument. reload_button (bool): Whether to show reload button. reload_label (str): The text displayed on the reload button. recent_files (List[str]): List of recent files. directory_aliases (dict): An {alias: dir} dictionary for fast directories' access. allow_empty (bool): Whether empty path is allowed. """ super().__init__() self.dialog_title = dialog_title self.dialog_format = dialog_format self.start_dir = start_dir self.recent_files = recent_files self.directory_aliases = directory_aliases or {} self.check_existence() self.on_open.connect(on_open) self.allow_empty = allow_empty self.empty_file_label = empty_file_label layout = QHBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) if recent_files is not None: self.file_combo = QComboBox() self.file_combo.setMinimumWidth(minimal_width) self.file_combo.activated[int].connect(self.select) self.update_combo() layout.addWidget(self.file_combo) self.browse_button = QPushButton(browse_label) self.browse_button.setFocusPolicy(Qt.NoFocus) self.browse_button.clicked.connect(self.browse) self.browse_button.setIcon(self.style() .standardIcon(QStyle.SP_DirOpenIcon)) self.browse_button.setIconSize(QSize(*icon_size)) self.browse_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) layout.addWidget(self.browse_button) if reload_button: self.reload_button = QPushButton(reload_label) self.reload_button.setFocusPolicy(Qt.NoFocus) self.reload_button.clicked.connect(self.reload) self.reload_button.setIcon(self.style() .standardIcon(QStyle.SP_BrowserReload)) self.reload_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.reload_button.setIconSize(QSize(*icon_size)) layout.addWidget(self.reload_button) def browse(self, start_dir=None): start_dir = start_dir or self.start_dir path, _ = QFileDialog().getOpenFileName(self, self.dialog_title, start_dir, self.dialog_format) if path and self.recent_files is not None: if path in self.recent_files: self.recent_files.remove(path) self.recent_files.insert(0, path) self.update_combo() self.open_file(path) def select(self, n): name = self.file_combo.currentText() if n < len(self.recent_files): name = self.recent_files[n] del self.recent_files[n] self.recent_files.insert(0, name) self.open_file(self.recent_files[0]) self.update_combo() elif name == self.empty_file_label: self.open_file(self.empty_file_label) elif name in self.directory_aliases: self.browse(self.directory_aliases[name]) def update_combo(self): if self.recent_files is not None: self.file_combo.clear() for file in self.recent_files: self.file_combo.addItem(os.path.split(file)[1]) if self.allow_empty or not self.recent_files: self.file_combo.addItem(self.empty_file_label) for alias in self.directory_aliases.keys(): self.file_combo.addItem(alias) def reload(self): if self.recent_files: self.select(0) def check_existence(self): if self.recent_files: to_remove = [ file for file in self.recent_files if not os.path.exists(file) ] for file in to_remove: self.recent_files.remove(file) def open_file(self, path): try: self.on_open.emit(path if path != self.empty_file_label else '') except (OSError, IOError): self.loading_error_signal.emit('Could not open "{}".' .format(path))
class FileWidget(QWidget): on_open = pyqtSignal(str) # TODO consider removing directory_aliases since it is not used any more def __init__(self, dialog_title='', dialog_format='', start_dir=os.path.expanduser('~/'), icon_size=(12, 20), minimal_width=200, browse_label='Browse', on_open=None, reload_button=True, reload_label='Reload', recent_files=None, directory_aliases=None, allow_empty=True, empty_file_label='(none)'): """ Creates a widget with a button for file loading and an optional combo box for recent files and reload buttons. Args: dialog_title (str): The title of the dialog. dialog_format (str): Formats for the dialog. start_dir (str): A directory to start from. icon_size (int, int): The size of buttons' icons. on_open (callable): A callback function that accepts filepath as the only argument. reload_button (bool): Whether to show reload button. reload_label (str): The text displayed on the reload button. recent_files (List[str]): List of recent files. directory_aliases (dict): An {alias: dir} dictionary for fast directories' access. allow_empty (bool): Whether empty path is allowed. """ super().__init__() self.dialog_title = dialog_title self.dialog_format = dialog_format self.start_dir = start_dir # Recent files should also contain `empty_file_label` so # when (none) is selected this is stored in settings. self.recent_files = recent_files if recent_files is not None else [] self.directory_aliases = directory_aliases or {} self.allow_empty = allow_empty self.empty_file_label = empty_file_label if self.empty_file_label not in self.recent_files \ and (self.allow_empty or not self.recent_files): self.recent_files.append(self.empty_file_label) self.check_existence() self.on_open.connect(on_open) layout = QHBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) if recent_files is not None: self.file_combo = QComboBox() self.file_combo.setMinimumWidth(minimal_width) self.file_combo.activated[int].connect(self.select) self.update_combo() layout.addWidget(self.file_combo) self.browse_button = QPushButton(browse_label) self.browse_button.setFocusPolicy(Qt.NoFocus) self.browse_button.clicked.connect(self.browse) self.browse_button.setIcon(self.style() .standardIcon(QStyle.SP_DirOpenIcon)) self.browse_button.setIconSize(QSize(*icon_size)) self.browse_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) layout.addWidget(self.browse_button) if reload_button: self.reload_button = QPushButton(reload_label) self.reload_button.setFocusPolicy(Qt.NoFocus) self.reload_button.clicked.connect(self.reload) self.reload_button.setIcon(self.style() .standardIcon(QStyle.SP_BrowserReload)) self.reload_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.reload_button.setIconSize(QSize(*icon_size)) layout.addWidget(self.reload_button) def browse(self, start_dir=None): start_dir = start_dir or self.start_dir path, _ = QFileDialog().getOpenFileName(self, self.dialog_title, start_dir, self.dialog_format) if path and self.recent_files is not None: if path in self.recent_files: self.recent_files.remove(path) self.recent_files.insert(0, path) self.update_combo() if path: self.open_file(path) def select(self, n): name = self.file_combo.currentText() if name == self.empty_file_label: del self.recent_files[n] self.recent_files.insert(0, self.empty_file_label) self.update_combo() self.open_file(self.empty_file_label) elif name in self.directory_aliases: self.browse(self.directory_aliases[name]) elif n < len(self.recent_files): name = self.recent_files[n] del self.recent_files[n] self.recent_files.insert(0, name) self.update_combo() self.open_file(self.recent_files[0]) def update_combo(self): """ Sync combo values to the changes in self.recent_files. """ if self.recent_files is not None: self.file_combo.clear() for i, file in enumerate(self.recent_files): # remove (none) when we have some files and allow_empty=False if file == self.empty_file_label and \ not self.allow_empty and len(self.recent_files) > 1: del self.recent_files[i] else: self.file_combo.addItem(os.path.split(file)[1]) for alias in self.directory_aliases.keys(): self.file_combo.addItem(alias) def reload(self): if self.recent_files: self.select(0) def check_existence(self): if self.recent_files: to_remove = [] for file in self.recent_files: doc_path = os.path.join(get_sample_corpora_dir(), file) exists = any(os.path.exists(f) for f in [file, doc_path]) if file != self.empty_file_label and not exists: to_remove.append(file) for file in to_remove: self.recent_files.remove(file) def open_file(self, path): self.on_open.emit(path if path != self.empty_file_label else '') def get_selected_filename(self): if self.recent_files: return self.recent_files[0] else: return self.empty_file_label