Henning Schröder avatar Henning Schröder committed 810bd7d

First version of additional Qt widgets collection

Comments (0)

Files changed (15)

Empty file added.

qtwidgets/dockwidget.py

+# -*- coding: utf-8 -*-
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+import dockwidget_icons
+
+
+# Ported from KOffice
+
+
+def hasFeature(dockwidget, feature):
+    return dockwidget.features() & feature == feature
+
+
+
+class DockWidgetTitleBarButton(QAbstractButton):
+
+
+    def __init__(self, titlebar):
+        QAbstractButton.__init__(self, titlebar)
+        self.setFocusPolicy(Qt.NoFocus)
+
+
+    def sizeHint(self):
+        self.ensurePolished()
+        margin = self.style().pixelMetric(QStyle.PM_DockWidgetTitleBarButtonMargin, None, self)
+        if self.icon().isNull():
+            return QSize(margin, margin)
+        iconSize = self.style().pixelMetric(QStyle.PM_SmallIconSize, None, self)
+        pm = self.icon().pixmap(iconSize)
+        return QSize(pm.width() + margin, pm.height() + margin)
+
+
+    def enterEvent(self, event):
+        if self.isEnabled():
+            self.update()
+        QAbstractButton.enterEvent(self, event)
+
+
+    def leaveEvent(self, event):
+        if self.isEnabled():
+            self.update()
+        QAbstractButton.leaveEvent(self, event)
+
+
+
+    def paintEvent(self, event):
+        p = QPainter(self)
+        r = self.rect()
+        opt = QStyleOptionToolButton()
+        opt.init(self)
+        opt.state |= QStyle.State_AutoRaise
+        if self.isEnabled() and self.underMouse() and \
+           not self.isChecked() and not self.isDown():
+            opt.state |= QStyle.State_Raised
+        if self.isChecked():
+            opt.state |= QStyle.State_On
+        if self.isDown():
+            opt.state |= QStyle.State_Sunken
+        self.style().drawPrimitive(
+            QStyle.PE_PanelButtonTool, opt, p, self)
+        opt.icon = self.icon()
+        opt.subControls = QStyle.SubControls()
+        opt.activeSubControls = QStyle.SubControls()
+        opt.features = QStyleOptionToolButton.None
+        opt.arrowType = Qt.NoArrow
+        size = self.style().pixelMetric(QStyle.PM_SmallIconSize, None, self)
+        opt.iconSize = QSize(size, size)
+        self.style().drawComplexControl(QStyle.CC_ToolButton, opt, p, self)
+
+
+
+
+class DockWidgetTitleBar(QWidget):
+    # XXX: support QDockWidget.DockWidgetVerticalTitleBar feature
+
+    
+    def __init__(self, dockWidget):
+        QWidget.__init__(self, dockWidget)
+        self.openIcon = QIcon(":arrow-down.png")
+        self.closeIcon = QIcon(":arrow-right.png")
+        self.pinIcon = QIcon(":pin.png")
+        q = dockWidget
+        self.floatButton = DockWidgetTitleBarButton(self)
+        self.floatButton.setIcon(q.style().standardIcon(
+            QStyle.SP_TitleBarNormalButton, None, q))
+        self.connect(self.floatButton, SIGNAL("clicked()"),
+                     self.toggleFloating)
+        self.floatButton.setVisible(True)
+        self.closeButton = DockWidgetTitleBarButton(self)
+        self.closeButton.setIcon(q.style().standardIcon(
+            QStyle.SP_TitleBarCloseButton, None, q))
+        self.connect(self.closeButton, SIGNAL("clicked()"), dockWidget.close)
+        self.closeButton.setVisible(True)
+        self.collapseButton = DockWidgetTitleBarButton(self)
+        self.collapseButton.setIcon(self.openIcon)
+        self.connect(self.collapseButton, SIGNAL("clicked()"),
+                     self.toggleCollapsed)
+        self.collapseButton.setVisible(True)
+        self.pinButton = DockWidgetTitleBarButton(self)
+        self.pinButton.setIcon(self.pinIcon)
+        self.pinButton.setCheckable(True)
+        self.pinButton.setChecked(True)
+        self.connect(self.pinButton, SIGNAL("clicked(bool)"), self.togglePinned)
+        self.pinButton.setVisible(True)
+        self.connect(dockWidget, SIGNAL("featuresChanged(QDockWidget.DockWidgetFeatures)"), self.featuresChanged)
+        self.featuresChanged(0)
+
+
+    def minimumSizeHint(self):
+        return self.sizeHint()
+
+
+    def sizeHint(self):
+        q = self.parentWidget()
+        mw = q.style().pixelMetric(QStyle.PM_DockWidgetTitleMargin, None, q)
+        fw = q.style().pixelMetric(QStyle.PM_DockWidgetFrameWidth, None, q)
+        closeSize = QSize(0, 0)
+        if self.closeButton:
+            closeSize = self.closeButton.sizeHint()
+        floatSize = QSize(0, 0)
+        if self.floatButton:
+            floatSize = self.floatButton.sizeHint()
+        hideSize = QSize(0, 0)
+        if self.collapseButton:
+            hideSize = self.collapseButton.sizeHint()
+        pinSize = QSize(0, 0)
+        if self.pinButton:
+            pinSize = self.pinButton.sizeHint()
+        buttonHeight = max(max(closeSize.height(), floatSize.height()), 
+                            hideSize.height(), pinSize.height()) + 2
+        buttonWidth = closeSize.width() + floatSize.width() + hideSize.width() + pinSize.width()
+        titleFontMetrics = q.fontMetrics()
+        fontHeight = titleFontMetrics.lineSpacing() + 2 * mw
+        height = max(buttonHeight, fontHeight)
+        width = buttonWidth + height + 4 * mw + 2 * fw
+        if hasFeature(q, QDockWidget.DockWidgetVerticalTitleBar):
+            width, height = height, width
+        return QSize(width, height)
+
+
+    def paintEvent(self, event):
+        p = QStylePainter(self)
+        q = self.parentWidget()
+        if hasFeature(q, QDockWidget.DockWidgetVerticalTitleBar):
+            fw = 1 or q.isFloating() and q.style().pixelMetric(
+                QStyle.PM_DockWidgetFrameWidth, None, q) or 0
+            mw = q.style().pixelMetric(QStyle.PM_DockWidgetTitleMargin, None, q)
+            titleOpt = QStyleOptionDockWidgetV2()
+            titleOpt.initFrom(q)
+            titleOpt.verticalTitleBar = True
+            titleOpt.rect = QRect(
+                QPoint(fw, fw + mw + \
+                       self.collapseButton.size().height() + self.pinButton.size().height()),
+                QSize(
+                   self.geometry().width() - (fw * 2),
+                   self.geometry().height() - (fw * 2) - \
+                   mw - self.collapseButton.size().height() - self.pinButton.size().height()))
+            titleOpt.title = q.windowTitle()
+            titleOpt.closable = hasFeature(q, QDockWidget.DockWidgetClosable)
+            titleOpt.floatable = hasFeature(q, QDockWidget.DockWidgetFloatable)
+            p.drawControl(QStyle.CE_DockWidgetTitle, titleOpt)
+        else:
+            fw = q.isFloating() and q.style().pixelMetric(
+                QStyle.PM_DockWidgetFrameWidth, None, q) or 0
+            mw = q.style().pixelMetric(QStyle.PM_DockWidgetTitleMargin, None, q)
+            titleOpt = QStyleOptionDockWidgetV2()
+            titleOpt.initFrom(q)
+            titleOpt.rect = QRect(
+                QPoint(fw + mw + \
+                       self.collapseButton.size().width() + self.pinButton.size().width(), fw),
+                QSize(
+                   self.geometry().width() - (fw * 2) - \
+                   mw - self.collapseButton.size().width() - self.pinButton.size().width(),
+                   self.geometry().height() - (fw * 2)))
+            titleOpt.title = q.windowTitle()
+            titleOpt.closable = hasFeature(q, QDockWidget.DockWidgetClosable)
+            titleOpt.floatable = hasFeature(q, QDockWidget.DockWidgetFloatable)
+            p.drawControl(QStyle.CE_DockWidgetTitle, titleOpt)
+
+
+    def resizeEvent(self, event):
+        q = self.parentWidget()
+        if hasFeature(q, QDockWidget.DockWidgetVerticalTitleBar):
+            fh = q.isFloating() and q.style().pixelMetric(
+                QStyle.PM_DockWidgetFrameWidth, None, q) or 0
+            opt = QStyleOptionDockWidgetV2()
+            opt.initFrom(q)
+            opt.verticalTitleBar = True
+            opt.rect = QRect(
+                QPoint(fh, 40), #self.geometry().height() - (fh * 3)),
+                QSize(
+                  self.geometry().width() - (fh * 2),
+                  fh * 2))
+            opt.title = q.windowTitle()
+            opt.closable = hasFeature(q, QDockWidget.DockWidgetClosable)
+            opt.floatable = hasFeature(q, QDockWidget.DockWidgetFloatable)
+            floatRect = q.style().subElementRect(
+                QStyle.SE_DockWidgetFloatButton, opt, q)
+            if not floatRect.isNull():
+                self.floatButton.setGeometry(floatRect)
+            closeRect = q.style().subElementRect(
+                QStyle.SE_DockWidgetCloseButton, opt, q)
+            if not closeRect.isNull():
+                self.closeButton.setGeometry(closeRect)
+            top = fh
+            if not floatRect.isNull():
+                top = floatRect.x()
+            elif not closeRect.isNull():
+                top = closeRect.x()
+            size = self.collapseButton.size()
+            if not closeRect.isNull():
+                size = self.closeButton.size()
+            elif not floatRect.isNull():
+                size = self.floatButton.size()
+            collapseRect = QRect(QPoint(top, fh), size)
+            self.collapseButton.setGeometry(collapseRect)
+            pinRect = QRect(QPoint(top, fh+collapseRect.height()+1), size)
+            self.pinButton.setGeometry(pinRect)
+        else:
+            fw = q.isFloating() and q.style().pixelMetric(
+                QStyle.PM_DockWidgetFrameWidth, None, q) or 0
+            opt = QStyleOptionDockWidgetV2()
+            opt.initFrom(q)
+            opt.rect = QRect(
+                QPoint(fw, fw),
+                QSize(
+                  self.geometry().width() - (fw * 2),
+                  self.geometry().height() - (fw * 2)))
+            opt.title = q.windowTitle()
+            opt.closable = hasFeature(q, QDockWidget.DockWidgetClosable)
+            opt.floatable = hasFeature(q, QDockWidget.DockWidgetFloatable)
+            floatRect = q.style().subElementRect(
+                QStyle.SE_DockWidgetFloatButton, opt, q)
+            if not floatRect.isNull():
+                self.floatButton.setGeometry(floatRect)
+            closeRect = q.style().subElementRect(
+                QStyle.SE_DockWidgetCloseButton, opt, q)
+            if not closeRect.isNull():
+                self.closeButton.setGeometry(closeRect)
+            top = fw
+            if not floatRect.isNull():
+                top = floatRect.y()
+            elif not closeRect.isNull():
+                top = closeRect.y()
+            size = self.collapseButton.size()
+            if not closeRect.isNull():
+                size = self.closeButton.size()
+            elif not floatRect.isNull():
+                size = self.floatButton.size()
+            collapseRect = QRect(QPoint(fw, top), size)
+            self.collapseButton.setGeometry(collapseRect)
+            pinRect = QRect(QPoint(fw + collapseRect.width() + 1, top), size)
+            self.pinButton.setGeometry(pinRect)
+
+
+    def setCollapsed(self, collapsed):
+        q = self.parentWidget()
+        if q and q.widget() and q.widget().isHidden() != collapsed:
+            self.toggleCollapsed()
+
+
+    def toggleFloating(self):
+        q = self.parentWidget()
+        q.setFloating(not q.isFloating())
+
+
+    def toggleCollapsed(self):
+        q = self.parentWidget()
+        if not q:
+            return
+        q.toggleCollapsed()
+        self.setCollapsedIcon(q.isCollapsed())
+
+
+    def setCollapsedIcon(self, flag):
+        self.collapseButton.setIcon(flag and self.openIcon or self.closeIcon)
+
+
+    def togglePinned(self, checked):
+        self.parent().setPinned(checked)
+
+
+    def featuresChanged(self, features):
+        q = self.parentWidget()
+        self.closeButton.setVisible(hasFeature(q, QDockWidget.DockWidgetClosable))
+        self.floatButton.setVisible(hasFeature(q, QDockWidget.DockWidgetFloatable))
+        # self.resizeEvent(None)
+
+
+
+class DockMainWidgetWrapper(QWidget):
+
+
+    def __init__(self, dockwidget):
+        QWidget.__init__(self, dockwidget)
+        self.widget = None
+        self.hlayout = QHBoxLayout(self)
+        self.hlayout.setSpacing(0)
+        self.hlayout.setContentsMargins(0, 0, 0, 0)
+        self.setLayout(self.hlayout)
+
+
+    def setWidget(self, widget):
+        self.widget = widget
+        self.widget_height = widget.height
+        self.layout().addWidget(widget)
+
+
+    def isCollapsed(self):
+        return self.widget.isVisible()
+ 
+
+    def setCollapsed(self, flag):
+        if not flag:
+            self.old_size = self.size()
+            self.layout().removeWidget(self.widget)
+            self.widget.hide()
+            if hasFeature(self.parent(), QDockWidget.DockWidgetVerticalTitleBar):
+                self.parent().setMaximumWidth(self.parent().width() - self.width())
+            else:
+                self.parent().setMaximumHeight(self.parent().height() - self.height())
+        else:
+            self.setFixedSize(self.old_size)
+            self.parent().setMinimumSize(QSize(1, 1))
+            self.parent().setMaximumSize(QSize(32768, 32768))
+            self.widget.show()
+            self.layout().addWidget(self.widget)
+            self.setMinimumSize(QSize(1, 1))
+            self.setMaximumSize(QSize(32768, 32768)) 
+
+
+
+class DockWidget(QDockWidget):
+
+
+    def __init__(self, *args):
+        QDockWidget.__init__(self, *args)
+        self.titleBar = DockWidgetTitleBar(self)
+        self.setTitleBarWidget(self.titleBar)
+        self.mainWidget = None
+        self.entered = False
+        self.pinned = True
+        self.shot = False
+
+
+    def enterEvent(self, event):
+        self.entered = True
+        if not self.shot and not self.isPinned() and not self.isFloating():
+            self.shot = True
+            QTimer.singleShot(500, self.autoshow)
+        return QDockWidget.enterEvent(self, event)
+
+
+    def leaveEvent(self, event):
+        self.entered = False
+        if not self.shot and not self.isPinned() and not self.isFloating():
+            self.shot = True
+            QTimer.singleShot(1000, self.autohide)
+        return QDockWidget.leaveEvent(self, event)
+
+    
+    def autohide(self):
+        self.shot = False
+        if not self.entered: 
+            self.setCollapsed(False)
+
+
+    def autoshow(self):
+        self.shot = False
+        if self.entered:
+            self.setCollapsed(True)
+
+
+    def isPinned(self):
+        return self.pinned
+
+
+    def setPinned(self, flag):
+        self.pinned = flag
+
+
+    def setWidget(self, widget):
+        self.mainWidget = DockMainWidgetWrapper(self)
+        self.mainWidget.setWidget(widget)
+        QDockWidget.setWidget(self, self.mainWidget)
+    
+
+    def setCollapsed(self, flag):
+        self.mainWidget.setCollapsed(flag)
+        self.titleBarWidget().setCollapsedIcon(flag)
+
+
+    def isCollapsed(self):
+        return self.mainWidget.isCollapsed()
+
+
+    def toggleCollapsed(self):
+        self.setCollapsed(not self.isCollapsed())
+

