Created a configuration page for the hex editor.

Mon, 11 Jan 2016 17:39:04 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 11 Jan 2016 17:39:04 +0100
changeset 4658
d760763dcc4a
parent 4656
ec546bd4ec56
child 4659
2863d05e83c6

Created a configuration page for the hex editor.

HexEdit/HexEditMainWindow.py file | annotate | diff | comparison | revisions
HexEdit/HexEditWidget.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationDialog.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/HexEditorPage.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/HexEditorPage.ui file | annotate | diff | comparison | revisions
Preferences/__init__.py file | annotate | diff | comparison | revisions
UI/UserInterface.py file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
--- a/HexEdit/HexEditMainWindow.py	Sun Jan 10 19:50:06 2016 +0100
+++ b/HexEdit/HexEditMainWindow.py	Mon Jan 11 17:39:04 2016 +0100
@@ -11,9 +11,11 @@
 
 import os
 
-from PyQt5.QtCore import pyqtSignal, pyqtSlot, QFile, QFileInfo, QSize
+from PyQt5.QtCore import pyqtSignal, pyqtSlot, QFile, QFileInfo, QSize, \
+    QCoreApplication
 from PyQt5.QtGui import QKeySequence
-from PyQt5.QtWidgets import QWhatsThis, QLabel, QWidget, QVBoxLayout
+from PyQt5.QtWidgets import QWhatsThis, QLabel, QWidget, QVBoxLayout, \
+    QDialog, QAction
 
 from E5Gui.E5Action import E5Action
 from E5Gui.E5MainWindow import E5MainWindow
@@ -28,7 +30,6 @@
 import Preferences
 
 
-# TODO: implement a configuration page for the hex editor
 class HexEditMainWindow(E5MainWindow):
     """
     Class implementing the web browser main window.
@@ -52,10 +53,10 @@
         super(HexEditMainWindow, self).__init__(parent)
         self.setObjectName("eric6_hex_editor")
         
-        self.fromEric = fromEric
+        self.__fromEric = fromEric
         self.setWindowIcon(UI.PixmapCache.getIcon("hexEditor.png"))
         
-        if not self.fromEric:
+        if not self.__fromEric:
             self.setStyle(Preferences.getUI("Style"),
                           Preferences.getUI("StyleSheet"))
         
@@ -96,7 +97,11 @@
         self.__editor.dataChanged.connect(self.__modificationChanged)
         self.__editor.overwriteModeChanged.connect(self.__showEditMode)
         self.__editor.readOnlyChanged.connect(self.__showReadOnlyMode)
-        self.__editor.readOnlyChanged.connect(self.__modificationChanged)
+        self.__editor.readOnlyChanged.connect(self.__checkActions)
+        
+        self.preferencesChanged()
+        self.__editor.setOverwriteMode(
+            Preferences.getHexEditor("OpenInOverwriteMode"))
         
         self.__project = project
         self.__lastOpenPath = ""
@@ -118,6 +123,8 @@
         self.__initFileActions()
         self.__initEditActions()
         self.__initHelpActions()
+        if not self.__fromEric:
+            self.__initConfigActions()
         
     def __initFileActions(self):
         """
@@ -138,32 +145,20 @@
         self.newWindowAct.triggered.connect(self.__openHexFileNewWindow)
         self.__actions.append(self.newWindowAct)
         
+        # correct texts will be set later
         self.openAct = E5Action(
             self.tr('Open'),
             UI.PixmapCache.getIcon("open.png"),
             self.tr('&Open...'),
             QKeySequence(self.tr("Ctrl+O", "File|Open")),
             0, self, 'hexEditor_file_open')
-        self.openAct.setStatusTip(self.tr('Open a binary file for editing'))
-        self.openAct.setWhatsThis(self.tr(
-            """<b>Open File</b>"""
-            """<p>This opens a binary file for editing."""
-            """ It pops up a file selection dialog.</p>"""
-        ))
         self.openAct.triggered.connect(self.__openHexFile)
         self.__actions.append(self.openAct)
         
+        # correct texts will be set later
         self.openReadOnlyAct = E5Action(
-            self.tr('Open Read Only'),
-            self.tr('Open Read Only...'),
+            "", "",
             0, 0, self, 'hexEditor_file_open_read_only')
-        self.openReadOnlyAct.setStatusTip(self.tr(
-            'Open a binary file for viewing'))
-        self.openReadOnlyAct.setWhatsThis(self.tr(
-            """<b>Open Read Only</b>"""
-            """<p>This opens a binary file for viewing (i.e. in read only"""
-            """ mode). It pops up a file selection dialog.</p>"""
-        ))
         self.openReadOnlyAct.triggered.connect(self.__openHexFileReadOnly)
         self.__actions.append(self.openReadOnlyAct)
         
@@ -263,7 +258,7 @@
             """<b>Quit</b>"""
             """<p>Quit the hex editor.</p>"""
         ))
