class JoinChannelDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.app = QApplication.instance() self.chans = ChatChannels() self.ui = ui_chatchannelslist.Ui_ChannelsListDialog() self.ui.setupUi(self) self.ui.joinButton.clicked.connect(self.onJoinClicked) self.ui.cancelButton.clicked.connect(functools.partial(self.done, 1)) self.channelsModel = QStandardItemModel() self.channelsModel.setHorizontalHeaderLabels(['Channel', 'Connected']) self.channelsProxyModel = QSortFilterProxyModel(self) self.channelsProxyModel.setSourceModel(self.channelsModel) self.channelsProxyModel.setFilterKeyColumn(0) self.channelsProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.ui.channelsView.setModel(self.channelsProxyModel) self.ui.channelsView.doubleClicked.connect( lambda idx: self.onJoinClicked()) self.ui.channelsView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.ui.searchLine.textChanged.connect(self.onApplySearch) @ipfsOp async def initDialog(self, ipfsop): dagChannels = ipfsop.ctx.currentProfile.dagChatChannels for channel in dagChannels.channels: self.channelsModel.appendRow([ UneditableItem(channel), UneditableItem(str(await self.chans.cnCountByChannel(channel))) ]) await ipfsop.sleep() def onApplySearch(self): self.channelsProxyModel.setFilterRegExp(self.ui.searchLine.text()) def onJoinClicked(self): try: idx = self.ui.channelsView.selectionModel().selectedRows(0).pop() except Exception: return chan = self.channelsProxyModel.data(idx, Qt.DisplayRole) if chan: ensure(self.onJoinChannel(chan)) self.done(1) @ipfsOp async def onJoinChannel(self, ipfsop, channel): log.info(f'Joining channel: {channel}') widget = await self.chans.joinChannel(channel) self.app.mainWindow.registerTab(widget, name=channel, icon=getIcon('chat.png'), current=True, workspace=WS_PEERS)
class PostSelectionWidget(QDialog): def __init__(self, app, parent=None): super(PostSelectionWidget, self).__init__(parent=parent) self.app = app self.model = PostsListModel(app) self.filtermodel = QSortFilterProxyModel() self.filtermodel.setSourceModel(self.model) self.resize(450, 250) self.layout = QVBoxLayout() self.setLayout(self.layout) view = QListView(self) self.completer = QCompleter(parent=self) self.completer.setCompletionMode(QCompleter.InlineCompletion) self.completer.setCompletionColumn(0) self.completer.setCompletionRole(Qt.DisplayRole) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel) self.completer.setModel(self.model) self._edit = QLineEdit('') self._edit.setCompleter(self.completer) self._edit.textEdited.connect(self.setfilter) self.layout.addWidget(self._edit) self.layout.addWidget(view) view.setModel(self.filtermodel) view.clicked.connect(self.select) view.doubleClicked.connect(self.select_and_edit) self._button = QPushButton('Edit') self._button.clicked.connect(self.edit) self.layout.addWidget(self._button) def setfilter(self, text): regexp = QRegExp("%s*" % text, Qt.CaseInsensitive, QRegExp.Wildcard) self.filtermodel.setFilterRegExp(regexp) def select(self, index): text = self.filtermodel.data(index) self._edit.setText(text) def select_and_edit(self, index): text = self.filtermodel.data(index) self._edit.setText(text) self.app.edit_post(text) def edit(self): self.app.edit_post(self._edit.text())
class JoinChannelDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.app = QApplication.instance() self.chans = ChatChannels() self.ui = ui_chatchannelslist.Ui_ChannelsListDialog() self.ui.setupUi(self) self.ui.joinButton.clicked.connect(self.onJoinClicked) self.ui.cancelButton.clicked.connect(functools.partial(self.done, 1)) self.channelsModel = UneditableStringListModel(self) self.channelsProxyModel = QSortFilterProxyModel(self) self.channelsProxyModel.setSourceModel(self.channelsModel) self.ui.channelsView.setModel(self.channelsProxyModel) self.ui.channelsView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.ui.searchLine.textChanged.connect(self.onApplySearch) @ipfsOp async def initDialog(self, ipfsop): dagChannels = ipfsop.ctx.currentProfile.dagChatChannels self.channelsModel.setStringList(dagChannels.channels) def onApplySearch(self): self.channelsProxyModel.setFilterRegExp(self.ui.searchLine.text()) def onJoinClicked(self): idx = self.ui.channelsView.currentIndex() chan = self.channelsProxyModel.data(idx, Qt.DisplayRole) if chan: ensure(self.onJoinChannel(chan)) self.done(1) @ipfsOp async def onJoinChannel(self, ipfsop, channel): log.info(f'Joining channel: {channel}') widget = await self.chans.joinChannel(channel) self.app.mainWindow.registerTab(widget, name=channel, icon=getIcon('qta:mdi.chat-outline'), current=True)
def data(self, index, role=Qt.DisplayRole): """ Public method to get data from the model. @param index index of history entry to get data for (QModelIndex) @param role data role (integer) @return history entry data """ # If the model is valid, tell QCompleter that everything we have # filtered matches what the user typed; if not, nothing matches if role == self.HistoryCompletionRole and index.isValid(): if self.isValid(): return "t" else: return "f" if role == Qt.DisplayRole: if index.column() == 0: role = HistoryModel.UrlStringRole else: role = HistoryModel.TitleRole return QSortFilterProxyModel.data(self, index, role)
def data(self, index, role=Qt.DisplayRole): """ Public method to get data from the model. @param index index of history entry to get data for (QModelIndex) @param role data role (integer) @return history entry data """ # If the model is valid, tell QCompleter that everything we have # filtered matches what the user typed; if not, nothing matches if role == self.HistoryCompletionRole and index.isValid(): if self.isValid(): return "t" else: return "f" if role == Qt.DisplayRole: if index.column() == 0: role = HistoryModel.UrlStringRole else: role = HistoryModel.TitleRole return QSortFilterProxyModel.data(self, index, role)
class ResourceBrowser(QDialog, Ui_ResourceBrowser): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) self.icon = None self.extensions = (".svg", ".png", ".jpg", ".gif", ".jpeg", ".bmp", ".ico") self.resource_model = RessourceModel(self.extensions, self) self.proxy_model = QSortFilterProxyModel() self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive) self.proxy_model.setSourceModel(self.resource_model) self.view.setModel(self.proxy_model) self.view.setContextMenuPolicy(Qt.CustomContextMenu) self.view.customContextMenuRequested.connect(self.on_context_menu) self.filterLineEdit.textChanged.connect( self.proxy_model.setFilterRegExp) self.view.clicked.connect(self.on_click) self.view.doubleClicked.connect(self.on_double_click) self.splitter.setStretchFactor(0, 0) self.splitter.setStretchFactor(1, 1) self.default_item = None self.ressourceTree.setColumnCount(2) self.build_resource_tree(self.ressourceTree.invisibleRootItem(), "") self.ressourceTree.setColumnHidden(1, True) self.ressourceTree.currentItemChanged.connect( self.on_ressource_changed) self.ressourceTree.expandItem(self.default_item) self.ressourceTree.setCurrentItem(self.default_item) def build_resource_tree(self, parent_item, parent_key): for key in QResource(parent_key).children(): full_key = f"{parent_key}/{key}" if QResource(full_key).isDir(): item = QTreeWidgetItem([key, full_key]) self.build_resource_tree(item, full_key) parent_item.addChild(item) if full_key == "/images/themes/default": self.default_item = item def on_ressource_changed(self, current_item, previous_item): self.resource_model.set_source(current_item.data(1, Qt.DisplayRole)) def set_icon(self, url): self.previewLabel.setPixmap(QIcon(url).pixmap(QSize(64, 64))) self.previewName.setText(url) self.icon = url self.okButton.setEnabled(True) def on_click(self, index): url = self.proxy_model.data(index, Qt.EditRole) self.set_icon(url) def on_double_click(self, index): self.on_click(index) self.accept() def on_context_menu(self, point): index = self.view.indexAt(point) if index.isValid(): menu = QMenu() menu.addAction( QIcon(":/images/themes/default/mActionEditCopy.svg"), self.tr("Copy resource path to clipboard"), ) menu.exec(self.view.mapToGlobal(point)) QGuiApplication.clipboard().setText( self.proxy_model.data(index, Qt.EditRole))
class MasternodesWidget(QWidget): """Widget that displays masternodes.""" def __init__(self, manager, parent=None): super(MasternodesWidget, self).__init__(parent) self.manager = manager self.model = MasternodesModel(self.manager) self.proxy_model = QSortFilterProxyModel() self.proxy_model.setSourceModel(self.model) self.view = QTableView() self.view.setModel(self.proxy_model) for header in [self.view.horizontalHeader(), self.view.verticalHeader()]: header.setHighlightSections(False) header = self.view.horizontalHeader() header.setSectionResizeMode(MasternodesModel.ALIAS, QHeaderView.ResizeToContents) header.setSectionResizeMode(MasternodesModel.VIN, QHeaderView.Stretch) header.setSectionResizeMode(MasternodesModel.COLLATERAL, QHeaderView.ResizeToContents) header.setSectionResizeMode(MasternodesModel.DELEGATE, QHeaderView.ResizeToContents) self.view.verticalHeader().setVisible(False) self.view.setSelectionMode(QAbstractItemView.SingleSelection) self.view.setSelectionBehavior(QAbstractItemView.SelectRows) self.view.setSortingEnabled(True) self.view.sortByColumn(self.model.ALIAS, Qt.AscendingOrder) vbox = QVBoxLayout() vbox.setContentsMargins(0, 0, 0, 0) vbox.addWidget(self.view) self.setLayout(vbox) def select_masternode(self, alias): """Select the row that represents alias.""" self.view.clearSelection() for i in range(self.proxy_model.rowCount()): idx = self.proxy_model.index(i, 0) mn_alias = str(self.proxy_model.data(idx)) if mn_alias == alias: self.view.selectRow(i) break def populate_collateral_key(self, row): """Fill in the collateral key for a masternode based on its collateral output. row refers to the desired row in the proxy model, not the actual model. """ mn = self.masternode_for_row(row) self.manager.populate_masternode_output(mn.alias) # Emit dataChanged for the collateral key. index = self.model.index(row, self.model.COLLATERAL) self.model.dataChanged.emit(index, index) def refresh_items(self): self.model.dataChanged.emit(QModelIndex(), QModelIndex()) def add_masternode(self, masternode, save = True): self.model.add_masternode(masternode, save=save) def remove_masternode(self, alias, save = True): self.model.remove_masternode(alias, save=save) def masternode_for_row(self, row): idx = self.proxy_model.mapToSource(self.proxy_model.index(row, 0)) return self.model.masternode_for_row(idx.row()) def import_masternode_conf_lines(self, conf_lines, pw): return self.model.import_masternode_conf_lines(conf_lines, pw)
class ConfigurationDialog(QDialog, Ui_Configuration, SettingDialog): def __init__(self): QDialog.__init__(self) self.setupUi(self) self.settings = MySettings() SettingDialog.__init__(self, self.settings) # new declaration of ProjectFinder since changes can be cancelled self.project_finder = ProjectFinder(self) # table model self.project_search_model = ProjectSearchModel(self.project_finder) self.proxyModel = QSortFilterProxyModel(self) self.proxyModel.setSourceModel(self.project_search_model) self.projectSearchTable.setModel(self.proxyModel) header = self.projectSearchTable.horizontalHeader() header.setSectionResizeMode(QHeaderView.ResizeToContents) # open/create QuickFinder file self.createFileButton.clicked.connect(self.create_QFTS_file) self.openFileButton.clicked.connect(self.open_QFTS_file) self.read_QFTS_file() # project search self.addSearchButton.clicked.connect(self.add_project_search) self.removeSearchButton.clicked.connect(self.remove_project_search) self.editSearchButton.clicked.connect(self.edit_project_search) self.refreshButton.clicked.connect(self.refresh_project_search) self.projectSearchTable.selectionModel().selectionChanged.connect( self.enableButtons) self.enableButtons() # geomapfish self.geomapfishCrsButton.clicked.connect( self.geomapfishCrsButtonClicked) def reject(self): if self.close_and_control(): QDialog.reject(self) def accept(self): if self.close_and_control(): QDialog.accept(self) def close_and_control(self): self.project_finder.close() for search in self.project_finder.searches.values(): if search.dateEvaluated is None: box = QMessageBox( QMessageBox.Warning, "Quick Finder", QCoreApplication.translate( "Configuration dialog", "Some searches are still not recorded to the file. Do you want to record them now ? " ), QMessageBox.Cancel | QMessageBox.Yes | QMessageBox.Close, self) ret = box.exec_() if ret == QMessageBox.Cancel: return False elif ret == QMessageBox.Yes: self.refresh_project_search() return False return True def read_QFTS_file(self): filepath = self.qftsfilepath.text() self.project_finder.setFile(filepath) self.projectSearchTable.setEnabled(self.project_finder.isValid) self.projectSearchButtonsWidget.setEnabled(self.project_finder.isValid) def create_QFTS_file(self): prjPath = QgsProject.instance().homePath() filepath = QFileDialog.getSaveFileName( self, "Create Quickfinder index file", prjPath, "Quickfinder file (*.qfts)") if filepath: if filepath[-5:] != ".qfts": filepath += ".qfts" if path.isfile(filepath): remove(filepath) create_FTS_file(filepath) self.qftsfilepath.setText(filepath) self.read_QFTS_file() def open_QFTS_file(self): prjPath = QgsProject.instance().homePath() filepath = QFileDialog.getOpenFileName(self, "Open Quickfinder index file", prjPath, "Quickfinder file (*.qfts)") if filepath: self.qftsfilepath.setText(filepath) self.read_QFTS_file() def add_project_search(self): ProjectSearchDialog(self.project_finder, self.project_search_model).exec_() def remove_project_search(self): sel = self.selected_search_ids() if len(sel) == 0: return box = QMessageBox( QMessageBox.Warning, "Quick Finder", QCoreApplication.translate( "Configuration dialog", "Are you sure to remove {0} search(es) ? ").format(len(sel)), QMessageBox.Yes | QMessageBox.Cancel, self) ret = box.exec_() if ret == QMessageBox.Cancel: return self.project_search_model.removeSearches(sel) def edit_project_search(self): sel = self.selected_search_ids() if len(sel) != 1: return if not self.project_search_model.searches.has_key(sel[0]): return search = self.project_search_model.searches[sel[0]] if search: ProjectSearchDialog(self.project_finder, self.project_search_model, search).exec_() def refresh_project_search(self): RefreshDialog(self.project_finder, self.project_search_model, self.selected_search_ids()).exec_() def selected_search_ids(self): selectedSearchId = [] for idx in self.projectSearchTable.selectionModel().selectedRows(): selectedSearchId.append(self.proxyModel.data(idx, SearchIdRole)) return selectedSearchId def enableButtons(self): n = len(self.selected_search_ids()) self.removeSearchButton.setEnabled(n > 0) self.editSearchButton.setEnabled(n == 1) self.projectSearchButtonsWidget.setEnabled(self.project_finder.isValid) def geomapfishCrsButtonClicked(self): dlg = QgsGenericProjectionSelector(self) dlg.setMessage('Select GeoMapFish CRS') dlg.setSelectedAuthId(self.geomapfishCrs.text()) if dlg.exec_(): self.geomapfishCrs.setText(dlg.selectedAuthId())
class CookiesDialog(QDialog, Ui_CookiesDialog): """ Class implementing a dialog to show all cookies. """ def __init__(self, cookieJar, parent=None): """ Constructor @param cookieJar reference to the cookie jar (CookieJar) @param parent reference to the parent widget (QWidget) """ super(CookiesDialog, self).__init__(parent) self.setupUi(self) self.addButton.setEnabled(False) self.__cookieJar = cookieJar self.removeButton.clicked.connect(self.cookiesTable.removeSelected) self.removeAllButton.clicked.connect(self.cookiesTable.removeAll) self.cookiesTable.verticalHeader().hide() model = CookieModel(cookieJar, self) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setSourceModel(model) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.cookiesTable.setModel(self.__proxyModel) self.cookiesTable.doubleClicked.connect(self.__showCookieDetails) self.cookiesTable.selectionModel().selectionChanged.connect( self.__tableSelectionChanged) self.cookiesTable.model().modelReset.connect(self.__tableModelReset) fm = QFontMetrics(QFont()) height = fm.height() + fm.height() // 3 self.cookiesTable.verticalHeader().setDefaultSectionSize(height) self.cookiesTable.verticalHeader().setMinimumSectionSize(-1) for section in range(model.columnCount()): header = self.cookiesTable.horizontalHeader()\ .sectionSizeHint(section) if section == 0: header = fm.width("averagebiglonghost.averagedomain.info") elif section == 1: header = fm.width("_session_id") elif section == 4: header = fm.width( QDateTime.currentDateTime().toString(Qt.LocalDate)) buffer = fm.width("mm") header += buffer self.cookiesTable.horizontalHeader().resizeSection(section, header) self.cookiesTable.horizontalHeader().setStretchLastSection(True) self.cookiesTable.model().sort( self.cookiesTable.horizontalHeader().sortIndicatorSection(), Qt.AscendingOrder) self.__detailsDialog = None def __showCookieDetails(self, index): """ Private slot to show a dialog with the cookie details. @param index index of the entry to show (QModelIndex) """ if not index.isValid(): return cookiesTable = self.sender() if cookiesTable is None: return model = cookiesTable.model() row = index.row() domain = model.data(model.index(row, 0)) name = model.data(model.index(row, 1)) path = model.data(model.index(row, 2)) secure = model.data(model.index(row, 3)) expires = model.data(model.index(row, 4)).toString("yyyy-MM-dd hh:mm") value = bytes( QByteArray.fromPercentEncoding( model.data(model.index(row, 5)))).decode() if self.__detailsDialog is None: from .CookieDetailsDialog import CookieDetailsDialog self.__detailsDialog = CookieDetailsDialog(self) self.__detailsDialog.setData(domain, name, path, secure, expires, value) self.__detailsDialog.show() @pyqtSlot() def on_addButton_clicked(self): """ Private slot to add a new exception. """ selection = self.cookiesTable.selectionModel().selectedRows() if len(selection) == 0: return from .CookiesExceptionsDialog import CookiesExceptionsDialog firstSelected = selection[0] domainSelection = firstSelected.sibling(firstSelected.row(), 0) domain = self.__proxyModel.data(domainSelection, Qt.DisplayRole) dlg = CookiesExceptionsDialog(self.__cookieJar, self) dlg.setDomainName(domain) dlg.exec_() def __tableSelectionChanged(self, selected, deselected): """ Private slot to handle a change of selected items. @param selected selected indexes (QItemSelection) @param deselected deselected indexes (QItemSelection) """ self.addButton.setEnabled(len(selected.indexes()) > 0) def __tableModelReset(self): """ Private slot to handle a reset of the cookies table. """ self.addButton.setEnabled(False)
class IPTagsSelectDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.app = QApplication.instance() self.destTags = [] self.allTagsModel = UneditableStringListModel(self) self.destTagsModel = UneditableStringListModel(self) self.allTagsProxyModel = QSortFilterProxyModel(self) self.allTagsProxyModel.setSourceModel(self.allTagsModel) self.ui = ui_iptagsmanager.Ui_IPTagsDialog() self.ui.setupUi(self) self.ui.destTagsView.setModel(self.destTagsModel) self.ui.destTagsView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.ui.destTagsView.doubleClicked.connect(self.onTagDoubleClicked) self.ui.addTagButton.clicked.connect(lambda: ensure(self.addTag())) self.ui.lineEditTag.textChanged.connect(self.onTagEditChanged) self.ui.lineEditTag.setValidator( QRegExpValidator(QRegExp(r'[A-Za-z0-9-_@#]+'))) self.ui.lineEditTag.setMaxLength(128) self.ui.tagItButton.clicked.connect(self.onTagObject) self.ui.untagItButton.clicked.connect(self.untagObject) self.ui.okButton.clicked.connect(lambda: ensure(self.validate())) self.ui.noTagsButton.clicked.connect(self.reject) self.setMinimumSize(self.app.desktopGeometry.width() / 2, (2 * self.app.desktopGeometry.height()) / 3) def onTagEditChanged(self, text): self.allTagsProxyModel.setFilterRegExp(text) self.ui.allTagsView.clearSelection() def onTagDoubleClicked(self, idx): ensure(self.tagObject([idx])) def onTagObject(self): ensure(self.tagObject()) def untagObject(self): try: for idx in self.ui.destTagsView.selectedIndexes(): tag = self.destTagsModel.data(idx, Qt.DisplayRole) if tag: tagList = self.destTagsModel.stringList() tagList.remove(tag) self.destTagsModel.setStringList(tagList) except Exception: pass async def tagObject(self, indexes=None): if indexes is None: indexes = self.ui.allTagsView.selectedIndexes() for idx in indexes: tag = self.allTagsProxyModel.data(idx, Qt.DisplayRole) if tag and tag not in self.destTagsModel.stringList(): self.destTagsModel.setStringList( self.destTagsModel.stringList() + [tag]) async def initDialog(self): await self.updateAllTags() async def addTag(self): tagname = self.ui.lineEditTag.text() if not tagname: return await database.ipTagAdd(ipTagsFormat(tagname)) self.ui.lineEditTag.clear() await self.updateAllTags() async def updateAllTags(self): tags = [t.name for t in await database.ipTagsAll()] self.allTagsModel.setStringList(tags) self.ui.allTagsView.setModel(self.allTagsProxyModel) self.allTagsProxyModel.sort(0) async def validate(self): self.destTags = self.destTagsModel.stringList() self.done(1)
class FileChooser(BaseFileChooser): def __init__(self, **kwargs): super(FileChooser, self).__init__(**kwargs) self.options = PropDict() self.edit.textEdited.connect(self._onTextEdited) self.view.activated.connect(self._onActivated) # models self.rootChanger = RootChangerProxy() fsModel = QFileSystemModel(self) self.setModel(fsModel) self.filter = QSortFilterProxyModel() self.filter.setSourceModel(self.rootChanger) self.view.setModel(self.filter) def setModel(self, model): self.baseModel = model self.rootChanger.setSourceModel(self.baseModel) @Slot(str) def setRoot(self, path): self.root = path srcIdx = self.baseModel.setRootPath(path) self.rootChanger.setRootSource(srcIdx) self.view.setRootIndex(QModelIndex()) @Slot(str) def _onTextEdited(self, txt): elems = txt.rsplit('/', 1) if len(elems) == 2: dir, base = elems else: dir, base = '', elems[0] path = os.path.join(self.root, dir) self.rootChanger.setRootSource(self.baseModel.index(path)) self.filter.setFilterRegExp(QRegExp(base, Qt.CaseInsensitive, QRegExp.Wildcard)) if self.options.get('autosuggest'): names = [self.filter.data(self.filter.index(i, 0)).toString() for i in range(self.filter.rowCount(QModelIndex()))] names = [n[len(base):] for n in names] add = commonPrefix(names) cursor = self.edit.cursorPosition() self.edit.setText(self.edit.text()[:cursor] + add) self.edit.setSelection(cursor, len(self.edit.text())) @Slot(QModelIndex) def _onActivated(self, idx): idx = self.filter.mapToSource(idx) idx = self.rootChanger.mapToSource(idx) info = self.baseModel.fileInfo(idx) if info.isDir(): return path = info.absoluteFilePath() self.openFile(path)
def data(self, index, role): if role == Qt.ToolTipRole: return QSortFilterProxyModel.data(self, index, Qt.DisplayRole) else: return QSortFilterProxyModel.data(self, index, role)
class CookiesDialog(QDialog, Ui_CookiesDialog): """ Class implementing a dialog to show all cookies. """ def __init__(self, cookieJar, parent=None): """ Constructor @param cookieJar reference to the cookie jar (CookieJar) @param parent reference to the parent widget (QWidget) """ super(CookiesDialog, self).__init__(parent) self.setupUi(self) self.addButton.setEnabled(False) self.__cookieJar = cookieJar self.removeButton.clicked.connect(self.cookiesTable.removeSelected) self.removeAllButton.clicked.connect(self.cookiesTable.removeAll) self.cookiesTable.verticalHeader().hide() model = CookieModel(cookieJar, self) self.__proxyModel = QSortFilterProxyModel(self) self.__proxyModel.setSourceModel(model) self.searchEdit.textChanged.connect( self.__proxyModel.setFilterFixedString) self.cookiesTable.setModel(self.__proxyModel) self.cookiesTable.doubleClicked.connect(self.__showCookieDetails) self.cookiesTable.selectionModel().selectionChanged.connect( self.__tableSelectionChanged) self.cookiesTable.model().modelReset.connect(self.__tableModelReset) fm = QFontMetrics(QFont()) height = fm.height() + fm.height() // 3 self.cookiesTable.verticalHeader().setDefaultSectionSize(height) self.cookiesTable.verticalHeader().setMinimumSectionSize(-1) for section in range(model.columnCount()): header = self.cookiesTable.horizontalHeader()\ .sectionSizeHint(section) if section == 0: header = fm.width("averagebiglonghost.averagedomain.info") elif section == 1: header = fm.width("_session_id") elif section == 4: header = fm.width( QDateTime.currentDateTime().toString(Qt.LocalDate)) buffer = fm.width("mm") header += buffer self.cookiesTable.horizontalHeader().resizeSection(section, header) self.cookiesTable.horizontalHeader().setStretchLastSection(True) self.cookiesTable.model().sort( self.cookiesTable.horizontalHeader().sortIndicatorSection(), Qt.AscendingOrder) self.__detailsDialog = None def __showCookieDetails(self, index): """ Private slot to show a dialog with the cookie details. @param index index of the entry to show (QModelIndex) """ if not index.isValid(): return cookiesTable = self.sender() if cookiesTable is None: return model = cookiesTable.model() row = index.row() domain = model.data(model.index(row, 0)) name = model.data(model.index(row, 1)) path = model.data(model.index(row, 2)) secure = model.data(model.index(row, 3)) expires = model.data(model.index(row, 4)).toString("yyyy-MM-dd hh:mm") value = bytes( QByteArray.fromPercentEncoding( model.data(model.index(row, 5)))).decode() if self.__detailsDialog is None: from .CookieDetailsDialog import CookieDetailsDialog self.__detailsDialog = CookieDetailsDialog(self) self.__detailsDialog.setData(domain, name, path, secure, expires, value) self.__detailsDialog.show() @pyqtSlot() def on_addButton_clicked(self): """ Private slot to add a new exception. """ selection = self.cookiesTable.selectionModel().selectedRows() if len(selection) == 0: return from .CookiesExceptionsDialog import CookiesExceptionsDialog firstSelected = selection[0] domainSelection = firstSelected.sibling(firstSelected.row(), 0) domain = self.__proxyModel.data(domainSelection, Qt.DisplayRole) dlg = CookiesExceptionsDialog(self.__cookieJar, self) dlg.setDomainName(domain) dlg.exec_() def __tableSelectionChanged(self, selected, deselected): """ Private slot to handle a change of selected items. @param selected selected indexes (QItemSelection) @param deselected deselected indexes (QItemSelection) """ self.addButton.setEnabled(len(selected.indexes()) > 0) def __tableModelReset(self): """ Private slot to handle a reset of the cookies table. """ self.addButton.setEnabled(False)
class ConfigurationDialog(QDialog, Ui_Configuration, SettingDialog): def __init__(self): QDialog.__init__(self) self.setupUi(self) self.settings = MySettings() SettingDialog.__init__(self, self.settings) # new declaration of ProjectFinder since changes can be cancelled self.project_finder = ProjectFinder(self) # table model self.project_search_model = ProjectSearchModel(self.project_finder) self.proxyModel = QSortFilterProxyModel(self) self.proxyModel.setSourceModel(self.project_search_model) self.projectSearchTable.setModel(self.proxyModel) header = self.projectSearchTable.horizontalHeader() header.setSectionResizeMode(QHeaderView.ResizeToContents) # open/create QuickFinder file self.createFileButton.clicked.connect(self.create_QFTS_file) self.openFileButton.clicked.connect(self.open_QFTS_file) self.read_QFTS_file() # project search self.addSearchButton.clicked.connect(self.add_project_search) self.removeSearchButton.clicked.connect(self.remove_project_search) self.editSearchButton.clicked.connect(self.edit_project_search) self.refreshButton.clicked.connect(self.refresh_project_search) self.projectSearchTable.selectionModel().selectionChanged.connect(self.enableButtons) self.enableButtons() # geomapfish self.geomapfishCrsButton.clicked.connect(self.geomapfishCrsButtonClicked) def reject(self): if self.close_and_control(): QDialog.reject(self) def accept(self): if self.close_and_control(): QDialog.accept(self) def close_and_control(self): self.project_finder.close() for search in self.project_finder.searches.values(): if search.dateEvaluated is None: box = QMessageBox(QMessageBox.Warning, "Quick Finder", QCoreApplication.translate("Configuration dialog", "Some searches are still not recorded to the file. Do you want to record them now ? "), QMessageBox.Cancel | QMessageBox.Yes | QMessageBox.Close, self) ret = box.exec_() if ret == QMessageBox.Cancel: return False elif ret == QMessageBox.Yes: self.refresh_project_search() return False return True def read_QFTS_file(self): filepath = self.qftsfilepath.text() self.project_finder.setFile(filepath) self.projectSearchTable.setEnabled(self.project_finder.isValid) self.projectSearchButtonsWidget.setEnabled(self.project_finder.isValid) def create_QFTS_file(self): prjPath = QgsProject.instance().homePath() filepath = QFileDialog.getSaveFileName(self, "Create Quickfinder index file", prjPath, "Quickfinder file (*.qfts)") if filepath: if filepath[-5:] != ".qfts": filepath += ".qfts" if path.isfile(filepath): remove(filepath) create_FTS_file(filepath) self.qftsfilepath.setText(filepath) self.read_QFTS_file() def open_QFTS_file(self): prjPath = QgsProject.instance().homePath() filepath = QFileDialog.getOpenFileName(self, "Open Quickfinder index file", prjPath, "Quickfinder file (*.qfts)") if filepath: self.qftsfilepath.setText(filepath) self.read_QFTS_file() def add_project_search(self): ProjectSearchDialog(self.project_finder, self.project_search_model).exec_() def remove_project_search(self): sel = self.selected_search_ids() if len(sel) == 0: return box = QMessageBox(QMessageBox.Warning, "Quick Finder", QCoreApplication.translate("Configuration dialog", "Are you sure to remove {0} search(es) ? ").format(len(sel)), QMessageBox.Yes | QMessageBox.Cancel, self) ret = box.exec_() if ret == QMessageBox.Cancel: return self.project_search_model.removeSearches(sel) def edit_project_search(self): sel = self.selected_search_ids() if len(sel) != 1: return if not self.project_search_model.searches.has_key(sel[0]): return search = self.project_search_model.searches[sel[0]] if search: ProjectSearchDialog(self.project_finder, self.project_search_model, search).exec_() def refresh_project_search(self): RefreshDialog(self.project_finder, self.project_search_model, self.selected_search_ids()).exec_() def selected_search_ids(self): selectedSearchId = [] for idx in self.projectSearchTable.selectionModel().selectedRows(): selectedSearchId.append(self.proxyModel.data(idx, SearchIdRole)) return selectedSearchId def enableButtons(self): n = len(self.selected_search_ids()) self.removeSearchButton.setEnabled(n > 0) self.editSearchButton.setEnabled(n == 1) self.projectSearchButtonsWidget.setEnabled(self.project_finder.isValid) def geomapfishCrsButtonClicked(self): dlg = QgsGenericProjectionSelector(self) dlg.setMessage('Select GeoMapFish CRS') dlg.setSelectedAuthId(self.geomapfishCrs.text()) if dlg.exec_(): self.geomapfishCrs.setText(dlg.selectedAuthId())
class FileChooser(BaseFileChooser): def __init__(self, **kwargs): super(FileChooser, self).__init__(**kwargs) self.options = PropDict() self.edit.textEdited.connect(self._onTextEdited) self.view.activated.connect(self._onActivated) # models self.rootChanger = RootChangerProxy() fsModel = QFileSystemModel(self) self.setModel(fsModel) self.filter = QSortFilterProxyModel() self.filter.setSourceModel(self.rootChanger) self.view.setModel(self.filter) def setModel(self, model): self.baseModel = model self.rootChanger.setSourceModel(self.baseModel) @Slot(str) def setRoot(self, path): self.root = path srcIdx = self.baseModel.setRootPath(path) self.rootChanger.setRootSource(srcIdx) self.view.setRootIndex(QModelIndex()) @Slot(str) def _onTextEdited(self, txt): elems = txt.rsplit('/', 1) if len(elems) == 2: dir, base = elems else: dir, base = '', elems[0] path = os.path.join(self.root, dir) self.rootChanger.setRootSource(self.baseModel.index(path)) self.filter.setFilterRegExp(QRegExp(base, Qt.CaseInsensitive, QRegExp.Wildcard)) if self.options.get('autosuggest'): names = [self.filter.data(self.filter.index(i, 0)).toString() for i in range(self.filter.rowCount(QModelIndex()))] names = [n[len(base):] for n in names] add = commonPrefix(names) cursor = self.edit.cursorPosition() self.edit.setText(self.edit.text()[:cursor] + add) self.edit.setSelection(cursor, len(self.edit.text())) @Slot(QModelIndex) def _onActivated(self, idx): idx = self.filter.mapToSource(idx) idx = self.rootChanger.mapToSource(idx) info = self.baseModel.fileInfo(idx) if info.isDir(): return path = info.absoluteFilePath() self.openFile(path)
class Window(QWidget): def __init__(self, connection): super(Window, self).__init__() self.conn = connection self.proxyModel = MySortFilterProxyModel(self) self.proxyModel.setDynamicSortFilter(True) self.proxyView = QTreeView() set_tree_view(self.proxyView) self.proxyView.setModel(self.proxyModel) self.proxyView.customContextMenuRequested.connect(self.pop_menu) self.filterType = QComboBox() self.filterModule = QComboBox() self.filterClass = QComboBox() self.filterNote = QComboBox() self.infLabel = QLabel() self.link_type = QComboBox() self.resView = QTreeView() set_tree_view(self.resView) self.resModel = QSortFilterProxyModel(self.resView) self.resView.setModel(self.resModel) self.resView.customContextMenuRequested.connect(self.menu_res_view) self.link_box = self.set_layout() self.sort_key = None self.repo = [] self.old_links = [] self.new_links = [] self.query_time = time_run() self.curr_id_db = 0 self.setWindowTitle("Custom Sort/Filter Model") self.resize(900, 750) def set_layout(self): filter_box: QGroupBox = self.set_filter_box() height = 92 filter_box.setMaximumHeight(height) link_box = self.set_link_box() link_box.setMaximumHeight(height) link_box.hide() stack_layout = QVBoxLayout() stack_layout.addWidget(filter_box) stack_layout.addWidget(link_box) proxyLayout = QGridLayout() proxyLayout.addWidget(self.proxyView, 0, 0) proxyLayout.addLayout(stack_layout, 1, 0) proxyLayout.addWidget(self.resView, 2, 0) proxyLayout.setRowStretch(0, 5) proxyLayout.setRowStretch(1, 0) proxyLayout.setRowStretch(2, 3) proxyGroupBox = QGroupBox("Module/Class/Method list") proxyGroupBox.setLayout(proxyLayout) mainLayout = QVBoxLayout() mainLayout.addWidget(proxyGroupBox) self.setLayout(mainLayout) return link_box def save_clicked(self, btn): { "Unload DB": save_init, "Copy all links": copy_to_clipboard }[btn.text()]() def set_filter_box(self): save_btn = QDialogButtonBox(Qt.Vertical) save_btn.addButton("Unload DB", QDialogButtonBox.ActionRole) save_btn.addButton("Copy all links", QDialogButtonBox.ActionRole) save_btn.clicked.connect(self.save_clicked) self.filterNote.addItem("All") self.filterNote.addItem("Not blank") filterTypeLabel = QLabel("&Type Filter") filterTypeLabel.setBuddy(self.filterType) filterModuleLabel = QLabel("&Module Filter") filterModuleLabel.setBuddy(self.filterModule) filterClassLabel = QLabel("&Class Filter") filterClassLabel.setBuddy(self.filterClass) filterNoteLabel = QLabel("&Remark Filter") filterNoteLabel.setBuddy(self.filterNote) filter_box = QGridLayout() filter_box.addWidget(filterTypeLabel, 0, 0) filter_box.addWidget(filterModuleLabel, 0, 1) filter_box.addWidget(filterClassLabel, 0, 2) filter_box.addWidget(filterNoteLabel, 0, 3) filter_box.addWidget(save_btn, 0, 4, 2, 1) filter_box.addWidget(self.filterType, 1, 0) filter_box.addWidget(self.filterModule, 1, 1) filter_box.addWidget(self.filterClass, 1, 2) filter_box.addWidget(self.filterNote, 1, 3) self.set_filters_combo() self.textFilterChanged() self.filterType.currentIndexChanged.connect(self.textFilterChanged) self.filterModule.currentIndexChanged.connect( self.textFilterModuleChanged) self.filterClass.currentIndexChanged.connect(self.textFilterChanged) self.filterNote.currentIndexChanged.connect(self.textFilterChanged) grp_box = QGroupBox() grp_box.setFlat(True) grp_box.setLayout(filter_box) return grp_box def set_filters_combo(self): curs = self.conn.cursor() self.filterType.clear() self.filterType.addItem("All") curs.execute(qsel3) for cc in curs: self.filterType.addItem(memb_type[cc[0]]) self.filterModule.clear() self.filterModule.addItem("All") self.filterModule.addItem("") curs.execute(qsel0) for cc in curs: self.filterModule.addItem(cc[0]) self.filterClass.clear() self.filterClass.addItem("All") curs.execute(qsel1) for cc in curs: self.filterClass.addItem(cc[0]) def textFilterModuleChanged(self): curs = self.conn.cursor() self.filterClass.clear() self.filterClass.addItem("All") if self.filterModule.currentText() == "All": curs.execute(qsel1) else: curs.execute( ("select distinct class from methods2 " "where module = ? order by class;"), (self.filterModule.currentText(), ), ) for cc in curs: self.filterClass.addItem(cc[0]) for cc in curs: self.filterType.addItem(memb_type[cc[0]]) def menu_res_view(self, pos): """ only copy to clipboard """ menu = QMenu(self) menu.addAction("clipboard") # menu.addAction("refresh") action = menu.exec_(self.resView.mapToGlobal(pos)) if action: self._to_clipboard() def _to_clipboard(self): rr = [] for rep in self.repo: pp = [str(x) for x in rep] rr.append("\t".join(pp)) QApplication.clipboard().setText("\n".join(rr)) def pop_menu(self, pos): idx = self.proxyView.indexAt(pos) menu = QMenu(self) if idx.isValid(): menu.addAction("First level only") menu.addSeparator() menu.addAction("sort by level") menu.addAction("sort by module") menu.addSeparator() menu.addAction("append row") if idx.isValid(): menu.addAction("delete rows") menu.addAction("edit links") menu.addSeparator() menu.addAction("not called") menu.addSeparator() menu.addAction("complexity") menu.addSeparator() menu.addAction("refresh") menu.addAction("reload DB") action = menu.exec_(self.proxyView.mapToGlobal(pos)) if action: self.menu_action(action.text()) def setSourceModel(self, model: QStandardItemModel): self.proxyModel.setSourceModel(model) set_columns_width(self.proxyView) set_headers(self.proxyModel, main_headers) def textFilterChanged(self): self.proxyModel.filter_changed( self.filterType.currentText(), self.filterModule.currentText(), self.filterClass.currentText(), self.filterNote.currentText(), ) def menu_action(self, act: str): { "First level only": self.first_level_only, "sort by level": self.sort_by_level, "sort by module": self.sort_by_module, "append row": self.append_row, "refresh": self.refresh, "not called": self.is_not_called, "complexity": self.recalc_complexity, "reload DB": self.reload_data, "edit links": self.edit_links, "delete rows": self.delete_selected_rows, }[act]() def recalc_complexity(self): """ add radon cyclomatic complexity repor data """ mm = self.filterModule.currentText() module = "" if mm == "All" else mm cc_list = cc_report(module) for row in cc_list: self.update_cc(row) mark_deleted_methods(cc_list, module) def update_cc(self, row: Iterable): """ @param row: CC, length, type(C/F/M), module, class, method """ sql_sel = ("select id from methods2 where " "type = ? and module = ? and class = ? and method = ?") sql_upd = "update methods2 set cc = ?, length = ? " "where id = ?" sql_ins = ("insert into methods2 (CC, length, type, module, " "Class, method, remark) values(?,?,?,?,?,?,?);") rr = (*row, ) qq = self.conn.cursor() id = qq.execute(sql_sel, rr[2:]).fetchone() if id: qq.execute(sql_upd, (*rr[:2], id[0])) else: tt = datetime.now().strftime("%Y-%m-%d %H:%M") qq.execute(sql_ins, (*rr, tt)) self.conn.commit() def is_not_called(self): qq = self.conn.cursor() qq.execute(not_called) self.set_res_model(qq, call_headers, False) set_columns_width(self.resView, proportion=(2, 2, 5, 7, 7, 2, 3, 5)) set_headers(self.resModel, call_headers) def reload_data(self): sql1 = ( "delete from methods2;", "insert into methods2 (" "ID, type, module, class, method, CC, length, remark) " "values (?, ?, ?, ?, ?, ?, ?, ?);", ) input_file = prj_path / input_meth load_table(input_file, sql1) sql2 = ( "delete from one_link;", "insert into one_link (id, call_id) values (?, ?);", ) input_file = prj_path / input_link load_table(input_file, sql2) curs = conn.cursor() curs.execute("delete from links;") conn.commit() curs.execute(all_levels_link) conn.commit() self.refresh() def refresh(self): model = QStandardItemModel(0, len(main_headers.split(",")), self.proxyView) qq = conn.cursor() qq.execute(qsel2) vv = ((x[0], memb_type[x[1]], *x[2:-2], x[-2].rjust(4), x[-1]) for x in qq) fill_in_model(model, vv) self.setSourceModel(model) def clear_report_view(self): self.repo.clear() model = QStandardItemModel(0, len(rep_headers.split(",")), self.resView) self.resModel.setSourceModel(model) set_columns_width(self.resView, proportion=(3, 2, 2, 2, 7, 7, 7, 2, 2, 1)) set_headers(self.resModel, rep_headers) self.query_time = time_run() def append_row(self): crs = conn.cursor() items = ( memb_key[self.proxyModel.type_filter], self.proxyModel.module_filter, self.proxyModel.class_filter, "", "", "", "", self.query_time[0], ) crs.execute(ins0, items) idn = crs.lastrowid conn.commit() param = ( self.proxyModel.rowCount(), (self.proxyModel.type_filter, *items[1:]), idn, ) add_row(self.proxyModel, param) def delete_selected_rows(self): idx_list = self.proxyView.selectionModel().selectedRows() idx_list.reverse() for p_idx in idx_list: if p_idx.isValid(): row = p_idx.row() self.delete_from_db(p_idx) self.proxyModel.removeRows(row, 1) def delete_from_db(self, index: QModelIndex): id_db = self.proxyModel.get_data(index, Qt.UserRole) conn.execute("delete from methods2 where id=?;", (id_db, )) conn.commit() def edit_links(self): index = self.proxyView.currentIndex() ss = self.proxyModel.get_data(index) id_db = self.proxyModel.get_data(index, Qt.UserRole) self.infLabel.setText("{:04d}: {}".format(id_db, ".".join(ss[1:4]))) self.link_box.show() qq = conn.cursor() qq.execute(sql_links.format(id_db, id_db)) self.set_res_model(qq, link_headers, True) self.repo.append((id_db, 'Sel', *ss[:4])) set_columns_width(self.resView, proportion=(3, 2, 8, 8, 8)) set_headers(self.resModel, link_headers) self.old_links = qq.execute(sql_id2.format(id_db, id_db)).fetchall() self.new_links = self.old_links[:] self.curr_id_db = id_db def set_res_model(self, qq: Iterable, headers: str, user_data: bool): self.repo.clear() for row in qq: self.repo.append(row) model = QStandardItemModel(0, len(headers.split(",")), self.resView) fill_in_model(model, self.repo, user_data) self.resModel.setSourceModel(model) def set_link_box(self): self.link_type.addItem("What") self.link_type.addItem("From") f_type = QLabel("Link &type:") f_type.setBuddy(self.link_type) ok_btn = QDialogButtonBox() ok_btn.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) ok_btn.addButton("+", QDialogButtonBox.ActionRole) ok_btn.addButton("-", QDialogButtonBox.ActionRole) ok_btn.clicked.connect(self.btn_clicked) l_box = QGridLayout() l_box.addWidget(self.infLabel, 0, 0) l_box.addWidget(f_type, 1, 0) l_box.addWidget(self.link_type, 1, 1) l_box.addWidget(ok_btn, 1, 2) l_box.setRowStretch(0, 1) l_box.setRowStretch(1, 0) l_box.setRowStretch(2, 1) grp = QGroupBox() grp.setFlat(True) grp.setLayout(l_box) return grp def btn_clicked(self, btn): { "OK": self.ok_clicked, "Cancel": self.cancel_cliked, "+": self.plus_clicked, "-": self.minus_clicked, }[btn.text()]() def ok_clicked(self): s_new = set(self.new_links) s_old = set(self.old_links) added = s_new - s_old removed = s_old - s_new if removed: for link in removed: conn.execute("delete from one_link where id=? and call_id=?;", link) if added: for link in added: conn.execute( "insert into one_link (id, call_id) values (?, ?);", link) conn.commit() self.resModel.sourceModel().clear() self.link_box.hide() if removed or added: recreate_links() def cancel_cliked(self): self.resModel.sourceModel().clear() self.link_box.hide() def plus_clicked(self): """ add link to resModel """ to_insert = self.collect_links_with_selected() row_no = self.resModel.rowCount() for row in to_insert: add_row(self.resModel, (row_no, row[1:], row[0])) row_no += 1 def collect_links_with_selected(self): """ creation links according to selected rows in proxyView and direction of link selected in self.link_type: self.curr_id_db - DB id of edited method (object) link is a pair of ids (what called, called from) """ stat = self.link_type.currentText() idx_sel = self.proxyView.selectedIndexes() idx_col0 = [ix for ix in idx_sel if ix.column() == 0] to_insert = [] for idx in idx_col0: id = self.proxyModel.get_data(idx, Qt.UserRole) link = (id, self.curr_id_db) if stat == "What" else (self.curr_id_db, id) if link in self.new_links or link[::-1] in self.new_links: continue self.new_links.append(link) row = self.proxyModel.get_data(idx)[:-1] to_insert.append([id, stat] + row) return to_insert def minus_clicked(self): idx_sel = self.resView.selectionModel().selectedRows() idx_sel.reverse() for idx in idx_sel: self.remove_in_new_links(idx) self.remove_in_model(idx) def remove_in_new_links(self, index: QModelIndex): link_type = self.resModel.data(index) id_db = self.resModel.data(index, Qt.UserRole) link = ((id_db, self.curr_id_db) if link_type == "What" else (self.curr_id_db, id_db)) self.new_links.remove(link) def remove_in_model(self, index): row = index.row() self.resModel.removeRows(row, 1) def get_selected_methods(self): """ Returns lists of rows selected in the proxyView: @return: list of selected methods """ indexes = self.proxyView.selectionModel().selectedRows() methods = [] for idx in indexes: methods.append(self.proxyModel.get_data(idx)) return methods def first_level_only(self): """ select method to create link-report depending on number of selected methods @return: None """ self.clear_report_view() self.sort_key = sort_keys["by module"] ids = self.proxyView.selectionModel().selectedRows() opt = len(ids) if len(ids) < 3 else "more than 2" { 1: self.selected_only_one, 2: self.selected_exactly_two, "more than 2": self.selected_more_than_two }[opt](1) def prep_sql(self, sql: str, lvl: int = 0) -> str: mod = self.filterModule.currentText() cls = self.filterClass.currentText() return (sql + ("" if mod == "All" else where_mod.format(mod)) + ("" if cls == "All" else where_cls.format(cls)) + (and_level if lvl else "") + group_by) def selected_only_one(self, lvl): pre = (self.query_time[1], "Sel", "") names = self.get_selected_methods() self.sorted_report(self.repo, (pre, names, "")) lst = self.first_1_part(what_call_1, lvl) pre = (self.query_time[1], "What", "") self.sorted_report(self.repo, (pre, lst, "")) lst = self.first_1_part(called_from_1, lvl) pre = (self.query_time[1], "From", "") self.sorted_report(self.repo, (pre, lst, "")) fill_in_model(self.resModel.sourceModel(), self.repo, user_data=False) def first_1_part(self, sql: str, lvl: int): p_sql = self.prep_sql(sql, lvl) ids = self.get_db_ids() lst = self.exec_sql_b(p_sql, ids) return [(*map(str, x), ) for x in lst] def get_db_ids(self): ids = [] indexes = self.proxyView.selectionModel().selectedRows() for idx in indexes: ids.append(self.proxyModel.get_data(idx, Qt.UserRole)) return ids def selected_exactly_two(self, lvl): pre = (self.query_time[1], "Sel") names = self.get_selected_methods() n_names = [("A", *names[0]), ("B", *names[1])] self.sorted_report(self.repo, (pre, n_names, "")) self.report_four("What", lvl) self.report_four("From", lvl) fill_in_model(self.resModel.sourceModel(), self.repo, user_data=False) def report_four(self, what, lvl): sql = {"What": what_call_1, "From": called_from_1}[what] p_sql = self.prep_sql(sql, lvl) ids = self.get_db_ids() lst_a = self.first_2_part((ids[0], ), sql) lst_b = self.first_2_part((ids[1], ), sql) self.sorted_report(self.repo, ( (self.query_time[1], what, "A | B"), list(set(lst_a) | set(lst_b)), "", )) self.sorted_report(self.repo, ( (self.query_time[1], what, "A - B"), list(set(lst_a) - set(lst_b)), "", )) self.sorted_report(self.repo, ( (self.query_time[1], what, "B - A"), list(set(lst_b) - set(lst_a)), "", )) self.sorted_report(self.repo, ( (self.query_time[1], what, "A & B"), list(set(lst_a) & set(lst_b)), "", )) def first_2_part(self, ids: Iterable, sql: str) -> list: lst = self.exec_sql_b(sql, ids) return [(*map(str, x), ) for x in lst] def selected_more_than_two(self, lvl): pre = (self.query_time[1], "Sel", "") names = self.get_selected_methods() self.sorted_report(self.repo, (pre, names, "")) self.report_23("What", lvl) self.report_23("From", lvl) fill_in_model(self.resModel.sourceModel(), self.repo, user_data=False) def report_23(self, param, lvl): sql = {"What": what_id, "From": from_id}[param] ids = self.get_db_ids() links = self.exec_sql_2(ids, lvl, sql) rep_prep = pre_report(links) self.methods_by_id_list(three_or_more, rep_prep[0:3:2], param, "ALL") self.methods_by_id_list(three_or_more, rep_prep[1:], param, "ANY") def exec_sql_2(self, ids, lvl, sql) -> list: """ @param: ids - list of id of selected rows @param: lvl - level of call: all or only first @param: sql - select methods by type of link: "call What"/"called From" @return: list of tuples (method_id, level of call) """ res = [] curs = self.conn.cursor() loc_sql = sql.format("and level=1" if lvl else "") for id_ in ids: w_id = curs.execute(loc_sql, (id_, )) res.append(dict(w_id)) return res def methods_by_id_list(self, sql: str, ids: list, what: str, all_any: str): if ids: cc = self.exec_sql_f(sql, (",".join((map(str, ids[0]))), )) pre = (self.query_time[1], what, all_any) vv = insert_levels(cc, ids[1]) self.sorted_report(self.repo, (pre, vv, "")) def sort_by_level(self): """ Show lists of methods sorted by level @param ids: indexes of selected methods @param names: selected methods as (module, class, method) list @return: None """ self.clear_report_view() self.sort_key = sort_keys["by level"] self.sel_count_handle() def sort_by_module(self): """ Show lists of methods sorted by module name @param ids: indexes of selected methods @param names: selected methods as (module, class, method) list @return: None """ self.clear_report_view() self.sort_key = sort_keys["by module"] self.sel_count_handle() def sel_count_handle(self): """ This method does the same as the "first_level_only" method @return: None """ ids = self.proxyView.selectionModel().selectedRows() opt = len(ids) if len(ids) < 3 else "more than 2" { 1: self.selected_only_one, 2: self.selected_exactly_two, "more than 2": self.selected_more_than_two }[opt](0) def exec_sql_b(self, sql: str, sql_par: tuple): """ exesute SQL - bind parameters with '?' @param sql: @param sql_par: @return: list of lists of strings """ curs = self.conn.cursor() cc = curs.execute(sql, sql_par) return [(*map(str, x), ) for x in cc] def exec_sql_f(self, sql: str, sql_par: tuple): """ exesute SQL - insert parameters into SQL with str.format method @param sql: @param sql_par: @return: list of lists of strings """ curs = self.conn.cursor() cc = curs.execute(sql.format(*sql_par)) return [(*map(str, x), ) for x in cc] def sorted_report(self, report: list, rep_data: tuple): pre, lst, post = rep_data lst.sort(key=self.sort_key) for ll in lst: report.append((*pre, *ll, *post))