Repository: spyder-ide/spyder

Issue:
Preserve size in status bar widgets
this is only a very minor visual bug, that is most probably not important for other people, but it really distracts me..

could you make the status bar (bottom bar) have fixed field sizes? my cpu usage usually hovers around 8-12%, always jumping between one and two digit, making the whole status bar move a little bit to the left.. and catching my attention.. changing numbers are ok, shifting layout is to much..

Since it probably just me, I'll try to have a look at it if I got some more time..



Discussion:
If you could look at this one, the better ;-)

@mariacamilaremolinagutierrez, please work on this one.
Maybe this is a good opportunity to implement something like what VS code does in the status bar.

Clicking on this widgets allows to modify the setting they display.

Also they are in general too big, so we could try to also reduce the size and make them more compact.

<img width="1440" alt="screen shot 2017-01-16 at 12 44 43 pm" src="https://cloud.githubusercontent.com/assets/3627835/21993587/948e6c36-dbe9-11e6-9773-8c1addeff0cd.png">




Resolving patch:
diff --git a/spyder/widgets/status.py b/spyder/widgets/status.py
--- a/spyder/widgets/status.py
+++ b/spyder/widgets/status.py
@@ -4,13 +4,13 @@
 # Licensed under the terms of the MIT License
 # (see spyder/__init__.py for details)
 
-"""Status bar widgets"""
+"""Status bar widgets."""
 
 # Standard library imports
 import os
 
 # Third party imports
-from qtpy.QtCore import QTimer
+from qtpy.QtCore import Qt, QTimer
 from qtpy.QtWidgets import QHBoxLayout, QLabel, QWidget
 
 # Local imports
@@ -27,35 +27,55 @@
 
 
 class StatusBarWidget(QWidget):
-    def __init__(self, parent, statusbar):
-        QWidget.__init__(self, parent)
+    """Status bar widget base."""
 
-        self.label_font = font = get_font(option='rich_font')
-        font.setPointSize(self.font().pointSize())
-        font.setBold(True)
+    def __init__(self, parent, statusbar):
+        """Status bar widget base."""
+        super(StatusBarWidget, self).__init__(parent)
+        self.label_font = get_font(option='rich_font')
+        self.label_font.setPointSize(self.font().pointSize())
+        self.label_font.setBold(True)
 
+        # Layouts
         layout = QHBoxLayout()
         layout.setContentsMargins(0, 0, 0, 0)
         self.setLayout(layout)
 
+        # Setup
         statusbar.addPermanentWidget(self)
 
 
-#==============================================================================
+# =============================================================================
 # Main window-related status bar widgets
-#==============================================================================
+# =============================================================================
 class BaseTimerStatus(StatusBarWidget):
+    """Status bar widget base for widgets that update based on timers."""
+
     TITLE = None
     TIP = None
+
     def __init__(self, parent, statusbar):
-        StatusBarWidget.__init__(self, parent, statusbar)
+        """Status bar widget base for widgets that update based on timers."""
+        super(BaseTimerStatus, self).__init__(parent, statusbar)
+
+        # Widgets
+        self.label = QLabel(self.TITLE)
+        self.value = QLabel()
+
+        # Widget setup
         self.setToolTip(self.TIP)
+        self.value.setAlignment(Qt.AlignRight)
+        self.value.setFont(self.label_font)
+        fm = self.value.fontMetrics()
+        self.value.setMinimumWidth(fm.width('000%'))
+
+        # Layout
         layout = self.layout()
-        layout.addWidget(QLabel(self.TITLE))
-        self.label = QLabel()
-        self.label.setFont(self.label_font)
         layout.addWidget(self.label)
+        layout.addWidget(self.value)
         layout.addSpacing(20)
+
+        # Setup
         if self.is_supported():
             self.timer = QTimer()
             self.timer.timeout.connect(self.update_label)
@@ -65,16 +85,16 @@ def __init__(self, parent, statusbar):
             self.hide()
     
     def set_interval(self, interval):
-        """Set timer interval (ms)"""
+        """Set timer interval (ms)."""
         if self.timer is not None:
             self.timer.setInterval(interval)
     
     def import_test(self):
-        """Raise ImportError if feature is not supported"""
+        """Raise ImportError if feature is not supported."""
         raise NotImplementedError
 
     def is_supported(self):
-        """Return True if feature is supported"""
+        """Return True if feature is supported."""
         try:
             self.import_test()
             return True
@@ -82,32 +102,40 @@ def is_supported(self):
             return False
     
     def get_value(self):
-        """Return value (e.g. CPU or memory usage)"""
+        """Return value (e.g. CPU or memory usage)."""
         raise NotImplementedError
         
     def update_label(self):
-        """Update status label widget, if widget is visible"""
+        """Update status label widget, if widget is visible."""
         if self.isVisible():
-            self.label.setText('%d %%' % self.get_value())
+            self.value.setText('%d %%' % self.get_value())
+
 
 class MemoryStatus(BaseTimerStatus):
+    """Status bar widget for system memory usage."""
+
     TITLE = _("Memory:")
     TIP = _("Memory usage status: "
             "requires the `psutil` (>=v0.3) library on non-Windows platforms")
+
     def import_test(self):
-        """Raise ImportError if feature is not supported"""
+        """Raise ImportError if feature is not supported."""
         from spyder.utils.system import memory_usage  # analysis:ignore
 
     def get_value(self):