-        if not self.fromEric:
+        if not self.__fromEric:
             self.exitAct.triggered.connect(self.__closeAll)
         self.__actions.append(self.exitAct)
     
@@ -556,6 +551,68 @@
         self.whatsThisAct.triggered.connect(self.__whatsThis)
         self.__actions.append(self.whatsThisAct)
     
+    def __initConfigActions(self):
+        """
+        Private method to create the Settings actions.
+        """
+        self.prefAct = E5Action(
+            self.tr('Preferences'),
+            UI.PixmapCache.getIcon("configure.png"),
+            self.tr('&Preferences...'),
+            0, 0, self, 'hexEditor_settings_preferences')
+        self.prefAct.setStatusTip(self.tr(
+            'Set the prefered configuration'))
+        self.prefAct.setWhatsThis(self.tr(
+            """<b>Preferences</b>"""
+            """<p>Set the configuration items of the application"""
+            """ with your prefered values.</p>"""
+        ))
+        self.prefAct.triggered.connect(self.__showPreferences)
+        self.prefAct.setMenuRole(QAction.PreferencesRole)
+        self.__actions.append(self.prefAct)
+    
+    def __setReadOnlyActionTexts(self):
+        """
+        Private method to switch the 'Open Read Only' action between
+        'read only' and 'read write'.
+        """
+        if Preferences.getHexEditor("OpenReadOnly"):
+            self.openAct.setStatusTip(self.tr(
+                'Open a binary file for viewing'))
+            self.openAct.setWhatsThis(self.tr(
+                """<b>Open File</b>"""
+                """<p>This opens a binary file for viewing (i.e. in read"""
+                """ only mode). It pops up a file selection dialog.</p>"""
+            ))
+            
+            self.openReadOnlyAct.setText(self.tr('Open for Editing...'))
+            self.openReadOnlyAct.setIconText(self.tr('Open for Editing'))
+            self.openReadOnlyAct.setStatusTip(self.tr(
+                'Open a binary file for editing'))
+            self.openReadOnlyAct.setWhatsThis(self.tr(
+                """<b>Open for Editing</b>"""
+                """<p>This opens a binary file for editing."""
+                """ It pops up a file selection dialog.</p>"""
+            ))
+        else:
+            self.openAct.setStatusTip(self.tr(
+                'Open a binary file for editing'))
+            self.openAct.setWhatsThis(self.tr(
+                """<b>Open File</b>"""
+                """<p>This opens a binary file for editing."""
+                """ It pops up a file selection dialog.</p>"""
+            ))
+            
+            self.openReadOnlyAct.setText(self.tr('Open Read Only...'))
+            self.openReadOnlyAct.setIconText(self.tr('Open Read Only'))
+            self.openReadOnlyAct.setStatusTip(self.tr(
+                'Open a binary file for viewing'))
+            self.openReadOnlyAct.setWhatsThis(self.tr(
+                """<b>Open Read Only</b>"""
+                """<p>This opens a binary file for viewing (i.e. in read"""
+                """ only mode). It pops up a file selection dialog.</p>"""
+            ))
+    
     def __initMenus(self):
         """
         Private method to create the menus.
@@ -574,7 +631,7 @@
         menu.addSeparator()
         menu.addAction(self.closeAct)
         menu.addAction(self.closeOthersAct)
-        if self.fromEric:
+        if self.__fromEric:
             menu.addAction(self.closeAllAct)
         else:
             menu.addSeparator()
@@ -601,6 +658,11 @@
         menu.addSeparator()
         menu.addAction(self.readonlyAct)
         
+        if not self.__fromEric:
+            menu = mb.addMenu(self.tr("Se&ttings"))
+            menu.setTearOffEnabled(True)
+            menu.addAction(self.prefAct)
+        
         mb.addSeparator()
         
         menu = mb.addMenu(self.tr("&Help"))
@@ -623,7 +685,7 @@
         filetb.addAction(self.saveAsAct)
         filetb.addSeparator()
         filetb.addAction(self.closeAct)
-        if not self.fromEric:
+        if not self.__fromEric:
             filetb.addAction(self.exitAct)
         
         edittb = self.addToolBar(self.tr("Edit"))
@@ -643,6 +705,12 @@
         searchtb.addAction(self.searchNextAct)
         searchtb.addAction(self.searchPrevAct)
         
+        if not self.__fromEric:
+            settingstb = self.addToolBar(self.tr("Settings"))
+            settingstb.setObjectName("SettingsToolBar")
+            settingstb.setIconSize(UI.Config.ToolBarIconSize)
+            settingstb.addAction(self.prefAct)
+        
         helptb = self.addToolBar(self.tr("Help"))
         helptb.setObjectName("HelpToolBar")
         helptb.setIconSize(UI.Config.ToolBarIconSize)
@@ -742,13 +810,13 @@
             Preferences.setGeometry("HexEditorGeometry", self.saveGeometry())
             
             try:
-                if self.fromEric or len(self.__class__.windows) > 1:
+                if self.__fromEric or len(self.__class__.windows) > 1:
                     del self.__class__.windows[
                         self.__class__.windows.index(self)]
             except ValueError:
                 pass
             
-            if not self.fromEric:
+            if not self.__fromEric:
                 Preferences.syncPreferences()
             
             evt.accept()
@@ -772,7 +840,7 @@
         if fileName:
             he = HexEditMainWindow(fileName=fileName,
                                    parent=self.parent(),
-                                   fromEric=self.fromEric,
+                                   fromEric=self.__fromEric,
                                    project=self.__project)
             he.setRecentPaths("", self.__lastSavePath)
             he.show()
@@ -822,6 +890,8 @@
         self.__lastOpenPath = os.path.dirname(fileName)
         self.__editor.setData(data)
         self.__setCurrentFile(fileName)
+        
+        self.__editor.setReadOnly(Preferences.getHexEditor("OpenReadOnly"))
     
     def __openHexFile(self):
         """
@@ -846,7 +916,7 @@
         Private slot to open a binary file in read only mode.
         """
         self.__openHexFile()
-        self.__editor.setReadOnly(True)
+        self.__editor.setReadOnly(not Preferences.getHexEditor("OpenReadOnly"))
         self.__checkActions()
     
     def __saveHexFile(self):
@@ -1130,3 +1200,55 @@
         """
         self.__searchWidget.hide()
         self.__replaceWidget.show()
+    
+    def preferencesChanged(self):
+        """
+        Public method to (re-)read the various settings.
+        """
+        self.__editor.setAddressWidth(
+            Preferences.getHexEditor("AddressAreaWidth"))
+        self.__editor.setAddressArea(
+            Preferences.getHexEditor("ShowAddressArea"))
+        self.__editor.setAsciiArea(
+            Preferences.getHexEditor("ShowAsciiArea"))
+        self.__editor.setHighlighting(
+            Preferences.getHexEditor("HighlightChanges"))
+        self.__editor.setHighlightColors(
+            Preferences.getHexEditor("HighlightingForeGround"),
+            Preferences.getHexEditor("HighlightingBackGround"))
+        self.__editor.setSelectionColors(
+            Preferences.getHexEditor("SelectionForeGround"),
+            Preferences.getHexEditor("SelectionBackGround"))
+        self.__editor.setAddressAreaColors(
+            Preferences.getHexEditor("AddressAreaForeGround"),
+            Preferences.getHexEditor("AddressAreaBackGround"))
+        self.__editor.setFont(
+            Preferences.getHexEditor("Font"))
+        
+        self.__setReadOnlyActionTexts()
+    
+    def __showPreferences(self):
+        """
+        Private slot to set the preferences.
+        """
+        from Preferences.ConfigurationDialog import ConfigurationDialog
+        dlg = ConfigurationDialog(
+            None, 'Configuration', True, fromEric=True,
+            displayMode=ConfigurationDialog.HexEditorMode)
+        dlg.preferencesChanged.connect(
+            self.__preferencesChangedByLocalPreferencesDialog)
+        dlg.show()
+        dlg.showConfigurationPageByName("hexEditorPage")
+        dlg.exec_()
+        QCoreApplication.processEvents()
+        if dlg.result() == QDialog.Accepted:
+            dlg.setPreferences()
+            Preferences.syncPreferences()
+            self.__preferencesChangedByLocalPreferencesDialog()
+    
+    def __preferencesChangedByLocalPreferencesDialog(self):
+        """
+        Private slot to handle preferences changes by our local dialog.
+        """
+        for hexEditor in HexEditMainWindow.windows:
+            hexEditor.preferencesChanged()
--- a/HexEdit/HexEditWidget.py	Sun Jan 10 19:50:06 2016 +0100
+++ b/HexEdit/HexEditWidget.py	Mon Jan 11 17:39:04 2016 +0100
@@ -21,7 +21,6 @@
 import Globals
 
 
-# TODO: implement cursor in ASCII area
 # TODO: implement editing in ASCII area
 
 
@@ -71,8 +70,9 @@
         # Properties
         self.__addressArea = True
         # switch the address area on/off
-        self.__addressAreaColor = QColor()
-        # color of the address area
+        self.__addressAreaBrush = QBrush()
+        self.__addressAreaPen = QPen()
+        # background and pen of the address area
         self.__addressOffset = 0
         # offset into the shown address range
         self.__addressWidth = 4
@@ -137,9 +137,15 @@
         else:
             self.setFont(QFont("Monospace", 10))
         
-        self.setAddressAreaColor(self.palette().alternateBase().color())
-        self.setHighlightColor(QColor(0xff, 0xff, 0x99, 0xff))
-        self.setSelectionColor(self.palette().highlight().color())
+        self.setAddressAreaColors(
+            self.palette().color(QPalette.WindowText),
+            self.palette().alternateBase().color())
+        self.setHighlightColors(
+            self.palette().color(QPalette.WindowText),
+            QColor(0xff, 0xff, 0x99, 0xff))
+        self.setSelectionColors(
+            self.palette().highlightedText().color(),
+            self.palette().highlight().color())
         
         self.__cursorTimer = QTimer()
         self.__cursorTimer.timeout.connect(self.__updateCursor)
