Exemple #1
0
    def sideSensitiveArea(self, widget, side):
        widgetRect = widget.rect()
        if side == ToolWindowManager.TopOf:
            return QRect(
                QPoint(widgetRect.left(),
                       widgetRect.top() - self.borderSensitivity),
                QSize(widgetRect.width(), self.borderSensitivity * 2))
        elif side == ToolWindowManager.LeftOf:
            return QRect(
                QPoint(widgetRect.left() - self.borderSensitivity,
                       widgetRect.top()),
                QSize(self.borderSensitivity * 2, widgetRect.height()))

        elif side == ToolWindowManager.BottomOf:
            return QRect(
                QPoint(
                    widgetRect.left(),
                    widgetRect.top() + widgetRect.height() -
                    self.borderSensitivity),
                QSize(widgetRect.width(), self.borderSensitivity * 2))
        elif side == ToolWindowManager.RightOf:
            return QRect(
                QPoint(
                    widgetRect.left() + widgetRect.width() -
                    self.borderSensitivity, widgetRect.top()),
                QSize(self.borderSensitivity * 2, widgetRect.height()))
        else:
            qWarning('invalid side')
            return QRect()
Exemple #2
0
    def findSuggestions(self, wrapper):
        self.suggestions = []
        self.dropCurrentSuggestionIndex = -1
        globalPos = QCursor.pos()
        candidates = []
        for splitter in wrapper.findChildren(QSplitter):
            candidates.append(splitter)

        for area in self.areas:
            if area.window() == wrapper.window():
                candidates.append(area)

        for widget in candidates:
            splitter = cast(widget, QSplitter)
            area = cast(widget, ToolWindowManagerArea)
            if not (splitter or area):
                qWarning('unexpected widget type')
                continue

            parentSplitter = cast(widget.parentWidget(), QSplitter)
            lastInSplitter = parentSplitter and \
              parentSplitter.indexOf(widget) == parentSplitter.count() - 1

            allowedSides = []
            if not splitter or splitter.orientation() == Qt.Vertical:
                allowedSides.append(ToolWindowManager.LeftOf)

            if not splitter or splitter.orientation() == Qt.Horizontal:
                allowedSides.append(ToolWindowManager.TopOf)

            if not parentSplitter or parentSplitter.orientation(
            ) == Qt.Vertical or lastInSplitter:
                if not splitter or splitter.orientation() == Qt.Vertical:
                    allowedSides.append(ToolWindowManager.RightOf)

            if not parentSplitter or parentSplitter.orientation(
            ) == Qt.Horizontal or lastInSplitter:
                if not splitter or splitter.orientation() == Qt.Horizontal:
                    allowedSides.append(ToolWindowManager.BottomOf)
            for side in allowedSides:
                rect = self.sideSensitiveArea(widget, side)
                pos = widget.mapFromGlobal(globalPos)
                if rect.contains(pos):
                    self.suggestions.append(AreaReference(side, widget))
            if area:
                rect = area.rect()
                pos = area.mapFromGlobal(globalPos)
                if rect.contains(pos):
                    self.suggestions.append(
                        AreaReference(ToolWindowManager.AddTo, area))

        #end of for
        if not candidates:
            self.suggestions.append(AreaReference(
                ToolWindowManager.EmptySpace))

        if len(self.suggestions) == 0:
            self.handleNoSuggestions()
        else:
            self.showNextDropSuggestion()
