QScintilla/QsciScintillaCompat.py

changeset 6305
7652b925c25e
parent 6285
045dc4c38701
child 6309
acaae2a2f1cb
--- 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.

eric ide

mercurial