Exemple #1
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.model = Project()
        self.view = QTreeView(self)
        self.view.setModel(self.model)
        self.view.setDragEnabled(True)
        self.view.setDragDropMode(QAbstractItemView.InternalMove)
        self.setCentralWidget(self.view)

    def mousePressEvent(self, e):
        print(e.x(), e.y())
        return QMainWindow.mousePressEvent(self, e)
Exemple #2
0
class MainWidget(QWidget):
    def __init__(self, parent=None):
        super(MainWidget, self).__init__(parent)

        # define tree view
        self.treeView = QTreeView(self)

        # insert line edit
        self.lineEdit1 = QLineEdit(self)
        self.lineEdit2 = QLineEdit(self)

        # insert a button group widget
        self.buttonGroupWidget1 = ButtonGroupWidget(self)
        self.buttonGroupWidget1.setTitle("Select option")
        self.buttonGroupWidget1.addRadioButton("Option 1", 1)
        self.buttonGroupWidget1.addRadioButton("Option 2", 2)
        self.buttonGroupWidget1.addRadioButton("Option 3", 3)

        layoutMain = QVBoxLayout(self)
        layoutMain.addWidget(self.treeView)
        layoutMain.addWidget(self.lineEdit1)
        layoutMain.addWidget(self.lineEdit2)
        layoutMain.addWidget(self.buttonGroupWidget1)

        # Create the data model and map the model to the widgets.
        self._model = DataModel()
        self.treeView.setModel(self._model)

        self._dataMapper = QDataWidgetMapper()
        self._dataMapper.setModel(self._model)
        # the mapping works fine for line edits and combo boxes
        self._dataMapper.addMapping(self.lineEdit1, 0)
        self._dataMapper.addMapping(self.lineEdit2, 1)
        # mapping to custom property
        self._dataMapper.addMapping(self.buttonGroupWidget1, 1,
                                    "selectedOption")

        self.treeView.selectionModel().currentChanged.connect(
            self.setSelection)

    def setSelection(self, current):
        parent = current.parent()
        # self._dataMapper.setRootIndex(parent)
        self._dataMapper.setCurrentModelIndex(current)
class FileSystemView(QWidget):
    def __init__(self, dir_path):
        super().__init__()
        # appWidth = 800
        # appHeight = 300
        self.setWindowTitle('File System Viewer')
        # self.setGeometry(300, 300, appWidth, appHeight)

        self.model = QFileSystemModel()
        self.model.setRootPath(dir_path)
        self.tree = QTreeView()
        self.tree.setModel(self.model)
        self.tree.setRootIndex(self.model.index(dir_path))
        self.tree.setColumnWidth(0, 250)
        self.tree.setAlternatingRowColors(True)

        layout = QVBoxLayout()
        layout.addWidget(self.tree)
        self.setLayout(layout)
Exemple #4
0
def model_view():
    app = QApplication()
    splitter = QSplitter()

    model = QFileSystemModel()
    model.setRootPath(QDir.currentPath())
    parentIndex = model.index(QDir.currentPath())

    tree = QTreeView(splitter)
    tree.setModel(model)
    tree.setRootIndex(parentIndex)

    list = QListView(splitter)
    list.setModel(model)
    list.setRootIndex(parentIndex)

    table = QTableView(splitter)
    table.setModel(model)
    table.setRootIndex(parentIndex)

    splitter.setWindowTitle("Two views onto the same file system model")
    splitter.show()
    app.exec_()
Exemple #5
0
class TreeView(QWidget):
    def __init__(self, path=None):

        super(TreeView, self).__init__()

        self.model = QFileSystemModel()

        if path:
            self.selectedPath = path
            self.model.setRootPath(self.selectedPath)
        else:
            self.selectedPath = QDir.currentPath()
            self.model.setRootPath(self.selectedPath)

        mainLayout = QVBoxLayout()
        mainLayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(mainLayout)

        self.tree = QTreeView()
        self.tree.setModel(self.model)
        self.tree.setRootIndex(self.model.index(self.selectedPath))
        self.tree.setColumnHidden(1, True)
        self.tree.setColumnHidden(2, True)
        self.tree.setColumnHidden(3, True)
        mainLayout.addWidget(self.tree)

    def changePath(self, path):

        self.selectedPath = path

        self.tree.setModel(None)

        self.model.setRootPath(self.selectedPath)
        self.model.setNameFilters(
            ["*.png", "*.jpg", "*.bmp", "*.svg", "*.tiff", "*.gif"])

        self.tree.setModel(self.model)
        self.tree.setRootIndex(self.model.index(self.selectedPath))
        self.tree.setColumnHidden(1, True)
        self.tree.setColumnHidden(2, True)
        self.tree.setColumnHidden(3, True)

        self.repaint()
Exemple #6
0
class DownloadDirTreeWidget(QWidget):
    def __init__(self, root_path) -> None:
        QWidget.__init__(self)

        # self.index stores the index of the latest item which is clicked
        # self.root_path is the path to the folder currently showing
        self.index = None
        self.root_path = os.path.abspath(root_path)

        self.dir_view = QTreeView()
        self.model = QFileSystemModel(self.dir_view)
        self.model.setRootPath(self.root_path)
        self.dir_view.clicked.connect(self.onFileItemClicked)
        self.dir_view.doubleClicked.connect(self.onFileItemDoubleClicked)
        self.dir_view.setModel(self.model)
        self.dir_view.setRootIndex(self.model.index(self.root_path))

        open_button = QPushButton("Open")
        open_button.clicked.connect(self.openFile)

        open_in_file_explorer_button = QPushButton("Open in File Explorer")
        open_in_file_explorer_button.clicked.connect(self.openInFileExplorer)

        self.root_path_line_edit = QLineEdit(self.root_path)
        self.root_path_line_edit.returnPressed.connect(
            self.onChangeLineEditReturned)
        self.root_path_line_edit.setSizePolicy(QSizePolicy.Minimum,
                                               QSizePolicy.Minimum)
        self.root_path_line_edit.adjustSize()

        change_path_button = QPushButton('Change Directory')
        change_path_button.clicked.connect(self.onChangeButtonClicked)

        addressCompleter = QCompleter()
        addressCompleter.setModel(self.model)
        self.root_path_line_edit.setCompleter(addressCompleter)

        # Set layout
        layout = QGridLayout()
        layout.addWidget(self.root_path_line_edit, 0, 0, 1, 1)
        layout.addWidget(change_path_button, 0, 1, 1, 1)
        layout.addWidget(self.dir_view, 1, 0, 1, 2)
        layout.addWidget(open_button, 2, 0, 1, 1)
        layout.addWidget(open_in_file_explorer_button, 2, 1, 1, 1)
        layout.setMargin(0)
        self.setLayout(layout)

    def setRootPath(self, root_path):
        self.root_path = os.path.abspath(root_path)

    def openFile(self):
        if self.index is not None:
            file_path = self.model.filePath(self.index).replace('/', '\\')
            is_dir = self.model.isDir(self.index)
            # If is file, open with default program
            # If is directory, open with file explorer
            if is_dir is False:
                os.startfile(file_path, 'open')
            else:
                subprocess.run(['explorer', file_path])

    def openInFileExplorer(self):
        if self.index is None:
            file_path = self.model.filePath(self.index).replace('/', '\\')
            subprocess.run(['explorer', '/select,', file_path])

    def onFileItemClicked(self, index):
        # When clicked, resize and update self.index
        self.dir_view.resizeColumnToContents(0)
        self.index = index

    def onFileItemDoubleClicked(self, index):
        # When double clicked, update self.index and open the file directly
        self.index = index
        if self.sender().model().isDir(index) is False:
            self.openFile()

    def onChangeButtonClicked(self):
        new_path = QFileDialog.getExistingDirectory(self, 'Change Directory',
                                                    self.root_path)
        self.changeRootPath(new_path)

    def onChangeLineEditReturned(self):
        new_path = self.root_path_line_edit.text()
        if os.path.isdir(new_path):
            self.changeRootPath(new_path)
        else:
            subprocess.run(['explorer', new_path])
            self.root_path_line_edit.setText(self.root_path)

    def changeRootPath(self, new_path: str):
        if os.path.exists(new_path):
            self.root_path = os.path.abspath(new_path)
            self.dir_view.setRootIndex(self.model.index(self.root_path))
            self.root_path_line_edit.setText(self.root_path)
Exemple #7
0
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        #QWidget.__init__(self)

        self.createActions()
        self.createMenus()
        self.setWindowTitle("Map")
        self.painter = MyPainter()
        self.createLayout()

        self.fileName = ''

        #按钮 选取状态
        self.state = False
        #QObject.connect(self.painter, QtCore.SIGNAL("get_point_id()"), self, QtCore.SLOT("stateDisplay()"))
        self.painter.valueChanged.connect(self.stateDisplay)
        self.button3.clicked.connect(self.clearPoint)
        self.button0.clicked.connect(self.displayPoint)
        self.button4.clicked.connect(self.createLane)
        self.button5.clicked.connect(self.createConn)

    #读取点号
    def stateDisplay(self):
        self.brower1.setText(str(self.painter.start_point.id))
        self.brower2.setText(str(self.painter.end_point.id))

    def clearPoint(self):
        self.painter.target_point = 0
        self.painter.start_point.id = ''
        self.painter.end_point.id = ''
        self.painter.repaint()
        self.brower1.setText(str(self.painter.start_point.id))
        self.brower2.setText(str(self.painter.end_point.id))

    #根据输入框内id显示点号。当不显示时,需点击鼠标两下,由self.target_point的设计决定
    def displayPoint(self):
        self.painter.start_point.id = int(self.brower1.text())
        self.painter.start_point.draw_point = self.painter.allPoint[
            self.painter.start_point.id].draw_point
        self.painter.end_point.id = int(self.brower2.text())
        self.painter.end_point.draw_point = self.painter.allPoint[
            self.painter.end_point.id].draw_point
        self.painter.repaint()

    #可能需要加入条件,起始点id小于终止点id。conn同
    def createLane(self):
        #self.painter.data
        msgBox = QtWidgets.QMessageBox()

        if (self.painter.start_point.id == ''
                or self.painter.end_point.id == ''):
            msgBox.setText("输入错误")
        else:
            startline = self.painter.data[self.painter.data[0] ==
                                          self.painter.start_point.id]
            endline = self.painter.data[self.painter.data[0] ==
                                        self.painter.end_point.id]

            start_index = startline.index.values[0]
            end_index = endline.index.values[0]
            output_data = self.painter.data.iloc[start_index:end_index + 1, :]
            #输出
            output_data[0] = output_data[0].astype('int64')
            num = len(os.listdir("outputDATA\\Lane"))
            output_data.to_csv('outputDATA\\Lane\\' + str(num) + '.txt',
                               sep='\t',
                               index=False,
                               header=False)

            #此处不加等于即路段留有衔接点
            #存有部分点没删除?for in和remove的问题。
            #12.12 保留路段末尾处衔接点,用于生成道路
            for item in self.painter.allPoint:
                if int(item.id) >= int(self.painter.start_point.id) and int(
                        item.id) < int(self.painter.end_point.id):
                    self.painter.displayPoint.remove(item)
                    #print(item.id,self.painter.start_point.id,self.painter.end_point.id)
            self.painter.repaint()

            msgBox.setText("已生成目标道路Lane" + str(num))
        msgBox.exec_()

    def createConn(self):
        #self.painter.data
        msgBox = QtWidgets.QMessageBox()
        if (self.painter.start_point.id == ''
                or self.painter.end_point.id == ''):
            msgBox.setText("输入错误")
        else:
            startline = self.painter.data[self.painter.data[0] ==
                                          self.painter.start_point.id]
            endline = self.painter.data[self.painter.data[0] ==
                                        self.painter.end_point.id]

            start_index = startline.index.values[0]
            end_index = endline.index.values[0]
            output_data = self.painter.data.iloc[start_index:end_index + 1, :]
            #输出
            output_data[0] = output_data[0].astype('int64')
            num = len(os.listdir("outputDATA\\Conn"))
            output_data.to_csv('outputDATA\\Conn\\' + str(num) + '.txt',
                               sep='\t',
                               index=False,
                               header=False)

            for item in self.painter.allPoint:
                if int(item.id) >= int(self.painter.start_point.id) and int(
                        item.id) < int(self.painter.end_point.id):
                    self.painter.displayPoint.remove(item)
                    #print(item.id,self.painter.start_point.id,self.painter.end_point.id)
            self.painter.repaint()

            msgBox.setText("已生成目标道路Conn" + str(num))
        msgBox.exec_()

    def fileList(self):
        #树状文件列表
        self.model = QDirModel()
        self.view = QTreeView(self)
        self.view.setModel(self.model)
        self.view.setColumnHidden(1, True)
        self.view.setColumnHidden(2, True)
        self.view.setColumnHidden(3, True)
        self.view.setHeaderHidden(True)
        #self.view.setRootIndex(self.model.index("c:/"))
        self.layout.addWidget(self.view, 0, 0, 2, 1)

    def createLayout(self):
        self.widget = QWidget()
        self.setCentralWidget(self.widget)

        #栅格布局
        self.layout = QGridLayout()
        #设置拉伸因子,每一列的比例
        self.layout.setColumnStretch(0, 1)
        self.layout.setColumnStretch(1, 4)
        #控件
        self.fileList()
        self.layout.addWidget(self.painter, 0, 1)
        #页面
        self.button1 = QtWidgets.QLabel("起始点")
        self.brower1 = QtWidgets.QLineEdit()
        self.button2 = QtWidgets.QLabel("终止点")
        self.brower2 = QtWidgets.QLineEdit()
        self.button3 = QtWidgets.QPushButton("清除")

        self.button0 = QtWidgets.QPushButton("显示点号")
        self.button4 = QtWidgets.QPushButton("生成Lane")
        self.button5 = QtWidgets.QPushButton("生成Conn")

        labelLayout1 = QtWidgets.QHBoxLayout()
        labelLayout2 = QtWidgets.QHBoxLayout()

        labelLayout1.addWidget(self.button1)
        labelLayout1.addWidget(self.brower1)
        labelLayout1.addWidget(self.button2)
        labelLayout1.addWidget(self.brower2)
        labelLayout1.addWidget(self.button3)

        labelLayout2.addWidget(self.button0)
        labelLayout2.addWidget(self.button4)
        labelLayout2.addWidget(self.button5)

        self.layout.addLayout(labelLayout1, 1, 1)
        self.layout.addLayout(labelLayout2, 2, 1)
        self.widget.setLayout(self.layout)

    def createActions(self):
        self.openRoadAct = QtWidgets.QAction("加载道路数据",
                                             self,
                                             shortcut="Ctrl+O",
                                             triggered=self.openRoad)

        self.openPointAct = QtWidgets.QAction("加载点数据",
                                              self,
                                              shortcut="Ctrl+P",
                                              triggered=self.openPoint)
        #self.saveAsAct = QtWidgets.QAction("&Save As...", self, shortcut="Ctrl+S",triggered=self.saveAs)

        self.exitAct = QtWidgets.QAction("退出",
                                         self,
                                         shortcut="Ctrl+Q",
                                         triggered=self.close)

        #self.aboutAct = QtWidgets.QAction("&About", self, triggered=self.about)

        #self.aboutQtAct = QtWidgets.QAction("About &Qt", self,triggered=QtWidgets.qApp.aboutQt)

    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&打开")
        self.fileMenu.addAction(self.openRoadAct)
        self.fileMenu.addAction(self.openPointAct)
        #self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addAction(self.exitAct)

        self.menuBar().addSeparator()

        #self.helpMenu = self.menuBar().addMenu("&Help")
        #self.helpMenu.addAction(self.aboutAct)
        #self.helpMenu.addAction(self.aboutQtAct)

    #加载NovAtel文件数据
    def openRoad(self):
        fileName = QtWidgets.QFileDialog.getOpenFileName(
            self, "加载数据", QtCore.QDir.currentPath(), "Files (*.txt *.csv)")[0]

        if not fileName:
            return

        inFile = QtCore.QFile(fileName)
        if not inFile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtWidgets.QMessageBox.warning(
                self, "Text",
                "Cannot read file %s:\n%s." % (fileName, inFile.errorString()))
            return

        #data = QtCore.QTextStream(inFile)
        #self.line=data.readAll()
        inFile.close()
        self.painter.addData(fileName)

    #加载MissionPoint文件数据
    #getOpenFileNames()函数,可打开多个文件
    def openPoint(self):
        fileName = QtWidgets.QFileDialog.getOpenFileName(
            self, "加载数据", QtCore.QDir.currentPath(), "Files (*.txt *.csv)")[0]
        if not fileName:
            return

        inFile = QtCore.QFile(fileName)
        if not inFile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtWidgets.QMessageBox.warning(
                self, "Text",
                "Cannot read file %s:\n%s." % (fileName, inFile.errorString()))
            return
        inFile.close()
        self.painter.addPointData(fileName)
Exemple #8
0
        source_model.invisibleRootItem().appendRow(row)
        list.append("FancyTextNumber {}".format(i))

    # Needed by QMLModelViewClient
    role_names = {
        Qt.DisplayRole: QByteArray(b'_text'),
        Qt.BackgroundRole: QByteArray(b'_color')
    }
    source_model.setItemRoleNames(role_names)

    roles = [Qt.DisplayRole, Qt.BackgroundRole]

    print("Creating registry host")
    node = QRemoteObjectRegistryHost(QUrl("local:registry"))

    node2 = QRemoteObjectHost(QUrl("local:replica"), QUrl("local:registry"))
    node2.enableRemoting(source_model, "RemoteModel", roles)

    view = QTreeView()
    view.setWindowTitle("SourceView")
    view.setModel(source_model)
    view.show()
    handler = TimerHandler(source_model)
    QTimer.singleShot(5000, handler.change_data)
    QTimer.singleShot(10000, handler.insert_data)
    QTimer.singleShot(11000, handler.change_flags)
    QTimer.singleShot(12000, handler.remove_data)
    QTimer.singleShot(13000, handler.move_data)

    sys.exit(app.exec_())