Exemple #3
0
    def simplifyLayout(self):
        newAreas = []
        currentAreas = self.areas
        for area in currentAreas:
            if area.parentWidget() is None:
                if area.count() == 0:
                    if area == self.lastUsedArea: self.lastUsedArea = None
                    self.removeArea(area)
                continue

            splitter = cast(area.parentWidget(), QSplitter)
            validSplitter = None  # least top level splitter that should remain
            invalidSplitter = None  #most top level splitter that should be deleted
            while (splitter):
                if splitter.count() > 1:
                    validSplitter = splitter
                    break
                else:
                    invalidSplitter = splitter
                    splitter = cast(splitter.parentWidget(), QSplitter)
            if not validSplitter:
                wrapper = findClosestParent(area, ToolWindowManagerWrapper)
                if not wrapper:
                    qWarning('can not find wrapper')
                    print((findClosestParent(area, ToolWindowManagerWrapper)))
                    print((type(
                        area.parentWidget()) == ToolWindowManagerWrapper))
                    return
                if area.count() == 0 and wrapper.isWindow():
                    wrapper.hide()
                    wrapper.setParent(None)
                    # can not deleteLater immediately (strange MacOS bug)
                    self.removeWrapper(wrapper)

                elif area.parent() != wrapper:
                    wrapper.layout().addWidget(area)

            else:
                if area.count() > 0:
                    if validSplitter and area.parent() != validSplitter:
                        index = validSplitter.indexOf(invalidSplitter)
                        validSplitter.insertWidget(index, area)

            if not invalidSplitter is None:
                invalidSplitter.hide()
                invalidSplitter.setParent(None)
                invalidSplitter.deleteLater()

            if area.count() == 0:
                area.hide()
                area.setParent(None)
                if area == self.lastUsedArea: self.lastUsedArea = None
                self.removeArea(area)
                continue

            newAreas.append(area)
        #keep
        self.areas = newAreas
Exemple #4
0
 def releaseToolWindow(self, toolWindow):
     previousTabWidget = findClosestParent(toolWindow,
                                           ToolWindowManagerArea)
     if not previousTabWidget:
         qWarning('cannot find tab widget for tool window')
         return
     previousTabWidget.removeTab(previousTabWidget.indexOf(toolWindow))
     toolWindow.hide()
     toolWindow.setParent(None)
Exemple #5
0
 def startDrag(self, toolWindows):
     if self.dragInProgress():
         qWarning(
             'ToolWindowManager::execDrag: drag is already in progress')
         return
     if not toolWindows: return
     self.draggedToolWindows = toolWindows
     self.dragIndicator.setPixmap(self.generateDragPixmap(toolWindows))
     self.updateDragPosition()
     self.dragIndicator.show()
Exemple #6
0
 def tabCloseRequested(self, index):
     if not isinstance(self.sender(), ToolWindowManagerArea):
         qWarning('sender is not a ToolWindowManagerArea')
         return
     area = self.sender()
     toolWindow = area.widget(index)
     if not self.hasToolWindow(toolWindow):
         qWarning('unknown tab in tab widget')
         return
     self.hideToolWindow(toolWindow)
Exemple #7
0
 def restoreState(self, data):
     for objectName in data.get('objectNames', []):
         found = False
         for window in self.manager.toolWindows():
             if window.objectName() == objectName:
                 self.addToolWindow(window)
                 found = True
                 break
         if not found:
             qWarning("tool window with name '%s' not found" % objectName)
     self.setCurrentIndex(data.get("currentIndex", 0))
 def restoreState(self, data):
     if 'geometry' in data:
         self.restoreGeometry(data['geometry'])
     if self.layout().count() > 0:
         qWarning('wrapper is not empty')
         return
     if 'splitter' in data:
         self.layout().addWidget(
             self.manager.restoreSplitterState(data['splitter'].toMap()))
     elif 'area' in data:
         area = self.manager.createArea()
         area.restoreState(data['area'])
         self.layout().addWidget(area)
Exemple #9
0
    def showNextDropSuggestion(self):
        if len(self.suggestions) == 0:
            qWarning('showNextDropSuggestion called but no suggestions')
            return

        self.dropCurrentSuggestionIndex += 1
        if self.dropCurrentSuggestionIndex >= len(self.suggestions):
            self.dropCurrentSuggestionIndex = 0

        suggestion = self.suggestions[self.dropCurrentSuggestionIndex]
        if suggestion.type in (ToolWindowManager.AddTo,
                               ToolWindowManager.EmptySpace):
            if suggestion.type == ToolWindowManager.EmptySpace:
                widget = self.findChild(ToolWindowManagerWrapper)
            else:
                widget = suggestion.widget

            if widget.window() == self.window():
                placeHolderParent = self
            else:
                placeHolderParent = widget.window()

            placeHolderGeometry = widget.rect()
            placeHolderGeometry.moveTopLeft(
                widget.mapTo(placeHolderParent, placeHolderGeometry.topLeft()))
            self.rectRubberBand.setGeometry(placeHolderGeometry)
            self.rectRubberBand.setParent(placeHolderParent)
            self.rectRubberBand.show()
            self.lineRubberBand.hide()

        elif suggestion.type in (ToolWindowManager.LeftOf,
                                 ToolWindowManager.RightOf,
                                 ToolWindowManager.TopOf,
                                 ToolWindowManager.BottomOf):
            if suggestion.widget.window() == self.window():
                placeHolderParent = self
            else:
                placeHolderParent = suggestion.widget.window()

            placeHolderGeometry = self.sidePlaceHolderRect(
                suggestion.widget, suggestion.type)
            placeHolderGeometry.moveTopLeft(
                suggestion.widget.mapTo(placeHolderParent,
                                        placeHolderGeometry.topLeft()))
            self.lineRubberBand.setGeometry(placeHolderGeometry)
            self.lineRubberBand.setParent(placeHolderParent)
            self.lineRubberBand.show()
            self.rectRubberBand.hide()

        else:
            qWarning('unsupported suggestion type')