qtwidgets/dockwidget_icons.py

+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created: Mi Aug 20 05:23:34 2008
+#      by: The Resource Compiler for PyQt (Qt v4.3.4)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt4 import QtCore
+
+qt_resource_data = "\
+\x00\x00\x02\x0d\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
+\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
+\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
+\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
+\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
+\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x01\x8a\x49\x44\
+\x41\x54\x78\xda\xdd\x93\x31\x4b\x5c\x41\x14\x85\xcf\xbc\x37\xc3\
+\x6e\x50\x57\xc5\x64\xc5\x3f\x91\xca\x56\x48\x13\x42\x04\x8d\x8b\
+\x55\xfe\x80\xe8\x3f\x90\x20\x68\x61\x93\xc2\xc2\x5a\xd1\x36\x65\
+\x92\x26\x16\x46\xc5\x22\xe5\x6a\x23\x08\x8b\x98\x14\xba\xb3\xef\
+\xe5\xed\x2a\x6f\x67\x57\x9d\xf7\xf6\x38\x3c\xd0\xca\x28\x92\x42\
+\xf0\xbb\x5c\xb8\x30\x70\x38\x9c\x3b\x57\x90\xc4\xff\xe0\xb9\x7e\
+\x5a\x01\x09\x87\x70\x60\x02\x79\x3c\x86\xaf\xb8\xa0\x23\x13\xc0\
+\x18\x16\x47\x87\x47\x3f\x59\x61\x61\x5c\xc5\x7e\x0c\xe3\xbb\x49\
+\x1a\xd4\x44\x00\x14\x00\x74\x89\xcc\x6f\x91\x45\xf4\x5e\xf6\xa1\
+\x32\x52\x59\x01\x30\x95\x09\xc0\x60\x49\xff\xd5\xd3\xa5\x52\xa9\
+\x5f\x9f\x6b\x51\x35\x55\x68\xab\x11\x7a\x21\x6a\xac\x01\xaf\x00\
+\xbc\x64\xe6\xb7\xa1\x23\xe2\xb7\x67\x70\x95\xce\xdf\x66\xc0\x9f\
+\xac\x97\x0f\xcb\x6f\xb7\x76\xb6\xac\x92\x0a\xca\x53\x90\x42\x42\
+\x75\x14\x70\x05\xa0\xe5\xba\xee\x3a\x00\x06\x6a\xc5\x34\x08\x83\
+\x12\x67\x59\xbd\xc9\x20\x83\x3f\x58\x16\x1f\xc4\x74\x77\x6f\xf7\
+\x4a\x61\xa8\xe0\xab\x54\xc1\x4f\x7d\x78\x4d\x0f\x1d\x57\x68\x3b\
+\x23\x76\x30\x0d\x8e\xc3\x39\x2e\xd8\xcd\x3b\xb7\xc0\x6f\x5c\xdf\
+\xd8\xdd\x58\x8d\xeb\x71\x2a\x13\x09\xaf\xed\x41\x9e\x4b\x20\x02\
+\x7a\xa2\x42\xd2\xfc\x63\xbe\xa7\x0b\x97\x9f\xef\x5d\xa3\x7d\x6d\
+\x67\xb6\x7f\x6d\xef\xb1\xc5\x54\x5d\x28\xb0\x4e\xe4\xce\x72\x49\
+\x27\xe2\x51\x9b\xcd\xc9\x07\xff\x01\xe7\xc9\xf8\x24\x7e\xb7\x77\
+\xb0\xdf\x90\x2d\x49\x46\xa4\x4a\x72\xc6\x34\xe2\x37\x74\x6f\x0f\
+\x0a\xdc\x84\x1a\x06\xc1\xfb\x13\x7d\x6a\x73\x2a\x9f\x34\x1b\xad\
+\x71\x2e\x53\xe3\x0e\xee\xbd\x05\xf1\x51\x4c\xe2\x85\xaf\xb8\x96\
+\x7c\xc1\x3f\x78\x06\xc7\x74\x0d\x90\x24\xc3\xdb\x6d\x74\x09\xd1\
+\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x02\x6c\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
+\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\
+\x00\x00\x00\x06\x62\x4b\x47\x44\x00\x00\x00\x00\x00\x00\xf9\x43\
+\xbb\x7f\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x12\x00\x00\
+\x0b\x12\x01\xd2\xdd\x7e\xfc\x00\x00\x00\x07\x74\x49\x4d\x45\x07\
+\xd2\x0b\x01\x0d\x00\x32\x9c\x41\x83\x23\x00\x00\x01\xe9\x49\x44\
+\x41\x54\x78\xda\x85\x93\xbd\x8b\x13\x51\x14\xc5\x7f\x4f\x07\xd7\
+\xc4\x04\xb2\x90\x2d\x32\x33\x11\x41\x10\x54\x58\x85\xf8\x0f\xd8\
+\x5a\x6a\x61\x65\x63\x21\x06\x02\x3a\x29\xd2\xd8\x29\x62\x13\xc2\
+\x42\x94\x34\x61\x43\x48\x1a\x21\x56\xdb\xd8\x68\x65\xa7\x29\x76\
+\x41\x50\x41\x0c\x64\x87\xc9\x84\x7c\x1a\x21\xb3\x60\x66\x2c\xb2\
+\x6f\x36\x93\x1d\xf0\xc1\x2b\xde\xfd\x38\xe7\xde\x7b\xde\x15\xdd\
+\x6e\x17\x00\x21\x04\x42\x08\x34\x4d\xc3\xb2\x2c\xff\xbd\x7a\x57\
+\xe3\xe4\x55\x9a\xcd\x66\xc0\x09\x90\x4a\xa5\x00\xe8\x74\x3a\xb4\
+\x5a\xad\x80\x6f\x15\xc4\x30\x0c\x84\x69\x9a\x01\x06\x99\x2c\xcf\
+\x60\x30\x08\xad\x22\x91\x48\x00\x2c\x2b\x58\x67\x00\x3c\x49\x96\
+\x4c\x26\x01\x28\x95\x4a\x7e\x8c\x61\x18\xbe\x1f\xcb\xb2\xe8\xf5\
+\x7a\xd8\xb6\x4d\xbf\xdf\xf7\x01\xf6\x5f\xc7\xbc\x63\xa0\x8c\x34\
+\x66\x32\x99\x75\x1f\x4a\xa3\xd1\x08\xf4\x25\x4f\x64\xeb\x26\x3f\
+\xde\xc2\x95\xfb\x9f\xbe\xc8\xe4\x76\xbb\xcd\xbb\x67\x11\x62\xfa\
+\x6d\x60\x6f\xd9\x42\xa1\x50\xe0\x98\xe5\x0e\xf0\x5c\x02\x6c\x24\
+\xb7\xb9\x90\xba\xca\x87\x37\x2e\x49\xef\x80\x98\xae\xf2\xe7\xf0\
+\x3b\x03\xb1\x8d\x12\x4f\x9f\x0c\x14\xa8\x00\x8f\x4d\xd3\x44\x55\
+\x55\x4c\xd3\x44\xd7\x75\x66\x87\x7b\xb8\x7f\x67\x98\xfd\x23\xd4\
+\xcd\xdf\x28\x91\x34\x9e\x7b\xc4\xfe\xd7\x2e\x37\xae\xa7\xb9\x7c\
+\xeb\x09\x80\x50\x80\x2c\x50\xd5\x34\x2d\x50\xc1\xcf\xcf\x35\x46\
+\xdf\xde\x73\xf0\x6b\x41\x7a\xeb\x0c\x00\x9b\x31\x41\xc7\x76\xb9\
+\x14\xb9\xeb\xcf\x4b\x14\x8b\xc5\x80\x3c\xf9\x7c\x1e\xc0\xfb\xf8\
+\x2a\x4a\xc7\x76\x79\xb8\xe3\x04\x64\x7d\xf1\xe0\x1c\xd7\x2e\x9e\
+\xe5\xde\xcb\xf9\xb2\x83\xe1\x70\xc8\x68\x34\x62\x3c\x1e\x33\x99\
+\x4c\x7c\x15\x76\x9f\x9e\x3f\xa5\x82\xf4\xed\x3c\xda\x38\x51\xa1\
+\x5e\xaf\x87\xfd\x03\xc9\xec\x1b\xcb\xe5\xb2\x8c\x13\xb9\x5c\xce\
+\xf3\x87\x38\x9d\x4e\x03\x2d\xc4\xe3\xf1\x00\x90\xe3\x38\xa1\x3f\
+\x51\x51\x94\xa5\x8c\xb5\x5a\x2d\xb4\x02\x00\xcb\xb2\xa8\x56\xab\
+\xa7\x76\x05\xa0\x52\xa9\x90\xcd\x66\x11\xb3\xd9\x2c\xc0\x10\x8d\
+\x46\x99\xcf\xe7\xa1\xdb\xb8\x5e\x09\x80\x70\x1c\x87\xc5\x62\xf1\
+\xdf\xb5\x0d\x4b\x06\xf8\x07\xf0\x1d\xb1\x3d\x6a\xe9\x1c\x20\x00\
+\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x02\x0f\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
+\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
+\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
+\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
+\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
+\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x01\x8c\x49\x44\
+\x41\x54\x78\xda\xa5\x93\x3f\x4b\x9b\x51\x14\x87\x7f\xe7\xfe\x79\
+\x93\x5c\xd3\x94\x1a\xad\x28\x2e\x9a\x21\x38\x04\x6a\xa1\x85\x40\
+\x1d\x05\xc9\xa4\x11\xa1\x54\x27\x33\xb4\x73\xa5\x73\xe9\x26\x01\
+\xc1\xc5\x45\x17\xe9\xd2\x51\xfc\x16\x0e\xfd\x02\x8d\x58\x11\x41\
+\x13\x93\x9a\x28\xc6\x44\xdf\x7b\xdf\xa3\x59\x2d\x89\xd1\x3c\x70\
+\xa6\x03\x0f\x9c\xdf\x39\x87\x98\x19\xbd\x20\xf0\x00\x9a\xa5\x4c\
+\x64\x3e\xb2\xf4\x6c\x01\x18\x4b\x2b\x8b\x2b\x3f\x63\x1f\x63\x5b\
+\xf4\x83\xe8\xc9\x82\x16\x66\xc0\x50\x6e\x21\xb7\x3c\x7c\x38\xfc\
+\x9b\xa6\xa9\xff\x69\x82\x08\x50\xbc\x2c\xc2\x85\x9d\xc8\xce\x66\
+\xdf\x24\x92\x89\x3f\x94\xa1\x49\xb4\x41\xe1\x21\x7d\x40\xb1\x5e\
+\x04\xa8\xd5\x54\x22\xfd\x21\x1d\x37\x2f\xcc\x1e\xcd\xd1\x67\xde\
+\xe1\xed\x47\x05\xc2\x48\x59\xb2\x25\x04\x41\xd0\x12\x40\x5b\x4d\
+\xa3\xe3\xa3\x9e\x0e\xe9\x2d\xef\x93\x97\xf6\x93\xfe\x17\xfe\xce\
+\xdc\x5e\x10\x16\xb2\x42\x15\xf8\xe4\x43\x3b\x0d\xe5\x2b\xc8\x86\
+\x84\x8e\x68\x95\x1a\x4b\xe5\x0a\xc7\xfb\x6f\x89\xe8\x3d\xdf\xd3\
+\x56\x50\xa0\x02\x6c\x60\x81\x06\x40\x17\x04\x51\x13\x70\x65\x07\
+\x73\x63\x38\x30\x01\x75\x0c\x51\x7a\x5a\x88\x41\x01\xc4\x01\xbc\
+\x04\x38\xca\x70\x21\x87\x57\x43\xfd\xd6\xc6\x83\x5f\xcd\x91\xe6\
+\x3b\xe6\x4e\x23\x78\x42\x71\x4b\x70\x05\xc0\x02\xba\xae\xd9\x67\
+\xe7\x57\x9b\xb5\xaf\xbc\xee\x36\x1e\x0d\x91\x34\xc9\xfb\x02\x08\
+\x88\x22\xea\xc2\x0d\x73\x55\x69\x54\x67\x78\xed\x76\xaf\xab\x35\
+\x4a\xad\x24\x9f\x5a\xbc\xae\x0f\x59\x7b\x14\x1c\x54\x4e\xce\xa6\
+\x38\xcf\xe5\xae\x0f\x49\x28\x21\xc7\xfe\x25\x70\xfd\xf7\x76\xf7\
+\xbc\x5a\x9e\xe0\x55\x2e\xa3\x03\xff\x7d\xa3\xca\x87\xe6\x40\x34\
+\x68\xbf\x35\x37\xd1\x05\x3d\xbf\xf3\x1d\x7f\x4b\x95\x33\x4b\xa1\
+\xe2\xc5\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+"
+
+qt_resource_name = "\
+\x00\x0e\
+\x06\x0c\x0a\x07\
+\x00\x61\
+\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x07\
+\x07\x01\x57\xa7\
+\x00\x70\
+\x00\x69\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0f\
+\x0f\x22\x64\xc7\
+\x00\x61\
+\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\
+"
+
+qt_resource_struct = "\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x00\x22\x00\x00\x00\x00\x00\x01\x00\x00\x02\x11\
+\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x04\x81\
+"
+
+def qInitResources():
+    QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+    QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()