Exemple #9
0
class ApplicationPage(QWidget):
    host: "Host"

    def __init__(self, host: "Host", **kwargs):
        super().__init__(**kwargs)
        self.host = host
        self.model = AppStoreModel(self, self.host.app_store)
        self._layout()

    def _layout(self):
        layout = QHBoxLayout(self)
        self.setLayout(layout)

        self.tree = QTreeView(self)
        self.tree.setModel(self.model)
        self.tree.setUniformRowHeights(True)
        self.tree.setColumnWidth(0, 200)
        self.tree.setDragEnabled(True)
        self.tree.setDragDropMode(QAbstractItemView.InternalMove)
        self.tree.viewport().setAcceptDrops(True)
        layout.addWidget(self.tree, 1)

        buttons = QVBoxLayout()
        buttons.setAlignment(Qt.AlignTop)

        add_button = QPushButton(QIcon.fromTheme("list-add"), "", self)
        add_button.setToolTip("Add application")
        add_button.clicked.connect(self.on_add)
        buttons.addWidget(add_button)

        mkdir_button = QPushButton(QIcon.fromTheme("folder-new"), "", self)
        mkdir_button.setToolTip("Make directory")
        mkdir_button.clicked.connect(self.on_mkdir)
        buttons.addWidget(mkdir_button)

        delete_button = QPushButton(QIcon.fromTheme("list-remove"), "", self)
        delete_button.setToolTip("Remove selected item")
        delete_button.clicked.connect(self.on_delete)
        buttons.addWidget(delete_button)

        layout.addLayout(buttons)

    def on_add(self):
        dialog = QInputDialog(self)
        dialog.setLabelText("Enter appconfig.json URL")

        if dialog.exec_() == QInputDialog.Rejected:
            return

        app_url = dialog.textValue().strip()
        self.host.app_store.add_app_ui([app_url])

    def on_mkdir(self):
        dialog = QInputDialog(self)
        dialog.setLabelText("Directory name")

        if dialog.exec_() == QInputDialog.Rejected:
            return

        dirname = dialog.textValue().strip()

        if not dirname or "/" in dirname:
            QMessageBox.critical(self, "Invalid input",
                                 "This directory name cannot be used")
            return

        self.host.app_store.mkdir(dirname)

    def on_delete(self):
        data = self.model.mimeData(self.tree.selectedIndexes())
        if not data:
            return

        data = json.loads(
            data.data("application/x-qabstractitemmodeldatalist").data())
        if data["type"] == "dir":
            confirm = QMessageBox.question(
                self,
                "Remove folder",
                f"Remove {data['id']}?\n\nAll applications will be moved to the top level",
            )
            if confirm == QMessageBox.StandardButton.No:
                return

            self.host.app_store.rmdir(data["id"])
        else:
            app = self.host.app_store[data["id"]]
            confirm = QMessageBox.question(
                self,
                "Remove application",
                f"Remove {app['appName']}?",
            )
            if confirm == QMessageBox.StandardButton.No:
                return

            self.host.app_store.remove_app(data["id"])
Exemple #10
0
class Snippets(QDialog):

    def __init__(self, parent=None):
        super(Snippets, self).__init__(parent)
        # Create widgets
        self.setWindowModality(Qt.NonModal)
        self.title = QLabel(self.tr("Snippet Editor"))
        self.saveButton = QPushButton(self.tr("Save"))
        self.revertButton = QPushButton(self.tr("Revert"))
        self.clearHotkeyButton = QPushButton(self.tr("Clear Hotkey"))
        self.setWindowTitle(self.title.text())
        self.newFolderButton = QPushButton("New Folder")
        self.deleteSnippetButton = QPushButton("Delete")
        self.newSnippetButton = QPushButton("New Snippet")
        self.edit = QPlainTextEdit()
        self.resetting = False
        self.columns = 3

        self.keySequenceEdit = QKeySequenceEdit(self)
        self.currentHotkey = QKeySequence()
        self.currentHotkeyLabel = QLabel("")
        self.currentFileLabel = QLabel()
        self.currentFile = ""
        self.snippetDescription = QLineEdit()
        self.snippetEditsPending = False

        self.clearSelection()

        #Set Editbox Size
        font = getMonospaceFont(self)
        self.edit.setFont(font)
        font = QFontMetrics(font)
        self.edit.setTabStopWidth(4 * font.width(' ')); #TODO, replace with settings API

        #Files
        self.files = QFileSystemModel()
        self.files.setRootPath(snippetPath)
        self.files.setNameFilters(["*.py"])

        #Tree
        self.tree = QTreeView()
        self.tree.setModel(self.files)
        self.tree.setSortingEnabled(True)
        self.tree.hideColumn(2)
        self.tree.sortByColumn(0, Qt.AscendingOrder)
        self.tree.setRootIndex(self.files.index(snippetPath))
        for x in range(self.columns):
            #self.tree.resizeColumnToContents(x)
            self.tree.header().setSectionResizeMode(x, QHeaderView.ResizeToContents) 
        treeLayout = QVBoxLayout()
        treeLayout.addWidget(self.tree)
        treeButtons = QHBoxLayout()
        treeButtons.addWidget(self.newFolderButton)
        treeButtons.addWidget(self.newSnippetButton)
        treeButtons.addWidget(self.deleteSnippetButton)
        treeLayout.addLayout(treeButtons)
        treeWidget = QWidget()
        treeWidget.setLayout(treeLayout)

        # Create layout and add widgets
        buttons = QHBoxLayout()
        buttons.addWidget(self.clearHotkeyButton)
        buttons.addWidget(self.keySequenceEdit)
        buttons.addWidget(self.currentHotkeyLabel)
        buttons.addWidget(self.revertButton)
        buttons.addWidget(self.saveButton)

        description = QHBoxLayout()
        description.addWidget(QLabel(self.tr("Description: ")))
        description.addWidget(self.snippetDescription)

        vlayoutWidget = QWidget()
        vlayout = QVBoxLayout()
        vlayout.addWidget(self.currentFileLabel)
        vlayout.addWidget(self.edit)
        vlayout.addLayout(description)
        vlayout.addLayout(buttons)
        vlayoutWidget.setLayout(vlayout)

        hsplitter = QSplitter()
        hsplitter.addWidget(treeWidget)
        hsplitter.addWidget(vlayoutWidget)

        hlayout = QHBoxLayout()
        hlayout.addWidget(hsplitter)

        self.showNormal() #Fixes bug that maximized windows are "stuck"
        self.settings = QSettings("Vector 35", "Snippet Editor")
        if self.settings.contains("ui/snippeteditor/geometry"):
            self.restoreGeometry(self.settings.value("ui/snippeteditor/geometry"))
        else:
            self.edit.setMinimumWidth(80 * font.averageCharWidth())
            self.edit.setMinimumHeight(30 * font.lineSpacing())

        # Set dialog layout
        self.setLayout(hlayout)

        # Add signals
        self.saveButton.clicked.connect(self.save)
        self.revertButton.clicked.connect(self.loadSnippet)
        self.clearHotkeyButton.clicked.connect(self.clearHotkey)
        self.tree.selectionModel().selectionChanged.connect(self.selectFile)
        self.newSnippetButton.clicked.connect(self.newFileDialog)
        self.deleteSnippetButton.clicked.connect(self.deleteSnippet)
        self.newFolderButton.clicked.connect(self.newFolder)

    def registerAllSnippets(self):
        for action in list(filter(lambda x: x.startswith("Snippet\\"), UIAction.getAllRegisteredActions())):
            UIActionHandler.globalActions().unbindAction(action)
            UIAction.unregisterAction(action)

        for snippet in includeWalk(snippetPath, ".py"):
            (snippetDescription, snippetKey, snippetCode) = loadSnippetFromFile(snippet)
            if not snippetDescription:
                actionText = "Snippet\\" + snippet
            else:
                actionText = "Snippet\\" + snippetDescription
            UIAction.registerAction(actionText, snippetKey)
            UIActionHandler.globalActions().bindAction(actionText, UIAction(makeSnippetFunction(snippetCode)))

    def clearSelection(self):
        self.keySequenceEdit.clear()
        self.currentHotkey = QKeySequence()
        self.currentHotkeyLabel.setText("")
        self.currentFileLabel.setText("")
        self.snippetDescription.setText("")
        self.edit.setPlainText("")

    def reject(self):
        self.settings.setValue("ui/snippeteditor/geometry", self.saveGeometry())

        if self.snippetChanged():
            question = QMessageBox.question(self, self.tr("Discard"), self.tr("You have unsaved changes, quit anyway?"))
            if question != QMessageBox.StandardButton.Yes:
                return
        self.accept()

    def newFolder(self):
        (folderName, ok) = QInputDialog.getText(self, self.tr("Folder Name"), self.tr("Folder Name: "))
        if ok and folderName:
            index = self.tree.selectionModel().currentIndex()
            selection = self.files.filePath(index)
            if QFileInfo(selection).isDir():
                QDir(selection).mkdir(folderName)
            else:
                QDir(snippetPath).mkdir(folderName)    

    def selectFile(self, new, old):
        if (self.resetting):
            self.resetting = False
            return
        newSelection = self.files.filePath(new.indexes()[0])
        if QFileInfo(newSelection).isDir():
            self.clearSelection()
            return

        if old.length() > 0:
            oldSelection = self.files.filePath(old.indexes()[0])
            if not QFileInfo(oldSelection).isDir() and self.snippetChanged():
                question = QMessageBox.question(self, self.tr("Discard"), self.tr("Snippet changed. Discard changes?"))
                if question != QMessageBox.StandardButton.Yes:
                    self.resetting = True
                    self.tree.selectionModel().select(old, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
                    return False

        self.currentFile = newSelection
        self.loadSnippet()

    def loadSnippet(self):
        self.currentFileLabel.setText(QFileInfo(self.currentFile).baseName())
        log_debug("Loading %s as a snippet." % self.currentFile)
        (snippetDescription, snippetKey, snippetCode) = loadSnippetFromFile(self.currentFile)
        self.snippetDescription.setText(snippetDescription) if snippetDescription else self.snippetDescription.setText("")
        self.keySequenceEdit.setKeySequence(snippetKey[0]) if len(snippetKey) != 0 else self.keySequenceEdit.setKeySequence(QKeySequence(""))
        self.edit.setPlainText(snippetCode) if snippetCode else self.edit.setPlainText("")

    def newFileDialog(self):
        (snippetName, ok) = QInputDialog.getText(self, self.tr("Snippet Name"), self.tr("Snippet Name: "))
        if ok and snippetName:
            if not snippetName.endswith(".py"):
                snippetName += ".py"
            index = self.tree.selectionModel().currentIndex()
            selection = self.files.filePath(index)
            if QFileInfo(selection).isDir():
                open(os.path.join(selection, snippetName), "w").close()
            else:
                open(os.path.join(snippetPath, snippetName), "w").close()
            log_debug("Snippet %s created." % snippetName)

    def deleteSnippet(self):
        selection = self.tree.selectedIndexes()[::self.columns][0] #treeview returns each selected element in the row
        snippetName = self.files.fileName(selection)
        question = QMessageBox.question(self, self.tr("Confirm"), self.tr("Confirm deletion: ") + snippetName)
        if (question == QMessageBox.StandardButton.Yes):
            log_debug("Deleting snippet %s." % snippetName)
            self.clearSelection()
            self.files.remove(selection)

    def snippetChanged(self):
        if (self.currentFile == "" or QFileInfo(self.currentFile).isDir()):
            return False
        (snippetDescription, snippetKey, snippetCode) = loadSnippetFromFile(self.currentFile)
        if (not snippetCode):
            return False
        if len(snippetKey) == 0 and not self.keySequenceEdit.keySequence().isEmpty():
            return True
        if len(snippetKey) != 0 and snippetKey[0] != self.keySequenceEdit.keySequence():
            return True
        return self.edit.toPlainText() != snippetCode or \
               self.snippetDescription.text() != snippetDescription

    def save(self):
        log_debug("Saving snippet %s" % self.currentFile)
        outputSnippet = open(self.currentFile, "w")
        outputSnippet.write("#" + self.snippetDescription.text() + "\n")
        outputSnippet.write("#" + self.keySequenceEdit.keySequence().toString() + "\n")
        outputSnippet.write(self.edit.toPlainText())
        outputSnippet.close()
        self.registerAllSnippets()

    def clearHotkey(self):
        self.keySequenceEdit.clear()
Exemple #11
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # SET => App Icon
        self.icon = QIcon("img/iconXLNK.png")
        # End

        self.tree_view = None
        self.file_system_model = None

        # SET => Window Icon
        self.setWindowIcon(self.icon)
        # End

        # WSET => Window Title
        self.setWindowTitle("XLNK | Data Manager")
        # End

        # Menus
        self.menu = self.menuBar()
        self.file_menu = self.menu.addMenu("&File")
        self.edit_menu = self.menu.addMenu("&Edit")
        self.view_menu = self.menu.addMenu("&View")
        self.help_menu = self.menu.addMenu("&Help")
        # End

        # ===================
        # Menu Button Actions

        # Exit QAction
        exit_action = QAction("Exit", self)
        exit_action.setShortcut(QKeySequence.Quit)
        exit_action.triggered.connect(self.close)
        self.file_menu.addAction(exit_action)
        # End
        # End

        # Tool Bar
        toolbar = QToolBar(self)
        self.addToolBar(toolbar)

        # delete action on toolbar
        delete_action_tb = QAction("DELETE TABLE ROW", self)
        delete_action_tb.setStatusTip("Obrisi Red U Tabeli")
        delete_action_tb.triggered.connect(self.delete_table_row_tb)
        toolbar.addAction(delete_action_tb)

        # Dock Widget
        dock_widget = QDockWidget("EXPLORER", self)
        # File System Model
        self.file_system_model = QFileSystemModel()
        self.file_system_model.setRootPath(QDir.currentPath())
        # SET => Tree View MOdel
        self.tree_view = QTreeView()
        self.tree_view.setModel(self.file_system_model)
        self.tree_view.setRootIndex(
            self.file_system_model.index(QDir.currentPath() + "/data"))
        self.tree_view.clicked.connect(self.file_clicked_handler)
        dock_widget.setWidget(self.tree_view)
        dock_widget.setFloating(False)
        self.addDockWidget(Qt.LeftDockWidgetArea, dock_widget)

        # QLabel
        qlabel = QLabel(self)
        qlabel.setText("Welcome to XLNK.")

        # Central Widget
        self.clicked_file = None

        self.setCentralWidget(qlabel)

        self.showMaximized()

    # ToolBar Functions
    # TODO
    def delete_table_row_tb(self):
        print("Ugraditi funkciju za brisanje reda iz tabele.")

    def file_clicked_handler(self, index):
        index = self.tree_view.currentIndex()
        file_clicked_param = os.path.basename(
            self.file_system_model.filePath(index))
        self.clicked_file = file_clicked_param
        self.status_bar = QStatusBar(self)
        self.status_bar.showMessage(
            "File Selected: {}".format(file_clicked_param), 3000)
        self.setStatusBar(self.status_bar)
        self.workspace_widget = WorkSpaceWidget(self, self.clicked_file)
        self.setCentralWidget(self.workspace_widget)
Exemple #12
0
class MyWidget(QtWidgets.QWidget):
    @Slot()
    def run_report(self):
        dialog = ReportNameDialog()
        if dialog.exec_():
            metadata_fields = {}
            item_model = self.list.model()
            for i in range(item_model.rowCount()):
                qmodel_index = item_model.index(i, 0)
                index_name = item_model.item(i, 0).text()
                if item_model.itemData(qmodel_index).get(10) == 2:
                    metadata_fields[index_name] = ""
                    if hasattr(item_model.item(i, 1), "text"):
                        index_value = item_model.item(i, 1).text()
                        if index_name == DOCUMENT_TYPE:
                            if index_value == TYPE_ASSET:
                                index_value = "IO"
                            if index_value == TYPE_FOLDER:
                                index_value = "SO"
                            if index_value == TYPE_ANY:
                                index_value = ""
                        metadata_fields[index_name] = index_value

            self.progress = QProgressDialog(
                "Creating Report\n\nPlease Wait...", None, 0, 100)
            self.progress.setModal(True)
            self.progress.setWindowTitle("Report")
            self.progress.setAutoClose(True)
            self.progress.setAutoReset(True)
            self.callback = CallBack()
            worker = Worker(self.client, self.search_value.text(),
                            dialog.report(), metadata_fields, self.callback,
                            dialog.auto_report())
            self.callback.change_value.connect(self.progress.setValue)
            self.callback.max_value.connect(self.progress.setMaximum)
            self.callback.reset_dialog.connect(self.progress.reset)
            self.threadpool.start(worker)

            self.progress.show()

    def __init__(self):
        super().__init__()
        self.threadpool = QThreadPool()
        self.threadpool.setMaxThreadCount(1)
        self.setWindowTitle("Preservica Solr Reporting")
        self.windowModality()
        self.progress = None
        self.callback = None

        self.search_label = QtWidgets.QLabel(
            "Main Search Term (% returns everything)")
        self.search_value = QtWidgets.QLineEdit("%")

        self.help_label = QtWidgets.QLabel(
            "Select from the list of indexed fields below to "
            "add columns to the output spreadsheet\n\n"
            "Indexes can have an optional filter term. Filters "
            "are only applied to selected fields")

        self.list = QTreeView()
        self.list.setSelectionBehavior(QAbstractItemView.SelectRows)
        model = QStandardItemModel()
        model.setHorizontalHeaderLabels(['Index Name', 'Index Filter Term'])
        self.list.setModel(model)
        self.list.setUniformRowHeights(True)
        self.list.setAlternatingRowColors(True)
        self.list.setColumnWidth(0, 350)
        self.list.setColumnWidth(1, 250)

        self.list.setItemDelegateForColumn(
            1, ComboDelegate(self.list, DOCUMENT_TYPE, model))

        if not os.path.isfile("credentials.properties"):
            dialog = PasswordDialog()
            if dialog.exec_():
                self.client = ContentAPI(dialog.username(), dialog.password(),
                                         dialog.tenant(), dialog.server())
            else:
                raise SystemExit
        else:
            self.client = ContentAPI()

        for index_name in self.client.indexed_fields():
            if index_name == "xip.full_text":
                continue
            index = QStandardItem(index_name)
            index.setCheckable(True)
            index.setEditable(False)

            model.appendRow([index])

        self.run_report_button = QtWidgets.QPushButton("Run Report")
        self.run_report_button.released.connect(self.run_report)

        self.list.setModel(model)
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.search_label)
        self.layout.addWidget(self.search_value)
        self.layout.addWidget(self.help_label)
        self.layout.addWidget(self.list)
        self.layout.addWidget(self.run_report_button)
        self.setLayout(self.layout)
