diff --git a/kstyle/breezemdiwindowshadow.cpp b/kstyle/breezemdiwindowshadow.cpp index 84c1514a..b1d5a81e 100644 --- a/kstyle/breezemdiwindowshadow.cpp +++ b/kstyle/breezemdiwindowshadow.cpp @@ -1,248 +1,249 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * 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 2 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezemdiwindowshadow.h" #include "breeze.h" #include "breezestyleconfigdata.h" #include #include #include #include namespace Breeze { //____________________________________________________________________ MdiWindowShadow::MdiWindowShadow( QWidget* parent, TileSet shadowTiles ): QWidget( parent ), - _widget( nullptr ), _shadowTiles( shadowTiles ) { setAttribute( Qt::WA_OpaquePaintEvent, false ); setAttribute( Qt::WA_TransparentForMouseEvents, true ); setFocusPolicy( Qt::NoFocus ); } //____________________________________________________________________ void MdiWindowShadow::updateGeometry( void ) { if( !_widget ) return; // metrics const int shadowSize = StyleConfigData::shadowSize()*12/16; const int shadowOffset = qMax( shadowSize/2, Metrics::Shadow_Overlap*2 ); const int size( shadowSize - Metrics::Shadow_Overlap ); const int topSize( size - shadowOffset ); const int bottomSize( size ); const int leftSize( size - shadowOffset ); const int rightSize( size ); // get tileSet rect auto hole = _widget->frameGeometry(); _shadowTilesRect = hole.adjusted( -leftSize, -topSize, rightSize, bottomSize ); // get parent MDI area's viewport auto parent( parentWidget() ); if (parent && !qobject_cast(parent) && qobject_cast(parent->parentWidget())) { parent = parent->parentWidget(); } if( qobject_cast( parent ) ) { parent = qobject_cast( parent )->viewport(); } // set geometry QRect geometry( _shadowTilesRect ); if( parent ) { geometry &= parent->rect(); hole &= parent->rect(); } // update geometry and mask const QRegion mask = QRegion( geometry ) - hole; if( mask.isEmpty() ) hide(); else { setGeometry( geometry ); setMask( mask.translated( -geometry.topLeft() ) ); show(); } // translate rendering rect _shadowTilesRect.translate( -geometry.topLeft() ); } //____________________________________________________________________ void MdiWindowShadow::updateZOrder( void ) { stackUnder( _widget ); } //____________________________________________________________________ void MdiWindowShadow::paintEvent( QPaintEvent* event ) { if( !_shadowTiles.isValid() ) return; QPainter painter( this ); painter.setRenderHints( QPainter::Antialiasing ); painter.setClipRegion( event->region() ); _shadowTiles.render( _shadowTilesRect, &painter ); } //____________________________________________________________________ MdiWindowShadowFactory::MdiWindowShadowFactory( QObject* parent ): QObject( parent ) {} //____________________________________________________________________________________ bool MdiWindowShadowFactory::registerWidget( QWidget* widget ) { // check widget type auto subwindow( qobject_cast( widget ) ); if( !subwindow ) return false; if( subwindow->widget() && subwindow->widget()->inherits( "KMainWindow" ) ) return false; // make sure widget is not already registered if( isRegistered( widget ) ) return false; // store in set _registeredWidgets.insert( widget ); + // create shadow immediatly if widget is already visible if( widget->isVisible() ) { installShadow( widget ); updateShadowGeometry( widget ); updateShadowZOrder( widget ); } + widget->installEventFilter( this ); // catch object destruction connect( widget, SIGNAL(destroyed(QObject*)), SLOT(widgetDestroyed(QObject*)) ); return true; } //____________________________________________________________________________________ void MdiWindowShadowFactory::unregisterWidget( QWidget* widget ) { if( !isRegistered( widget ) ) return; widget->removeEventFilter( this ); _registeredWidgets.remove( widget ); removeShadow( widget ); } //____________________________________________________________________________________ bool MdiWindowShadowFactory::eventFilter( QObject* object, QEvent* event ) { switch( event->type() ) { // TODO: possibly implement ZOrderChange event, to make sure that // the shadow is always painted on top case QEvent::ZOrderChange: updateShadowZOrder( object ); break; case QEvent::Destroy: if( isRegistered( object ) ) { _registeredWidgets.remove( object ); removeShadow( object ); } break; case QEvent::Hide: hideShadows( object ); break; case QEvent::Show: installShadow( object ); updateShadowGeometry( object ); updateShadowZOrder( object ); break; case QEvent::Move: case QEvent::Resize: updateShadowGeometry( object ); break; default: break; } return QObject::eventFilter( object, event ); } //____________________________________________________________________________________ MdiWindowShadow* MdiWindowShadowFactory::findShadow( QObject* object ) const { // check object, if( !object->parent() ) return nullptr; // find existing window shadows auto children = object->parent()->children(); foreach( QObject *child, children ) { if( MdiWindowShadow* shadow = qobject_cast(child) ) { if( shadow->widget() == object ) return shadow; } } return nullptr; } //____________________________________________________________________________________ void MdiWindowShadowFactory::installShadow( QObject* object ) { // cast auto widget( static_cast( object ) ); if( !widget->parentWidget() ) return; // make sure shadow is not already installed if( findShadow( object ) ) return; // create new shadow auto windowShadow( new MdiWindowShadow( widget->parentWidget(), _shadowTiles ) ); windowShadow->setWidget( widget ); return; } //____________________________________________________________________________________ void MdiWindowShadowFactory::removeShadow( QObject* object ) { if( MdiWindowShadow* windowShadow = findShadow( object ) ) { windowShadow->hide(); windowShadow->deleteLater(); } } //____________________________________________________________________________________ void MdiWindowShadowFactory::widgetDestroyed( QObject* object ) { _registeredWidgets.remove( object ); } } diff --git a/kstyle/breezemdiwindowshadow.h b/kstyle/breezemdiwindowshadow.h index 008d3559..51119a47 100644 --- a/kstyle/breezemdiwindowshadow.h +++ b/kstyle/breezemdiwindowshadow.h @@ -1,170 +1,170 @@ #ifndef breezemdiwindowshadow_h #define breezemdiwindowshadow_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * 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 2 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include #include #include #include #include #include "breezetileset.h" namespace Breeze { //* frame shadow /** this allows the shadow to be painted over the widgets viewport */ class MdiWindowShadow: public QWidget { Q_OBJECT public: //* constructor explicit MdiWindowShadow( QWidget*, TileSet ); //* update geometry void updateGeometry( void ); //* update ZOrder void updateZOrder( void ); //* set associated window void setWidget( QWidget* value ) { _widget = value; } //* associated window QWidget* widget( void ) const { return _widget; } protected: //* painting virtual void paintEvent(QPaintEvent *); private: //* associated widget - QWidget* _widget; + QWidget* _widget = nullptr; //* tileset rect, used for painting QRect _shadowTilesRect; //* tileset used to draw shadow TileSet _shadowTiles; }; //* shadow manager class MdiWindowShadowFactory: public QObject { Q_OBJECT public: //* constructor explicit MdiWindowShadowFactory( QObject* ); //* destructor virtual ~MdiWindowShadowFactory( void ) {} //* set shadow tiles void setShadowTiles( const TileSet& shadowTiles ) { _shadowTiles = shadowTiles; } //* register widget bool registerWidget( QWidget* ); //* unregister void unregisterWidget( QWidget* ); //* true if widget is registered bool isRegistered( const QObject* widget ) const { return _registeredWidgets.contains( widget ); } //* event filter virtual bool eventFilter( QObject*, QEvent*); protected: //* find shadow matching a given object MdiWindowShadow* findShadow( QObject* ) const; //* install shadows on given widget void installShadow( QObject* ); //* remove shadows from widget void removeShadow( QObject* ); //* hide shadows void hideShadows( QObject* object ) const { if( MdiWindowShadow* windowShadow = findShadow( object ) ) { windowShadow->hide(); } } //* update ZOrder void updateShadowZOrder( QObject* object ) const { if( MdiWindowShadow* windowShadow = findShadow( object ) ) { if( !windowShadow->isVisible() ) windowShadow->show(); windowShadow->updateZOrder(); } } //* update shadows geometry void updateShadowGeometry( QObject* object ) const { if( MdiWindowShadow* windowShadow = findShadow( object ) ) { windowShadow->updateGeometry(); } } //* update shadows void update( QObject* object ) const { if( MdiWindowShadow* windowShadow = findShadow( object ) ) { windowShadow->update(); } } protected Q_SLOTS: //* triggered by object destruction void widgetDestroyed( QObject* ); private: //* set of registered widgets QSet _registeredWidgets; //* tileset used to draw shadow TileSet _shadowTiles; }; } #endif