138 lines
3.5 KiB
C++
138 lines
3.5 KiB
C++
|
/******************************************************************************
|
||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include "QskFocusIndicator.h"
|
||
|
#include "QskRectNode.h"
|
||
|
#include "QskAspect.h"
|
||
|
#include "QskEvent.h"
|
||
|
|
||
|
#include <QQuickWindow>
|
||
|
|
||
|
QSK_SUBCONTROL( QskFocusIndicator, Panel )
|
||
|
|
||
|
static void qskSetupGeometryConnections(
|
||
|
const QQuickItem* sender, QQuickItem* receiver, const char* method )
|
||
|
{
|
||
|
QObject::connect( sender, SIGNAL( xChanged() ), receiver, method );
|
||
|
QObject::connect( sender, SIGNAL( yChanged() ), receiver, method );
|
||
|
QObject::connect( sender, SIGNAL( widthChanged() ), receiver, method );
|
||
|
QObject::connect( sender, SIGNAL( heightChanged() ), receiver, method );
|
||
|
}
|
||
|
|
||
|
QskFocusIndicator::QskFocusIndicator( QQuickItem* parent ):
|
||
|
Inherited( parent )
|
||
|
{
|
||
|
setTransparentForPositioner( true );
|
||
|
resetConnections();
|
||
|
|
||
|
connectWindow( window(), true );
|
||
|
}
|
||
|
|
||
|
QskFocusIndicator::~QskFocusIndicator()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void QskFocusIndicator::onFocusItemGeometryChanged()
|
||
|
{
|
||
|
updateFocusFrame();
|
||
|
}
|
||
|
|
||
|
void QskFocusIndicator::onFocusItemChanged()
|
||
|
{
|
||
|
disconnect( this, SLOT( onFocusItemGeometryChanged() ) );
|
||
|
|
||
|
const QQuickItem* focusItem = window() ? window()->activeFocusItem() : nullptr;
|
||
|
|
||
|
if ( focusItem )
|
||
|
{
|
||
|
qskSetupGeometryConnections( focusItem,
|
||
|
this, SLOT(onFocusItemGeometryChanged()) );
|
||
|
|
||
|
// we might have to raise on top, but the code below
|
||
|
// might not be good enough to cover all corner cases ??
|
||
|
|
||
|
const QQuickItem* item = focusItem;
|
||
|
while ( item->parentItem() )
|
||
|
{
|
||
|
if ( item->parentItem() == parentItem() )
|
||
|
{
|
||
|
setZ( item->z() + 10e-6 );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
item = item->parentItem();
|
||
|
|
||
|
qskSetupGeometryConnections( item,
|
||
|
this, SLOT(onFocusItemGeometryChanged()) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
updateFocusFrame();
|
||
|
}
|
||
|
|
||
|
void QskFocusIndicator::updateFocusFrame()
|
||
|
{
|
||
|
QRectF r = focusRect();
|
||
|
setVisible( !r.isEmpty() );
|
||
|
|
||
|
if ( !r.isEmpty() )
|
||
|
{
|
||
|
r = r.marginsAdded( edgeMetrics( Panel, QskAspect::Padding ) );
|
||
|
setGeometry( r );
|
||
|
}
|
||
|
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
QRectF QskFocusIndicator::focusRect() const
|
||
|
{
|
||
|
if ( window() && parentItem() )
|
||
|
{
|
||
|
const QQuickItem* focusItem = window()->activeFocusItem();
|
||
|
if ( focusItem )
|
||
|
return parentItem()->mapRectFromItem( focusItem, focusItem->boundingRect() );
|
||
|
}
|
||
|
|
||
|
return QRectF();
|
||
|
}
|
||
|
|
||
|
void QskFocusIndicator::resetConnections()
|
||
|
{
|
||
|
disconnect( this, SLOT( updateFocusFrame() ) );
|
||
|
|
||
|
QQuickItem* item = parentItem();
|
||
|
if ( item )
|
||
|
{
|
||
|
qskSetupGeometryConnections( item, this, SLOT(updateFocusFrame()) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QskFocusIndicator::windowChangeEvent( QskWindowChangeEvent* event )
|
||
|
{
|
||
|
Inherited::windowChangeEvent( event );
|
||
|
|
||
|
connectWindow( event->oldWindow(), false );
|
||
|
connectWindow( event->window(), true );
|
||
|
}
|
||
|
|
||
|
void QskFocusIndicator::connectWindow( const QQuickWindow* window, bool on )
|
||
|
{
|
||
|
if ( window == nullptr )
|
||
|
return;
|
||
|
|
||
|
if ( on )
|
||
|
{
|
||
|
connect( window, &QQuickWindow::activeFocusItemChanged,
|
||
|
this, &QskFocusIndicator::onFocusItemChanged );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
disconnect( window, &QQuickWindow::activeFocusItemChanged,
|
||
|
this, &QskFocusIndicator::onFocusItemChanged );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#include "moc_QskFocusIndicator.cpp"
|