地面站终端 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.

358 lines
8.9 KiB

/* -*- 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 <qpainter.h>
#include <qstyle.h>
#include <qevent.h>
#include "qwt_math.h"
#include "qwt_polygon.h"
#include "qwt_arrow_button.h"
static const int MaxNum = 3;
static const int Margin = 2;
static const int Spacing = 1;
class QwtArrowButton::PrivateData
{
public:
int num;
Qt::ArrowType arrowType;
};
#if QT_VERSION >= 0x040000
#include <qstyleoption.h>
static QStyleOptionButton styleOpt(const QwtArrowButton* btn)
{
QStyleOptionButton option;
option.init(btn);
option.features = QStyleOptionButton::None;
if (btn->isFlat())
option.features |= QStyleOptionButton::Flat;
if (btn->menu())
option.features |= QStyleOptionButton::HasMenu;
if (btn->autoDefault() || btn->isDefault())
option.features |= QStyleOptionButton::AutoDefaultButton;
if (btn->isDefault())
option.features |= QStyleOptionButton::DefaultButton;
if (btn->isDown())
option.state |= QStyle::State_Sunken;
if (!btn->isFlat() && !btn->isDown())
option.state |= QStyle::State_Raised;
return option;
}
#endif
/*!
\param num Number of arrows
\param arrowType see Qt::ArowType in the Qt docs.
\param parent Parent widget
*/
QwtArrowButton::QwtArrowButton(int num,
Qt::ArrowType arrowType, QWidget *parent):
QPushButton(parent)
{
d_data = new PrivateData;
d_data->num = qwtLim(num, 1, MaxNum);
d_data->arrowType = arrowType;
setAutoRepeat(true);
setAutoDefault(false);
switch(d_data->arrowType) {
case Qt::LeftArrow:
case Qt::RightArrow:
setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Fixed);
break;
default:
setSizePolicy(QSizePolicy::Fixed,
QSizePolicy::Expanding);
}
}
//! Destructor
QwtArrowButton::~QwtArrowButton()
{
delete d_data;
d_data = NULL;
}
/*!
\brief The direction of the arrows
*/
Qt::ArrowType QwtArrowButton::arrowType() const
{
return d_data->arrowType;
}
/*!
\brief The number of arrows
*/
int QwtArrowButton::num() const
{
return d_data->num;
}
/*!
\return the bounding rect for the label
*/
QRect QwtArrowButton::labelRect() const
{
const int m = Margin;
QRect r = rect();
r.setRect(r.x() + m, r.y() + m,
r.width() - 2 * m, r.height() - 2 * m);
if ( isDown() ) {
int ph, pv;
#if QT_VERSION < 0x040000
ph = style().pixelMetric(
QStyle::PM_ButtonShiftHorizontal, this);
pv = style().pixelMetric(
QStyle::PM_ButtonShiftVertical, this);
r.moveBy(ph, pv);
#else
QStyleOptionButton option = styleOpt(this);
ph = style()->pixelMetric(
QStyle::PM_ButtonShiftHorizontal, &option, this);
pv = style()->pixelMetric(
QStyle::PM_ButtonShiftVertical, &option, this);
r.translate(ph, pv);
#endif
}
return r;
}
#if QT_VERSION >= 0x040000
/*!
Paint event handler
\param event Paint event
*/
void QwtArrowButton::paintEvent(QPaintEvent *event)
{
QPushButton::paintEvent(event);
QPainter painter(this);
drawButtonLabel(&painter);
}
#endif
/*!
\brief Draw the button label
\param painter Painter
\sa The Qt Manual on QPushButton
*/
void QwtArrowButton::drawButtonLabel(QPainter *painter)
{
const bool isVertical = d_data->arrowType == Qt::UpArrow ||
d_data->arrowType == Qt::DownArrow;
const QRect r = labelRect();
QSize boundingSize = labelRect().size();
if ( isVertical )
boundingSize.transpose();
const int w =
(boundingSize.width() - (MaxNum - 1) * Spacing) / MaxNum;
QSize arrow = arrowSize(Qt::RightArrow,
QSize(w, boundingSize.height()));
if ( isVertical )
arrow.transpose();
QRect contentsSize; // aligned rect where to paint all arrows
if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow ) {
contentsSize.setWidth(d_data->num * arrow.width()
+ (d_data->num - 1) * Spacing);
contentsSize.setHeight(arrow.height());
} else {
contentsSize.setWidth(arrow.width());
contentsSize.setHeight(d_data->num * arrow.height()
+ (d_data->num - 1) * Spacing);
}
QRect arrowRect(contentsSize);
arrowRect.moveCenter(r.center());
arrowRect.setSize(arrow);
painter->save();
for (int i = 0; i < d_data->num; i++) {
drawArrow(painter, arrowRect, d_data->arrowType);
int dx = 0;
int dy = 0;
if ( isVertical )
dy = arrow.height() + Spacing;
else
dx = arrow.width() + Spacing;
#if QT_VERSION >= 0x040000
arrowRect.translate(dx, dy);
#else
arrowRect.moveBy(dx, dy);
#endif
}
painter->restore();
if ( hasFocus() ) {
#if QT_VERSION >= 0x040000
QStyleOptionFocusRect option;
option.init(this);
option.backgroundColor = palette().color(QPalette::Background);
style()->drawPrimitive(QStyle::PE_FrameFocusRect,
&option, painter, this);
#else
const QRect focusRect =
style().subRect(QStyle::SR_PushButtonFocusRect, this);
style().drawPrimitive(QStyle::PE_FocusRect, painter,
focusRect, colorGroup());
#endif
}
}
/*!
Draw an arrow int a bounding rect
\param painter Painter
\param r Rectangle where to paint the arrow
\param arrowType Arrow type
*/
void QwtArrowButton::drawArrow(QPainter *painter,
const QRect &r, Qt::ArrowType arrowType) const
{
QwtPolygon pa(3);
switch(arrowType) {
case Qt::UpArrow:
pa.setPoint(0, r.bottomLeft());
pa.setPoint(1, r.bottomRight());
pa.setPoint(2, r.center().x(), r.top());
break;
case Qt::DownArrow:
pa.setPoint(0, r.topLeft());
pa.setPoint(1, r.topRight());
pa.setPoint(2, r.center().x(), r.bottom());
break;
case Qt::RightArrow:
pa.setPoint(0, r.topLeft());
pa.setPoint(1, r.bottomLeft());
pa.setPoint(2, r.right(), r.center().y());
break;
case Qt::LeftArrow:
pa.setPoint(0, r.topRight());
pa.setPoint(1, r.bottomRight());
pa.setPoint(2, r.left(), r.center().y());
break;
default:
break;
}
painter->save();
#if QT_VERSION < 0x040000
painter->setPen(colorGroup().buttonText());
painter->setBrush(colorGroup().brush(QColorGroup::ButtonText));
#else
painter->setPen(palette().color(QPalette::ButtonText));
painter->setBrush(palette().brush(QPalette::ButtonText));
#endif
painter->drawPolygon(pa);
painter->restore();
}
/*!
\return a size hint
*/
QSize QwtArrowButton::sizeHint() const
{
return minimumSizeHint();
}
/*!
\brief Return a minimum size hint
*/
QSize QwtArrowButton::minimumSizeHint() const
{
const QSize asz = arrowSize(Qt::RightArrow, QSize());
QSize sz(
2 * Margin + (MaxNum - 1) * Spacing + MaxNum * asz.width(),
2 * Margin + asz.height()
);
if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow )
sz.transpose();
#if QT_VERSION >= 0x040000
QStyleOption styleOption;
styleOption.init(this);
const QSize hsz = style()->sizeFromContents(QStyle::CT_PushButton,
&styleOption, sz, this);
#if QT_VERSION < 0x040300
if ( hsz.width() != 80 ) // avoid a bug in the Cleanlooks style
#endif
sz = hsz;
#else
sz = style().sizeFromContents(QStyle::CT_PushButton, this, sz);
#endif
return sz;
}
/*!
Calculate the size for a arrow that fits into a rect of a given size
\param arrowType Arrow type
\param boundingSize Bounding size
\return Size of the arrow
*/
QSize QwtArrowButton::arrowSize(Qt::ArrowType arrowType,
const QSize &boundingSize) const
{
QSize bs = boundingSize;
if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
bs.transpose();
const int MinLen = 2;
const QSize sz = bs.expandedTo(
QSize(MinLen, 2 * MinLen - 1)); // minimum
int w = sz.width();
int h = 2 * w - 1;
if ( h > sz.height() ) {
h = sz.height();
w = (h + 1) / 2;
}
QSize arrSize(w, h);
if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
arrSize.transpose();
return arrSize;
}
/*!
\brief autoRepeat for the space keys
*/
void QwtArrowButton::keyPressEvent(QKeyEvent *e)
{
if ( e->isAutoRepeat() && e->key() == Qt::Key_Space )
emit clicked();
QPushButton::keyPressEvent(e);
}