diff --git a/novelwriter/__init__.py b/novelwriter/__init__.py index 0d1df83a..135eae98 100644 --- a/novelwriter/__init__.py +++ b/novelwriter/__init__.py @@ -76,6 +76,7 @@ def main(sysArgs: list | None = None): "config=", "data=", "testmode", + "meminfo" ] helpMsg = ( @@ -127,6 +128,7 @@ def main(sysArgs: list | None = None): elif inOpt == "--info": logLevel = logging.INFO elif inOpt == "--debug": + CONFIG.isDebug = True logLevel = logging.DEBUG logFormat = "[{asctime:}] {filename:>17}:{lineno:<4d} {levelname:8} {message:}" elif inOpt == "--style": @@ -137,6 +139,8 @@ def main(sysArgs: list | None = None): dataPath = inArg elif inOpt == "--testmode": testMode = True + elif inOpt == "--meminfo": + CONFIG.memInfo = True # Setup Logging pkgLogger = logging.getLogger(__package__) diff --git a/novelwriter/config.py b/novelwriter/config.py index 39035371..debe960b 100644 --- a/novelwriter/config.py +++ b/novelwriter/config.py @@ -225,7 +225,8 @@ class Config: # Other System Info self.hostName = QSysInfo.machineHostName() self.kernelVer = QSysInfo.kernelVersion() - self.isDebug = False + self.isDebug = False # True if running in debug mode + self.memInfo = False # True if displaying mem info in status bar # Packages self.hasEnchant = False # The pyenchant package @@ -485,7 +486,6 @@ class Config: self._recentObj.loadCache() self._checkOptionalPackages() - self.isDebug = logger.getEffectiveLevel() == logging.DEBUG logger.debug("Config instance initialised") diff --git a/novelwriter/gui/statusbar.py b/novelwriter/gui/statusbar.py index 76a94454..1f35ffb8 100644 --- a/novelwriter/gui/statusbar.py +++ b/novelwriter/gui/statusbar.py @@ -27,6 +27,7 @@ import logging from time import time from typing import TYPE_CHECKING, Literal +from datetime import datetime from PyQt5.QtCore import pyqtSlot, QLocale from PyQt5.QtGui import QColor @@ -50,8 +51,9 @@ class GuiMainStatus(QStatusBar): logger.debug("Create: GuiMainStatus") - self._refTime = -1.0 + self._refTime = -1.0 self._userIdle = False + self._debugInfo = False colNone = QColor(*SHARED.theme.statNone) colSaved = QColor(*SHARED.theme.statSaved) @@ -223,4 +225,29 @@ class GuiMainStatus(QStatusBar): self.setDocumentStatus(StatusLED.S_BAD if status else StatusLED.S_GOOD) return + ## + # Debug + ## + + def memInfo(self) -> None: # pragma: no cover + """Display memory info on the status bar.""" + import tracemalloc + if not self._debugInfo: + if tracemalloc.is_tracing(): + self._traceMallocRef = "Total" + else: + self._traceMallocRef = "Relative" + tracemalloc.start() + self._debugInfo = True + + mem = tracemalloc.get_traced_memory() + stamp = datetime.now().strftime("%H:%M:%S") + self.showMessage(( + f"Debug [{stamp}]" + f" \u2013 Widgets: {len(qApp.allWidgets())}" + f" \u2013 {self._traceMallocRef} Memory: {mem[0]:n}" + f" \u2013 Peak: {mem[1]:n}" + ), 6000) + return + # END Class GuiMainStatus diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index bed57b5c..33c849d4 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -1321,6 +1321,8 @@ class GuiMain(QMainWindow): self.mainStatus.setUserIdle(editIdle or userIdle) SHARED.updateIdleTime(currTime, editIdle or userIdle) self.mainStatus.updateTime(idleTime=SHARED.projectIdleTime) + if CONFIG.memInfo and int(currTime) % 5 == 0: # pragma: no cover + self.mainStatus.memInfo() return @pyqtSlot() diff --git a/tests/test_base/test_base_init.py b/tests/test_base/test_base_init.py index 01645e04..c30ec7d3 100644 --- a/tests/test_base/test_base_init.py +++ b/tests/test_base/test_base_init.py @@ -83,7 +83,7 @@ def testBaseInit_Options(monkeypatch, fncPath): """Test command line options for logging level.""" monkeypatch.setattr("novelwriter.guimain.GuiMain", MockGuiMain) monkeypatch.setattr(sys, "argv", [ - "novelWriter.py", "--testmode", f"--config={fncPath}", f"--data={fncPath}" + "novelWriter.py", "--testmode", "--meminfo", f"--config={fncPath}", f"--data={fncPath}" ]) # Defaults w/None Args