def __init__(self, **kwargs): super(ProjectsDock, self).__init__(**kwargs) self.setupUi(self) self.projectManager = self.application.projectManager self.fileManager = self.application.fileManager self.projectTreeProxyModel = self.projectManager.projectTreeProxyModel self.setupTreeViewProjects() # Model for selector dialog self.selectableProjectFileModel = SelectableProjectFileProxyModel(self.projectManager, self.fileManager, parent = self) # Bundle Filter Dialog self.bundleFilterDialog = BundleFilterDialog(self) self.bundleFilterDialog.setWindowTitle("Select Related Bundles") self.bundleFilterDialog.setModel(self.projectManager.projectMenuProxyModel) self.bundleFilterDialog.setHelpVisible(False)
def configToolbar(self): self.toolbarMenu = QtWidgets.QMenu("Menu", self) action = QtWidgets.QAction("New Command", self) action.triggered.connect(self.on_actionCommand_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Drag Command", self) action.triggered.connect(self.on_actionDragCommand_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Language", self) action.triggered.connect(self.on_actionLanguage_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Snippet", self) action.triggered.connect(self.on_actionSnippet_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Template", self) action.triggered.connect(self.on_actionTemplate_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Project", self) action.triggered.connect(self.on_actionProject_triggered) self.toolbarMenu.addAction(action) self.staticFileAction = QtWidgets.QAction("New Static File", self) self.staticFileAction.triggered.connect(self.on_actionStaticFile_triggered) self.toolbarMenu.addAction(self.staticFileAction) action = QtWidgets.QAction("New Preferences", self) action.triggered.connect(self.on_actionPreferences_triggered) self.toolbarMenu.addAction(action) self.toolbarMenu.addSeparator() action = QtWidgets.QAction("New Bundle", self) action.triggered.connect(self.on_actionBundle_triggered) self.toolbarMenu.addAction(action) def conditionalEnabledStaticFile(): node = self.proxyTreeModel.node(self.treeView.currentIndex()) self.staticFileAction.setEnabled(not node.isRootNode() and (node.type() in ("template", "staticfile", "project"))) self.toolbarMenu.aboutToShow.connect(conditionalEnabledStaticFile) self.pushButtonAdd.setMenu(self.toolbarMenu) #Bundle global filter dialog self.bundleFilterDialog = BundleFilterDialog(self) self.bundleFilterDialog.setModel(self.manager.bundleProxyModel)
class ProjectsDock(PrymatexDock, FileSystemTasks, Ui_ProjectsDock, QtGui.QDockWidget): SEQUENCE = resources.get_sequence("Docks", "ProjectsDock", "Alt+X") ICON = resources.get_icon("project-development") PREFERED_AREA = QtCore.Qt.LeftDockWidgetArea #======================================================================= # Settings #======================================================================= SETTINGS_GROUP = 'Projects' @ConfigurableItem(default = '') def customFilters(self, filters): filters = [p.strip() for p in filters.split(",")] self.selectableProjectFileModel.setBaseFilters(filters) self.projectTreeProxyModel.setFilterRegExp(",".join(filters)) @ConfigurableHook("CodeEditor.defaultTheme") def defaultTheme(self, themeUUID): theme = self.application.supportManager.getBundleItem(themeUUID) self.treeViewProjects.setPalette(theme.palette()) self.treeViewProjects.viewport().setPalette(theme.palette()) def __init__(self, **kwargs): super(ProjectsDock, self).__init__(**kwargs) self.setupUi(self) self.projectManager = self.application.projectManager self.fileManager = self.application.fileManager self.projectTreeProxyModel = self.projectManager.projectTreeProxyModel self.setupTreeViewProjects() # Model for selector dialog self.selectableProjectFileModel = SelectableProjectFileProxyModel(self.projectManager, self.fileManager, parent = self) # Bundle Filter Dialog self.bundleFilterDialog = BundleFilterDialog(self) self.bundleFilterDialog.setWindowTitle("Select Related Bundles") self.bundleFilterDialog.setModel(self.projectManager.projectMenuProxyModel) self.bundleFilterDialog.setHelpVisible(False) def initialize(self, **kwargs): super(ProjectsDock, self).initialize(**kwargs) self.projectDialog = self.mainWindow().findChild(QtGui.QDialog, "ProjectDialog") self.templateDialog = self.mainWindow().findChild(QtGui.QDialog, "TemplateDialog") self.bundleEditorDialog = self.mainWindow().findChild(QtGui.QDialog, "BundleEditorDialog") self.propertiesDialog = self.mainWindow().findChild(QtGui.QDialog, "PropertiesDialog") self.setupPropertiesWidgets() @classmethod def contributeToSettings(cls): return [ ] # Contributes to Main Menu @classmethod def contributeToMainMenu(cls): navigation = [ {'text': 'Go to project file', 'triggered': cls.on_actionGoToProjectFile_triggered, 'sequence': resources.get_sequence("Projects", "GoToProjectFiles", 'Meta+Ctrl+Shift+F'), }, {'text': 'Go to project symbol', 'triggered': cls.on_actionGoToProjectFile_triggered, 'sequence': resources.get_sequence("Projects", "GoToProjectFiles", 'Meta+Ctrl+Shift+F'), } ] return { "navigation": navigation} # ------------------ Menu Actions def on_actionGoToProjectFile_triggered(self): filePath = self.mainWindow().selectorDialog.select(self.selectableProjectFileModel, title=_("Select Project File")) if filePath is not None: index = self.projectTreeProxyModel.indexForPath(filePath) self.treeViewProjects.setCurrentIndex(index) self.application.openFile(filePath) def addFileSystemNodeFormater(self, formater): self.projectTreeProxyModel.addNodeFormater(formater) def componentState(self): expandedIndexes = [index for index in self.projectTreeProxyModel.persistentIndexList() if self.treeViewProjects.isExpanded(index)] expandedPaths = [self.projectTreeProxyModel.node(index).path() for index in expandedIndexes] return { "expanded": expandedPaths } def setComponentState(self, state): #Expanded Nodes list(map(lambda index: index.isValid() and self.treeViewProjects.setExpanded(index, True), [self.projectTreeProxyModel.indexForPath(path) for path in state["expanded"]])) def environmentVariables(self): environment = PrymatexDock.environmentVariables(self) indexes = self.treeViewProjects.selectedIndexes() if indexes: node = self.currentNode() paths = [self.application.fileManager.normcase(node.path()) for node in [ self.projectTreeProxyModel.node(index) for index in indexes ]] environment.update({ 'TM_SELECTED_FILE': node.path(), 'TM_SELECTED_FILES': " ".join(["'%s'" % path for path in paths ]) }) return environment def keyPressEvent(self, event): if not self.runKeyHelper(event): return QtGui.QDockWidget.keyPressEvent(self, event) def setupPropertiesWidgets(self): from prymatex.gui.properties.project import ProjectPropertiesWidget from prymatex.gui.properties.environment import EnvironmentPropertiesWidget from prymatex.gui.properties.resource import ResoucePropertiesWidget for propertyClass in [ProjectPropertiesWidget, EnvironmentPropertiesWidget, ResoucePropertiesWidget]: self.application.extendComponent(propertyClass) self.application.projectManager.registerPropertyWidget(propertyClass(parent = self.propertiesDialog)) def setupTreeViewProjects(self): self.treeViewProjects.setModel(self.projectTreeProxyModel) self.treeViewProjects.setHeaderHidden(True) self.treeViewProjects.setUniformRowHeights(False) #Setup Context Menu optionsMenu = { "text": "Project Options", "items": [ { "text": "Order", "items": [ (self.actionOrderByName, self.actionOrderBySize, self.actionOrderByDate, self.actionOrderByType), "-", self.actionOrderDescending, self.actionOrderFoldersFirst ] } ] } self.actionOrderFoldersFirst.setChecked(True) self.actionOrderByName.trigger() self.projectOptionsMenu = create_menu(self, optionsMenu) self.pushButtonOptions.setMenu(self.projectOptionsMenu) #Connect context menu self.treeViewProjects.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.treeViewProjects.customContextMenuRequested.connect(self.showProjectTreeViewContextMenu) #======================================================================= # Drag and Drop (see the proxy model) #======================================================================= self.treeViewProjects.setDragEnabled(True) self.treeViewProjects.setAcceptDrops(True) self.treeViewProjects.setDefaultDropAction(QtCore.Qt.MoveAction) self.treeViewProjects.setDropIndicatorShown(True) self.treeViewProjects.setAlternatingRowColors(True) self.treeViewProjects.setAnimated(True) # Selection Mode self.treeViewProjects.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) #================================================ # Build Menus #================================================ def buildContextMenu(self, index): contextMenu = { "text": "Context", "items": [ { "text": "New", "items": [ self.actionNewFolder, self.actionNewFile, "-", self.actionNewFromTemplate, self.actionNewProject, ] }, "--refresh", self.actionRefresh, "--bundles" ] } if index.isValid(): node = self.projectTreeProxyModel.node(index) self.extendFileSystemItemMenu(contextMenu, node) self.extendAddonsItemMenu(contextMenu, node) self.extendProjectBundleItemMenu(contextMenu, node) # contextMenu = create_menu(contextMenu, self, separatorName = True) contextMenu = create_menu(self, contextMenu, separatorName = True) contextMenu.aboutToShow.connect(self.on_contextMenu_aboutToShow) contextMenu.aboutToHide.connect(self.on_contextMenu_aboutToHide) contextMenu.triggered.connect(self.on_contextMenu_triggered) return contextMenu def on_contextMenu_aboutToShow(self): # TODO Quiza un metodo que haga esto en el manager self.application.supportManager.setEditorAvailable(False) self.application.supportManager.blockSignals(True) def on_contextMenu_aboutToHide(self): self.application.supportManager.setEditorAvailable(True) def restore_supportManager_signals(): self.application.supportManager.blockSignals(False) # TODO No estoy muy contento con esto pero que le vamos a hacer QtCore.QTimer.singleShot(0, restore_supportManager_signals) def on_contextMenu_triggered(self, action): if hasattr(action, "bundleTreeNode"): node = self.currentNode() env = { 'TM_FILEPATH': node.path(), 'TM_FILENAME': node.nodeName(), 'TM_DIRECTORY': node.nodeParent().path() } if node.isfile else { 'TM_DIRECTORY': node.path() } env.update(node.project().environmentVariables()) self.mainWindow().insertBundleItem(action.bundleTreeNode, environment = env) def extendFileSystemItemMenu(self, menu, node): extend_menu_section(menu, ["--open", self.actionOpenSystemEditor, "--handlepaths", self.actionDelete, self.actionRename]) #extend_menu_section(menu, ["--interact", self.actionSetInTerminal ], section = -1) # TODO Quiza sea mejor ponerle un type y controlar contra una cadena if isinstance(node, ProjectTreeNode): extend_menu_section(menu, [self.actionPaste, self.actionRemove], section = "handlepaths", position = 0) #extend_menu_section(menu, [self.actionBashInit], section = "interact") extend_menu_section(menu, [self.actionProjectBundles, self.actionSelectRelatedBundles], section = "bundles") else: extend_menu_section(menu, [self.actionCut, self.actionCopy, self.actionPaste], section = "handlepaths", position = 0) if node.isfile: extend_menu_section(menu, self.actionOpen, section = "open", position = 0) if node.isdir or isinstance(node, ProjectTreeNode): extend_menu_section(menu, [self.actionGoDown], section = "refresh") #El final extend_menu_section(menu, ["--properties", self.actionProperties], section = -1) def extendAddonsItemMenu(self, menu, node): #Menu de los addons addonMenues = [ "-" ] for component in self.components(): addonMenues.extend(component.contributeToContextMenu(node)) if len(addonMenues) > 1: extend_menu_section(menu, addonMenues, section = 'properties') def extendProjectBundleItemMenu(self, menu, node): #Menu de los bundles relacionados al proyecto #Try get all bundles for project bundle definition bundles = [self.application.supportManager.getManagedObject(uuid) for uuid in node.project().bundleMenu or []] #Filter None bundles bundles = [bundle for bundle in bundles if bundle is not None] #Sort by name bundles = sorted(bundles, key=lambda bundle: bundle.name) if bundles: bundleMenues = [self.application.supportManager.menuForBundle(bundle) for bundle in bundles] extend_menu_section(menu, bundleMenues, section = "bundles", position = 0) #================================================ # Tree View Project #================================================ def showProjectTreeViewContextMenu(self, point): index = self.treeViewProjects.indexAt(point) if not index.isValid(): index = self.treeViewProjects.currentIndex() self.buildContextMenu(index).popup(self.treeViewProjects.mapToGlobal(point)) def on_treeViewProjects_doubleClicked(self, index): self.on_actionOpen_triggered() def currentPath(self): return self.projectTreeProxyModel.filePath(self.treeViewProjects.currentIndex()) def currentNode(self): return self.projectTreeProxyModel.node(self.treeViewProjects.currentIndex()) def currentDirectory(self): return self.application.fileManager.directory(self.currentPath()) #================================================ # Actions Create, Delete, Rename objects #================================================ @QtCore.Slot() def on_actionNewFile_triggered(self): currentDirectory = self.currentDirectory() filePath = self.createFile(currentDirectory) if filePath is not None: self.application.openFile(filePath) #TODO: si esta en auto update ver como hacer los refresh self.projectTreeProxyModel.refreshPath(currentDirectory) @QtCore.Slot() def on_actionNewFromTemplate_triggered(self): currentDirectory = self.currentDirectory() filePath = self.templateDialog.createFile(fileDirectory = self.currentDirectory()) if filePath is not None: self.application.openFile(filePath) #TODO: si esta en auto update ver como hacer los refresh self.projectTreeProxyModel.refreshPath(currentDirectory) @QtCore.Slot() def on_actionNewFolder_triggered(self): currentDirectory = self.currentDirectory() dirPath = self.createDirectory(currentDirectory) if dirPath is not None: #TODO: si esta en auto update ver como hacer los refresh self.projectTreeProxyModel.refreshPath(currentDirectory) @QtCore.Slot() def on_actionNewProject_triggered(self): self.projectDialog.createProject() @QtCore.Slot() def on_actionDelete_triggered(self): indexes = self.treeViewProjects.selectedIndexes() projects = [] paths = [] for index in indexes: node = self.projectTreeProxyModel.node(index) if node.isproject: #Es proyecto question = CheckableMessageBox.questionFactory(self, "Delete project", "Are you sure you want to delete project '%s' from the workspace?" % node.name, "Delete project contents on disk (cannot be undone)", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Yes ) question.setDetailedText("Project location:\n%s" % node.path()) ret = question.exec_() if ret == QtGui.QMessageBox.Yes: projects.append((node, question.isChecked())) elif ret == QtGui.QMessageBox.Cancel: return else: paths.append(node) # TODO Que pasa con los proyectos y si un path es subpath de otro? for node in paths: self.deletePath(node.path()) for index in indexes: self.projectTreeProxyModel.refresh(index.parent()) @QtCore.Slot() def on_actionRemove_triggered(self): node = self.currentNode() if node.isproject: ret = QtGui.QMessageBox.question(self, "Remove project", "Are you sure you want to remove project '%s' from the workspace?" % node.name, QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Ok ) if ret == QtGui.QMessageBox.Ok: self.application.projectManager.removeProject(node) @QtCore.Slot() def on_actionRename_triggered(self): self.renamePath(self.currentPath()) self.projectTreeProxyModel.refresh(self.treeViewProjects.currentIndex()) @QtCore.Slot() def on_actionCloseProject_triggered(self): treeNode = self.currentNode() if treeNode.isproject: self.application.projectManager.closeProject(treeNode) @QtCore.Slot() def on_actionOpenProject_triggered(self): treeNode = self.currentNode() if treeNode.isproject: self.application.projectManager.openProject(treeNode) @QtCore.Slot() def on_actionProperties_triggered(self): self.propertiesDialog.setModel(self.application.projectManager.propertiesProxyModel) self.propertiesDialog.exec_(self.currentNode()) @QtCore.Slot() def on_actionRefresh_triggered(self): indexes = self.treeViewProjects.selectedIndexes() for index in indexes: self.projectTreeProxyModel.refresh(index) @QtCore.Slot() def on_actionOpen_triggered(self): node = self.currentNode() if node.isfile: self.application.openFile(node.path()) @QtCore.Slot() def on_actionOpenSystemEditor_triggered(self): QtGui.QDesktopServices.openUrl(QtCore.QUrl("file://%s" % self.currentPath(), QtCore.QUrl.TolerantMode)) @QtCore.Slot() def on_pushButtonCollapseAll_pressed(self): self.treeViewProjects.collapseAll() @QtCore.Slot(bool) def on_pushButtonSync_toggled(self, checked): if checked: #Conectar señal self.mainWindow().currentEditorChanged.connect(self.on_mainWindow_currentEditorChanged) self.on_mainWindow_currentEditorChanged(self.mainWindow().currentEditor()) else: #Desconectar señal self.mainWindow().currentEditorChanged.disconnect(self.on_mainWindow_currentEditorChanged) def on_mainWindow_currentEditorChanged(self, editor): if editor is not None and not editor.isNew(): index = self.projectTreeProxyModel.indexForPath(editor.filePath()) self.treeViewProjects.setCurrentIndex(index) @QtCore.Slot() def on_actionProjectBundles_triggered(self): self.bundleEditorDialog.execEditor(namespaceFilter = self.currentNode().namespaceName) @QtCore.Slot() def on_actionSelectRelatedBundles_triggered(self): project = self.currentNode() self.projectManager.projectMenuProxyModel.setCurrentProject(project) self.bundleFilterDialog.exec_() @QtCore.Slot() def on_actionCopy_triggered(self): mimeData = self.projectTreeProxyModel.mimeData( self.treeViewProjects.selectedIndexes() ) self.application.clipboard().setMimeData(mimeData) @QtCore.Slot() def on_actionCut_triggered(self): mimeData = self.projectTreeProxyModel.mimeData( self.treeViewProjects.selectedIndexes() ) self.application.clipboard().setMimeData(mimeData) @QtCore.Slot() def on_actionPaste_triggered(self): parentPath = self.currentPath() mimeData = self.application.clipboard().mimeData() if mimeData.hasUrls() and os.path.isdir(parentPath): for url in mimeData.urls(): srcPath = url.toLocalFile() basename = self.application.fileManager.basename(srcPath) dstPath = os.path.join(parentPath, basename) while self.application.fileManager.exists(dstPath): basename, ret = ReplaceRenameInputDialog.getText(self, _("Already exists"), _("Destiny already exists\nReplace or or replace?"), text = basename, ) if ret == ReplaceRenameInputDialog.Cancel: return if ret == ReplaceRenameInputDialog.Replace: break dstPath = os.path.join(parentPath, basename) if os.path.isdir(srcPath): self.application.fileManager.copytree(srcPath, dstPath) else: self.application.fileManager.copy(srcPath, dstPath) self.projectTreeProxyModel.refresh(self.treeViewProjects.currentIndex()) @QtCore.Slot() def on_actionGoDown_triggered(self): directory = self.currentNode() index = self.projectTreeProxyModel.indexForPath(directory.path()) self.treeViewProjects.setRootIndex(index) #================================================ # Navigation #================================================ @QtCore.Slot() def on_pushButtonGoUp_pressed(self): index = self.treeViewProjects.rootIndex() parentIndex = self.projectTreeProxyModel.parent(index) self.treeViewProjects.setRootIndex(parentIndex) #================================================ # Custom filters #================================================ @QtCore.Slot() def on_pushButtonCustomFilters_pressed(self): filters, accepted = QtGui.QInputDialog.getText(self, _("Custom Filter"), _("Enter the filters (separated by comma)\nOnly * and ? may be used for custom matching"), text = self.customFilters) if accepted: #Save and set filters self._settings.setValue('customFilters', filters) self.projectTreeProxyModel.setFilterRegExp(filters) #================================================ # Sort and order Actions #================================================ @QtCore.Slot() def on_actionOrderByName_triggered(self): self.projectTreeProxyModel.sortBy("name", self.actionOrderFoldersFirst.isChecked(), self.actionOrderDescending.isChecked()) @QtCore.Slot() def on_actionOrderBySize_triggered(self): self.projectTreeProxyModel.sortBy("size", self.actionOrderFoldersFirst.isChecked(), self.actionOrderDescending.isChecked()) @QtCore.Slot() def on_actionOrderByDate_triggered(self): self.projectTreeProxyModel.sortBy("date", self.actionOrderFoldersFirst.isChecked(), self.actionOrderDescending.isChecked()) @QtCore.Slot() def on_actionOrderByType_triggered(self): self.projectTreeProxyModel.sortBy("type", self.actionOrderFoldersFirst.isChecked(), self.actionOrderDescending.isChecked()) @QtCore.Slot() def on_actionOrderDescending_triggered(self): self.projectTreeProxyModel.sortBy(self.projectTreeProxyModel.orderBy, self.actionOrderFoldersFirst.isChecked(), self.actionOrderDescending.isChecked()) @QtCore.Slot() def on_actionOrderFoldersFirst_triggered(self): self.projectTreeProxyModel.sortBy(self.projectTreeProxyModel.orderBy, self.actionOrderFoldersFirst.isChecked(), self.actionOrderDescending.isChecked()) #================================================ # Helper actions #================================================ def refresh(self): self.on_actionRefresh_triggered() def copy(self): self.on_actionCopy_triggered() def paste(self): self.on_actionPaste_triggered() def cut(self): self.on_actionCut_triggereda() def delete(self): self.on_actionDelete_triggered() def rename(self): self.on_actionRefresh_triggered()
class BundleEditorDialog(PrymatexDialog, Ui_BundleEditorDialog, QtWidgets.QDialog): BASE_EDITOR = -1 #El ultimo es el editor base, no tiene nada def __init__(self, **kwargs): super(BundleEditorDialog, self).__init__(**kwargs) self.setupUi(self) self.namespace = None self.namespaces = [] self.manager = self.application().supportManager self.proxyTreeModel = self.manager.bundleProxyTreeModel # Connect signals self.manager.bundleChanged.connect(self.on_manager_itemChanged) self.manager.bundleItemChanged.connect(self.on_manager_itemChanged) self.finished.connect(self.on_bundleEditor_finished) #Cargar los widgets editores self.configEditorWidgets() #Configurar filter, tree, toolbar y activaciones self.configSelectTop() self.configTreeView() self.configToolbar() self.configActivation() # --------------- signal handlers def on_manager_itemChanged(self, item): editor = self.currentEditor() if editor.bundleItem is not None and editor.bundleItem == item and editor.getName() != item.name: editor.setName(item.name) self.labelTitle.setText(editor.title()) self.lineEditName.setText(editor.getName()) def on_bundleEditor_finished(self, code): self.saveChanges() # ---------------- custom execs def exec_(self): #Limiar el editor self.setCurrentEditor(self.editors[-1]) #Quitar seleccion firstIndex = self.proxyTreeModel.index(0, 0) self.treeView.setSelection(self.treeView.visualRect(firstIndex), QtCore.QItemSelectionModel.Clear) return super(BundleEditorDialog, self).exec_() def execEditor(self, types=None, namespaces=None, title="Bundle Editor"): # Title self.setWindowTitle(title) # Set namespace and filters self.namespace = namespaces and namespaces[0] or config.USR_NS_NAME self.proxyTreeModel.setFilterNamespace(namespaces) self.proxyTreeModel.setFilterBundleItemTypes(types) index = self.comboBoxItemFilter.findData(types) self.comboBoxItemFilter.setCurrentIndex(index) # Go! self.exec_() def execCommand(self): return self.execEditor(("command",)) def execLanguage(self): return self.execEditor(("syntax",)) def execSnippet(self): return self.execEditor(("snippet",)) def configEditorWidgets(self): self.stackedWidget = QtWidgets.QStackedWidget() self.stackedWidget.setFrameShape(QtWidgets.QFrame.StyledPanel) self.stackedWidget.setFrameShadow(QtWidgets.QFrame.Sunken) self.editorsLayout.insertWidget(1, self.stackedWidget) self.indexes = {} self.editors = [ widgets.SnippetEditorWidget(self), widgets.CommandEditorWidget(self), widgets.DragCommandEditorWidget(self), widgets.BundleEditorWidget(self), widgets.StaticFileEditorWidget(self), widgets.TemplateEditorWidget(self), widgets.PreferenceEditorWidget(self), widgets.LanguageEditorWidget(self), widgets.MacroEditorWidget(self), widgets.ProjectEditorWidget(self), widgets.NoneEditorWidget(self) ] for editor in self.editors: self.indexes[editor.type()] = self.stackedWidget.addWidget(editor) # ----------------- Toolbar create and delete bundle items def getBundleForIndex(self, index): if not index.isValid(): return self.manager.getDefaultBundle() bundle = self.proxyTreeModel.node(index) while bundle.type() != 'bundle': bundle = bundle.nodeParent() return bundle def createBundleItem(self, itemType): index = self.treeView.currentIndex() bundle = self.getBundleForIndex(index) bundleItemNode = self.manager.createBundleItem(itemType, bundle, self.namespace) sIndex = self.manager.bundleTreeModel.createIndex(bundleItemNode.row(), 0, bundleItemNode) index = self.proxyTreeModel.mapFromSource(sIndex) self.treeView.setCurrentIndex(index) self.editTreeItem(bundleItemNode) self.treeView.edit(index) @QtCore.Slot() def on_actionCommand_triggered(self): self.createBundleItem("command") @QtCore.Slot() def on_actionDragCommand_triggered(self): self.createBundleItem("dragcommand") @QtCore.Slot() def on_actionLanguage_triggered(self): self.createBundleItem("syntax") @QtCore.Slot() def on_actionSnippet_triggered(self): self.createBundleItem("snippet") @QtCore.Slot() def on_actionTemplate_triggered(self): self.createBundleItem("template") @QtCore.Slot() def on_actionProject_triggered(self): self.createBundleItem("project") @QtCore.Slot() def on_actionStaticFile_triggered(self): index = self.treeView.currentIndex() if index.isValid(): template = self.proxyTreeModel.node(index) if template.type() == 'staticfile': template = template.nodeParent() self.manager.createStaticFile(template, self.namespace) @QtCore.Slot() def on_actionPreferences_triggered(self): self.createBundleItem("preference") @QtCore.Slot() def on_actionBundle_triggered(self): bundleNode = self.manager.createBundle(self.namespace) sIndex = self.manager.bundleTreeModel.createIndex(bundleNode.row(), 0, bundleNode) index = self.proxyTreeModel.mapFromSource(sIndex) self.treeView.setCurrentIndex(index) self.editTreeItem(bundleNode) self.treeView.edit(index) @QtCore.Slot() def on_pushButtonRemove_pressed(self): index = self.treeView.currentIndex() if index.isValid(): item = self.proxyTreeModel.node(index) if item.type() == 'bundle': self.manager.deleteBundle(item) elif item.type() == 'staticfile': self.manager.deleteStaticFile(item) else: self.manager.deleteBundleItem(item) @QtCore.Slot() def on_pushButtonFilter_pressed(self): self.bundleFilterDialog.show() def configToolbar(self): self.toolbarMenu = QtWidgets.QMenu("Menu", self) action = QtWidgets.QAction("New Command", self) action.triggered.connect(self.on_actionCommand_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Drag Command", self) action.triggered.connect(self.on_actionDragCommand_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Language", self) action.triggered.connect(self.on_actionLanguage_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Snippet", self) action.triggered.connect(self.on_actionSnippet_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Template", self) action.triggered.connect(self.on_actionTemplate_triggered) self.toolbarMenu.addAction(action) action = QtWidgets.QAction("New Project", self) action.triggered.connect(self.on_actionProject_triggered) self.toolbarMenu.addAction(action) self.staticFileAction = QtWidgets.QAction("New Static File", self) self.staticFileAction.triggered.connect(self.on_actionStaticFile_triggered) self.toolbarMenu.addAction(self.staticFileAction) action = QtWidgets.QAction("New Preferences", self) action.triggered.connect(self.on_actionPreferences_triggered) self.toolbarMenu.addAction(action) self.toolbarMenu.addSeparator() action = QtWidgets.QAction("New Bundle", self) action.triggered.connect(self.on_actionBundle_triggered) self.toolbarMenu.addAction(action) def conditionalEnabledStaticFile(): node = self.proxyTreeModel.node(self.treeView.currentIndex()) self.staticFileAction.setEnabled(not node.isRootNode() and (node.type() in ("template", "staticfile", "project"))) self.toolbarMenu.aboutToShow.connect(conditionalEnabledStaticFile) self.pushButtonAdd.setMenu(self.toolbarMenu) #Bundle global filter dialog self.bundleFilterDialog = BundleFilterDialog(self) self.bundleFilterDialog.setModel(self.manager.bundleProxyModel) # ------------------- Filter bundle items def on_comboBoxItemFilter_returnPressed(self): self.proxyTreeModel.setFilterBundleItemTypes(None) self.proxyTreeModel.setFilterRegExp(".*%s.*" % self.comboBoxItemFilter.currentText()) @QtCore.Slot(int) def on_comboBoxItemFilter_activated(self, index): value = self.comboBoxItemFilter.itemData(index) self.proxyTreeModel.setFilterBundleItemTypes(value) def configSelectTop(self): self.comboBoxItemFilter.addItem("Show all", ()) self.comboBoxItemFilter.addItem(self.resources().get_icon("bundle-item-syntax"), "Languages", ("syntax",)) self.comboBoxItemFilter.addItem(self.resources().get_icon("bundle-item-snippet"), "Snippets", ("snippet",)) self.comboBoxItemFilter.addItem(self.resources().get_icon("bundle-item-macro"), "Macros", ("macro",)) self.comboBoxItemFilter.addItem(self.resources().get_icon("bundle-item-command"), "Commands", ("command",)) self.comboBoxItemFilter.addItem(self.resources().get_icon("bundle-item-dragcommand"), "DragCommands", ("dragcommand",)) self.comboBoxItemFilter.addItem(self.resources().get_icon("bundle-item-preference"), "Preferences", ("preference",)) self.comboBoxItemFilter.addItem(self.resources().get_icon("bundle-item-template"), "Templates", ("template", "staticfile")) self.comboBoxItemFilter.addItem(self.resources().get_icon("bundle-item-project"), "Projects", ("project", "staticfile")) self.comboBoxItemFilter.setInsertPolicy(QtWidgets.QComboBox.NoInsert) self.comboBoxItemFilter.lineEdit().returnPressed.connect(self.on_comboBoxItemFilter_returnPressed) # --------------------------- Tree View display the bundle items model def getEditorBase(self): return self.editors[self.BASE_EDITOR] def getEditorForTreeItem(self, node): item = node.bundleItem() if not node.isRootNode() and item.type() in self.indexes: index = self.indexes[item.type()] return self.editors[index] def on_bundleTreeModel_rowsInserted(self, parent, start, end): sIndex = self.manager.bundleTreeModel.index(start, 0, parent) index = self.proxyTreeModel.mapFromSource(sIndex) node = self.proxyTreeModel.node(index) self.treeView.setCurrentIndex(index) self.editTreeItem(node) self.treeView.edit(index) def on_proxyTreeModel_dataChanged(self, sindex, eindex): current = self.stackedWidget.currentWidget() self.labelTitle.setText(current.title()) def on_treeView_selectionChanged(self, selected, deselected): indexes = selected.indexes() if indexes: treeItem = self.proxyTreeModel.node(indexes[0]) self.editTreeItem(treeItem) else: self.editTreeItem(None) def configTreeView(self, manager=None): self.proxyTreeModel.dataChanged.connect(self.on_proxyTreeModel_dataChanged) self.treeView.setModel(self.proxyTreeModel) self.treeView.setHeaderHidden(True) self.treeView.setAnimated(True) self.treeView.selectionModel().selectionChanged.connect(self.on_treeView_selectionChanged) # -------------------- Activation def eventFilter(self, obj, event): if event.type() == QtCore.QEvent.KeyPress and obj == self.lineEditKeyEquivalentActivation: keyseq = QtWidgets.QKeySequence(int(event.modifiers()) + event.key()) self.stackedWidget.currentWidget().setKeySequence(keyseq) self.lineEditKeyEquivalentActivation.setText(keyseq.toString()) return True return QtWidgets.QDialog.eventFilter(self, obj, event) @QtCore.Slot() def on_pushButtonCleanKeyEquivalent_pressed(self): self.stackedWidget.currentWidget().setKeySequence(None) self.lineEditKeyEquivalentActivation.setText("") @QtCore.Slot(str) def on_lineEditScopeSelector_textEdited(self, text): self.stackedWidget.currentWidget().setScope(text) @QtCore.Slot(str) def on_lineEditTabTriggerActivation_textEdited(self, text): self.stackedWidget.currentWidget().setTabTrigger(text) @QtCore.Slot(str) def on_lineEditName_textEdited(self, text): self.stackedWidget.currentWidget().setName(text) def configActivation(self): self.lineEditKeyEquivalentActivation.installEventFilter(self) def saveChanges(self): current = self.stackedWidget.currentWidget() if current.isChanged(): if current.type() == "bundle": self.manager.updateBundle(current.bundleItem, self.namespace, **current.changes) elif current.type() == "staticfile": self.manager.updateStaticFile(current.bundleItem, self.namespace, **current.changes) else: self.manager.updateBundleItem(current.bundleItem, self.namespace, **current.changes) def editTreeItem(self, treeItem): self.saveChanges() editor = self.getEditorForTreeItem(treeItem) if treeItem is not None else self.getEditorBase() if editor != None: editor.edit(treeItem.bundleItem()) self.setCurrentEditor(editor) def currentEditor(self): return self.stackedWidget.currentWidget() def setCurrentEditor(self, editor): self.stackedWidget.setCurrentWidget(editor) self.labelTitle.setText(editor.title()) self.lineEditName.setText(editor.getName()) self.lineEditSemanticClass.setText(editor.getSemanticClass()) scope = editor.getScope() tabTrigger = editor.getTabTrigger() keySequence = editor.getKeySequence() semanticClass = editor.getSemanticClass() # Scope self.lineEditScopeSelector.setEnabled(scope is not None) self.lineEditScopeSelector.setText(scope is not None and scope or "") # KeySequence self.lineEditKeyEquivalentActivation.setEnabled(keySequence is not None) self.lineEditKeyEquivalentActivation.setText(keySequence and\ keySequence.toString() or "") # TabTrigger self.lineEditTabTriggerActivation.setEnabled(tabTrigger is not None) self.lineEditTabTriggerActivation.setText(tabTrigger or "") # SemanticClass self.lineEditSemanticClass.setEnabled(semanticClass is not None) self.lineEditSemanticClass.setText(semanticClass or "")