Exemple #10
0
 def saveState(self):
     result = {}
     objectNames = []
     for i in range(self.count()):
         name = self.widget(i).objectName()
         if name:
             objectNames.append(name)
         else:
             qWarning(
                 "cannot save state of tool window without object name")
     result["type"] = "area"
     result["currentIndex"] = self.currentIndex()
     result["objectNames"] = objectNames
     return result
Exemple #11
0
 def check_mouse_move(self, event):
     self.manager.updateDragPosition()
     if event.buttons() == Qt.LeftButton \
     and not self.rect().contains( self.mapFromGlobal( QCursor.pos() ) ) \
     and self.dragCanStart:
         self.dragCanStart = False
         toolWindows = []
         for i in range(self.count()):
             toolWindow = self.widget(i)
             if self.manager.hasToolWindow(toolWindow):
                 toolWindows.append(toolWindow)
             else:
                 qWarning("tab widget contains unmanaged widget")
         self.manager.startDrag(toolWindows)
Exemple #12
0
    def saveState(self):
        result = {}
        result['toolWindowManagerStateFormat'] = 1
        mainWrapper = self.findChild(ToolWindowManagerWrapper)
        if not mainWrapper:
            qWarning('can not find main wrapper')
            return {}

        result['mainWrapper'] = mainWrapper.saveState()
        floatingWindowsData = []
        for wrapper in self.wrappers:
            if not wrapper.isWindow(): continue
            floatingWindowsData.append(wrapper.saveState())
        result['floatingWindows'] = floatingWindowsData
        return result
Exemple #13
0
    def finishDrag(self):
        if not self.dragInProgress():
            qWarning('unexpected finishDrag')
            return

        if len(self.suggestions) == 0:
            self.moveToolWindows(self.draggedToolWindows,
                                 ToolWindowManager.NewFloatingArea)
        else:
            if self.dropCurrentSuggestionIndex >= len(self.suggestions):
                qWarning('invalid self.dropCurrentSuggestionIndex')
                return
            suggestion = self.suggestions[self.dropCurrentSuggestionIndex]
            self.handleNoSuggestions()
            self.moveToolWindows(self.draggedToolWindows, suggestion)

        self.dragIndicator.hide()
        self.draggedToolWindows = []
Exemple #14
0
    def restoreSplitterState(self, data):
        if len(data['items']) < 2:
            qWarning('invalid splitter encountered')

        splitter = self.createSplitter()

        for itemData in data['items']:
            itemType = itemData['type']
            if itemType == 'splitter':
                splitter.addWidget(self.restoreSplitterState(itemData))
            elif itemType == 'area':
                area = self.createArea()
                area.restoreState(itemData)
                splitter.addWidget(area)
            else:
                qWarning('unknown item type')
        splitter.restoreState(data['state'])
        return splitter
Exemple #15
0
    def saveSplitterState(self, splitter):
        result = {}
        result['state'] = splitter.saveState()
        result['type'] = 'splitter'

        items = []
        for i in range(splitter.count()):
            item = splitter.widget(i)
            area = cast(item, ToolWindowManagerArea)
            if area:
                items.append(area.saveState())
            else:
                childSplitter = cast(item, QSplitter)
                if childSplitter:
                    items.append(self.saveSplitterState(childSplitter))
                else:
                    qWarning('unknown splitter item')
        result['items'] = items
        return result
