地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

539 lines
0 B

15 years ago
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_panner.h"
#include "qwt_picker.h"
#include "qwt_painter.h"
15 years ago
#include <qpainter.h>
#include <qpixmap.h>
#include <qevent.h>
#include <qcursor.h>
#include <qbitmap.h>
15 years ago
static QVector<QwtPicker *> qwtActivePickers( QWidget *w )
15 years ago
{
QVector<QwtPicker *> pickers;
15 years ago
QObjectList children = w->children();
for ( int i = 0; i < children.size(); i++ )
{
QwtPicker *picker = qobject_cast<QwtPicker *>( children[i] );
if ( picker && picker->isEnabled() )
pickers += picker;
15 years ago
}
return pickers;
}
class QwtPanner::PrivateData
{
public:
PrivateData():
button( Qt::LeftButton ),
buttonModifiers( Qt::NoModifier ),
abortKey( Qt::Key_Escape ),
abortKeyModifiers( Qt::NoModifier ),
15 years ago
#ifndef QT_NO_CURSOR
cursor( NULL ),
restoreCursor( NULL ),
hasCursor( false ),
15 years ago
#endif
isEnabled( false )
{
15 years ago
orientations = Qt::Vertical | Qt::Horizontal;
}
~PrivateData()
{
15 years ago
#ifndef QT_NO_CURSOR
delete cursor;
delete restoreCursor;
#endif
}
Qt::MouseButton button;
Qt::KeyboardModifiers buttonModifiers;
15 years ago
int abortKey;
Qt::KeyboardModifiers abortKeyModifiers;
15 years ago
QPoint initialPos;
QPoint pos;
QPixmap pixmap;
QBitmap contentsMask;
15 years ago
#ifndef QT_NO_CURSOR
QCursor *cursor;
QCursor *restoreCursor;
bool hasCursor;
#endif
bool isEnabled;
Qt::Orientations orientations;
};
/*!
Creates an panner that is enabled for the left mouse button.
\param parent Parent widget to be panned
*/
QwtPanner::QwtPanner( QWidget *parent ):
QWidget( parent )
15 years ago
{
d_data = new PrivateData();
setAttribute( Qt::WA_TransparentForMouseEvents );
setAttribute( Qt::WA_NoSystemBackground );
setFocusPolicy( Qt::NoFocus );
15 years ago
hide();
setEnabled( true );
15 years ago
}
//! Destructor
QwtPanner::~QwtPanner()
{
delete d_data;
}
/*!
Change the mouse button and modifiers used for panning
The defaults are Qt::LeftButton and Qt::NoModifier
15 years ago
*/
void QwtPanner::setMouseButton( Qt::MouseButton button,
Qt::KeyboardModifiers modifiers )
15 years ago
{
d_data->button = button;
d_data->buttonModifiers = modifiers;
15 years ago
}
//! Get mouse button and modifiers used for panning
void QwtPanner::getMouseButton( Qt::MouseButton &button,
Qt::KeyboardModifiers &modifiers ) const
15 years ago
{
button = d_data->button;
modifiers = d_data->buttonModifiers;
15 years ago
}
/*!
Change the abort key
The defaults are Qt::Key_Escape and Qt::NoModifiers
\param key Key ( See Qt::Keycode )
\param modifiers Keyboard modifiers
15 years ago
*/
void QwtPanner::setAbortKey( int key,
Qt::KeyboardModifiers modifiers )
15 years ago
{
d_data->abortKey = key;
d_data->abortKeyModifiers = modifiers;
15 years ago
}
//! Get the abort key and modifiers
void QwtPanner::getAbortKey( int &key,
Qt::KeyboardModifiers &modifiers ) const
15 years ago
{
key = d_data->abortKey;
modifiers = d_data->abortKeyModifiers;
15 years ago
}
/*!
Change the cursor, that is active while panning
The default is the cursor of the parent widget.
\param cursor New cursor
\sa setCursor()
*/
#ifndef QT_NO_CURSOR
void QwtPanner::setCursor( const QCursor &cursor )
15 years ago
{
d_data->cursor = new QCursor( cursor );
15 years ago
}
#endif
/*!
\return Cursor that is active while panning
\sa setCursor()
*/
#ifndef QT_NO_CURSOR
const QCursor QwtPanner::cursor() const
{
if ( d_data->cursor )
return *d_data->cursor;
if ( parentWidget() )
return parentWidget()->cursor();
return QCursor();
}
#endif
/*!
15 years ago
\brief En/disable the panner
15 years ago
When enabled is true an event filter is installed for
the observed widget, otherwise the event filter is removed.
\param on true or false
\sa isEnabled(), eventFilter()
*/
void QwtPanner::setEnabled( bool on )
15 years ago
{
if ( d_data->isEnabled != on )
{
15 years ago
d_data->isEnabled = on;
QWidget *w = parentWidget();
if ( w )
{
if ( d_data->isEnabled )
{
w->installEventFilter( this );
}
else
{
w->removeEventFilter( this );
15 years ago
hide();
}
}
}
}
/*!
Set the orientations, where panning is enabled
The default value is in both directions: Qt::Horizontal | Qt::Vertical
/param o Orientation
*/
void QwtPanner::setOrientations( Qt::Orientations o )
15 years ago
{
d_data->orientations = o;
}
//! Return the orientation, where paning is enabled
Qt::Orientations QwtPanner::orientations() const
{
return d_data->orientations;
}
/*!
\return True if an orientation is enabled
15 years ago
\sa orientations(), setOrientations()
*/
bool QwtPanner::isOrientationEnabled( Qt::Orientation o ) const
15 years ago
{
return d_data->orientations & o;
}
/*!
\return true when enabled, false otherwise
\sa setEnabled, eventFilter()
*/
bool QwtPanner::isEnabled() const
{
return d_data->isEnabled;
}
/*!
\brief Paint event
Repaint the grabbed pixmap on its current position and
fill the empty spaces by the background of the parent widget.
\param pe Paint event
*/
void QwtPanner::paintEvent( QPaintEvent *pe )
15 years ago
{
int dx = d_data->pos.x() - d_data->initialPos.x();
int dy = d_data->pos.y() - d_data->initialPos.y();
15 years ago
QRect r( 0, 0, d_data->pixmap.width(), d_data->pixmap.height() );
r.moveCenter( QPoint( r.center().x() + dx, r.center().y() + dy ) );
15 years ago
QPixmap pm( size() );
QwtPainter::fillPixmap( parentWidget(), pm );
15 years ago
QPainter painter( &pm );
15 years ago
if ( !d_data->contentsMask.isNull() )
{
QPixmap masked = d_data->pixmap;
masked.setMask( d_data->contentsMask );
painter.drawPixmap( r, masked );
}
else
{
painter.drawPixmap( r, d_data->pixmap );
}
15 years ago
painter.end();
if ( !d_data->contentsMask.isNull() )
pm.setMask( d_data->contentsMask );
painter.begin( this );
painter.setClipRegion( pe->region() );
painter.drawPixmap( 0, 0, pm );
}
/*!
\brief Calculate a mask for the contents of the panned widget
Sometimes only parts of the contents of a widget should be
panned. F.e. for a widget with a styled background with rounded borders
only the area inside of the border should be panned.
\return An empty bitmap, indicating no mask
*/
QBitmap QwtPanner::contentsMask() const
{
return QBitmap();
}
/*!
Grab the widget into a pixmap.
\return Grabbed pixmap
*/
QPixmap QwtPanner::grab() const
{
#if QT_VERSION >= 0x050000
return parentWidget()->grab( parentWidget()->rect() );
#else
return QPixmap::grabWidget( parentWidget() );
#endif
15 years ago
}
/*!
15 years ago
\brief Event filter
When isEnabled() is true mouse events of the
observed widget are filtered.
\param object Object to be filtered
\param event Event
\return Always false, beside for paint events for the
parent widget.
15 years ago
\sa widgetMousePressEvent(), widgetMouseReleaseEvent(),
widgetMouseMoveEvent()
*/
bool QwtPanner::eventFilter( QObject *object, QEvent *event )
15 years ago
{
if ( object == NULL || object != parentWidget() )
15 years ago
return false;
switch ( event->type() )
{
case QEvent::MouseButtonPress:
{
widgetMousePressEvent( static_cast<QMouseEvent *>( event ) );
break;
}
case QEvent::MouseMove:
{
widgetMouseMoveEvent( static_cast<QMouseEvent *>( event ) );
break;
}
case QEvent::MouseButtonRelease:
{
widgetMouseReleaseEvent( static_cast<QMouseEvent *>( event ) );
break;
}
case QEvent::KeyPress:
{
widgetKeyPressEvent( static_cast<QKeyEvent *>( event ) );
break;
}
case QEvent::KeyRelease:
{
widgetKeyReleaseEvent( static_cast<QKeyEvent *>( event ) );
break;
}
case QEvent::Paint:
{
if ( isVisible() )
return true;
break;
}
default:;
15 years ago
}
return false;
}
/*!
Handle a mouse press event for the observed widget.
\param mouseEvent Mouse event
15 years ago
\sa eventFilter(), widgetMouseReleaseEvent(),
widgetMouseMoveEvent(),
*/
void QwtPanner::widgetMousePressEvent( QMouseEvent *mouseEvent )
15 years ago
{
if ( ( mouseEvent->button() != d_data->button )
|| ( mouseEvent->modifiers() != d_data->buttonModifiers ) )
{
15 years ago
return;
}
15 years ago
QWidget *w = parentWidget();
if ( w == NULL )
return;
#ifndef QT_NO_CURSOR
showCursor( true );
15 years ago
#endif
d_data->initialPos = d_data->pos = mouseEvent->pos();
15 years ago
setGeometry( parentWidget()->rect() );
15 years ago
// We don't want to grab the picker !
QVector<QwtPicker *> pickers = qwtActivePickers( parentWidget() );
for ( int i = 0; i < pickers.size(); i++ )
pickers[i]->setEnabled( false );
15 years ago
d_data->pixmap = grab();
d_data->contentsMask = contentsMask();
15 years ago
for ( int i = 0; i < pickers.size(); i++ )
pickers[i]->setEnabled( true );
15 years ago
show();
}
/*!
Handle a mouse move event for the observed widget.
\param mouseEvent Mouse event
15 years ago
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent()
*/
void QwtPanner::widgetMouseMoveEvent( QMouseEvent *mouseEvent )
15 years ago
{
if ( !isVisible() )
return;
QPoint pos = mouseEvent->pos();
if ( !isOrientationEnabled( Qt::Horizontal ) )
pos.setX( d_data->initialPos.x() );
if ( !isOrientationEnabled( Qt::Vertical ) )
pos.setY( d_data->initialPos.y() );
15 years ago
if ( pos != d_data->pos && rect().contains( pos ) )
{
15 years ago
d_data->pos = pos;
update();
Q_EMIT moved( d_data->pos.x() - d_data->initialPos.x(),
d_data->pos.y() - d_data->initialPos.y() );
15 years ago
}
}
/*!
Handle a mouse release event for the observed widget.
\param mouseEvent Mouse event
15 years ago
\sa eventFilter(), widgetMousePressEvent(),
widgetMouseMoveEvent(),
*/
void QwtPanner::widgetMouseReleaseEvent( QMouseEvent *mouseEvent )
15 years ago
{
if ( isVisible() )
{
15 years ago
hide();
#ifndef QT_NO_CURSOR
showCursor( false );
15 years ago
#endif
QPoint pos = mouseEvent->pos();
if ( !isOrientationEnabled( Qt::Horizontal ) )
pos.setX( d_data->initialPos.x() );
if ( !isOrientationEnabled( Qt::Vertical ) )
pos.setY( d_data->initialPos.y() );
15 years ago
d_data->pixmap = QPixmap();
d_data->contentsMask = QBitmap();
15 years ago
d_data->pos = pos;
if ( d_data->pos != d_data->initialPos )
{
Q_EMIT panned( d_data->pos.x() - d_data->initialPos.x(),
d_data->pos.y() - d_data->initialPos.y() );
15 years ago
}
}
}
/*!
Handle a key press event for the observed widget.
\param keyEvent Key event
15 years ago
\sa eventFilter(), widgetKeyReleaseEvent()
*/
void QwtPanner::widgetKeyPressEvent( QKeyEvent *keyEvent )
15 years ago
{
if ( ( keyEvent->key() == d_data->abortKey )
&& ( keyEvent->modifiers() == d_data->abortKeyModifiers ) )
{
hide();
15 years ago
#ifndef QT_NO_CURSOR
showCursor( false );
15 years ago
#endif
d_data->pixmap = QPixmap();
15 years ago
}
}
/*!
Handle a key release event for the observed widget.
\param keyEvent Key event
15 years ago
\sa eventFilter(), widgetKeyReleaseEvent()
*/
void QwtPanner::widgetKeyReleaseEvent( QKeyEvent *keyEvent )
15 years ago
{
Q_UNUSED( keyEvent );
15 years ago
}
#ifndef QT_NO_CURSOR
void QwtPanner::showCursor( bool on )
15 years ago
{
if ( on == d_data->hasCursor )
return;
QWidget *w = parentWidget();
if ( w == NULL || d_data->cursor == NULL )
return;
d_data->hasCursor = on;
if ( on )
{
if ( w->testAttribute( Qt::WA_SetCursor ) )
15 years ago
{
delete d_data->restoreCursor;
d_data->restoreCursor = new QCursor( w->cursor() );
15 years ago
}
w->setCursor( *d_data->cursor );
}
else
{
if ( d_data->restoreCursor )
{
w->setCursor( *d_data->restoreCursor );
15 years ago
delete d_data->restoreCursor;
d_data->restoreCursor = NULL;
}
else
15 years ago
w->unsetCursor();
}
}
#endif