Exemple #13
0
class BindiffViewerDialog(QDialog):
	def __init__(self, bv, match_db, role, primary_be, secondary_be):
		super(BindiffViewerDialog, self).__init__()

		self.bv = bv
		self.primary_be = primary_be
		self.secondary_be = secondary_be
		self.role = role

		# UI
		self.match_model = BindiffMatchModel(bv, match_db, role, primary_be, secondary_be)

		self.match_view = QTreeView()
		self.match_view.setModel(self.match_model)

		self.match_view.setSelectionMode(QTreeView.ExtendedSelection)

		self.match_view.setContextMenuPolicy(Qt.CustomContextMenu)
		self.match_view.customContextMenuRequested.connect(self.match_view_context_menu_requested)
		self.match_view.doubleClicked.connect(self.match_view_double_clicked)

		self.match_view.setRootIsDecorated(False)
		self.match_view.setFont(binaryninjaui.getMonospaceFont(self))

		for i in range(len(self.match_model.column_infos)):
			self.match_view.resizeColumnToContents(i)

		self.match_view.setSortingEnabled(True)
		self.match_view.sortByColumn(0, Qt.AscendingOrder)

		layout = QVBoxLayout()
		layout.addWidget(self.match_view)

		self.setLayout(layout)
		self.setWindowTitle("BinDiff Viewer")
		self.resize(1000, 640)
		flags = self.windowFlags()
		flags |= Qt.WindowMaximizeButtonHint
		flags &= ~Qt.WindowContextHelpButtonHint
		self.setWindowFlags(flags)

	def match_view_double_clicked(self, index):
		if not index.isValid():
			assert(False)
			return
		if self.role == None:
			return

		entry = self.match_model.entries[index.row()]
		if self.role == 0:
			address = entry["address1"]
		elif self.role == 1:
			address = entry["address2"]
		else:
			assert(False)

		self.bv.navigate(self.bv.file.view, address)

	def match_view_context_menu_requested(self, pos):
		if self.role == None:
			return

		selected_indices = self.match_view.selectionModel().selectedIndexes()

		# This may return each row multiple times, so we uniquify
		selected = set([i.row() for i in selected_indices])

		def action_port_symbols():
			for i in selected:
				self.port_symbols(i)

		menu = QMenu(self.match_view)
		menu.addAction("Port symbols", action_port_symbols)
		menu.exec_(self.match_view.mapToGlobal(pos))

	def port_symbols(self, i):
		if self.role == None:
			return

		entry = self.match_model.entries[i]
		target_index = self.role
		source_index = 1 if target_index == 0 else 0

		source_name = entry["name{}".format(source_index + 1)]
		target_address = entry["address{}".format(target_index + 1)]

		old_sym = self.bv.get_symbol_at(target_address)

		target_name = None
		if old_sym:
			target_name = old_sym.name
		target_text = target_name if target_name else "<unnamed>"

		if not source_name:
			bn.log_warn("Port symbols: {} @ {:x} has no source name, skipping".format(target_text, target_address))
			return

		if old_sym and not old_sym.auto:
			bn.log_warn("Port symbols: {} @ {:x} is already named, skipping".format(target_text, target_address))
			return

		bn.log_info("Port symbols: {} @ {:x} -> {}".format(target_text, target_address, source_name))
		new_sym = bn.Symbol(bn.SymbolType.FunctionSymbol, target_address, source_name)
		self.bv.define_user_symbol(new_sym)
Exemple #14
0
class ComponentTreeViewTab(QWidget):
    def __init__(self, parent=None):
        super().__init__()
        self.setLayout(QVBoxLayout())
        self.setParent(parent)
        self.componentsTabLayout = QVBoxLayout()
        self.component_tree_view = QTreeView()
        self.componentsTabLayout.addWidget(self.component_tree_view)
        self.layout().addLayout(self.componentsTabLayout)

        self.component_tree_view.setDragEnabled(True)
        self.component_tree_view.setAcceptDrops(True)
        self.component_tree_view.setDropIndicatorShown(True)
        self.component_tree_view.header().hide()
        self.component_tree_view.updateEditorGeometries()
        self.component_tree_view.updateGeometries()
        self.component_tree_view.updateGeometry()
        self.component_tree_view.clicked.connect(self._set_button_state)
        self.component_tree_view.setSelectionMode(QAbstractItemView.SingleSelection)

        self.component_tool_bar = QToolBar("Actions", self)
        self.new_component_action = create_and_add_toolbar_action(
            "new_component.png",
            "New Component",
            self.parent().show_add_component_window,
            self.component_tool_bar,
            self,
            True,
        )
        self.new_translation_action = create_and_add_toolbar_action(
            "new_translation.png",
            "New Translation",
            lambda: self._add_transformation(TransformationType.TRANSLATION),
            self.component_tool_bar,
            self,
        )
        self.new_rotation_action = create_and_add_toolbar_action(
            "new_rotation.png",
            "New Rotation",
            lambda: self._add_transformation(TransformationType.ROTATION),
            self.component_tool_bar,
            self,
        )
        self.create_link_action = create_and_add_toolbar_action(
            "create_link.png",
            "Create Link",
            self.on_create_link,
            self.component_tool_bar,
            self,
        )
        self.duplicate_action = create_and_add_toolbar_action(
            "duplicate.png",
            "Duplicate",
            self.on_duplicate_node,
            self.component_tool_bar,
            self,
        )
        self.edit_component_action = create_and_add_toolbar_action(
            "edit_component.png",
            "Edit Component",
            self.parent().show_edit_component_dialog,
            self.component_tool_bar,
            self,
        )
        self.delete_action = create_and_add_toolbar_action(
            "delete.png", "Delete", self.on_delete_item, self.component_tool_bar, self
        )
        self.zoom_action = create_and_add_toolbar_action(
            "zoom.svg",
            "Zoom To Component",
            self.on_zoom_item,
            self.component_tool_bar,
            self,
        )
        self.component_tool_bar.insertSeparator(self.zoom_action)
        self.componentsTabLayout.insertWidget(0, self.component_tool_bar)

    def set_up_model(self, instrument):
        self.component_model = ComponentTreeModel(instrument)
        self.component_delegate = ComponentEditorDelegate(
            self.component_tree_view, instrument
        )
        self.component_tree_view.setItemDelegate(self.component_delegate)
        self.component_tree_view.setModel(self.component_model)

    def _set_button_state(self):
        set_button_states(
            self.component_tree_view,
            self.delete_action,
            self.duplicate_action,
            self.new_rotation_action,
            self.new_translation_action,
            self.create_link_action,
            self.zoom_action,
            self.edit_component_action,
        )

    def on_create_link(self):
        selected = self.component_tree_view.selectedIndexes()
        if len(selected) > 0:
            self.component_model.add_link(selected[0])
            self._expand_transformation_list(selected[0])
            self._set_button_state()

    def on_duplicate_node(self):
        selected = self.component_tree_view.selectedIndexes()
        if len(selected) > 0:
            self.component_model.duplicate_node(selected[0])
            self._expand_transformation_list(selected[0])

    def _expand_transformation_list(self, node: QModelIndex):
        expand_transformation_list(node, self.component_tree_view, self.component_model)

    def _add_transformation(self, transformation_type: TransformationType):
        add_transformation(
            transformation_type, self.component_tree_view, self.component_model
        )

    def on_delete_item(self):
        selected = self.component_tree_view.selectedIndexes()
        for item in selected:
            self.component_model.remove_node(item)
        self._set_button_state()

    def on_zoom_item(self):
        selected = self.component_tree_view.selectedIndexes()[0]
        component = selected.internalPointer()
        self.sceneWidget.zoom_to_component(
            self.sceneWidget.get_entity(component.name), self.sceneWidget.view.camera()
        )
Exemple #15
0
            return self.createIndex(row, column, childItem)
        else:
            return QModelIndex()

    def parent(self, index):
        if not index.isValid():
            return QModelIndex()

        childItem = index.internalPointer()
        if not childItem:
            return QModelIndex()

        parentItem = childItem.parent()

        if parentItem == self.rootItem:
            return QModelIndex()

        return self.createIndex(parentItem.row(), 0, parentItem)


if __name__ == "__main__":
    # http://blog.mathieu-leplatre.info/filesystem-watch-with-pyqt4.html
    import sys

    # app = QApplication(sys.argv)
    TreeView = QTreeView()
    TreeModel = NodeTree(
        TreeView, [['A', ['a', 1], ['b', ['c', 1]]], ['C', 'D'], ['E', 'F']])
    TreeView.setModel(TreeModel)
    TreeView.show()
    # app.exec_()