Exemple #16
0
    def restoreState(self, data):
        if not isinstance(data, dict): return
        if data['toolWindowManagerStateFormat'] != 1:
            qWarning('state format is not recognized')
            return
        self.moveToolWindows(self.toolWindowList, ToolWindowManager.NoArea)
        mainWrapper = self.findChild(ToolWindowManagerWrapper)
        if not mainWrapper:
            qWarning('can not find main wrapper')

        mainWrapper.restoreState(data['mainWrapper'])
        for windowData in data['floatingWindows']:
            wrapper = ToolWindowManagerWrapper(self)
            wrapper.restoreState(windowData)
            wrapper.show()

        self.simplifyLayout()
        for toolWindow in self.toolWindowList:
            self.toolWindowVisibilityChanged.emit(
                toolWindow,
                toolWindow.parentWidget() != None)
Exemple #17
0
    def sidePlaceHolderRect(self, widget, side):
        widgetRect = widget.rect()
        parentSplitter = cast(widget.parentWidget(), QSplitter)
        if parentSplitter and parentSplitter.indexOf(widget) > 0:
            delta = parentSplitter.handleWidth(
            ) / 2 + self.rubberBandLineWidth / 2
            if side == ToolWindowManager.TopOf and parentSplitter.orientation(
            ) == Qt.Vertical:
                return QRect(
                    QPoint(widgetRect.left(),
                           widgetRect.top() - delta),
                    QSize(widgetRect.width(), self.rubberBandLineWidth))
            elif side == ToolWindowManager.LeftOf and parentSplitter.orientation(
            ) == Qt.Horizontal:
                return QRect(
                    QPoint(widgetRect.left() - delta, widgetRect.top()),
                    QSize(self.rubberBandLineWidth, widgetRect.height()))

        if side == ToolWindowManager.TopOf:
            return QRect(QPoint(widgetRect.left(), widgetRect.top()),
                         QSize(widgetRect.width(), self.rubberBandLineWidth))
        elif side == ToolWindowManager.LeftOf:
            return QRect(QPoint(widgetRect.left(), widgetRect.top()),
                         QSize(self.rubberBandLineWidth, widgetRect.height()))
        elif side == ToolWindowManager.BottomOf:
            return QRect(
                QPoint(
                    widgetRect.left(),
                    widgetRect.top() + widgetRect.height() -
                    self.rubberBandLineWidth),
                QSize(widgetRect.width(), self.rubberBandLineWidth))
        elif side == ToolWindowManager.RightOf:
            return QRect(
                QPoint(
                    widgetRect.left() + widgetRect.width() -
                    self.rubberBandLineWidth, widgetRect.top()),
                QSize(self.rubberBandLineWidth, widgetRect.height()))
        else:
            qWarning('invalid side')
            return QRect()
Exemple #18
0
    def setWidget(self, widget):
        if self.type in [
                ToolWindowManager.LastUsedArea,
                ToolWindowManager.NewFloatingArea, ToolWindowManager.NoArea,
                ToolWindowManager.EmptySpace
        ]:
            if widget:
                qWarning('area parameter ignored for this type')
            self.widget = None

        elif self.type == ToolWindowManager.AddTo:
            if isinstance(widget, ToolWindowManagerArea):
                self.widget = widget
            else:
                qWarning(
                    'only ToolWindowManagerArea can be used with this type')

        else:
            if isinstance(widget, ToolWindowManagerArea) or isinstance(
                    widget, QSplitter):
                self.widget = widget
            else:
                qWarning(
                    'only ToolWindowManagerArea or splitter can be used with this type'
                )
                self.widget = None
    def saveState(self):
        result = {}
        if self.layout().count() > 1:
            qWarning('too many children for wrapper')
            return result

        if self.isWindow() and self.layout().count() == 0:
            qWarning('empty top level wrapper')
            return result

        result['geometry'] = str(self.saveGeometry())
        splitter = self.findChild(QtWidgets.QSplitter)
        if splitter:
            result['splitter'] = self.manager.saveSplitterState(splitter)
        else:
            area = self.findChild(ToolWindowManagerArea)
            if area:
                result['area'] = area.saveState()
            elif self.layout().count() > 0:
                qWarning('unknown child')
                return {}
        return result