qtwidgets/flowlayout.py

+# -*. coding: utf-8 -*-
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+
+
+# Qt example layout
+    
+class FlowLayout(QLayout):
+    def __init__(self, parent=None, margin=0, spacing=-1):
+        QLayout.__init__(self, parent)
+        if parent is not None:
+            self.setMargin(margin)
+        self.setSpacing(spacing)
+        self.itemList = []
+
+        
+    def addItem(self, item):
+        self.itemList.append(item)
+
+        
+    def count(self):
+        return len(self.itemList)
+
+    
+    def itemAt(self, index):
+        if index >= 0 and index < len(self.itemList):
+            return self.itemList[index]
+
+
+    def takeAt(self, index):
+        if index >= 0 and index < len(self.itemList):
+            return self.itemList.pop(index)
+
+
+    def expandingDirections(self):
+        return Qt.Orientations(Qt.Orientation(0))
+
+
+    def hasHeightForWidth(self):
+        return True
+
+
+    def heightForWidth(self, width):
+        height = self.doLayout(QRect(0, 0, width, 0), True)
+        return height
+
+
+    def setGeometry(self, rect):
+        QLayout.setGeometry(self, rect)
+        self.doLayout(rect, False)
+
+
+    def sizeHint(self):
+        return self.minimumSize()
+
+    
+    def minimumSize(self):
+        size = QSize()
+        for item in self.itemList:
+            size = size.expandedTo(item.minimumSize())
+        size += QSize(2 * self.margin(), 2 * self.margin())
+        return size
+
+
+    def doLayout(self, rect, testOnly):
+        x = rect.x()
+        y = rect.y()
+        lineHeight = 0
+        for item in self.itemList:
+            nextX = x + item.sizeHint().width() + self.spacing()
+            if nextX - self.spacing() > rect.right() and lineHeight > 0:
+                x = rect.x()
+                y = y + lineHeight + self.spacing()
+                nextX = x + item.sizeHint().width() + self.spacing()
+                lineHeight = 0
+            if not testOnly:
+                item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
+            x = nextX
+            lineHeight = max(lineHeight, item.sizeHint().height())
+        return y + lineHeight - rect.y()
+
+
+
+    
+
+    