Exemple #16
0
class ExportDialog(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.model = ExportChangesModel()
        self.error_dialog = None
        self.setWindowIcon(QIcon("paragon.ico"))
        self.setWindowTitle("Export")

        main_layout = QVBoxLayout(self)
        self.export_button = QPushButton()
        self.export_button.setText("Export")
        self.main_view = QTreeView()
        self.main_view.setModel(self.model)
        self.main_view.setHeaderHidden(True)
        self.main_view.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        self.remember_selections_checkbox = QCheckBox()
        self.remember_selections_checkbox.setText("Remember selections.")
        main_layout.addWidget(self.export_button)
        main_layout.addWidget(self.main_view)
        main_layout.addWidget(self.remember_selections_checkbox)
        self.setLayout(main_layout)

        self.main_view.expanded.connect(self._on_item_expanded)
        self.export_button.clicked.connect(self._on_export_triggered)
        self.remember_selections_checkbox.stateChanged.connect(
            self._on_remember_selections_state_changed)

        self._set_remember_checkbox_state_from_settings()

    def _set_remember_checkbox_state_from_settings(self):
        settings_service = locator.get_static("SettingsService")
        if settings_service.get_remember_exports():
            self.remember_selections_checkbox.setCheckState(QtCore.Qt.Checked)

    @staticmethod
    def _on_remember_selections_state_changed(state: int):
        should_remember = state == QtCore.Qt.Checked
        locator.get_static("SettingsService").set_remember_exports(
            should_remember)

    def closeEvent(self, event: QtGui.QCloseEvent):
        self.model.save_selected_items_tree()
        event.accept()

    def _on_export_triggered(self):
        file_name, ok = QFileDialog.getSaveFileName(
            self, caption="Select Changes File Destination", filter="*.json")
        if ok:
            self._try_export_and_write(file_name)

    def _try_export_and_write(self, file_name):
        logging.debug("Exporting selected data to %s" % file_name)
        try:
            export_data = self.model.export_selected_items()
            with open(file_name, "w", encoding="utf-8") as f:
                json.dump(export_data, f, indent=4, ensure_ascii=False)
        except:
            logging.exception("An error occurred while exporting data.")
            self.error_dialog = ErrorDialog(
                "An error occurred while exporting. See the log for details.")
            self.error_dialog.show()

    def _on_item_expanded(self, index: QModelIndex):
        self.model.update_data_for_index(index)
Exemple #17
0
class CatsTreeWindow(PBDialog):
    """Extension of `PBDialog` that shows the categories tree"""
    def __init__(
        self,
        parent=None,
        askCats=False,
        askForBib=None,
        askForExp=None,
        expButton=True,
        previous=[],
        single=False,
        multipleRecords=False,
    ):
        """Initialize instance parameters and call the function that
        creates the layout.

        Parameters:
            parent (default None): the parent widget
            askCats (default False): if True, enable checkboxes for
                selection of categories
            askForBib (default None): the optional key which identifies
                in the database the bibtex entry for which categories
                are being selected
            askForExp (default None): the optional ID which identifies
                in the database the experiment for which categories
                are being selected
            expButton (default True): if True, add a button to accept
                the widget content and later ask for experiments
            previous (default []): the list of categories that
                must be selected at the beginning
            single (default False): if True, only allow the selection
                of a single category (the parent category, typically).
                Multiple checkboxes can be selected,
                but only the first one will be considered
            multipleRecords: used when dealing with categories
                corresponding to multiple records. Activate a tristate
                checkbox for the initial list of categories, which are
                typically not the same for all the elements in the list
        """
        PBDialog.__init__(self, parent)
        self.setWindowTitle(cwstr.cats)
        self.currLayout = QVBoxLayout(self)
        self.setLayout(self.currLayout)
        self.askCats = askCats
        self.askForBib = askForBib
        self.askForExp = askForExp
        self.expButton = expButton
        self.previous = previous
        self.single = single
        self.multipleRecords = multipleRecords
        self.result = False
        self.marked = []
        self.root_model = None
        self.proxyModel = None
        self.tree = None
        self.menu = None
        self.timer = None
        self.expsButton = None
        self.filterInput = None
        self.newCatButton = None
        self.acceptButton = None
        self.cancelButton = None

        self.setMinimumWidth(400)
        self.setMinimumHeight(600)

        self.createForm()

    def populateAskCat(self):
        """If selection of categories is allowed, add some information
        on the bibtex/experiment for which the categories are requested
        and a simple message, then create few required empty lists
        """
        if self.askCats:
            if self.askForBib is not None:
                try:
                    bibitem = pBDB.bibs.getByBibkey(self.askForBib,
                                                    saveQuery=False)[0]
                except IndexError:
                    pBGUILogger.warning(
                        cwstr.entryNotInDb % self.askForBib,
                        exc_info=True,
                    )
                    return
                try:
                    if bibitem["inspire"] != "" and bibitem[
                            "inspire"] is not None:
                        link = "<a href='%s'>%s</a>" % (
                            pBView.getLink(self.askForBib, "inspire"),
                            self.askForBib,
                        )
                    elif bibitem["arxiv"] != "" and bibitem[
                            "arxiv"] is not None:
                        link = "<a href='%s'>%s</a>" % (
                            pBView.getLink(self.askForBib, "arxiv"),
                            self.askForBib,
                        )
                    elif bibitem["doi"] != "" and bibitem["doi"] is not None:
                        link = "<a href='%s'>%s</a>" % (
                            pBView.getLink(self.askForBib, "doi"),
                            self.askForBib,
                        )
                    else:
                        link = self.askForBib
                    bibtext = PBLabel(
                        cwstr.markCatBibKAT %
                        (link, bibitem["author"], bibitem["title"]))
                except KeyError:
                    bibtext = PBLabel(cwstr.markCatBibK % (self.askForBib))
                self.currLayout.addWidget(bibtext)
            elif self.askForExp is not None:
                try:
                    expitem = pBDB.exps.getByID(self.askForExp)[0]
                except IndexError:
                    pBGUILogger.warning(
                        cwstr.expNotInDb % self.askForExp,
                        exc_info=True,
                    )
                    return
                try:
                    exptext = PBLabel(
                        cwstr.markCatExpINC %
                        (self.askForExp, expitem["name"], expitem["comments"]))
                except KeyError:
                    exptext = PBLabel(cwstr.markCatExpI % (self.askForExp))
                self.currLayout.addWidget(exptext)
            else:
                if self.single:
                    comment = PBLabel(cwstr.selectCat)
                else:
                    comment = PBLabel(cwstr.selectCats)
                self.currLayout.addWidget(comment)
            self.marked = []
            self.parent().selectedCats = []
        return True

    def onCancel(self):
        """Reject the dialog content and close the window"""
        self.result = False
        self.close()

    def onOk(self, exps=False):
        """Accept the dialog content
        (update the list of selected categories)
        and close the window.
        May set `self.result` to "Exps"
        for later opening of a new dialog to ask for experiments.

        Parameter:
            exps (default False): if True, set the result to "Exps",
                otherwise to "Ok"
        """
        self.parent().selectedCats = [
            idC for idC in self.root_model.selectedCats.keys()
            if self.root_model.selectedCats[idC] == True
        ]
        self.parent().previousUnchanged = [
            idC for idC in self.root_model.previousSaved.keys()
            if self.root_model.previousSaved[idC] == True
        ]

        if (self.single and len(self.parent().selectedCats) > 1
                and self.parent().selectedCats[0] == 0):
            self.parent().selectedCats.pop(0)
            self.parent().selectedCats = [self.parent().selectedCats[0]]
        self.result = "Exps" if exps else "Ok"
        self.close()

    def changeFilter(self, string):
        """When the filter `QLineEdit` is changed,
        update the `LeafFilterProxyModel` regexp filter

        Parameter:
            string: the new filter string
        """
        self.proxyModel.setFilterRegExp(str(string))
        self.tree.expandAll()

    def onAskExps(self):
        """Action to perform when the selection of categories
        will be folloed by the selection of experiments.
        Call `self.onOk` with `exps = True`.
        """
        self.onOk(exps=True)

    def onNewCat(self):
        """Action to perform when the creation
        of a new category is requested
        """
        editCategory(self, self.parent())

    def keyPressEvent(self, e):
        """Manage the key press events.
        Do nothing unless `Esc` is pressed:
        in this case close the dialog
        """
        if e.key() == Qt.Key_Escape:
            self.close()

    def createForm(self):
        """Create the dialog content, connect the model to the view
        and eventually add the buttons at the end
        """
        self.populateAskCat()

        catsTree = pBDB.cats.getHier()

        self.filterInput = QLineEdit("", self)
        self.filterInput.setPlaceholderText(cwstr.filterCat)
        self.filterInput.textChanged.connect(self.changeFilter)
        self.currLayout.addWidget(self.filterInput)
        self.filterInput.setFocus()

        self.tree = QTreeView(self)
        self.currLayout.addWidget(self.tree)
        self.tree.setMouseTracking(True)
        self.tree.entered.connect(self.handleItemEntered)
        self.tree.doubleClicked.connect(self.cellDoubleClick)
        self.tree.setExpandsOnDoubleClick(False)

        catsNamedTree = self._populateTree(catsTree[0], 0)

        self.root_model = CatsModel(
            pBDB.cats.getAll(),
            [catsNamedTree],
            self,
            self.previous,
            multipleRecords=self.multipleRecords,
        )
        self.proxyModel = LeafFilterProxyModel(self)
        self.proxyModel.setSourceModel(self.root_model)
        self.proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.proxyModel.setSortCaseSensitivity(Qt.CaseInsensitive)
        self.proxyModel.setFilterKeyColumn(-1)
        self.tree.setModel(self.proxyModel)

        self.tree.expandAll()

        self.tree.setHeaderHidden(True)
        # self.tree.doubleClicked.connect(self.askAndPerformAction)

        self.newCatButton = QPushButton(cwstr.addNew, self)
        self.newCatButton.clicked.connect(self.onNewCat)
        self.currLayout.addWidget(self.newCatButton)

        if self.askCats:
            self.acceptButton = QPushButton(cwstr.ok, self)
            self.acceptButton.clicked.connect(self.onOk)
            self.currLayout.addWidget(self.acceptButton)

            if self.expButton:
                self.expsButton = QPushButton(cwstr.askExp, self)
                self.expsButton.clicked.connect(self.onAskExps)
                self.currLayout.addWidget(self.expsButton)

            # cancel button
            self.cancelButton = QPushButton(cwstr.cancel, self)
            self.cancelButton.clicked.connect(self.onCancel)
            self.cancelButton.setAutoDefault(True)
            self.currLayout.addWidget(self.cancelButton)

    def _populateTree(self, children, idCat):
        """Read the list of categories recursively and
        populate the categories tree

        Parameters:
            children: the list of children categories
                of the currently considered one
            idCat: the id of the current category
        """
        name = pBDB.cats.getByID(idCat)[0]["name"]
        children_list = []
        for child in cats_alphabetical(children, pBDB):
            child_item = self._populateTree(children[child], child)
            children_list.append(child_item)
        return NamedElement(idCat, name, children_list)

    def handleItemEntered(self, index):
        """Process event when mouse enters an item and
        create a `QTooltip` which describes the category, with a timer

        Parameter:
            index: a `QModelIndex` instance
        """
        if index.isValid():
            row = index.row()
        else:
            return
        try:
            idString = self.proxyModel.sibling(row, 0, index).data()
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        try:
            idCat, catName = idString.split(": ")
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        idCat = idCat.strip()
        try:
            self.timer.stop()
            QToolTip.showText(QCursor.pos(), "", self.tree.viewport())
        except AttributeError:
            pass
        try:
            catData = pBDB.cats.getByID(idCat)[0]
        except IndexError:
            pBGUILogger.exception(cwstr.failedFind)
            return
        self.timer = QTimer(self)
        self.timer.setSingleShot(True)
        self.timer.timeout.connect(lambda: QToolTip.showText(
            QCursor.pos(),
            cwstr.catId.format(idC=idCat, cat=catData["name"]) + cwstr.
            entriesCorrespondent.format(en=pBDB.catBib.countByCat(idCat)) +
            cwstr.expsAssociated.format(ex=pBDB.catExp.countByCat(idCat)),
            self.tree.viewport(),
            self.tree.visualRect(index),
            3000,
        ))
        self.timer.start(500)

    def contextMenuEvent(self, event):
        """Create a right click menu with few actions
        on the selected category

        Parameter:
            event: a `QEvent`
        """
        indexes = self.tree.selectedIndexes()
        try:
            index = indexes[0]
        except IndexError:
            pBLogger.debug(cwstr.clickMissingIndex)
            return
        if index.isValid():
            row = index.row()
        else:
            return
        try:
            idString = self.proxyModel.sibling(row, 0, index).data()
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        try:
            idCat, catName = idString.split(": ")
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        idCat = idCat.strip()

        menu = PBMenu()
        self.menu = menu
        titAction = QAction(cwstr.catDescr % catName)
        titAction.setDisabled(True)
        bibAction = QAction(cwstr.openEntryList)
        modAction = QAction(cwstr.modify)
        delAction = QAction(cwstr.delete)
        subAction = QAction(cwstr.addSub)
        menu.possibleActions = [
            titAction,
            None,
            bibAction,
            None,
            modAction,
            delAction,
            None,
            subAction,
        ]
        menu.fillMenu()

        action = menu.exec_(event.globalPos())

        if action == bibAction:
            self.parent().reloadMainContent(pBDB.bibs.getByCat(idCat))
        elif action == modAction:
            editCategory(self, self.parent(), idCat)
        elif action == delAction:
            deleteCategory(self, self.parent(), idCat, catName)
        elif action == subAction:
            editCategory(self, self.parent(), useParentCat=idCat)
        return

    def cellDoubleClick(self, index):
        """Process event when mouse double clicks an item.
        Opens a link if some columns

        Parameter:
            index: a `QModelIndex` instance
        """
        if index.isValid():
            row = index.row()
            col = index.column()
        else:
            return
        try:
            idString = self.proxyModel.sibling(row, 0, index).data()
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        try:
            idCat, catName = idString.split(": ")
        except AttributeError:
            pBLogger.debug("", exc_info=True)
            return
        idCat = idCat.strip()
        self.parent().reloadMainContent(pBDB.bibs.getByCat(idCat))
        return

    def recreateTable(self):
        """Delete the previous widgets and recreate them with new data"""
        self.cleanLayout()
        self.createForm()
Exemple #18
0
class RssTab(QWidget):
    new_torrents = Signal(int)

    def __init__(self):
        QWidget.__init__(self)
        layout = QVBoxLayout(self)
        self.splitter = QSplitter(self)
        self.cats = QTreeView(self)
        self.cats.setSortingEnabled(True)
        self.cat_model = RssCategoryModel()
        proxy = QSortFilterProxyModel()
        proxy.setSourceModel(self.cat_model)
        self.cats.setModel(proxy)
        self.splitter.addWidget(self.cats)
        self.t = QTableWidget(0, 4, self)
        self.splitter.addWidget(self.t)
        self.stats = [QLabel('{}'.format(datetime.now())) for _ in range(8)]

        stat: QLabel
        for stat in self.stats:
            stat.setFont(QFont(pointSize=14))
            layout.addWidget(stat, 0, Qt.AlignTop)

        layout.addWidget(self.splitter, 0, Qt.AlignTop)

        self.ds = DataSource()
        self.f_model = ForumsModel(self.ds.get_forums())
        self.forums = QTableView(self)
        self.forums.setModel(self.f_model)
        self.forums.resizeColumnsToContents()
        layout.addWidget(self.forums, 10, Qt.AlignTop)

        self.setLayout(layout)

        self.worker = RssWorker()
        self.worker_thread = QThread()
        self.worker_thread.started.connect(self.worker.run)
        self.worker.finished.connect(self.worker_thread.quit)
        self.worker.moveToThread(self.worker_thread)
        self.worker_thread.start()
        self.worker.processed.connect(self.processed)
        self.worker.current.connect(self.current)

    @Slot(str)
    def current(self, topic):
        for i in range(len(self.stats) - 1):
            self.stats[i].setText(self.stats[i + 1].text())
        self.stats[len(self.stats) - 1].setText('{0} - {1}'.format(
            datetime.now(), topic))

    @Slot(int, int)
    def processed(self, forum_id, torrents):
        print('\t\t\tRSS: ' + str(forum_id) + ', ' + str(torrents))
        forum = self.ds.get_forum(forum_id)
        print('\t\t\tRSS FORUM: ' + str(forum))
        cat = self.ds.get_category(forum['category'])
        print('\t\t\tRSS CAT: ' + str(cat))
        self.cat_model.addCategory(cat['title'], torrents)

    def finish(self):
        self.worker.finish()
        self.worker_thread.quit()
        self.worker_thread.wait()
Exemple #19
0
import sys
from PySide2.QtWidgets import QApplication, QSplitter, QFileSystemModel, QTreeView, QListView
from PySide2.QtCore import QDir

if __name__ == '__main__':
    app = QApplication(sys.argv)
    splitter = QSplitter()
    model = QFileSystemModel()
    model.setRootPath("/")
    tree = QTreeView(splitter)
    tree.setModel(model)
    tree.setRootIndex(model.index("/"))
    list = QListView(splitter)
    list.setModel(model)
    list.setRootIndex(model.index("/"))
    splitter.setWindowTitle(
        "A model with two views or two views with one model")
    splitter.show()
    app.exec_()
Exemple #20
0
    def create_ui(self):
        """Setup main UI elements, dock widgets, UI-related elements, etc.
        """

        log.debug('Loading UI')

        # Undo Stack
        self.undo_stack = QUndoStack(self)
        self.undo_stack.setUndoLimit(100)

        # Object navigation history
        self.obj_history = deque([], config.MAX_OBJ_HISTORY)

        app = QApplication.instance()
        base_font = QFont()
        base_font.fromString(self.prefs['base_font'])
        app.setFont(base_font)

        # Object class table widget
        # classTable = QTableView(self)
        classTable = classtable.TableView(self)
        classTable.setObjectName("classTable")
        classTable.setAlternatingRowColors(True)
        classTable.setFrameShape(QFrame.StyledPanel)
        classTable_font = QFont()
        classTable_font.fromString(self.prefs['class_table_font'])
        classTable.setFont(classTable_font)
        fm = classTable.fontMetrics()
        classTable.setWordWrap(True)
        classTable.setEditTriggers(QAbstractItemView.EditKeyPressed |
                                   QAbstractItemView.DoubleClicked |
                                   QAbstractItemView.AnyKeyPressed |
                                   QAbstractItemView.SelectedClicked)
        # classTable.horizontalHeader().setMovable(True)
        # classTable.verticalHeader().setMovable(False)
        classTable.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
        classTable.verticalHeader().setSectionResizeMode(QHeaderView.Interactive)
        classTable.horizontalHeader().setDefaultSectionSize(self.prefs['default_column_width'])
        classTable.verticalHeader().setDefaultSectionSize(fm.height() + 0)
        classTable.setSelectionMode(QAbstractItemView.ExtendedSelection)
        classTable.setContextMenuPolicy(Qt.CustomContextMenu)
        classTable.customContextMenuRequested.connect(self.custom_table_context_menu)

        # Create table model and proxy layers for transposing and filtering
        self.classTableModel = classtable.IDFObjectTableModel(classTable)
        self.transposeableModel = classtable.TransposeProxyModel(self.classTableModel)
        self.transposeableModel.setSourceModel(self.classTableModel)
        self.sortableModel = classtable.SortFilterProxyModel(self.transposeableModel)
        self.sortableModel.setSourceModel(self.transposeableModel)

        # Assign model to table (enable sorting FIRST)
        # table.setSortingEnabled(True) # Disable for now, CRUD actions won't work!
        classTable.setModel(self.sortableModel)

        # Connect some signals
        selection_model = classTable.selectionModel()
        selection_model.selectionChanged.connect(self.table_selection_changed)
        scroll_bar = classTable.verticalScrollBar()
        scroll_bar.valueChanged.connect(self.scroll_changed)

        # These are currently broken
        # classTable.horizontalHeader().sectionMoved.connect(self.moveObject)
        # classTable.verticalHeader().sectionMoved.connect(self.moveObject)

        # Object class tree widget
        classTreeDockWidget = QDockWidget("Object Classes and Counts", self)
        classTreeDockWidget.setObjectName("classTreeDockWidget")
        classTreeDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas)

        classTree = QTreeView(classTreeDockWidget)
        classTree.setUniformRowHeights(True)
        classTree.setAllColumnsShowFocus(True)
        classTree.setRootIsDecorated(False)
        classTree.setExpandsOnDoubleClick(True)
        classTree.setIndentation(15)
        classTree.setAnimated(True)
        classTree_font = QFont()
        classTree_font.fromString(self.prefs['class_tree_font'])
        classTree.setFont(classTree_font)
        classTree.setAlternatingRowColors(True)
        classTree.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        palette = classTree.palette()
        palette.setColor(QPalette.Highlight, Qt.darkCyan)
        classTree.setPalette(palette)

        class_tree_window = QWidget(classTreeDockWidget)
        class_tree_dock_layout_v = QVBoxLayout()
        class_tree_dock_layout_h = QHBoxLayout()
        class_tree_dock_layout_v.setContentsMargins(0, 8, 0, 0)
        class_tree_dock_layout_h.setContentsMargins(0, 0, 0, 0)

        class_tree_filter_edit = QLineEdit(classTreeDockWidget)
        class_tree_filter_edit.setPlaceholderText("Filter Classes")
        class_tree_filter_edit.textChanged.connect(self.treeFilterRegExpChanged)

        class_tree_filter_cancel = QPushButton("Clear", classTreeDockWidget)
        class_tree_filter_cancel.setMaximumWidth(45)
        class_tree_filter_cancel.clicked.connect(self.clearTreeFilterClicked)

        class_tree_dock_layout_h.addWidget(class_tree_filter_edit)
        class_tree_dock_layout_h.addWidget(class_tree_filter_cancel)
        class_tree_dock_layout_v.addLayout(class_tree_dock_layout_h)
        class_tree_dock_layout_v.addWidget(classTree)
        class_tree_window.setLayout(class_tree_dock_layout_v)

        classTreeDockWidget.setWidget(class_tree_window)
        classTreeDockWidget.setContentsMargins(0,0,0,0)

        # Comments widget
        commentDockWidget = QDockWidget("Comments", self)
        commentDockWidget.setObjectName("commentDockWidget")
        commentDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas)
        commentView = UndoRedoTextEdit(commentDockWidget, self)
        commentView.setLineWrapMode(QTextEdit.FixedColumnWidth)
        commentView.setLineWrapColumnOrWidth(499)
        commentView.setFrameShape(QFrame.StyledPanel)
        commentView_font = QFont()
        commentView_font.fromString(self.prefs['comments_font'])
        commentView.setFont(commentView_font)
        commentDockWidget.setWidget(commentView)

        # Info and help widget
        infoDockWidget = QDockWidget("Info", self)
        infoDockWidget.setObjectName("infoDockWidget")
        infoDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas)
        infoView = QTextEdit(infoDockWidget)
        infoView.setFrameShape(QFrame.StyledPanel)
        infoView.setReadOnly(True)
        infoDockWidget.setWidget(infoView)

        # Node list and jump menu widget
        refDockWidget = QDockWidget("Field References", self)
        refDockWidget.setObjectName("refDockWidget")
        refDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas)
        ref_model = reftree.ReferenceTreeModel(None, refDockWidget)
        refView = QTreeView(refDockWidget)
        refView.setModel(ref_model)
        refView.setUniformRowHeights(True)
        refView.setRootIsDecorated(False)
        refView.setIndentation(15)
        refView.setColumnWidth(0, 160)
        refView.setFrameShape(QFrame.StyledPanel)
        refDockWidget.setWidget(refView)
        refView.doubleClicked.connect(self.ref_tree_double_clicked)

        # Logging and debugging widget
        logDockWidget = QDockWidget("Log Viewer", self)
        logDockWidget.setObjectName("logDockWidget")
        logDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas)
        logView = QPlainTextEdit(logDockWidget)
        logView.setLineWrapMode(QPlainTextEdit.NoWrap)
        logView.setReadOnly(True)
        logView_font = QFont()
        logView_font.fromString(self.prefs['base_font'])
        logView.setFont(logView_font)
        logView.ensureCursorVisible()
        logDockWidget.setWidget(logView)

        # Undo view widget
        undoDockWidget = QDockWidget("Undo History", self)
        undoDockWidget.setObjectName("undoDockWidget")
        undoDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas)
        undoView = QUndoView(self.undo_stack)
        undoDockWidget.setWidget(undoView)

        # Define corner docking behaviour
        self.setDockNestingEnabled(True)
        self.setCorner(Qt.TopLeftCorner,
                       Qt.LeftDockWidgetArea)
        self.setCorner(Qt.TopRightCorner,
                       Qt.RightDockWidgetArea)
        self.setCorner(Qt.BottomLeftCorner,
                       Qt.LeftDockWidgetArea)
        self.setCorner(Qt.BottomRightCorner,
                       Qt.RightDockWidgetArea)

        # Assign main widget and dock widgets to QMainWindow
        self.setCentralWidget(classTable)
        self.addDockWidget(Qt.LeftDockWidgetArea, classTreeDockWidget)
        self.addDockWidget(Qt.RightDockWidgetArea, commentDockWidget)
        self.addDockWidget(Qt.RightDockWidgetArea, infoDockWidget)
        self.addDockWidget(Qt.RightDockWidgetArea, refDockWidget)
        self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget)
        self.addDockWidget(Qt.RightDockWidgetArea, undoDockWidget)

        # Store widgets for access by other objects
        self.classTable = classTable
        self.commentView = commentView
        self.infoView = infoView
        self.classTree = classTree
        self.logView = logView
        self.undoView = undoView
        self.refView = refView
        self.filterTreeBox = class_tree_filter_edit

        # Store docks for access by other objects
        self.commentDockWidget = commentDockWidget
        self.infoDockWidget = infoDockWidget
        self.classTreeDockWidget = classTreeDockWidget
        self.logDockWidget = logDockWidget
        self.undoDockWidget = undoDockWidget
        self.refDockWidget = refDockWidget

        # Perform other UI-related initialization tasks
        self.center()
        self.setUnifiedTitleAndToolBarOnMac(True)
        self.setWindowIcon(QIcon(':/images/logo.png'))

        # Status bar setup
        self.statusBar().showMessage('Status: Ready')
        self.unitsLabel = QLabel()
        self.unitsLabel.setAlignment(Qt.AlignCenter)
        self.unitsLabel.setMinimumSize(self.unitsLabel.sizeHint())
        self.unitsLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.statusBar().addPermanentWidget(self.unitsLabel)
        self.pathLabel = QLabel()
        self.pathLabel.setAlignment(Qt.AlignCenter)
        self.pathLabel.setMinimumSize(self.pathLabel.sizeHint())
        self.pathLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.statusBar().addPermanentWidget(self.pathLabel)
        self.versionLabel = QLabel()
        self.versionLabel.setAlignment(Qt.AlignCenter)
        self.versionLabel.setMinimumSize(self.versionLabel.sizeHint())
        self.versionLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.statusBar().addPermanentWidget(self.versionLabel)
        self.progressBarIDF = QProgressBar()
        self.progressBarIDF.setAlignment(Qt.AlignCenter)
        self.progressBarIDF.setMaximumWidth(200)
        self.statusBar().addPermanentWidget(self.progressBarIDF)

        self.clipboard = QApplication.instance().clipboard()
        self.obj_clipboard = []

        self.setStyleSheet("""
            QToolTip {
               background-color: gray;
               color: white;
               border: black solid 1px
            } 
            # QMenu {
            #     background-color: rgbf(0.949020, 0.945098, 0.941176);
            #     color: rgb(255,255,255);
            # }
            # QMenu::item::selected {
            #     background-color: rgbf(0.949020, 0.945098, 0.941176);
            # }
            """)
