--- a/eric6/UI/UserInterface.py Sat Oct 03 11:14:23 2020 +0200 +++ b/eric6/UI/UserInterface.py Sun Nov 01 11:15:18 2020 +0100 @@ -7,10 +7,13 @@ Module implementing the main user interface. """ - import os import sys import logging +import shutil +import json +import datetime +import getpass from PyQt5.QtCore import ( pyqtSlot, QTimer, QFile, QFileInfo, pyqtSignal, PYQT_VERSION_STR, QDate, @@ -42,6 +45,7 @@ import Preferences import Utilities +import Globals import UI.PixmapCache @@ -1457,7 +1461,100 @@ # no files, project or multiproject was given if not self.__noOpenAtStartup: self.__openOnStartup() - + + def processInstallInfoFile(self): + """ + Public method to process the file containing installation information. + """ + import Globals + + installInfoFile = Globals.getInstallInfoFilePath() + if not os.path.exists(installInfoFile): + filename = os.path.join(getConfig("ericDir"), "eric6install.json") + if os.path.exists(filename): + # eric was installed via the install.py script + shutil.copy2(filename, installInfoFile) + else: + filename = os.path.join(getConfig("ericDir"), + "eric6installpip.json") + if os.path.exists(filename): + # eric was installed via pip (i.e. eric-ide) + try: + installDateTime = datetime.datetime.now(tz=None) + with open(filename, "r") as infoFile: + installInfo = json.load(infoFile) + installInfo["guessed"] = True + installInfo["eric"] = getConfig("ericDir") + installInfo["virtualenv"] = ( + installInfo["eric"].startswith( + os.path.expanduser("~")) + ) + if installInfo["virtualenv"]: + installInfo["user"] = getpass.getuser() + installInfo["exe"] = sys.executable + installInfo["installed"] = True + installInfo["installed_on"] = installDateTime.strftime( + "%Y-%m-%d %H:%M:%S") + installInfo["sudo"] = not os.access( + installInfo["eric"], os.W_OK) + with open(installInfoFile, "w") as infoFile: + json.dump(installInfo, infoFile, indent=2) + except EnvironmentError: + # ignore this + pass + else: + changed = False + with open(installInfoFile, "r") as infoFile: + installInfo = json.load(infoFile) + + # 1. adapt stored file to latest format + if "install_cwd" not in installInfo: + installInfo["install_cwd"] = "" + installInfo["install_cwd_edited"] = False + changed = True + if "installed_on" not in installInfo: + installInfo["installed_on"] = "" + changed = True + + # 2. merge new data into stored file + filename = os.path.join(getConfig("ericDir"), "eric6install.json") + if os.path.exists(filename): + # eric was updated via the install.py script + if ( + os.path.getmtime(filename) > + os.path.getmtime(installInfoFile) + ): + if not installInfo["edited"]: + shutil.copy2(filename, installInfoFile) + else: + with open(filename, "r") as infoFile: + installInfo2 = json.load(infoFile) + if not installInfo["install_cwd_edited"]: + installInfo2["install_cwd"] = installInfo[ + "install_cwd"] + if not installInfo["exe_edited"]: + installInfo2["exe"] = installInfo["exe"] + if not installInfo["argv_edited"]: + installInfo2["argv"] = installInfo["argv"] + if not installInfo["eric_edited"]: + installInfo2["eric"] = installInfo["eric"] + installInfo = installInfo2 + changed = True + else: + filename = os.path.join(getConfig("ericDir"), + "eric6installpip.json") + if os.path.exists(filename): + # eric was updated via pip (i.e. eric-ide) + # just update the installation date and time + installDateTime = datetime.datetime.now(tz=None) + installInfo["installed_on"] = installDateTime.strftime( + "%Y-%m-%d %H:%M:%S") + changed = True + + if changed: + with open(installInfoFile, "w") as infoFile: + json.dump(installInfo, infoFile, indent=2) + def __createDockWindow(self, name): """ Private method to create a dock window with common properties. @@ -2115,6 +2212,20 @@ self.showErrorLogAct.triggered.connect(self.__showErrorLog) self.actions.append(self.showErrorLogAct) + self.showInstallInfoAct = E5Action( + self.tr('Show Install Info'), + self.tr('Show Install &Info...'), + 0, 0, self, 'show_install_info') + self.showInstallInfoAct.setStatusTip(self.tr( + 'Show Installation Information')) + self.showInstallInfoAct.setWhatsThis(self.tr( + """<b>Show Install Info...</b>""" + """<p>Opens a dialog showing some information about the""" + """ installation process.</p>""" + )) + self.showInstallInfoAct.triggered.connect(self.__showInstallInfo) + self.actions.append(self.showInstallInfoAct) + self.reportBugAct = E5Action( self.tr('Report Bug'), self.tr('Report &Bug...'), @@ -3145,6 +3256,8 @@ self.__menus["help"].addAction(self.checkUpdateAct) self.__menus["help"].addAction(self.showVersionsAct) self.__menus["help"].addSeparator() + self.__menus["help"].addAction(self.showInstallInfoAct) + self.__menus["help"].addSeparator() self.__menus["help"].addAction(self.showErrorLogAct) self.__menus["help"].addAction(self.reportBugAct) self.__menus["help"].addAction(self.requestFeatureAct) @@ -3520,6 +3633,9 @@ self.showVersionsAct.setEnabled(not self.__inVersionCheck) self.showErrorLogAct.setEnabled(self.__hasErrorLog()) + infoFileName = Globals.getInstallInfoFilePath() + self.showInstallInfoAct.setEnabled(os.path.exists(infoFileName)) + self.showMenu.emit("Help", self.__menus["help"]) def __showSettingsMenu(self): @@ -3692,9 +3808,8 @@ address = BugAddress subject = "[eric6] " if attachFile is not None: - f = open(attachFile, "r", encoding="utf-8") - body = f.read() - f.close() + with open(attachFile, "r", encoding="utf-8") as f: + body = f.read() if deleteAttachFile: os.remove(attachFile) else: @@ -3721,7 +3836,7 @@ if os.path.exists(logFile): from .ErrorLogDialog import ErrorLogDialog dlg = ErrorLogDialog(logFile, False, self) - dlg.exec_() + dlg.exec() def __hasErrorLog(self): """ @@ -3743,7 +3858,17 @@ from .ErrorLogDialog import ErrorLogDialog dlg = ErrorLogDialog(logFile, True, self) dlg.show() - + + def __showInstallInfo(self): + """ + Private slot to show a dialog containing information about the + installation process. + """ + from .InstallInfoDialog import InstallInfoDialog + dlg = InstallInfoDialog(self) + if dlg.wasLoaded(): + dlg.exec() + def __compareFiles(self): """ Private slot to handle the Compare Files dialog. @@ -4756,7 +4881,7 @@ from Preferences.ToolConfigurationDialog import ToolConfigurationDialog dlg = ToolConfigurationDialog( self.toolGroups[self.currentToolGroup][1], self) - if dlg.exec_() == QDialog.Accepted: + if dlg.exec() == QDialog.Accepted: self.toolGroups[self.currentToolGroup][1] = dlg.getToollist() self.__updateExternalToolsActions() @@ -4769,7 +4894,7 @@ ) dlg = ToolGroupConfigurationDialog( self.toolGroups, self.currentToolGroup, self) - if dlg.exec_() == QDialog.Accepted: + if dlg.exec() == QDialog.Accepted: self.toolGroups, self.currentToolGroup = dlg.getToolGroups() def __createUnitTestDialog(self): @@ -5947,7 +6072,7 @@ self.__lastConfigurationPageName) else: self.__configurationDialog.showConfigurationPageByName("empty") - self.__configurationDialog.exec_() + self.__configurationDialog.exec() QApplication.processEvents() if self.__configurationDialog.result() == QDialog.Accepted: self.__configurationDialog.setPreferences() @@ -6088,7 +6213,7 @@ from Preferences.ViewProfileDialog import ViewProfileDialog dlg = ViewProfileDialog(self.__layoutType, self.profiles['edit'][1], self.profiles['debug'][1]) - if dlg.exec_() == QDialog.Accepted: + if dlg.exec() == QDialog.Accepted: edit, debug = dlg.getVisibilities() self.profiles['edit'][1] = edit self.profiles['debug'][1] = debug @@ -6104,7 +6229,7 @@ """ from E5Gui.E5ToolBarDialog import E5ToolBarDialog dlg = E5ToolBarDialog(self.toolbarManager) - if dlg.exec_() == QDialog.Accepted: + if dlg.exec() == QDialog.Accepted: Preferences.setUI( "ToolbarManagerState", self.toolbarManager.saveState()) @@ -6163,7 +6288,7 @@ from E5Network.E5SslCertificatesDialog import E5SslCertificatesDialog dlg = E5SslCertificatesDialog(self) - dlg.exec_() + dlg.exec() def __clearPrivateData(self): """ @@ -6171,7 +6296,7 @@ """ from .ClearPrivateDataDialog import ClearPrivateDataDialog dlg = ClearPrivateDataDialog(self) - if dlg.exec_() == QDialog.Accepted: + if dlg.exec() == QDialog.Accepted: # recent files, recent projects, recent multi projects, # debug histories, shell histories (files, projects, multiProjects, debug, shell, vcs, plugins) = ( @@ -6628,7 +6753,7 @@ self.pluginManager, [] if pluginFileNames is None else pluginFileNames[:], self) - dlg.exec_() + dlg.exec() if dlg.restartNeeded(): self.__restart(ask=True) @@ -6638,7 +6763,7 @@ """ from PluginManager.PluginUninstallDialog import PluginUninstallDialog dlg = PluginUninstallDialog(self.pluginManager, self) - dlg.exec_() + dlg.exec() def showPluginsAvailable(self): """ @@ -6646,7 +6771,7 @@ """ from PluginManager.PluginRepositoryDialog import PluginRepositoryDialog dlg = PluginRepositoryDialog(self.pluginManager, self) - res = dlg.exec_() + res = dlg.exec() if res == (QDialog.Accepted + 1): self.__installPlugins(dlg.getDownloadedPlugins())