qtwidgets/freedesktop.py

+# -*- coding: utf-8 -*-
+import __main__
+import os
+from ConfigParser import SafeConfigParser as IniFile
+
+try:
+    from elementtree.ElementTree import ElementTree
+except ImportError:
+    try:
+        from xml.etree.ElementTree import ElementTree
+    except ImportError:
+        ElementTree = None
+        
+    
+__all__ = [
+    "find_icon",
+    ]
+
+    
+
+application_prefix = os.path.dirname(os.path.abspath(__main__.__file__))
+
+
+class DesktopEnvironmentBase(object):
+
+    DEFAULT_ICON_SIZE = 22
+    DEFAULT_ICON_BUTTON_SIZE = 16
+    DEFAULT_ICON_THEME = "hicolor"
+    ICON_SEARCH_PATH = [
+        os.path.join(application_prefix, "icons"),
+        os.path.join(application_prefix, "share", "icons"),
+        os.path.expanduser("~/.local/share/icons"),
+        "/usr/share/icons",
+        "/usr/local/share/icons",
+        ]
+    ICON_SIZES = [128, 64, 48, 32, 22, 16]
+    ICON_CATEGORIES = [
+        "actions", 
+        "apps",
+        "mimetypes", 
+        "devices",
+        "filesystems", "."
+        ]
+    ICON_EXTENSIONS = [".png"]
+
+
+    def __new__(type):
+        # Singleton
+        if not '_instance' in type.__dict__:
+            type._instance = object.__new__(type)
+        return type._instance
+
+
+    def __init__(self):
+        self.init()
+        self.cache = {}
+        self.theme = self.find_theme()
+
+
+    def init(self):
+        pass
+
+
+    def __repr__(self):
+        return "<Desktop %s>" % self.__class__.__name__.upper()
+
+
+    def find_icon(self, name, max_size=None):
+        max_size = max_size or self.DEFAULT_ICON_SIZE
+        try:
+            return self.cache[(name,max_size)]
+        except KeyError:
+            pass
+
+        theme_search_list = [ self.theme ]
+        for other_theme in [
+            self.DEFAULT_ICON_THEME, #"oxygen", "nuvola", "crystalclear", 
+            "."]:
+            if other_theme not in theme_search_list:
+                theme_search_list.append(other_theme)
+
+        for theme in theme_search_list:
+            for size in self.ICON_SIZES:
+                if size > max_size: continue
+                size_size = "%sx%s" % (size, size)
+                for category in self.ICON_CATEGORIES:
+                    for path in self.ICON_SEARCH_PATH:
+                        for ext in self.ICON_EXTENSIONS:
+                            filename = os.path.join(
+                                path, theme, size_size, category, name+ext)
+                            if os.path.exists(filename):
+                                self.cache[(name,max_size)] = filename
+                                return filename
+        self.cache[(name,max_size)] = None
+
+
+
+class Kde(DesktopEnvironmentBase):
+
+    DEFAULT_theme = "default.kde"
+    ICON_SEARCH_PATH = [
+        os.path.expanduser("~/.kde4/share/icons"),
+        os.path.expanduser("~/.kde3/share/icons"),
+        os.path.expanduser("~/.kde/share/icons"),
+        ] + DesktopEnvironmentBase.ICON_SEARCH_PATH
+
+    KDEHOME = os.path.expanduser(os.environ.get("KDEHOME", "~/.kde"))
+    if not os.path.exists(KDEHOME):
+        KDEHOME = None
+
+    if KDEHOME not in ICON_SEARCH_PATH:
+        ICON_SEARCH_PATH.insert(
+            0, os.path.join(KDEHOME, "share", "icons"))
+
+
+    def init(self):
+        self.ini_cache = {}
+
+
+    def kdeini(self, name, section, key, default=None):
+        filename = os.path.join(
+            self.KDEHOME, "share", "config", name)
+        ini = self.ini_cache.get(filename)
+        if not ini:
+            ini = self.kdeglobals_cfg = IniFile()
+            try:
+                ini.read([filename])
+            except:
+                pass
+            self.ini_cache[filename] = ini
+        try:
+            return ini.get(section, key) or default
+        except Exception:
+            return default
+
+
+    def kdeglobals(self, section, key, default=None):
+        return self.kdeini("kdeglobals", section, key, default)
+
+
+    def find_theme(self):
+        return self.kdeglobals("Icons", "Theme", self.DEFAULT_ICON_THEME)
+
+
+
+
+class Gnome(DesktopEnvironmentBase):
+    
+    DEFAULT_ICON_THEME = "gnome"
+    ICON_SEARCH_PATH = [
+        os.path.expanduser("~/.gnome2/share/icons")
+        ] + DesktopEnvironmentBase.ICON_SEARCH_PATH
+
+
+    def init(self):
+        self.etree_cache = {}
+
+
+    def gconf(self, name, key, default=None):
+        filename = os.path.expanduser(
+            "~/.gconf/desktop/gnome/%s/%%gconf.xml" % name)
+        etree = self.etree_cache.get(filename)
+        if not etree:
+            try:
+                etree = ElementTree(file=open(filename))
+                self.etree_cache[filename] = etree
+                for entry in etree.findall("entry"):
+                    if entry.get("name") == key:
+                        return entry.find("stringvalue").text
+            except Exception:
+                pass
+        return default
+
+
+    def find_theme(self):
+        return self.gconf("interface", "icon_theme",
+                          self.DEFAULT_ICON_THEME)
+
+
+
+
+if os.environ.get("KDE_FULL_SESSION", "false") == "true":
+    desktop = Kde()
+else:
+    desktop = Gnome()
+
+find_icon = desktop.find_icon
+
+
+if __name__ == "__main__":
+    for name in ["filenew"]:
+        print Kde().find_icon(name)
+        print Gnome().find_icon(name)

