|
Packit |
8e9c33 |
/*************************************************************************
|
|
Packit |
8e9c33 |
* Copyright (C) 2014 by Hugo Pereira Da Costa <hugo.pereira@free.fr> *
|
|
Packit |
8e9c33 |
* *
|
|
Packit |
8e9c33 |
* This program is free software; you can redistribute it and/or modify *
|
|
Packit |
8e9c33 |
* it under the terms of the GNU General Public License as published by *
|
|
Packit |
8e9c33 |
* the Free Software Foundation; either version 2 of the License, or *
|
|
Packit |
8e9c33 |
* (at your option) any later version. *
|
|
Packit |
8e9c33 |
* *
|
|
Packit |
8e9c33 |
* This program is distributed in the hope that it will be useful, *
|
|
Packit |
8e9c33 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
Packit |
8e9c33 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
Packit |
8e9c33 |
* GNU General Public License for more details. *
|
|
Packit |
8e9c33 |
* *
|
|
Packit |
8e9c33 |
* You should have received a copy of the GNU General Public License *
|
|
Packit |
8e9c33 |
* along with this program; if not, write to the *
|
|
Packit |
8e9c33 |
* Free Software Foundation, Inc., *
|
|
Packit |
8e9c33 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
|
|
Packit |
8e9c33 |
*************************************************************************/
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
#include "adwaitasplitterproxy.h"
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
#include "adwaita.h"
|
|
Packit |
8e9c33 |
#include "fakeadwaitastyleconfigdata.h"
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
#include <QCoreApplication>
|
|
Packit |
8e9c33 |
#include <QDebug>
|
|
Packit |
8e9c33 |
#include <QPainter>
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
namespace Adwaita
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
void SplitterFactory::setEnabled( bool value )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
if( _enabled != value )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
// store
|
|
Packit |
8e9c33 |
_enabled = value;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// assign to existing splitters
|
|
Packit |
8e9c33 |
for( WidgetMap::iterator iter = _widgets.begin(); iter != _widgets.end(); ++iter )
|
|
Packit |
8e9c33 |
{ if( iter.value() ) iter.value().data()->setEnabled( value ); }
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
bool SplitterFactory::registerWidget( QWidget *widget )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// check widget type
|
|
Packit |
8e9c33 |
if( qobject_cast<QMainWindow*>( widget ) )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
WidgetMap::iterator iter( _widgets.find( widget ) );
|
|
Packit |
8e9c33 |
if( iter == _widgets.end() || !iter.value() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
widget->installEventFilter( &_addEventFilter );
|
|
Packit |
8e9c33 |
SplitterProxy* proxy( new SplitterProxy( widget, _enabled ) );
|
|
Packit |
8e9c33 |
widget->removeEventFilter( &_addEventFilter );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
widget->installEventFilter( proxy );
|
|
Packit |
8e9c33 |
_widgets.insert( widget, proxy );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else {
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
widget->removeEventFilter( iter.value().data() );
|
|
Packit |
8e9c33 |
widget->installEventFilter( iter.value().data() );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
return true;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else if( qobject_cast<QSplitterHandle*>( widget ) ) {
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
QWidget* window( widget->window() );
|
|
Packit |
8e9c33 |
WidgetMap::iterator iter( _widgets.find( window ) );
|
|
Packit |
8e9c33 |
if( iter == _widgets.end() || !iter.value() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
window->installEventFilter( &_addEventFilter );
|
|
Packit |
8e9c33 |
SplitterProxy* proxy( new SplitterProxy( window, _enabled ) );
|
|
Packit |
8e9c33 |
window->removeEventFilter( &_addEventFilter );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
widget->installEventFilter( proxy );
|
|
Packit |
8e9c33 |
_widgets.insert( window, proxy );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else {
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
widget->removeEventFilter( iter.value().data() );
|
|
Packit |
8e9c33 |
widget->installEventFilter( iter.value().data() );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
return true;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
void SplitterFactory::unregisterWidget( QWidget *widget )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
WidgetMap::iterator iter( _widgets.find( widget ) );
|
|
Packit |
8e9c33 |
if( iter != _widgets.end() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
if( iter.value() ) iter.value().data()->deleteLater();
|
|
Packit |
8e9c33 |
_widgets.erase( iter );
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
SplitterProxy::SplitterProxy( QWidget* parent, bool enabled ):
|
|
Packit |
8e9c33 |
QWidget( parent ),
|
|
Packit |
8e9c33 |
_enabled( enabled ),
|
|
Packit |
8e9c33 |
_timerId( 0 )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
setAttribute( Qt::WA_TranslucentBackground, true );
|
|
Packit |
8e9c33 |
setAttribute( Qt::WA_OpaquePaintEvent, false );
|
|
Packit |
8e9c33 |
hide();
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
SplitterProxy::~SplitterProxy( void )
|
|
Packit |
8e9c33 |
{}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
void SplitterProxy::setEnabled( bool value )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
// make sure status has changed
|
|
Packit |
8e9c33 |
if( _enabled != value )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
_enabled = value;
|
|
Packit |
8e9c33 |
if( _enabled ) clearSplitter();
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
bool SplitterProxy::eventFilter( QObject* object, QEvent* event )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// do nothing if disabled
|
|
Packit |
8e9c33 |
if( !_enabled ) return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// do nothing in case of mouse grab
|
|
Packit |
8e9c33 |
if( mouseGrabber() ) return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
switch( event->type() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
case QEvent::HoverEnter:
|
|
Packit |
8e9c33 |
if( !isVisible() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// cast to splitter handle
|
|
Packit |
8e9c33 |
if( QSplitterHandle* handle = qobject_cast<QSplitterHandle*>( object ) )
|
|
Packit |
8e9c33 |
{ setSplitter( handle ); }
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
case QEvent::HoverMove:
|
|
Packit |
8e9c33 |
case QEvent::HoverLeave:
|
|
Packit |
8e9c33 |
return isVisible() && object == _splitter.data();
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
case QEvent::MouseMove:
|
|
Packit |
8e9c33 |
case QEvent::Timer:
|
|
Packit |
8e9c33 |
case QEvent::Move:
|
|
Packit |
8e9c33 |
return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
case QEvent::CursorChange:
|
|
Packit |
8e9c33 |
if( QWidget *window = qobject_cast<QMainWindow*>( object ) )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
if( window->cursor().shape() == Qt::SplitHCursor || window->cursor().shape() == Qt::SplitVCursor )
|
|
Packit |
8e9c33 |
{ setSplitter( window ); }
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
case QEvent::WindowDeactivate:
|
|
Packit |
8e9c33 |
case QEvent::MouseButtonRelease:
|
|
Packit |
8e9c33 |
clearSplitter();
|
|
Packit |
8e9c33 |
return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
default:
|
|
Packit |
8e9c33 |
return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
bool SplitterProxy::event( QEvent *event )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
switch( event->type() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
#if 0
|
|
Packit |
8e9c33 |
case QEvent::Paint:
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
QPainter painter( this );
|
|
Packit |
8e9c33 |
painter.setClipRegion( static_cast<QPaintEvent*>( event )->region() );
|
|
Packit |
8e9c33 |
painter.setRenderHints( QPainter::Antialiasing );
|
|
Packit |
8e9c33 |
painter.setPen( Qt::red );
|
|
Packit |
8e9c33 |
painter.drawRect( QRectF( rect() ).adjusted( 0.5, 0.5, -0.5, -0.5 ) );
|
|
Packit |
8e9c33 |
return true;
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
#endif
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
case QEvent::MouseMove:
|
|
Packit |
8e9c33 |
case QEvent::MouseButtonPress:
|
|
Packit |
8e9c33 |
case QEvent::MouseButtonRelease:
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// check splitter
|
|
Packit |
8e9c33 |
if( !_splitter ) return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
event->accept();
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// grab on mouse press
|
|
Packit |
8e9c33 |
if( event->type() == QEvent::MouseButtonPress)
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
grabMouse();
|
|
Packit |
8e9c33 |
resize(1,1);
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// cast to mouse event
|
|
Packit |
8e9c33 |
QMouseEvent *mouseEvent( static_cast<QMouseEvent*>( event ) );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// get relevant position to post mouse drag event to application
|
|
Packit |
8e9c33 |
if( event->type() == QEvent::MouseButtonPress )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// use hook, to make sure splitter is properly dragged
|
|
Packit |
8e9c33 |
QMouseEvent copy(
|
|
Packit |
8e9c33 |
mouseEvent->type(),
|
|
Packit |
8e9c33 |
_hook,
|
|
Packit |
8e9c33 |
_splitter.data()->mapToGlobal(_hook),
|
|
Packit |
8e9c33 |
mouseEvent->button(),
|
|
Packit |
8e9c33 |
mouseEvent->buttons(), mouseEvent->modifiers());
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
QCoreApplication::sendEvent( _splitter.data(), © );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else {
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// map event position to current splitter and post.
|
|
Packit |
8e9c33 |
QMouseEvent copy(
|
|
Packit |
8e9c33 |
mouseEvent->type(),
|
|
Packit |
8e9c33 |
_splitter.data()->mapFromGlobal( mouseEvent->globalPos() ),
|
|
Packit |
8e9c33 |
mouseEvent->globalPos(),
|
|
Packit |
8e9c33 |
mouseEvent->button(),
|
|
Packit |
8e9c33 |
mouseEvent->buttons(), mouseEvent->modifiers());
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
QCoreApplication::sendEvent( _splitter.data(), © );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// release grab on mouse-Release
|
|
Packit |
8e9c33 |
if( event->type() == QEvent::MouseButtonRelease && mouseGrabber() == this )
|
|
Packit |
8e9c33 |
{ releaseMouse(); }
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
return true;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
case QEvent::Timer:
|
|
Packit |
8e9c33 |
if( static_cast<QTimerEvent*>( event )->timerId() != _timerId )
|
|
Packit |
8e9c33 |
{ return QWidget::event( event ); }
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
/*
|
|
Packit |
8e9c33 |
Fall through is intended.
|
|
Packit |
8e9c33 |
We somehow lost a QEvent::Leave before timeout. We fix it from here
|
|
Packit |
8e9c33 |
*/
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
case QEvent::HoverLeave:
|
|
Packit |
8e9c33 |
case QEvent::Leave:
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( mouseGrabber() == this )
|
|
Packit |
8e9c33 |
{ return true; }
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// reset splitter
|
|
Packit |
8e9c33 |
if( isVisible() && !rect().contains( mapFromGlobal( QCursor::pos() ) ) )
|
|
Packit |
8e9c33 |
{ clearSplitter(); }
|
|
Packit |
8e9c33 |
return true;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
default:
|
|
Packit |
8e9c33 |
return QWidget::event( event );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
void SplitterProxy::setSplitter( QWidget* widget )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// check if changed
|
|
Packit |
8e9c33 |
if( _splitter.data() == widget ) return;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// get cursor position
|
|
Packit |
8e9c33 |
QPoint position( QCursor::pos() );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// store splitter and hook
|
|
Packit |
8e9c33 |
_splitter = widget;
|
|
Packit |
8e9c33 |
_hook = _splitter.data()->mapFromGlobal( position );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// adjust rect
|
|
Packit |
8e9c33 |
QRect rect( 0, 0, 2*StyleConfigData::splitterProxyWidth(), 2*StyleConfigData::splitterProxyWidth() );
|
|
Packit |
8e9c33 |
rect.moveCenter( parentWidget()->mapFromGlobal( position ) );
|
|
Packit |
8e9c33 |
setGeometry( rect );
|
|
Packit |
8e9c33 |
setCursor( _splitter.data()->cursor().shape() );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// show
|
|
Packit |
8e9c33 |
raise();
|
|
Packit |
8e9c33 |
show();
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// timer used to automatically hide proxy in case leave events are lost
|
|
Packit |
8e9c33 |
if( !_timerId ) _timerId = startTimer(150);
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//____________________________________________________________________
|
|
Packit |
8e9c33 |
void SplitterProxy::clearSplitter( void )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// check if changed
|
|
Packit |
8e9c33 |
if( !_splitter ) return;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// release mouse
|
|
Packit |
8e9c33 |
if( mouseGrabber() == this ) releaseMouse();
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// hide
|
|
Packit |
8e9c33 |
parentWidget()->setUpdatesEnabled(false);
|
|
Packit |
8e9c33 |
hide();
|
|
Packit |
8e9c33 |
parentWidget()->setUpdatesEnabled(true);
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// send hover event
|
|
Packit |
8e9c33 |
if( _splitter )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
QHoverEvent hoverEvent(
|
|
Packit |
8e9c33 |
qobject_cast<QSplitterHandle*>(_splitter.data()) ? QEvent::HoverLeave : QEvent::HoverMove,
|
|
Packit |
8e9c33 |
_splitter.data()->mapFromGlobal(QCursor::pos()), _hook);
|
|
Packit |
8e9c33 |
QCoreApplication::sendEvent( _splitter.data(), &hoverEvent );
|
|
Packit |
8e9c33 |
_splitter.clear();
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// kill timer if any
|
|
Packit |
8e9c33 |
if( _timerId )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
killTimer( _timerId );
|
|
Packit |
8e9c33 |
_timerId = 0;
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|