Exemple #21
0
class TriageFilePicker(QWidget):
	def __init__(self, context):
		super(TriageFilePicker, self).__init__()
		self.context = context
		self.actionHandler = UIActionHandler()
		self.actionHandler.setupActionHandler(self)
		self.contextMenu = Menu()
		self.contextMenuManager = ContextMenuManager(self)

		layout = QVBoxLayout()
		layout.setContentsMargins(0, 0, 0, 0)

		self.model = QFileSystemModel()
		self.model.setRootPath("")
		self.model.setFilter(QDir.AllEntries | QDir.Hidden | QDir.System)
		self.tree = QTreeView(self)
		self.tree.setModel(self.model)
		self.tree.setSelectionMode(QAbstractItemView.ExtendedSelection)
		self.tree.setColumnWidth(0, 500)
		layout.addWidget(self.tree, 1)

		self.setLayout(layout)

		self.tree.doubleClicked.connect(self.onDoubleClick)

		recentFile = QSettings().value("triage/recentFile", os.path.expanduser("~"))
		while len(recentFile) > 0:
			f = self.model.index(recentFile)
			if f.isValid():
				self.tree.scrollTo(f)
				self.tree.setExpanded(f, True)
				break
			parentDir = os.path.dirname(recentFile)
			if parentDir == recentFile:
				break
			recentFile = parentDir

		self.actionHandler.bindAction("Open Selected Files", UIAction(
			lambda context: self.openSelectedFiles(),
			lambda context: self.areFilesSelected()))
		self.contextMenu.addAction("Open Selected Files", "Open")

	def contextMenuEvent(self, event):
		self.contextMenuManager.show(self.contextMenu, self.actionHandler)

	def onDoubleClick(self, index):
		self.openSelectedFiles()

	def openSelectedFiles(self):
		failedToOpen = []
		files = set()

		for index in self.tree.selectionModel().selectedIndexes():
			if self.model.fileInfo(index).isFile():
				files.add(self.model.fileInfo(index).absoluteFilePath())

		for filename in files:
				QSettings().setValue("triage/recentFile", filename)

				f = FileContext.openFilename(filename)
				if not f:
					failedToOpen.append(filename)
					continue

				f.createBinaryViews()
				for data in f.getAllDataViews():
					Settings().set_string("analysis.mode", Settings().get_string("triage.analysisMode"), data)
					Settings().set_bool("triage.preferSummaryView", True, data)
					if data.view_type != "Raw":
						linearSweepMode = Settings().get_string("triage.linearSweep")
						if linearSweepMode == "none":
							Settings().set_bool("analysis.linearSweep.autorun", False, data)
						elif linearSweepMode == "partial":
							Settings().set_bool("analysis.linearSweep.autorun", True, data)
							Settings().set_bool("analysis.linearSweep.controlFlowGraph", False, data)
						elif linearSweepMode == "full":
							Settings().set_bool("analysis.linearSweep.autorun", True, data)
							Settings().set_bool("analysis.linearSweep.controlFlowGraph", True, data)

				self.context.openFileContext(f)

		if len(failedToOpen) > 0:
			QMessageBox.critical(self, "Error", "Unable to open:\n" + "\n".join(failedToOpen))

	def areFilesSelected(self):
		return self.tree.selectionModel().hasSelection()
Exemple #22
0
class MVCConfigurationGUI(MVCConfigurationBase):
    """
    GUI implementation of MVCConfigurationBase
    """
    def __init__(self, configuration):
        super().__init__(configuration)
        assertMainThread()
        srv = Services.getService("MainWindow")
        srv.aboutToClose.connect(self._aboutToClose)
        confMenu = srv.menuBar().addMenu("&Configuration")
        toolBar = srv.getToolBar()

        configuration.configNameChanged.connect(self._configNameChanged)
        configuration.dirtyChanged.connect(self._dirtyChanged)

        style = QApplication.style()
        self.actLoad = QAction(
            QIcon.fromTheme("document-open",
                            style.standardIcon(QStyle.SP_DialogOpenButton)),
            "Open config", self)
        self.actLoad.triggered.connect(self._execLoad)
        self.actSave = QAction(
            QIcon.fromTheme("document-save",
                            style.standardIcon(QStyle.SP_DialogSaveButton)),
            "Save config", self)
        self.actSave.triggered.connect(self._execSaveConfig)
        self.actSaveWithGuiState = QAction(
            QIcon.fromTheme("document-save",
                            style.standardIcon(QStyle.SP_DialogSaveButton)),
            "Save config sync gui state", self)
        self.actSaveWithGuiState.triggered.connect(
            self._execSaveConfigWithGuiState)
        self.actNew = QAction(
            QIcon.fromTheme("document-new",
                            style.standardIcon(QStyle.SP_FileIcon)),
            "New config", self)
        self.actNew.triggered.connect(self._execNew)

        self.actActivate = QAction(
            QIcon.fromTheme("arrow-up", style.standardIcon(QStyle.SP_ArrowUp)),
            "Initialize", self)
        self.actActivate.triggered.connect(self.activate)
        self.actDeactivate = QAction(
            QIcon.fromTheme("arrow-down",
                            style.standardIcon(QStyle.SP_ArrowDown)),
            "Deinitialize", self)
        self.actDeactivate.triggered.connect(self.deactivate)

        confMenu.addAction(self.actLoad)
        confMenu.addAction(self.actSave)
        confMenu.addAction(self.actSaveWithGuiState)
        confMenu.addAction(self.actNew)
        confMenu.addAction(self.actActivate)
        confMenu.addAction(self.actDeactivate)
        toolBar.addAction(self.actLoad)
        toolBar.addAction(self.actSave)
        toolBar.addAction(self.actNew)
        toolBar.addAction(self.actActivate)
        toolBar.addAction(self.actDeactivate)

        self.recentConfigs = [QAction() for i in range(10)]
        self.recentConfigs[0].setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
        confMenu.addSeparator()
        recentMenu = confMenu.addMenu("Recent")
        for a in self.recentConfigs:
            a.setVisible(False)
            a.triggered.connect(self._openRecent)
            recentMenu.addAction(a)

        self.mainWidget = srv.newDockWidget("Configuration", None,
                                            Qt.LeftDockWidgetArea)
        self.treeView = QTreeView(self.mainWidget)
        self.treeView.setHeaderHidden(False)
        self.treeView.setSelectionMode(QAbstractItemView.NoSelection)
        self.treeView.setEditTriggers(self.treeView.EditKeyPressed
                                      | self.treeView.AnyKeyPressed)
        self.treeView.setAllColumnsShowFocus(True)
        self.treeView.setExpandsOnDoubleClick(False)
        self.treeView.setDragEnabled(True)
        self.treeView.setDropIndicatorShown(True)
        self.treeView.setDragDropMode(QAbstractItemView.DragOnly)
        self.mainWidget.setWidget(self.treeView)
        self.treeView.setModel(self.model)
        self.treeView.header().setStretchLastSection(True)
        self.treeView.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.treeView.doubleClicked.connect(self._onItemDoubleClicked)
        self.treeView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeView.customContextMenuRequested.connect(
            self._execTreeViewContextMenu)
        # expand applications by default
        self.treeView.setExpanded(self.model.index(1, 0), True)
        self.delegate = PropertyDelegate(self.model, ITEM_ROLE,
                                         ConfigurationModel.PropertyContent,
                                         self)
        self.treeView.setItemDelegate(self.delegate)

        self.restoreState()
        srv.aboutToClose.connect(self.saveState)
        # a list of dock widgets displaying subgraphs
        self._graphViews = []
        # make sure that the graph views are closed when the config is closed
        self._configuration.subConfigRemoved.connect(self._subConfigRemoved)
        self._waitForActivated = None
        self._waitForOpenState = None

    def _execLoad(self):
        assertMainThread()
        if self._checkDirty():
            return
        fn, _ = QFileDialog.getOpenFileName(self.mainWidget,
                                            "Load configuration",
                                            self.cfgfile,
                                            filter="*.json")
        if fn is not None and fn != "":
            logger.debug("Loading config file %s", fn)
            try:
                self.loadConfig(fn)
            except Exception as e:  # pylint: disable=broad-except
                logger.exception("Error while loading configuration %s: %s",
                                 fn, str(e))
                QMessageBox.warning(self.mainWidget,
                                    "Error while loading configuration",
                                    str(e))

    def _openRecent(self):
        """
        Called when the user clicks on a recent config.

        :return:
        """
        if self._checkDirty():
            return
        action = self.sender()
        fn = action.data()
        try:
            self.loadConfig(fn)
        except Exception as e:  # pylint: disable=broad-except
            # catching general exception is wanted here.
            logger.exception("Error while loading configuration %s: %s", fn,
                             str(e))
            QMessageBox.warning(self.mainWidget,
                                "Error while loading configuration", str(e))

    def _checkDirty(self):
        if self._configuration.dirty():
            ans = QMessageBox.question(
                None,
                "Save changes?",
                "There are unsaved changes. Do you want to save them?",
                buttons=QMessageBox.Save | QMessageBox.Discard
                | QMessageBox.Cancel,
                defaultButton=QMessageBox.Save)
            if ans == QMessageBox.Save:
                self.saveConfig()
                return False
            if ans == QMessageBox.Cancel:
                return True
        return False

    def _aboutToClose(self, mainWindow):
        if self._checkDirty():
            mainWindow.ignoreCloseEvent()

    def _execNew(self):
        assertMainThread()
        if self._checkDirty():
            return
        fn, _ = QFileDialog.getSaveFileName(self.mainWidget,
                                            "New configuration",
                                            ".",
                                            filter="*.json")
        if fn is not None and fn != "":
            logger.debug("Creating config file %s", fn)
            self.newConfig(fn)

    def _execSaveConfig(self):
        if self.configuration().filename() is None:
            self._execSaveConfigAs()
        else:
            self.saveConfig()

    def _execSaveConfigWithGuiState(self):
        if self.configuration().filename() is None:
            self._execSaveConfigAs()
        else:
            self.saveConfigWithGuiState()

    def _execSaveConfigAs(self):
        """
        Opens a file dialog to get the save file name and calls saveConfig.

        :return:
        """
        assertMainThread()
        fn, _ = QFileDialog.getSaveFileName(self.mainWidget,
                                            "Save configuration as", ".",
                                            "*.json")
        if fn is not None and fn != "":
            self.saveConfigAs(fn)

    def _addGraphView(self, subConfig):
        g = subConfig.getGraph()
        # remove already deleted graph views from internal list
        valid_graphViews = []
        for gv in self._graphViews:
            if shiboken2.isValid(gv):  # pylint: disable=no-member
                valid_graphViews.append(gv)
        self._graphViews = valid_graphViews
        # check if graph view is already there
        for gv in self._graphViews:
            if gv.widget().scene().graph == g:
                logger.info("Graph view already exists.")
                return
        # create new graph view
        srv = Services.getService("MainWindow")
        graphDw = srv.newDockWidget("Graph (%s)" % (subConfig.getName()),
                                    parent=None,
                                    defaultArea=Qt.RightDockWidgetArea,
                                    allowedArea=Qt.RightDockWidgetArea
                                    | Qt.BottomDockWidgetArea)
        graphDw.setAttribute(Qt.WA_DeleteOnClose, True)
        assert isinstance(graphDw, QDockWidget)
        graphView = GraphEditorView(graphDw)
        graphView.setScene(GraphScene(subConfig.getGraph(), graphDw))
        graphDw.setWidget(graphView)
        self._graphViews.append(graphDw)
        graphDw.visibleChanged.connect(self._removeGraphViewFromList)

    def _subConfigRemoved(self, subConfigName, configType):
        g = self._configuration.subConfigByNameAndTye(subConfigName,
                                                      configType).getGraph()
        for gv in self._graphViews:
            if gv.widget().scene().graph == g:
                logger.debug("deleting graph view for subconfig %s",
                             subConfigName)
                gv.deleteLater()

    def _removeGraphViewFromList(self, visible):
        if visible:
            return
        gv = self.sender()
        try:
            self._graphViews.remove(gv)
            logger.debug("removed graphview from list")
        except ValueError:
            logger.debug("graphview not in list, ignored")

    def _execTreeViewContextMenu(self, point):
        index = self.treeView.indexAt(point)
        item = self.model.data(index, ITEM_ROLE)
        if isinstance(item, ConfigurationModel.SubConfigContent):
            m = QMenu()
            a1 = QAction("Edit graph")
            m.addAction(a1)
            a1.triggered.connect(lambda: self._addGraphView(item.subConfig))
            if self.model.isApplication(index):
                a2 = QAction("Select Application")
                a2.triggered.connect(lambda: self.changeActiveApp(
                    self.model.data(index, Qt.DisplayRole)))
                a3 = QAction("Init Application")
                a3.triggered.connect(lambda: self._changeActiveAppAndInit(
                    self.model.data(index, Qt.DisplayRole)))
                m.addActions([a2, a3])
                pbsrv = Services.getService("PlaybackControl")
                m2 = m.addMenu("Init and load sequence")
                m3 = m.addMenu("Init, load and play")
                s1 = []
                s2 = []
                for a in pbsrv.recentSeqs:
                    assert isinstance(a, QAction)
                    if a.isVisible():
                        # pylint: disable=cell-var-from-loop
                        # the below statements are tested and work
                        aseq = QAction(a.text())
                        aseq.triggered.connect(lambda arg1=a.data(
                        ), seq=a.data(): self._changeActiveAppInitAndLoad(
                            self.model.data(index, Qt.DisplayRole), seq, False)
                                               )
                        s1.append(aseq)
                        aseq = QAction(a.text())
                        aseq.triggered.connect(lambda arg1=a.data(
                        ), seq=a.data(): self._changeActiveAppInitAndLoad(
                            self.model.data(index, Qt.DisplayRole), seq, True))
                        # pylint: enable=cell-var-from-loop
                        s2.append(aseq)
                m2.addActions(s1)
                m3.addActions(s2)
            m.exec_(self.treeView.mapToGlobal(point))
            return
        if self.model.isSubConfigParent(
                index) == Configuration.CONFIG_TYPE_APPLICATION:
            m = QMenu()
            a = QAction("Add application")
            m.addAction(a)
            a = m.exec_(self.treeView.mapToGlobal(point))
            if a is not None:
                self._configuration.addNewApplication()
            return
        if self.model.isSubConfigParent(
                index) == Configuration.CONFIG_TYPE_COMPOSITE:
            m = QMenu()
            a = QAction("Add composite filter")
            m.addAction(a)
            a = m.exec_(self.treeView.mapToGlobal(point))
            if a is not None:
                self._configuration.addNewCompositeFilter()
            return

    def _configNameChanged(self, cfgfile):
        logger.debug("_configNameChanged: %s", cfgfile)
        assertMainThread()
        self.cfgfile = cfgfile
        self._dirtyChanged(self._configuration.dirty())
        foundIdx = None
        for i, a in enumerate(self.recentConfigs):
            if a.data() == cfgfile:
                foundIdx = i
        if foundIdx is None:
            foundIdx = len(self.recentConfigs) - 1
        for i in range(foundIdx, 0, -1):
            self.recentConfigs[i].setText(self.recentConfigs[i - 1].text())
            self.recentConfigs[i].setData(self.recentConfigs[i - 1].data())
            self.recentConfigs[i].setVisible(
                self.recentConfigs[i - 1].data() is not None)
        self.recentConfigs[0].setText(cfgfile)
        self.recentConfigs[0].setData(cfgfile)
        self.recentConfigs[0].setVisible(True)

    def _dirtyChanged(self, dirty):
        srv = Services.getService("MainWindow")
        if self.cfgfile is None:
            title = "nexxT: <unnamed>"
        else:
            title = "nexxT: " + self.cfgfile
        if dirty:
            title += " *"
        srv.setWindowTitle(title)

    def _onItemDoubleClicked(self, index):
        assertMainThread()
        if self.model.isApplication(index):
            app = self.model.data(index, Qt.DisplayRole)
            self.changeActiveApp(app)
        else:
            self.treeView.edit(index)

    def _changeActiveAppAndInit(self, app):
        """
        Call this slot to activate and init an application

        :param app: can be either an Application instance or the name of an application
        :return:
        """
        assertMainThread()
        if isinstance(app, str):
            app = self.configuration().applicationByName(app)
        currentApp = Application.activeApplication
        if currentApp is not None:
            currentApp = currentApp.getApplication()
        self._waitForActivated = app
        self.changeActiveApp(app.getName())

    def _changeActiveAppInitAndLoad(self, app, sequence, startPlay):
        self._waitForOpenState = (app, sequence, startPlay)
        self._changeActiveAppAndInit(app)

    def appActivated(self, name, app):  # pylint: disable=unused-argument
        """
        Called when the application is activated.

        :param name: the application name
        :param app: An ActiveApplication instance.
        :return:
        """
        assertMainThread()
        if app is not None:
            self.activeAppStateChange(app.getState())
            app.stateChanged.connect(self.activeAppStateChange)
            if self._waitForActivated == app.getApplication():
                MethodInvoker(self.activate, Qt.QueuedConnection)
        else:
            self.actActivate.setEnabled(False)
            self.actDeactivate.setEnabled(False)
        self._waitForActivated = None

    def _disconnectSingleShotPlay(self):
        assertMainThread()
        pbsrv = Services.getService("PlaybackControl")
        try:
            pbsrv.playbackPaused.disconnect(self._singleShotPlay)
        except RuntimeError:
            # we are already disconnected.
            pass

    def _singleShotPlay(self):
        assertMainThread()
        pbsrv = Services.getService("PlaybackControl")
        MethodInvoker(pbsrv.startPlayback, Qt.QueuedConnection)
        self._disconnectSingleShotPlay()

    def activeAppStateChange(self, newState):
        """
        Called when the active application changes its state.

        :param newState: the new application's state (see FilterState)
        :return:
        """
        assertMainThread()
        if newState == FilterState.CONSTRUCTED:
            self.actActivate.setEnabled(True)
        else:
            self.actActivate.setEnabled(False)
        if newState == FilterState.ACTIVE:
            if self._waitForOpenState is not None:
                app, pbfile, startPlay = self._waitForOpenState
                self._waitForOpenState = None
                if app == Application.activeApplication.getApplication(
                ).getName():
                    pbsrv = Services.getService("PlaybackControl")
                    if startPlay:
                        pbsrv.playbackPaused.connect(self._singleShotPlay)
                        QTimer.singleShot(2000, self._disconnectSingleShotPlay)
                    MethodInvoker(pbsrv.browser.setActive, Qt.QueuedConnection,
                                  pbfile)
            self.actDeactivate.setEnabled(True)
            self.actSaveWithGuiState.setEnabled(False)
        else:
            self.actDeactivate.setEnabled(False)
            self.actSaveWithGuiState.setEnabled(True)

    def restoreState(self):
        """
        Restore the state of the configuration gui service (namely the recently
        open config files). This is saved in QSettings because it is used
        across config files.

        :return:
        """
        logger.debug("restoring config state ...")
        settings = QSettings()
        v = settings.value("ConfigurationRecentFiles")
        if v is not None and isinstance(v, QByteArray):
            ds = QDataStream(v)
            recentFiles = ds.readQStringList()
            idx = 0
            for f in recentFiles:
                if f != "" and f is not None:
                    self.recentConfigs[idx].setData(f)
                    self.recentConfigs[idx].setText(f)
                    self.recentConfigs[idx].setVisible(True)
                    idx += 1
                    if idx >= len(self.recentConfigs):
                        break
        logger.debug("restoring config state done")

    def saveState(self):
        """
        Save the state of the configuration gui service (namely the recently
        open config files). This is saved in QSettings because it is used
        across config files.

        :return:
        """
        logger.debug("saving config state ...")
        settings = QSettings()
        b = QByteArray()
        ds = QDataStream(b, QIODevice.WriteOnly)
        l = [
            rc.data() for rc in self.recentConfigs
            if rc.isVisible() and rc.data() is not None and rc.data() != ""
        ]
        ds.writeQStringList(l)
        settings.setValue("ConfigurationRecentFiles", b)
        logger.debug("saving config state done (%s)", l)