qtwidgets/splitter.py

+# -*. coding: utf-8 -*-
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+
+
+# Ported from minisplitter.{h,cpp} included in QtCreator
+
+
+class StyleHelper(object):
+
+
+    def baseColor(self):
+        return QColor(0x666666)
+
+
+    def borderColor(self):
+        result = self.baseColor()
+        result.setHsv(result.hue(),
+                    result.saturation(),
+                    result.value() / 2)
+        return result
+
+
+StyleHelper.instance = StyleHelper()
+
+
+class SplitterHandle(QSplitterHandle):
+
+    def __init__(self, orientation, parent):
+        QSplitterHandle.__init__(self, orientation, parent)
+        self.setMask(QRegion(self.contentsRect()))
+        self.setAttribute(Qt.WA_MouseNoMask, True)
+
+
+    def resizeEvent(self, event):
+        if self.orientation() == Qt.Horizontal:
+            self.setContentsMargins(2, 0, 2, 0)
+        else:
+            self.setContentsMargins(0, 2, 0, 2)
+        self.setMask(QRegion(self.contentsRect()))
+        return QSplitterHandle.resizeEvent(self, event)
+
+
+    def paintEvent(self, event):
+        painter = QPainter(self)
+        painter.fillRect(event.rect(), StyleHelper.instance.borderColor())
+
+
+
+class Splitter(QSplitter):
+
+
+    def __init__(self, parent):
+        QSplitter.__init__(self, parent)
+        self.setHandleWidth(1)
+        self.setChildrenCollapsible(False)
+
+
+    def createHandle(self):
+        return SplitterHandle(self.orientation(), self)
+

qtwidgets/tabwidget.py

+# -*- coding: utf-8 -*-
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+
+# Ported from http://wiki.qtcentre.org/index.php?title=Movable_Tabs
+
+class MoveableTabBar(QTabBar):
+
+
+    def __init__(self, parent=None):
+        QTabBar.__init__(self, parent)
+        self.setAcceptDrops(True)
+
+
+    def mousePressEvent(self, event):
+        if event.button() == Qt.LeftButton:
+            self.dragStartPos = event.pos()
+        QTabBar.mousePressEvent(self, event)        
+
+        
+    def mouseMoveEvent(self, event):
+        if not (event.buttons() & Qt.LeftButton):
+            return
+        #if (event.pos() - self.dragStartPos).manhattanLength() < \
+        #      QApplication.startDragDistance():
+        #    return
+
+        drag = QDrag(self)
+        mimeData = QMimeData()
+        mimeData.setData("action", "tab-reordering")
+        drag.setMimeData(mimeData)
+        drag.exec_()
+
+        
+    def dragEnterEvent(self, event):
+        m = event.mimeData()
+        formats = m.formats()
+        if formats.contains("action") and m.data("action") == "tab-reordering":
+            event.acceptProposedAction()
+            
+    
+    def dropEvent(self, event):
+        fromIndex = self.tabAt(self.dragStartPos)
+        toIndex = self.tabAt(event.pos())
+        if fromIndex != toIndex:
+            self.emit(SIGNAL("tabMoveRequested"), fromIndex, toIndex)
+        event.acceptProposedAction()
+
+
+
+class TabWidget(QTabWidget):
+
+    
+    def __init__(self, parent=None):
+        QTabWidget.__init__(self, parent)
+        self.tb = MoveableTabBar(self)
+        self.connect(self.tb, SIGNAL("tabMoveRequested"), self.moveTab)
+        self.setTabBar(self.tb)
+    
+
+    def moveTab(self, fromIndex, toIndex):
+        w = self.widget(fromIndex)
+        icon = self.tabIcon(fromIndex)
+        text = self.tabText(fromIndex)
+        self.removeTab(fromIndex)
+        self.insertTab(toIndex, w, icon, text)
+        self.setCurrentIndex(toIndex)
+        
Add a comment to this file