-        """Return memory usage"""
+        """Return memory usage."""
         from spyder.utils.system import memory_usage
         return memory_usage()
 
+
 class CPUStatus(BaseTimerStatus):
+    """Status bar widget for system cpu usage."""
+
     TITLE = _("CPU:")
     TIP = _("CPU usage status: requires the `psutil` (>=v0.3) library")
+
     def import_test(self):
-        """Raise ImportError if feature is not supported"""
+        """Raise ImportError if feature is not supported."""
         from spyder.utils import programs
         if not programs.is_module_installed('psutil', '>=0.2.0'):
             # The `interval` argument in `psutil.cpu_percent` function
@@ -115,70 +143,121 @@ def import_test(self):
             raise ImportError
 
     def get_value(self):
-        """Return CPU usage"""
+        """Return CPU usage."""
         import psutil
         return psutil.cpu_percent(interval=0)
 
 
-#==============================================================================
+# =============================================================================
 # Editor-related status bar widgets
-#==============================================================================
-class ReadWriteStatus(StatusBarWidget):
+# =============================================================================
+class ReadWriteStatus(StatusBarWidget):    
+    """Status bar widget for current file read/write mode."""
+
     def __init__(self, parent, statusbar):
-        StatusBarWidget.__init__(self, parent, statusbar)
-        layout = self.layout()
-        layout.addWidget(QLabel(_("Permissions:")))
+        """Status bar widget for current file read/write mode."""
+        super(ReadWriteStatus, self).__init__(parent, statusbar)
+
+        # Widget
+        self.label = QLabel(_("Permissions:"))
         self.readwrite = QLabel()
+
+        # Widget setup
+        self.label.setAlignment(Qt.AlignRight)
         self.readwrite.setFont(self.label_font)
+
+        # Layouts
+        layout = self.layout()
+        layout.addWidget(self.label)
         layout.addWidget(self.readwrite)
         layout.addSpacing(20)
         
     def readonly_changed(self, readonly):
+        """Update read/write file status."""
         readwrite = "R" if readonly else "RW"
         self.readwrite.setText(readwrite.ljust(3))
 
+
 class EOLStatus(StatusBarWidget):
+    """Status bar widget for the current file end of line."""
+
     def __init__(self, parent, statusbar):
-        StatusBarWidget.__init__(self, parent, statusbar)
-        layout = self.layout()
-        layout.addWidget(QLabel(_("End-of-lines:")))
+        """Status bar widget for the current file end of line."""
+        super(EOLStatus, self).__init__(parent, statusbar)
+
+        # Widget
+        self.label = QLabel(_("End-of-lines:"))
         self.eol = QLabel()
+
+        # Widget setup
+        self.label.setAlignment(Qt.AlignRight)
         self.eol.setFont(self.label_font)
+
+        # Layouts
+        layout = self.layout()
+        layout.addWidget(self.label)
         layout.addWidget(self.eol)
         layout.addSpacing(20)
         
     def eol_changed(self, os_name):
+        """Update end of line status."""
         os_name = to_text_string(os_name)
         self.eol.setText({"nt": "CRLF", "posix": "LF"}.get(os_name, "CR"))
 
+
 class EncodingStatus(StatusBarWidget):
+    """Status bar widget for the current file encoding."""
+
     def __init__(self, parent, statusbar):
-        StatusBarWidget.__init__(self, parent, statusbar)
-        layout = self.layout()
-        layout.addWidget(QLabel(_("Encoding:")))
+        """Status bar widget for the current file encoding."""
+        super(EncodingStatus, self).__init__(parent, statusbar)
+
+        # Widgets
+        self.label = QLabel(_("Encoding:"))
         self.encoding = QLabel()
+
+        # Widget setup
+        self.label.setAlignment(Qt.AlignRight)
         self.encoding.setFont(self.label_font)
+
+        # Layouts
+        layout = self.layout()
+        layout.addWidget(self.label)
         layout.addWidget(self.encoding)
         layout.addSpacing(20)
         
     def encoding_changed(self, encoding):
+        """Update encoding of current file."""
         self.encoding.setText(str(encoding).upper().ljust(15))
 
+
 class CursorPositionStatus(StatusBarWidget):
+    """Status bar widget for the current file cursor postion."""
+
     def __init__(self, parent, statusbar):
-        StatusBarWidget.__init__(self, parent, statusbar)
-        layout = self.layout()
-        layout.addWidget(QLabel(_("Line:")))
+        """Status bar widget for the current file cursor postion."""
+        super(CursorPositionStatus, self).__init__(parent, statusbar)
+
+        # Widget
+        self.label_line = QLabel(_("Line:"))
+        self.label_column = QLabel(_("Column:"))
+        self.column = QLabel()
         self.line = QLabel()
+
+        # Widget setup
         self.line.setFont(self.label_font)
-        layout.addWidget(self.line)
-        layout.addWidget(QLabel(_("Column:")))
-        self.column = QLabel()
         self.column.setFont(self.label_font)
+
+        # Layout
+        layout = self.layout()
+        layout.addWidget(self.label_line)
+        layout.addWidget(self.line)
+        layout.addWidget(self.label_column)
         layout.addWidget(self.column)
         self.setLayout(layout)
         
     def cursor_position_changed(self, line, index):
+        """Update cursos position."""
         self.line.setText("%-6d" % (line+1))
         self.column.setText("%-4d" % (index+1))
 


Test patch: