Resize auto complete list box to fit with contents.

Sun, 27 May 2018 11:32:01 +0200

author
T.Rzepka <Tobias.Rzepka@gmail.com>
date
Sun, 27 May 2018 11:32:01 +0200
changeset 6305
7652b925c25e
parent 6304
68f9aa03bf75
child 6306
af71f34a0cfb

Resize auto complete list box to fit with contents.

Preferences/ConfigurationPages/EditorAutocompletionPage.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/EditorAutocompletionPage.ui file | annotate | diff | comparison | revisions
Preferences/__init__.py file | annotate | diff | comparison | revisions
QScintilla/Editor.py file | annotate | diff | comparison | revisions
QScintilla/QsciScintillaCompat.py file | annotate | diff | comparison | revisions
QScintilla/Shell.py file | annotate | diff | comparison | revisions
changelog file | annotate | diff | comparison | revisions
--- a/Preferences/ConfigurationPages/EditorAutocompletionPage.py	Thu May 24 19:16:36 2018 +0200
+++ b/Preferences/ConfigurationPages/EditorAutocompletionPage.py	Sun May 27 11:32:01 2018 +0200
@@ -49,6 +49,10 @@
             Preferences.getEditor("AutoCompletionCacheTime"))
         self.acWatchdogDoubleSpinBox.setValue(
             Preferences.getEditor("AutoCompletionWatchdogTime") / 1000.0)
+        self.acLinesSlider.setValue(
+            Preferences.getEditor("AutoCompletionMaxLines"))
+        self.acCharSlider.setValue(
+            Preferences.getEditor("AutoCompletionMaxChars"))
         
     def save(self):
         """
@@ -85,6 +89,12 @@
         Preferences.setEditor(
             "AutoCompletionWatchdogTime",
             self.acWatchdogDoubleSpinBox.value() * 1000)
+        Preferences.setEditor(
+            "AutoCompletionMaxLines",
+            self.acLinesSlider.value())
+        Preferences.setEditor(
+            "AutoCompletionMaxChars",
+            self.acCharSlider.value())
     
 
 def create(dlg):
--- a/Preferences/ConfigurationPages/EditorAutocompletionPage.ui	Thu May 24 19:16:36 2018 +0200
+++ b/Preferences/ConfigurationPages/EditorAutocompletionPage.ui	Sun May 27 11:32:01 2018 +0200
@@ -36,36 +36,149 @@
      <property name="title">
       <string>General</string>
      </property>
-     <layout class="QGridLayout" name="gridLayout_2">
-      <item row="0" column="0" colspan="2">
-       <widget class="QCheckBox" name="acCaseSensitivityCheckBox">
-        <property name="toolTip">
-         <string>Select this to have case sensitive auto-completion lists</string>
+     <layout class="QVBoxLayout" name="verticalLayout_3">
+      <property name="spacing">
+       <number>0</number>
+      </property>
+      <property name="margin">
+       <number>0</number>
+      </property>
+      <item>
+       <layout class="QGridLayout" name="gridLayout_2">
+        <property name="verticalSpacing">
+         <number>9</number>
+        </property>
+        <property name="margin">
+         <number>9</number>
         </property>
-        <property name="text">
-         <string>Case sensitive</string>
-        </property>
-       </widget>
+        <item row="0" column="1">
+         <widget class="QCheckBox" name="acReplaceWordCheckBox">
+          <property name="toolTip">
+           <string>Select this, if the word to the right should be replaced by the selected entry</string>
+          </property>
+          <property name="text">
+           <string>Replace word</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="0">
+         <widget class="QCheckBox" name="acCaseSensitivityCheckBox">
+          <property name="toolTip">
+           <string>Select this to have case sensitive auto-completion lists</string>
+          </property>
+          <property name="text">
+           <string>Case sensitive</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="0">
+         <widget class="QCheckBox" name="acReversedCheckBox">
+          <property name="toolTip">
+           <string>Select to show completions of type 'public' first</string>
+          </property>
+          <property name="text">
+           <string>Show 'public' completions first</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
       </item>
-      <item row="0" column="2" colspan="2">
-       <widget class="QCheckBox" name="acReplaceWordCheckBox">
-        <property name="toolTip">
-         <string>Select this, if the word to the right should be replaced by the selected entry</string>
+      <item>
+       <layout class="QGridLayout" name="gridLayout_3">
+        <property name="margin">
+         <number>9</number>
         </property>
-        <property name="text">
-         <string>Replace word</string>
+        <property name="spacing">
+         <number>9</number>
         </property>
-       </widget>
-      </item>
-      <item row="1" column="0" colspan="2">
-       <widget class="QCheckBox" name="acReversedCheckBox">
-        <property name="toolTip">
-         <string>Select to show completions of type 'public' first</string>
-        </property>
-        <property name="text">
-         <string>Show 'public' completions first</string>
-        </property>
-       </widget>
+        <item row="1" column="0">
+         <widget class="QLabel" name="label_6">
+          <property name="text">
+           <string>Maximum visible characters:</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="0">
+         <widget class="QLabel" name="label_5">
+          <property name="text">
+           <string>Maximum visible lines: </string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="QSlider" name="acLinesSlider">
+          <property name="toolTip">
+           <string>Move to set the maximum number of lines shown in a autocomplete list.</string>
+          </property>
+          <property name="minimum">
+           <number>1</number>
+          </property>
+          <property name="maximum">
+           <number>20</number>
+          </property>
+          <property name="pageStep">
+           <number>2</number>
+          </property>
+          <property name="value">
+           <number>6</number>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="2">
+         <widget class="QLCDNumber" name="lcdNumber">
+          <property name="toolTip">
+           <string>Displays the maximum number of lines.</string>
+          </property>
+          <property name="digitCount">
+           <number>3</number>
+          </property>
+          <property name="segmentStyle">
+           <enum>QLCDNumber::Flat</enum>
+          </property>
+          <property name="intValue" stdset="0">
+           <number>6</number>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QSlider" name="acCharSlider">
+          <property name="toolTip">
+           <string>Move to set the maximum number of characters visible in one line.</string>
+          </property>
+          <property name="minimum">
+           <number>10</number>
+          </property>
+          <property name="maximum">
+           <number>100</number>
+          </property>
+          <property name="value">
+           <number>40</number>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="2">
+         <widget class="QLCDNumber" name="lcdNumber_2">
+          <property name="toolTip">
+           <string>Displays the approximate number of characters per line.</string>
+          </property>
+          <property name="digitCount">
+           <number>3</number>
+          </property>
+          <property name="segmentStyle">
+           <enum>QLCDNumber::Flat</enum>
+          </property>
+          <property name="intValue" stdset="0">
+           <number>40</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
       </item>
      </layout>
     </widget>
@@ -126,7 +239,7 @@
            <string>Displays the selected autocompletion threshold</string>
           </property>
           <property name="digitCount">
-           <number>2</number>
+           <number>3</number>
           </property>
           <property name="segmentStyle">
            <enum>QLCDNumber::Flat</enum>
@@ -378,6 +491,8 @@
   <tabstop>acCaseSensitivityCheckBox</tabstop>
   <tabstop>acReplaceWordCheckBox</tabstop>
   <tabstop>acReversedCheckBox</tabstop>
+  <tabstop>acLinesSlider</tabstop>
+  <tabstop>acCharSlider</tabstop>
   <tabstop>acEnabledGroupBox</tabstop>
   <tabstop>acThresholdSlider</tabstop>
   <tabstop>acTimeoutSpinBox</tabstop>
@@ -396,11 +511,11 @@
    <hints>
     <hint type="sourcelabel">
      <x>442</x>
-     <y>161</y>
+     <y>221</y>
     </hint>
     <hint type="destinationlabel">
      <x>485</x>
-     <y>162</y>
+     <y>222</y>
     </hint>
    </hints>
   </connection>
@@ -411,12 +526,44 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>30</x>
-     <y>237</y>
+     <x>49</x>
+     <y>305</y>
     </hint>
     <hint type="destinationlabel">
-     <x>155</x>
-     <y>259</y>
+     <x>202</x>
+     <y>332</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>acLinesSlider</sender>
+   <signal>valueChanged(int)</signal>
+   <receiver>lcdNumber</receiver>
+   <slot>display(int)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>224</x>
+     <y>125</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>473</x>
+     <y>127</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>acCharSlider</sender>
+   <signal>valueChanged(int)</signal>
+   <receiver>lcdNumber_2</receiver>
+   <slot>display(int)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>255</x>
+     <y>155</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>468</x>
+     <y>154</y>
     </hint>
    </hints>
   </connection>
--- a/Preferences/__init__.py	Thu May 24 19:16:36 2018 +0200
+++ b/Preferences/__init__.py	Sun May 27 11:32:01 2018 +0200
@@ -430,6 +430,8 @@
         "AutoCompletionCacheSize": 100,
         "AutoCompletionCacheTime": 300,     # 5 minutes
         "AutoCompletionWatchdogTime": 3000,     # ms
+        "AutoCompletionMaxLines": 6,
+        "AutoCompletionMaxChars": 40,
         
         "CallTipsEnabled": False,
         "CallTipsVisible": 0,
@@ -2152,7 +2154,8 @@
                  "CaretWidth", "AutoCompletionSource",
                  "AutoCompletionThreshold", "AutoCompletionTimeout",
                  "AutoCompletionCacheSize", "AutoCompletionCacheTime",
-                 "AutoCompletionWatchdogTime", "CallTipsVisible",
+                 "AutoCompletionWatchdogTime", "AutoCompletionMaxLines",
+                 "AutoCompletionMaxChars", "CallTipsVisible",
                  "CallTipsStyle", "MarkOccurrencesTimeout",
                  "AutoSpellCheckChunkSize", "SpellCheckingMinWordSize",
                  "PostScriptLevel", "EOLMode", "ZoomFactor", "WhitespaceSize",
@@ -3908,4 +3911,4 @@
 initRecentSettings()
 
 #
-# eflag: noqa = M613
+# eflag: noqa = M201, M613
--- a/QScintilla/Editor.py	Thu May 24 19:16:36 2018 +0200
+++ b/QScintilla/Editor.py	Sun May 27 11:32:01 2018 +0200
@@ -4444,6 +4444,9 @@
             self.setAutoCompletionThreshold(-1)
             self.setAutoCompletionSource(QsciScintilla.AcsNone)
         
+        self.maxLines = Preferences.getEditor("AutoCompletionMaxLines")
+        self.maxChars = Preferences.getEditor("AutoCompletionMaxChars")
+        
     def __setCallTips(self):
         """
         Private method to configure the calltips function.
--- a/QScintilla/QsciScintillaCompat.py	Thu May 24 19:16:36 2018 +0200
+++ b/QScintilla/QsciScintillaCompat.py	Sun May 27 11:32:01 2018 +0200
@@ -9,9 +9,9 @@
 
 from __future__ import unicode_literals
 
-from PyQt5.QtCore import pyqtSignal, Qt
-from PyQt5.QtGui import QPalette, QColor
-from PyQt5.QtWidgets import QApplication
+from PyQt5.QtCore import pyqtSignal, Qt, QPoint
+from PyQt5.QtGui import QPalette, QColor, QFontMetrics
+from PyQt5.QtWidgets import QApplication, QListWidget
 from PyQt5.Qsci import QsciScintillaBase, QsciScintilla, \
     QSCINTILLA_VERSION as QSCIQSCINTILLA_VERSION
 
@@ -75,6 +75,12 @@
         
         self.userListActivated.connect(self.__completionListSelected)
         self.modificationChanged.connect(self.__modificationChanged)
+        
+        self.maxLines = 5
+        self.maxChars = 40
+        # Adjust the min. size of the autocomplete list box for short strings.
+        # Otherwise the width of the list box is at least the standard width.
+        self.SendScintilla(QsciScintilla.SCI_AUTOCSETMAXWIDTH, 5)
     
     def __modificationChanged(self, m):
         """
@@ -1459,28 +1465,114 @@
     ## replacements for buggy methods
     ###########################################################################
     
-    if "showUserList" not in QsciScintilla.__dict__:
-        def showUserList(self, listId, lst):
-            """
-            Public method to show a user supplied list.
-            
-            @param listId id of the list (integer)
-            @param lst list to be show (list of strings)
-            """
-            if listId <= 0:
-                return
-            
-            self.SendScintilla(
-                QsciScintilla.SCI_AUTOCSETSEPARATOR,
-                ord(self.UserSeparator))
-            self.SendScintilla(
-                QsciScintilla.SCI_USERLISTSHOW, listId,
-                self._encodeString(self.UserSeparator.join(lst)))
+    def showUserList(self, listId, lst):
+        """
+        Public method to show a user supplied list.
+        
+        @param listId id of the list (integer)
+        @param lst list to be show (list of strings)
+        """
+        if listId <= 0:
+            return
+        
+        # Setup seperator for user lists
+        self.SendScintilla(
+            QsciScintilla.SCI_AUTOCSETSEPARATOR, ord(self.UserSeparator))
+        self.SendScintilla(
+            QsciScintilla.SCI_USERLISTSHOW, listId,
+            self._encodeString(self.UserSeparator.join(lst)))
+        
+        self.updateUserListSize()
+    
+    def autoCompleteFromDocument(self):
+        """
+        Public method to resize list box after creation.
+        """
+        super(QsciScintillaCompat, self).autoCompleteFromDocument()
+        self.updateUserListSize()
+    
+    def autoCompleteFromAPIs(self):
+        """
+        Public method to resize list box after creation.
+        """
+        super(QsciScintillaCompat, self).autoCompleteFromAPIs()
+        self.updateUserListSize()
+    
+    def autoCompleteFromAll(self):
+        """
+        Public method to resize list box after creation.
+        """
+        super(QsciScintillaCompat, self).autoCompleteFromAll()
+        self.updateUserListSize()
     
     ###########################################################################
     ## work-arounds for buggy behavior
     ###########################################################################
     
+    def updateUserListSize(self):
+        """
+        Public method to resize the autocompletion list to fit with contents.
+        """
+        childs = self.findChildren(QListWidget)
+        if not childs:
+            return
+        
+        ch = childs[-1]
+        geom = ch.geometry()
+        
+        baseHeight = geom.height()
+        
+        # Workaround for getting all items instead of ch.items() call with
+        # unknown mime types.
+        all_items = ch.findItems('', Qt.MatchStartsWith)
+        if not all_items:
+            return
+        
+        width = 0
+        for item in all_items:
+            itemWidth = ch.visualItemRect(item).width()
+            if itemWidth > width:
+                width = itemWidth
+        
+        width += 4  # Borders
+        
+        itemHeight = ch.visualItemRect(all_items[0]).height()
+        height = min(self.maxLines, len(all_items)) * itemHeight
+        # Just a fiddling factor: 4 for the borders, 2 for better readability,
+        # e.g. underscores at the end of the list.
+        height += 6
+        
+        sbSize = self.verticalScrollBar().sizeHint().width()
+        font = ch.font()
+        fm = QFontMetrics(font)
+        averageCharWidth = fm.averageCharWidth()
+        maxWidth = averageCharWidth * self.maxChars
+        if width > (maxWidth):
+            width = maxWidth
+            height += sbSize
+            # List box doesn't honor limited size to show scroll bars, e.g.
+            # Python 2 on Win 10. So just force it.
+            ch.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+        
+        if len(all_items) > self.maxLines:
+            width += sbSize
+        
+        # Special case, where the space below current line where to less
+        yPos = geom.y()
+        charPos = self.SendScintilla(QsciScintilla.SCI_GETCURRENTPOS)
+        currentYPos = self.SendScintilla(
+            QsciScintilla.SCI_POINTYFROMPOSITION, 0, charPos)
+        
+        # X position doesn't matter: set to 0
+        globalPos = self.mapToGlobal(QPoint(0, currentYPos))
+        if yPos < globalPos.y():
+            deltaHeight = baseHeight - height
+            geom.setY(yPos + deltaHeight - 4)
+        
+        geom.setWidth(width)
+        geom.setHeight(height)
+        ch.setGeometry(geom)
+    
     def __completionListSelected(self, listId, txt):
         """
         Private slot to handle the selection from the completion list.
--- a/QScintilla/Shell.py	Thu May 24 19:16:36 2018 +0200
+++ b/QScintilla/Shell.py	Sun May 27 11:32:01 2018 +0200
@@ -526,6 +526,9 @@
         
         self.racEnabled = Preferences.getShell("AutoCompletionEnabled")
         
+        self.maxLines = Preferences.getEditor("AutoCompletionMaxLines")
+        self.maxChars = Preferences.getEditor("AutoCompletionMaxChars")
+        
     def __setCallTips(self, language='Python'):
         """
         Private method to configure the calltips function.
--- a/changelog	Thu May 24 19:16:36 2018 +0200
+++ b/changelog	Sun May 27 11:32:01 2018 +0200
@@ -7,6 +7,11 @@
      on the left or right of the editor
   -- added a context menu for the "fold" margin
   -- improved handling of folded lines when using "go to" functions
+  -- resize auto complete list box to fit with contents
+    -- added a configuration option (Editor->autocomplete to set up maximum
+       width and height of the auto complete list box
+- Shell
+  -- resize auto complete list box to fit with contents
 - pip Interface
   -- added an action to install a locally available package/wheel
 - Web Browser (NG)

eric ide

mercurial