Exemple #20
0
    def moveToolWindows(self, toolWindows, area):
        if type(area) == int:
            area = AreaReference(area)

        for toolWindow in toolWindows:
            if not self.hasToolWindow(toolWindow): return
            if toolWindow.parentWidget():
                self.releaseToolWindow(toolWindow)

        areaType = area.type

        if areaType == ToolWindowManager.LastUsedArea and not self.lastUsedArea:
            foundArea = self.findChild(ToolWindowManagerArea)
            if foundArea:
                area = AreaReference(ToolWindowManager.AddTo, foundArea)
            else:
                area = ToolWindowManager.EmptySpace

        if areaType == ToolWindowManager.NoArea:
            #do nothing
            pass

        elif areaType == ToolWindowManager.NewFloatingArea:
            area = self.createArea()
            area.addToolWindows(toolWindows)
            wrapper = ToolWindowManagerWrapper(self)
            wrapper.layout().addWidget(area)
            wrapper.move(QCursor.pos())
            wrapper.show()

        elif areaType == ToolWindowManager.AddTo:
            area.area().addToolWindows(toolWindows)

        elif areaType in (ToolWindowManager.LeftOf, ToolWindowManager.RightOf,
                          ToolWindowManager.TopOf, ToolWindowManager.BottomOf):
            parentSplitter = cast(area.widget.parentWidget(), QSplitter)
            wrapper = cast(area.widget.parentWidget(),
                           ToolWindowManagerWrapper)
            if not (parentSplitter or wrapper):
                qWarning('unknown parent type')
                return
            # import pudb; pu.db
            useParentSplitter = False
            indexInParentSplitter = 0
            if parentSplitter:
                indexInParentSplitter = parentSplitter.indexOf(area.widget)
                if parentSplitter.orientation() == Qt.Vertical:
                    useParentSplitter = areaType in (
                        ToolWindowManager.TopOf, ToolWindowManager.BottomOf)
                else:
                    useParentSplitter = areaType in (ToolWindowManager.LeftOf,
                                                     ToolWindowManager.RightOf)

            if useParentSplitter:
                if areaType in (ToolWindowManager.BottomOf,
                                ToolWindowManager.RightOf):
                    indexInParentSplitter += 1
                newArea = self.createArea()
                newArea.addToolWindows(toolWindows)
                parentSplitter.insertWidget(indexInParentSplitter, newArea)

            else:
                area.widget.hide()
                area.widget.setParent(None)
                splitter = self.createSplitter()
                if areaType in (ToolWindowManager.TopOf,
                                ToolWindowManager.BottomOf):
                    splitter.setOrientation(Qt.Vertical)
                else:
                    splitter.setOrientation(Qt.Horizontal)

                splitter.addWidget(area.widget)
                area.widget.show()
                newArea = self.createArea()
                if areaType in (ToolWindowManager.TopOf,
                                ToolWindowManager.LeftOf):
                    splitter.insertWidget(0, newArea)
                else:
                    splitter.addWidget(newArea)

                if parentSplitter:
                    parentSplitter.insertWidget(indexInParentSplitter,
                                                splitter)
                else:
                    wrapper.layout().addWidget(splitter)
                newArea.addToolWindows(toolWindows)

        elif areaType == ToolWindowManager.EmptySpace:
            wrapper = self.findChild(ToolWindowManagerWrapper)
            if wrapper.isOccupied():
                self.lastUsedArea.addToolWindows(toolWindows)
            else:
                newArea = self.createArea()
                wrapper.layout().addWidget(newArea)
                newArea.addToolWindows(toolWindows)

        elif areaType == ToolWindowManager.LastUsedArea:
            self.lastUsedArea.addToolWindows(toolWindows)

        else:
            qWarning('invalid type')

        self.simplifyLayout()
        for toolWindow in toolWindows:
            self.toolWindowVisibilityChanged.emit(toolWindow,
                                                  toolWindow.parent() != None)
Exemple #21
0
 def removeToolWindow(self, toolWindow):
     if not self.toolWindowList.contains(toolWindow):
         qWarning('unknown tool window')
         return
     self.moveToolWindow(toolWindow, ToolWindowManager.NoArea)
     self.toolWindowList.removeOne(toolWindow)