class QStringTable(QTableView): def __init__(self, parent, selection_callback=None): super(QStringTable, self).__init__(parent) self._selected = selection_callback self._filter = None self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setShowGrid(False) self.verticalHeader().setVisible(False) self.verticalHeader().setDefaultSectionSize(24) self.setHorizontalScrollMode(self.ScrollPerPixel) self._model = QStringModel(None) self._proxy = QSortFilterProxyModel(self) self._proxy.setSourceModel(self._model) self._proxy.setFilterCaseSensitivity(Qt.CaseInsensitive) self.setModel(self._proxy) self.setSortingEnabled(True) self.setSelectionMode(QAbstractItemView.SingleSelection) # let the last column (string) fill table width self.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed) self.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch) self.doubleClicked.connect(self._on_string_selected) # # Properties # @property def cfg(self): return self._model.cfg @cfg.setter def cfg(self, v): self._model.cfg = v self.fast_resize() @property def xrefs(self): return self._model.xrefs @xrefs.setter def xrefs(self, v): self._model.xrefs = v @property def function(self): return self._model.function @function.setter def function(self, v): self._model.function = v self.fast_resize() @property def filter_string(self): return self._filter @filter_string.setter def filter_string(self, v): self._filter = v if isinstance(v, re.Pattern): self._proxy.setFilterRegExp(self._filter.pattern) else: self._proxy.setFilterWildcard(self._filter) self._proxy.setFilterKeyColumn(2) # # Public methods # def fast_resize(self): self.setVisible(False) self.resizeColumnsToContents() self.setVisible(True) # # Event handlers # def _on_string_selected(self, model_index): model_index = self._proxy.mapToSource(model_index) selected_index = model_index.row() if self._model is None: return if 0 <= selected_index < len(self._model.values): selected_item = self._model.values[selected_index] else: selected_item = None if self._selected is not None: self._selected(selected_item)
class SmartSyncDialog(object): def __init__(self, parent): self._dialog = QDialog(parent) self._dialog.setWindowIcon(QIcon(':/images/icon.png')) self._ui = Ui_Dialog() self._ui.setupUi(self._dialog) self._ui.centralWidget.setFrameShape(QFrame.NoFrame) self._ui.centralWidget.setLineWidth(1) self._model = None self._proxy_model = QSortFilterProxyModel() self._view = self._ui.folder_list_view self._view.setModel(self._proxy_model) self._view.expanded.connect(self.on_item_expanded) self._offline_paths = None # for frameless window moving self._x_coord = 0 self._y_coord = 0 self._dialog.mousePressEvent = self.on_mouse_press_event self._dialog.mouseMoveEvent = self.on_mouse_move_event self._loader_movie = QMovie(":/images/loader.gif") self._ui.loader_label.setMovie(self._loader_movie) def on_mouse_press_event(self, ev): self._x_coord = ev.x() self._y_coord = ev.y() def on_mouse_move_event(self, ev): self._dialog.move( ev.globalX() - self._x_coord, ev.globalY() - self._y_coord) def on_item_expanded(self, index): if self._model: self._model.on_item_expanded(self._proxy_model.mapToSource(index)) def show(self, root_path, hide_dotted=False): if LOGGING_ENABLED: logger.info( "Opening smart sync dialog for path '%s'...", root_path) self._model = TreeModel( root_path, hide_dotted=hide_dotted) self._proxy_model.setSourceModel(self._model) self.show_cursor_loading(show_movie=True) # Execute dialog result = self._dialog.exec_() if result == QDialog.Accepted: offline_dirs = self._model.get_added_to_offline_paths() new_online = list(self._model.get_removed_from_offline_paths()) new_offline = list(offline_dirs - self._offline_paths) if LOGGING_ENABLED: logger.debug("new offline dirs %s, new online dirs %s", new_offline, new_online) return new_offline, new_online else: return [], [] def set_offline_paths(self, offline_paths): self._offline_paths = offline_paths logger.debug("offline paths %s", offline_paths) self._model.set_offline_dirs(offline_paths) self.show_cursor_normal() self._view.expand(self._proxy_model.mapFromSource( self._model.get_root_path_index())) self._proxy_model.sort(0, Qt.AscendingOrder) def show_cursor_loading(self, show_movie=False): if show_movie: self._ui.stackedWidget.setCurrentIndex(1) self._loader_movie.start() else: self._dialog.setCursor(Qt.WaitCursor) def show_cursor_normal(self): self._dialog.setCursor(Qt.ArrowCursor) if self._loader_movie.state() == QMovie.Running: self._loader_movie.stop() self._ui.stackedWidget.setCurrentIndex(0)