@@ -211,23 +217,26 @@
         self.setCursorPosition(self.__cursorPosition)
         self.viewport().update()
     
-    def addressAreaColor(self):
+    def addressAreaColors(self):
         """
-        Public method to get the address area color.
+        Public method to get the address area colors.
         
-        @return address area color
-        @rtype QColor
+        @return address area foreground and background colors
+        @rtype tuple of 2 QColor
         """
-        return QColor(self.__addressAreaColor)
+        return self.__addressAreaPen.color(), self.__addressAreaBrush.color()
     
-    def setAddressAreaColor(self, color):
+    def setAddressAreaColors(self, foreground, background):
         """
-        Public method to set the address area color.
+        Public method to set the address area colors.
         
-        @param color address area color
+        @param foreground address area foreground color
+        @type QColor
+        @param background address area background color
         @type QColor
         """
-        self.__addressAreaColor = QColor(color)
+        self.__addressAreaPen = QPen(foreground)
+        self.__addressAreaBrush = QBrush(background)
         self.viewport().update()
     
     def addressOffset(self):
@@ -436,25 +445,26 @@
         self.__highlighting = on
         self.viewport().update()
     
-    def highlightingColor(self):
+    def highlightColors(self):
         """
-        Public method to get the highlighting color.
+        Public method to get the highlight colors.
         
-        @return highlighting color
-        @rtype QColor
+        @return highlight foreground and background colors
+        @rtype tuple of 2 QColor
         """
-        return self.__highlightingBrush.color()
+        return self.__highlightingPen.color(), self.__highlightingBrush.color()
     
-    def setHighlightColor(self, color):
+    def setHighlightColors(self, foreground, background):
         """
-        Public method to set the highlight color.
+        Public method to set the highlight colors.
         
-        @param color new highlight color
+        @param foreground highlight foreground color
+        @type QColor
+        @param background highlight background color
         @type QColor
         """
-        self.__highlightingBrush = QBrush(color)
-        self.__highlightingPen = QPen(
-            self.viewport().palette().color(QPalette.WindowText))
+        self.__highlightingPen = QPen(foreground)
+        self.__highlightingBrush = QBrush(background)
         self.viewport().update()
     
     def overwriteMode(self):
@@ -476,24 +486,26 @@
         self.__overwriteMode = on
         self.overwriteModeChanged.emit(self.__overwriteMode)
     
-    def selectionColor(self):
+    def selectionColors(self):
         """
-        Public method to get the selection color.
+        Public method to get the selection colors.
         
-        @return selection color
-        @rtype QColor
+        @return selection foreground and background colors
+        @rtype tuple of 2 QColor
         """
-        return self.__selectionBrush.color()
+        return self.__selectionPen.color(), self.__selectionBrush.color()
     
-    def setSelectionColor(self, color):
+    def setSelectionColors(self, foreground, background):
         """
-        Public method to set the selection color.
+        Public method to set the selection colors.
         
-        @param color new selection color
+        @param foreground selection foreground color
+        @type QColor
+        @param background selection background color
         @type QColor
         """
-        self.__selectionBrush = QBrush(color)
-        self.__selectionPen = QPen(Qt.white)
+        self.__selectionPen = QPen(foreground)
+        self.__selectionBrush = QBrush(background)
         self.viewport().update()
     
     def isReadOnly(self):
@@ -539,6 +551,7 @@
         self.__pxGapHexAscii = 2 * self.__pxCharWidth
         self.__pxCursorWidth = self.__pxCharHeight // 7
         self.__pxSelectionSub = self.fontMetrics().descent()
+        self.__adjust()
         self.viewport().update()
     
     def dataAt(self, pos, count=-1):
@@ -1317,7 +1330,7 @@
                     QRect(-pxOfsX, evt.rect().top(),
                           self.__pxPosHexX - self.__pxGapAdrHex // 2 - pxOfsX,
                           self.height()),
