def init_file_system_tree(self): model = QFileSystemModel(nameFilterDisables=False) model.setRootPath("Desktop") model.setNameFilters(["*.txt", "*.csv"]) self.ui.browserTreeView.setModel(model) self.ui.browserTreeView.setRootIndex(model.index("Desktop")) self.ui.browserTreeView.hideColumn(1) self.ui.browserTreeView.hideColumn(2) self.ui.browserTreeView.hideColumn(3) self.ui.browserTreeView.doubleClicked.connect(self.onClicked)
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()
def open_directory(self, dir): model = QFileSystemModel(self.ui.fileTreeView) model.setNameFilters(["*.jpg", "*.JPG"]) model.setRootPath(dir) self.ui.fileTreeView.setModel(model) self.ui.fileTreeView.setRootIndex(model.index(dir)) self.ui.fileTreeView.header().setStretchLastSection(False) self.ui.fileTreeView.header().setSectionResizeMode(0, QHeaderView.Stretch) self.ui.fileTreeView.selectionModel().selectionChanged.connect(self.current_file_changed) self.ui.fileTreeView.hideColumn(1) self.ui.fileTreeView.hideColumn(2) self.ui.fileTreeView.hideColumn(3) self.ui.fileTreeView.hideColumn(4)
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)
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_()
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()
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)
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()
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_()
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)
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))
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()
class FileBrowser(QObject): file_selected = Signal(str) file_activated = Signal(str) def __init__(self, app, window): QObject.__init__(self) self.app = app self.view = window.file_tree self.show_hidden_chk = window.show_hidden self.name_filter_combo = window.name_filter self.model = QFileSystemModel(self.view) self.icon_provider = FileIconProvider() if app.args.root: self.model.setRootPath(app.args.root) self.current_path = app.args.root else: self.model.setRootPath("") self.current_path = os.path.realpath(os.curdir) self.model.setIconProvider(self.icon_provider) self.view.setModel(self.model) self.view.sortByColumn(0, Qt.AscendingOrder) self.view.setSortingEnabled(True) index = self.model.index(self.current_path) if app.args.root: self.view.setRootIndex(index) self.view.setExpanded(index, True) self.view.setCurrentIndex(index) self.view.setDragDropMode(QAbstractItemView.DragDropMode.DragOnly) self.view.setSelectionMode(QAbstractItemView.ExtendedSelection) self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.add_name_filters() self.apply_show_hidden() self.apply_name_filters() self.model.setNameFilterDisables(False) self.model.directoryLoaded.connect(self.directory_loaded) self.model.dataChanged.connect(self.data_changed) selection_model = self.view.selectionModel() selection_model.selectionChanged.connect(self.selection_changed) self.show_hidden_chk.stateChanged.connect(self.apply_show_hidden) self.name_filter_combo.currentIndexChanged.connect( self.apply_name_filters) self.view.doubleClicked.connect(self.double_clicked) def add_name_filters(self): for name, filters in NAME_FILTERS: label = "{} ({})".format(name, ", ".join(filters)) self.name_filter_combo.addItem(label, filters) self.name_filter_combo.setCurrentIndex(0) @Slot() def apply_show_hidden(self): show = self.show_hidden_chk.checkState() logging.debug("apply_show_hidden(): %r", show) flags = QDir.AllDirs | QDir.Files | QDir.NoDotAndDotDot if show: flags |= QDir.Hidden self.model.setFilter(flags) QTimer.singleShot(100, self.scroll_to_current) @Slot() def apply_name_filters(self): filters = self.name_filter_combo.currentData() self.model.setNameFilters(filters) QTimer.singleShot(100, self.scroll_to_current) @Slot(str) def directory_loaded(self, path): logger.debug("directory loaded: %s", path) if path == self.current_path: logger.debug("requesting scrolling") QTimer.singleShot(100, self.scroll_to_current) @Slot() def data_changed(self, *args): logger.debug("Data changed: %r", args) @Slot() def scroll_to_current(self): index = self.model.index(self.current_path) self.view.scrollTo(index) self.view.resizeColumnToContents(0) @Slot(QItemSelection) def selection_changed(self, selection): indexes = selection.indexes() if indexes: index = indexes[0] path = self.model.filePath(index) if os.path.isfile(path): self.file_selected.emit(path) self.current_path = path @Slot(QModelIndex) def double_clicked(self, index): path = self.model.filePath(index) if os.path.isfile(path): self.file_activated.emit(path)
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()
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()