def createLeftSide(self):
        self.leftSideGB = QGroupBox()

        home_directory = "./app/"

        palette = QPalette()
        palette.setColor(QPalette.Window, QColor(30, 30, 30))

        model = QDirModel()
        view = QTreeView()
        view.setStyleSheet("QTreeView { border: 0px; }")
        view.setModel(model)
        view.setRootIndex(model.index(home_directory))
        view.setColumnHidden(1, True)
        view.setColumnHidden(2, True)
        view.setColumnHidden(3, True)
        view.show()
        view.setPalette(palette)

        runButton = QPushButton("►")
        stopButton = QPushButton("❚❚")

        bottomBar = QHBoxLayout()
        bottomBar.addWidget(runButton)
        bottomBar.addWidget(stopButton)

        layout = QVBoxLayout()
        layout.addWidget(view)
        layout.addLayout(bottomBar)
        layout.setStretch(0, 2)
        self.leftSideGB.setLayout(layout)
Exemple #2
0
    def __initFileTreeView__(self, model):
        treeView = QTreeView()
        treeView.setIndentation(20)
        treeView.setSortingEnabled(True)
        treeView.setMinimumWidth(100)
        treeView.setModel(model)
        treeView.setRootIndex(model.index(r'C:'))

        for i in range(1, 5):
            treeView.hideColumn(i)

        return treeView
Exemple #3
0
class App(QWidget):
    '''The FolderMaker base class'''
    def __init__(self, root_path, conf):
        super().__init__()
        self.title = 'FolderMaker'
        self.root_path = root_path
        self.conf = conf
        self.init_ui()

    def on_btn(self):
        '''Creates buttons on click'''
        basedir = ROOT_PATH
        try:
            create_dirs(
                self.conf, basedir,
                range(int(self.start_box.text()), int(self.stop_box.text())))
        except ValueError:
            msg = QMessageBox()
            msg.setText('Error! Invalid numbers in text boxes!')
            msg.exec()
        except FileExistsError as file_ex:
            msg = QMessageBox()
            msg.setText(
                f'Error! Directory already exists! Exception: {str(file_ex)}')
            msg.exec()

    def init_ui(self):
        '''Initializes the UI'''
        self.setWindowTitle(self.title)
        self.model = QFileSystemModel()
        self.model.setRootPath(ROOT_PATH)
        self.tree = QTreeView()
        self.tree.setModel(self.model)
        self.tree.setRootIndex(self.model.index(self.root_path))
        self.start_box = QLineEdit()
        self.stop_box = QLineEdit()
        self.start_box.setValidator(QIntValidator())
        self.stop_box.setValidator(QIntValidator())
        self.make_btn = QPushButton("Create Project Folders")
        self.make_btn.clicked.connect(self.on_btn)
        layout = QVBoxLayout()
        layout.addWidget(self.tree)
        subgrid = QGridLayout()
        subgrid.addWidget(self.start_box, 0, 1)
        subgrid.addWidget(self.stop_box, 1, 1)
        subgrid.addWidget(QLabel('From (inc.): '), 0, 0)
        subgrid.addWidget(QLabel('To (not inc.): '), 1, 0)
        layout.addLayout(subgrid)
        layout.addWidget(self.make_btn)
        self.setLayout(layout)
        self.show()
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 #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
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 #7
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 #8
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 #9
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)
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()
Exemple #11
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 #12
0
class FileSystemWidget(QWidget):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.currentRootPath = '/'
        self.currentPath = QDir.currentPath()

        self.mainWindow = parent

        self.chooseDirAction = QAction(IconFactory.getIcon('folder'),
                                       'Root directory',
                                       self,
                                       statusTip="Change root directory",
                                       triggered=self.chooseRootDir)
        self.showOFAction = QAction(IconFactory.getIcon('filter_alt'),
                                    'Show only FITS files',
                                    self,
                                    statusTip="Show only FITS/all files",
                                    triggered=self.showOFFiles)
        self.showOFAction.setCheckable(True)
        self.showOFAction.toggled.connect(self.showOFFiles)

        self.chooseDirBtn = QToolButton()
        self.chooseDirBtn.setDefaultAction(self.chooseDirAction)

        self.showOFBtn = QToolButton()
        self.showOFBtn.setDefaultAction(self.showOFAction)

        iconlayout = QHBoxLayout()
        iconlayout.setAlignment(Qt.AlignLeft)
        iconlayout.addWidget(self.chooseDirBtn)
        iconlayout.addWidget(self.showOFBtn)

        self.viewsSplitter = QSplitter(Qt.Horizontal)
        self.viewsSplitter.splitterMoved.connect(self.splitterMoved)

        self.dirsModel = QFileSystemModel(self)
        self.dirsModel.setOption(QFileSystemModel.DontWatchForChanges, True)
        self.dirsModel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs)
        self.dirsModel.setNameFilterDisables(False)

        self.dirs = QTreeView()
        self.dirs.setModel(self.dirsModel)
        self.dirs.hideColumn(1)
        self.dirs.hideColumn(2)
        self.dirs.hideColumn(3)

        self.dirs.clicked.connect(self.onDirsClick)
        self.dirs.doubleClicked.connect(self.onDirsDoubleClick)

        self.filesModel = QFileSystemModel(self)
        self.filesModel.setOption(QFileSystemModel.DontWatchForChanges, True)
        self.filesModel.setFilter(QDir.NoDotAndDotDot | QDir.Files)
        self.filesModel.setNameFilterDisables(False)

        self.files = QListView()
        self.files.setModel(self.filesModel)
        self.files.doubleClicked.connect(self.onFilesDoubleClick)

        self.viewsSplitter.addWidget(self.dirs)
        self.viewsSplitter.addWidget(self.files)
        viewslayout = QHBoxLayout()
        viewslayout.addWidget(self.viewsSplitter)

        layout = QVBoxLayout()
        layout.addLayout(iconlayout)
        layout.addLayout(viewslayout)

        self.setLayout(layout)

        self.dirsModel.setRootPath(self.currentRootPath)
        self.dirs.setRootIndex(self.dirsModel.index(self.currentRootPath))

        index = self.dirsModel.index(self.currentPath)
        self.dirs.setCurrentIndex(index)
        self.dirs.setExpanded(index, True)

        self.filesModel.setRootPath(self.currentPath)
        self.files.setRootIndex(self.filesModel.index(self.currentPath))

    def splitterMoved(self, pos, index):
        if pos == 0:
            self.filesModel.setFilter(QDir.NoDot | QDir.AllEntries
                                      | QDir.DirsFirst | QDir.Type)
        elif pos == self.viewsSplitter.width(
        ) - self.viewsSplitter.handleWidth():
            self.dirsModel.setFilter(QDir.NoDotAndDotDot | QDir.AllEntries)
        else:
            self.dirsModel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs)
            self.filesModel.setFilter(QDir.NoDotAndDotDot | QDir.Files)

    def onDirsClick(self, item):
        index = self.dirs.selectedIndexes()[0]
        info = self.dirsModel.fileInfo(index)
        if info.isDir():
            self.currentPath = info.filePath()
            self.files.setRootIndex(
                self.filesModel.setRootPath(info.filePath()))

    def onDirsDoubleClick(self, item):
        index = self.dirs.selectedIndexes()[0]
        info = self.dirsModel.fileInfo(index)
        if info.isDir():
            self.currentPath = info.filePath()
            self.files.setRootIndex(
                self.filesModel.setRootPath(info.filePath()))
        else:
            self.mainWindow.open_fits(info.filePath())

    def onFilesDoubleClick(self, item):
        index = self.files.selectedIndexes()[0]
        info = self.filesModel.fileInfo(index)
        if info.isDir():
            self.setPath(info.filePath())
        else:
            try:
                self.mainWindow.open_fits(info.filePath())
            except FileNotFoundError:
                self.setPath(self.currentPath)  # refesh maybe?

    def setPath(self, path):
        self.currentPath = path

        index = self.dirsModel.index(self.currentPath)
        self.dirs.setCurrentIndex(index)
        self.dirs.setExpanded(index, True)

        self.files.setRootIndex(self.filesModel.setRootPath(self.currentPath))

    def chooseRootDir(self):
        dir = QFileDialog.getExistingDirectory(self, 'Select directory')
        if dir:
            self.setRootPath(dir)

    def setRootPath(self, dir):
        self.currentRootPath = dir

        self.dirsModel.setRootPath(self.currentRootPath)
        self.dirs.setRootIndex(self.dirsModel.index(self.currentRootPath))

        self.setPath(self.currentRootPath)

    def showOFFiles(self):
        if self.showOFAction.isChecked():
            self.dirsModel.setNameFilters(["*.FITS", "*.fits"])
            self.filesModel.setNameFilters(["*.FITS", "*.fits"])
        else:
            self.dirsModel.setNameFilters(["*"])
            self.filesModel.setNameFilters(["*"])

    def writeSettings(self, settings):
        settings.beginGroup("fileWidget")
        settings.setValue('splitterGeometry',
                          self.viewsSplitter.saveGeometry())
        settings.setValue('splitterState', self.viewsSplitter.saveState())
        settings.setValue('rootPath', self.currentRootPath)
        settings.setValue('path', self.currentPath)
        settings.endGroup()

    def readSettings(self, settings):
        settings.beginGroup("fileWidget")
        self.viewsSplitter.restoreGeometry(settings.value("splitterGeometry"))
        self.viewsSplitter.restoreState(settings.value("splitterState"))
        rootPath = settings.value("rootPath")
        path = settings.value("path")
        settings.endGroup()

        if rootPath is None:
            rootPath = '/'
        self.setRootPath(rootPath)

        if path is None:
            path = QDir.currentPath()
        self.setPath(path)

        self.splitterMoved(self.viewsSplitter.handle(1).pos().x(), 0)