ressources/arrow-down.png

Added
New image
Add a comment to this file

ressources/arrow-right.png

Added
New image

ressources/dockwidget_icons.qrc

+<!DOCTYPE RCC>
+<RCC version="1.0">
+<qresource>
+       <file>pin.png</file>
+       <file>arrow-right.png</file>	
+       <file>arrow-down.png</file>	
+</qresource>
+</RCC>
Added
New image

test/test_dockwidget.py

+#!/usr/bin/end python
+# -*- coding: utf-8 -*-
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from qtwidgets.dockwidget import DockWidget
+
+
+
+def test_dockwidget():
+    import sys
+    app = QApplication(sys.argv)    
+    win = QMainWindow()
+    dock1 = DockWidget("1st dockwidget", win)
+    dock1.setFeatures(dock1.features() | QDockWidget.DockWidgetVerticalTitleBar)
+    combo =  QComboBox(dock1)
+    dock1.setWidget(combo)
+    win.addDockWidget(Qt.LeftDockWidgetArea, dock1)
+    dock2 = DockWidget("2nd dockwidget")
+    dock2.setFeatures(dock1.features() | QDockWidget.DockWidgetVerticalTitleBar)
+    button = QPushButton("Hello, world!", dock2)
+    dock2.setWidget(button)
+    win.addDockWidget(Qt.RightDockWidgetArea, dock2)
+    edit = QTextEdit(win)
+    win.setCentralWidget(edit)
+    win.resize(640, 480)
+    win.show()
+    app.exec_()
+
+
+
+
+if __name__ == "__main__":
+    test_dockwidget()