-                    self.__addressAreaColor)
+                    self.__addressAreaBrush)
             if self.__asciiArea:
                 linePos = self.__pxPosAsciiX - (self.__pxGapHexAscii // 2)
                 painter.setPen(Qt.gray)
@@ -1329,6 +1342,7 @@
             
             # paint the address area
             if self.__addressArea:
+                painter.setPen(self.__addressAreaPen)
                 address = ""
                 row = 0
                 pxPosY = self.__pxCharHeight
@@ -1417,10 +1431,10 @@
                 # increment loop variables
                 row += 1
                 pxPosY += self.__pxCharHeight
-            
-            painter.setBackgroundMode(Qt.TransparentMode)
-            painter.setPen(
-                self.viewport().palette().color(QPalette.WindowText))
+        
+        painter.setBackgroundMode(Qt.TransparentMode)
+        painter.setPen(
+            self.viewport().palette().color(QPalette.WindowText))
             
         # paint cursor
         if self.__blink and not self.__readOnly and self.hasFocus():
--- a/Preferences/ConfigurationDialog.py	Sun Jan 10 19:50:06 2016 +0100
+++ b/Preferences/ConfigurationDialog.py	Mon Jan 11 17:39:04 2016 +0100
@@ -78,6 +78,7 @@
     DefaultMode = 0
     HelpBrowserMode = 1
     TrayStarterMode = 2
+    HexEditorMode = 3
     
     def __init__(self, parent=None, fromEric=True, displayMode=DefaultMode,
                  expandedEntries=[]):
@@ -88,7 +89,7 @@
         @keyparam fromEric flag indicating a dialog generation from within the
             eric6 ide (boolean)
         @keyparam displayMode mode of the configuration dialog
-            (DefaultMode, HelpBrowserMode, TrayStarterMode)
+            (DefaultMode, HelpBrowserMode, TrayStarterMode, HexEditorMode)
         @exception RuntimeError raised to indicate an invalid dialog mode
         @keyparam expandedEntries list of entries to be shown expanded
             (list of strings)
@@ -96,7 +97,8 @@
         assert displayMode in (
             ConfigurationWidget.DefaultMode,
             ConfigurationWidget.HelpBrowserMode,
-            ConfigurationWidget.TrayStarterMode
+            ConfigurationWidget.TrayStarterMode,
+            ConfigurationWidget.HexEditorMode,
         )
         
         super(ConfigurationWidget, self).__init__(parent)
@@ -138,6 +140,9 @@
                 "graphicsPage":
                 [self.tr("Graphics"), "preferences-graphics.png",
                  "GraphicsPage", None, None],
+                "hexEditorPage":
+                [self.tr("Hex Editor"), "hexEditor.png",
+                 "HexEditorPage", None, None],
                 "iconsPage":
                 [self.tr("Icons"), "preferences-icons.png",
                  "IconsPage", None, None],
@@ -395,6 +400,19 @@
                  "TrayStarterPage", None, None],
             }
         
+        elif displayMode == ConfigurationWidget.HexEditorMode:
+            self.configItems = {
+                # key : [display string, pixmap name, dialog module name or
+                #        page creation function, parent key,
+                #        reference to configuration page (must always be last)]
+                # The dialog module must have the module function 'create' to
+                # create the configuration page. This must have the method
+                # 'save' to save the settings.
+                "hexEditorPage":
+                [self.tr("Hex Editor"), "hexEditor.png",
+                 "HexEditorPage", None, None],
+            }
+        
         else:
             raise RuntimeError("Illegal mode value: {0}".format(displayMode))
         
@@ -426,7 +444,13 @@
         self.buttonBox.accepted.connect(self.accept)
         self.buttonBox.rejected.connect(self.rejected)
         
-        if displayMode != ConfigurationWidget.TrayStarterMode:
+        if displayMode in [ConfigurationWidget.HelpBrowserMode,
+                           ConfigurationWidget.TrayStarterMode,
+                           ConfigurationWidget.HexEditorMode]:
+            self.configListSearch.hide()
+        
+        if displayMode not in [ConfigurationWidget.TrayStarterMode,
+                               ConfigurationWidget.HexEditorMode]:
             self.__initLexers()
         
     def accept(self):
@@ -764,6 +788,7 @@
             self.preferencesChanged.emit()
             if savedState is not None:
                 page.setState(savedState)
+            page.polishPage()
         
     @pyqtSlot()
     def on_resetButton_clicked(self):
@@ -828,6 +853,7 @@
     DefaultMode = ConfigurationWidget.DefaultMode
     HelpBrowserMode = ConfigurationWidget.HelpBrowserMode
     TrayStarterMode = ConfigurationWidget.TrayStarterMode