Exemple #13
0
class TestController(Window):
    """Contains code for  the window that the user initially sees"""
    def __init__(self):
        if not path.exists(algorithm_directory):
            os.makedirs(algorithm_directory, exist_ok=True)

        self.fmodel = QFileSystemModel()
        self.fmodel.setRootPath(algorithm_directory)
        self.module_list = QTreeView()
        self.module_list.setModel(self.fmodel)
        self.module_list.setRootIndex(self.fmodel.index(algorithm_directory))
        self.module_button = QPushButton("Change Directory")
        self.module_button.clicked.connect(self.change_dir)

        self.start_date = ToggleButton('Start Date')
        self.end_date = ToggleButton('End Date', 'Default (Present)')

        self.test_types = ['Profit', 'Accuracy']
        self.test_type = QComboBox()
        self.test_type.addItems(self.test_types)

        self.test_output = QTextEdit()
        self.test_output.setDisabled(True)
        self.run_btn = QPushButton('Run Test')

        self.profit = QLCDNumber()
        self.accuracy = QLCDNumber()

        super().__init__('Jencks Stock Algorithm Tester')

    def setup_left_column(self):
        self.left.addWidget(QLabel("Test Files"))
        self.left.addWidget(self.module_list)
        self.left.addWidget(self.module_button)

    def setup_center_column(self):
        hbox = QHBoxLayout()
        hbox.addLayout(self.start_date.box)
        hbox.addLayout(self.end_date.box)
        self.center.addLayout(hbox)
        self.center.addWidget(QLabel('Test Type'))
        self.center.addWidget(self.test_type)
        self.center.addWidget(QLabel('Test Run Output'))
        self.center.addWidget(self.test_output)
        self.center.addWidget(self.run_btn)

    def setup_right_column(self):
        self.right.addWidget(QLabel('Test Diagnostics'))
        self.right.addWidget(QLabel('Profit'))
        self.right.addWidget(self.profit)
        self.right.addWidget(QLabel('Accuracy'))
        self.right.addWidget(self.accuracy)

    def setup_menus(self):
        super().setup_menus()
        self.menu_entries += [(self.edit_menu, 'Preferences',
                               self.open_preferences, 'Ctrl+Alt+P')]

    @Slot()
    def open_preferences(self, checked):
        print('Opening preference menu.')

    @Slot()
    def change_dir(self, checked):
        dialog = QFileDialog()
        fdir = dialog.getExistingDirectory()
        self.fmodel.setRootPath(fdir)
        self.module_list.setRootIndex(self.fmodel.index(fdir))
