""" Plugin for Krita UI Redesign, Copyright (C) 2020 Kapyia, Pedro Reis This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ from krita import * from PyQt5.QtWidgets import QWidget, QToolButton import sys class subWindowFilter(QObject): """Event Filter object""" def __init__(self, parent=None): super().__init__(parent) qWin = Application.activeWindow().qwindow() self.mdiArea = qWin.centralWidget().findChild(QMdiArea) self.target = None def eventFilter(self, obj, e): """Event filter: Update the Toolbox's position to match to the current view if the (sub-)window has moved, changed in size or been activated.""" if (e.type() == QEvent.Move or e.type() == QEvent.Resize or e.type() == QEvent.WindowActivate): self.moveToolBox() return False def moveToolBox(self): """Move the toolbox to the position of the current View""" subWin = self.mdiArea.activeSubWindow() if subWin and self.target: for c in subWin.children(): if 'view' in c.objectName(): # Grab the View from the tab/sub-window view = c ### NOTE: Determining the correct corner position might be better done based ### on whether Krita is set to handle multiple documents as 'Subwindows' or 'Tabs' # pos = self.mdiArea.pos() # Move to top of QMdiArea. Only suitable for 'Subwindows' mode. pos = self.mdiArea.mapFromGlobal(view.mapToGlobal(QPoint(0,0))) # Move to top left corner of current view self.target.move(pos) if view.height() < self.target.sizeHint().height(): self.target.resize(self.target.sizeHint().width(), view.height()) else: self.target.resize(self.target.sizeHint()) def setTargetWidget(self, wdgt): self.target = wdgt class floatingToolbarWidget(QWidget): def __init__(self, parent=None): super(floatingToolbarWidget, self).__init__(parent) self.setWindowFlags( Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint ) self.setLayout(QVBoxLayout()) self.layout().setContentsMargins(4,4,4,4) self.btnHide = QToolButton() self.btnHide.setIcon(Application.icon("light_visible")) self.btnHide.setIconSize(QSize(14,14)) self.btnHide.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) self.btnHide.clicked.connect(self.toggleWidgetVisible) self.layout().addWidget(self.btnHide) self.widget = None self.widgetDocker = None def closeEvent(self, e): self.returnDocker() return super().closeEvent(e) def borrowDocker(self, name): """Borrow a docker widget from Krita's existing list of dockers""" docker = Application.activeWindow().qwindow().findChild(QDockWidget, name) # Does requested widget exist? if docker and docker.widget(): # Return any previous widget self.returnDocker() self.widgetDocker = docker self.widget = docker.widget() self.layout().addWidget(self.widget) self.resize(self.sizeHint()) return True return False def returnDocker(self): """Return the borrowed docker to it's original QDockerWidget""" # Ensure there's a widget to return if self.widget: self.widgetDocker.setWidget(self.widget) self.widget = None self.widgetDocker = None def toggleWidgetVisible(self): self.widget.setVisible(not self.widget.isVisible()) self.resize(self.sizeHint()) # Get all the Krita widgets we need qWin = Application.activeWindow().qwindow() tlbx = qWin.findChild(QDockWidget, 'ToolBox') mdiArea = qWin.findChild(QMdiArea) def createWidget(name, parent=None): wdgt = floatingToolbarWidget(parent) wdgt.setObjectName(name) return wdgt def slotMdiFilterManager(subWin): '''Ensure that the current SubWindow has the filter installed, and immediately move the Toolbox to current View.''' if subWin: subWin.installEventFilter(filterObj) filterObj.moveToolBox() # Create the new floating widget floater = createWidget('floatingToolbox', mdiArea) floater.setStyleSheet(""" QWidget { background-color: rgba(128, 128, 128, .01); } .QScrollArea { background-color: #00000000; } QScrollArea * { background-color: #00000000; } QScrollArea QToolTip { background-color: #ffffff; } QAbstractButton { background-color: #77000000; border: none; border-radius: 4px; } QAbstractButton:checked { background-color: #aa306fa8; } QAbstractButton:hover { background-color: #1c1c1c; } QAbstractButton:pressed { background-color: #53728e; } """) floater.borrowDocker('ToolBox') # Create and install event filter to sub window(s) and main window filterObj = subWindowFilter() # Create filter object filterObj.setTargetWidget(floater) mdiArea.subWindowActivated.connect(slotMdiFilterManager) qWin.installEventFilter(filterObj) floater.show()