class Snippets(QDialog):

    def __init__(self, context, parent=None):
        super(Snippets, self).__init__(parent)
        # Create widgets
        self.setWindowModality(Qt.ApplicationModal)
        self.title = QLabel(self.tr("Snippet Editor"))
        self.saveButton = QPushButton(self.tr("&Save"))
        self.saveButton.setShortcut(QKeySequence(self.tr("Ctrl+S")))
        self.runButton = QPushButton(self.tr("&Run"))
        self.runButton.setShortcut(QKeySequence(self.tr("Ctrl+R")))
        self.closeButton = QPushButton(self.tr("Close"))
        self.clearHotkeyButton = QPushButton(self.tr("Clear Hotkey"))
        self.setWindowTitle(self.title.text())
        #self.newFolderButton = QPushButton("New Folder")
        self.browseButton = QPushButton("Browse Snippets")
        self.browseButton.setIcon(QIcon.fromTheme("edit-undo"))
        self.deleteSnippetButton = QPushButton("Delete")
        self.newSnippetButton = QPushButton("New Snippet")
        self.edit = QCodeEditor(HIGHLIGHT_CURRENT_LINE=False, SyntaxHighlighter=PythonHighlighter)
        self.edit.setPlaceholderText("python code")
        self.resetting = False
        self.columns = 3
        self.context = context

        self.keySequenceEdit = QKeySequenceEdit(self)
        self.currentHotkey = QKeySequence()
        self.currentHotkeyLabel = QLabel("")
        self.currentFileLabel = QLabel()
        self.currentFile = ""
        self.snippetDescription = QLineEdit()
        self.snippetDescription.setPlaceholderText("optional description")

        #Set Editbox Size
        font = getMonospaceFont(self)
        self.edit.setFont(font)
        font = QFontMetrics(font)
        self.edit.setTabStopWidth(4 * font.width(' ')); #TODO, replace with settings API

        #Files
        self.files = QFileSystemModel()
        self.files.setRootPath(snippetPath)
        self.files.setNameFilters(["*.py"])

        #Tree
        self.tree = QTreeView()
        self.tree.setModel(self.files)
        self.tree.setSortingEnabled(True)
        self.tree.hideColumn(2)
        self.tree.sortByColumn(0, Qt.AscendingOrder)
        self.tree.setRootIndex(self.files.index(snippetPath))
        for x in range(self.columns):
            #self.tree.resizeColumnToContents(x)
            self.tree.header().setSectionResizeMode(x, QHeaderView.ResizeToContents)
        treeLayout = QVBoxLayout()
        treeLayout.addWidget(self.tree)
        treeButtons = QHBoxLayout()
        #treeButtons.addWidget(self.newFolderButton)
        treeButtons.addWidget(self.browseButton)
        treeButtons.addWidget(self.newSnippetButton)
        treeButtons.addWidget(self.deleteSnippetButton)
        treeLayout.addLayout(treeButtons)
        treeWidget = QWidget()
        treeWidget.setLayout(treeLayout)

        # Create layout and add widgets
        buttons = QHBoxLayout()
        buttons.addWidget(self.clearHotkeyButton)
        buttons.addWidget(self.keySequenceEdit)
        buttons.addWidget(self.currentHotkeyLabel)
        buttons.addWidget(self.closeButton)
        buttons.addWidget(self.runButton)
        buttons.addWidget(self.saveButton)

        description = QHBoxLayout()
        description.addWidget(QLabel(self.tr("Description: ")))
        description.addWidget(self.snippetDescription)

        vlayoutWidget = QWidget()
        vlayout = QVBoxLayout()
        vlayout.addLayout(description)
        vlayout.addWidget(self.edit)
        vlayout.addLayout(buttons)
        vlayoutWidget.setLayout(vlayout)

        hsplitter = QSplitter()
        hsplitter.addWidget(treeWidget)
        hsplitter.addWidget(vlayoutWidget)

        hlayout = QHBoxLayout()
        hlayout.addWidget(hsplitter)

        self.showNormal() #Fixes bug that maximized windows are "stuck"
        #Because you can't trust QT to do the right thing here
        if (sys.platform == "darwin"):
            self.settings = QSettings("Vector35", "Snippet Editor")
        else:
            self.settings = QSettings("Vector 35", "Snippet Editor")
        if self.settings.contains("ui/snippeteditor/geometry"):
            self.restoreGeometry(self.settings.value("ui/snippeteditor/geometry"))
        else:
            self.edit.setMinimumWidth(80 * font.averageCharWidth())
            self.edit.setMinimumHeight(30 * font.lineSpacing())

        # Set dialog layout
        self.setLayout(hlayout)

        # Add signals
        self.saveButton.clicked.connect(self.save)
        self.closeButton.clicked.connect(self.close)
        self.runButton.clicked.connect(self.run)
        self.clearHotkeyButton.clicked.connect(self.clearHotkey)
        self.tree.selectionModel().selectionChanged.connect(self.selectFile)
        self.newSnippetButton.clicked.connect(self.newFileDialog)
        self.deleteSnippetButton.clicked.connect(self.deleteSnippet)
        #self.newFolderButton.clicked.connect(self.newFolder)
        self.browseButton.clicked.connect(self.browseSnippets)

        if self.settings.contains("ui/snippeteditor/selected"):
            selectedName = self.settings.value("ui/snippeteditor/selected")
            self.tree.selectionModel().select(self.files.index(selectedName), QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
            if self.tree.selectionModel().hasSelection():
                self.selectFile(self.tree.selectionModel().selection(), None)
                self.edit.setFocus()
                cursor = self.edit.textCursor()
                cursor.setPosition(self.edit.document().characterCount()-1)
                self.edit.setTextCursor(cursor)
            else:
                self.readOnly(True)
        else:
            self.readOnly(True)


    @staticmethod
    def registerAllSnippets():
        for action in list(filter(lambda x: x.startswith("Snippets\\"), UIAction.getAllRegisteredActions())):
            if action == "Snippets\\Snippet Editor...":
                continue
            UIActionHandler.globalActions().unbindAction(action)
            Menu.mainMenu("Tools").removeAction(action)
            UIAction.unregisterAction(action)

        for snippet in includeWalk(snippetPath, ".py"):
            snippetKeys = None
            (snippetDescription, snippetKeys, snippetCode) = loadSnippetFromFile(snippet)
            actionText = actionFromSnippet(snippet, snippetDescription)
            if snippetCode:
                if snippetKeys == None:
                    UIAction.registerAction(actionText)
                else:
                    UIAction.registerAction(actionText, snippetKeys)
                UIActionHandler.globalActions().bindAction(actionText, UIAction(makeSnippetFunction(snippetCode)))
                Menu.mainMenu("Tools").addAction(actionText, "Snippets")

    def clearSelection(self):
        self.keySequenceEdit.clear()
        self.currentHotkey = QKeySequence()
        self.currentHotkeyLabel.setText("")
        self.currentFileLabel.setText("")
        self.snippetDescription.setText("")
        self.edit.clear()
        self.tree.clearSelection()
        self.currentFile = ""

    def reject(self):
        self.settings.setValue("ui/snippeteditor/geometry", self.saveGeometry())

        if self.snippetChanged():
            question = QMessageBox.question(self, self.tr("Discard"), self.tr("You have unsaved changes, quit anyway?"))
            if question != QMessageBox.StandardButton.Yes:
                return
        self.accept()

    def browseSnippets(self):
        url = QUrl.fromLocalFile(snippetPath)
        QDesktopServices.openUrl(url);

    def newFolder(self):
        (folderName, ok) = QInputDialog.getText(self, self.tr("Folder Name"), self.tr("Folder Name: "))
        if ok and folderName:
            index = self.tree.selectionModel().currentIndex()
            selection = self.files.filePath(index)
            if QFileInfo(selection).isDir():
                QDir(selection).mkdir(folderName)
            else:
                QDir(snippetPath).mkdir(folderName)

    def selectFile(self, new, old):
        if (self.resetting):
            self.resetting = False
            return
        if len(new.indexes()) == 0:
            self.clearSelection()
            self.currentFile = ""
            self.readOnly(True)
            return
        newSelection = self.files.filePath(new.indexes()[0])
        self.settings.setValue("ui/snippeteditor/selected", newSelection)
        if QFileInfo(newSelection).isDir():
            self.readOnly(True)
            self.clearSelection()
            self.currentFile = ""
            return

        if old and old.length() > 0:
            oldSelection = self.files.filePath(old.indexes()[0])
            if not QFileInfo(oldSelection).isDir() and self.snippetChanged():
                question = QMessageBox.question(self, self.tr("Discard"), self.tr("Snippet changed. Discard changes?"))
                if question != QMessageBox.StandardButton.Yes:
                    self.resetting = True
                    self.tree.selectionModel().select(old, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
                    return False

        self.currentFile = newSelection
        self.loadSnippet()

    def loadSnippet(self):
        self.currentFileLabel.setText(QFileInfo(self.currentFile).baseName())
        (snippetDescription, snippetKeys, snippetCode) = loadSnippetFromFile(self.currentFile)
        self.snippetDescription.setText(snippetDescription) if snippetDescription else self.snippetDescription.setText("")
        self.keySequenceEdit.setKeySequence(snippetKeys) if snippetKeys else self.keySequenceEdit.setKeySequence(QKeySequence(""))
        self.edit.setPlainText(snippetCode) if snippetCode else self.edit.setPlainText("")
        self.readOnly(False)

    def newFileDialog(self):
        (snippetName, ok) = QInputDialog.getText(self, self.tr("Snippet Name"), self.tr("Snippet Name: "))
        if ok and snippetName:
            if not snippetName.endswith(".py"):
                snippetName += ".py"
            index = self.tree.selectionModel().currentIndex()
            selection = self.files.filePath(index)
            if QFileInfo(selection).isDir():
                path = os.path.join(selection, snippetName)
            else:
                path = os.path.join(snippetPath, snippetName)
                self.readOnly(False)
            open(path, "w").close()
            self.tree.setCurrentIndex(self.files.index(path))
            log_debug("Snippet %s created." % snippetName)

    def readOnly(self, flag):
        self.keySequenceEdit.setEnabled(not flag)
        self.snippetDescription.setReadOnly(flag)
        self.edit.setReadOnly(flag)
        if flag:
            self.snippetDescription.setDisabled(True)
            self.edit.setDisabled(True)
        else:
            self.snippetDescription.setEnabled(True)
            self.edit.setEnabled(True)

    def deleteSnippet(self):
        selection = self.tree.selectedIndexes()[::self.columns][0] #treeview returns each selected element in the row
        snippetName = self.files.fileName(selection)
        question = QMessageBox.question(self, self.tr("Confirm"), self.tr("Confirm deletion: ") + snippetName)
        if (question == QMessageBox.StandardButton.Yes):
            log_debug("Deleting snippet %s." % snippetName)
            self.clearSelection()
            self.files.remove(selection)
            self.registerAllSnippets()

    def snippetChanged(self):
        if (self.currentFile == "" or QFileInfo(self.currentFile).isDir()):
            return False
        (snippetDescription, snippetKeys, snippetCode) = loadSnippetFromFile(self.currentFile)
        if snippetKeys == None and not self.keySequenceEdit.keySequence().isEmpty():
            return True
        if snippetKeys != None and snippetKeys != self.keySequenceEdit.keySequence().toString():
            return True
        return self.edit.toPlainText() != snippetCode or \
               self.snippetDescription.text() != snippetDescription

    def save(self):
        log_debug("Saving snippet %s" % self.currentFile)
        outputSnippet = codecs.open(self.currentFile, "w", "utf-8")
        outputSnippet.write("#" + self.snippetDescription.text() + "\n")
        outputSnippet.write("#" + self.keySequenceEdit.keySequence().toString() + "\n")
        outputSnippet.write(self.edit.toPlainText())
        outputSnippet.close()
        self.registerAllSnippets()

    def run(self):
        if self.context == None:
            log_warn("Cannot run snippets outside of the UI at this time.")
            return
        if self.snippetChanged():
            question = QMessageBox.question(self, self.tr("Confirm"), self.tr("You have unsaved changes, must save first. Save?"))
            if (question == QMessageBox.StandardButton.No):
                return
            else:
                self.save()
        actionText = actionFromSnippet(self.currentFile, self.snippetDescription.text())
        UIActionHandler.globalActions().executeAction(actionText, self.context)

        log_debug("Saving snippet %s" % self.currentFile)
        outputSnippet = codecs.open(self.currentFile, "w", "utf-8")
        outputSnippet.write("#" + self.snippetDescription.text() + "\n")
        outputSnippet.write("#" + self.keySequenceEdit.keySequence().toString() + "\n")
        outputSnippet.write(self.edit.toPlainText())
        outputSnippet.close()
        self.registerAllSnippets()

    def clearHotkey(self):
        self.keySequenceEdit.clear()
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.proxyModel = SortFilterProxyModel()
        self.proxyModel.setDynamicSortFilter(True)

        self.sourceGroupBox = QGroupBox("Original Model")
        self.proxyGroupBox = QGroupBox("Sorted/Filtered Model")

        self.sourceView = QTreeView()
        self.sourceView.setRootIsDecorated(False)
        self.sourceView.setAlternatingRowColors(True)

        self.proxyView = QTreeView()
        self.proxyView.setRootIsDecorated(False)
        self.proxyView.setAlternatingRowColors(True)
        self.proxyView.setModel(self.proxyModel)
        self.proxyView.setSortingEnabled(True)

        self.sortCaseSensitivityCheckBox = QCheckBox("Case sensitive sorting")
        self.filterCaseSensitivityCheckBox = QCheckBox("Case sensitive filter")

        self.filterPatternLineEdit = QLineEdit()
        self.filterPatternLabel = QLabel("&Filter pattern:")
        self.filterPatternLabel.setBuddy(self.filterPatternLineEdit)

        self.filterSyntaxComboBox = QComboBox()
        self.filterSyntaxComboBox.addItem("Regular expression", QRegExp.RegExp)
        self.filterSyntaxComboBox.addItem("Wildcard", QRegExp.Wildcard)
        self.filterSyntaxComboBox.addItem("Fixed string", QRegExp.FixedString)
        self.filterSyntaxLabel = QLabel("Filter &syntax:")
        self.filterSyntaxLabel.setBuddy(self.filterSyntaxComboBox)

        self.filterColumnComboBox = QComboBox()
        self.filterColumnComboBox.addItem("Subject")
        self.filterColumnComboBox.addItem("Sender")
        self.filterColumnComboBox.addItem("Date")
        self.filterColumnLabel = QLabel("Filter &column:")
        self.filterColumnLabel.setBuddy(self.filterColumnComboBox)

        self.filterPatternLineEdit.textChanged.connect(
            self.filterRegExpChanged)
        self.filterSyntaxComboBox.currentIndexChanged.connect(
            self.filterRegExpChanged)
        self.filterColumnComboBox.currentIndexChanged.connect(
            self.filterColumnChanged)
        self.filterCaseSensitivityCheckBox.toggled.connect(
            self.filterRegExpChanged)
        self.sortCaseSensitivityCheckBox.toggled.connect(self.sortChanged)

        sourceLayout = QHBoxLayout()
        sourceLayout.addWidget(self.sourceView)
        self.sourceGroupBox.setLayout(sourceLayout)

        proxyLayout = QGridLayout()
        proxyLayout.addWidget(self.proxyView, 0, 0, 1, 3)
        proxyLayout.addWidget(self.filterPatternLabel, 1, 0)
        proxyLayout.addWidget(self.filterPatternLineEdit, 1, 1, 1, 2)
        proxyLayout.addWidget(self.filterSyntaxLabel, 2, 0)
        proxyLayout.addWidget(self.filterSyntaxComboBox, 2, 1, 1, 2)
        proxyLayout.addWidget(self.filterColumnLabel, 3, 0)
        proxyLayout.addWidget(self.filterColumnComboBox, 3, 1, 1, 2)
        proxyLayout.addWidget(self.filterCaseSensitivityCheckBox, 4, 0, 1, 2)
        proxyLayout.addWidget(self.sortCaseSensitivityCheckBox, 4, 2)
        self.proxyGroupBox.setLayout(proxyLayout)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.sourceGroupBox)
        mainLayout.addWidget(self.proxyGroupBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("Basic Sort/Filter Model")
        self.resize(500, 450)

        self.proxyView.sortByColumn(SENDER, Qt.AscendingOrder)
        self.filterColumnComboBox.setCurrentIndex(SENDER)

        self.filterPatternLineEdit.setText("Andy|Grace")
        self.filterCaseSensitivityCheckBox.setChecked(True)
        self.sortCaseSensitivityCheckBox.setChecked(True)

    def setSourceModel(self, model):
        self.proxyModel.setSourceModel(model)
        self.sourceView.setModel(model)

    def filterRegExpChanged(self):
        syntax_nr = self.filterSyntaxComboBox.itemData(
            self.filterSyntaxComboBox.currentIndex())
        syntax = QRegExp.PatternSyntax(syntax_nr)

        if self.filterCaseSensitivityCheckBox.isChecked():
            caseSensitivity = Qt.CaseSensitive
        else:
            caseSensitivity = Qt.CaseInsensitive

        regExp = QRegExp(self.filterPatternLineEdit.text(), caseSensitivity,
                         syntax)
        self.proxyModel.setFilterRegExp(regExp)

    def filterColumnChanged(self):
        self.proxyModel.setFilterKeyColumn(
            self.filterColumnComboBox.currentIndex())

    def sortChanged(self):
        if self.sortCaseSensitivityCheckBox.isChecked():
            caseSensitivity = Qt.CaseSensitive
        else:
            caseSensitivity = Qt.CaseInsensitive

        self.proxyModel.setSortCaseSensitivity(caseSensitivity)
Exemple #25
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.proxyModel = QSortFilterProxyModel()
        self.proxyModel.setDynamicSortFilter(True)

        self.sourceGroupBox = QGroupBox("Original Model")
        self.proxyGroupBox = QGroupBox("Sorted/Filtered Model")

        self.sourceView = QTreeView()
        self.sourceView.setRootIsDecorated(False)
        self.sourceView.setAlternatingRowColors(True)

        self.proxyView = QTreeView()
        self.proxyView.setRootIsDecorated(False)
        self.proxyView.setAlternatingRowColors(True)
        self.proxyView.setModel(self.proxyModel)
        self.proxyView.setSortingEnabled(True)

        self.sortCaseSensitivityCheckBox = QCheckBox("Case sensitive sorting")
        self.filterCaseSensitivityCheckBox = QCheckBox("Case sensitive filter")

        self.filterPatternLineEdit = QLineEdit()
        self.filterPatternLineEdit.setClearButtonEnabled(True)
        self.filterPatternLabel = QLabel("&Filter pattern:")
        self.filterPatternLabel.setBuddy(self.filterPatternLineEdit)

        self.filterSyntaxComboBox = QComboBox()
        self.filterSyntaxComboBox.addItem("Regular expression",
                                          REGULAR_EXPRESSION)
        self.filterSyntaxComboBox.addItem("Wildcard",
                                          WILDCARD)
        self.filterSyntaxComboBox.addItem("Fixed string",
                                          FIXED_STRING)
        self.filterSyntaxLabel = QLabel("Filter &syntax:")
        self.filterSyntaxLabel.setBuddy(self.filterSyntaxComboBox)

        self.filterColumnComboBox = QComboBox()
        self.filterColumnComboBox.addItem("Subject")
        self.filterColumnComboBox.addItem("Sender")
        self.filterColumnComboBox.addItem("Date")
        self.filterColumnLabel = QLabel("Filter &column:")
        self.filterColumnLabel.setBuddy(self.filterColumnComboBox)

        self.filterPatternLineEdit.textChanged.connect(self.filterRegExpChanged)
        self.filterSyntaxComboBox.currentIndexChanged.connect(self.filterRegExpChanged)
        self.filterColumnComboBox.currentIndexChanged.connect(self.filterColumnChanged)
        self.filterCaseSensitivityCheckBox.toggled.connect(self.filterRegExpChanged)
        self.sortCaseSensitivityCheckBox.toggled.connect(self.sortChanged)

        sourceLayout = QHBoxLayout()
        sourceLayout.addWidget(self.sourceView)
        self.sourceGroupBox.setLayout(sourceLayout)

        proxyLayout = QGridLayout()
        proxyLayout.addWidget(self.proxyView, 0, 0, 1, 3)
        proxyLayout.addWidget(self.filterPatternLabel, 1, 0)
        proxyLayout.addWidget(self.filterPatternLineEdit, 1, 1, 1, 2)
        proxyLayout.addWidget(self.filterSyntaxLabel, 2, 0)
        proxyLayout.addWidget(self.filterSyntaxComboBox, 2, 1, 1, 2)
        proxyLayout.addWidget(self.filterColumnLabel, 3, 0)
        proxyLayout.addWidget(self.filterColumnComboBox, 3, 1, 1, 2)
        proxyLayout.addWidget(self.filterCaseSensitivityCheckBox, 4, 0, 1, 2)
        proxyLayout.addWidget(self.sortCaseSensitivityCheckBox, 4, 2)
        self.proxyGroupBox.setLayout(proxyLayout)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.sourceGroupBox)
        mainLayout.addWidget(self.proxyGroupBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("Basic Sort/Filter Model")
        self.resize(500, 450)

        self.proxyView.sortByColumn(1, Qt.AscendingOrder)
        self.filterColumnComboBox.setCurrentIndex(1)

        self.filterPatternLineEdit.setText("Andy|Grace")
        self.filterCaseSensitivityCheckBox.setChecked(True)
        self.sortCaseSensitivityCheckBox.setChecked(True)

    def setSourceModel(self, model):
        self.proxyModel.setSourceModel(model)
        self.sourceView.setModel(model)

    def filterRegExpChanged(self):
        syntax_nr = self.filterSyntaxComboBox.currentData()
        pattern = self.filterPatternLineEdit.text()
        if syntax_nr == WILDCARD:
            pattern = QRegularExpression.wildcardToRegularExpression(pattern)
        elif syntax_nr == FIXED_STRING:
            pattern = QRegularExpression.escape(pattern)

        regExp = QRegularExpression(pattern)
        if not self.filterCaseSensitivityCheckBox.isChecked():
            options = regExp.patternOptions()
            options |= QRegularExpression.CaseInsensitiveOption
            regExp.setPatternOptions(options)
        self.proxyModel.setFilterRegularExpression(regExp)

    def filterColumnChanged(self):
        self.proxyModel.setFilterKeyColumn(self.filterColumnComboBox.currentIndex())

    def sortChanged(self):
        if self.sortCaseSensitivityCheckBox.isChecked():
            caseSensitivity = Qt.CaseSensitive
        else:
            caseSensitivity = Qt.CaseInsensitive

        self.proxyModel.setSortCaseSensitivity(caseSensitivity)
Exemple #26
0
class MainWindow(QMainWindow):
    def __init__(self, app):
        super(MainWindow, self).__init__()
        self._app = app
        self._selectedIndex = None

        # model
        nodeFactory = NodeFactory()
        rootNode = nodeFactory.create(NodeType.General, 'Root')
        # for i in range(10000):  # for testing
        childNode0 = nodeFactory.create(NodeType.General, 'RightPirateLeg',
                                        rootNode)
        childNode1 = nodeFactory.create(NodeType.General, 'RightPirateLeg_END',
                                        childNode0)
        childNode2 = nodeFactory.create(NodeType.General, 'LeftFemur',
                                        rootNode)
        childNode3 = nodeFactory.create(NodeType.Sphere, 'LeftTibia',
                                        childNode2)
        childNode4 = nodeFactory.create(NodeType.Sphere, 'LeftFoot',
                                        childNode3)
        transform = childNode4.component(ComponentType.Transform)
        qTransform = transform.component()
        translation = qTransform.translation()
        translation.setX(5)
        qTransform.setTranslation(translation)

        # childNode5 = nodeFactory.create(NodeType.Box, 'LeftFoot_END', childNode4)
        self._model = SceneGraphModel(rootNode)

        self._sceneView = SceneView(rootNode.entity())
        self._container = self.createWindowContainer(self._sceneView)

        # scene graph view
        self._treeView = QTreeView()
        self._treeView.setModel(self._model)
        self._treeView.setHeaderHidden(True)
        self._treeView.setAlternatingRowColors(True)

        dockWidget = QDockWidget()
        dockWidget.setWidget(self._treeView)
        dockWidget.setWindowTitle('Scene Graph')
        dockWidget.setObjectName('sceneGraph')
        sceneGraphToggleAction = dockWidget.toggleViewAction()
        self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget)

        # property editor
        propertyEditor = PropertyEditor(self._model, nodeFactory,
                                        FieldFactory())

        dockWidget = QDockWidget()
        dockWidget.setWidget(propertyEditor)
        dockWidget.setWindowTitle('Property Editor')
        dockWidget.setObjectName('propertyEditor')
        propertyEditorToggleAction = dockWidget.toggleViewAction()
        self.addDockWidget(Qt.RightDockWidgetArea, dockWidget)

        # menu
        menuBar = self.menuBar()
        menu = menuBar.addMenu('&File')
        exitAction = menu.addAction('E&xit')
        exitAction.triggered.connect(self.close)
        menu.addAction(exitAction)
        menu = menuBar.addMenu('&Windows')
        menu.addAction(sceneGraphToggleAction)
        menu.addAction(propertyEditorToggleAction)
        menuBar.addMenu(menu)

        # central widget
        #button = QPushButton()
        self.setCentralWidget(self._container)

        # selection change event
        selectionModel = self._treeView.selectionModel()
        selectionModel.currentChanged.connect(propertyEditor.changeSelection)

        # click event
        #button.clicked.connect(self.buttonClicked)

    def selectedNode(self):
        indices = self._treeView.selectedIndexes()
        result = None
        if len(indices) == 1:
            self._selectedIndex = indices[0]
            result = self._selectedIndex.internalPointer()
        return result

    def commitChange(self):
        self._model.dataChanged.emit(self._selectedIndex, self._selectedIndex)

    def closeEvent(self, event):
        self._app.exit()

    # data change example
    def buttonClicked(self):
        node = self.selectedNode()
        if not node:
            return
        general = node.component(ComponentType.General)
        general.setName('CLICKED')
        self.commitChange()
Exemple #27
0
class MyWindow(QWidget):
    def __init__(self, *args):
        super().__init__()

        self.setFixedSize(930, 631)
        self.setLocale(QLocale(QLocale.English, QLocale.UnitedStates))
        self.setWindowTitle(
            QCoreApplication.translate("MainWindow", "PyInspect"))

        self.central_widget = QWidget(self)

        self.comboBox = QComboBox(self.central_widget)
        self.comboBox.setGeometry(QRect(10, 10, 451, 22))
        self.comboBox.setMouseTracking(False)
        self.comboBox.setMaxVisibleItems(5)
        self.comboBox.setObjectName("comboBox")

        for _backend in backend.registry.backends.keys():
            self.comboBox.addItem(_backend)

        self.tree_view = QTreeView(self.central_widget)
        self.tree_view.setGeometry(QRect(10, 40, 451, 581))
        self.tree_view.setColumnWidth(0, 150)

        self.comboBox.setCurrentText('uia')
        self.__show_tree()

        self.table_view = QTableView(self.central_widget)
        self.table_view.setGeometry(QRect(470, 40, 451, 581))

        self.comboBox.activated[str].connect(self.__show_tree)
        self.tree_view.clicked.connect(self.__show_property)

    def __show_tree(self, _backend='uia'):
        self.__initialize_calc(_backend)

    def __initialize_calc(self, _backend):
        self.element_info = backend.registry.backends[
            _backend].element_info_class()
        self.tree_model = MyTreeModel(self.element_info, _backend)
        self.tree_model.setHeaderData(0, Qt.Horizontal, 'Controls')
        self.tree_view.setModel(self.tree_model)

    def __show_property(self, index=None):
        data = index.data()
        self.table_model = MyTableModel(self.tree_model.props_dict.get(data),
                                        self)
        self.table_view.wordWrap()
        self.table_view.setModel(self.table_model)
        self.table_view.setColumnWidth(1, 320)

        element = self.tree_model.element_dict.get(data, None)
        if element is not None:
            with contextlib.suppress(Exception):
                element.set_focus()

            locate_element = center_locate_element(element)
            if locate_element is not None:
                pyperclip.copy('{0}, {1}'.format(*locate_element))
            else:
                pyperclip.copy('Retângulo não identificado.')

            try:
                im: Image = element.capture_as_image()
                im.show()
            except:
                alert(
                    title='Atenção',
                    text=
                    'O elemento selecionado não é uma imagem ou não contém o atributo show.'
                )

            element.draw_outline(colour='green', thickness=4)
Exemple #28
0
class NavigationWidget(QWidget):
    def __init__(self, index_filename):
        QWidget.__init__(self)

        self.data_index = pd.DataFrame()
        self.data_info = aecg.tools.indexer.StudyInfo()
        self.data_index_stats = aecg.tools.indexer.StudyStats(
            self.data_info, self.data_index)

        # Getting the Models
        self.project_loaded = ''
        self.projectmodel = ProjectTreeModel()

        # Creating a QTreeView for displaying the selected project index
        self.project_treeview = QTreeView()
        self.project_treeview.setModel(self.projectmodel)
        self.phorizontal_header = self.project_treeview.header()
        self.phorizontal_header.setSectionResizeMode(
            QHeaderView.ResizeToContents)
        self.phorizontal_header.setStretchLastSection(True)

        self.sp_right = QSplitter(Qt.Orientation.Horizontal)
        self.sp_left = QSplitter(Qt.Orientation.Vertical, self.sp_right)
        # NavigationWidget Layout
        self.main_layout = QVBoxLayout()
        size = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

        # Left side
        # Left side - Top layout
        # Left side - Bottom Layout
        size.setVerticalStretch(4)
        self.project_treeview.setSizePolicy(size)

        self.sp_left.addWidget(self.project_treeview)

        # Right side
        size = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        size.setHorizontalStretch(2)
        size.setHeightForWidth(False)
        self.tabdisplays = TabDisplays(self)
        self.sp_right.addWidget(self.tabdisplays)
        self.tabdisplays.validator_data_ready.connect(
            self.load_projectindex_after_validation)
        self.sp_right.setSizePolicy(size)

        # Set the layout to the QWidget
        self.main_layout.addWidget(self.sp_right)
        self.setLayout(self.main_layout)

        self.tabdisplays.setCurrentWidget(self.tabdisplays.validator)

        # Load study index
        if index_filename and (index_filename != ""):
            if os.path.exists(index_filename):
                self.load_projectindex(os.path.normpath(index_filename))
            else:
                QMessageBox.warning(self, f"Study index file not found",
                                    f"{index_filename} not found")

    projectindex_loaded = Signal()
    projectindexstats_loaded = Signal()

    def load_projectindex_after_validation(self):
        self.load_projectindex(
            os.path.normpath(self.tabdisplays.study_info_file.text()))

    def load_projectindex(self, project_idx_file):
        index_loaded = False
        stats_loaded = False
        if project_idx_file != "":
            if os.path.exists(project_idx_file):
                try:
                    self.parent().status.showMessage(
                        f"Loading {project_idx_file}")
                    progress = QProgressDialog("Loading index file...",
                                               "Cancel", 0, 3, self)
                    progress.setWindowTitle("Loading study index")
                    progress.setWindowModality(Qt.WindowModal)
                    progress.setMinimumWidth(300)
                    progress.setMinimumDuration(0)
                    progress.forceShow()
                    progress.setValue(0)
                    wb = load_workbook(project_idx_file, read_only=True)
                    progress.setValue(1)
                    ws = wb['Index']
                    ws.reset_dimensions()
                    data = ws.values
                    cols = next(data)
                    data = list(data)
                    progress.setValue(2)
                    self.data_index = pd.DataFrame(data,
                                                   columns=cols).fillna("")
                    progress.setValue(3)
                    progress.close()
                    # Parse index to the tree
                    num_ecgs = 0
                    if "EGREFID" in self.data_index.columns:
                        num_ecgs = self.data_index[[
                            "ZIPFILE", "AECGXML", "EGREFID", "WFTYPE"
                        ]].drop_duplicates().shape[0]
                        progress = QProgressDialog("Parsing index ...",
                                                   "Cancel", 0, num_ecgs, self)
                        progress.setWindowTitle("Loading study index")
                        progress.setLabelText("Parsing index...")
                        progress.setWindowModality(Qt.WindowModal)
                        progress.setMinimumWidth(300)
                        progress.setMinimumDuration(0)
                        progress.forceShow()
                        progress.setValue(0)
                        self.projectmodel = ProjectTreeModel(
                            self.data_index, progress_dialog=progress)
                        self.project_treeview.setModel(self.projectmodel)
                        self.project_treeview.selectionModel().\
                            selectionChanged.connect(self.load_data)
                        progress.close()
                    else:
                        QMessageBox.warning(
                            self, "EGREFID missing",
                            f"EGREFID column missing Index sheet of "
                            f"{project_idx_file}")
                    self.project_loaded = project_idx_file

                    # Reset aECG display
                    self.tabdisplays.aecg_display.aecg_data = None
                    self.tabdisplays.aecg_display.plot_aecg()

                    # Populate study information/validator tab
                    self.tabdisplays.load_study_info(project_idx_file)
                    self.data_index_info = self.tabdisplays.studyindex_info

                    index_loaded = True
                    try:
                        progress = QProgressDialog(
                            "Loading study index stats...", "Cancel", 0, 3,
                            self)
                        progress.setWindowTitle("Loading study index stats")
                        progress.setWindowModality(Qt.WindowModal)
                        progress.setMinimumWidth(300)
                        progress.setMinimumDuration(0)
                        progress.forceShow()
                        progress.setValue(0)
                        ws = wb['Stats']
                        ws.reset_dimensions()
                        data = ws.values
                        cols = next(data)
                        data = list(data)
                        progress.setValue(1)
                        progress.forceShow()
                        statsdf = pd.DataFrame(data, columns=cols).fillna("")
                        progress.setValue(2)
                        progress.forceShow()
                        self.data_index_stats = aecg.tools.indexer.StudyStats()
                        self.data_index_stats.__dict__.update(
                            statsdf.set_index("Property").transpose().
                            reset_index(drop=True).to_dict('index')[0])
                        progress.setValue(3)
                        progress.forceShow()
                        progress.close()
                        stats_loaded = True
                    except Exception as ex:
                        QMessageBox.warning(
                            self, f"Error loading study index stats",
                            f"Error loading study index stats from"
                            f"{project_idx_file}\n{str(ex)}")
                except Exception as ex:
                    QMessageBox.warning(
                        self, f"Error loading study index",
                        f"Error loading study index from {project_idx_file}"
                        f"\n{str(ex)}")
            else:
                QMessageBox.warning(self, f"Study index file not found",
                                    f"{project_idx_file} not found")

            if index_loaded:
                self.projectindex_loaded.emit()
                if stats_loaded:
                    self.projectindexstats_loaded.emit()
            self.parentWidget().status.clearMessage()

    def load_data(self, selected, deselected):
        self.tabdisplays.setCurrentWidget(self.tabdisplays.waveforms)
        rhythm = self.projectmodel.itemData(selected.indexes()[2])[0]
        derived = self.projectmodel.itemData(selected.indexes()[3])[0]
        # Get study directory provided in the GUI
        studydir = self.tabdisplays.effective_aecgs_dir(self, silent=True)
        # Calculate effective study dir
        aecg_xml_file = self.projectmodel.itemData(selected.indexes()[5])[0]
        if aecg_xml_file != "":
            zipfile = self.projectmodel.itemData(selected.indexes()[4])[0]
            if zipfile != "":
                zipfile = os.path.join(studydir, zipfile)
            else:
                aecg_xml_file = os.path.join(studydir, aecg_xml_file)
            # Load aECG file
            aecg_data = aecg.io.read_aecg(aecg_xml_file,
                                          zipfile,
                                          include_digits=True,
                                          in_memory_xml=True,
                                          log_validation=False)
            if aecg_data.xmlfound:
                # Plot aECG
                self.tabdisplays.aecg_display.set_aecg(aecg_data)
                self.tabdisplays.aecg_display.plot_aecg(
                    rhythm,
                    derived,
                    ecg_layout=aecg.utils.ECG_plot_layout(
                        self.tabdisplays.cbECGLayout.currentIndex() + 1))

                # Populate XML viewer
                self.tabdisplays.xml_display.setText(aecg_data.xmlstring())
            else:
                QMessageBox.warning(self, "aECG XML file not found",
                                    f"aECG XML {aecg_xml_file} not found")
                self.parentWidget().update_status_bar()
Exemple #29
0
class MP3TagManipulator(QWidget):
    last_directory = '.'
    song = None

    def __init__(self):
        super().__init__()
        self.title = 'MP3TagManipulator v1.0'
        self.top = 100
        self.left = 100
        self.height = 400
        self.width = 640

        self.init_ui()

    def init_ui(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)

        # layout root of application
        main_layout = QVBoxLayout(self)
        self.setLayout(main_layout)

        # to set the model of tree
        model = QFileSystemModel()
        model.setRootPath("/home/denison/Downloads/music")
        model.setNameFilters(['*.mp3', '*.m4a', '*.flac'])
        model.setNameFilterDisables(False)

        self.tree = QTreeView()
        self.tree.setModel(model)
        self.tree.setAnimated(True)
        self.tree.setColumnWidth(0, 500)

        file_layout = QHBoxLayout()
        label_file = QLabel('file/directory')
        text_file = QLineEdit()
        btn_load = QPushButton('load')
        file_layout.addWidget(label_file)
        file_layout.addWidget(text_file)
        file_layout.addWidget(btn_load)

        grid_info_layout = QGridLayout()
        # strings to labels
        self.labels = [
            'ARTIST', 'ALBUMARTIST', 'ALBUM', 'TITLE', 'GENRE', 'DATE'
        ]

        # line edits to tags
        self.text_artist = QLineEdit('ARTIST')
        self.text_album = QLineEdit('ALBUM')
        self.text_album_artist = QLineEdit('ALBUMARTIST')
        self.text_title = QLineEdit('TITLE')
        self.text_genre = QLineEdit('GENRE')
        self.text_date = QLineEdit('DATE')

        self.text_tags = [
            self.text_artist, self.text_album_artist, self.text_album,
            self.text_title, self.text_genre, self.text_date
        ]

        for text in self.text_tags:
            text.setEnabled(False)
            #text.textChanged.connect(self.enable_save)

        # labels
        for label, i in zip(self.labels, range(6)):
            grid_info_layout.addWidget(QLabel(label), i, 0)

        # cb_artist = QCheckBox()
        # cb_album_artist = QCheckBox()
        # cb_album = QCheckBox()
        # cb_title = QCheckBox()
        # cb_genre = QCheckBox()
        # cb_date = QCheckBox()
        # self.checkboxes = [
        #     cb_artist, cb_album_artist, cb_album,
        #     cb_title, cb_genre, cb_date
        # ]

        # for cb in self.checkboxes:
        #     cb.setText('editar')

        # cb_artist.stateChanged.connect(lambda: self.enable_tag_edit(self.text_artist))
        # cb_album_artist.stateChanged.connect(lambda: self.enable_tag_edit(self.text_album_artist))
        # cb_album.stateChanged.connect(lambda: self.enable_tag_edit(self.text_album))
        # cb_title.stateChanged.connect(lambda: self.enable_tag_edit(self.text_title))
        # cb_genre.stateChanged.connect(lambda: self.enable_tag_edit(self.text_genre))
        # cb_date.stateChanged.connect(lambda: self.enable_tag_edit(self.text_date))

        for i, text in zip(range(6), self.text_tags):
            grid_info_layout.addWidget(text, i, 1)

        # for cb, i in zip(self.checkboxes, range(6)) :
        #     grid_info_layout.addWidget(cb, i, 2)

        action_layout = QHBoxLayout()
        btn_exit = QPushButton('Exit')
        self.btn_save = QPushButton('save changes')
        self.btn_save.setDisabled(True)
        action_layout.addWidget(btn_exit)
        action_layout.addWidget(self.btn_save)

        #main_layout.addLayout(file_layout)
        main_layout.addWidget(self.tree)
        main_layout.addLayout(grid_info_layout)
        main_layout.addLayout(action_layout)

        btn_load.clicked.connect(self.open_file)
        btn_exit.clicked.connect(self.close_application)
        self.btn_save.clicked.connect(self.edit_tags)
        self.tree.doubleClicked.connect(self.get_selected_file)
        self.show()

    def enable_edit_text(self):
        if self.song:
            for t in self.text_tags:
                t.setEnabled(True)
            self.enable_save()
        else:
            for t in self.text_tags:
                t.setEnabled(False)

    def enable_save(self):
        self.btn_save.setEnabled(True)

    def close_application(self):
        if self.song:
            self.song.close()
        print('vazando...;-)')
        self.close()

    def enable_tag_edit(self, txt_edit):
        txt_edit.setEnabled(not txt_edit.isEnabled())
        for edit in self.text_tags:
            edit.textChanged.connect(self.enable_save)
        print('executou self.enable_tag_edit()')
        print('não sei o q tá acontecendo :(')

    def get_selected_file(self):
        print('executou self.get_selected_file()')
        selected = self.tree.selectedIndexes()[0]
        print(selected.model().filePath(selected))
        self.song = taglib.File(selected.model().filePath(selected))
        self.enable_edit_text()
        self.load_song_info(self.song)
        return self.song

    def edit_tags(self):
        print("não tá funcionando 8'-(")
        self.song.tags['ARTIST'] = self.text_artist.text()
        self.song.tags['ALBUMARTIST'] = self.text_album_artist.text()
        self.song.tags['ALBUM'] = self.text_album.text()
        self.song.tags['TITLE'] = self.text_title.text()
        self.song.tags['GENRE'] = self.text_genre.text()
        self.song.tags['DATE'] = self.text_date.text()
        self.song.save()
        print(self.song.tags)
        self.btn_save.setDisabled(True)
        self.song.close()

    def open_file(self):
        print('*** quase lá *** ')
        dialog = QFileDialog(self)
        dialog.setViewMode(QFileDialog.Detail)
        file = dialog.getOpenFileName(self, 'load...', self.last_directory,
                                      'songs (*.mp3 *.m4a *.flac *.wma)')
        song = taglib.File(file[0])
        # print(song.tags)
        self.show_song_info(song)
        song.close()

    def load_song_info(self, song):
        print('executou self.load_song_info()')
        for t, tag in zip(self.text_tags, self.labels):
            try:
                t.setText(song.tags[tag][0])
            except KeyError:
                t.setText('none')
Exemple #30
0
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
## $QT_END_LICENSE$
##
#############################################################################
"""PySide2 port of the remoteobjects/modelviewclient example from Qt v5.x"""

import sys

from PySide2.QtCore import QUrl
from PySide2.QtWidgets import (QApplication, QTreeView)
from PySide2.QtRemoteObjects import QRemoteObjectNode

if __name__ == '__main__':
    app = QApplication(sys.argv)
    node = QRemoteObjectNode(QUrl("local:registry"))
    node.setHeartbeatInterval(1000)
    view = QTreeView()
    view.setWindowTitle("RemoteView")
    view.resize(640, 480)
    model = node.acquireModel("RemoteModel")
    view.setModel(model)
    view.show()

    sys.exit(app.exec_())
Exemple #31
0
class ProjectWidget(QSplitter):

    treeCurrentItemChanged = Signal(Container)

    def __init__(self, parent, f=...):
        super().__init__(parent, f)
        self.project = Project()
        self.current_tree_item: Optional[Container] = None

        self.main_splitter = self  # inheritance from QSplitter may not be preserved
        self.main_splitter.setOrientation(Qt.Horizontal)
        self.left_splitter = QSplitter(Qt.Vertical)
        self.right_splitter = QSplitter(Qt.Vertical)
        self.main_splitter.addWidget(self.left_splitter)
        self.main_splitter.addWidget(self.right_splitter)

        # self.w_parameters = ParametersWidget(self.project.bundle)
        self.w_parameters_tree = QTreeView()
        self.w_parameters_tree.setModel(self.project.parameters_model)
        delegate = ParametersTableDelegate()
        self.w_parameters_tree.setItemDelegate(delegate)
        self.selection_model_parameters = self.w_parameters_tree.selectionModel(
        )
        self.selection_model_parameters.currentRowChanged.connect(
            self._on_tree_row_changed)

        self.w_curves_tree = QTreeView()
        self.w_curves_tree.setModel(self.project.curves_model)
        delegate = CurvesTableDelegate()
        self.w_curves_tree.setItemDelegate(delegate)
        self.selection_model_curves = self.w_curves_tree.selectionModel()
        self.selection_model_curves.currentRowChanged.connect(
            self._on_tree_row_changed)

        self.w_light_plot = LightPlotWidget(self.project.curves_model)
        self.w_rv_plot = RvPlotWidget(self.project.curves_model)

        self.left_splitter.addWidget(self.w_parameters_tree)
        self.left_splitter.addWidget(self.w_curves_tree)

        self.right_splitter.addWidget(self.w_light_plot)
        self.right_splitter.addWidget(self.w_rv_plot)

    def resizeEvent(self, arg__1: PySide2.QtGui.QResizeEvent):
        super().resizeEvent(arg__1)

    def save_session(self, settings: QSettings):
        settings.beginGroup('project_splitter')
        settings.setValue('horiz', self.main_splitter.saveState())
        settings.setValue('vert_trees', self.left_splitter.saveState())
        settings.setValue('vert_plots', self.right_splitter.saveState())
        settings.endGroup()
        settings.beginGroup('tree_columns')
        settings.setValue('params',
                          self.w_parameters_tree.header().saveState())
        settings.setValue('curves', self.w_curves_tree.header().saveState())
        settings.endGroup()

    def restore_session(self, settings: QSettings):
        settings.beginGroup('project_splitter')
        try:
            self.main_splitter.restoreState(settings.value("horiz"))
            self.left_splitter.restoreState(settings.value("vert_trees"))
            self.right_splitter.restoreState(settings.value("vert_plots"))
        except AttributeError:
            pass
        settings.endGroup()
        settings.beginGroup('tree_columns')
        try:
            self.w_parameters_tree.header().restoreState(
                settings.value("params"))
            self.w_curves_tree.header().restoreState(settings.value("curves"))
        except AttributeError:
            pass
        settings.endGroup()

    @Slot(QModelIndex, QModelIndex)
    def _on_tree_row_changed(self, current: QModelIndex,
                             previous: QModelIndex):
        model = current.model()

        prev_item, prev_column = model.item_and_column(previous)
        curr_item, curr_column = model.item_and_column(current)

        logger().info(f'Selection changed {prev_item} -> {curr_item}')
        self.current_tree_item = curr_item

        self.treeCurrentItemChanged.emit(curr_item)

    @Slot()
    def add_lc(self):
        self.project.add_lc()

    @Slot()
    def add_rv(self):
        self.project.add_rv()

    @Slot()
    def del_curve(self):
        to_del = self.current_tree_item
        while to_del is not None and not isinstance(to_del, CurveContainer):
            to_del = to_del.parent()
        if QMessageBox.question(self, 'Deleting Curve Confirmation', f'Delete the curve "{to_del.objectName()}"?') \
                != QMessageBox.Yes:
            return
        self.project.delete_curve(to_del)