Exemple #14
0
class Dock(QDockWidget):
    def __init__(self, title, central_widget, parent=None):
        super().__init__(title, parent=parent)
        self.central_widget = central_widget

        self.model = QFileSystemModel()
        self.model.setRootPath(QDir.currentPath())
        self.tree = QTreeView()
        self.tree.pressed.connect(self.setIndex)
        self.index_ = None

        self.db_tree = QTreeView()
        self.db_tree.setAnimated(True)
        self.db_model = QStandardItemModel()
        self.db_model.setHorizontalHeaderLabels(["Database"])
        self.db_root = self.db_model.invisibleRootItem()

        self.dbs = []

    def contextMenuEvent(self, event):
        contextMenu = QMenu(self)
        deleteFile = contextMenu.addAction("Delete File")
        action = contextMenu.exec_(self.mapToGlobal(event.pos()))
        if action == deleteFile:
            alert = QMessageBox()
            alert.setWindowTitle("Action Dialog")
            alert.setText("Are you sure you want to delete this file?")
            alert.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
            alert.setDefaultButton(QMessageBox.No)
            response = alert.exec_()
            if response == QMessageBox.No:
                contextMenu.close()
            else:
                file_name = self.model.filePath(
                    self.index_).split("storage/")[1]
                os.remove(self.model.filePath(self.index_))
                os.remove(
                    self.model.filePath(self.index_).split("/storage")[0] +
                    "/meta/" + file_name + "_metadata.json")
                contextMenu.close()

    def setIndex(self, index):
        self.index_ = index

    def tree_init(self):
        self.tree.setModel(self.model)
        self.tree.setRootIndex(
            self.model.index(QDir.currentPath() + "/model/storage"))

        self.tree.clicked.connect(self.file_clicked)

        self.setWidget(self.tree)

    def init_db_tree(self):
        self.clear_tree()
        self.db_tree.setModel(self.db_model)
        self.db_tree.clicked.connect(self.table_clicked)
        self.setWidget(self.db_tree)
        self.connected_dbs()

    def file_clicked(self, index):
        file_path = self.model.filePath(index)
        workspace = Workspace(file_path, self.central_widget)
        self.central_widget.add_tab(
            workspace,
            QIcon("view/images/dark/baseline_notes_black_48dp.png"),
            file_path.split("storage/")[1],
        )

    def connected_dbs(self):
        if os.path.exists("model/session/connected_dbs") and os.path.getsize(
                "model/session/connected_dbs") > 0:
            self.clear_tree()

            self.dbs = []

            with open("model/session/connected_dbs", "rb") as sessions:
                db_sessions = pickle.load(sessions)

            for db in db_sessions:
                connection = mysql.connect(
                    host=db["host"],
                    user=db["user"],
                    password=db["password"],
                    db=db["db"],
                    charset="utf8mb4",
                    cursorclass=mysql.cursors.DictCursor)

                temp_db = StandardItem(db["db"], 10, is_bold=True)

                self.dbs.append(db["db"])

                try:
                    with connection.cursor() as cursor:
                        cursor.execute("SHOW TABLES")
                        db_tables = cursor.fetchall()

                    for table in db_tables:
                        for key in table.keys():
                            temp_table = StandardItem(table[key], 9)
                            temp_db.appendRow(temp_table)
                finally:
                    connection.close()

                self.db_root.appendRow(temp_db)
        else:
            self.clear_tree()
            self.dbs = []
            no_db = StandardItem("No Connected Databases", 10, is_bold=True)
            self.db_root.appendRow(no_db)

    def table_clicked(self, val):
        self.is_db = False
        if os.path.exists("model/session/connected_dbs") and len(
                self.dbs) != 0:
            for db in self.dbs:
                if db == val.data():
                    self.is_db = True

                    remove_choice = QMessageBox.question(
                        self.db_tree, "Disconnect Database",
                        f'Do you want to remove "{val.data()}" from connected databases?',
                        QMessageBox.Yes | QMessageBox.No)

                    if remove_choice == QMessageBox.Yes:
                        with open("model/session/connected_dbs",
                                  "rb") as sessions:
                            db_sessions = pickle.load(sessions)

                        db_sessions[:] = [
                            db for db in db_sessions
                            if db.get('db') != val.data()
                        ]

                        for db in db_sessions:
                            if db["index"] != 1:
                                db["index"] -= 1

                        self.dbs[:] = [
                            db for db in self.dbs if db != val.data()
                        ]

                        if len(db_sessions) == 0:
                            os.remove("model/session/connected_dbs")
                        else:
                            with open("model/session/connected_dbs",
                                      "wb") as sessions:
                                pickle.dump(db_sessions, sessions)

                        QMessageBox.information(
                            self.db_tree, "(㇏(•̀ᵥᵥ•́)ノ)",
                            f'Database "{val.data()}" successfully disconnected.',
                            QMessageBox.Ok)
                        self.connected_dbs()
                        break

                    if remove_choice == QMessageBox.No:
                        break

            if not self.is_db:
                user_reply = QMessageBox.question(
                    self.db_tree, "Answer. Thanks.",
                    f'Do you want to open the "{val.data()}" table?',
                    QMessageBox.Open | QMessageBox.Cancel)

                if user_reply == QMessageBox.Cancel:
                    pass

                if user_reply == QMessageBox.Open:
                    workspace = DBWorkspace(val.parent().data(), val.data(),
                                            self.central_widget)
                    self.central_widget.add_tab(
                        workspace,
                        QIcon("view/images/menubar/database-connect.png"),
                        val.data(),
                    )

    def clear_tree(self):
        self.db_model.clear()
        self.db_model.setHorizontalHeaderLabels(["Database"])
        self.db_root = self.db_model.invisibleRootItem()