test/test_flowlayout.py

+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from qtwidgets.flowlayout import FlowLayout
+
+
+def test_flowlayout():
+    class Window(QWidget):
+        def __init__(self, parent=None):
+            QWidget.__init__(self, parent)
+            flowLayout = FlowLayout()
+            flowLayout.addWidget(QPushButton(self.tr("Short")))
+            flowLayout.addWidget(QPushButton(self.tr("Longer")))
+            flowLayout.addWidget(QPushButton(self.tr("Different text")))
+            flowLayout.addWidget(QPushButton(self.tr("More text")))
+            flowLayout.addWidget(QPushButton(self.tr("Even longer button text")))
+            self.setLayout(flowLayout)
+            self.setWindowTitle(self.tr("Flow Layout"))
+
+    import sys
+    app = QApplication(sys.argv)
+    mainWin = Window()
+    mainWin.show()
+    app.exec_()
+
+
+        
+if __name__ == "__main__":
+    test_flowlayout()

test/test_splitter.py

+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from qtwidgets.splitter import Splitter
+
+
+def test_splitter():
+    import sys
+    app = QApplication(sys.argv)
+    win = QDialog()
+    win.resize(640,480)
+    l = QVBoxLayout(win)
+    s = Splitter(win)
+    l.addWidget(s)
+    a = QPushButton(s)
+    a.setText("Button A")
+    b = QPushButton(s)
+    b.setText("Button B")
+    win.show()
+    app.exec_()
+
+
+
+
+if __name__ == "__main__":
+    test_splitter()

test/test_tabwidget.py

+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from qtwidgets.tabwidget import TabWidget
+
+
+def test_tabwidget():
+    import sys
+    app = QApplication(sys.argv)
+    win = TabWidget()
+    win.addTab(QLabel("tab 1", win), "&Foo")
+    win.addTab(QLabel("tab 2", win), "&Bar")
+    win.show()
+    app.exec_()
+
+
+    
+if __name__ == "__main__":
+    test_tabwidget()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.