def commentaryListView(self): # https://doc.qt.io/archives/qtforpython-5.12/PySide2/QtCore/QStringListModel.html # https://gist.github.com/minoue/9f384cd36339429eb0bf # https://www.pythoncentral.io/pyside-pyqt-tutorial-qlistview-and-qstandarditemmodel/ list = QListView() list.setEditTriggers(QAbstractItemView.NoEditTriggers) model = QStandardItemModel(list) for index, commentary in enumerate(self.parent.commentaryFullNameList): item = QStandardItem(commentary) item.setToolTip(self.parent.commentaryList[index]) #item.setCheckable(True) #item.setCheckState(Qt.CheckState.Checked) #item.setCheckState(Qt.CheckState.Unchecked) #print(item.checkState() is Qt.CheckState.Checked) model.appendRow(item) #model = QStringListModel(self.parent.commentaryList) #model = QStringListModel(self.parent.commentaryFullNameList) list.setModel(model) if config.commentaryText in self.parent.commentaryList: list.setCurrentIndex( model.index( self.parent.commentaryList.index(config.commentaryText), 0)) list.selectionModel().selectionChanged.connect(self.commentarySelected) return list
def setupUI(self): layout = QVBoxLayout() # Add a label layout.addWidget(QLabel(config.thisTranslation["downloadOptions"])) # Add a list view list = QListView() list.setEditTriggers(QAbstractItemView.NoEditTriggers) model = QStringListModel(self.options) list.setModel(model) list.selectionModel().selectionChanged.connect(self.optionSelected) list.setCurrentIndex(model.index(len(self.options) - 1, 0)) layout.addWidget(list) subLayout = QHBoxLayout() # Add a cancel button button = QPushButton(config.thisTranslation["message_cancel"]) button.clicked.connect(self.close) subLayout.addWidget(button) # Add a download button button = QPushButton(config.thisTranslation["download"]) button.clicked.connect( lambda: self.parent.downloadSelectedOption(self.selectedOption)) subLayout.addWidget(button) layout.addLayout(subLayout) # Set layout self.setLayout(layout)
def devotionsListView(self): list = QListView() list.setEditTriggers(QAbstractItemView.NoEditTriggers) model = QStandardItemModel(list) for devotional in self.devotionals: item = QStandardItem(devotional) model.appendRow(item) list.setModel(model) list.selectionModel().selectionChanged.connect(self.devotionalSelected) return list
def videoListView(self): list = QListView() list.setEditTriggers(QAbstractItemView.NoEditTriggers) model = QStandardItemModel(list) for file in self.videoList: item = QStandardItem(file) model.appendRow(item) list.setModel(model) list.selectionModel().selectionChanged.connect(self.playSelectedVideo) return list
def pdfListView(self): list = QListView() list.setEditTriggers(QAbstractItemView.NoEditTriggers) model = QStandardItemModel(list) for pdf in self.pdfList: item = QStandardItem(pdf) model.appendRow(item) list.setModel(model) if config.pdfText in self.parent.pdfList: list.setCurrentIndex( model.index(self.parent.pdfList.index(config.pdfText), 0)) list.selectionModel().selectionChanged.connect(self.pdfSelected) return list
class Switcher(QDialog): """ A multi purpose switcher. Example ------- SwitcherItem: [title description <shortcut> section] SwitcherItem: [title description <shortcut> section] SwitcherSeparator: [---------------------------------------] SwitcherItem: [title description <shortcut> section] SwitcherItem: [title description <shortcut> section] """ # Dismissed switcher sig_rejected = Signal() # Search/Filter text changes sig_text_changed = Signal(TEXT_TYPES[-1]) # Current item changed sig_item_changed = Signal(object) # List item selected, mode and cleaned search text sig_item_selected = Signal(object, TEXT_TYPES[-1], TEXT_TYPES[-1], ) sig_mode_selected = Signal(TEXT_TYPES[-1]) _MAX_NUM_ITEMS = 15 _MIN_WIDTH = 580 _MIN_HEIGHT = 200 _MAX_HEIGHT = 390 _ITEM_WIDTH = _MIN_WIDTH - 20 def __init__(self, parent, help_text=None, item_styles=ITEM_STYLES, item_separator_styles=ITEM_SEPARATOR_STYLES): """Multi purpose switcher.""" super(Switcher, self).__init__(parent) self._modes = {} self._mode_on = '' self._item_styles = item_styles self._item_separator_styles = item_separator_styles # Widgets self.edit = QLineEdit(self) self.list = QListView(self) self.model = QStandardItemModel(self.list) self.proxy = SwitcherProxyModel(self.list) self.filter = KeyPressFilter() # Widgets setup self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint) self.setWindowOpacity(0.95) # self.setMinimumHeight(self._MIN_HEIGHT) self.setMaximumHeight(self._MAX_HEIGHT) self.edit.installEventFilter(self.filter) self.edit.setPlaceholderText(help_text if help_text else '') self.list.setMinimumWidth(self._MIN_WIDTH) self.list.setItemDelegate(SwitcherDelegate(self)) self.list.setFocusPolicy(Qt.NoFocus) self.list.setSelectionBehavior(self.list.SelectItems) self.list.setSelectionMode(self.list.SingleSelection) self.list.setVerticalScrollMode(QAbstractItemView.ScrollPerItem) self.proxy.setSourceModel(self.model) self.list.setModel(self.proxy) # Layout layout = QVBoxLayout() layout.addWidget(self.edit) layout.addWidget(self.list) self.setLayout(layout) # Signals self.filter.sig_up_key_pressed.connect(self.previous_row) self.filter.sig_down_key_pressed.connect(self.next_row) self.filter.sig_enter_key_pressed.connect(self.enter) self.edit.textChanged.connect(self.setup) self.edit.textChanged.connect(self.sig_text_changed) self.edit.returnPressed.connect(self.enter) self.list.clicked.connect(self.enter) self.list.clicked.connect(self.edit.setFocus) self.list.selectionModel().currentChanged.connect( self.current_item_changed) self.edit.setFocus() # --- Helper methods def _add_item(self, item, last_item=True): """Perform common actions when adding items.""" item.set_width(self._ITEM_WIDTH) self.model.appendRow(item) if last_item: # Only set the current row to the first item when the added item is # the last one in order to prevent performance issues when # adding multiple items self.set_current_row(0) self.set_height() self.setup_sections() # --- API def clear(self): """Remove all items from the list and clear the search text.""" self.set_placeholder_text('') self.model.beginResetModel() self.model.clear() self.model.endResetModel() self.setMinimumHeight(self._MIN_HEIGHT) def set_placeholder_text(self, text): """Set the text appearing on the empty line edit.""" self.edit.setPlaceholderText(text) def add_mode(self, token, description): """Add mode by token key and description.""" if len(token) == 1: self._modes[token] = description else: raise Exception('Token must be of length 1!') def get_mode(self): """Get the current mode the switcher is in.""" return self._mode_on def remove_mode(self, token): """Remove mode by token key.""" if token in self._modes: self._modes.pop(token) def clear_modes(self): """Delete all modes spreviously defined.""" del self._modes self._modes = {} def add_item(self, icon=None, title=None, description=None, shortcut=None, section=None, data=None, tool_tip=None, action_item=False, last_item=True): """Add switcher list item.""" item = SwitcherItem( parent=self.list, icon=icon, title=title, description=description, data=data, shortcut=shortcut, section=section, action_item=action_item, tool_tip=tool_tip, styles=self._item_styles ) self._add_item(item, last_item=last_item) def add_separator(self): """Add separator item.""" item = SwitcherSeparatorItem(parent=self.list, styles=self._item_separator_styles) self._add_item(item) def setup(self): """Set-up list widget content based on the filtering.""" # Check exited mode mode = self._mode_on if mode: search_text = self.search_text()[len(mode):] else: search_text = self.search_text() # Check exited mode if self.search_text() == '': self._mode_on = '' self.clear() self.proxy.set_filter_by_score(False) self.sig_mode_selected.emit(self._mode_on) return # Check entered mode for key in self._modes: if self.search_text().startswith(key) and not mode: self._mode_on = key self.sig_mode_selected.emit(key) return # Filter by text titles = [] for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): title = item.get_title() else: title = '' titles.append(title) search_text = clean_string(search_text) scores = get_search_scores(to_text_string(search_text), titles, template=u"<b>{0}</b>") for idx, (title, rich_title, score_value) in enumerate(scores): item = self.model.item(idx) if not self._is_separator(item) and not item.is_action_item(): rich_title = rich_title.replace(" ", " ") item.set_rich_title(rich_title) item.set_score(score_value) self.proxy.set_filter_by_score(True) self.setup_sections() if self.count(): self.set_current_row(0) else: self.set_current_row(-1) self.set_height() def setup_sections(self): """Set-up which sections appear on the item list.""" mode = self._mode_on if mode: search_text = self.search_text()[len(mode):] else: search_text = self.search_text() if search_text: for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): item.set_section_visible(False) else: sections = [] for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): sections.append(item.get_section()) item.set_section_visible(bool(search_text)) else: sections.append('') if row != 0: visible = sections[row] != sections[row - 1] if not self._is_separator(item): item.set_section_visible(visible) else: item.set_section_visible(True) self.proxy.sortBy('_score') self.sig_item_changed.emit(self.current_item()) def set_height(self): """Set height taking into account the number of items.""" if self.count() >= self._MAX_NUM_ITEMS: switcher_height = self._MAX_HEIGHT elif self.count() != 0 and self.current_item(): current_item = self.current_item() item_height = current_item.get_height() list_height = item_height * (self.count() + 3) edit_height = self.edit.height() spacing_height = self.layout().spacing() * 4 switcher_height = list_height + edit_height + spacing_height switcher_height = max(switcher_height, self._MIN_HEIGHT) else: switcher_height = self._MIN_HEIGHT self.setFixedHeight(int(switcher_height)) def set_position(self, top): """Set the position of the dialog.""" parent = self.parent() if parent is not None: geo = parent.geometry() width = self.list.width() # This has been set in setup left = parent.geometry().width()/2 - width/2 while parent: geo = parent.geometry() top += geo.top() left += geo.left() parent = parent.parent() self.move(round(left), top) @Slot(QModelIndex, QModelIndex) def current_item_changed(self, current, previous): """Handle item selection.""" self.sig_item_changed.emit(self.current_item()) # --- Qt overrides # ------------------------------------------------------------------------ @Slot() @Slot(QListWidgetItem) def enter(self, itemClicked=None): """Override Qt method.""" row = self.current_row() model_index = self.proxy.mapToSource(self.proxy.index(row, 0)) item = self.model.item(model_index.row()) if item: mode = self._mode_on self.sig_item_selected.emit(item, mode, self.search_text()[len(mode):]) def accept(self): """Override Qt method.""" super(Switcher, self).accept() def reject(self): """Override Qt method.""" self.set_search_text('') self.sig_rejected.emit() super(Switcher, self).reject() def resizeEvent(self, event): """Override Qt method.""" super(Switcher, self).resizeEvent(event) # --- Helper methods: Lineedit widget def search_text(self): """Get the normalized (lowecase) content of the search text.""" return to_text_string(self.edit.text()).lower() def set_search_text(self, string): """Set the content of the search text.""" self.edit.setText(string) # --- Helper methods: List widget def _is_separator(self, item): """Check if item is an separator item (SwitcherSeparatorItem).""" return isinstance(item, SwitcherSeparatorItem) def _select_row(self, steps): """Select row in list widget based on a number of steps with direction. Steps can be positive (next rows) or negative (previous rows). """ row = self.current_row() + steps if 0 <= row < self.count(): self.set_current_row(row) def count(self): """Get the item count in the list widget.""" return self.proxy.rowCount() def current_row(self): """Return the current selected row in the list widget.""" return self.list.currentIndex().row() def current_item(self): """Return the current selected item in the list widget.""" row = self.current_row() model_index = self.proxy.mapToSource(self.proxy.index(row, 0)) item = self.model.item(model_index.row()) return item def set_current_row(self, row): """Set the current selected row in the list widget.""" proxy_index = self.proxy.index(row, 0) selection_model = self.list.selectionModel() # https://doc.qt.io/qt-5/qitemselectionmodel.html#SelectionFlag-enum selection_model.setCurrentIndex( proxy_index, selection_model.ClearAndSelect) # Ensure that the selected item is visible self.list.scrollTo(proxy_index, QAbstractItemView.EnsureVisible) def previous_row(self): """Select previous row in list widget.""" steps = 1 prev_row = self.current_row() - steps if prev_row == -1: self.set_current_row(self.count() - 1) else: if prev_row >= 0: # Need to map the filtered list to the actual model items list_index = self.proxy.index(prev_row, 0) model_index = self.proxy.mapToSource(list_index) item = self.model.item(model_index.row(), 0) if self._is_separator(item): steps += 1 self._select_row(-steps) def next_row(self): """Select next row in list widget.""" steps = 1 next_row = self.current_row() + steps # Need to map the filtered list to the actual model items list_index = self.proxy.index(next_row, 0) model_index = self.proxy.mapToSource(list_index) item = self.model.item(model_index.row(), 0) if next_row >= self.count(): self.set_current_row(0) else: if item: if self._is_separator(item): steps += 1 self._select_row(steps)
class DataTypeKeysWidget(QWidget): dataTypeKeySelected = Signal() def __init__(self, model): QWidget.__init__(self) self.__filter_popup = FilterPopup(self) self.__filter_popup.filterSettingsChanged.connect(self.onItemChanged) layout = QVBoxLayout() self.model = model self.filter_model = DataTypeProxyModel(self.model) filter_layout = QHBoxLayout() self.search_box = SearchBox() self.search_box.filterChanged.connect(self.setSearchString) filter_layout.addWidget(self.search_box) filter_popup_button = QToolButton() filter_popup_button.setIcon(resourceIcon("ide/cog_edit.png")) filter_popup_button.clicked.connect(self.showFilterPopup) filter_layout.addWidget(filter_popup_button) layout.addLayout(filter_layout) self.data_type_keys_widget = QListView() self.data_type_keys_widget.setModel(self.filter_model) self.data_type_keys_widget.selectionModel().selectionChanged.connect( self.itemSelected) layout.addSpacing(15) layout.addWidget(self.data_type_keys_widget, 2) layout.addStretch() # layout.addWidget(Legend("Default types", DataTypeKeysListModel.DEFAULT_DATA_TYPE)) layout.addWidget( Legend("Observations available", DataTypeKeysListModel.HAS_OBSERVATIONS)) self.setLayout(layout) def onItemChanged(self, item): # self.filter_model.setShowBlockKeys(item["block"]) self.filter_model.setShowSummaryKeys(item["summary"]) self.filter_model.setShowGenKWKeys(item["gen_kw"]) self.filter_model.setShowGenDataKeys(item["gen_data"]) self.filter_model.setShowCustomKwKeys(item["custom_kw"]) # self.filter_model.setShowCustomPcaKeys(item["custom_pca"]) def itemSelected(self): selected_item = self.getSelectedItem() if selected_item is not None: self.dataTypeKeySelected.emit() def getSelectedItem(self): """ @rtype: str """ index = self.data_type_keys_widget.currentIndex() source_index = self.filter_model.mapToSource(index) item = self.model.itemAt(source_index) return item def selectDefault(self): self.data_type_keys_widget.setCurrentIndex( self.filter_model.index(0, 0)) def setSearchString(self, filter): self.filter_model.setFilterFixedString(filter) def showFilterPopup(self): self.__filter_popup.show()
class ConfigDialog(QDialog): def __init__(self): super(ConfigDialog, self).__init__() # Set size and position self.setGeometry(0, 0, 900, 550) frameGm = self.frameGeometry() screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos()) centerPoint = QApplication.desktop().screenGeometry(screen).center() frameGm.moveCenter(centerPoint) self.move(frameGm.topLeft()) self.contentsWidget = QListView() self.contentsWidget.setViewMode(QListView.IconMode) # self.contentsWidget.setIconSize(QSize(96, 84)) self.contentsWidget.setMovement(QListView.Static) self.contentsWidget.setMaximumWidth(174) self.contentsWidget.setSpacing(12) self.contentsWidget.setSelectionMode(QAbstractItemView.SingleSelection) self.contentsModel = QStandardItemModel() self.contentsWidget.setModel(self.contentsModel) self.contentsWidget.selectionModel().currentChanged.connect(self.changePage) self.buttonboxWidget = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Apply# | QDialogButtonBox.Help ) self.buttonboxWidget.button(QDialogButtonBox.Ok).clicked.connect(self.ok) self.buttonboxWidget.button(QDialogButtonBox.Apply).clicked.connect(self.apply) self.buttonboxWidget.button(QDialogButtonBox.Cancel).clicked.connect(self.close) self.pagesWidget = QStackedWidget() horizontalLayout = QHBoxLayout() horizontalLayout.addWidget(self.contentsWidget) horizontalLayout.addWidget(self.pagesWidget, 1) mainLayout = QVBoxLayout() mainLayout.addLayout(horizontalLayout) # mainLayout.addStretch(1) mainLayout.addSpacing(12) mainLayout.addWidget(self.buttonboxWidget) self.setLayout(mainLayout) self.setWindowTitle("Config Dialog") # Set modality self.setModal(True) self.lastwidget = None self.createIcons() self.restore() pluginmanager.attach(self.pluginsChanged) def createIcons(self): self.contentsModel.clear() for pluginInfo in pluginmanager.getPluginsOfCategory("SettingsPlugin"): item = QStandardItem(pluginInfo.plugin_object.icon, pluginInfo.plugin_object.name()) item.widget = pluginInfo.plugin_object.widget item.setTextAlignment(Qt.AlignHCenter) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) item.setSizeHint(QSize(136, 80)) self.contentsModel.appendRow(item) def show(self): if self.lastwidget: self.pagesWidget.addWidget(self.lastwidget) self.pagesWidget.setCurrentWidget(self.lastwidget) self.restore() super(ConfigDialog, self).show() def changePage(self, current, previous): if not current: current = previous current = self.contentsModel.itemFromIndex(current) self.pagesWidget.addWidget(current.widget) self.pagesWidget.setCurrentWidget(current.widget) self.lastwidget = current.widget def pluginsChanged(self): self.createIcons() def restore(self): for pluginInfo in pluginmanager.getPluginsOfCategory("SettingsPlugin"): pluginInfo.plugin_object.restore() self.apply() def ok(self): self._empty() self.apply() self.accept() def apply(self): for pluginInfo in pluginmanager.getPluginsOfCategory("SettingsPlugin"): pluginInfo.plugin_object.save() def close(self): self._empty() self.restore() self.reject() def _empty(self): """ Disown all widget children (otherwise their c++ objects are force deleted when the dialog closes). Must be run in reverse to avoid index update errors """ for i in reversed(range(self.pagesWidget.count())): self.pagesWidget.widget(i).setParent(None) def closeEvent(self, event): self.close() event.accept() def keyPressEvent(self, e: QKeyEvent): if e.key() != Qt.Key_Escape: super(ConfigDialog, self).keyPressEvent(e) else: self.close()
class HistoryLauncher(QWidget): def __init__(self, parent): super().__init__() # set title self.setWindowTitle(config.thisTranslation["menu_history"]) # set up variables self.parent = parent self.startup = True # setup interface self.setupUI() def setupUI(self): mainLayout = QHBoxLayout() leftColumnWidget = QGroupBox(config.thisTranslation["mainWindow"]) layout = QVBoxLayout() layout.addWidget(self.createMainListView()) button = QPushButton(config.thisTranslation["open"]) button.clicked.connect(lambda: self.openLastRecord("main")) layout.addWidget(button) leftColumnWidget.setLayout(layout) middleColumnWidget = QGroupBox(config.thisTranslation["studyWindow"]) layout = QVBoxLayout() layout.addWidget(self.createStudyListView()) button = QPushButton(config.thisTranslation["open"]) button.clicked.connect(lambda: self.openLastRecord("study")) layout.addWidget(button) middleColumnWidget.setLayout(layout) rightColumnWidget = QGroupBox( config.thisTranslation["menu_external_notes"]) layout = QVBoxLayout() layout.addWidget(self.createExternalListView()) subLayout = QHBoxLayout() button = QPushButton(config.thisTranslation["open"]) button.clicked.connect(lambda: self.externalFileAction(False)) subLayout.addWidget(button) button = QPushButton(config.thisTranslation["edit"]) button.clicked.connect(lambda: self.externalFileAction(True)) subLayout.addWidget(button) layout.addLayout(subLayout) rightColumnWidget.setLayout(layout) mainLayout.addWidget(leftColumnWidget) mainLayout.addWidget(middleColumnWidget) mainLayout.addWidget(rightColumnWidget) self.setLayout(mainLayout) def createMainListView(self): # Main and study history records are editable, so users can slightly modify a command and execute a new one. self.mainListView = QListView() self.mainModel = QStringListModel() self.mainListView.setModel(self.mainModel) self.mainListView.selectionModel().selectionChanged.connect( lambda selection: self.historyAction(selection, "main")) return self.mainListView def createStudyListView(self): #studyItems = list(reversed(config.history["study"])) # Main and study history records are editable, so users can slightly modify a command and execute a new one. self.studyListView = QListView() self.studyModel = QStringListModel() self.studyListView.setModel(self.studyModel) self.studyListView.selectionModel().selectionChanged.connect( lambda selection: self.historyAction(selection, "study")) return self.studyListView def createExternalListView(self): self.externalListView = QListView() # Only external file history record is not editable self.externalListView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.externalModel = QStringListModel() self.externalListView.setModel(self.externalModel) self.externalListView.selectionModel().selectionChanged.connect( lambda selection: self.historyAction(selection, "external")) return self.externalListView def filterExternalFileRecords(self): # Hide those which do not exist on the current platform # This may be useful when users use the same config.py across different platforms files = list(reversed(config.history["external"])) return [file for file in files if os.path.isfile(file)] def refresh(self): mainItems = list(reversed(config.history["main"])) studyItems = list(reversed(config.history["study"])) externalItems = self.filterExternalFileRecords() self.mainModel.setStringList(mainItems) self.studyModel.setStringList(studyItems) self.externalModel.setStringList(externalItems) self.setSelection(mainItems, studyItems, externalItems) def setSelection(self, mainItems, studyItems, externalItems): if mainItems: self.mainListView.setCurrentIndex(self.mainModel.index(0, 0)) if studyItems: self.studyListView.setCurrentIndex(self.studyModel.index(0, 0)) if externalItems: self.externalListView.setCurrentIndex( self.externalModel.index(0, 0)) def openLastRecord(self, key): selectedItem = config.history[key][-1] self.openSelectedItem(selectedItem, key) def externalFileAction(self, edit): command = "{0}:::-1".format("_editfile" if edit else "_openfile") self.parent.runTextCommand(command) def historyAction(self, selection, key): if not self.parent.isRefreshing: selectedItem = selection[0].indexes()[0].data() self.openSelectedItem(selectedItem, key) def openSelectedItem(self, selectedItem, key): if key == "external": command = "OPENNOTE:::{0}".format(selectedItem) self.parent.runTextCommand(command) else: self.parent.runTextCommand(selectedItem)
class DataTypeKeysWidget(QWidget): dataTypeKeySelected = Signal() def __init__(self, key_defs): QWidget.__init__(self) self.__filter_popup = FilterPopup(self, key_defs) self.__filter_popup.filterSettingsChanged.connect(self.onItemChanged) layout = QVBoxLayout() self.model = DataTypeKeysListModel(key_defs) self.filter_model = DataTypeProxyModel(self, self.model) filter_layout = QHBoxLayout() self.search_box = SearchBox() self.search_box.filterChanged.connect(self.setSearchString) filter_layout.addWidget(self.search_box) filter_popup_button = QToolButton() filter_popup_button.setIcon(resourceIcon("filter_list.svg")) filter_popup_button.clicked.connect(self.showFilterPopup) filter_layout.addWidget(filter_popup_button) layout.addLayout(filter_layout) self.data_type_keys_widget = QListView() self.data_type_keys_widget.setModel(self.filter_model) self.data_type_keys_widget.selectionModel().selectionChanged.connect( self.itemSelected) layout.addSpacing(15) layout.addWidget(self.data_type_keys_widget, 2) layout.addStretch() layout.addWidget( Legend("Observations available", DataTypeKeysListModel.HAS_OBSERVATIONS)) self.setLayout(layout) def onItemChanged(self, item): # self.filter_model.setShowBlockKeys(item["block"]) for value, visible in item.items(): self.filter_model.setFilterOnMetadata("data_origin", value, visible) def itemSelected(self): selected_item = self.getSelectedItem() if selected_item is not None: self.dataTypeKeySelected.emit() def getSelectedItem(self): """@rtype: str""" index = self.data_type_keys_widget.currentIndex() source_index = self.filter_model.mapToSource(index) item = self.model.itemAt(source_index) return item def selectDefault(self): self.data_type_keys_widget.setCurrentIndex( self.filter_model.index(0, 0)) def setSearchString(self, filter): self.filter_model.setFilterFixedString(filter) def showFilterPopup(self): self.__filter_popup.show()
class LibraryLauncher(QWidget): def __init__(self, parent): super().__init__() # set title self.setWindowTitle(config.thisTranslation["menu_library"]) # set up variables self.parent = parent # setup interface self.setupUI() self.selectedBook = None def setupUI(self): mainLayout = QGridLayout() leftColumnWidget = QGroupBox(config.thisTranslation["commentaries"]) commentaryLayout = QVBoxLayout() commentaryLayout.addWidget(self.commentaryListView()) subSubLayout = QHBoxLayout() button = QPushButton(config.thisTranslation["open"]) button.clicked.connect(self.openPreviousCommentary) subSubLayout.addWidget(button) button = QPushButton(config.thisTranslation["activeOnly"]) button.clicked.connect(self.showActiveOnlyCommentaries) subSubLayout.addWidget(button) commentaryLayout.addLayout(subSubLayout) leftColumnWidget.setLayout(commentaryLayout) rightColumnWidget = QGroupBox(config.thisTranslation["menu10_books"]) bookLayout = QHBoxLayout() subLayout = QVBoxLayout() subLayout.addWidget(self.bookListView()) subSubLayout = QHBoxLayout() button = QPushButton(config.thisTranslation["showAll"]) button.clicked.connect(self.showAllBooks) subSubLayout.addWidget(button) button = QPushButton(config.thisTranslation["favouriteOnly"]) button.clicked.connect(self.favouriteBookOnly) subSubLayout.addWidget(button) button = QPushButton(config.thisTranslation["addFavourite"]) button.clicked.connect(self.addFavorite) subSubLayout.addWidget(button) button = QPushButton(config.thisTranslation["removeFavourite"]) button.clicked.connect(self.removeFavorite) subSubLayout.addWidget(button) subLayout.addLayout(subSubLayout) bookLayout.addLayout(subLayout) subLayout = QVBoxLayout() subLayout.addWidget(self.chapterListView()) button = QPushButton(config.thisTranslation["open"]) button.clicked.connect(self.openPreviousBookChapter) subLayout.addWidget(button) bookLayout.addLayout(subLayout) rightColumnWidget.setLayout(bookLayout) mainLayout.addWidget(leftColumnWidget, 0, 0) mainLayout.addWidget(rightColumnWidget, 0, 1) mainLayout.setColumnStretch(1, 2) self.setLayout(mainLayout) def testChecked(self, test): print(test) def commentaryListView(self): # https://doc.qt.io/archives/qtforpython-5.12/PySide2/QtCore/QStringListModel.html # https://gist.github.com/minoue/9f384cd36339429eb0bf # https://www.pythoncentral.io/pyside-pyqt-tutorial-qlistview-and-qstandarditemmodel/ self.commentaryListView = QListView() self.commentaryListView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.reloadCommentariesListModel() return self.commentaryListView def reloadCommentariesListModel(self, showOnlyActiveCommentaries=False): self.commentaryList = [] activeCommentaries = [] if showOnlyActiveCommentaries: activeCommentaries = [item[1] for item in Commentary().getCommentaryListThatHasBookAndChapter(config.mainB, config.mainC)] for index, commentary in enumerate(self.parent.commentaryFullNameList): if not showOnlyActiveCommentaries or commentary in activeCommentaries: # item = QStandardItem(commentary) # item.setToolTip(self.parent.commentaryList[index]) self.commentaryList.append(commentary) model = QStringListModel(self.commentaryList) self.commentaryListView.setModel(model) if config.commentaryText in self.commentaryList: self.commentaryListView.setCurrentIndex(model.index(self.commentaryList.index(config.commentaryText), 0)) self.commentaryListView.selectionModel().selectionChanged.connect(self.commentarySelected) def bookListView(self): self.bookList = QListView() self.bookList.setEditTriggers(QAbstractItemView.NoEditTriggers) self.reloadBookListModel() return self.bookList def reloadBookListModel(self, files=None): self.dirsAndFiles = self.getSubdirectories() if files is None: self.dirsAndFiles += BookData().getBooks() else: books = BookData().getBooks() for file in files: if file in books: self.dirsAndFiles.append(file) self.bookModel = QStringListModel(self.dirsAndFiles) self.bookList.setModel(self.bookModel) if config.book in self.dirsAndFiles: self.bookList.setCurrentIndex(self.bookModel.index(self.dirsAndFiles.index(config.book), 0)) self.bookList.selectionModel().selectionChanged.connect(self.bookOrFileSelected) def getSubdirectories(self): return ["../"] + BookData().getDirectories() def chapterListView(self): self.chapterlist = QListView() self.chapterlist.setEditTriggers(QAbstractItemView.NoEditTriggers) topicList = self.getBookTopicList() self.chapterModel = QStringListModel(topicList) self.chapterlist.setModel(self.chapterModel) self.scrollChapterList(topicList) self.chapterlist.selectionModel().selectionChanged.connect(self.chapterSelected) return self.chapterlist def getBookTopicList(self): return Book(config.book).getTopicList() def scrollChapterList(self, topicList): self.chapterlist.setCurrentIndex(self.chapterModel.index(topicList.index(config.bookChapter) if topicList and config.bookChapter in topicList else 0, 0)) def openPreviousCommentary(self): command = "COMMENTARY:::{0}:::{1}".format(config.commentaryText, self.parent.bibleTab.getSelectedReference()) self.parent.runTextCommand(command) def openPreviousBookChapter(self): if config.bookChapter == "": config.bookChapter = self.getBookTopicList()[0] command = "BOOK:::{0}:::{1}".format(config.book, config.bookChapter) self.parent.runTextCommand(command) def commentarySelected(self, selection): index = selection[0].indexes()[0].row() reverseLookup = {v: k for k, v in Commentary.fileLookup.items()} config.commentaryText = reverseLookup[self.commentaryList[index]] command = "COMMENTARY:::{0}:::{1}".format(config.commentaryText, self.parent.bibleTab.getSelectedReference()) self.parent.runTextCommand(command) def showActiveOnlyCommentaries(self): self.reloadCommentariesListModel(True) def showAllBooks(self): self.reloadBookListModel() def favouriteBookOnly(self): self.reloadBookListModel(sorted(config.favouriteBooks)) def bookOrFileSelected(self, selection): self.parent.isRefreshing = True self.selectedBook = selection[0].indexes()[0].data() if config.book != self.selectedBook: if self.selectedBook.endswith("/"): config.booksFolder = FileUtil.normalizePath(os.path.join(config.booksFolder, self.selectedBook)) self.reloadBookListModel() else: config.book = self.selectedBook topicList = self.getBookTopicList() self.chapterModel.setStringList(topicList) config.bookChapter = topicList[0] if topicList else "" self.scrollChapterList(topicList) command = "SEARCHBOOK:::{0}:::".format(config.book) self.parent.commandField.setText(command) def addFavorite(self): if self.selectedBook and self.selectedBook not in config.favouriteBooks: config.favouriteBooks.append(self.selectedBook) self.reloadBookListModel(sorted(config.favouriteBooks)) def removeFavorite(self): if self.selectedBook and self.selectedBook in config.favouriteBooks: config.favouriteBooks.remove(self.selectedBook) self.reloadBookListModel(sorted(config.favouriteBooks)) def chapterSelected(self, selection): config.bookSearchString = '' config.bookChapter = selection[0].indexes()[0].data() if self.selectedBook: config.book = self.selectedBook command = "BOOK:::{0}:::{1}".format(config.book, config.bookChapter) if not self.parent.isRefreshing: self.parent.runTextCommand(command) self.parent.isRefreshing = False
class Switcher(QDialog): """ A multi purpose switcher. Example ------- SwitcherItem: [title description <shortcut> section] SwitcherItem: [title description <shortcut> section] SwitcherSeparator: [---------------------------------------] SwitcherItem: [title description <shortcut> section] SwitcherItem: [title description <shortcut> section] """ # Search/Filter text changes sig_text_changed = Signal(TEXT_TYPES[-1]) # List item selected, mode and cleaned search text sig_item_selected = Signal( object, TEXT_TYPES[-1], TEXT_TYPES[-1], ) sig_mode_selected = Signal(TEXT_TYPES[-1]) _MIN_WIDTH = 500 def __init__(self, parent, help_text=None, item_styles=ITEM_STYLES, item_separator_styles=ITEM_SEPARATOR_STYLES): """Multi purpose switcher.""" super(Switcher, self).__init__(parent) self._visible_rows = 0 self._modes = {} self._mode_on = '' self._item_styles = item_styles self._item_separator_styles = item_separator_styles # Widgets self.edit = QLineEdit(self) self.list = QListView(self) self.model = QStandardItemModel(self.list) self.proxy = SwitcherProxyModel(self.list) self.filter = KeyPressFilter() # Widgets setup # self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint) self.setWindowOpacity(0.95) self.edit.installEventFilter(self.filter) self.edit.setPlaceholderText(help_text if help_text else '') self.list.setMinimumWidth(self._MIN_WIDTH) self.list.setItemDelegate(HTMLDelegate(self)) self.list.setFocusPolicy(Qt.NoFocus) self.list.setSelectionBehavior(self.list.SelectRows) self.list.setSelectionMode(self.list.SingleSelection) self.proxy.setSourceModel(self.model) self.list.setModel(self.proxy) # Layout layout = QVBoxLayout() layout.addWidget(self.edit) layout.addWidget(self.list) self.setLayout(layout) # Signals self.filter.sig_up_key_pressed.connect(self.previous_row) self.filter.sig_down_key_pressed.connect(self.next_row) self.filter.sig_enter_key_pressed.connect(self.enter) self.edit.textChanged.connect(self.setup) self.edit.textChanged.connect(self.sig_text_changed) self.edit.returnPressed.connect(self.enter) self.list.clicked.connect(self.enter) self.list.clicked.connect(self.edit.setFocus) # --- Helper methods def _add_item(self, item): """Perform common actions when adding items.""" item.set_width(self._MIN_WIDTH) self.model.appendRow(item) self.set_current_row(0) self._visible_rows = self.model.rowCount() self.setup_sections() # --- API def clear(self): """Remove all items from the list and clear the search text.""" self.set_placeholder_text('') self.model.beginResetModel() self.model.clear() self.model.endResetModel() def set_placeholder_text(self, text): """Set the text appearing on the empty line edit.""" self.edit.setPlaceholderText(text) def add_mode(self, token, description): """Add mode by token key and description.""" if len(token) == 1: self._modes[token] = description else: raise Exception('Token must be of length 1!') def remove_mode(self, token): """Remove mode by token key.""" if token in self._modes: self._modes.pop(token) def clear_modes(self): """Delete all modes spreviously defined.""" del self._modes self._modes = {} def add_item(self, icon=None, title=None, description=None, shortcut=None, section=None, data=None, tool_tip=None, action_item=False): """Add switcher list item.""" item = SwitcherItem(parent=self.list, icon=icon, title=title, description=description, data=data, shortcut=shortcut, section=section, action_item=action_item, tool_tip=tool_tip, styles=self._item_styles) self._add_item(item) def add_separator(self): """Add separator item.""" item = SwitcherSeparatorItem(parent=self.list, styles=self._item_separator_styles) self._add_item(item) def setup(self): """Set-up list widget content based on the filtering.""" # Check exited mode mode = self._mode_on if mode: search_text = self.search_text()[len(mode):] else: search_text = self.search_text() # Check exited mode if mode and self.search_text() == '': self._mode_on = '' self.sig_mode_selected.emit(self._mode_on) return # Check entered mode for key in self._modes: if self.search_text().startswith(key) and not mode: self._mode_on = key self.sig_mode_selected.emit(key) return # Filter by text titles = [] for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): title = item.get_title() else: title = '' titles.append(title) search_text = clean_string(search_text) scores = get_search_scores(to_text_string(search_text), titles, template=u"<b>{0}</b>") self._visible_rows = self.model.rowCount() for idx, score in enumerate(scores): title, rich_title, score_value = score item = self.model.item(idx) if not self._is_separator(item): item.set_rich_title(rich_title) item.set_score(score_value) proxy_index = self.proxy.mapFromSource(self.model.index(idx, 0)) if not item.is_action_item(): self.list.setRowHidden(proxy_index.row(), score_value == -1) if score_value == -1: self._visible_rows -= 1 if self._visible_rows: self.set_current_row(0) else: self.set_current_row(-1) self.setup_sections() def setup_sections(self): """Set-up which sections appear on the item list.""" mode = self._mode_on if mode: search_text = self.search_text()[len(mode):] else: search_text = self.search_text() if search_text: for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): item.set_section_visible(False) else: sections = [] for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): sections.append(item.get_section()) item.set_section_visible(bool(search_text)) else: sections.append('') if row != 0: visible = sections[row] != sections[row - 1] if not self._is_separator(item): item.set_section_visible(visible) else: item.set_section_visible(True) self.proxy.sortBy('_score') # --- Qt overrides # ------------------------------------------------------------------------ @Slot() @Slot(QListWidgetItem) def enter(self, itemClicked=None): """Override Qt method.""" row = self.current_row() model_index = self.proxy.mapToSource(self.proxy.index(row, 0)) item = self.model.item(model_index.row()) if item: mode = self._mode_on self.sig_item_selected.emit(item, mode, self.search_text()[len(mode):]) def accept(self): """Override Qt method.""" super(Switcher, self).accept() def resizeEvent(self, event): """Override Qt method.""" super(Switcher, self).resizeEvent(event) # --- Helper methods: Lineedit widget def search_text(self): """Get the normalized (lowecase) content of the search text.""" return to_text_string(self.edit.text()).lower() def set_search_text(self, string): """Set the content of the search text.""" self.edit.setText(string) # --- Helper methods: List widget def _is_separator(self, item): """Check if item is an separator item (SwitcherSeparatorItem).""" return isinstance(item, SwitcherSeparatorItem) def _select_row(self, steps): """Select row in list widget based on a number of steps with direction. Steps can be positive (next rows) or negative (previous rows). """ row = self.current_row() + steps if 0 <= row < self.count(): self.set_current_row(row) def count(self): """Get the item count in the list widget.""" return self._visible_rows def current_row(self): """Return the current selected row in the list widget.""" return self.list.currentIndex().row() def set_current_row(self, row): """Set the current selected row in the list widget.""" index = self.model.index(row, 0) selection_model = self.list.selectionModel() # https://doc.qt.io/qt-5/qitemselectionmodel.html#SelectionFlag-enum selection_model.setCurrentIndex(index, selection_model.ClearAndSelect) def previous_row(self): """Select previous row in list widget.""" steps = 1 prev_row = self.current_row() - steps if prev_row == -1: self.set_current_row(self.count() - 1) else: if prev_row >= 0: # Need to map the filtered list to the actual model items list_index = self.proxy.index(prev_row, 0) model_index = self.proxy.mapToSource(list_index) item = self.model.item(model_index.row(), 0) if self._is_separator(item): steps += 1 self._select_row(-steps) def next_row(self): """Select next row in list widget.""" steps = 1 next_row = self.current_row() + steps # Need to map the filtered list to the actual model items list_index = self.proxy.index(next_row, 0) model_index = self.proxy.mapToSource(list_index) item = self.model.item(model_index.row(), 0) if next_row >= self.count(): self.set_current_row(0) else: if item: if self._is_separator(item): steps += 1 self._select_row(steps)
class LibraryLauncher(QWidget): def __init__(self, parent): super().__init__() # set title self.setWindowTitle(config.thisTranslation["menu_library"]) # set up variables self.parent = parent # setup interface self.setupUI() def setupUI(self): mainLayout = QGridLayout() leftColumnWidget = QGroupBox(config.thisTranslation["commentaries"]) commentaryLayout = QVBoxLayout() commentaryLayout.addWidget(self.commentaryListView()) button = QPushButton(config.thisTranslation["open"]) button.clicked.connect(self.openPreviousCommentary) commentaryLayout.addWidget(button) leftColumnWidget.setLayout(commentaryLayout) rightColumnWidget = QGroupBox(config.thisTranslation["menu10_books"]) bookLayout = QHBoxLayout() subLayout = QVBoxLayout() subLayout.addWidget(self.bookListView()) subSubLayout = QHBoxLayout() button = QPushButton(config.thisTranslation["showAll"]) button.clicked.connect(self.showAllBooks) subSubLayout.addWidget(button) button = QPushButton(config.thisTranslation["favouriteOnly"]) button.clicked.connect(self.fvouriteBookOnly) subSubLayout.addWidget(button) button = QPushButton(config.thisTranslation["addFavourite"]) button.clicked.connect(self.parent.parent.addFavouriteBookDialog) subSubLayout.addWidget(button) subLayout.addLayout(subSubLayout) bookLayout.addLayout(subLayout) subLayout = QVBoxLayout() subLayout.addWidget(self.chapterListView()) button = QPushButton(config.thisTranslation["open"]) button.clicked.connect(self.openPreviousBookChapter) subLayout.addWidget(button) bookLayout.addLayout(subLayout) rightColumnWidget.setLayout(bookLayout) mainLayout.addWidget(leftColumnWidget, 0, 0) mainLayout.addWidget(rightColumnWidget, 0, 1) mainLayout.setColumnStretch(1, 2) self.setLayout(mainLayout) def testChecked(self, test): print(test) def commentaryListView(self): # https://doc.qt.io/archives/qtforpython-5.12/PySide2/QtCore/QStringListModel.html # https://gist.github.com/minoue/9f384cd36339429eb0bf # https://www.pythoncentral.io/pyside-pyqt-tutorial-qlistview-and-qstandarditemmodel/ list = QListView() list.setEditTriggers(QAbstractItemView.NoEditTriggers) model = QStandardItemModel(list) for index, commentary in enumerate(self.parent.commentaryFullNameList): item = QStandardItem(commentary) item.setToolTip(self.parent.commentaryList[index]) #item.setCheckable(True) #item.setCheckState(Qt.CheckState.Checked) #item.setCheckState(Qt.CheckState.Unchecked) #print(item.checkState() is Qt.CheckState.Checked) model.appendRow(item) #model = QStringListModel(self.parent.commentaryList) #model = QStringListModel(self.parent.commentaryFullNameList) list.setModel(model) if config.commentaryText in self.parent.commentaryList: list.setCurrentIndex( model.index( self.parent.commentaryList.index(config.commentaryText), 0)) list.selectionModel().selectionChanged.connect(self.commentarySelected) return list def bookListView(self): self.bookList = QListView() self.bookList.setEditTriggers(QAbstractItemView.NoEditTriggers) self.bookModel = QStringListModel(self.parent.referenceBookList) self.bookList.setModel(self.bookModel) if config.book in self.parent.referenceBookList: self.bookList.setCurrentIndex( self.bookModel.index( self.parent.referenceBookList.index(config.book), 0)) self.bookList.selectionModel().selectionChanged.connect( self.bookSelected) return self.bookList def chapterListView(self): self.chapterlist = QListView() self.chapterlist.setEditTriggers(QAbstractItemView.NoEditTriggers) topicList = self.getBookTopicList() self.chapterModel = QStringListModel(topicList) self.chapterlist.setModel(self.chapterModel) self.scrollChapterList(topicList) self.chapterlist.selectionModel().selectionChanged.connect( self.chapterSelected) return self.chapterlist def getBookTopicList(self): return Book(config.book).getTopicList( ) if config.book in self.parent.referenceBookList else [] def scrollChapterList(self, topicList): self.chapterlist.setCurrentIndex( self.chapterModel.index( topicList.index(config.bookChapter) if topicList and config.bookChapter in topicList else 0, 0)) def openPreviousCommentary(self): command = "COMMENTARY:::{0}:::{1}".format( config.commentaryText, self.parent.bibleTab.getSelectedReference()) self.parent.runTextCommand(command) def openPreviousBookChapter(self): command = "BOOK:::{0}:::{1}".format(config.book, config.bookChapter) self.parent.runTextCommand(command) def commentarySelected(self, selection): #config.commentaryText = selection[0].indexes()[0].data() index = selection[0].indexes()[0].row() config.commentaryText = self.parent.commentaryList[index] command = "COMMENTARY:::{0}:::{1}".format( config.commentaryText, self.parent.bibleTab.getSelectedReference()) self.parent.runTextCommand(command) def showAllBooks(self): self.bookModel.setStringList(self.parent.referenceBookList) self.bookList.setCurrentIndex(self.bookModel.index(0, 0)) def fvouriteBookOnly(self): self.bookModel.setStringList(config.favouriteBooks) self.bookList.setCurrentIndex(self.bookModel.index(0, 0)) def bookSelected(self, selection): self.parent.isRefreshing = True selectedBook = selection[0].indexes()[0].data() if config.book != selectedBook: config.book = selectedBook topicList = self.getBookTopicList() self.chapterModel.setStringList(topicList) config.bookChapter = topicList[0] if topicList else "" self.scrollChapterList(topicList) def chapterSelected(self, selection): config.bookChapter = selection[0].indexes()[0].data() command = "BOOK:::{0}:::{1}".format(config.book, config.bookChapter) if not self.parent.isRefreshing: self.parent.runTextCommand(command) self.parent.isRefreshing = False
class ProgressView(QWidget): """ :type batch_manager: CalculationManager """ def __init__(self, parent, batch_manager): super().__init__(parent) self.task_count = 0 self.calculation_manager = batch_manager self.whole_progress = QProgressBar(self) self.whole_progress.setMinimum(0) self.whole_progress.setMaximum(1) self.whole_progress.setFormat("%v of %m") self.whole_progress.setTextVisible(True) self.part_progress = QProgressBar(self) self.part_progress.setMinimum(0) self.part_progress.setMaximum(1) self.part_progress.setFormat("%v of %m") self.whole_label = QLabel("All batch progress:", self) self.part_label = QLabel("Single batch progress:", self) self.cancel_remove_btn = QPushButton("Remove task") self.cancel_remove_btn.setDisabled(True) self.logs = ExceptionList(self) self.logs.setToolTip("Logs") self.task_view = QListView() self.task_que = QStandardItemModel(self) self.task_view.setModel(self.task_que) self.process_num_timer = QTimer() self.process_num_timer.setInterval(1000) self.process_num_timer.setSingleShot(True) self.process_num_timer.timeout.connect(self.change_number_of_workers) self.number_of_process = QSpinBox(self) self.number_of_process.setRange(1, multiprocessing.cpu_count()) self.number_of_process.setValue(1) self.number_of_process.setToolTip( "Number of process used in batch calculation") self.number_of_process.valueChanged.connect( self.process_num_timer_start) self.progress_item_dict = {} layout = QGridLayout() layout.addWidget(self.whole_label, 0, 0, Qt.AlignRight) layout.addWidget(self.whole_progress, 0, 1, 1, 2) layout.addWidget(self.part_label, 1, 0, Qt.AlignRight) layout.addWidget(self.part_progress, 1, 1, 1, 2) lab = QLabel("Number of process:") lab.setToolTip("Number of process used in batch calculation") layout.addWidget(lab, 2, 0) layout.addWidget(self.number_of_process, 2, 1) layout.addWidget(self.logs, 3, 0, 2, 3) layout.addWidget(self.task_view, 0, 4, 4, 1) layout.addWidget(self.cancel_remove_btn, 4, 4, 1, 1) layout.setColumnMinimumWidth(2, 10) layout.setColumnStretch(2, 1) self.setLayout(layout) self.preview_timer = QTimer() self.preview_timer.setInterval(1000) self.preview_timer.timeout.connect(self.update_info) self.task_view.selectionModel().currentChanged.connect( self.task_selection_change) self.cancel_remove_btn.clicked.connect(self.task_cancel_remove) def task_selection_change(self, new, old): task: CalculationProcessItem = self.task_que.item( new.row(), new.column()) if task is None: self.cancel_remove_btn.setDisabled(True) return self.cancel_remove_btn.setEnabled(True) if task.is_finished(): self.cancel_remove_btn.setText(f"Remove task {task.num}") else: self.cancel_remove_btn.setText(f"Cancel task {task.num}") def task_cancel_remove(self): index = self.task_view.selectionModel().currentIndex() task: CalculationProcessItem = self.task_que.item( index.row(), index.column()) if task.is_finished(): self.calculation_manager.remove_calculation(task.calculation) self.task_que.takeRow(index.row()) else: self.calculation_manager.cancel_calculation(task.calculation) print(task) def new_task(self): self.whole_progress.setMaximum( self.calculation_manager.calculation_size) if not self.preview_timer.isActive(): self.update_info() self.preview_timer.start() def update_info(self): res = self.calculation_manager.get_results() for el in res.errors: if el[0]: QListWidgetItem(el[0], self.logs) ExceptionListItem(el[1], self.logs) if (state_store.report_errors and parsed_version.is_devrelease and not isinstance(el[1][0], SegmentationLimitException) and isinstance(el[1][1], tuple)): with sentry_sdk.push_scope() as scope: scope.set_tag("auto_report", "true") sentry_sdk.capture_event(el[1][1][0]) self.whole_progress.setValue(res.global_counter) working_search = True for uuid, progress in res.jobs_status.items(): calculation = self.calculation_manager.calculation_dict[uuid] total = len(calculation.file_list) if uuid in self.progress_item_dict: item = self.progress_item_dict[uuid] item.update_count(progress) else: item = CalculationProcessItem(calculation, self.task_count, progress) self.task_count += 1 self.task_que.appendRow(item) self.progress_item_dict[uuid] = item if working_search and progress != total: self.part_progress.setMaximum(total) self.part_progress.setValue(progress) working_search = False if not self.calculation_manager.has_work: self.part_progress.setValue(self.part_progress.maximum()) self.preview_timer.stop() logging.info("Progress stop") def process_num_timer_start(self): self.process_num_timer.start() def update_progress(self, total_progress, part_progress): self.whole_progress.setValue(total_progress) self.part_progress.setValue(part_progress) def set_total_size(self, size): self.whole_progress.setMaximum(size) def set_part_size(self, size): self.part_progress.setMaximum(size) def change_number_of_workers(self): self.calculation_manager.set_number_of_workers( self.number_of_process.value())