Exemple #15
0
class SVDBrowser(QDialog):
    def __init__(self, context, parent=None):
        super(SVDBrowser, self).__init__(parent)
        QWebEngineProfile.defaultProfile().downloadRequested.connect(
            self.on_downloadRequested)

        # Create widgets
        #self.setWindowModality(Qt.ApplicationModal)
        self.title = QLabel(self.tr("SVD Browser"))
        self.closeButton = QPushButton(self.tr("Close"))
        self.setWindowTitle(self.title.text())
        self.browseButton = QPushButton("Browse SVD Folder")
        self.deleteSvdButton = QPushButton("Delete")
        self.applySvdButton = QPushButton("Apply SVD")
        self.view = QWebEngineView()
        url = "https://developer.arm.com/tools-and-software/embedded/cmsis/cmsis-search"
        self.view.load(QUrl(url))
        self.columns = 3
        self.context = context

        self.currentFileLabel = QLabel()
        self.currentFile = ""

        #Files
        self.files = QFileSystemModel()
        self.files.setRootPath(svdPath)
        self.files.setNameFilters(["*.svd", "*.patched"])

        #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(svdPath))
        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.applySvdButton)
        treeButtons.addWidget(self.deleteSvdButton)
        treeLayout.addLayout(treeButtons)
        treeWidget = QWidget()
        treeWidget.setLayout(treeLayout)

        # Create layout and add widgets
        buttons = QHBoxLayout()
        buttons.addWidget(self.closeButton)

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

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

        hlayout = QHBoxLayout()
        hlayout.addWidget(hsplitter)

        self.showMaximized()  #Fixes bug that maximized windows are "stuck"
        #Because you can't trust QT to do the right thing here

        # Set dialog layout
        self.setLayout(hlayout)

        # Add signals
        self.closeButton.clicked.connect(self.close)
        self.tree.selectionModel().selectionChanged.connect(self.selectFile)
        self.applySvdButton.clicked.connect(self.applySvd)
        self.deleteSvdButton.clicked.connect(self.deleteSvd)
        self.browseButton.clicked.connect(self.browseSvd)

    def browseSvd(self):
        url = QUrl.fromLocalFile(svdPath)
        QDesktopServices.openUrl(url)

    def selectFile(self, new, old):
        if len(new.indexes()) == 0:
            self.tree.clearSelection()
            self.currentFile = ""
            return
        newSelection = self.files.filePath(new.indexes()[0])
        if QFileInfo(newSelection).isDir():
            self.tree.clearSelection()
            self.currentFile = ""
            return
        self.currentFile = newSelection

    def applySvd(self):
        selection = self.tree.selectedIndexes()[::self.columns][
            0]  #treeview returns each selected element in the row
        svdName = self.files.fileName(selection)
        if (svdName != ""):
            question = QMessageBox.question(
                self, self.tr("Confirm"),
                self.
                tr(f"Confirm applying {svdName} to {os.path.basename(self.context.file.filename)} : "
                   ))
            if (question == QMessageBox.StandardButton.Yes):
                log_debug("SVD Browser: Applying SVD %s." % svdName)
                load_svd(self.context, self.currentFile)
                self.close()

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

    def on_downloadRequested(self, download):
        old_path = download.url().path()  # download.path()
        suffix = QFileInfo(old_path).suffix()
        if (suffix.lower() in ["zip", "svd", "pack", "patched"]):
            log_debug(f"SVD Browser: Downloading {str(download.url())}")
            if suffix.lower() == "svd" or suffix.lower() == "patched":
                download.setDownloadDirectory(svdPath)
                download.accept()
            else:
                with TemporaryDirectory() as tempfolder:
                    log_debug(
                        f"SVD Browser: Downloading pack/zip to {tempfolder}")
                    fname = download.url().fileName()
                    r = requests.get(download.url().toString(),
                                     allow_redirects=True)
                    dlfile = os.path.join(tempfolder, fname)
                    open(dlfile, "wb").write(r.content)
                    '''
                    # TODO: See if the original QT Downloader can be fixed since it would
                    # help with situations where the user entered credentials in the browser.
                    download.setDownloadDirectory(tempfolder)
                    download.accept()
                    while not download.finished:
                        import time
                        time.sleep(100)
                    '''
                    if fname.endswith(".zip") or fname.endswith(".pack"):
                        destFolder = os.path.join(svdPath,
                                                  os.path.splitext(fname)[0])
                        log_debug(f"SVD Browser: Creating {destFolder}")
                        if not os.path.exists(destFolder):
                            os.mkdir(destFolder)
                        with ZipFile(dlfile, 'r') as zipp:
                            for ifname in zipp.namelist():
                                if ifname.endswith(".svd"):
                                    info = zipp.getinfo(ifname)
                                    info.filename = os.path.basename(
                                        info.filename)
                                    log_debug(
                                        f"SVD Browser: Extracting {info.filename} from {ifname}"
                                    )
                                    zipp.extract(info, path=destFolder)
                    else:
                        #Move file into place
                        shutil.move(dlfile, svdPath)
        else:
            show_message_box(
                "Invalid file",
                "That download does not appear to be a valid SVD/ZIP/PACK file."
            )
        download.cancel()