Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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())
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
 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)
Exemplo n.º 6
0
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))
Exemplo n.º 7
0
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)
Exemplo n.º 8
0
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())
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
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)
Exemplo n.º 11
0
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)
Exemplo n.º 12
0
 def data(self, index, role):
     if role == Qt.ToolTipRole:
         return QSortFilterProxyModel.data(self, index, Qt.DisplayRole)
     else:
         return QSortFilterProxyModel.data(self, index, role)
Exemplo n.º 13
0
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)
Exemplo n.º 14
0
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())
Exemplo n.º 15
0
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)
Exemplo n.º 16
0
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))