eric6/Project/ProjectOthersBrowser.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/Project/ProjectOthersBrowser.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,378 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2002 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a class used to display the parts of the project, that
+don't fit the other categories.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import QModelIndex, pyqtSignal, QUrl
+from PyQt5.QtGui import QDesktopServices
+from PyQt5.QtWidgets import QDialog, QMenu
+
+from E5Gui import E5MessageBox
+
+from .ProjectBrowserModel import ProjectBrowserFileItem, \
+    ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem, \
+    ProjectBrowserOthersType
+from .ProjectBaseBrowser import ProjectBaseBrowser
+
+import Utilities.MimeTypes
+import Preferences
+
+
+class ProjectOthersBrowser(ProjectBaseBrowser):
+    """
+    A class used to display the parts of the project, that don't fit the
+    other categories.
+    
+    @signal showMenu(str, QMenu) emitted when a menu is about to be shown.
+        The name of the menu and a reference to the menu are given.
+    """
+    showMenu = pyqtSignal(str, QMenu)
+    
+    def __init__(self, project, parent=None):
+        """
+        Constructor
+        
+        @param project reference to the project object
+        @param parent parent widget of this browser (QWidget)
+        """
+        ProjectBaseBrowser.__init__(self, project, ProjectBrowserOthersType,
+                                    parent)
+    
+        self.selectedItemsFilter = [ProjectBrowserFileItem,
+                                    ProjectBrowserDirectoryItem]
+        self.specialMenuEntries = [1]
+
+        self.setWindowTitle(self.tr('Others'))
+
+        self.setWhatsThis(self.tr(
+            """<b>Project Others Browser</b>"""
+            """<p>This allows to easily see all other files and directories"""
+            """ contained in the current project. Several actions can be"""
+            """ executed via the context menu. The entry which is registered"""
+            """ in the project is shown in a different colour.</p>"""
+        ))
+        
+        project.prepareRepopulateItem.connect(self._prepareRepopulateItem)
+        project.completeRepopulateItem.connect(self._completeRepopulateItem)
+        
+    def _createPopupMenus(self):
+        """
+        Protected overloaded method to generate the popup menu.
+        """
+        ProjectBaseBrowser._createPopupMenus(self)
+        
+        self.menu.addAction(
+            self.tr('Open in Hex Editor'), self._openHexEditor)
+        self.editPixmapAct = self.menu.addAction(
+            self.tr('Open in Icon Editor'), self._editPixmap)
+        self.menu.addSeparator()
+        self.mimeTypeAct = self.menu.addAction(
+            self.tr('Show Mime-Type'), self.__showMimeType)
+        self.menu.addSeparator()
+        self.renameFileAct = self.menu.addAction(
+            self.tr('Rename file'), self._renameFile)
+        self.menuActions.append(self.renameFileAct)
+        act = self.menu.addAction(
+            self.tr('Remove from project'), self.__removeItem)
+        self.menuActions.append(act)
+        act = self.menu.addAction(self.tr('Delete'), self.__deleteItem)
+        self.menuActions.append(act)
+        self.menu.addSeparator()
+        self.menu.addAction(
+            self.tr('Add files...'), self.project.addOthersFiles)
+        self.menu.addAction(
+            self.tr('Add directory...'), self.project.addOthersDir)
+        self.menu.addSeparator()
+        self.menu.addAction(self.tr('Refresh'), self.__refreshItem)
+        self.menu.addSeparator()
+        self.menu.addAction(
+            self.tr('Copy Path to Clipboard'), self._copyToClipboard)
+        self.menu.addSeparator()
+        self.menu.addAction(
+            self.tr('Expand all directories'), self._expandAllDirs)
+        self.menu.addAction(
+            self.tr('Collapse all directories'), self._collapseAllDirs)
+        self.menu.addSeparator()
+        self.menu.addAction(self.tr('Configure...'), self._configure)
+
+        self.backMenu = QMenu(self)
+        self.backMenu.addAction(
+            self.tr('Add files...'), self.project.addOthersFiles)
+        self.backMenu.addAction(
+            self.tr('Add directory...'), self.project.addOthersDir)
+        self.backMenu.addSeparator()
+        self.backMenu.addAction(
+            self.tr('Expand all directories'), self._expandAllDirs)
+        self.backMenu.addAction(
+            self.tr('Collapse all directories'), self._collapseAllDirs)
+        self.backMenu.addSeparator()
+        self.backMenu.addAction(self.tr('Configure...'), self._configure)
+        self.backMenu.setEnabled(False)
+
+        self.multiMenu.addSeparator()
+        act = self.multiMenu.addAction(
+            self.tr('Remove from project'), self.__removeItem)
+        self.multiMenuActions.append(act)
+        act = self.multiMenu.addAction(
+            self.tr('Delete'), self.__deleteItem)
+        self.multiMenuActions.append(act)
+        self.multiMenu.addSeparator()
+        self.multiMenu.addAction(
+            self.tr('Expand all directories'), self._expandAllDirs)
+        self.multiMenu.addAction(
+            self.tr('Collapse all directories'), self._collapseAllDirs)
+        self.multiMenu.addSeparator()
+        self.multiMenu.addAction(self.tr('Configure...'), self._configure)
+        
+        self.menu.aboutToShow.connect(self.__showContextMenu)
+        self.multiMenu.aboutToShow.connect(self.__showContextMenuMulti)
+        self.backMenu.aboutToShow.connect(self.__showContextMenuBack)
+        self.mainMenu = self.menu
+        
+    def _contextMenuRequested(self, coord):
+        """
+        Protected slot to show the context menu.
+        
+        @param coord the position of the mouse pointer (QPoint)
+        """
+        if not self.project.isOpen():
+            return
+        
+        try:
+            cnt = self.getSelectedItemsCount()
+            if cnt <= 1:
+                index = self.indexAt(coord)
+                if index.isValid():
+                    self._selectSingleItem(index)
+                    cnt = self.getSelectedItemsCount()
+            
+            if cnt > 1:
+                self.multiMenu.popup(self.mapToGlobal(coord))
+            else:
+                index = self.indexAt(coord)
+                if cnt == 1 and index.isValid():
+                    itm = self.model().item(index)
+                    if isinstance(itm, ProjectBrowserFileItem):
+                        self.editPixmapAct.setVisible(itm.isPixmapFile())
+                        self.mimeTypeAct.setVisible(True)
+                        self.menu.popup(self.mapToGlobal(coord))
+                    elif isinstance(itm, ProjectBrowserDirectoryItem):
+                        self.editPixmapAct.setVisible(False)
+                        self.mimeTypeAct.setVisible(False)
+                        self.menu.popup(self.mapToGlobal(coord))
+                    else:
+                        self.backMenu.popup(self.mapToGlobal(coord))
+                else:
+                    self.backMenu.popup(self.mapToGlobal(coord))
+        except Exception:
+            pass
+        
+    def __showContextMenu(self):
+        """
+        Private slot called by the menu aboutToShow signal.
+        """
+        self._showContextMenu(self.menu)
+        
+        self.showMenu.emit("Main", self.menu)
+        
+    def __showContextMenuMulti(self):
+        """
+        Private slot called by the multiMenu aboutToShow signal.
+        """
+        ProjectBaseBrowser._showContextMenuMulti(self, self.multiMenu)
+        
+        self.showMenu.emit("MainMulti", self.multiMenu)
+        
+    def __showContextMenuBack(self):
+        """
+        Private slot called by the backMenu aboutToShow signal.
+        """
+        ProjectBaseBrowser._showContextMenuBack(self, self.backMenu)
+        
+        self.showMenu.emit("MainBack", self.backMenu)
+        
+    def _showContextMenu(self, menu):
+        """
+        Protected slot called before the context menu is shown.
+        
+        It enables/disables the VCS menu entries depending on the overall
+        VCS status and the file status.
+        
+        @param menu Reference to the popup menu (QPopupMenu)
+        """
+        if self.project.vcs is None:
+            for act in self.menuActions:
+                act.setEnabled(True)
+            itm = self.model().item(self.currentIndex())
+            if isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \
+               isinstance(itm, ProjectBrowserDirectoryItem):
+                self.renameFileAct.setEnabled(False)
+        else:
+            self.vcsHelper.showContextMenu(menu, self.menuActions)
+        
+    def _editPixmap(self):
+        """
+        Protected slot to handle the open in icon editor popup menu entry.
+        """
+        itmList = self.getSelectedItems()
+        
+        for itm in itmList:
+            if isinstance(itm, ProjectBrowserFileItem):
+                if itm.isPixmapFile():
+                    self.pixmapEditFile.emit(itm.fileName())
+        
+    def _openHexEditor(self):
+        """
+        Protected slot to handle the open in hex editor popup menu entry.
+        """
+        itmList = self.getSelectedItems()
+        
+        for itm in itmList:
+            if isinstance(itm, ProjectBrowserFileItem):
+                self.binaryFile.emit(itm.fileName())
+        
+    def _openItem(self):
+        """
+        Protected slot to handle the open popup menu entry.
+        """
+        itmList = self.getSelectedItems()
+        
+        for itm in itmList:
+            if isinstance(itm, ProjectBrowserFileItem):
+                if itm.isPixmapFile():
+                    self.pixmapFile.emit(itm.fileName())
+                elif itm.isSvgFile():
+                    self.svgFile.emit(itm.fileName())
+                else:
+                    if Utilities.MimeTypes.isTextFile(itm.fileName()):
+                        self.sourceFile.emit(itm.fileName())
+                    else:
+                        QDesktopServices.openUrl(QUrl(itm.fileName()))
+        
+    def __showMimeType(self):
+        """
+        Private slot to show the mime type of the selected entry.
+        """
+        itmList = self.getSelectedItems()
+        if itmList:
+            mimetype = Utilities.MimeTypes.mimeType(itmList[0].fileName())
+            if mimetype is None:
+                E5MessageBox.warning(
+                    self,
+                    self.tr("Show Mime-Type"),
+                    self.tr("""The mime type of the file could not be"""
+                            """ determined."""))
+            elif mimetype.split("/")[0] == "text":
+                E5MessageBox.information(
+                    self,
+                    self.tr("Show Mime-Type"),
+                    self.tr("""The file has the mime type <b>{0}</b>.""")
+                    .format(mimetype))
+            else:
+                textMimeTypesList = Preferences.getUI("TextMimeTypes")
+                if mimetype in textMimeTypesList:
+                    E5MessageBox.information(
+                        self,
+                        self.tr("Show Mime-Type"),
+                        self.tr("""The file has the mime type <b>{0}</b>.""")
+                        .format(mimetype))
+                else:
+                    ok = E5MessageBox.yesNo(
+                        self,
+                        self.tr("Show Mime-Type"),
+                        self.tr("""The file has the mime type <b>{0}</b>."""
+                                """<br/> Shall it be added to the list of"""
+                                """ text mime types?""").format(mimetype))
+                    if ok:
+                        textMimeTypesList.append(mimetype)
+                        Preferences.setUI("TextMimeTypes", textMimeTypesList)
+        
+    def __removeItem(self):
+        """
+        Private slot to remove the selected entry from the OTHERS project
+        data area.
+        """
+        itmList = self.getSelectedItems()
+        
+        for itm in itmList[:]:
+            if isinstance(itm, ProjectBrowserFileItem):
+                fn = itm.fileName()
+                self.closeSourceWindow.emit(fn)
+                self.project.removeFile(fn)
+            else:
+                dn = itm.dirName()
+                self.project.removeDirectory(dn)
+        
+    def __deleteItem(self):
+        """
+        Private method to delete the selected entry from the OTHERS project
+        data area.
+        """
+        itmList = self.getSelectedItems()
+        
+        items = []
+        names = []
+        fullNames = []
+        dirItems = []
+        dirNames = []
+        dirFullNames = []
+        for itm in itmList:
+            if isinstance(itm, ProjectBrowserFileItem):
+                fn2 = itm.fileName()
+                fn = self.project.getRelativePath(fn2)
+                items.append(itm)
+                fullNames.append(fn2)
+                names.append(fn)
+            else:
+                dn2 = itm.dirName()
+                dn = self.project.getRelativePath(dn2)
+                dirItems.append(itm)
+                dirFullNames.append(dn2)
+                dirNames.append(dn)
+        items.extend(dirItems)
+        fullNames.extend(dirFullNames)
+        names.extend(dirNames)
+        del itmList
+        del dirFullNames
+        del dirNames
+        
+        from UI.DeleteFilesConfirmationDialog import \
+            DeleteFilesConfirmationDialog
+        dlg = DeleteFilesConfirmationDialog(
+            self.parent(),
+            self.tr("Delete files/directories"),
+            self.tr(
+                "Do you really want to delete these entries from the"
+                " project?"),
+            names)
+        
+        if dlg.exec_() == QDialog.Accepted:
+            for itm, fn2, fn in zip(items[:], fullNames, names):
+                if isinstance(itm, ProjectBrowserFileItem):
+                    self.closeSourceWindow.emit(fn2)
+                    self.project.deleteFile(fn)
+                elif isinstance(itm, ProjectBrowserDirectoryItem):
+                    self.project.deleteDirectory(fn2)
+        
+    def __refreshItem(self):
+        """
+        Private slot to refresh (repopulate) an item.
+        """
+        itm = self.model().item(self.currentIndex())
+        if isinstance(itm, ProjectBrowserFileItem):
+            name = itm.fileName()
+            self.project.repopulateItem(name)
+        elif isinstance(itm, ProjectBrowserDirectoryItem):
+            name = itm.dirName()
+            self._model.directoryChanged(name)
+        else:
+            name = ''
+        
+        self._resizeColumns(QModelIndex())

eric ide

mercurial