+    HexEditorMode = ConfigurationWidget.HexEditorMode
     
     def __init__(self, parent=None, name=None, modal=False,
                  fromEric=True, displayMode=ConfigurationWidget.DefaultMode,
@@ -841,7 +867,7 @@
         @keyparam fromEric flag indicating a dialog generation from within the
             eric6 ide (boolean)
         @keyparam displayMode mode of the configuration dialog
-            (DefaultMode, HelpBrowserMode, TrayStarterMode)
+            (DefaultMode, HelpBrowserMode, TrayStarterMode, HexEditorMode)
         @keyparam expandedEntries list of entries to be shown expanded
             (list of strings)
         """
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Preferences/ConfigurationPages/HexEditorPage.py	Mon Jan 11 17:39:04 2016 +0100
@@ -0,0 +1,116 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+
+"""
+Module implementing the Hex Editor configuration page.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSlot
+
+from .ConfigurationPageBase import ConfigurationPageBase
+from .Ui_HexEditorPage import Ui_HexEditorPage
+
+import Preferences
+
+
+class HexEditorPage(ConfigurationPageBase, Ui_HexEditorPage):
+    """
+    Class implementing the Hex Editor configuration page.
+    """
+    def __init__(self):
+        """
+        Constructor
+        """
+        super(HexEditorPage, self).__init__()
+        self.setupUi(self)
+        self.setObjectName("HexEditorPage")
+        
+        # set initial values
+        self.readOnlyCheckBox.setChecked(Preferences.getHexEditor(
+            "OpenReadOnly"))
+        self.overwriteCheckBox.setChecked(Preferences.getHexEditor(
+            "OpenInOverwriteMode"))
+        self.addressAreaCheckBox.setChecked(Preferences.getHexEditor(
+            "ShowAddressArea"))
+        self.addressAreaWidthSpinBox.setValue(Preferences.getHexEditor(
+            "AddressAreaWidth"))
+        self.asciiAreaCheckBox.setChecked(Preferences.getHexEditor(
+            "ShowAsciiArea"))
+        self.highlightingCheckBox.setChecked(Preferences.getHexEditor(
+            "HighlightChanges"))
+        
+        # font
+        self.monospacedFont = Preferences.getHexEditor("Font")
+        self.monospacedFontSample.setFont(self.monospacedFont)
+
+        # colours
+        self.initColour("HighlightingBackGround",
+                        self.highlightingBackGroundButton,
+                        Preferences.getHexEditor)
+        self.initColour("HighlightingForeGround",
+                        self.highlightingForeGroundButton,
+                        Preferences.getHexEditor)
+        self.initColour("SelectionBackGround",
+                        self.selectionBackGroundButton,
+                        Preferences.getHexEditor)
+        self.initColour("SelectionForeGround",
+                        self.selectionForeGroundButton,
+                        Preferences.getHexEditor)
+        self.initColour("AddressAreaBackGround",
+                        self.addressAreaBackGroundButton,
+                        Preferences.getHexEditor)
+        self.initColour("AddressAreaForeGround",
+                        self.addressAreaForeGroundButton,
+                        Preferences.getHexEditor)
+    
+    def save(self):
+        """
+        Public slot to save the IRC configuration.
+        """
+        Preferences.setHexEditor(
+            "OpenReadOnly", self.readOnlyCheckBox.isChecked())
+        Preferences.setHexEditor(
+            "OpenInOverwriteMode", self.overwriteCheckBox.isChecked())
+        Preferences.setHexEditor(
+            "ShowAddressArea", self.addressAreaCheckBox.isChecked())
+        Preferences.setHexEditor(
+            "AddressAreaWidth", self.addressAreaWidthSpinBox.value())
+        Preferences.setHexEditor(
+            "ShowAsciiArea", self.asciiAreaCheckBox.isChecked())
+        Preferences.setHexEditor(
+            "HighlightChanges", self.highlightingCheckBox.isChecked())
+        Preferences.setHexEditor(
+            "Font", self.monospacedFont)
+        
+        # colours
+        self.saveColours(Preferences.setHexEditor)
+    
+    @pyqtSlot()
+    def on_monospacedFontButton_clicked(self):
+        """
+        Private method used to select the font to be used.
+        """
+        self.monospacedFont = self.selectFont(
+            self.monospacedFontSample, self.monospacedFont)
+    
+    def polishPage(self):
+        """
+        Public slot to perform some polishing actions.
+        """
+        self.monospacedFontSample.setFont(self.monospacedFont)
+
+
+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 = HexEditorPage()
+    return page
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Preferences/ConfigurationPages/HexEditorPage.ui	Mon Jan 11 17:39:04 2016 +0100
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HexEditorPage</class>
+ <widget class="QWidget" name="HexEditorPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>623</width>
+    <height>634</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="headerLabel">
+     <property name="text">
+      <string>&lt;b&gt;Configure Hex Editor&lt;/b&gt;</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="Line" name="line14">
+     <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>
+    <layout class="QHBoxLayout" name="horizontalLayout_4">
+     <item>
+      <widget class="QCheckBox" name="readOnlyCheckBox">
+       <property name="toolTip">
+        <string>Select whether files shall be opened in read only mode</string>
+       </property>
+       <property name="text">
+        <string>Open files 'read only'</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QCheckBox" name="overwriteCheckBox">
+       <property name="toolTip">
+        <string>Select whether the editor shall be started in Overwrite mode</string>
+       </property>
+       <property name="text">
+        <string>Overwrite data</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_3">
+     <property name="title">
+      <string>Address Area</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0" colspan="4">
+       <widget class="QCheckBox" name="addressAreaCheckBox">
+        <property name="toolTip">
+         <string>Select whether the address area shall be shown</string>
+        </property>
+        <property name="text">
+         <string>Show Address Area</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0" colspan="4">
+       <layout class="QHBoxLayout">
+        <item>
+         <widget class="QLabel" name="textLabel1_20">
+          <property name="text">
+           <string>Address Area Width:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="addressAreaWidthSpinBox">
+          <property name="toolTip">
+           <string>Enter the width of the address area in characters</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          </property>
+          <property name="suffix">
+           <string> Chars</string>
+          </property>
+          <property name="minimum">
+           <number>2</number>
+          </property>
+          <property name="maximum">
+           <number>12</number>
+          </property>
+          <property name="singleStep">
+           <number>2</number>
+          </property>
+          <property name="value">
+           <number>4</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="TextLabel1_3_4">
+        <property name="text">
+         <string>Foreground:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QPushButton" name="addressAreaForeGroundButton">
+        <property name="minimumSize">
+         <size>
+          <width>100</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Select the foreground colour of the address area</string>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="2">
+       <widget class="QLabel" name="TextLabel1_3_2_4">
+        <property name="text">
+         <string>Background:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="3">
+       <widget class="QPushButton" name="addressAreaBackGroundButton">
+        <property name="minimumSize">
+         <size>
+          <width>100</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Select the background colour of the address area</string>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_4">
+     <property name="title">
+      <string>ASCII Area</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_3">
+      <item>
+       <widget class="QCheckBox" name="asciiAreaCheckBox">
+        <property name="toolTip">
+         <string>Select whether the ASCII area shall be shown</string>
+        </property>
+        <property name="text">
+         <string>Show ASCII Area</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Highlighting</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0" colspan="4">
+       <widget class="QCheckBox" name="highlightingCheckBox">
+        <property name="toolTip">
+         <string>Select whether changed data shall be highlighted</string>
+        </property>
+        <property name="text">
+         <string>Highlight Changed Data</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="TextLabel1_3_2">
+        <property name="text">
+         <string>Foreground:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QPushButton" name="highlightingForeGroundButton">
+        <property name="minimumSize">
+         <size>
+          <width>100</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Select the foreground colour for highlighted data</string>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="2">
+       <widget class="QLabel" name="TextLabel1_3_2_2">
+        <property name="text">
+         <string>Background:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="3">
+       <widget class="QPushButton" name="highlightingBackGroundButton">
+        <property name="minimumSize">
+         <size>
+          <width>100</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Select the background colour for highlighted data</string>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>Selection</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLabel" name="TextLabel1_3_3">
+        <property name="text">
+         <string>Foreground:</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="selectionForeGroundButton">
+        <property name="minimumSize">
+         <size>
+          <width>100</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Select the foreground colour of the selection</string>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="TextLabel1_3_2_3">
+        <property name="text">
+         <string>Background:</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="selectionBackGroundButton">
+        <property name="minimumSize">
+         <size>
+          <width>100</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="toolTip">
+         <string>Select the background colour of the selection</string>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_5">
+     <property name="title">
+      <string>Font</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QPushButton" name="monospacedFontButton">
+        <property name="toolTip">
+         <string>Press to select the font to be used as the monospaced font</string>
+        </property>
+        <property name="text">
+         <string>Monospaced Font</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLineEdit" name="monospacedFontSample">
+        <property name="focusPolicy">
+         <enum>Qt::NoFocus</enum>
+        </property>
+        <property name="text">
+         <string>01 23 45 67 89 ab cd ef 70 81 92 a3 b4 c5 d6 e7 f9</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignHCenter</set>
+        </property>
+        <property name="readOnly">
+         <bool>true</bool>
+        </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>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>readOnlyCheckBox</tabstop>
+  <tabstop>overwriteCheckBox</tabstop>
+  <tabstop>addressAreaCheckBox</tabstop>
+  <tabstop>addressAreaWidthSpinBox</tabstop>
+  <tabstop>addressAreaForeGroundButton</tabstop>
+  <tabstop>addressAreaBackGroundButton</tabstop>
+  <tabstop>asciiAreaCheckBox</tabstop>
+  <tabstop>highlightingCheckBox</tabstop>
+  <tabstop>highlightingForeGroundButton</tabstop>
+  <tabstop>highlightingBackGroundButton</tabstop>
+  <tabstop>selectionForeGroundButton</tabstop>
+  <tabstop>selectionBackGroundButton</tabstop>
+  <tabstop>monospacedFontButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
--- a/Preferences/__init__.py	Sun Jan 10 19:50:06 2016 +0100
+++ b/Preferences/__init__.py	Mon Jan 11 17:39:04 2016 +0100
@@ -1192,7 +1192,23 @@
     # defaults for Hex Editor
     hexEditorDefaults = {
         "HexEditorState": QByteArray(),
+        "AddressAreaWidth": 4,
+        "ShowAddressArea": True,
+        "ShowAsciiArea": True,
+        "OpenInOverwriteMode": True,
+        "OpenReadOnly": False,
+        "HighlightChanges": True,
+        "HighlightingBackGround": QColor(0xff, 0xff, 0x99, 0xff),
+        "HighlightingForeGround": QColor(Qt.black),
+        "SelectionBackGround": QColor("#308cc6"),
+        "SelectionForeGround": QColor(Qt.white),
+        "AddressAreaBackGround": QColor("#efedec"),
+        "AddressAreaForeGround": QColor(Qt.black),
     }
+    if isWindowsPlatform():
+        hexEditorDefaults["Font"] = "Courier,10,-1,5,50,0,0,0,0,0"
+    else:
+        hexEditorDefaults["Font"] = "Monospace,10,-1,5,50,0,0,0,0,0"
 
 
 def readToolGroups(prefClass=Prefs):
@@ -2957,8 +2973,26 @@
     @param prefClass preferences class used as the storage area
     @return the requested user setting
     """
-    return prefClass.settings.value(
-        "HexEditor/" + key, prefClass.hexEditorDefaults[key])
+    if key in ["AddressAreaWidth"]:
+        return int(prefClass.settings.value(
+            "HexEditor/" + key, prefClass.hexEditorDefaults[key]))
+    elif key in ["ShowAddressArea", "ShowAsciiArea", "OpenInOverwriteMode",
+                 "OpenReadOnly", "HighlightChanges"]:
+        return toBool(prefClass.settings.value(
+            "HexEditor/" + key, prefClass.hexEditorDefaults[key]))
+    elif key in ["HighlightingBackGround", "HighlightingForeGround",
+                 "SelectionBackGround", "SelectionForeGround",
+                 "AddressAreaBackGround", "AddressAreaForeGround"]:
+        return QColor(prefClass.settings.value(
+            "HexEditor/" + key, prefClass.hexEditorDefaults[key]))
+    elif key in ["Font"]:
+        f = QFont()
+        f.fromString(prefClass.settings.value(
+            "HexEditor/" + key, prefClass.hexEditorDefaults[key]))
+        return f
+    else:
+        return prefClass.settings.value(
+            "HexEditor/" + key, prefClass.hexEditorDefaults[key])
     
 
 def setHexEditor(key, value, prefClass=Prefs):
@@ -2969,7 +3003,18 @@
     @param value the value to be set
     @param prefClass preferences class used as the storage area
     """
-    prefClass.settings.setValue("HexEditor/" + key, value)
+    if key in ["HighlightingBackGround", "HighlightingForeGround",
+               "SelectionBackGround", "SelectionForeGround",
+               "AddressAreaBackGround", "AddressAreaForeGround"]:
+        if value.alpha() < 255:
+            val = "#{0:8x}".format(value.rgba())
+        else:
+            val = value.name()
+        prefClass.settings.setValue("HexEditor/" + key, val)
+    elif key in ["Font"]:
+        prefClass.settings.setValue("HexEditor/" + key, value.toString())
+    else:
+        prefClass.settings.setValue("HexEditor/" + key, value)
 
 
 def getGeometry(key, prefClass=Prefs):
--- a/UI/UserInterface.py	Sun Jan 10 19:50:06 2016 +0100
+++ b/UI/UserInterface.py	Mon Jan 11 17:39:04 2016 +0100
@@ -5379,6 +5379,10 @@
             self.bottomSidebar.setDelay(delay)
             self.rightSidebar.setDelay(delay)
         
+        from HexEdit.HexEditMainWindow import HexEditMainWindow
+        for hexEditor in HexEditMainWindow.windows:
+            hexEditor.preferencesChanged()
+        
         self.preferencesChanged.emit()
     
     def __masterPasswordChanged(self, oldPassword, newPassword):
--- a/eric6.e4p	Sun Jan 10 19:50:06 2016 +0100
+++ b/eric6.e4p	Mon Jan 11 17:39:04 2016 +0100
@@ -797,6 +797,7 @@
     <Source>Preferences/ConfigurationPages/HelpViewersPage.py</Source>
     <Source>Preferences/ConfigurationPages/HelpVirusTotalPage.py</Source>
     <Source>Preferences/ConfigurationPages/HelpWebBrowserPage.py</Source>
+    <Source>Preferences/ConfigurationPages/HexEditorPage.py</Source>
     <Source>Preferences/ConfigurationPages/IconsPage.py</Source>
     <Source>Preferences/ConfigurationPages/IconsPreviewDialog.py</Source>
     <Source>Preferences/ConfigurationPages/InterfacePage.py</Source>
@@ -1554,6 +1555,7 @@
     <Form>Preferences/ConfigurationPages/HelpViewersPage.ui</Form>
     <Form>Preferences/ConfigurationPages/HelpVirusTotalPage.ui</Form>
     <Form>Preferences/ConfigurationPages/HelpWebBrowserPage.ui</Form>
+    <Form>Preferences/ConfigurationPages/HexEditorPage.ui</Form>
     <Form>Preferences/ConfigurationPages/IconsPage.ui</Form>
     <Form>Preferences/ConfigurationPages/IconsPreviewDialog.ui</Form>
     <Form>Preferences/ConfigurationPages/InterfacePage.ui</Form>

eric ide

mercurial