Sun, 12 Nov 2017 19:42:02 +0100
Started to add support for Google protobuf protocol files.
--- a/E5XML/ProjectReader.py Sat Nov 11 18:47:09 2017 +0100 +++ b/E5XML/ProjectReader.py Sun Nov 12 19:42:02 2017 +0100 @@ -15,6 +15,7 @@ import Utilities +# TODO: add support for 'PROTOCOLS' (analog INTERFACES) class ProjectReader(XMLStreamReaderBase): """ Class for reading an XML project file.
--- a/E5XML/ProjectWriter.py Sat Nov 11 18:47:09 2017 +0100 +++ b/E5XML/ProjectWriter.py Sun Nov 12 19:42:02 2017 +0100 @@ -20,6 +20,7 @@ import Utilities +# TODO: add support for 'PROTOCOLS' (analog INTERFACES) class ProjectWriter(XMLStreamWriterBase): """ Class implementing the writer class for writing an XML project file.
--- a/Preferences/ConfigurationDialog.py Sat Nov 11 18:47:09 2017 +0100 +++ b/Preferences/ConfigurationDialog.py Sun Nov 12 19:42:02 2017 +0100 @@ -179,6 +179,9 @@ "printerPage": [self.tr("Printer"), "preferences-printer.png", "PrinterPage", None, None], + "protobufPage": + [self.tr("Protobuf"), "protobuf.png", + "ProtobufPage", None, None], "pythonPage": [self.tr("Python"), "preferences-python.png", "PythonPage", None, None],
--- a/Preferences/ConfigurationPages/ProjectBrowserPage.py Sat Nov 11 18:47:09 2017 +0100 +++ b/Preferences/ConfigurationPages/ProjectBrowserPage.py Sun Nov 12 19:42:02 2017 +0100 @@ -93,7 +93,7 @@ """ from Project.ProjectBrowserFlags import SourcesBrowserFlag, \ FormsBrowserFlag, ResourcesBrowserFlag, TranslationsBrowserFlag, \ - InterfacesBrowserFlag, OthersBrowserFlag + InterfacesBrowserFlag, OthersBrowserFlag, ProtocolsBrowserFlag flags = 0 if self.sourcesBrowserCheckBox.isChecked(): @@ -108,6 +108,8 @@ flags |= InterfacesBrowserFlag if self.othersBrowserCheckBox.isChecked(): flags |= OthersBrowserFlag + if self.protocolsBrowserCheckBox.isChecked(): + flags |= ProtocolsBrowserFlag self.__projectBrowserFlags[projectType] = flags @@ -120,7 +122,7 @@ """ from Project.ProjectBrowserFlags import SourcesBrowserFlag, \ FormsBrowserFlag, ResourcesBrowserFlag, TranslationsBrowserFlag, \ - InterfacesBrowserFlag, OthersBrowserFlag + InterfacesBrowserFlag, OthersBrowserFlag, ProtocolsBrowserFlag flags = self.__projectBrowserFlags[projectType] @@ -132,6 +134,7 @@ self.interfacesBrowserCheckBox.setChecked( flags & InterfacesBrowserFlag) self.othersBrowserCheckBox.setChecked(flags & OthersBrowserFlag) + self.protocolsBrowserCheckBox.setChecked(flags & ProtocolsBrowserFlag) @pyqtSlot(int) def on_projectTypeCombo_activated(self, index):
--- a/Preferences/ConfigurationPages/ProjectBrowserPage.ui Sat Nov 11 18:47:09 2017 +0100 +++ b/Preferences/ConfigurationPages/ProjectBrowserPage.ui Sun Nov 12 19:42:02 2017 +0100 @@ -10,7 +10,7 @@ <height>497</height> </rect> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_2"> <item> <widget class="QLabel" name="headerLabel"> <property name="text"> @@ -81,7 +81,7 @@ <property name="title"> <string>Visible Project Browsers</string> </property> - <layout class="QVBoxLayout"> + <layout class="QVBoxLayout" name="verticalLayout"> <item> <layout class="QHBoxLayout"> <item> @@ -107,7 +107,7 @@ </layout> </item> <item> - <layout class="QGridLayout"> + <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QCheckBox" name="sourcesBrowserCheckBox"> <property name="toolTip"> @@ -119,12 +119,12 @@ </widget> </item> <item row="0" column="1"> - <widget class="QCheckBox" name="translationsBrowserCheckBox"> + <widget class="QCheckBox" name="interfacesBrowserCheckBox"> <property name="toolTip"> - <string>Select to show the translations browser</string> + <string>Select to show the interfaces (IDL) browser</string> </property> <property name="text"> - <string>Translations Browser</string> + <string>Interfaces (IDL) Browser</string> </property> </widget> </item> @@ -139,12 +139,12 @@ </widget> </item> <item row="1" column="1"> - <widget class="QCheckBox" name="interfacesBrowserCheckBox"> + <widget class="QCheckBox" name="protocolsBrowserCheckBox"> <property name="toolTip"> - <string>Select to show the interfaces (IDL) browser</string> + <string>Select to show the protocols (protobuf) browser</string> </property> <property name="text"> - <string>Interfaces (IDL) Browser</string> + <string>Protocols (protobuf) Browser</string> </property> </widget> </item> @@ -168,6 +168,16 @@ </property> </widget> </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="translationsBrowserCheckBox"> + <property name="toolTip"> + <string>Select to show the translations browser</string> + </property> + <property name="text"> + <string>Translations Browser</string> + </property> + </widget> + </item> </layout> </item> </layout> @@ -236,6 +246,7 @@ <tabstop>resourcesBrowserCheckBox</tabstop> <tabstop>translationsBrowserCheckBox</tabstop> <tabstop>interfacesBrowserCheckBox</tabstop> + <tabstop>protocolsBrowserCheckBox</tabstop> <tabstop>othersBrowserCheckBox</tabstop> <tabstop>followEditorCheckBox</tabstop> <tabstop>followCursorLineCheckBox</tabstop>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Preferences/ConfigurationPages/ProtobufPage.py Sun Nov 12 19:42:02 2017 +0100 @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the protobuf configuration page. +""" + +from __future__ import unicode_literals + +from E5Gui.E5PathPicker import E5PathPickerModes + +from .ConfigurationPageBase import ConfigurationPageBase +from .Ui_ProtobufPage import Ui_ProtobufPage + +import Preferences + + +class ProtobufPage(ConfigurationPageBase, Ui_ProtobufPage): + """ + Class implementing the protobuf configuration page. + """ + def __init__(self): + """ + Constructor + """ + super(ProtobufPage, self).__init__() + self.setupUi(self) + self.setObjectName("ProtobufPage") + + self.protocPicker.setMode(E5PathPickerModes.OpenFileMode) + self.protocPicker.setToolTip(self.tr( + "Press to select the Protobuf compiler via a file selection" + " dialog.")) + + # set initial values + self.protocPicker.setText(Preferences.getProtobuf("protoc")) + + def save(self): + """ + Public slot to save the protobuf configuration. + """ + Preferences.setProtobuf("protoc", self.protocPicker.text()) + + +def create(dlg): + """ + Module function to create the configuration page. + + @param dlg reference to the configuration dialog + @return reference to the instantiated page (ConfigurationPageBase) + """ + page = ProtobufPage() + return page
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Preferences/ConfigurationPages/ProtobufPage.ui Sun Nov 12 19:42:02 2017 +0100 @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ProtobufPage</class> + <widget class="QWidget" name="ProtobufPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>589</width> + <height>490</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QLabel" name="headerLabel"> + <property name="text"> + <string><b>Configure Protobuf support</b></string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line13"> + <property name="frameShape"> + <enum>QFrame::HLine</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Protobuf Compiler</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="E5PathPicker" name="protocPicker" native="true"> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="toolTip"> + <string>Enter the path to the protobuf compiler.</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="textLabel1_5"> + <property name="text"> + <string><b>Note:</b> Leave this entry empty to use the default value (protoc or protoc.exe).</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>81</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>E5PathPicker</class> + <extends>QWidget</extends> + <header>E5Gui/E5PathPicker.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui>
--- a/Preferences/ProgramsDialog.py Sat Nov 11 18:47:09 2017 +0100 +++ b/Preferences/ProgramsDialog.py Sun Nov 12 19:42:02 2017 +0100 @@ -197,13 +197,23 @@ Utilities.isWindowsPlatform() and "rbrcc.exe" or "rbrcc", '-version', 'Ruby Resource Compiler', -1) - # 5. do the CORBA programs + # 5. do the CORBA and Protobuf programs # 5a. omniORB exe = Preferences.getCorba("omniidl") + if not exe: + exe = "omniidl" if Utilities.isWindowsPlatform(): exe += ".exe" self.__createProgramEntry( self.tr("CORBA IDL Compiler"), exe, '-V', 'omniidl', -1) + # 5b. protobuf + exe = Preferences.getProtobuf("protoc") + if not exe: + exe = "protoc" + if Utilities.isWindowsPlatform(): + exe += ".exe" + self.__createProgramEntry( + self.tr("Protobuf Compiler"), exe, '--version', 'libprotoc', -1) # 6. do the spell checking entry try:
--- a/Preferences/__init__.py Sat Nov 11 18:47:09 2017 +0100 +++ b/Preferences/__init__.py Sun Nov 12 19:42:02 2017 +0100 @@ -53,7 +53,7 @@ from Project.ProjectBrowserFlags import SourcesBrowserFlag, FormsBrowserFlag, \ ResourcesBrowserFlag, TranslationsBrowserFlag, InterfacesBrowserFlag, \ - OthersBrowserFlag, AllBrowsersFlag + OthersBrowserFlag, ProtocolsBrowserFlag, AllBrowsersFlag try: from Helpviewer.FlashCookieManager.FlashCookieUtilities import \ @@ -780,54 +780,63 @@ ResourcesBrowserFlag | TranslationsBrowserFlag | InterfacesBrowserFlag | - OthersBrowserFlag), + OthersBrowserFlag | + ProtocolsBrowserFlag), "Qt4C": ( SourcesBrowserFlag | ResourcesBrowserFlag | TranslationsBrowserFlag | InterfacesBrowserFlag | - OthersBrowserFlag), + OthersBrowserFlag | + ProtocolsBrowserFlag), "PyQt5": ( SourcesBrowserFlag | FormsBrowserFlag | ResourcesBrowserFlag | TranslationsBrowserFlag | InterfacesBrowserFlag | - OthersBrowserFlag), + OthersBrowserFlag | + ProtocolsBrowserFlag), "PyQt5C": ( SourcesBrowserFlag | ResourcesBrowserFlag | TranslationsBrowserFlag | InterfacesBrowserFlag | - OthersBrowserFlag), + OthersBrowserFlag | + ProtocolsBrowserFlag), "E6Plugin": ( SourcesBrowserFlag | FormsBrowserFlag | ResourcesBrowserFlag | TranslationsBrowserFlag | InterfacesBrowserFlag | - OthersBrowserFlag), + OthersBrowserFlag | + ProtocolsBrowserFlag), "Console": ( SourcesBrowserFlag | InterfacesBrowserFlag | - OthersBrowserFlag), + OthersBrowserFlag | + ProtocolsBrowserFlag), "Other": ( SourcesBrowserFlag | InterfacesBrowserFlag | - OthersBrowserFlag), + OthersBrowserFlag | + ProtocolsBrowserFlag), "PySide": ( SourcesBrowserFlag | FormsBrowserFlag | ResourcesBrowserFlag | TranslationsBrowserFlag | InterfacesBrowserFlag | - OthersBrowserFlag), + OthersBrowserFlag | + ProtocolsBrowserFlag), "PySideC": ( SourcesBrowserFlag | ResourcesBrowserFlag | TranslationsBrowserFlag | InterfacesBrowserFlag | - OthersBrowserFlag), + OthersBrowserFlag | + ProtocolsBrowserFlag), } # defaults for the project browser colour settings @@ -1270,7 +1279,12 @@ # defaults for corba related stuff corbaDefaults = { - "omniidl": "omniidl" + "omniidl": "" + } + + # defaults for protobuf related stuff + protobufDefaults = { + "protoc": "" } # defaults for user related stuff @@ -3139,7 +3153,7 @@ def getCorba(key, prefClass=Prefs): """ - Module function to retrieve the various corba settings. + Module function to retrieve the various Corba settings. @param key the key of the value to get @param prefClass preferences class used as the storage area @@ -3151,7 +3165,7 @@ def setCorba(key, value, prefClass=Prefs): """ - Module function to store the various corba settings. + Module function to store the various Corba settings. @param key the key of the setting to be set @param value the value to be set @@ -3160,6 +3174,35 @@ prefClass.settings.setValue("Corba/" + key, value) +def getProtobuf(key, prefClass=Prefs): + """ + Module function to retrieve the various protobuf settings. + + @param key the key of the value to get + @type str + @param prefClass preferences class used as the storage area + @type Prefs + @return the requested protobuf setting + @rtype any + """ + return prefClass.settings.value( + "Protobuf/" + key, prefClass.protobufDefaults[key]) + + +def setProtobuf(key, value, prefClass=Prefs): + """ + Module function to store the various protobuf settings. + + @param key the key of the setting to be set + @type str + @param value the value to be set + @type any + @param prefClass preferences class used as the storage area + @type Prefs + """ + prefClass.settings.setValue("Protobuf/" + key, value) + + def getUser(key, prefClass=Prefs): """ Module function to retrieve the various user settings.
--- a/Project/Project.py Sat Nov 11 18:47:09 2017 +0100 +++ b/Project/Project.py Sun Nov 12 19:42:02 2017 +0100 @@ -43,6 +43,7 @@ import Utilities +# TODO: add support for 'PROTOCOLS' (analog INTERFACES) class Project(QObject): """ Class implementing the project management functionality. @@ -428,6 +429,7 @@ "FORMS": [], "RESOURCES": [], "INTERFACES": [], + "PROTOCOLS": [], "OTHERS": [], "TRANSLATIONS": [], "TRANSLATIONEXCEPTIONS": [],
--- a/Project/ProjectBrowser.py Sat Nov 11 18:47:09 2017 +0100 +++ b/Project/ProjectBrowser.py Sun Nov 12 19:42:02 2017 +0100 @@ -23,7 +23,7 @@ from .ProjectBrowserFlags import SourcesBrowserFlag, FormsBrowserFlag, \ ResourcesBrowserFlag, TranslationsBrowserFlag, InterfacesBrowserFlag, \ - OthersBrowserFlag, AllBrowsersFlag + OthersBrowserFlag, ProtocolsBrowserFlag, AllBrowsersFlag class ProjectBrowser(E5TabWidget): @@ -85,6 +85,7 @@ from .ProjectResourcesBrowser import ProjectResourcesBrowser from .ProjectInterfacesBrowser import ProjectInterfacesBrowser from .ProjectOthersBrowser import ProjectOthersBrowser + from .ProjectProtocolsBrowser import ProjectProtocolsBrowser # sources browser self.psBrowser = ProjectSourcesBrowser(self.project) # forms browser @@ -95,6 +96,8 @@ self.ptBrowser = ProjectTranslationsBrowser(self.project) # interfaces (IDL) browser self.piBrowser = ProjectInterfacesBrowser(self.project) + # protocols (protobuf) browser + self.ppBrowser = ProjectProtocolsBrowser(self.project) # others browser self.poBrowser = ProjectOthersBrowser(self.project) @@ -144,6 +147,14 @@ self.project.projectPropertiesChanged.connect( self.piBrowser._initMenusAndVcs) + # connect the protocols (protobuf) browser + self.project.projectClosed.connect(self.ppBrowser._projectClosed) + self.project.projectOpened.connect(self.ppBrowser._projectOpened) + self.project.newProject.connect(self.ppBrowser._newProject) + self.project.reinitVCS.connect(self.ppBrowser._initMenusAndVcs) + self.project.projectPropertiesChanged.connect( + self.ppBrowser._initMenusAndVcs) + # connect the others browser self.project.projectClosed.connect(self.poBrowser._projectClosed) self.project.projectOpened.connect(self.poBrowser._projectOpened) @@ -209,6 +220,12 @@ UI.PixmapCache.getIcon("projectInterfaces.png"), '') self.setTabToolTip(index, self.piBrowser.windowTitle()) + if browserFlags & ProtocolsBrowserFlag: + index = self.addTab( + self.ppBrowser, + UI.PixmapCache.getIcon("protobuf.png"), '') + self.setTabToolTip(index, self.ppBrowser.windowTitle()) + if browserFlags & OthersBrowserFlag: index = self.addTab( self.poBrowser,
--- a/Project/ProjectBrowserFlags.py Sat Nov 11 18:47:09 2017 +0100 +++ b/Project/ProjectBrowserFlags.py Sun Nov 12 19:42:02 2017 +0100 @@ -13,12 +13,15 @@ TranslationsBrowserFlag = 8 InterfacesBrowserFlag = 16 OthersBrowserFlag = 32 +ProtocolsBrowserFlag = 64 + AllBrowsersFlag = SourcesBrowserFlag | \ FormsBrowserFlag | \ ResourcesBrowserFlag | \ TranslationsBrowserFlag | \ InterfacesBrowserFlag | \ - OthersBrowserFlag + OthersBrowserFlag | \ + ProtocolsBrowserFlag # # eflag: noqa = M702
--- a/Project/ProjectBrowserModel.py Sat Nov 11 18:47:09 2017 +0100 +++ b/Project/ProjectBrowserModel.py Sun Nov 12 19:42:02 2017 +0100 @@ -35,6 +35,7 @@ ProjectBrowserTranslationType = 4 ProjectBrowserOthersType = 5 ProjectBrowserResourceType = 6 +ProjectBrowserProtocolsType = 7 class ProjectBrowserItemMixin(object): @@ -253,6 +254,7 @@ "FORMS": ProjectBrowserFormType, "RESOURCES": ProjectBrowserResourceType, "INTERFACES": ProjectBrowserInterfaceType, + "PROTOCOLS": ProjectBrowserProtocolsType, "TRANSLATIONS": ProjectBrowserTranslationType, "OTHERS": ProjectBrowserOthersType, }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Project/ProjectProtocolsBrowser.py Sun Nov 12 19:42:02 2017 +0100 @@ -0,0 +1,646 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the a class used to display the protocols (protobuf) part +of the project. +""" + +from __future__ import unicode_literals +try: + str = unicode +except NameError: + pass + +import os +import glob + +from PyQt5.QtCore import QThread, pyqtSignal, QProcess +from PyQt5.QtWidgets import QDialog, QApplication, QMenu + +from E5Gui.E5Application import e5App +from E5Gui import E5MessageBox +from E5Gui.E5ProgressDialog import E5ProgressDialog + +from .ProjectBrowserModel import ProjectBrowserFileItem, \ + ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem, \ + ProjectBrowserProtocolsType +from .ProjectBaseBrowser import ProjectBaseBrowser + +from UI.BrowserModel import BrowserFileItem, BrowserClassItem, \ + BrowserMethodItem, BrowserClassAttributeItem +import UI.PixmapCache + +import Preferences +import Utilities + + +class ProjectProtocolsBrowser(ProjectBaseBrowser): + """ + A class used to display the protocols (protobuf) part of the project. + + @signal appendStdout(str) emitted after something was received from + a QProcess on stdout + @signal appendStderr(str) emitted after something was received from + a QProcess on stderr + @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. + """ + appendStdout = pyqtSignal(str) + appendStderr = pyqtSignal(str) + showMenu = pyqtSignal(str, QMenu) + + def __init__(self, project, parent=None): + """ + Constructor + + @param project reference to the project object + @type Project + @param parent parent widget of this browser + @type QWidget + """ + self.__protoc = Preferences.getProtobuf("protoc") + if self.__protoc == "": + self.__protoc = Utilities.isWindowsPlatform() and \ + "protoc.exe" or "protoc" + if not Utilities.isinpath(self.__protoc): + self.__protoc = None + self.omniidl = self.__protoc # TODO: remove this line + + ProjectBaseBrowser.__init__(self, project, + ProjectBrowserProtocolsType, parent) + + self.selectedItemsFilter = \ + [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem] + + self.setWindowTitle(self.tr('Protocols (protobuf)')) + + self.setWhatsThis(self.tr( + """<b>Project Protocols Browser</b>""" + """<p>This allows to easily see all protocols (protobuf files)""" + """ contained in the current project. Several actions can be""" + """ executed via the context menu.</p>""" + )) + + project.prepareRepopulateItem.connect(self._prepareRepopulateItem) + project.completeRepopulateItem.connect(self._completeRepopulateItem) + + # TODO: continue from here + def _createPopupMenus(self): + """ + Protected overloaded method to generate the popup menu. + """ + self.menuActions = [] + self.multiMenuActions = [] + self.dirMenuActions = [] + self.dirMultiMenuActions = [] + + self.sourceMenu = QMenu(self) + if self.omniidl is not None: + self.sourceMenu.addAction( + self.tr('Compile interface'), self.__compileInterface) + self.sourceMenu.addAction( + self.tr('Compile all interfaces'), + self.__compileAllInterfaces) + self.sourceMenu.addAction(self.tr('Open'), self._openItem) + self.sourceMenu.addSeparator() + act = self.sourceMenu.addAction( + self.tr('Rename file'), self._renameFile) + self.menuActions.append(act) + act = self.sourceMenu.addAction( + self.tr('Remove from project'), self._removeFile) + self.menuActions.append(act) + act = self.sourceMenu.addAction( + self.tr('Delete'), self.__deleteFile) + self.menuActions.append(act) + self.sourceMenu.addSeparator() + self.sourceMenu.addAction( + self.tr('Add interfaces...'), self.__addInterfaceFiles) + self.sourceMenu.addAction( + self.tr('Add interfaces directory...'), + self.__addInterfacesDirectory) + self.sourceMenu.addSeparator() + self.sourceMenu.addAction( + self.tr('Copy Path to Clipboard'), self._copyToClipboard) + self.sourceMenu.addSeparator() + self.sourceMenu.addAction( + self.tr('Expand all directories'), self._expandAllDirs) + self.sourceMenu.addAction( + self.tr('Collapse all directories'), self._collapseAllDirs) + self.sourceMenu.addSeparator() + self.sourceMenu.addAction(self.tr('Configure...'), self._configure) + self.sourceMenu.addAction( + self.tr('Configure CORBA...'), self.__configureCorba) + + self.menu = QMenu(self) + if self.omniidl is not None: + self.menu.addAction( + self.tr('Compile interface'), self.__compileInterface) + self.menu.addAction( + self.tr('Compile all interfaces'), + self.__compileAllInterfaces) + self.menu.addAction(self.tr('Open'), self._openItem) + self.menu.addSeparator() + self.menu.addAction( + self.tr('Add interfaces...'), self.__addInterfaceFiles) + self.menu.addAction( + self.tr('Add interfaces directory...'), + self.__addInterfacesDirectory) + 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.menu.addAction( + self.tr('Configure CORBA...'), self.__configureCorba) + + self.backMenu = QMenu(self) + if self.omniidl is not None: + self.backMenu.addAction( + self.tr('Compile all interfaces'), + self.__compileAllInterfaces) + self.backMenu.addSeparator() + self.backMenu.addAction( + self.tr('Add interfaces...'), self.project.addIdlFiles) + self.backMenu.addAction( + self.tr('Add interfaces directory...'), self.project.addIdlDir) + 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.addAction( + self.tr('Configure CORBA...'), self.__configureCorba) + self.backMenu.setEnabled(False) + + # create the menu for multiple selected files + self.multiMenu = QMenu(self) + if self.omniidl is not None: + self.multiMenu.addAction( + self.tr('Compile interfaces'), + self.__compileSelectedInterfaces) + self.multiMenu.addAction(self.tr('Open'), self._openItem) + self.multiMenu.addSeparator() + act = self.multiMenu.addAction( + self.tr('Remove from project'), self._removeFile) + self.multiMenuActions.append(act) + act = self.multiMenu.addAction( + self.tr('Delete'), self.__deleteFile) + 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.multiMenu.addAction( + self.tr('Configure CORBA...'), self.__configureCorba) + + self.dirMenu = QMenu(self) + if self.omniidl is not None: + self.dirMenu.addAction( + self.tr('Compile all interfaces'), + self.__compileAllInterfaces) + self.dirMenu.addSeparator() + act = self.dirMenu.addAction( + self.tr('Remove from project'), self._removeFile) + self.dirMenuActions.append(act) + act = self.dirMenu.addAction( + self.tr('Delete'), self._deleteDirectory) + self.dirMenuActions.append(act) + self.dirMenu.addSeparator() + self.dirMenu.addAction( + self.tr('Add interfaces...'), self.__addInterfaceFiles) + self.dirMenu.addAction( + self.tr('Add interfaces directory...'), + self.__addInterfacesDirectory) + self.dirMenu.addSeparator() + self.dirMenu.addAction( + self.tr('Copy Path to Clipboard'), self._copyToClipboard) + self.dirMenu.addSeparator() + self.dirMenu.addAction( + self.tr('Expand all directories'), self._expandAllDirs) + self.dirMenu.addAction( + self.tr('Collapse all directories'), self._collapseAllDirs) + self.dirMenu.addSeparator() + self.dirMenu.addAction(self.tr('Configure...'), self._configure) + self.dirMenu.addAction( + self.tr('Configure CORBA...'), self.__configureCorba) + + self.dirMultiMenu = QMenu(self) + if self.omniidl is not None: + self.dirMultiMenu.addAction( + self.tr('Compile all interfaces'), + self.__compileAllInterfaces) + self.dirMultiMenu.addSeparator() + self.dirMultiMenu.addAction( + self.tr('Add interfaces...'), self.project.addIdlFiles) + self.dirMultiMenu.addAction( + self.tr('Add interfaces directory...'), self.project.addIdlDir) + self.dirMultiMenu.addSeparator() + self.dirMultiMenu.addAction( + self.tr('Expand all directories'), self._expandAllDirs) + self.dirMultiMenu.addAction( + self.tr('Collapse all directories'), self._collapseAllDirs) + self.dirMultiMenu.addSeparator() + self.dirMultiMenu.addAction( + self.tr('Configure...'), self._configure) + self.dirMultiMenu.addAction(self.tr('Configure CORBA...'), + self.__configureCorba) + + self.sourceMenu.aboutToShow.connect(self.__showContextMenu) + self.multiMenu.aboutToShow.connect(self.__showContextMenuMulti) + self.dirMenu.aboutToShow.connect(self.__showContextMenuDir) + self.dirMultiMenu.aboutToShow.connect(self.__showContextMenuDirMulti) + self.backMenu.aboutToShow.connect(self.__showContextMenuBack) + self.mainMenu = self.sourceMenu + + 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: + categories = self.getSelectedItemsCountCategorized( + [ProjectBrowserFileItem, BrowserClassItem, + BrowserMethodItem, ProjectBrowserSimpleDirectoryItem]) + cnt = categories["sum"] + if cnt <= 1: + index = self.indexAt(coord) + if index.isValid(): + self._selectSingleItem(index) + categories = self.getSelectedItemsCountCategorized( + [ProjectBrowserFileItem, BrowserClassItem, + BrowserMethodItem, ProjectBrowserSimpleDirectoryItem]) + cnt = categories["sum"] + + bfcnt = categories[str(ProjectBrowserFileItem)] + cmcnt = categories[str(BrowserClassItem)] + \ + categories[str(BrowserMethodItem)] + sdcnt = categories[str(ProjectBrowserSimpleDirectoryItem)] + if cnt > 1 and cnt == bfcnt: + self.multiMenu.popup(self.mapToGlobal(coord)) + elif cnt > 1 and cnt == sdcnt: + self.dirMultiMenu.popup(self.mapToGlobal(coord)) + else: + index = self.indexAt(coord) + if cnt == 1 and index.isValid(): + if bfcnt == 1 or cmcnt == 1: + itm = self.model().item(index) + if isinstance(itm, ProjectBrowserFileItem): + self.sourceMenu.popup(self.mapToGlobal(coord)) + elif isinstance(itm, BrowserClassItem) or \ + isinstance(itm, BrowserMethodItem): + self.menu.popup(self.mapToGlobal(coord)) + else: + self.backMenu.popup(self.mapToGlobal(coord)) + elif sdcnt == 1: + self.dirMenu.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. + """ + ProjectBaseBrowser._showContextMenu(self, 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 __showContextMenuDir(self): + """ + Private slot called by the dirMenu aboutToShow signal. + """ + ProjectBaseBrowser._showContextMenuDir(self, self.dirMenu) + + self.showMenu.emit("MainDir", self.dirMenu) + + def __showContextMenuDirMulti(self): + """ + Private slot called by the dirMultiMenu aboutToShow signal. + """ + ProjectBaseBrowser._showContextMenuDirMulti(self, self.dirMultiMenu) + + self.showMenu.emit("MainDirMulti", self.dirMultiMenu) + + def __showContextMenuBack(self): + """ + Private slot called by the backMenu aboutToShow signal. + """ + ProjectBaseBrowser._showContextMenuBack(self, self.backMenu) + + self.showMenu.emit("MainBack", self.backMenu) + + def _openItem(self): + """ + Protected slot to handle the open popup menu entry. + """ + itmList = self.getSelectedItems( + [BrowserFileItem, BrowserClassItem, BrowserMethodItem, + BrowserClassAttributeItem]) + + for itm in itmList: + if isinstance(itm, BrowserFileItem): + self.sourceFile[str].emit(itm.fileName()) + elif isinstance(itm, BrowserClassItem): + self.sourceFile[str, int].emit( + itm.fileName(), itm.classObject().lineno) + elif isinstance(itm, BrowserMethodItem): + self.sourceFile[str, int].emit( + itm.fileName(), itm.functionObject().lineno) + elif isinstance(itm, BrowserClassAttributeItem): + self.sourceFile[str, int].emit( + itm.fileName(), itm.attributeObject().lineno) + + def __addInterfaceFiles(self): + """ + Private method to add interface files to the project. + """ + itm = self.model().item(self.currentIndex()) + if isinstance(itm, ProjectBrowserFileItem) or \ + isinstance(itm, BrowserClassItem) or \ + isinstance(itm, BrowserMethodItem): + dn = os.path.dirname(itm.fileName()) + elif isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \ + isinstance(itm, ProjectBrowserDirectoryItem): + dn = itm.dirName() + else: + dn = None + self.project.addFiles('interface', dn) + + def __addInterfacesDirectory(self): + """ + Private method to add interface files of a directory to the project. + """ + itm = self.model().item(self.currentIndex()) + if isinstance(itm, ProjectBrowserFileItem) or \ + isinstance(itm, BrowserClassItem) or \ + isinstance(itm, BrowserMethodItem): + dn = os.path.dirname(itm.fileName()) + elif isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \ + isinstance(itm, ProjectBrowserDirectoryItem): + dn = itm.dirName() + else: + dn = None + self.project.addDirectory('interface', dn) + + def __deleteFile(self): + """ + Private method to delete files from the project. + """ + itmList = self.getSelectedItems() + + files = [] + fullNames = [] + for itm in itmList: + fn2 = itm.fileName() + fullNames.append(fn2) + fn = self.project.getRelativePath(fn2) + files.append(fn) + + from UI.DeleteFilesConfirmationDialog import \ + DeleteFilesConfirmationDialog + dlg = DeleteFilesConfirmationDialog( + self.parent(), + self.tr("Delete interfaces"), + self.tr("Do you really want to delete these interfaces from" + " the project?"), + files) + + if dlg.exec_() == QDialog.Accepted: + for fn2, fn in zip(fullNames, files): + self.closeSourceWindow.emit(fn2) + self.project.deleteFile(fn) + + ########################################################################### + ## Methods to handle the various compile commands + ########################################################################### + + def __readStdout(self): + """ + Private slot to handle the readyReadStandardOutput signal of the + omniidl process. + """ + if self.compileProc is None: + return + + ioEncoding = Preferences.getSystem("IOEncoding") + + self.compileProc.setReadChannel(QProcess.StandardOutput) + while self.compileProc and self.compileProc.canReadLine(): + s = 'omniidl: ' + output = str(self.compileProc.readLine(), ioEncoding, 'replace') + s += output + self.appendStdout.emit(s) + + def __readStderr(self): + """ + Private slot to handle the readyReadStandardError signal of the + omniidl process. + """ + if self.compileProc is None: + return + + ioEncoding = Preferences.getSystem("IOEncoding") + + self.compileProc.setReadChannel(QProcess.StandardError) + while self.compileProc and self.compileProc.canReadLine(): + s = 'omniidl: ' + error = str(self.compileProc.readLine(), ioEncoding, 'replace') + s += error + self.appendStderr.emit(s) + + def __compileIDLDone(self, exitCode, exitStatus): + """ + Private slot to handle the finished signal of the omniidl process. + + @param exitCode exit code of the process (integer) + @param exitStatus exit status of the process (QProcess.ExitStatus) + """ + self.compileRunning = False + ui = e5App().getObject("UserInterface") + if exitStatus == QProcess.NormalExit and exitCode == 0: + path = os.path.dirname(self.idlFile) + poaList = glob.glob(os.path.join(path, "*__POA")) + npoaList = [f.replace("__POA", "") for f in poaList] + fileList = glob.glob(os.path.join(path, "*_idl.py")) + for directory in poaList + npoaList: + fileList += Utilities.direntries(directory, True, "*.py") + for file in fileList: + self.project.appendFile(file) + if not self.noDialog and not ui.notificationsEnabled(): + E5MessageBox.information( + self, + self.tr("Interface Compilation"), + self.tr( + "The compilation of the interface file was" + " successful.")) + else: + ui.showNotification( + UI.PixmapCache.getPixmap("corba48.png"), + self.tr("Interface Compilation"), + self.tr( + "The compilation of the interface file was" + " successful.")) + else: + if not self.noDialog: + E5MessageBox.information( + self, + self.tr("Interface Compilation"), + self.tr( + "The compilation of the interface file failed.")) + else: + ui.showNotification( + UI.PixmapCache.getPixmap("corba48.png"), + self.tr("Interface Compilation"), + self.tr( + "The compilation of the interface file failed.")) + self.compileProc = None + + def __compileIDL(self, fn, noDialog=False, progress=None): + """ + Private method to compile a .idl file to python. + + @param fn filename of the .idl file to be compiled (string) + @param noDialog flag indicating silent operations (boolean) + @param progress reference to the progress dialog (E5ProgressDialog) + @return reference to the compile process (QProcess) + """ + self.compileProc = QProcess() + args = [] + + args.append("-bpython") + args.append("-I.") + + fn = os.path.join(self.project.ppath, fn) + self.idlFile = fn + args.append("-C{0}".format(os.path.dirname(fn))) + args.append(fn) + + self.compileProc.finished.connect(self.__compileIDLDone) + self.compileProc.readyReadStandardOutput.connect(self.__readStdout) + self.compileProc.readyReadStandardError.connect(self.__readStderr) + + self.noDialog = noDialog + self.compileProc.start(self.omniidl, args) + procStarted = self.compileProc.waitForStarted(5000) + if procStarted: + self.compileRunning = True + return self.compileProc + else: + self.compileRunning = False + if progress is not None: + progress.cancel() + E5MessageBox.critical( + self, + self.tr('Process Generation Error'), + self.tr( + '<p>Could not start {0}.<br>' + 'Ensure that it is in the search path.</p>' + ).format(self.omniidl)) + return None + + def __compileInterface(self): + """ + Private method to compile an interface to python. + """ + if self.omniidl is not None: + itm = self.model().item(self.currentIndex()) + fn2 = itm.fileName() + fn = self.project.getRelativePath(fn2) + self.__compileIDL(fn) + + def __compileAllInterfaces(self): + """ + Private method to compile all interfaces to python. + """ + if self.omniidl is not None: + numIDLs = len(self.project.pdata["INTERFACES"]) + progress = E5ProgressDialog( + self.tr("Compiling interfaces..."), + self.tr("Abort"), 0, numIDLs, + self.tr("%v/%m Interfaces"), self) + progress.setModal(True) + progress.setMinimumDuration(0) + progress.setWindowTitle(self.tr("Interfaces")) + i = 0 + + for fn in self.project.pdata["INTERFACES"]: + progress.setValue(i) + if progress.wasCanceled(): + break + proc = self.__compileIDL(fn, True, progress) + if proc is not None: + while proc.state() == QProcess.Running: + QApplication.processEvents() + QThread.msleep(300) + QApplication.processEvents() + else: + break + i += 1 + + progress.setValue(numIDLs) + + def __compileSelectedInterfaces(self): + """ + Private method to compile selected interfaces to python. + """ + if self.omniidl is not None: + items = self.getSelectedItems() + + files = [self.project.getRelativePath(itm.fileName()) + for itm in items] + numIDLs = len(files) + progress = E5ProgressDialog( + self.tr("Compiling interfaces..."), + self.tr("Abort"), 0, numIDLs, + self.tr("%v/%m Interfaces"), self) + progress.setModal(True) + progress.setMinimumDuration(0) + progress.setWindowTitle(self.tr("Interfaces")) + i = 0 + + for fn in files: + progress.setValue(i) + if progress.wasCanceled(): + break + proc = self.__compileIDL(fn, True, progress) + if proc is not None: + while proc.state() == QProcess.Running: + QApplication.processEvents() + QThread.msleep(300) + QApplication.processEvents() + else: + break + i += 1 + + progress.setValue(numIDLs) + + def __configureCorba(self): + """ + Private method to open the configuration dialog. + """ + e5App().getObject("UserInterface").showPreferences("corbaPage")
--- a/UI/Browser.py Sat Nov 11 18:47:09 2017 +0100 +++ b/UI/Browser.py Sun Nov 12 19:42:02 2017 +0100 @@ -463,6 +463,8 @@ self.multiProjectFile.emit(itm.fileName()) elif itm.isIdlFile(): self.sourceFile[str].emit(itm.fileName()) + elif itm.isProtobufFile(): + self.sourceFile[str].emit(itm.fileName()) elif itm.isResourcesFile(): self.sourceFile[str].emit(itm.fileName()) elif itm.isSvgFile():
--- a/UI/BrowserModel.py Sat Nov 11 18:47:09 2017 +0100 +++ b/UI/BrowserModel.py Sun Nov 12 19:42:02 2017 +0100 @@ -1135,6 +1135,8 @@ self._populated = False self._lazyPopulation = True self._moduleName = os.path.basename(finfo) + elif self.isProtobufFile(): + pixName = "protobuf.png" elif self.isSvgFile(): pixName = "fileSvg.png" elif self.isPixmapFile(): @@ -1285,6 +1287,15 @@ """ return self.fileext == '.idl' + def isProtobufFile(self): + """ + Public method to check, if this file is a Google Protocol Buffer file. + + @return flag indicating a protobuf file + @rtype bool + """ + return self.fileext == ".proto" + def isJavaScriptFile(self): """ Public method to check, if this file is a JavaScript file.
--- a/UI/UserInterface.py Sat Nov 11 18:47:09 2017 +0100 +++ b/UI/UserInterface.py Sun Nov 12 19:42:02 2017 +0100 @@ -357,6 +357,15 @@ self.projectBrowser.piBrowser.appendStdout.connect(self.appendToStdout) self.projectBrowser.piBrowser.appendStderr.connect(self.appendToStderr) + self.projectBrowser.ppBrowser.sourceFile[str].connect( + self.viewmanager.openSourceFile) + self.projectBrowser.ppBrowser.sourceFile[str, int].connect( + self.viewmanager.openSourceFile) + self.projectBrowser.ppBrowser.closeSourceWindow.connect( + self.viewmanager.closeWindow) + self.projectBrowser.ppBrowser.appendStdout.connect(self.appendToStdout) + self.projectBrowser.ppBrowser.appendStderr.connect(self.appendToStderr) + self.projectBrowser.poBrowser.sourceFile.connect( self.viewmanager.openSourceFile) self.projectBrowser.poBrowser.closeSourceWindow.connect( @@ -445,6 +454,8 @@ self.preferencesChanged.connect( self.projectBrowser.piBrowser.handlePreferencesChanged) self.preferencesChanged.connect( + self.projectBrowser.ppBrowser.handlePreferencesChanged) + self.preferencesChanged.connect( self.projectBrowser.poBrowser.handlePreferencesChanged) self.preferencesChanged.connect(self.browser.handlePreferencesChanged) self.preferencesChanged.connect(
--- a/eric6.e4p Sat Nov 11 18:47:09 2017 +0100 +++ b/eric6.e4p Sun Nov 12 19:42:02 2017 +0100 @@ -783,6 +783,7 @@ <Source>Preferences/ConfigurationPages/PrinterPage.py</Source> <Source>Preferences/ConfigurationPages/ProjectBrowserPage.py</Source> <Source>Preferences/ConfigurationPages/ProjectPage.py</Source> + <Source>Preferences/ConfigurationPages/ProtobufPage.py</Source> <Source>Preferences/ConfigurationPages/PythonPage.py</Source> <Source>Preferences/ConfigurationPages/QtPage.py</Source> <Source>Preferences/ConfigurationPages/SecurityPage.py</Source> @@ -825,6 +826,7 @@ <Source>Project/ProjectFormsBrowser.py</Source> <Source>Project/ProjectInterfacesBrowser.py</Source> <Source>Project/ProjectOthersBrowser.py</Source> + <Source>Project/ProjectProtocolsBrowser.py</Source> <Source>Project/ProjectResourcesBrowser.py</Source> <Source>Project/ProjectSourcesBrowser.py</Source> <Source>Project/ProjectTranslationsBrowser.py</Source> @@ -1849,6 +1851,7 @@ <Form>Preferences/ConfigurationPages/PrinterPage.ui</Form> <Form>Preferences/ConfigurationPages/ProjectBrowserPage.ui</Form> <Form>Preferences/ConfigurationPages/ProjectPage.ui</Form> + <Form>Preferences/ConfigurationPages/ProtobufPage.ui</Form> <Form>Preferences/ConfigurationPages/PythonPage.ui</Form> <Form>Preferences/ConfigurationPages/QtPage.ui</Form> <Form>Preferences/ConfigurationPages/SecurityPage.ui</Form>