彻底改版2.0
This commit is contained in:
BIN
third/0snap/designer.jpg
Normal file
BIN
third/0snap/designer.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 216 KiB |
BIN
third/0snap/hotkey.jpg
Normal file
BIN
third/0snap/hotkey.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
BIN
third/0snap/miniblink.jpg
Normal file
BIN
third/0snap/miniblink.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
third/0snap/qwtdemo.jpg
Normal file
BIN
third/0snap/qwtdemo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
third/0snap/shortcut.jpg
Normal file
BIN
third/0snap/shortcut.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
20
third/3rd_qhotkey/3rd_qhotkey.pri
Normal file
20
third/3rd_qhotkey/3rd_qhotkey.pri
Normal file
@@ -0,0 +1,20 @@
|
||||
CONFIG += C++11
|
||||
HEADERS += $$PWD/qhotkey.h
|
||||
HEADERS += $$PWD/qhotkey_p.h
|
||||
SOURCES += $$PWD/qhotkey.cpp
|
||||
|
||||
win32 {
|
||||
LIBS += -luser32
|
||||
SOURCES += $$PWD/qhotkey_win.cpp
|
||||
}
|
||||
|
||||
unix:!macx {
|
||||
QT += x11extras
|
||||
LIBS += -lX11
|
||||
SOURCES += $$PWD/qhotkey_x11.cpp
|
||||
}
|
||||
|
||||
macx {
|
||||
LIBS += -framework Carbon
|
||||
SOURCES += $$PWD/qhotkey_mac.cpp
|
||||
}
|
||||
349
third/3rd_qhotkey/qhotkey.cpp
Normal file
349
third/3rd_qhotkey/qhotkey.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
#include "qhotkey.h"
|
||||
#include "qhotkey_p.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QMetaMethod>
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
|
||||
QHotkey::QHotkey(QObject *parent) : QObject(parent)
|
||||
{
|
||||
_keyCode = Qt::Key_unknown;
|
||||
_modifiers = Qt::NoModifier;
|
||||
_nativeShortcut = 0;
|
||||
_registered = false;
|
||||
}
|
||||
|
||||
QHotkey::QHotkey(const QKeySequence &sequence, bool autoRegister, QObject *parent) : QHotkey(parent)
|
||||
{
|
||||
setShortcut(sequence, autoRegister);
|
||||
}
|
||||
|
||||
QHotkey::QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister, QObject *parent) : QHotkey(parent)
|
||||
{
|
||||
setShortcut(keyCode, modifiers, autoRegister);
|
||||
}
|
||||
|
||||
QHotkey::QHotkey(const QHotkey::NativeShortcut &shortcut, bool autoRegister, QObject *parent) : QHotkey(parent)
|
||||
{
|
||||
setNativeShortcut(shortcut, autoRegister);
|
||||
}
|
||||
|
||||
QHotkey::~QHotkey()
|
||||
{
|
||||
if (_registered) {
|
||||
QHotkeyPrivate::instance()->removeShortcut(this);
|
||||
}
|
||||
}
|
||||
|
||||
QKeySequence QHotkey::shortcut() const
|
||||
{
|
||||
if (_keyCode == Qt::Key_unknown) {
|
||||
return QKeySequence();
|
||||
} else {
|
||||
return QKeySequence(_keyCode | _modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
Qt::Key QHotkey::keyCode() const
|
||||
{
|
||||
return _keyCode;
|
||||
}
|
||||
|
||||
Qt::KeyboardModifiers QHotkey::modifiers() const
|
||||
{
|
||||
return _modifiers;
|
||||
}
|
||||
|
||||
QHotkey::NativeShortcut QHotkey::currentNativeShortcut() const
|
||||
{
|
||||
return _nativeShortcut;
|
||||
}
|
||||
|
||||
bool QHotkey::isRegistered() const
|
||||
{
|
||||
return _registered;
|
||||
}
|
||||
|
||||
bool QHotkey::setShortcut(const QKeySequence &shortcut, bool autoRegister)
|
||||
{
|
||||
if (shortcut.isEmpty()) {
|
||||
return resetShortcut();
|
||||
} else if (shortcut.count() > 1) {
|
||||
qDebug() << "Keysequences with multiple shortcuts are not allowed Only the first shortcut will be used!";;
|
||||
}
|
||||
|
||||
return setShortcut(Qt::Key(shortcut[0] & ~Qt::KeyboardModifierMask),
|
||||
Qt::KeyboardModifiers(shortcut[0] & Qt::KeyboardModifierMask),
|
||||
autoRegister);
|
||||
}
|
||||
|
||||
bool QHotkey::setShortcut(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister)
|
||||
{
|
||||
if (_registered) {
|
||||
if (autoRegister) {
|
||||
if (!QHotkeyPrivate::instance()->removeShortcut(this)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (keyCode == Qt::Key_unknown) {
|
||||
_keyCode = Qt::Key_unknown;
|
||||
_modifiers = Qt::NoModifier;
|
||||
_nativeShortcut = NativeShortcut();
|
||||
return true;
|
||||
}
|
||||
|
||||
_keyCode = keyCode;
|
||||
_modifiers = modifiers;
|
||||
_nativeShortcut = QHotkeyPrivate::instance()->nativeShortcut(keyCode, modifiers);
|
||||
if (_nativeShortcut.isValid()) {
|
||||
if (autoRegister) {
|
||||
return QHotkeyPrivate::instance()->addShortcut(this);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Unable to map shortcut to native keys. Key:" << keyCode << "Modifiers:" << modifiers;
|
||||
_keyCode = Qt::Key_unknown;
|
||||
_modifiers = Qt::NoModifier;
|
||||
_nativeShortcut = NativeShortcut();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool QHotkey::resetShortcut()
|
||||
{
|
||||
if (_registered &&
|
||||
!QHotkeyPrivate::instance()->removeShortcut(this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_keyCode = Qt::Key_unknown;
|
||||
_modifiers = Qt::NoModifier;
|
||||
_nativeShortcut = NativeShortcut();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QHotkey::setNativeShortcut(QHotkey::NativeShortcut nativeShortcut, bool autoRegister)
|
||||
{
|
||||
if (_registered) {
|
||||
if (autoRegister) {
|
||||
if (!QHotkeyPrivate::instance()->removeShortcut(this)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (nativeShortcut.isValid()) {
|
||||
_keyCode = Qt::Key_unknown;
|
||||
_modifiers = Qt::NoModifier;
|
||||
_nativeShortcut = nativeShortcut;
|
||||
if (autoRegister) {
|
||||
return QHotkeyPrivate::instance()->addShortcut(this);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
_keyCode = Qt::Key_unknown;
|
||||
_modifiers = Qt::NoModifier;
|
||||
_nativeShortcut = NativeShortcut();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool QHotkey::setRegistered(bool registered)
|
||||
{
|
||||
if (_registered && !registered) {
|
||||
return QHotkeyPrivate::instance()->removeShortcut(this);
|
||||
} else if (!_registered && registered) {
|
||||
if (!_nativeShortcut.isValid()) {
|
||||
return false;
|
||||
} else {
|
||||
return QHotkeyPrivate::instance()->addShortcut(this);
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- QHotkeyPrivate implementation ----------
|
||||
|
||||
QHotkeyPrivate::QHotkeyPrivate()
|
||||
{
|
||||
shortcuts = QMultiHash<QHotkey::NativeShortcut, QHotkey *>();
|
||||
Q_ASSERT_X(qApp, Q_FUNC_INFO, "QHotkey requires QCoreApplication to be instantiated");
|
||||
qApp->eventDispatcher()->installNativeEventFilter(this);
|
||||
}
|
||||
|
||||
QHotkeyPrivate::~QHotkeyPrivate()
|
||||
{
|
||||
if (!shortcuts.isEmpty()) {
|
||||
qDebug() << "QHotkeyPrivate destroyed with registered shortcuts!";
|
||||
}
|
||||
if (qApp && qApp->eventDispatcher()) {
|
||||
qApp->eventDispatcher()->removeNativeEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcut(Qt::Key keycode, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
Qt::ConnectionType conType = (QThread::currentThread() == thread() ?
|
||||
Qt::DirectConnection :
|
||||
Qt::BlockingQueuedConnection);
|
||||
QHotkey::NativeShortcut res;
|
||||
if (!QMetaObject::invokeMethod(this, "nativeShortcutInvoked", conType,
|
||||
Q_RETURN_ARG(QHotkey::NativeShortcut, res),
|
||||
Q_ARG(Qt::Key, keycode),
|
||||
Q_ARG(Qt::KeyboardModifiers, modifiers))) {
|
||||
return QHotkey::NativeShortcut();
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
bool QHotkeyPrivate::addShortcut(QHotkey *hotkey)
|
||||
{
|
||||
if (hotkey->_registered) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ConnectionType conType = (QThread::currentThread() == thread() ?
|
||||
Qt::DirectConnection :
|
||||
Qt::BlockingQueuedConnection);
|
||||
bool res = false;
|
||||
if (!QMetaObject::invokeMethod(this, "addShortcutInvoked", conType,
|
||||
Q_RETURN_ARG(bool, res),
|
||||
Q_ARG(QHotkey *, hotkey))) {
|
||||
return false;
|
||||
} else {
|
||||
if (res) {
|
||||
emit hotkey->registeredChanged(true);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
bool QHotkeyPrivate::removeShortcut(QHotkey *hotkey)
|
||||
{
|
||||
if (!hotkey->_registered) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ConnectionType conType = (QThread::currentThread() == thread() ?
|
||||
Qt::DirectConnection :
|
||||
Qt::BlockingQueuedConnection);
|
||||
bool res = false;
|
||||
if (!QMetaObject::invokeMethod(this, "removeShortcutInvoked", conType,
|
||||
Q_RETURN_ARG(bool, res),
|
||||
Q_ARG(QHotkey *, hotkey))) {
|
||||
return false;
|
||||
} else {
|
||||
if (res) {
|
||||
emit hotkey->registeredChanged(false);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
void QHotkeyPrivate::activateShortcut(QHotkey::NativeShortcut shortcut)
|
||||
{
|
||||
QMetaMethod signal = QMetaMethod::fromSignal(&QHotkey::activated);
|
||||
foreach (QHotkey *hkey, shortcuts.values(shortcut)) {
|
||||
signal.invoke(hkey, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
bool QHotkeyPrivate::addShortcutInvoked(QHotkey *hotkey)
|
||||
{
|
||||
QHotkey::NativeShortcut shortcut = hotkey->_nativeShortcut;
|
||||
|
||||
if (!shortcuts.contains(shortcut)) {
|
||||
if (!registerShortcut(shortcut)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
shortcuts.insert(shortcut, hotkey);
|
||||
hotkey->_registered = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QHotkeyPrivate::removeShortcutInvoked(QHotkey *hotkey)
|
||||
{
|
||||
QHotkey::NativeShortcut shortcut = hotkey->_nativeShortcut;
|
||||
if (shortcuts.remove(shortcut, hotkey) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hotkey->_registered = false;
|
||||
emit hotkey->registeredChanged(true);
|
||||
|
||||
if (shortcuts.count(shortcut) == 0) {
|
||||
return unregisterShortcut(shortcut);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
QHotkey::NativeShortcut QHotkeyPrivate::nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
bool ok1, ok2 = false;
|
||||
quint32 k = nativeKeycode(keycode, ok1);
|
||||
quint32 m = nativeModifiers(modifiers, ok2);
|
||||
if (ok1 && ok2) {
|
||||
return QHotkey::NativeShortcut(k, m);
|
||||
} else {
|
||||
return QHotkey::NativeShortcut();
|
||||
}
|
||||
}
|
||||
|
||||
QHotkey::NativeShortcut::NativeShortcut()
|
||||
{
|
||||
this->key = Qt::Key_unknown;
|
||||
this->modifier = Qt::NoModifier;
|
||||
this->valid = false;
|
||||
}
|
||||
|
||||
QHotkey::NativeShortcut::NativeShortcut(quint32 key, quint32 modifier)
|
||||
{
|
||||
this->key = key;
|
||||
this->modifier = modifier;
|
||||
this->valid = true;
|
||||
}
|
||||
|
||||
bool QHotkey::NativeShortcut::isValid() const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool QHotkey::NativeShortcut::operator ==(const QHotkey::NativeShortcut &other) const
|
||||
{
|
||||
return (key == other.key) &&
|
||||
(modifier == other.modifier) &&
|
||||
valid == other.valid;
|
||||
}
|
||||
|
||||
bool QHotkey::NativeShortcut::operator !=(const QHotkey::NativeShortcut &other) const
|
||||
{
|
||||
return (key != other.key) ||
|
||||
(modifier != other.modifier) ||
|
||||
valid != other.valid;
|
||||
}
|
||||
|
||||
uint qHash(const QHotkey::NativeShortcut &key)
|
||||
{
|
||||
return qHash(key.key) ^ qHash(key.modifier);
|
||||
}
|
||||
|
||||
uint qHash(const QHotkey::NativeShortcut &key, uint seed)
|
||||
{
|
||||
return qHash(key.key, seed) ^ qHash(key.modifier, seed);
|
||||
}
|
||||
111
third/3rd_qhotkey/qhotkey.h
Normal file
111
third/3rd_qhotkey/qhotkey.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef QHOTKEY_H
|
||||
#define QHOTKEY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QKeySequence>
|
||||
#include <QPair>
|
||||
|
||||
#ifdef QHOTKEY_LIB
|
||||
#ifdef QHOTKEY_LIB_BUILD
|
||||
#define QHOTKEY_SHARED_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
#define QHOTKEY_SHARED_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
#else
|
||||
#define QHOTKEY_SHARED_EXPORT
|
||||
#endif
|
||||
|
||||
//! A class to define global, systemwide Hotkeys
|
||||
class QHOTKEY_SHARED_EXPORT QHotkey : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class QHotkeyPrivate;
|
||||
|
||||
//! Specifies whether this hotkey is currently registered or not
|
||||
Q_PROPERTY(bool registered READ isRegistered WRITE setRegistered NOTIFY registeredChanged)
|
||||
//! Holds the shortcut this hotkey will be triggered on
|
||||
Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut RESET resetShortcut)
|
||||
|
||||
public:
|
||||
//! Defines shortcut with native keycodes
|
||||
class QHOTKEY_SHARED_EXPORT NativeShortcut
|
||||
{
|
||||
public:
|
||||
//! The native keycode
|
||||
quint32 key;
|
||||
//! The native modifiers
|
||||
quint32 modifier;
|
||||
|
||||
//! Creates an invalid native shortcut
|
||||
NativeShortcut();
|
||||
//! Creates a valid native shortcut, with the given key and modifiers
|
||||
NativeShortcut(quint32 key, quint32 modifier = 0);
|
||||
|
||||
//! Checks, whether this shortcut is valid or not
|
||||
bool isValid() const;
|
||||
|
||||
//! Equality operator
|
||||
bool operator ==(const NativeShortcut &other) const;
|
||||
//! Inequality operator
|
||||
bool operator !=(const NativeShortcut &other) const;
|
||||
|
||||
private:
|
||||
bool valid;
|
||||
};
|
||||
|
||||
//! Constructor
|
||||
explicit QHotkey(QObject *parent = 0);
|
||||
//! Constructs a hotkey with a shortcut and optionally registers it
|
||||
explicit QHotkey(const QKeySequence &shortcut, bool autoRegister = false, QObject *parent = 0);
|
||||
//! Constructs a hotkey with a key and modifiers and optionally registers it
|
||||
explicit QHotkey(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister = false, QObject *parent = 0);
|
||||
//! Constructs a hotkey from a native shortcut and optionally registers it
|
||||
explicit QHotkey(const NativeShortcut &shortcut, bool autoRegister = false, QObject *parent = 0);
|
||||
//! Destructor
|
||||
~QHotkey();
|
||||
|
||||
//! READ-Accessor for QHotkey::registered
|
||||
bool isRegistered() const;
|
||||
//! READ-Accessor for QHotkey::shortcut - the key and modifiers as a QKeySequence
|
||||
QKeySequence shortcut() const;
|
||||
//! READ-Accessor for QHotkey::shortcut - the key only
|
||||
Qt::Key keyCode() const;
|
||||
//! READ-Accessor for QHotkey::shortcut - the modifiers only
|
||||
Qt::KeyboardModifiers modifiers() const;
|
||||
|
||||
//! Get the current native shortcut
|
||||
NativeShortcut currentNativeShortcut() const;
|
||||
|
||||
public slots:
|
||||
//! WRITE-Accessor for QHotkey::registered
|
||||
bool setRegistered(bool registered);
|
||||
|
||||
//! WRITE-Accessor for QHotkey::shortcut
|
||||
bool setShortcut(const QKeySequence &shortcut, bool autoRegister = false);
|
||||
//! WRITE-Accessor for QHotkey::shortcut
|
||||
bool setShortcut(Qt::Key keyCode, Qt::KeyboardModifiers modifiers, bool autoRegister = false);
|
||||
//! RESET-Accessor for QHotkey::shortcut
|
||||
bool resetShortcut();
|
||||
|
||||
//! Set this hotkey to a native shortcut
|
||||
bool setNativeShortcut(NativeShortcut nativeShortcut, bool autoRegister = false);
|
||||
|
||||
signals:
|
||||
//! Will be emitted if the shortcut is pressed
|
||||
void activated();
|
||||
|
||||
//! NOTIFY-Accessor for QHotkey::registered
|
||||
void registeredChanged(bool registered);
|
||||
|
||||
private:
|
||||
Qt::Key _keyCode;
|
||||
Qt::KeyboardModifiers _modifiers;
|
||||
|
||||
NativeShortcut _nativeShortcut;
|
||||
bool _registered;
|
||||
};
|
||||
|
||||
uint QHOTKEY_SHARED_EXPORT qHash(const QHotkey::NativeShortcut &key);
|
||||
uint QHOTKEY_SHARED_EXPORT qHash(const QHotkey::NativeShortcut &key, uint seed);
|
||||
|
||||
#endif // QHOTKEY_H
|
||||
268
third/3rd_qhotkey/qhotkey_mac.cpp
Normal file
268
third/3rd_qhotkey/qhotkey_mac.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "qhotkey.h"
|
||||
#include "qhotkey_p.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <QDebug>
|
||||
|
||||
class QHotkeyPrivateMac : public QHotkeyPrivate
|
||||
{
|
||||
public:
|
||||
// QAbstractNativeEventFilter interface
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
|
||||
|
||||
static OSStatus hotkeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *data);
|
||||
|
||||
protected:
|
||||
// QHotkeyPrivate interface
|
||||
quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE;
|
||||
quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE;
|
||||
bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
|
||||
bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
static bool isHotkeyHandlerRegistered;
|
||||
static QHash<QHotkey::NativeShortcut, EventHotKeyRef> hotkeyRefs;
|
||||
};
|
||||
NATIVE_INSTANCE(QHotkeyPrivateMac)
|
||||
|
||||
bool QHotkeyPrivateMac::isHotkeyHandlerRegistered = false;
|
||||
QHash<QHotkey::NativeShortcut, EventHotKeyRef> QHotkeyPrivateMac::hotkeyRefs;
|
||||
|
||||
bool QHotkeyPrivateMac::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(message);
|
||||
Q_UNUSED(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
quint32 QHotkeyPrivateMac::nativeKeycode(Qt::Key keycode, bool &ok)
|
||||
{
|
||||
// Constants found in NSEvent.h from AppKit.framework
|
||||
ok = true;
|
||||
switch (keycode) {
|
||||
case Qt::Key_Return:
|
||||
return kVK_Return;
|
||||
case Qt::Key_Enter:
|
||||
return kVK_ANSI_KeypadEnter;
|
||||
case Qt::Key_Tab:
|
||||
return kVK_Tab;
|
||||
case Qt::Key_Space:
|
||||
return kVK_Space;
|
||||
case Qt::Key_Backspace:
|
||||
return kVK_Delete;
|
||||
case Qt::Key_Escape:
|
||||
return kVK_Escape;
|
||||
case Qt::Key_CapsLock:
|
||||
return kVK_CapsLock;
|
||||
case Qt::Key_Option:
|
||||
return kVK_Option;
|
||||
case Qt::Key_F17:
|
||||
return kVK_F17;
|
||||
case Qt::Key_VolumeUp:
|
||||
return kVK_VolumeUp;
|
||||
case Qt::Key_VolumeDown:
|
||||
return kVK_VolumeDown;
|
||||
case Qt::Key_F18:
|
||||
return kVK_F18;
|
||||
case Qt::Key_F19:
|
||||
return kVK_F19;
|
||||
case Qt::Key_F20:
|
||||
return kVK_F20;
|
||||
case Qt::Key_F5:
|
||||
return kVK_F5;
|
||||
case Qt::Key_F6:
|
||||
return kVK_F6;
|
||||
case Qt::Key_F7:
|
||||
return kVK_F7;
|
||||
case Qt::Key_F3:
|
||||
return kVK_F3;
|
||||
case Qt::Key_F8:
|
||||
return kVK_F8;
|
||||
case Qt::Key_F9:
|
||||
return kVK_F9;
|
||||
case Qt::Key_F11:
|
||||
return kVK_F11;
|
||||
case Qt::Key_F13:
|
||||
return kVK_F13;
|
||||
case Qt::Key_F16:
|
||||
return kVK_F16;
|
||||
case Qt::Key_F14:
|
||||
return kVK_F14;
|
||||
case Qt::Key_F10:
|
||||
return kVK_F10;
|
||||
case Qt::Key_F12:
|
||||
return kVK_F12;
|
||||
case Qt::Key_F15:
|
||||
return kVK_F15;
|
||||
case Qt::Key_Help:
|
||||
return kVK_Help;
|
||||
case Qt::Key_Home:
|
||||
return kVK_Home;
|
||||
case Qt::Key_PageUp:
|
||||
return kVK_PageUp;
|
||||
case Qt::Key_Delete:
|
||||
return kVK_ForwardDelete;
|
||||
case Qt::Key_F4:
|
||||
return kVK_F4;
|
||||
case Qt::Key_End:
|
||||
return kVK_End;
|
||||
case Qt::Key_F2:
|
||||
return kVK_F2;
|
||||
case Qt::Key_PageDown:
|
||||
return kVK_PageDown;
|
||||
case Qt::Key_F1:
|
||||
return kVK_F1;
|
||||
case Qt::Key_Left:
|
||||
return kVK_LeftArrow;
|
||||
case Qt::Key_Right:
|
||||
return kVK_RightArrow;
|
||||
case Qt::Key_Down:
|
||||
return kVK_DownArrow;
|
||||
case Qt::Key_Up:
|
||||
return kVK_UpArrow;
|
||||
default:
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
UTF16Char ch = keycode;
|
||||
|
||||
CFDataRef currentLayoutData;
|
||||
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
|
||||
|
||||
if (currentKeyboard == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
|
||||
CFRelease(currentKeyboard);
|
||||
if (currentLayoutData == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
UCKeyboardLayout *header = (UCKeyboardLayout *)CFDataGetBytePtr(currentLayoutData);
|
||||
UCKeyboardTypeHeader *table = header->keyboardTypeList;
|
||||
|
||||
uint8_t *data = (uint8_t *)header;
|
||||
for (quint32 i = 0; i < header->keyboardTypeCount; i++) {
|
||||
UCKeyStateRecordsIndex *stateRec = 0;
|
||||
if (table[i].keyStateRecordsIndexOffset != 0) {
|
||||
stateRec = reinterpret_cast<UCKeyStateRecordsIndex *>(data + table[i].keyStateRecordsIndexOffset);
|
||||
if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) {
|
||||
stateRec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
UCKeyToCharTableIndex *charTable = reinterpret_cast<UCKeyToCharTableIndex *>(data + table[i].keyToCharTableIndexOffset);
|
||||
if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (quint32 j = 0; j < charTable->keyToCharTableCount; j++) {
|
||||
UCKeyOutput *keyToChar = reinterpret_cast<UCKeyOutput *>(data + charTable->keyToCharTableOffsets[j]);
|
||||
for (quint32 k = 0; k < charTable->keyToCharTableSize; k++) {
|
||||
if (keyToChar[k] & kUCKeyOutputTestForIndexMask) {
|
||||
long idx = keyToChar[k] & kUCKeyOutputGetIndexMask;
|
||||
if (stateRec && idx < stateRec->keyStateRecordCount) {
|
||||
UCKeyStateRecord *rec = reinterpret_cast<UCKeyStateRecord *>(data + stateRec->keyStateRecordOffsets[idx]);
|
||||
if (rec->stateZeroCharData == ch) {
|
||||
ok = true;
|
||||
return k;
|
||||
}
|
||||
}
|
||||
} else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) {
|
||||
if (keyToChar[k] == ch) {
|
||||
ok = true;
|
||||
return k;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
quint32 QHotkeyPrivateMac::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok)
|
||||
{
|
||||
quint32 nMods = 0;
|
||||
if (modifiers & Qt::ShiftModifier) {
|
||||
nMods |= shiftKey;
|
||||
}
|
||||
if (modifiers & Qt::ControlModifier) {
|
||||
nMods |= cmdKey;
|
||||
}
|
||||
if (modifiers & Qt::AltModifier) {
|
||||
nMods |= optionKey;
|
||||
}
|
||||
if (modifiers & Qt::MetaModifier) {
|
||||
nMods |= controlKey;
|
||||
}
|
||||
if (modifiers & Qt::KeypadModifier) {
|
||||
nMods |= kEventKeyModifierNumLockMask;
|
||||
}
|
||||
ok = true;
|
||||
return nMods;
|
||||
}
|
||||
|
||||
bool QHotkeyPrivateMac::registerShortcut(QHotkey::NativeShortcut shortcut)
|
||||
{
|
||||
if (!this->isHotkeyHandlerRegistered) {
|
||||
EventTypeSpec eventSpec;
|
||||
eventSpec.eventClass = kEventClassKeyboard;
|
||||
eventSpec.eventKind = kEventHotKeyPressed;
|
||||
InstallApplicationEventHandler(&QHotkeyPrivateMac::hotkeyEventHandler, 1, &eventSpec, NULL, NULL);
|
||||
}
|
||||
|
||||
EventHotKeyID hkeyID;
|
||||
hkeyID.signature = shortcut.key;
|
||||
hkeyID.id = shortcut.modifier;
|
||||
|
||||
EventHotKeyRef eventRef = 0;
|
||||
OSStatus status = RegisterEventHotKey(shortcut.key,
|
||||
shortcut.modifier,
|
||||
hkeyID,
|
||||
GetApplicationEventTarget(),
|
||||
0,
|
||||
&eventRef);
|
||||
if (status != noErr) {
|
||||
qDebug() << "Failed to register hotkey. Error:" << status;
|
||||
return false;
|
||||
} else {
|
||||
this->hotkeyRefs.insert(shortcut, eventRef);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool QHotkeyPrivateMac::unregisterShortcut(QHotkey::NativeShortcut shortcut)
|
||||
{
|
||||
EventHotKeyRef eventRef = QHotkeyPrivateMac::hotkeyRefs.value(shortcut);
|
||||
OSStatus status = UnregisterEventHotKey(eventRef);
|
||||
if (status != noErr) {
|
||||
qDebug() << "Failed to unregister hotkey. Error:" << status;
|
||||
return false;
|
||||
} else {
|
||||
this->hotkeyRefs.remove(shortcut);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
OSStatus QHotkeyPrivateMac::hotkeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *data)
|
||||
{
|
||||
Q_UNUSED(nextHandler);
|
||||
Q_UNUSED(data);
|
||||
|
||||
if (GetEventClass(event) == kEventClassKeyboard &&
|
||||
GetEventKind(event) == kEventHotKeyPressed) {
|
||||
EventHotKeyID hkeyID;
|
||||
GetEventParameter(event,
|
||||
kEventParamDirectObject,
|
||||
typeEventHotKeyID,
|
||||
NULL,
|
||||
sizeof(EventHotKeyID),
|
||||
NULL,
|
||||
&hkeyID);
|
||||
hotkeyPrivate->activateShortcut(QHotkey::NativeShortcut(hkeyID.signature, hkeyID.id));
|
||||
}
|
||||
|
||||
return noErr;
|
||||
}
|
||||
49
third/3rd_qhotkey/qhotkey_p.h
Normal file
49
third/3rd_qhotkey/qhotkey_p.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef QHOTKEY_P_H
|
||||
#define QHOTKEY_P_H
|
||||
|
||||
#include "qhotkey.h"
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QMultiHash>
|
||||
#include <QMutex>
|
||||
#include <QGlobalStatic>
|
||||
|
||||
class QHOTKEY_SHARED_EXPORT QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public: QHotkeyPrivate();//singleton!!!
|
||||
~QHotkeyPrivate();
|
||||
|
||||
static QHotkeyPrivate *instance();
|
||||
|
||||
QHotkey::NativeShortcut nativeShortcut(Qt::Key keycode, Qt::KeyboardModifiers modifiers);
|
||||
|
||||
bool addShortcut(QHotkey *hotkey);
|
||||
bool removeShortcut(QHotkey *hotkey);
|
||||
|
||||
protected:
|
||||
void activateShortcut(QHotkey::NativeShortcut shortcut);
|
||||
|
||||
virtual quint32 nativeKeycode(Qt::Key keycode, bool &ok) = 0;//platform implement
|
||||
virtual quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) = 0;//platform implement
|
||||
|
||||
virtual bool registerShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement
|
||||
virtual bool unregisterShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement
|
||||
|
||||
private:
|
||||
QMultiHash<QHotkey::NativeShortcut, QHotkey *> shortcuts;
|
||||
|
||||
Q_INVOKABLE bool addShortcutInvoked(QHotkey *hotkey);
|
||||
Q_INVOKABLE bool removeShortcutInvoked(QHotkey *hotkey);
|
||||
Q_INVOKABLE QHotkey::NativeShortcut nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers);
|
||||
};
|
||||
|
||||
#define NATIVE_INSTANCE(ClassName) \
|
||||
Q_GLOBAL_STATIC(ClassName, hotkeyPrivate) \
|
||||
\
|
||||
QHotkeyPrivate *QHotkeyPrivate::instance()\
|
||||
{\
|
||||
return hotkeyPrivate;\
|
||||
}
|
||||
|
||||
#endif // QHOTKEY_P_H
|
||||
274
third/3rd_qhotkey/qhotkey_win.cpp
Normal file
274
third/3rd_qhotkey/qhotkey_win.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
#include "qhotkey.h"
|
||||
#include "qhotkey_p.h"
|
||||
#include <qt_windows.h>
|
||||
#include <QDebug>
|
||||
|
||||
#define HKEY_ID(nativeShortcut) (((nativeShortcut.key ^ (nativeShortcut.modifier << 8)) & 0x0FFF) | 0x7000)
|
||||
|
||||
class QHotkeyPrivateWin : public QHotkeyPrivate
|
||||
{
|
||||
public:
|
||||
// QAbstractNativeEventFilter interface
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
|
||||
|
||||
protected:
|
||||
// QHotkeyPrivate interface
|
||||
quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE;
|
||||
quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE;
|
||||
bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
|
||||
bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
static QString formatWinError(DWORD winError);
|
||||
};
|
||||
NATIVE_INSTANCE(QHotkeyPrivateWin)
|
||||
|
||||
bool QHotkeyPrivateWin::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(result);
|
||||
|
||||
MSG *msg = static_cast<MSG *>(message);
|
||||
if (msg->message == WM_HOTKEY) {
|
||||
this->activateShortcut(QHotkey::NativeShortcut(HIWORD(msg->lParam), LOWORD(msg->lParam)));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode, bool &ok)
|
||||
{
|
||||
ok = true;
|
||||
if (keycode <= 0xFFFF) { //Try to obtain the key from it's "character"
|
||||
const SHORT vKey = VkKeyScanW(keycode);
|
||||
if (vKey > -1) {
|
||||
return LOBYTE(vKey);
|
||||
}
|
||||
}
|
||||
|
||||
//find key from switch/case --> Only finds a very small subset of keys
|
||||
switch (keycode) {
|
||||
case Qt::Key_Escape:
|
||||
return VK_ESCAPE;
|
||||
case Qt::Key_Tab:
|
||||
case Qt::Key_Backtab:
|
||||
return VK_TAB;
|
||||
case Qt::Key_Backspace:
|
||||
return VK_BACK;
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
return VK_RETURN;
|
||||
case Qt::Key_Insert:
|
||||
return VK_INSERT;
|
||||
case Qt::Key_Delete:
|
||||
return VK_DELETE;
|
||||
case Qt::Key_Pause:
|
||||
return VK_PAUSE;
|
||||
case Qt::Key_Print:
|
||||
return VK_PRINT;
|
||||
case Qt::Key_Clear:
|
||||
return VK_CLEAR;
|
||||
case Qt::Key_Home:
|
||||
return VK_HOME;
|
||||
case Qt::Key_End:
|
||||
return VK_END;
|
||||
case Qt::Key_Left:
|
||||
return VK_LEFT;
|
||||
case Qt::Key_Up:
|
||||
return VK_UP;
|
||||
case Qt::Key_Right:
|
||||
return VK_RIGHT;
|
||||
case Qt::Key_Down:
|
||||
return VK_DOWN;
|
||||
case Qt::Key_PageUp:
|
||||
return VK_PRIOR;
|
||||
case Qt::Key_PageDown:
|
||||
return VK_NEXT;
|
||||
case Qt::Key_CapsLock:
|
||||
return VK_CAPITAL;
|
||||
case Qt::Key_NumLock:
|
||||
return VK_NUMLOCK;
|
||||
case Qt::Key_ScrollLock:
|
||||
return VK_SCROLL;
|
||||
|
||||
case Qt::Key_F1:
|
||||
return VK_F1;
|
||||
case Qt::Key_F2:
|
||||
return VK_F2;
|
||||
case Qt::Key_F3:
|
||||
return VK_F3;
|
||||
case Qt::Key_F4:
|
||||
return VK_F4;
|
||||
case Qt::Key_F5:
|
||||
return VK_F5;
|
||||
case Qt::Key_F6:
|
||||
return VK_F6;
|
||||
case Qt::Key_F7:
|
||||
return VK_F7;
|
||||
case Qt::Key_F8:
|
||||
return VK_F8;
|
||||
case Qt::Key_F9:
|
||||
return VK_F9;
|
||||
case Qt::Key_F10:
|
||||
return VK_F10;
|
||||
case Qt::Key_F11:
|
||||
return VK_F11;
|
||||
case Qt::Key_F12:
|
||||
return VK_F12;
|
||||
case Qt::Key_F13:
|
||||
return VK_F13;
|
||||
case Qt::Key_F14:
|
||||
return VK_F14;
|
||||
case Qt::Key_F15:
|
||||
return VK_F15;
|
||||
case Qt::Key_F16:
|
||||
return VK_F16;
|
||||
case Qt::Key_F17:
|
||||
return VK_F17;
|
||||
case Qt::Key_F18:
|
||||
return VK_F18;
|
||||
case Qt::Key_F19:
|
||||
return VK_F19;
|
||||
case Qt::Key_F20:
|
||||
return VK_F20;
|
||||
case Qt::Key_F21:
|
||||
return VK_F21;
|
||||
case Qt::Key_F22:
|
||||
return VK_F22;
|
||||
case Qt::Key_F23:
|
||||
return VK_F23;
|
||||
case Qt::Key_F24:
|
||||
return VK_F24;
|
||||
|
||||
case Qt::Key_Menu:
|
||||
return VK_APPS;
|
||||
case Qt::Key_Help:
|
||||
return VK_HELP;
|
||||
case Qt::Key_MediaNext:
|
||||
return VK_MEDIA_NEXT_TRACK;
|
||||
case Qt::Key_MediaPrevious:
|
||||
return VK_MEDIA_PREV_TRACK;
|
||||
case Qt::Key_MediaPlay:
|
||||
return VK_MEDIA_PLAY_PAUSE;
|
||||
case Qt::Key_MediaStop:
|
||||
return VK_MEDIA_STOP;
|
||||
case Qt::Key_VolumeDown:
|
||||
return VK_VOLUME_DOWN;
|
||||
case Qt::Key_VolumeUp:
|
||||
return VK_VOLUME_UP;
|
||||
case Qt::Key_VolumeMute:
|
||||
return VK_VOLUME_MUTE;
|
||||
case Qt::Key_Mode_switch:
|
||||
return VK_MODECHANGE;
|
||||
case Qt::Key_Select:
|
||||
return VK_SELECT;
|
||||
case Qt::Key_Printer:
|
||||
return VK_PRINT;
|
||||
case Qt::Key_Execute:
|
||||
return VK_EXECUTE;
|
||||
case Qt::Key_Sleep:
|
||||
return VK_SLEEP;
|
||||
case Qt::Key_Period:
|
||||
return VK_DECIMAL;
|
||||
case Qt::Key_Play:
|
||||
return VK_PLAY;
|
||||
case Qt::Key_Cancel:
|
||||
return VK_CANCEL;
|
||||
|
||||
case Qt::Key_Forward:
|
||||
return VK_BROWSER_FORWARD;
|
||||
case Qt::Key_Refresh:
|
||||
return VK_BROWSER_REFRESH;
|
||||
case Qt::Key_Stop:
|
||||
return VK_BROWSER_STOP;
|
||||
case Qt::Key_Search:
|
||||
return VK_BROWSER_SEARCH;
|
||||
case Qt::Key_Favorites:
|
||||
return VK_BROWSER_FAVORITES;
|
||||
case Qt::Key_HomePage:
|
||||
return VK_BROWSER_HOME;
|
||||
|
||||
case Qt::Key_LaunchMail:
|
||||
return VK_LAUNCH_MAIL;
|
||||
case Qt::Key_LaunchMedia:
|
||||
return VK_LAUNCH_MEDIA_SELECT;
|
||||
case Qt::Key_Launch0:
|
||||
return VK_LAUNCH_APP1;
|
||||
case Qt::Key_Launch1:
|
||||
return VK_LAUNCH_APP2;
|
||||
|
||||
case Qt::Key_Massyo:
|
||||
return VK_OEM_FJ_MASSHOU;
|
||||
case Qt::Key_Touroku:
|
||||
return VK_OEM_FJ_TOUROKU;
|
||||
|
||||
default:
|
||||
ok = false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
quint32 QHotkeyPrivateWin::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok)
|
||||
{
|
||||
quint32 nMods = 0;
|
||||
if (modifiers & Qt::ShiftModifier) {
|
||||
nMods |= MOD_SHIFT;
|
||||
}
|
||||
if (modifiers & Qt::ControlModifier) {
|
||||
nMods |= MOD_CONTROL;
|
||||
}
|
||||
if (modifiers & Qt::AltModifier) {
|
||||
nMods |= MOD_ALT;
|
||||
}
|
||||
if (modifiers & Qt::MetaModifier) {
|
||||
nMods |= MOD_WIN;
|
||||
}
|
||||
ok = true;
|
||||
return nMods;
|
||||
}
|
||||
|
||||
bool QHotkeyPrivateWin::registerShortcut(QHotkey::NativeShortcut shortcut)
|
||||
{
|
||||
BOOL ok = RegisterHotKey(NULL,
|
||||
HKEY_ID(shortcut),
|
||||
shortcut.modifier,
|
||||
shortcut.key);
|
||||
if (ok) {
|
||||
return true;
|
||||
} else {
|
||||
qDebug() << "Failed to register hotkey. Error:"
|
||||
<< qPrintable(QHotkeyPrivateWin::formatWinError(::GetLastError()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool QHotkeyPrivateWin::unregisterShortcut(QHotkey::NativeShortcut shortcut)
|
||||
{
|
||||
BOOL ok = UnregisterHotKey(NULL, HKEY_ID(shortcut));
|
||||
if (ok) {
|
||||
return true;
|
||||
} else {
|
||||
qDebug() << "Failed to unregister hotkey. Error:"
|
||||
<< qPrintable(QHotkeyPrivateWin::formatWinError(::GetLastError()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QString QHotkeyPrivateWin::formatWinError(DWORD winError)
|
||||
{
|
||||
wchar_t *buffer = NULL;
|
||||
DWORD num = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
winError,
|
||||
0,
|
||||
(LPWSTR)&buffer,
|
||||
0,
|
||||
NULL);
|
||||
if (buffer) {
|
||||
QString res = QString::fromWCharArray(buffer, num);
|
||||
LocalFree(buffer);
|
||||
return res;
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
201
third/3rd_qhotkey/qhotkey_x11.cpp
Normal file
201
third/3rd_qhotkey/qhotkey_x11.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
#include "qhotkey.h"
|
||||
#include "qhotkey_p.h"
|
||||
#include <QDebug>
|
||||
#include <QX11Info>
|
||||
#include <QThreadStorage>
|
||||
#include <X11/Xlib.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
class QHotkeyPrivateX11 : public QHotkeyPrivate
|
||||
{
|
||||
public:
|
||||
// QAbstractNativeEventFilter interface
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
|
||||
|
||||
protected:
|
||||
// QHotkeyPrivate interface
|
||||
quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE;
|
||||
quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE;
|
||||
bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
|
||||
bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
static const QVector<quint32> specialModifiers;
|
||||
static const quint32 validModsMask;
|
||||
|
||||
static QString formatX11Error(Display *display, int errorCode);
|
||||
|
||||
class HotkeyErrorHandler
|
||||
{
|
||||
public:
|
||||
HotkeyErrorHandler();
|
||||
~HotkeyErrorHandler();
|
||||
|
||||
static bool hasError;
|
||||
static QString errorString;
|
||||
|
||||
private:
|
||||
XErrorHandler prevHandler;
|
||||
|
||||
static int handleError(Display *display, XErrorEvent *error);
|
||||
};
|
||||
};
|
||||
NATIVE_INSTANCE(QHotkeyPrivateX11)
|
||||
|
||||
const QVector<quint32> QHotkeyPrivateX11::specialModifiers = {0, Mod2Mask, LockMask, (Mod2Mask | LockMask)};
|
||||
const quint32 QHotkeyPrivateX11::validModsMask = ShiftMask | ControlMask | Mod1Mask | Mod4Mask;
|
||||
|
||||
bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(result);
|
||||
|
||||
xcb_generic_event_t *genericEvent = static_cast<xcb_generic_event_t *>(message);
|
||||
if (genericEvent->response_type == XCB_KEY_PRESS) {
|
||||
xcb_key_press_event_t *keyEvent = static_cast<xcb_key_press_event_t *>(message);
|
||||
this->activateShortcut(QHotkey::NativeShortcut(keyEvent->detail, keyEvent->state & QHotkeyPrivateX11::validModsMask));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode, bool &ok)
|
||||
{
|
||||
KeySym keysym = XStringToKeysym(QKeySequence(keycode).toString(QKeySequence::NativeText).toLatin1().constData());
|
||||
if (keysym == NoSymbol) {
|
||||
//not found -> just use the key
|
||||
if (keycode <= 0xFFFF) {
|
||||
keysym = keycode;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Display *display = QX11Info::display();
|
||||
if (display) {
|
||||
auto res = XKeysymToKeycode(QX11Info::display(), keysym);
|
||||
if (res != 0) {
|
||||
ok = true;
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok)
|
||||
{
|
||||
quint32 nMods = 0;
|
||||
if (modifiers & Qt::ShiftModifier) {
|
||||
nMods |= ShiftMask;
|
||||
}
|
||||
if (modifiers & Qt::ControlModifier) {
|
||||
nMods |= ControlMask;
|
||||
}
|
||||
if (modifiers & Qt::AltModifier) {
|
||||
nMods |= Mod1Mask;
|
||||
}
|
||||
if (modifiers & Qt::MetaModifier) {
|
||||
nMods |= Mod4Mask;
|
||||
}
|
||||
ok = true;
|
||||
return nMods;
|
||||
}
|
||||
|
||||
bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut)
|
||||
{
|
||||
Display *display = QX11Info::display();
|
||||
if (!display) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HotkeyErrorHandler errorHandler;
|
||||
foreach (quint32 specialMod, QHotkeyPrivateX11::specialModifiers) {
|
||||
XGrabKey(display,
|
||||
shortcut.key,
|
||||
shortcut.modifier | specialMod,
|
||||
DefaultRootWindow(display),
|
||||
True,
|
||||
GrabModeAsync,
|
||||
GrabModeAsync);
|
||||
}
|
||||
XSync(display, False);
|
||||
|
||||
if (errorHandler.hasError) {
|
||||
qDebug() << "Failed to register hotkey. Error:" << qPrintable(errorHandler.errorString);
|
||||
this->unregisterShortcut(shortcut);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut)
|
||||
{
|
||||
Display *display = QX11Info::display();
|
||||
if (!display) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HotkeyErrorHandler errorHandler;
|
||||
foreach (quint32 specialMod, QHotkeyPrivateX11::specialModifiers) {
|
||||
XUngrabKey(display,
|
||||
shortcut.key,
|
||||
shortcut.modifier | specialMod,
|
||||
DefaultRootWindow(display));
|
||||
}
|
||||
XSync(display, False);
|
||||
|
||||
if (errorHandler.hasError) {
|
||||
qDebug() << "Failed to unregister hotkey. Error:" << qPrintable(errorHandler.errorString);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
QString QHotkeyPrivateX11::formatX11Error(Display *display, int errorCode)
|
||||
{
|
||||
char errStr[256];
|
||||
XGetErrorText(display, errorCode, errStr, 256);
|
||||
return QString::fromLatin1(errStr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- QHotkeyPrivateX11::HotkeyErrorHandler implementation ----------
|
||||
|
||||
bool QHotkeyPrivateX11::HotkeyErrorHandler::hasError = false;
|
||||
QString QHotkeyPrivateX11::HotkeyErrorHandler::errorString;
|
||||
|
||||
QHotkeyPrivateX11::HotkeyErrorHandler::HotkeyErrorHandler()
|
||||
{
|
||||
prevHandler = XSetErrorHandler(&HotkeyErrorHandler::handleError);
|
||||
}
|
||||
|
||||
QHotkeyPrivateX11::HotkeyErrorHandler::~HotkeyErrorHandler()
|
||||
{
|
||||
XSetErrorHandler(prevHandler);
|
||||
hasError = false;
|
||||
errorString.clear();
|
||||
}
|
||||
|
||||
int QHotkeyPrivateX11::HotkeyErrorHandler::handleError(Display *display, XErrorEvent *error)
|
||||
{
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_GCC("-Wimplicit-fallthrough")
|
||||
switch (error->error_code) {
|
||||
case BadAccess:
|
||||
case BadValue:
|
||||
case BadWindow:
|
||||
if (error->request_code == 33 || //grab key
|
||||
error->request_code == 34) {// ungrab key
|
||||
hasError = true;
|
||||
errorString = QHotkeyPrivateX11::formatX11Error(display, error->error_code);
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
}
|
||||
198
third/3rd_qwt/3rd_qwt.pri
Normal file
198
third/3rd_qwt/3rd_qwt.pri
Normal file
@@ -0,0 +1,198 @@
|
||||
QT += core gui
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport concurrent
|
||||
|
||||
DEFINES += QWT_NO_SVG QWT_NO_OPENGL
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/qwt.h \
|
||||
$$PWD/qwt_abstract_legend.h \
|
||||
$$PWD/qwt_abstract_scale.h \
|
||||
$$PWD/qwt_abstract_scale_draw.h \
|
||||
$$PWD/qwt_abstract_slider.h \
|
||||
$$PWD/qwt_analog_clock.h \
|
||||
$$PWD/qwt_arrow_button.h \
|
||||
$$PWD/qwt_clipper.h \
|
||||
$$PWD/qwt_color_map.h \
|
||||
$$PWD/qwt_column_symbol.h \
|
||||
$$PWD/qwt_compass.h \
|
||||
$$PWD/qwt_compass_rose.h \
|
||||
$$PWD/qwt_compat.h \
|
||||
$$PWD/qwt_counter.h \
|
||||
$$PWD/qwt_curve_fitter.h \
|
||||
$$PWD/qwt_date.h \
|
||||
$$PWD/qwt_date_scale_draw.h \
|
||||
$$PWD/qwt_date_scale_engine.h \
|
||||
$$PWD/qwt_dial.h \
|
||||
$$PWD/qwt_dial_needle.h \
|
||||
$$PWD/qwt_dyngrid_layout.h \
|
||||
$$PWD/qwt_event_pattern.h \
|
||||
$$PWD/qwt_global.h \
|
||||
$$PWD/qwt_graphic.h \
|
||||
$$PWD/qwt_interval.h \
|
||||
$$PWD/qwt_interval_symbol.h \
|
||||
$$PWD/qwt_knob.h \
|
||||
$$PWD/qwt_legend.h \
|
||||
$$PWD/qwt_legend_data.h \
|
||||
$$PWD/qwt_legend_label.h \
|
||||
$$PWD/qwt_magnifier.h \
|
||||
$$PWD/qwt_math.h \
|
||||
$$PWD/qwt_matrix_raster_data.h \
|
||||
$$PWD/qwt_null_paintdevice.h \
|
||||
$$PWD/qwt_painter.h \
|
||||
$$PWD/qwt_painter_command.h \
|
||||
$$PWD/qwt_panner.h \
|
||||
$$PWD/qwt_picker.h \
|
||||
$$PWD/qwt_picker_machine.h \
|
||||
$$PWD/qwt_pixel_matrix.h \
|
||||
$$PWD/qwt_plot.h \
|
||||
$$PWD/qwt_plot_abstract_barchart.h \
|
||||
$$PWD/qwt_plot_barchart.h \
|
||||
$$PWD/qwt_plot_canvas.h \
|
||||
$$PWD/qwt_plot_curve.h \
|
||||
$$PWD/qwt_plot_dict.h \
|
||||
$$PWD/qwt_plot_directpainter.h \
|
||||
$$PWD/qwt_plot_grid.h \
|
||||
$$PWD/qwt_plot_histogram.h \
|
||||
$$PWD/qwt_plot_intervalcurve.h \
|
||||
$$PWD/qwt_plot_item.h \
|
||||
$$PWD/qwt_plot_layout.h \
|
||||
$$PWD/qwt_plot_legenditem.h \
|
||||
$$PWD/qwt_plot_magnifier.h \
|
||||
$$PWD/qwt_plot_marker.h \
|
||||
$$PWD/qwt_plot_multi_barchart.h \
|
||||
$$PWD/qwt_plot_panner.h \
|
||||
$$PWD/qwt_plot_picker.h \
|
||||
$$PWD/qwt_plot_rasteritem.h \
|
||||
$$PWD/qwt_plot_renderer.h \
|
||||
$$PWD/qwt_plot_rescaler.h \
|
||||
$$PWD/qwt_plot_scaleitem.h \
|
||||
$$PWD/qwt_plot_seriesitem.h \
|
||||
$$PWD/qwt_plot_shapeitem.h \
|
||||
$$PWD/qwt_plot_spectrocurve.h \
|
||||
$$PWD/qwt_plot_spectrogram.h \
|
||||
$$PWD/qwt_plot_textlabel.h \
|
||||
$$PWD/qwt_plot_tradingcurve.h \
|
||||
$$PWD/qwt_plot_zoneitem.h \
|
||||
$$PWD/qwt_plot_zoomer.h \
|
||||
$$PWD/qwt_point_3d.h \
|
||||
$$PWD/qwt_point_data.h \
|
||||
$$PWD/qwt_point_mapper.h \
|
||||
$$PWD/qwt_point_polar.h \
|
||||
$$PWD/qwt_raster_data.h \
|
||||
$$PWD/qwt_round_scale_draw.h \
|
||||
$$PWD/qwt_samples.h \
|
||||
$$PWD/qwt_sampling_thread.h \
|
||||
$$PWD/qwt_scale_div.h \
|
||||
$$PWD/qwt_scale_draw.h \
|
||||
$$PWD/qwt_scale_engine.h \
|
||||
$$PWD/qwt_scale_map.h \
|
||||
$$PWD/qwt_scale_widget.h \
|
||||
$$PWD/qwt_series_data.h \
|
||||
$$PWD/qwt_series_store.h \
|
||||
$$PWD/qwt_slider.h \
|
||||
$$PWD/qwt_spline.h \
|
||||
$$PWD/qwt_symbol.h \
|
||||
$$PWD/qwt_system_clock.h \
|
||||
$$PWD/qwt_text.h \
|
||||
$$PWD/qwt_text_engine.h \
|
||||
$$PWD/qwt_text_label.h \
|
||||
$$PWD/qwt_thermo.h \
|
||||
$$PWD/qwt_transform.h \
|
||||
$$PWD/qwt_wheel.h \
|
||||
$$PWD/qwt_widget_overlay.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/qwt_abstract_legend.cpp \
|
||||
$$PWD/qwt_abstract_scale.cpp \
|
||||
$$PWD/qwt_abstract_scale_draw.cpp \
|
||||
$$PWD/qwt_abstract_slider.cpp \
|
||||
$$PWD/qwt_analog_clock.cpp \
|
||||
$$PWD/qwt_arrow_button.cpp \
|
||||
$$PWD/qwt_clipper.cpp \
|
||||
$$PWD/qwt_color_map.cpp \
|
||||
$$PWD/qwt_column_symbol.cpp \
|
||||
$$PWD/qwt_compass.cpp \
|
||||
$$PWD/qwt_compass_rose.cpp \
|
||||
$$PWD/qwt_counter.cpp \
|
||||
$$PWD/qwt_curve_fitter.cpp \
|
||||
$$PWD/qwt_date.cpp \
|
||||
$$PWD/qwt_date_scale_draw.cpp \
|
||||
$$PWD/qwt_date_scale_engine.cpp \
|
||||
$$PWD/qwt_dial.cpp \
|
||||
$$PWD/qwt_dial_needle.cpp \
|
||||
$$PWD/qwt_dyngrid_layout.cpp \
|
||||
$$PWD/qwt_event_pattern.cpp \
|
||||
$$PWD/qwt_graphic.cpp \
|
||||
$$PWD/qwt_interval.cpp \
|
||||
$$PWD/qwt_interval_symbol.cpp \
|
||||
$$PWD/qwt_knob.cpp \
|
||||
$$PWD/qwt_legend.cpp \
|
||||
$$PWD/qwt_legend_data.cpp \
|
||||
$$PWD/qwt_legend_label.cpp \
|
||||
$$PWD/qwt_magnifier.cpp \
|
||||
$$PWD/qwt_math.cpp \
|
||||
$$PWD/qwt_matrix_raster_data.cpp \
|
||||
$$PWD/qwt_null_paintdevice.cpp \
|
||||
$$PWD/qwt_painter.cpp \
|
||||
$$PWD/qwt_painter_command.cpp \
|
||||
$$PWD/qwt_panner.cpp \
|
||||
$$PWD/qwt_picker.cpp \
|
||||
$$PWD/qwt_picker_machine.cpp \
|
||||
$$PWD/qwt_pixel_matrix.cpp \
|
||||
$$PWD/qwt_plot.cpp \
|
||||
$$PWD/qwt_plot_abstract_barchart.cpp \
|
||||
$$PWD/qwt_plot_axis.cpp \
|
||||
$$PWD/qwt_plot_barchart.cpp \
|
||||
$$PWD/qwt_plot_canvas.cpp \
|
||||
$$PWD/qwt_plot_curve.cpp \
|
||||
$$PWD/qwt_plot_dict.cpp \
|
||||
$$PWD/qwt_plot_directpainter.cpp \
|
||||
$$PWD/qwt_plot_grid.cpp \
|
||||
$$PWD/qwt_plot_histogram.cpp \
|
||||
$$PWD/qwt_plot_intervalcurve.cpp \
|
||||
$$PWD/qwt_plot_item.cpp \
|
||||
$$PWD/qwt_plot_layout.cpp \
|
||||
$$PWD/qwt_plot_legenditem.cpp \
|
||||
$$PWD/qwt_plot_magnifier.cpp \
|
||||
$$PWD/qwt_plot_marker.cpp \
|
||||
$$PWD/qwt_plot_multi_barchart.cpp \
|
||||
$$PWD/qwt_plot_panner.cpp \
|
||||
$$PWD/qwt_plot_picker.cpp \
|
||||
$$PWD/qwt_plot_rasteritem.cpp \
|
||||
$$PWD/qwt_plot_renderer.cpp \
|
||||
$$PWD/qwt_plot_rescaler.cpp \
|
||||
$$PWD/qwt_plot_scaleitem.cpp \
|
||||
$$PWD/qwt_plot_seriesitem.cpp \
|
||||
$$PWD/qwt_plot_shapeitem.cpp \
|
||||
$$PWD/qwt_plot_spectrocurve.cpp \
|
||||
$$PWD/qwt_plot_spectrogram.cpp \
|
||||
$$PWD/qwt_plot_textlabel.cpp \
|
||||
$$PWD/qwt_plot_tradingcurve.cpp \
|
||||
$$PWD/qwt_plot_xml.cpp \
|
||||
$$PWD/qwt_plot_zoneitem.cpp \
|
||||
$$PWD/qwt_plot_zoomer.cpp \
|
||||
$$PWD/qwt_point_3d.cpp \
|
||||
$$PWD/qwt_point_data.cpp \
|
||||
$$PWD/qwt_point_mapper.cpp \
|
||||
$$PWD/qwt_point_polar.cpp \
|
||||
$$PWD/qwt_raster_data.cpp \
|
||||
$$PWD/qwt_round_scale_draw.cpp \
|
||||
$$PWD/qwt_sampling_thread.cpp \
|
||||
$$PWD/qwt_scale_div.cpp \
|
||||
$$PWD/qwt_scale_draw.cpp \
|
||||
$$PWD/qwt_scale_engine.cpp \
|
||||
$$PWD/qwt_scale_map.cpp \
|
||||
$$PWD/qwt_scale_widget.cpp \
|
||||
$$PWD/qwt_series_data.cpp \
|
||||
$$PWD/qwt_slider.cpp \
|
||||
$$PWD/qwt_spline.cpp \
|
||||
$$PWD/qwt_symbol.cpp \
|
||||
$$PWD/qwt_system_clock.cpp \
|
||||
$$PWD/qwt_text.cpp \
|
||||
$$PWD/qwt_text_engine.cpp \
|
||||
$$PWD/qwt_text_label.cpp \
|
||||
$$PWD/qwt_thermo.cpp \
|
||||
$$PWD/qwt_transform.cpp \
|
||||
$$PWD/qwt_wheel.cpp \
|
||||
$$PWD/qwt_widget_overlay.cpp
|
||||
22
third/3rd_qwt/qwt.h
Normal file
22
third/3rd_qwt/qwt.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_H
|
||||
#define QWT_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
|
||||
/*!
|
||||
Some constants for use within Qwt.
|
||||
*/
|
||||
namespace Qwt
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
38
third/3rd_qwt/qwt_abstract_legend.cpp
Normal file
38
third/3rd_qwt/qwt_abstract_legend.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/* -*- 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_abstract_legend.h"
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
\param parent Parent widget
|
||||
*/
|
||||
QwtAbstractLegend::QwtAbstractLegend( QWidget *parent ):
|
||||
QFrame( parent )
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtAbstractLegend::~QwtAbstractLegend()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Return the extent, that is needed for elements to scroll
|
||||
the legend ( usually scrollbars ),
|
||||
|
||||
\param orientation Orientation
|
||||
\return Extent of the corresponding scroll element
|
||||
*/
|
||||
int QwtAbstractLegend::scrollExtent( Qt::Orientation orientation ) const
|
||||
{
|
||||
Q_UNUSED( orientation );
|
||||
return 0;
|
||||
}
|
||||
71
third/3rd_qwt/qwt_abstract_legend.h
Normal file
71
third/3rd_qwt/qwt_abstract_legend.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_ABSTRACT_LEGEND_H
|
||||
#define QWT_ABSTRACT_LEGEND_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_legend_data.h"
|
||||
#include <qframe.h>
|
||||
#include <qlist.h>
|
||||
|
||||
class QVariant;
|
||||
|
||||
/*!
|
||||
\brief Abstract base class for legend widgets
|
||||
|
||||
Legends, that need to be under control of the QwtPlot layout system
|
||||
need to be derived from QwtAbstractLegend.
|
||||
|
||||
\note Other type of legends can be implemented by connecting to
|
||||
the QwtPlot::legendDataChanged() signal. But as these legends
|
||||
are unknown to the plot layout system the layout code
|
||||
( on screen and for QwtPlotRenderer ) need to be organized
|
||||
in application code.
|
||||
|
||||
\sa QwtLegend
|
||||
*/
|
||||
class QWT_EXPORT QwtAbstractLegend : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QwtAbstractLegend( QWidget *parent = NULL );
|
||||
virtual ~QwtAbstractLegend();
|
||||
|
||||
/*!
|
||||
Render the legend into a given rectangle.
|
||||
|
||||
\param painter Painter
|
||||
\param rect Bounding rectangle
|
||||
\param fillBackground When true, fill rect with the widget background
|
||||
|
||||
\sa renderLegend() is used by QwtPlotRenderer
|
||||
*/
|
||||
virtual void renderLegend( QPainter *painter,
|
||||
const QRectF &rect, bool fillBackground ) const = 0;
|
||||
|
||||
//! \return True, when no plot item is inserted
|
||||
virtual bool isEmpty() const = 0;
|
||||
|
||||
virtual int scrollExtent( Qt::Orientation ) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
/*!
|
||||
\brief Update the entries for a plot item
|
||||
|
||||
\param itemInfo Info about an item
|
||||
\param data List of legend entry attributes for the item
|
||||
*/
|
||||
virtual void updateLegend( const QVariant &itemInfo,
|
||||
const QList<QwtLegendData> &data ) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
449
third/3rd_qwt/qwt_abstract_scale.cpp
Normal file
449
third/3rd_qwt/qwt_abstract_scale.cpp
Normal file
@@ -0,0 +1,449 @@
|
||||
/* -*- 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_abstract_scale.h"
|
||||
#include "qwt_scale_engine.h"
|
||||
#include "qwt_scale_draw.h"
|
||||
#include "qwt_scale_div.h"
|
||||
#include "qwt_scale_map.h"
|
||||
#include "qwt_interval.h"
|
||||
|
||||
class QwtAbstractScale::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
maxMajor( 5 ),
|
||||
maxMinor( 3 ),
|
||||
stepSize( 0.0 )
|
||||
{
|
||||
scaleEngine = new QwtLinearScaleEngine();
|
||||
scaleDraw = new QwtScaleDraw();
|
||||
}
|
||||
|
||||
~PrivateData()
|
||||
{
|
||||
delete scaleEngine;
|
||||
delete scaleDraw;
|
||||
}
|
||||
|
||||
QwtScaleEngine *scaleEngine;
|
||||
QwtAbstractScaleDraw *scaleDraw;
|
||||
|
||||
int maxMajor;
|
||||
int maxMinor;
|
||||
double stepSize;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
\param parent Parent widget
|
||||
|
||||
Creates a default QwtScaleDraw and a QwtLinearScaleEngine.
|
||||
The initial scale boundaries are set to [ 0.0, 100.0 ]
|
||||
|
||||
The scaleStepSize() is initialized to 0.0, scaleMaxMajor() to 5
|
||||
and scaleMaxMajor to 3.
|
||||
*/
|
||||
|
||||
QwtAbstractScale::QwtAbstractScale( QWidget *parent ):
|
||||
QWidget( parent )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
rescale( 0.0, 100.0, d_data->stepSize );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtAbstractScale::~QwtAbstractScale()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the lower bound of the scale
|
||||
|
||||
\param value Lower bound
|
||||
|
||||
\sa lowerBound(), setScale(), setUpperBound()
|
||||
\note For inverted scales the lower bound
|
||||
is greater than the upper bound
|
||||
*/
|
||||
void QwtAbstractScale::setLowerBound( double value )
|
||||
{
|
||||
setScale( value, upperBound() );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Lower bound of the scale
|
||||
\sa setLowerBound(), setScale(), upperBound()
|
||||
*/
|
||||
double QwtAbstractScale::lowerBound() const
|
||||
{
|
||||
return d_data->scaleDraw->scaleDiv().lowerBound();
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the upper bound of the scale
|
||||
|
||||
\param value Upper bound
|
||||
|
||||
\sa upperBound(), setScale(), setLowerBound()
|
||||
\note For inverted scales the lower bound
|
||||
is greater than the upper bound
|
||||
*/
|
||||
void QwtAbstractScale::setUpperBound( double value )
|
||||
{
|
||||
setScale( lowerBound(), value );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Upper bound of the scale
|
||||
\sa setUpperBound(), setScale(), lowerBound()
|
||||
*/
|
||||
double QwtAbstractScale::upperBound() const
|
||||
{
|
||||
return d_data->scaleDraw->scaleDiv().upperBound();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Specify a scale.
|
||||
|
||||
Define a scale by an interval
|
||||
|
||||
The ticks are calculated using scaleMaxMinor(),
|
||||
scaleMaxMajor() and scaleStepSize().
|
||||
|
||||
\param lowerBound lower limit of the scale interval
|
||||
\param upperBound upper limit of the scale interval
|
||||
|
||||
\note For inverted scales the lower bound
|
||||
is greater than the upper bound
|
||||
*/
|
||||
void QwtAbstractScale::setScale( double lowerBound, double upperBound )
|
||||
{
|
||||
rescale( lowerBound, upperBound, d_data->stepSize );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Specify a scale.
|
||||
|
||||
Define a scale by an interval
|
||||
|
||||
The ticks are calculated using scaleMaxMinor(),
|
||||
scaleMaxMajor() and scaleStepSize().
|
||||
|
||||
\param interval Interval
|
||||
*/
|
||||
void QwtAbstractScale::setScale( const QwtInterval &interval )
|
||||
{
|
||||
setScale( interval.minValue(), interval.maxValue() );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Specify a scale.
|
||||
|
||||
scaleMaxMinor(), scaleMaxMajor() and scaleStepSize() and have no effect.
|
||||
|
||||
\param scaleDiv Scale division
|
||||
\sa setAutoScale()
|
||||
*/
|
||||
void QwtAbstractScale::setScale( const QwtScaleDiv &scaleDiv )
|
||||
{
|
||||
if ( scaleDiv != d_data->scaleDraw->scaleDiv() )
|
||||
{
|
||||
#if 1
|
||||
if ( d_data->scaleEngine )
|
||||
{
|
||||
d_data->scaleDraw->setTransformation(
|
||||
d_data->scaleEngine->transformation() );
|
||||
}
|
||||
#endif
|
||||
|
||||
d_data->scaleDraw->setScaleDiv( scaleDiv );
|
||||
|
||||
scaleChange();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the maximum number of major tick intervals.
|
||||
|
||||
The scale's major ticks are calculated automatically such that
|
||||
the number of major intervals does not exceed ticks.
|
||||
|
||||
The default value is 5.
|
||||
|
||||
\param ticks Maximal number of major ticks.
|
||||
|
||||
\sa scaleMaxMajor(), setScaleMaxMinor(),
|
||||
setScaleStepSize(), QwtScaleEngine::divideInterval()
|
||||
*/
|
||||
void QwtAbstractScale::setScaleMaxMajor( int ticks )
|
||||
{
|
||||
if ( ticks != d_data->maxMajor )
|
||||
{
|
||||
d_data->maxMajor = ticks;
|
||||
updateScaleDraw();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Maximal number of major tick intervals
|
||||
\sa setScaleMaxMajor(), scaleMaxMinor()
|
||||
*/
|
||||
int QwtAbstractScale::scaleMaxMajor() const
|
||||
{
|
||||
return d_data->maxMajor;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the maximum number of minor tick intervals
|
||||
|
||||
The scale's minor ticks are calculated automatically such that
|
||||
the number of minor intervals does not exceed ticks.
|
||||
The default value is 3.
|
||||
|
||||
\param ticks Maximal number of minor ticks.
|
||||
|
||||
\sa scaleMaxMajor(), setScaleMaxMinor(),
|
||||
setScaleStepSize(), QwtScaleEngine::divideInterval()
|
||||
*/
|
||||
void QwtAbstractScale::setScaleMaxMinor( int ticks )
|
||||
{
|
||||
if ( ticks != d_data->maxMinor )
|
||||
{
|
||||
d_data->maxMinor = ticks;
|
||||
updateScaleDraw();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Maximal number of minor tick intervals
|
||||
\sa setScaleMaxMinor(), scaleMaxMajor()
|
||||
*/
|
||||
int QwtAbstractScale::scaleMaxMinor() const
|
||||
{
|
||||
return d_data->maxMinor;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the step size used for calculating a scale division
|
||||
|
||||
The step size is hint for calculating the intervals for
|
||||
the major ticks of the scale. A value of 0.0 is interpreted
|
||||
as no hint.
|
||||
|
||||
\param stepSize Hint for the step size of the scale
|
||||
|
||||
\sa scaleStepSize(), QwtScaleEngine::divideScale()
|
||||
|
||||
\note Position and distance between the major ticks also
|
||||
depends on scaleMaxMajor().
|
||||
*/
|
||||
void QwtAbstractScale::setScaleStepSize( double stepSize )
|
||||
{
|
||||
if ( stepSize != d_data->stepSize )
|
||||
{
|
||||
d_data->stepSize = stepSize;
|
||||
updateScaleDraw();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Hint for the step size of the scale
|
||||
\sa setScaleStepSize(), QwtScaleEngine::divideScale()
|
||||
*/
|
||||
double QwtAbstractScale::scaleStepSize() const
|
||||
{
|
||||
return d_data->stepSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set a scale draw
|
||||
|
||||
scaleDraw has to be created with new and will be deleted in
|
||||
the destructor or the next call of setAbstractScaleDraw().
|
||||
|
||||
\sa abstractScaleDraw()
|
||||
*/
|
||||
void QwtAbstractScale::setAbstractScaleDraw( QwtAbstractScaleDraw *scaleDraw )
|
||||
{
|
||||
if ( scaleDraw == NULL || scaleDraw == d_data->scaleDraw )
|
||||
return;
|
||||
|
||||
if ( d_data->scaleDraw != NULL )
|
||||
scaleDraw->setScaleDiv( d_data->scaleDraw->scaleDiv() );
|
||||
|
||||
delete d_data->scaleDraw;
|
||||
d_data->scaleDraw = scaleDraw;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Scale draw
|
||||
\sa setAbstractScaleDraw()
|
||||
*/
|
||||
QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw()
|
||||
{
|
||||
return d_data->scaleDraw;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Scale draw
|
||||
\sa setAbstractScaleDraw()
|
||||
*/
|
||||
const QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() const
|
||||
{
|
||||
return d_data->scaleDraw;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set a scale engine
|
||||
|
||||
The scale engine is responsible for calculating the scale division
|
||||
and provides a transformation between scale and widget coordinates.
|
||||
|
||||
scaleEngine has to be created with new and will be deleted in
|
||||
the destructor or the next call of setScaleEngine.
|
||||
*/
|
||||
void QwtAbstractScale::setScaleEngine( QwtScaleEngine *scaleEngine )
|
||||
{
|
||||
if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine )
|
||||
{
|
||||
delete d_data->scaleEngine;
|
||||
d_data->scaleEngine = scaleEngine;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Scale engine
|
||||
\sa setScaleEngine()
|
||||
*/
|
||||
const QwtScaleEngine *QwtAbstractScale::scaleEngine() const
|
||||
{
|
||||
return d_data->scaleEngine;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Scale engine
|
||||
\sa setScaleEngine()
|
||||
*/
|
||||
QwtScaleEngine *QwtAbstractScale::scaleEngine()
|
||||
{
|
||||
return d_data->scaleEngine;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Scale boundaries and positions of the ticks
|
||||
|
||||
The scale division might have been assigned explicitly
|
||||
or calculated implicitly by rescale().
|
||||
*/
|
||||
const QwtScaleDiv &QwtAbstractScale::scaleDiv() const
|
||||
{
|
||||
return d_data->scaleDraw->scaleDiv();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Map to translate between scale and widget coordinates
|
||||
*/
|
||||
const QwtScaleMap &QwtAbstractScale::scaleMap() const
|
||||
{
|
||||
return d_data->scaleDraw->scaleMap();
|
||||
}
|
||||
|
||||
/*!
|
||||
Translate a scale value into a widget coordinate
|
||||
|
||||
\param value Scale value
|
||||
\return Corresponding widget coordinate for value
|
||||
\sa scaleMap(), invTransform()
|
||||
*/
|
||||
int QwtAbstractScale::transform( double value ) const
|
||||
{
|
||||
return qRound( d_data->scaleDraw->scaleMap().transform( value ) );
|
||||
}
|
||||
|
||||
/*!
|
||||
Translate a widget coordinate into a scale value
|
||||
|
||||
\param value Widget coordinate
|
||||
\return Corresponding scale coordinate for value
|
||||
\sa scaleMap(), transform()
|
||||
*/
|
||||
double QwtAbstractScale::invTransform( int value ) const
|
||||
{
|
||||
return d_data->scaleDraw->scaleMap().invTransform( value );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return True, when the scale is increasing in opposite direction
|
||||
to the widget coordinates
|
||||
*/
|
||||
bool QwtAbstractScale::isInverted() const
|
||||
{
|
||||
return d_data->scaleDraw->scaleMap().isInverting();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The boundary with the smaller value
|
||||
\sa maximum(), lowerBound(), upperBound()
|
||||
*/
|
||||
double QwtAbstractScale::minimum() const
|
||||
{
|
||||
return qMin( d_data->scaleDraw->scaleDiv().lowerBound(),
|
||||
d_data->scaleDraw->scaleDiv().upperBound() );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The boundary with the larger value
|
||||
\sa minimum(), lowerBound(), upperBound()
|
||||
*/
|
||||
double QwtAbstractScale::maximum() const
|
||||
{
|
||||
return qMax( d_data->scaleDraw->scaleDiv().lowerBound(),
|
||||
d_data->scaleDraw->scaleDiv().upperBound() );
|
||||
}
|
||||
|
||||
//! Notify changed scale
|
||||
void QwtAbstractScale::scaleChange()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Recalculate the scale division and update the scale.
|
||||
|
||||
\param lowerBound Lower limit of the scale interval
|
||||
\param upperBound Upper limit of the scale interval
|
||||
\param stepSize Major step size
|
||||
|
||||
\sa scaleChange()
|
||||
*/
|
||||
void QwtAbstractScale::rescale(
|
||||
double lowerBound, double upperBound, double stepSize )
|
||||
{
|
||||
const QwtScaleDiv scaleDiv = d_data->scaleEngine->divideScale(
|
||||
lowerBound, upperBound, d_data->maxMajor, d_data->maxMinor, stepSize );
|
||||
|
||||
if ( scaleDiv != d_data->scaleDraw->scaleDiv() )
|
||||
{
|
||||
#if 1
|
||||
d_data->scaleDraw->setTransformation(
|
||||
d_data->scaleEngine->transformation() );
|
||||
#endif
|
||||
|
||||
d_data->scaleDraw->setScaleDiv( scaleDiv );
|
||||
scaleChange();
|
||||
}
|
||||
}
|
||||
|
||||
void QwtAbstractScale::updateScaleDraw()
|
||||
{
|
||||
rescale( d_data->scaleDraw->scaleDiv().lowerBound(),
|
||||
d_data->scaleDraw->scaleDiv().upperBound(), d_data->stepSize );
|
||||
}
|
||||
105
third/3rd_qwt/qwt_abstract_scale.h
Normal file
105
third/3rd_qwt/qwt_abstract_scale.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_ABSTRACT_SCALE_H
|
||||
#define QWT_ABSTRACT_SCALE_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qwidget.h>
|
||||
|
||||
class QwtScaleEngine;
|
||||
class QwtAbstractScaleDraw;
|
||||
class QwtScaleDiv;
|
||||
class QwtScaleMap;
|
||||
class QwtInterval;
|
||||
|
||||
/*!
|
||||
\brief An abstract base class for widgets having a scale
|
||||
|
||||
The scale of an QwtAbstractScale is determined by a QwtScaleDiv
|
||||
definition, that contains the boundaries and the ticks of the scale.
|
||||
The scale is painted using a QwtScaleDraw object.
|
||||
|
||||
The scale division might be assigned explicitly - but usually
|
||||
it is calculated from the boundaries using a QwtScaleEngine.
|
||||
|
||||
The scale engine also decides the type of transformation of the scale
|
||||
( linear, logarithmic ... ).
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtAbstractScale: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( double lowerBound READ lowerBound WRITE setLowerBound )
|
||||
Q_PROPERTY( double upperBound READ upperBound WRITE setUpperBound )
|
||||
|
||||
Q_PROPERTY( int scaleMaxMajor READ scaleMaxMajor WRITE setScaleMaxMajor )
|
||||
Q_PROPERTY( int scaleMaxMinor READ scaleMaxMinor WRITE setScaleMaxMinor )
|
||||
|
||||
Q_PROPERTY( double scaleStepSize READ scaleStepSize WRITE setScaleStepSize )
|
||||
|
||||
public:
|
||||
QwtAbstractScale( QWidget *parent = NULL );
|
||||
virtual ~QwtAbstractScale();
|
||||
|
||||
void setScale( double lowerBound, double upperBound );
|
||||
void setScale( const QwtInterval & );
|
||||
void setScale( const QwtScaleDiv & );
|
||||
|
||||
const QwtScaleDiv& scaleDiv() const;
|
||||
|
||||
void setLowerBound( double value );
|
||||
double lowerBound() const;
|
||||
|
||||
void setUpperBound( double value );
|
||||
double upperBound() const;
|
||||
|
||||
void setScaleStepSize( double stepSize );
|
||||
double scaleStepSize() const;
|
||||
|
||||
void setScaleMaxMajor( int ticks );
|
||||
int scaleMaxMinor() const;
|
||||
|
||||
void setScaleMaxMinor( int ticks );
|
||||
int scaleMaxMajor() const;
|
||||
|
||||
void setScaleEngine( QwtScaleEngine * );
|
||||
const QwtScaleEngine *scaleEngine() const;
|
||||
QwtScaleEngine *scaleEngine();
|
||||
|
||||
int transform( double ) const;
|
||||
double invTransform( int ) const;
|
||||
|
||||
bool isInverted() const;
|
||||
|
||||
double minimum() const;
|
||||
double maximum() const;
|
||||
|
||||
const QwtScaleMap &scaleMap() const;
|
||||
|
||||
protected:
|
||||
void rescale( double lowerBound,
|
||||
double upperBound, double stepSize );
|
||||
|
||||
void setAbstractScaleDraw( QwtAbstractScaleDraw * );
|
||||
|
||||
const QwtAbstractScaleDraw *abstractScaleDraw() const;
|
||||
QwtAbstractScaleDraw *abstractScaleDraw();
|
||||
|
||||
virtual void scaleChange();
|
||||
|
||||
private:
|
||||
void updateScaleDraw();
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
419
third/3rd_qwt/qwt_abstract_scale_draw.cpp
Normal file
419
third/3rd_qwt/qwt_abstract_scale_draw.cpp
Normal file
@@ -0,0 +1,419 @@
|
||||
/* -*- 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_abstract_scale_draw.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_text.h"
|
||||
#include "qwt_painter.h"
|
||||
#include "qwt_scale_map.h"
|
||||
#include <qpainter.h>
|
||||
#include <qpalette.h>
|
||||
#include <qmap.h>
|
||||
#include <qlocale.h>
|
||||
|
||||
class QwtAbstractScaleDraw::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
spacing( 4.0 ),
|
||||
penWidth( 0 ),
|
||||
minExtent( 0.0 )
|
||||
{
|
||||
components = QwtAbstractScaleDraw::Backbone
|
||||
| QwtAbstractScaleDraw::Ticks
|
||||
| QwtAbstractScaleDraw::Labels;
|
||||
|
||||
tickLength[QwtScaleDiv::MinorTick] = 4.0;
|
||||
tickLength[QwtScaleDiv::MediumTick] = 6.0;
|
||||
tickLength[QwtScaleDiv::MajorTick] = 8.0;
|
||||
}
|
||||
|
||||
ScaleComponents components;
|
||||
|
||||
QwtScaleMap map;
|
||||
QwtScaleDiv scaleDiv;
|
||||
|
||||
double spacing;
|
||||
double tickLength[QwtScaleDiv::NTickTypes];
|
||||
int penWidth;
|
||||
|
||||
double minExtent;
|
||||
|
||||
QMap<double, QwtText> labelCache;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
|
||||
The range of the scale is initialized to [0, 100],
|
||||
The spacing (distance between ticks and labels) is
|
||||
set to 4, the tick lengths are set to 4,6 and 8 pixels
|
||||
*/
|
||||
QwtAbstractScaleDraw::QwtAbstractScaleDraw()
|
||||
{
|
||||
d_data = new QwtAbstractScaleDraw::PrivateData;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtAbstractScaleDraw::~QwtAbstractScaleDraw()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
En/Disable a component of the scale
|
||||
|
||||
\param component Scale component
|
||||
\param enable On/Off
|
||||
|
||||
\sa hasComponent()
|
||||
*/
|
||||
void QwtAbstractScaleDraw::enableComponent(
|
||||
ScaleComponent component, bool enable )
|
||||
{
|
||||
if ( enable )
|
||||
d_data->components |= component;
|
||||
else
|
||||
d_data->components &= ~component;
|
||||
}
|
||||
|
||||
/*!
|
||||
Check if a component is enabled
|
||||
|
||||
\param component Component type
|
||||
\return true, when component is enabled
|
||||
\sa enableComponent()
|
||||
*/
|
||||
bool QwtAbstractScaleDraw::hasComponent( ScaleComponent component ) const
|
||||
{
|
||||
return ( d_data->components & component );
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the scale division
|
||||
\param scaleDiv New scale division
|
||||
*/
|
||||
void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &scaleDiv )
|
||||
{
|
||||
d_data->scaleDiv = scaleDiv;
|
||||
d_data->map.setScaleInterval( scaleDiv.lowerBound(), scaleDiv.upperBound() );
|
||||
d_data->labelCache.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the transformation of the scale
|
||||
\param transformation New scale transformation
|
||||
*/
|
||||
void QwtAbstractScaleDraw::setTransformation(
|
||||
QwtTransform *transformation )
|
||||
{
|
||||
d_data->map.setTransformation( transformation );
|
||||
}
|
||||
|
||||
//! \return Map how to translate between scale and pixel values
|
||||
const QwtScaleMap &QwtAbstractScaleDraw::scaleMap() const
|
||||
{
|
||||
return d_data->map;
|
||||
}
|
||||
|
||||
//! \return Map how to translate between scale and pixel values
|
||||
QwtScaleMap &QwtAbstractScaleDraw::scaleMap()
|
||||
{
|
||||
return d_data->map;
|
||||
}
|
||||
|
||||
//! \return scale division
|
||||
const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const
|
||||
{
|
||||
return d_data->scaleDiv;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Specify the width of the scale pen
|
||||
\param width Pen width
|
||||
\sa penWidth()
|
||||
*/
|
||||
void QwtAbstractScaleDraw::setPenWidth( int width )
|
||||
{
|
||||
if ( width < 0 )
|
||||
width = 0;
|
||||
|
||||
if ( width != d_data->penWidth )
|
||||
d_data->penWidth = width;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Scale pen width
|
||||
\sa setPenWidth()
|
||||
*/
|
||||
int QwtAbstractScaleDraw::penWidth() const
|
||||
{
|
||||
return d_data->penWidth;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Draw the scale
|
||||
|
||||
\param painter The painter
|
||||
|
||||
\param palette Palette, text color is used for the labels,
|
||||
foreground color for ticks and backbone
|
||||
*/
|
||||
void QwtAbstractScaleDraw::draw( QPainter *painter,
|
||||
const QPalette& palette ) const
|
||||
{
|
||||
painter->save();
|
||||
|
||||
QPen pen = painter->pen();
|
||||
pen.setWidth( d_data->penWidth );
|
||||
pen.setCosmetic( false );
|
||||
painter->setPen( pen );
|
||||
|
||||
if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style
|
||||
|
||||
const QList<double> &majorTicks =
|
||||
d_data->scaleDiv.ticks( QwtScaleDiv::MajorTick );
|
||||
|
||||
for ( int i = 0; i < majorTicks.count(); i++ )
|
||||
{
|
||||
const double v = majorTicks[i];
|
||||
if ( d_data->scaleDiv.contains( v ) )
|
||||
drawLabel( painter, v );
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
pen = painter->pen();
|
||||
pen.setColor( palette.color( QPalette::WindowText ) );
|
||||
pen.setCapStyle( Qt::FlatCap );
|
||||
|
||||
painter->setPen( pen );
|
||||
|
||||
for ( int tickType = QwtScaleDiv::MinorTick;
|
||||
tickType < QwtScaleDiv::NTickTypes; tickType++ )
|
||||
{
|
||||
const double tickLen = d_data->tickLength[tickType];
|
||||
if ( tickLen <= 0.0 )
|
||||
continue;
|
||||
|
||||
const QList<double> &ticks = d_data->scaleDiv.ticks( tickType );
|
||||
for ( int i = 0; i < ticks.count(); i++ )
|
||||
{
|
||||
const double v = ticks[i];
|
||||
if ( d_data->scaleDiv.contains( v ) )
|
||||
drawTick( painter, v, tickLen );
|
||||
}
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
pen = painter->pen();
|
||||
pen.setColor( palette.color( QPalette::WindowText ) );
|
||||
pen.setCapStyle( Qt::FlatCap );
|
||||
|
||||
painter->setPen( pen );
|
||||
|
||||
drawBackbone( painter );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the spacing between tick and labels
|
||||
|
||||
The spacing is the distance between ticks and labels.
|
||||
The default spacing is 4 pixels.
|
||||
|
||||
\param spacing Spacing
|
||||
|
||||
\sa spacing()
|
||||
*/
|
||||
void QwtAbstractScaleDraw::setSpacing( double spacing )
|
||||
{
|
||||
if ( spacing < 0 )
|
||||
spacing = 0;
|
||||
|
||||
d_data->spacing = spacing;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Get the spacing
|
||||
|
||||
The spacing is the distance between ticks and labels.
|
||||
The default spacing is 4 pixels.
|
||||
|
||||
\return Spacing
|
||||
\sa setSpacing()
|
||||
*/
|
||||
double QwtAbstractScaleDraw::spacing() const
|
||||
{
|
||||
return d_data->spacing;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set a minimum for the extent
|
||||
|
||||
The extent is calculated from the components of the
|
||||
scale draw. In situations, where the labels are
|
||||
changing and the layout depends on the extent (f.e scrolling
|
||||
a scale), setting an upper limit as minimum extent will
|
||||
avoid jumps of the layout.
|
||||
|
||||
\param minExtent Minimum extent
|
||||
|
||||
\sa extent(), minimumExtent()
|
||||
*/
|
||||
void QwtAbstractScaleDraw::setMinimumExtent( double minExtent )
|
||||
{
|
||||
if ( minExtent < 0.0 )
|
||||
minExtent = 0.0;
|
||||
|
||||
d_data->minExtent = minExtent;
|
||||
}
|
||||
|
||||
/*!
|
||||
Get the minimum extent
|
||||
\return Minimum extent
|
||||
\sa extent(), setMinimumExtent()
|
||||
*/
|
||||
double QwtAbstractScaleDraw::minimumExtent() const
|
||||
{
|
||||
return d_data->minExtent;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the length of the ticks
|
||||
|
||||
\param tickType Tick type
|
||||
\param length New length
|
||||
|
||||
\warning the length is limited to [0..1000]
|
||||
*/
|
||||
void QwtAbstractScaleDraw::setTickLength(
|
||||
QwtScaleDiv::TickType tickType, double length )
|
||||
{
|
||||
if ( tickType < QwtScaleDiv::MinorTick ||
|
||||
tickType > QwtScaleDiv::MajorTick )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( length < 0.0 )
|
||||
length = 0.0;
|
||||
|
||||
const double maxTickLen = 1000.0;
|
||||
if ( length > maxTickLen )
|
||||
length = maxTickLen;
|
||||
|
||||
d_data->tickLength[tickType] = length;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Length of the ticks
|
||||
\sa setTickLength(), maxTickLength()
|
||||
*/
|
||||
double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const
|
||||
{
|
||||
if ( tickType < QwtScaleDiv::MinorTick ||
|
||||
tickType > QwtScaleDiv::MajorTick )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return d_data->tickLength[tickType];
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Length of the longest tick
|
||||
|
||||
Useful for layout calculations
|
||||
\sa tickLength(), setTickLength()
|
||||
*/
|
||||
double QwtAbstractScaleDraw::maxTickLength() const
|
||||
{
|
||||
double length = 0.0;
|
||||
for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
|
||||
length = qMax( length, d_data->tickLength[i] );
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Convert a value into its representing label
|
||||
|
||||
The value is converted to a plain text using
|
||||
QLocale().toString(value).
|
||||
This method is often overloaded by applications to have individual
|
||||
labels.
|
||||
|
||||
\param value Value
|
||||
\return Label string.
|
||||
*/
|
||||
QwtText QwtAbstractScaleDraw::label( double value ) const
|
||||
{
|
||||
return QLocale().toString( value );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Convert a value into its representing label and cache it.
|
||||
|
||||
The conversion between value and label is called very often
|
||||
in the layout and painting code. Unfortunately the
|
||||
calculation of the label sizes might be slow (really slow
|
||||
for rich text in Qt4), so it's necessary to cache the labels.
|
||||
|
||||
\param font Font
|
||||
\param value Value
|
||||
|
||||
\return Tick label
|
||||
*/
|
||||
const QwtText &QwtAbstractScaleDraw::tickLabel(
|
||||
const QFont &font, double value ) const
|
||||
{
|
||||
QMap<double, QwtText>::const_iterator it1 = d_data->labelCache.constFind( value );
|
||||
if ( it1 != d_data->labelCache.constEnd() )
|
||||
return *it1;
|
||||
|
||||
QwtText lbl = label( value );
|
||||
lbl.setRenderFlags( 0 );
|
||||
lbl.setLayoutAttribute( QwtText::MinimumLayout );
|
||||
|
||||
( void )lbl.textSize( font ); // initialize the internal cache
|
||||
|
||||
QMap<double, QwtText>::iterator it2 = d_data->labelCache.insert( value, lbl );
|
||||
return *it2;
|
||||
}
|
||||
|
||||
/*!
|
||||
Invalidate the cache used by tickLabel()
|
||||
|
||||
The cache is invalidated, when a new QwtScaleDiv is set. If
|
||||
the labels need to be changed. while the same QwtScaleDiv is set,
|
||||
invalidateCache() needs to be called manually.
|
||||
*/
|
||||
void QwtAbstractScaleDraw::invalidateCache()
|
||||
{
|
||||
d_data->labelCache.clear();
|
||||
}
|
||||
141
third/3rd_qwt/qwt_abstract_scale_draw.h
Normal file
141
third/3rd_qwt/qwt_abstract_scale_draw.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_ABSTRACT_SCALE_DRAW_H
|
||||
#define QWT_ABSTRACT_SCALE_DRAW_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_scale_div.h"
|
||||
#include "qwt_text.h"
|
||||
|
||||
class QPalette;
|
||||
class QPainter;
|
||||
class QFont;
|
||||
class QwtTransform;
|
||||
class QwtScaleMap;
|
||||
|
||||
/*!
|
||||
\brief A abstract base class for drawing scales
|
||||
|
||||
QwtAbstractScaleDraw can be used to draw linear or logarithmic scales.
|
||||
|
||||
After a scale division has been specified as a QwtScaleDiv object
|
||||
using setScaleDiv(), the scale can be drawn with the draw() member.
|
||||
*/
|
||||
class QWT_EXPORT QwtAbstractScaleDraw
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
Components of a scale
|
||||
\sa enableComponent(), hasComponent
|
||||
*/
|
||||
enum ScaleComponent
|
||||
{
|
||||
//! Backbone = the line where the ticks are located
|
||||
Backbone = 0x01,
|
||||
|
||||
//! Ticks
|
||||
Ticks = 0x02,
|
||||
|
||||
//! Labels
|
||||
Labels = 0x04
|
||||
};
|
||||
|
||||
//! Scale components
|
||||
typedef QFlags<ScaleComponent> ScaleComponents;
|
||||
|
||||
QwtAbstractScaleDraw();
|
||||
virtual ~QwtAbstractScaleDraw();
|
||||
|
||||
void setScaleDiv( const QwtScaleDiv & );
|
||||
const QwtScaleDiv& scaleDiv() const;
|
||||
|
||||
void setTransformation( QwtTransform * );
|
||||
const QwtScaleMap &scaleMap() const;
|
||||
QwtScaleMap &scaleMap();
|
||||
|
||||
void enableComponent( ScaleComponent, bool enable = true );
|
||||
bool hasComponent( ScaleComponent ) const;
|
||||
|
||||
void setTickLength( QwtScaleDiv::TickType, double length );
|
||||
double tickLength( QwtScaleDiv::TickType ) const;
|
||||
double maxTickLength() const;
|
||||
|
||||
void setSpacing( double );
|
||||
double spacing() const;
|
||||
|
||||
void setPenWidth( int width );
|
||||
int penWidth() const;
|
||||
|
||||
virtual void draw( QPainter *, const QPalette & ) const;
|
||||
|
||||
virtual QwtText label( double ) const;
|
||||
|
||||
/*!
|
||||
Calculate the extent
|
||||
|
||||
The extent is the distance from the baseline to the outermost
|
||||
pixel of the scale draw in opposite to its orientation.
|
||||
It is at least minimumExtent() pixels.
|
||||
|
||||
\param font Font used for drawing the tick labels
|
||||
\return Number of pixels
|
||||
|
||||
\sa setMinimumExtent(), minimumExtent()
|
||||
*/
|
||||
virtual double extent( const QFont &font ) const = 0;
|
||||
|
||||
void setMinimumExtent( double );
|
||||
double minimumExtent() const;
|
||||
|
||||
protected:
|
||||
/*!
|
||||
Draw a tick
|
||||
|
||||
\param painter Painter
|
||||
\param value Value of the tick
|
||||
\param len Length of the tick
|
||||
|
||||
\sa drawBackbone(), drawLabel()
|
||||
*/
|
||||
virtual void drawTick( QPainter *painter, double value, double len ) const = 0;
|
||||
|
||||
/*!
|
||||
Draws the baseline of the scale
|
||||
\param painter Painter
|
||||
|
||||
\sa drawTick(), drawLabel()
|
||||
*/
|
||||
virtual void drawBackbone( QPainter *painter ) const = 0;
|
||||
|
||||
/*!
|
||||
Draws the label for a major scale tick
|
||||
|
||||
\param painter Painter
|
||||
\param value Value
|
||||
|
||||
\sa drawTick(), drawBackbone()
|
||||
*/
|
||||
virtual void drawLabel( QPainter *painter, double value ) const = 0;
|
||||
|
||||
void invalidateCache();
|
||||
const QwtText &tickLabel( const QFont &, double value ) const;
|
||||
|
||||
private:
|
||||
QwtAbstractScaleDraw( const QwtAbstractScaleDraw & );
|
||||
QwtAbstractScaleDraw &operator=( const QwtAbstractScaleDraw & );
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QwtAbstractScaleDraw::ScaleComponents )
|
||||
|
||||
#endif
|
||||
822
third/3rd_qwt/qwt_abstract_slider.cpp
Normal file
822
third/3rd_qwt/qwt_abstract_slider.cpp
Normal file
@@ -0,0 +1,822 @@
|
||||
/* -*- 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_abstract_slider.h"
|
||||
#include "qwt_abstract_scale_draw.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_scale_map.h"
|
||||
#include <qevent.h>
|
||||
|
||||
#if QT_VERSION < 0x040601
|
||||
#define qFabs(x) ::fabs(x)
|
||||
#endif
|
||||
|
||||
static double qwtAlignToScaleDiv(
|
||||
const QwtAbstractSlider *slider, double value )
|
||||
{
|
||||
const QwtScaleDiv &sd = slider->scaleDiv();
|
||||
|
||||
const int tValue = slider->transform( value );
|
||||
|
||||
if ( tValue == slider->transform( sd.lowerBound() ) )
|
||||
return sd.lowerBound();
|
||||
|
||||
if ( tValue == slider->transform( sd.upperBound() ) )
|
||||
return sd.upperBound();
|
||||
|
||||
for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
|
||||
{
|
||||
const QList<double> ticks = sd.ticks( i );
|
||||
for ( int j = 0; j < ticks.size(); j++ )
|
||||
{
|
||||
if ( slider->transform( ticks[ j ] ) == tValue )
|
||||
return ticks[ j ];
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
class QwtAbstractSlider::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
isScrolling( false ),
|
||||
isTracking( true ),
|
||||
pendingValueChanged( false ),
|
||||
readOnly( false ),
|
||||
totalSteps( 100 ),
|
||||
singleSteps( 1 ),
|
||||
pageSteps( 10 ),
|
||||
stepAlignment( true ),
|
||||
isValid( false ),
|
||||
value( 0.0 ),
|
||||
wrapping( false ),
|
||||
invertedControls( false )
|
||||
{
|
||||
}
|
||||
|
||||
bool isScrolling;
|
||||
bool isTracking;
|
||||
bool pendingValueChanged;
|
||||
|
||||
bool readOnly;
|
||||
|
||||
uint totalSteps;
|
||||
uint singleSteps;
|
||||
uint pageSteps;
|
||||
bool stepAlignment;
|
||||
|
||||
bool isValid;
|
||||
double value;
|
||||
|
||||
bool wrapping;
|
||||
bool invertedControls;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
|
||||
The scale is initialized to [0.0, 100.0], the
|
||||
number of steps is set to 100 with 1 and 10 and single
|
||||
an page step sizes. Step alignment is enabled.
|
||||
|
||||
The initial value is invalid.
|
||||
|
||||
\param parent Parent widget
|
||||
*/
|
||||
QwtAbstractSlider::QwtAbstractSlider( QWidget *parent ):
|
||||
QwtAbstractScale( parent )
|
||||
{
|
||||
d_data = new QwtAbstractSlider::PrivateData;
|
||||
|
||||
setScale( 0.0, 100.0 );
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtAbstractSlider::~QwtAbstractSlider()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the value to be valid/invalid
|
||||
|
||||
\param on When true, the value is invalidated
|
||||
|
||||
\sa setValue()
|
||||
*/
|
||||
void QwtAbstractSlider::setValid( bool on )
|
||||
{
|
||||
if ( on != d_data->isValid )
|
||||
{
|
||||
d_data->isValid = on;
|
||||
sliderChange();
|
||||
|
||||
Q_EMIT valueChanged( d_data->value );
|
||||
}
|
||||
}
|
||||
|
||||
//! \return True, when the value is invalid
|
||||
bool QwtAbstractSlider::isValid() const
|
||||
{
|
||||
return d_data->isValid;
|
||||
}
|
||||
|
||||
/*!
|
||||
En/Disable read only mode
|
||||
|
||||
In read only mode the slider can't be controlled by mouse
|
||||
or keyboard.
|
||||
|
||||
\param on Enables in case of true
|
||||
\sa isReadOnly()
|
||||
|
||||
\warning The focus policy is set to Qt::StrongFocus or Qt::NoFocus
|
||||
*/
|
||||
void QwtAbstractSlider::setReadOnly( bool on )
|
||||
{
|
||||
if ( d_data->readOnly != on )
|
||||
{
|
||||
d_data->readOnly = on;
|
||||
setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus );
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
In read only mode the slider can't be controlled by mouse
|
||||
or keyboard.
|
||||
|
||||
\return true if read only
|
||||
\sa setReadOnly()
|
||||
*/
|
||||
bool QwtAbstractSlider::isReadOnly() const
|
||||
{
|
||||
return d_data->readOnly;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Enables or disables tracking.
|
||||
|
||||
If tracking is enabled, the slider emits the valueChanged()
|
||||
signal while the movable part of the slider is being dragged.
|
||||
If tracking is disabled, the slider emits the valueChanged() signal
|
||||
only when the user releases the slider.
|
||||
|
||||
Tracking is enabled by default.
|
||||
\param on \c true (enable) or \c false (disable) tracking.
|
||||
|
||||
\sa isTracking(), sliderMoved()
|
||||
*/
|
||||
void QwtAbstractSlider::setTracking( bool on )
|
||||
{
|
||||
d_data->isTracking = on;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return True, when tracking has been enabled
|
||||
\sa setTracking()
|
||||
*/
|
||||
bool QwtAbstractSlider::isTracking() const
|
||||
{
|
||||
return d_data->isTracking;
|
||||
}
|
||||
|
||||
/*!
|
||||
Mouse press event handler
|
||||
\param event Mouse event
|
||||
*/
|
||||
void QwtAbstractSlider::mousePressEvent( QMouseEvent *event )
|
||||
{
|
||||
if ( isReadOnly() )
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !d_data->isValid || lowerBound() == upperBound() )
|
||||
return;
|
||||
|
||||
d_data->isScrolling = isScrollPosition( event->pos() );
|
||||
|
||||
if ( d_data->isScrolling )
|
||||
{
|
||||
d_data->pendingValueChanged = false;
|
||||
|
||||
Q_EMIT sliderPressed();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Mouse Move Event handler
|
||||
\param event Mouse event
|
||||
*/
|
||||
void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *event )
|
||||
{
|
||||
if ( isReadOnly() )
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( d_data->isValid && d_data->isScrolling )
|
||||
{
|
||||
double value = scrolledTo( event->pos() );
|
||||
if ( value != d_data->value )
|
||||
{
|
||||
value = boundedValue( value );
|
||||
|
||||
if ( d_data->stepAlignment )
|
||||
{
|
||||
value = alignedValue( value );
|
||||
}
|
||||
else
|
||||
{
|
||||
value = qwtAlignToScaleDiv( this, value );
|
||||
}
|
||||
|
||||
if ( value != d_data->value )
|
||||
{
|
||||
d_data->value = value;
|
||||
|
||||
sliderChange();
|
||||
|
||||
Q_EMIT sliderMoved( d_data->value );
|
||||
|
||||
if ( d_data->isTracking )
|
||||
Q_EMIT valueChanged( d_data->value );
|
||||
else
|
||||
d_data->pendingValueChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Mouse Release Event handler
|
||||
\param event Mouse event
|
||||
*/
|
||||
void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *event )
|
||||
{
|
||||
if ( isReadOnly() )
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( d_data->isScrolling && d_data->isValid )
|
||||
{
|
||||
d_data->isScrolling = false;
|
||||
|
||||
if ( d_data->pendingValueChanged )
|
||||
Q_EMIT valueChanged( d_data->value );
|
||||
|
||||
Q_EMIT sliderReleased();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Wheel Event handler
|
||||
|
||||
In/decreases the value by s number of steps. The direction
|
||||
depends on the invertedControls() property.
|
||||
|
||||
When the control or shift modifier is pressed the wheel delta
|
||||
( divided by 120 ) is mapped to an increment according to
|
||||
pageSteps(). Otherwise it is mapped to singleSteps().
|
||||
|
||||
\param event Wheel event
|
||||
*/
|
||||
void QwtAbstractSlider::wheelEvent( QWheelEvent *event )
|
||||
{
|
||||
if ( isReadOnly() )
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !d_data->isValid || d_data->isScrolling )
|
||||
return;
|
||||
|
||||
int numSteps = 0;
|
||||
|
||||
if ( ( event->modifiers() & Qt::ControlModifier) ||
|
||||
( event->modifiers() & Qt::ShiftModifier ) )
|
||||
{
|
||||
// one page regardless of delta
|
||||
numSteps = d_data->pageSteps;
|
||||
if ( event->delta() < 0 )
|
||||
numSteps = -numSteps;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int numTurns = ( event->delta() / 120 );
|
||||
numSteps = numTurns * d_data->singleSteps;
|
||||
}
|
||||
|
||||
if ( d_data->invertedControls )
|
||||
numSteps = -numSteps;
|
||||
|
||||
const double value = incrementedValue( d_data->value, numSteps );
|
||||
if ( value != d_data->value )
|
||||
{
|
||||
d_data->value = value;
|
||||
sliderChange();
|
||||
|
||||
Q_EMIT sliderMoved( d_data->value );
|
||||
Q_EMIT valueChanged( d_data->value );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Handles key events
|
||||
|
||||
QwtAbstractSlider handles the following keys:
|
||||
|
||||
- Qt::Key_Left\n
|
||||
Add/Subtract singleSteps() in direction to lowerBound();
|
||||
- Qt::Key_Right\n
|
||||
Add/Subtract singleSteps() in direction to upperBound();
|
||||
- Qt::Key_Down\n
|
||||
Subtract singleSteps(), when invertedControls() is false
|
||||
- Qt::Key_Up\n
|
||||
Add singleSteps(), when invertedControls() is false
|
||||
- Qt::Key_PageDown\n
|
||||
Subtract pageSteps(), when invertedControls() is false
|
||||
- Qt::Key_PageUp\n
|
||||
Add pageSteps(), when invertedControls() is false
|
||||
- Qt::Key_Home\n
|
||||
Set the value to the minimum()
|
||||
- Qt::Key_End\n
|
||||
Set the value to the maximum()
|
||||
|
||||
\param event Key event
|
||||
\sa isReadOnly()
|
||||
*/
|
||||
void QwtAbstractSlider::keyPressEvent( QKeyEvent *event )
|
||||
{
|
||||
if ( isReadOnly() )
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !d_data->isValid || d_data->isScrolling )
|
||||
return;
|
||||
|
||||
int numSteps = 0;
|
||||
double value = d_data->value;
|
||||
|
||||
switch ( event->key() )
|
||||
{
|
||||
case Qt::Key_Left:
|
||||
{
|
||||
numSteps = -static_cast<int>( d_data->singleSteps );
|
||||
if ( isInverted() )
|
||||
numSteps = -numSteps;
|
||||
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Right:
|
||||
{
|
||||
numSteps = d_data->singleSteps;
|
||||
if ( isInverted() )
|
||||
numSteps = -numSteps;
|
||||
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Down:
|
||||
{
|
||||
numSteps = -static_cast<int>( d_data->singleSteps );
|
||||
if ( d_data->invertedControls )
|
||||
numSteps = -numSteps;
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Up:
|
||||
{
|
||||
numSteps = d_data->singleSteps;
|
||||
if ( d_data->invertedControls )
|
||||
numSteps = -numSteps;
|
||||
|
||||
break;
|
||||
}
|
||||
case Qt::Key_PageUp:
|
||||
{
|
||||
numSteps = d_data->pageSteps;
|
||||
if ( d_data->invertedControls )
|
||||
numSteps = -numSteps;
|
||||
break;
|
||||
}
|
||||
case Qt::Key_PageDown:
|
||||
{
|
||||
numSteps = -static_cast<int>( d_data->pageSteps );
|
||||
if ( d_data->invertedControls )
|
||||
numSteps = -numSteps;
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Home:
|
||||
{
|
||||
value = minimum();
|
||||
break;
|
||||
}
|
||||
case Qt::Key_End:
|
||||
{
|
||||
value = maximum();
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
{
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
if ( numSteps != 0 )
|
||||
{
|
||||
value = incrementedValue( d_data->value, numSteps );
|
||||
}
|
||||
|
||||
if ( value != d_data->value )
|
||||
{
|
||||
d_data->value = value;
|
||||
sliderChange();
|
||||
|
||||
Q_EMIT sliderMoved( d_data->value );
|
||||
Q_EMIT valueChanged( d_data->value );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the number of steps
|
||||
|
||||
The range of the slider is divided into a number of steps from
|
||||
which the value increments according to user inputs depend.
|
||||
|
||||
The default setting is 100.
|
||||
|
||||
\param stepCount Number of steps
|
||||
|
||||
\sa totalSteps(), setSingleSteps(), setPageSteps()
|
||||
*/
|
||||
void QwtAbstractSlider::setTotalSteps( uint stepCount )
|
||||
{
|
||||
d_data->totalSteps = stepCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of steps
|
||||
\sa setTotalSteps(), singleSteps(), pageSteps()
|
||||
*/
|
||||
uint QwtAbstractSlider::totalSteps() const
|
||||
{
|
||||
return d_data->totalSteps;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the number of steps for a single increment
|
||||
|
||||
The range of the slider is divided into a number of steps from
|
||||
which the value increments according to user inputs depend.
|
||||
|
||||
\param stepCount Number of steps
|
||||
|
||||
\sa singleSteps(), setTotalSteps(), setPageSteps()
|
||||
*/
|
||||
|
||||
void QwtAbstractSlider::setSingleSteps( uint stepCount )
|
||||
{
|
||||
d_data->singleSteps = stepCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of steps
|
||||
\sa setSingleSteps(), totalSteps(), pageSteps()
|
||||
*/
|
||||
uint QwtAbstractSlider::singleSteps() const
|
||||
{
|
||||
return d_data->singleSteps;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the number of steps for a page increment
|
||||
|
||||
The range of the slider is divided into a number of steps from
|
||||
which the value increments according to user inputs depend.
|
||||
|
||||
\param stepCount Number of steps
|
||||
|
||||
\sa pageSteps(), setTotalSteps(), setSingleSteps()
|
||||
*/
|
||||
|
||||
void QwtAbstractSlider::setPageSteps( uint stepCount )
|
||||
{
|
||||
d_data->pageSteps = stepCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of steps
|
||||
\sa setPageSteps(), totalSteps(), singleSteps()
|
||||
*/
|
||||
uint QwtAbstractSlider::pageSteps() const
|
||||
{
|
||||
return d_data->pageSteps;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Enable step alignment
|
||||
|
||||
When step alignment is enabled values resulting from slider
|
||||
movements are aligned to the step size.
|
||||
|
||||
\param on Enable step alignment when true
|
||||
\sa stepAlignment()
|
||||
*/
|
||||
void QwtAbstractSlider::setStepAlignment( bool on )
|
||||
{
|
||||
if ( on != d_data->stepAlignment )
|
||||
{
|
||||
d_data->stepAlignment = on;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return True, when step alignment is enabled
|
||||
\sa setStepAlignment()
|
||||
*/
|
||||
bool QwtAbstractSlider::stepAlignment() const
|
||||
{
|
||||
return d_data->stepAlignment;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the slider to the specified value
|
||||
|
||||
\param value New value
|
||||
\sa setValid(), sliderChange(), valueChanged()
|
||||
*/
|
||||
void QwtAbstractSlider::setValue( double value )
|
||||
{
|
||||
value = qBound( minimum(), value, maximum() );
|
||||
|
||||
const bool changed = ( d_data->value != value ) || !d_data->isValid;
|
||||
|
||||
d_data->value = value;
|
||||
d_data->isValid = true;
|
||||
|
||||
if ( changed )
|
||||
{
|
||||
sliderChange();
|
||||
Q_EMIT valueChanged( d_data->value );
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns the current value.
|
||||
double QwtAbstractSlider::value() const
|
||||
{
|
||||
return d_data->value;
|
||||
}
|
||||
|
||||
/*!
|
||||
If wrapping is true stepping up from upperBound() value will
|
||||
take you to the minimum() value and vice versa.
|
||||
|
||||
\param on En/Disable wrapping
|
||||
\sa wrapping()
|
||||
*/
|
||||
void QwtAbstractSlider::setWrapping( bool on )
|
||||
{
|
||||
d_data->wrapping = on;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return True, when wrapping is set
|
||||
\sa setWrapping()
|
||||
*/
|
||||
bool QwtAbstractSlider::wrapping() const
|
||||
{
|
||||
return d_data->wrapping;
|
||||
}
|
||||
|
||||
/*!
|
||||
Invert wheel and key events
|
||||
|
||||
Usually scrolling the mouse wheel "up" and using keys like page
|
||||
up will increase the slider's value towards its maximum.
|
||||
When invertedControls() is enabled the value is scrolled
|
||||
towards its minimum.
|
||||
|
||||
Inverting the controls might be f.e. useful for a vertical slider
|
||||
with an inverted scale ( decreasing from top to bottom ).
|
||||
|
||||
\param on Invert controls, when true
|
||||
|
||||
\sa invertedControls(), keyEvent(), wheelEvent()
|
||||
*/
|
||||
void QwtAbstractSlider::setInvertedControls( bool on )
|
||||
{
|
||||
d_data->invertedControls = on;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return True, when the controls are inverted
|
||||
\sa setInvertedControls()
|
||||
*/
|
||||
bool QwtAbstractSlider::invertedControls() const
|
||||
{
|
||||
return d_data->invertedControls;
|
||||
}
|
||||
|
||||
/*!
|
||||
Increment the slider
|
||||
|
||||
The step size depends on the number of totalSteps()
|
||||
|
||||
\param stepCount Number of steps
|
||||
\sa setTotalSteps(), incrementedValue()
|
||||
*/
|
||||
void QwtAbstractSlider::incrementValue( int stepCount )
|
||||
{
|
||||
const double value = incrementedValue(
|
||||
d_data->value, stepCount );
|
||||
|
||||
if ( value != d_data->value )
|
||||
{
|
||||
d_data->value = value;
|
||||
sliderChange();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Increment a value
|
||||
|
||||
\param value Value
|
||||
\param stepCount Number of steps
|
||||
|
||||
\return Incremented value
|
||||
*/
|
||||
double QwtAbstractSlider::incrementedValue(
|
||||
double value, int stepCount ) const
|
||||
{
|
||||
if ( d_data->totalSteps == 0 )
|
||||
return value;
|
||||
|
||||
const QwtTransform *transformation =
|
||||
scaleMap().transformation();
|
||||
|
||||
if ( transformation == NULL )
|
||||
{
|
||||
const double range = maximum() - minimum();
|
||||
value += stepCount * range / d_data->totalSteps;
|
||||
}
|
||||
else
|
||||
{
|
||||
QwtScaleMap map = scaleMap();
|
||||
map.setPaintInterval( 0, d_data->totalSteps );
|
||||
|
||||
// we need equidant steps according to
|
||||
// paint device coordinates
|
||||
const double range = transformation->transform( maximum() )
|
||||
- transformation->transform( minimum() );
|
||||
|
||||
const double stepSize = range / d_data->totalSteps;
|
||||
|
||||
double v = transformation->transform( value );
|
||||
|
||||
v = qRound( v / stepSize ) * stepSize;
|
||||
v += stepCount * range / d_data->totalSteps;
|
||||
|
||||
value = transformation->invTransform( v );
|
||||
}
|
||||
|
||||
value = boundedValue( value );
|
||||
|
||||
if ( d_data->stepAlignment )
|
||||
value = alignedValue( value );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
double QwtAbstractSlider::boundedValue( double value ) const
|
||||
{
|
||||
const double vmin = minimum();
|
||||
const double vmax = maximum();
|
||||
|
||||
if ( d_data->wrapping && vmin != vmax )
|
||||
{
|
||||
const int fullCircle = 360 * 16;
|
||||
|
||||
const double pd = scaleMap().pDist();
|
||||
if ( int( pd / fullCircle ) * fullCircle == pd )
|
||||
{
|
||||
// full circle scales: min and max are the same
|
||||
const double range = vmax - vmin;
|
||||
|
||||
if ( value < vmin )
|
||||
{
|
||||
value += ::ceil( ( vmin - value ) / range ) * range;
|
||||
}
|
||||
else if ( value > vmax )
|
||||
{
|
||||
value -= ::ceil( ( value - vmax ) / range ) * range;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( value < vmin )
|
||||
value = vmax;
|
||||
else if ( value > vmax )
|
||||
value = vmin;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = qBound( vmin, value, vmax );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
double QwtAbstractSlider::alignedValue( double value ) const
|
||||
{
|
||||
if ( d_data->totalSteps == 0 )
|
||||
return value;
|
||||
|
||||
double stepSize;
|
||||
|
||||
if ( scaleMap().transformation() == NULL )
|
||||
{
|
||||
stepSize = ( maximum() - minimum() ) / d_data->totalSteps;
|
||||
if ( stepSize > 0.0 )
|
||||
{
|
||||
value = lowerBound() +
|
||||
qRound( ( value - lowerBound() ) / stepSize ) * stepSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stepSize = ( scaleMap().p2() - scaleMap().p1() ) / d_data->totalSteps;
|
||||
|
||||
if ( stepSize > 0.0 )
|
||||
{
|
||||
double v = scaleMap().transform( value );
|
||||
|
||||
v = scaleMap().p1() +
|
||||
qRound( ( v - scaleMap().p1() ) / stepSize ) * stepSize;
|
||||
|
||||
value = scaleMap().invTransform( v );
|
||||
}
|
||||
}
|
||||
|
||||
if ( qAbs( stepSize ) > 1e-12 )
|
||||
{
|
||||
if ( qFuzzyCompare( value + 1.0, 1.0 ) )
|
||||
{
|
||||
// correct rounding error if value = 0
|
||||
value = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// correct rounding error at the border
|
||||
if ( qFuzzyCompare( value, upperBound() ) )
|
||||
value = upperBound();
|
||||
else if ( qFuzzyCompare( value, lowerBound() ) )
|
||||
value = lowerBound();
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*!
|
||||
Update the slider according to modifications of the scale
|
||||
*/
|
||||
void QwtAbstractSlider::scaleChange()
|
||||
{
|
||||
const double value = qBound( minimum(), d_data->value, maximum() );
|
||||
|
||||
const bool changed = ( value != d_data->value );
|
||||
if ( changed )
|
||||
{
|
||||
d_data->value = value;
|
||||
}
|
||||
|
||||
if ( d_data->isValid || changed )
|
||||
Q_EMIT valueChanged( d_data->value );
|
||||
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
|
||||
//! Calling update()
|
||||
void QwtAbstractSlider::sliderChange()
|
||||
{
|
||||
update();
|
||||
}
|
||||
167
third/3rd_qwt/qwt_abstract_slider.h
Normal file
167
third/3rd_qwt/qwt_abstract_slider.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_ABSTRACT_SLIDER_H
|
||||
#define QWT_ABSTRACT_SLIDER_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_abstract_scale.h"
|
||||
|
||||
/*!
|
||||
\brief An abstract base class for slider widgets with a scale
|
||||
|
||||
A slider widget displays a value according to a scale.
|
||||
The class is designed as a common super class for widgets like
|
||||
QwtKnob, QwtDial and QwtSlider.
|
||||
|
||||
When the slider is nor readOnly() its value can be modified
|
||||
by keyboard, mouse and wheel inputs.
|
||||
|
||||
The range of the slider is divided into a number of steps from
|
||||
which the value increments according to user inputs depend.
|
||||
Only for linear scales the number of steps correspond with
|
||||
a fixed step size.
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtAbstractSlider: public QwtAbstractScale
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( double value READ value WRITE setValue )
|
||||
|
||||
Q_PROPERTY( uint totalSteps READ totalSteps WRITE setTotalSteps )
|
||||
Q_PROPERTY( uint singleSteps READ singleSteps WRITE setSingleSteps )
|
||||
Q_PROPERTY( uint pageSteps READ pageSteps WRITE setPageSteps )
|
||||
Q_PROPERTY( bool stepAlignment READ stepAlignment WRITE setStepAlignment )
|
||||
|
||||
Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly )
|
||||
Q_PROPERTY( bool tracking READ isTracking WRITE setTracking )
|
||||
Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping )
|
||||
|
||||
Q_PROPERTY( bool invertedControls READ invertedControls WRITE setInvertedControls )
|
||||
|
||||
public:
|
||||
explicit QwtAbstractSlider( QWidget *parent = NULL );
|
||||
virtual ~QwtAbstractSlider();
|
||||
|
||||
void setValid( bool );
|
||||
bool isValid() const;
|
||||
|
||||
double value() const;
|
||||
|
||||
void setWrapping( bool );
|
||||
bool wrapping() const;
|
||||
|
||||
void setTotalSteps( uint );
|
||||
uint totalSteps() const;
|
||||
|
||||
void setSingleSteps( uint );
|
||||
uint singleSteps() const;
|
||||
|
||||
void setPageSteps( uint );
|
||||
uint pageSteps() const;
|
||||
|
||||
void setStepAlignment( bool );
|
||||
bool stepAlignment() const;
|
||||
|
||||
void setTracking( bool );
|
||||
bool isTracking() const;
|
||||
|
||||
void setReadOnly( bool );
|
||||
bool isReadOnly() const;
|
||||
|
||||
void setInvertedControls( bool );
|
||||
bool invertedControls() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setValue( double value );
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/*!
|
||||
\brief Notify a change of value.
|
||||
|
||||
When tracking is enabled (default setting),
|
||||
this signal will be emitted every time the value changes.
|
||||
|
||||
\param value New value
|
||||
|
||||
\sa setTracking(), sliderMoved()
|
||||
*/
|
||||
void valueChanged( double value );
|
||||
|
||||
/*!
|
||||
This signal is emitted when the user presses the
|
||||
movable part of the slider.
|
||||
*/
|
||||
void sliderPressed();
|
||||
|
||||
/*!
|
||||
This signal is emitted when the user releases the
|
||||
movable part of the slider.
|
||||
*/
|
||||
void sliderReleased();
|
||||
|
||||
/*!
|
||||
This signal is emitted when the user moves the
|
||||
slider with the mouse.
|
||||
|
||||
\param value New value
|
||||
|
||||
\sa valueChanged()
|
||||
*/
|
||||
void sliderMoved( double value );
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent( QMouseEvent * );
|
||||
virtual void mouseReleaseEvent( QMouseEvent * );
|
||||
virtual void mouseMoveEvent( QMouseEvent * );
|
||||
virtual void keyPressEvent( QKeyEvent * );
|
||||
virtual void wheelEvent( QWheelEvent * );
|
||||
|
||||
/*!
|
||||
\brief Determine what to do when the user presses a mouse button.
|
||||
|
||||
\param pos Mouse position
|
||||
|
||||
\retval True, when pos is a valid scroll position
|
||||
\sa scrolledTo()
|
||||
*/
|
||||
virtual bool isScrollPosition( const QPoint &pos ) const = 0;
|
||||
|
||||
/*!
|
||||
\brief Determine the value for a new position of the
|
||||
movable part of the slider
|
||||
|
||||
\param pos Mouse position
|
||||
|
||||
\return Value for the mouse position
|
||||
\sa isScrollPosition()
|
||||
*/
|
||||
virtual double scrolledTo( const QPoint &pos ) const = 0;
|
||||
|
||||
void incrementValue( int stepCount );
|
||||
|
||||
virtual void scaleChange();
|
||||
|
||||
protected:
|
||||
virtual void sliderChange();
|
||||
|
||||
double incrementedValue(
|
||||
double value, int stepCount ) const;
|
||||
|
||||
private:
|
||||
double alignedValue( double ) const;
|
||||
double boundedValue( double ) const;
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
244
third/3rd_qwt/qwt_analog_clock.cpp
Normal file
244
third/3rd_qwt/qwt_analog_clock.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
/* -*- 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_analog_clock.h"
|
||||
#include "qwt_round_scale_draw.h"
|
||||
#include <qmath.h>
|
||||
#include <qlocale.h>
|
||||
|
||||
class QwtAnalogClockScaleDraw: public QwtRoundScaleDraw
|
||||
{
|
||||
public:
|
||||
QwtAnalogClockScaleDraw()
|
||||
{
|
||||
setSpacing( 8 );
|
||||
|
||||
enableComponent( QwtAbstractScaleDraw::Backbone, false );
|
||||
|
||||
setTickLength( QwtScaleDiv::MinorTick, 2 );
|
||||
setTickLength( QwtScaleDiv::MediumTick, 4 );
|
||||
setTickLength( QwtScaleDiv::MajorTick, 8 );
|
||||
|
||||
setPenWidth( 1 );
|
||||
}
|
||||
|
||||
virtual QwtText label( double value ) const
|
||||
{
|
||||
if ( qFuzzyCompare( value + 1.0, 1.0 ) )
|
||||
value = 60.0 * 60.0 * 12.0;
|
||||
|
||||
return QLocale().toString( qRound( value / ( 60.0 * 60.0 ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
\param parent Parent widget
|
||||
*/
|
||||
QwtAnalogClock::QwtAnalogClock( QWidget *parent ):
|
||||
QwtDial( parent )
|
||||
{
|
||||
setWrapping( true );
|
||||
setReadOnly( true );
|
||||
|
||||
setOrigin( 270.0 );
|
||||
setScaleDraw( new QwtAnalogClockScaleDraw() );
|
||||
|
||||
setTotalSteps( 60 );
|
||||
|
||||
const int secondsPerHour = 60.0 * 60.0;
|
||||
|
||||
QList<double> majorTicks;
|
||||
QList<double> minorTicks;
|
||||
|
||||
for ( int i = 0; i < 12; i++ )
|
||||
{
|
||||
majorTicks += i * secondsPerHour;
|
||||
|
||||
for ( int j = 1; j < 5; j++ )
|
||||
minorTicks += i * secondsPerHour + j * secondsPerHour / 5.0;
|
||||
}
|
||||
|
||||
QwtScaleDiv scaleDiv;
|
||||
scaleDiv.setInterval( 0.0, 12.0 * secondsPerHour );
|
||||
scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks );
|
||||
scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks );
|
||||
setScale( scaleDiv );
|
||||
|
||||
QColor knobColor = palette().color( QPalette::Active, QPalette::Text );
|
||||
knobColor = knobColor.dark( 120 );
|
||||
|
||||
QColor handColor;
|
||||
int width;
|
||||
|
||||
for ( int i = 0; i < NHands; i++ )
|
||||
{
|
||||
if ( i == SecondHand )
|
||||
{
|
||||
width = 2;
|
||||
handColor = knobColor.dark( 120 );
|
||||
}
|
||||
else
|
||||
{
|
||||
width = 8;
|
||||
handColor = knobColor;
|
||||
}
|
||||
|
||||
QwtDialSimpleNeedle *hand = new QwtDialSimpleNeedle(
|
||||
QwtDialSimpleNeedle::Arrow, true, handColor, knobColor );
|
||||
hand->setWidth( width );
|
||||
|
||||
d_hand[i] = NULL;
|
||||
setHand( static_cast<Hand>( i ), hand );
|
||||
}
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtAnalogClock::~QwtAnalogClock()
|
||||
{
|
||||
for ( int i = 0; i < NHands; i++ )
|
||||
delete d_hand[i];
|
||||
}
|
||||
|
||||
/*!
|
||||
Nop method, use setHand() instead
|
||||
\sa setHand()
|
||||
*/
|
||||
void QwtAnalogClock::setNeedle( QwtDialNeedle * )
|
||||
{
|
||||
// no op
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set a clock hand
|
||||
\param hand Specifies the type of hand
|
||||
\param needle Hand
|
||||
\sa hand()
|
||||
*/
|
||||
void QwtAnalogClock::setHand( Hand hand, QwtDialNeedle *needle )
|
||||
{
|
||||
if ( hand >= 0 && hand < NHands )
|
||||
{
|
||||
delete d_hand[hand];
|
||||
d_hand[hand] = needle;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Clock hand
|
||||
\param hd Specifies the type of hand
|
||||
\sa setHand()
|
||||
*/
|
||||
QwtDialNeedle *QwtAnalogClock::hand( Hand hd )
|
||||
{
|
||||
if ( hd < 0 || hd >= NHands )
|
||||
return NULL;
|
||||
|
||||
return d_hand[hd];
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Clock hand
|
||||
\param hd Specifies the type of hand
|
||||
\sa setHand()
|
||||
*/
|
||||
const QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) const
|
||||
{
|
||||
return const_cast<QwtAnalogClock *>( this )->hand( hd );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the current time
|
||||
*/
|
||||
void QwtAnalogClock::setCurrentTime()
|
||||
{
|
||||
setTime( QTime::currentTime() );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set a time
|
||||
\param time Time to display
|
||||
*/
|
||||
void QwtAnalogClock::setTime( const QTime &time )
|
||||
{
|
||||
if ( time.isValid() )
|
||||
{
|
||||
setValue( ( time.hour() % 12 ) * 60.0 * 60.0
|
||||
+ time.minute() * 60.0 + time.second() );
|
||||
}
|
||||
else
|
||||
setValid( false );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Draw the needle
|
||||
|
||||
A clock has no single needle but three hands instead. drawNeedle()
|
||||
translates value() into directions for the hands and calls
|
||||
drawHand().
|
||||
|
||||
\param painter Painter
|
||||
\param center Center of the clock
|
||||
\param radius Maximum length for the hands
|
||||
\param dir Dummy, not used.
|
||||
\param colorGroup ColorGroup
|
||||
|
||||
\sa drawHand()
|
||||
*/
|
||||
void QwtAnalogClock::drawNeedle( QPainter *painter, const QPointF ¢er,
|
||||
double radius, double dir, QPalette::ColorGroup colorGroup ) const
|
||||
{
|
||||
Q_UNUSED( dir );
|
||||
|
||||
if ( isValid() )
|
||||
{
|
||||
const double hours = value() / ( 60.0 * 60.0 );
|
||||
const double minutes =
|
||||
( value() - qFloor(hours) * 60.0 * 60.0 ) / 60.0;
|
||||
const double seconds = value() - qFloor(hours) * 60.0 * 60.0
|
||||
- qFloor(minutes) * 60.0;
|
||||
|
||||
double angle[NHands];
|
||||
angle[HourHand] = 360.0 * hours / 12.0;
|
||||
angle[MinuteHand] = 360.0 * minutes / 60.0;
|
||||
angle[SecondHand] = 360.0 * seconds / 60.0;
|
||||
|
||||
for ( int hand = 0; hand < NHands; hand++ )
|
||||
{
|
||||
const double d = 360.0 - angle[hand] - origin();
|
||||
drawHand( painter, static_cast<Hand>( hand ),
|
||||
center, radius, d, colorGroup );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw a clock hand
|
||||
|
||||
\param painter Painter
|
||||
\param hd Specify the type of hand
|
||||
\param center Center of the clock
|
||||
\param radius Maximum length for the hands
|
||||
\param direction Direction of the hand in degrees, counter clockwise
|
||||
\param cg ColorGroup
|
||||
*/
|
||||
void QwtAnalogClock::drawHand( QPainter *painter, Hand hd,
|
||||
const QPointF ¢er, double radius, double direction,
|
||||
QPalette::ColorGroup cg ) const
|
||||
{
|
||||
const QwtDialNeedle *needle = hand( hd );
|
||||
if ( needle )
|
||||
{
|
||||
if ( hd == HourHand )
|
||||
radius = qRound( 0.8 * radius );
|
||||
|
||||
needle->draw( painter, center, radius, direction, cg );
|
||||
}
|
||||
}
|
||||
93
third/3rd_qwt/qwt_analog_clock.h
Normal file
93
third/3rd_qwt/qwt_analog_clock.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_ANALOG_CLOCK_H
|
||||
#define QWT_ANALOG_CLOCK_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_dial.h"
|
||||
#include "qwt_dial_needle.h"
|
||||
#include <qdatetime.h>
|
||||
|
||||
/*!
|
||||
\brief An analog clock
|
||||
|
||||
\image html analogclock.png
|
||||
|
||||
\par Example
|
||||
\code
|
||||
#include <qwt_analog_clock.h>
|
||||
|
||||
QwtAnalogClock *clock = new QwtAnalogClock(...);
|
||||
clock->scaleDraw()->setPenWidth(3);
|
||||
clock->setLineWidth(6);
|
||||
clock->setFrameShadow(QwtDial::Sunken);
|
||||
clock->setTime();
|
||||
|
||||
// update the clock every second
|
||||
QTimer *timer = new QTimer(clock);
|
||||
timer->connect(timer, SIGNAL(timeout()), clock, SLOT(setCurrentTime()));
|
||||
timer->start(1000);
|
||||
|
||||
\endcode
|
||||
|
||||
\note The examples/dials example shows how to use QwtAnalogClock.
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtAnalogClock: public QwtDial
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/*!
|
||||
Hand type
|
||||
\sa setHand(), hand()
|
||||
*/
|
||||
enum Hand
|
||||
{
|
||||
//! Needle displaying the seconds
|
||||
SecondHand,
|
||||
|
||||
//! Needle displaying the minutes
|
||||
MinuteHand,
|
||||
|
||||
//! Needle displaying the hours
|
||||
HourHand,
|
||||
|
||||
//! Number of needles
|
||||
NHands
|
||||
};
|
||||
|
||||
explicit QwtAnalogClock( QWidget* parent = NULL );
|
||||
virtual ~QwtAnalogClock();
|
||||
|
||||
void setHand( Hand, QwtDialNeedle * );
|
||||
|
||||
const QwtDialNeedle *hand( Hand ) const;
|
||||
QwtDialNeedle *hand( Hand );
|
||||
|
||||
public Q_SLOTS:
|
||||
void setCurrentTime();
|
||||
void setTime( const QTime & );
|
||||
|
||||
protected:
|
||||
virtual void drawNeedle( QPainter *, const QPointF &,
|
||||
double radius, double direction, QPalette::ColorGroup ) const;
|
||||
|
||||
virtual void drawHand( QPainter *, Hand, const QPointF &,
|
||||
double radius, double direction, QPalette::ColorGroup ) const;
|
||||
|
||||
private:
|
||||
// use setHand instead
|
||||
void setNeedle( QwtDialNeedle * );
|
||||
|
||||
QwtDialNeedle *d_hand[NHands];
|
||||
};
|
||||
|
||||
#endif
|
||||
333
third/3rd_qwt/qwt_arrow_button.cpp
Normal file
333
third/3rd_qwt/qwt_arrow_button.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
/* -*- 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_arrow_button.h"
|
||||
#include "qwt_math.h"
|
||||
#include <qpainter.h>
|
||||
#include <qstyle.h>
|
||||
#include <qstyleoption.h>
|
||||
#include <qevent.h>
|
||||
#include <qapplication.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;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*!
|
||||
\param num Number of arrows
|
||||
\param arrowType see Qt::ArrowType 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 = qBound( 1, num, 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 rectangle 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() )
|
||||
{
|
||||
QStyleOptionButton option = styleOpt( this );
|
||||
const int ph = style()->pixelMetric(
|
||||
QStyle::PM_ButtonShiftHorizontal, &option, this );
|
||||
const int pv = style()->pixelMetric(
|
||||
QStyle::PM_ButtonShiftVertical, &option, this );
|
||||
|
||||
r.translate( ph, pv );
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*!
|
||||
Paint event handler
|
||||
\param event Paint event
|
||||
*/
|
||||
void QwtArrowButton::paintEvent( QPaintEvent *event )
|
||||
{
|
||||
QPushButton::paintEvent( event );
|
||||
QPainter painter( this );
|
||||
drawButtonLabel( &painter );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Draw the button label
|
||||
|
||||
\param painter Painter
|
||||
\sa The Qt Manual for 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;
|
||||
|
||||
arrowRect.translate( dx, dy );
|
||||
}
|
||||
painter->restore();
|
||||
|
||||
if ( hasFocus() )
|
||||
{
|
||||
QStyleOptionFocusRect option;
|
||||
option.init( this );
|
||||
option.backgroundColor = palette().color( QPalette::Window );
|
||||
|
||||
style()->drawPrimitive( QStyle::PE_FrameFocusRect,
|
||||
&option, painter, this );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw an arrow int a bounding rectangle
|
||||
|
||||
\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
|
||||
{
|
||||
QPolygon 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();
|
||||
|
||||
painter->setRenderHint( QPainter::Antialiasing, true );
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( palette().brush( QPalette::ButtonText ) );
|
||||
painter->drawPolygon( pa );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return a size hint
|
||||
*/
|
||||
QSize QwtArrowButton::sizeHint() const
|
||||
{
|
||||
const QSize hint = minimumSizeHint();
|
||||
return hint.expandedTo( QApplication::globalStrut() );
|
||||
}
|
||||
|
||||
/*!
|
||||
\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();
|
||||
|
||||
QStyleOption styleOption;
|
||||
styleOption.init( this );
|
||||
|
||||
sz = style()->sizeFromContents( QStyle::CT_PushButton,
|
||||
&styleOption, sz, this );
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
/*!
|
||||
Calculate the size for a arrow that fits into a rectangle 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 *event )
|
||||
{
|
||||
if ( event->isAutoRepeat() && event->key() == Qt::Key_Space )
|
||||
Q_EMIT clicked();
|
||||
|
||||
QPushButton::keyPressEvent( event );
|
||||
}
|
||||
52
third/3rd_qwt/qwt_arrow_button.h
Normal file
52
third/3rd_qwt/qwt_arrow_button.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_ARROW_BUTTON_H
|
||||
#define QWT_ARROW_BUTTON_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qpushbutton.h>
|
||||
|
||||
/*!
|
||||
\brief Arrow Button
|
||||
|
||||
A push button with one or more filled triangles on its front.
|
||||
An Arrow button can have 1 to 3 arrows in a row, pointing
|
||||
up, down, left or right.
|
||||
*/
|
||||
class QWT_EXPORT QwtArrowButton : public QPushButton
|
||||
{
|
||||
public:
|
||||
explicit QwtArrowButton ( int num, Qt::ArrowType, QWidget *parent = NULL );
|
||||
virtual ~QwtArrowButton();
|
||||
|
||||
Qt::ArrowType arrowType() const;
|
||||
int num() const;
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
virtual QSize minimumSizeHint() const;
|
||||
|
||||
protected:
|
||||
virtual void paintEvent( QPaintEvent *event );
|
||||
|
||||
virtual void drawButtonLabel( QPainter * );
|
||||
virtual void drawArrow( QPainter *,
|
||||
const QRect &, Qt::ArrowType ) const;
|
||||
virtual QRect labelRect() const;
|
||||
virtual QSize arrowSize( Qt::ArrowType,
|
||||
const QSize &boundingSize ) const;
|
||||
|
||||
virtual void keyPressEvent( QKeyEvent * );
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
510
third/3rd_qwt/qwt_clipper.cpp
Normal file
510
third/3rd_qwt/qwt_clipper.cpp
Normal file
@@ -0,0 +1,510 @@
|
||||
/* -*- 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_clipper.h"
|
||||
#include "qwt_point_polar.h"
|
||||
#include <qrect.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if QT_VERSION < 0x040601
|
||||
#define qAtan(x) ::atan(x)
|
||||
#endif
|
||||
|
||||
namespace QwtClip
|
||||
{
|
||||
// some templates used for inlining
|
||||
template <class Point, typename T> class LeftEdge;
|
||||
template <class Point, typename T> class RightEdge;
|
||||
template <class Point, typename T> class TopEdge;
|
||||
template <class Point, typename T> class BottomEdge;
|
||||
|
||||
template <class Point> class PointBuffer;
|
||||
}
|
||||
|
||||
template <class Point, typename Value>
|
||||
class QwtClip::LeftEdge
|
||||
{
|
||||
public:
|
||||
inline LeftEdge( Value x1, Value, Value, Value ):
|
||||
d_x1( x1 )
|
||||
{
|
||||
}
|
||||
|
||||
inline bool isInside( const Point &p ) const
|
||||
{
|
||||
return p.x() >= d_x1;
|
||||
}
|
||||
|
||||
inline Point intersection( const Point &p1, const Point &p2 ) const
|
||||
{
|
||||
double dy = ( p1.y() - p2.y() ) / double( p1.x() - p2.x() );
|
||||
return Point( d_x1, static_cast< Value >( p2.y() + ( d_x1 - p2.x() ) * dy ) );
|
||||
}
|
||||
private:
|
||||
const Value d_x1;
|
||||
};
|
||||
|
||||
template <class Point, typename Value>
|
||||
class QwtClip::RightEdge
|
||||
{
|
||||
public:
|
||||
inline RightEdge( Value, Value x2, Value, Value ):
|
||||
d_x2( x2 )
|
||||
{
|
||||
}
|
||||
|
||||
inline bool isInside( const Point &p ) const
|
||||
{
|
||||
return p.x() <= d_x2;
|
||||
}
|
||||
|
||||
inline Point intersection( const Point &p1, const Point &p2 ) const
|
||||
{
|
||||
double dy = ( p1.y() - p2.y() ) / double( p1.x() - p2.x() );
|
||||
return Point( d_x2, static_cast<Value>( p2.y() + ( d_x2 - p2.x() ) * dy ) );
|
||||
}
|
||||
|
||||
private:
|
||||
const Value d_x2;
|
||||
};
|
||||
|
||||
template <class Point, typename Value>
|
||||
class QwtClip::TopEdge
|
||||
{
|
||||
public:
|
||||
inline TopEdge( Value, Value, Value y1, Value ):
|
||||
d_y1( y1 )
|
||||
{
|
||||
}
|
||||
|
||||
inline bool isInside( const Point &p ) const
|
||||
{
|
||||
return p.y() >= d_y1;
|
||||
}
|
||||
|
||||
inline Point intersection( const Point &p1, const Point &p2 ) const
|
||||
{
|
||||
double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() );
|
||||
return Point( static_cast<Value>( p2.x() + ( d_y1 - p2.y() ) * dx ), d_y1 );
|
||||
}
|
||||
|
||||
private:
|
||||
const Value d_y1;
|
||||
};
|
||||
|
||||
template <class Point, typename Value>
|
||||
class QwtClip::BottomEdge
|
||||
{
|
||||
public:
|
||||
inline BottomEdge( Value, Value, Value, Value y2 ):
|
||||
d_y2( y2 )
|
||||
{
|
||||
}
|
||||
|
||||
inline bool isInside( const Point &p ) const
|
||||
{
|
||||
return p.y() <= d_y2;
|
||||
}
|
||||
|
||||
inline Point intersection( const Point &p1, const Point &p2 ) const
|
||||
{
|
||||
double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() );
|
||||
return Point( static_cast<Value>( p2.x() + ( d_y2 - p2.y() ) * dx ), d_y2 );
|
||||
}
|
||||
|
||||
private:
|
||||
const Value d_y2;
|
||||
};
|
||||
|
||||
template<class Point>
|
||||
class QwtClip::PointBuffer
|
||||
{
|
||||
public:
|
||||
PointBuffer( int capacity = 0 ):
|
||||
m_capacity( 0 ),
|
||||
m_size( 0 ),
|
||||
m_buffer( NULL )
|
||||
{
|
||||
if ( capacity > 0 )
|
||||
reserve( capacity );
|
||||
}
|
||||
|
||||
~PointBuffer()
|
||||
{
|
||||
if ( m_buffer )
|
||||
::free( m_buffer );
|
||||
}
|
||||
|
||||
inline void setPoints( int numPoints, const Point *points )
|
||||
{
|
||||
reserve( numPoints );
|
||||
|
||||
m_size = numPoints;
|
||||
::memcpy( m_buffer, points, m_size * sizeof( Point ) );
|
||||
}
|
||||
|
||||
inline void reset()
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
inline int size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
inline Point *data() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
inline Point &operator[]( int i )
|
||||
{
|
||||
return m_buffer[i];
|
||||
}
|
||||
|
||||
inline const Point &operator[]( int i ) const
|
||||
{
|
||||
return m_buffer[i];
|
||||
}
|
||||
|
||||
inline void add( const Point &point )
|
||||
{
|
||||
if ( m_capacity <= m_size )
|
||||
reserve( m_size + 1 );
|
||||
|
||||
m_buffer[m_size++] = point;
|
||||
}
|
||||
|
||||
private:
|
||||
inline void reserve( int size )
|
||||
{
|
||||
if ( m_capacity == 0 )
|
||||
m_capacity = 1;
|
||||
|
||||
while ( m_capacity < size )
|
||||
m_capacity *= 2;
|
||||
|
||||
m_buffer = static_cast<Point *>(
|
||||
::realloc( m_buffer, m_capacity * sizeof( Point ) ) );
|
||||
}
|
||||
|
||||
int m_capacity;
|
||||
int m_size;
|
||||
Point *m_buffer;
|
||||
};
|
||||
|
||||
using namespace QwtClip;
|
||||
|
||||
template <class Polygon, class Rect, class Point, typename T>
|
||||
class QwtPolygonClipper
|
||||
{
|
||||
public:
|
||||
QwtPolygonClipper( const Rect &clipRect ):
|
||||
d_clipRect( clipRect )
|
||||
{
|
||||
}
|
||||
|
||||
Polygon clipPolygon( const Polygon &polygon, bool closePolygon ) const
|
||||
{
|
||||
#if 0
|
||||
if ( d_clipRect.contains( polygon.boundingRect() ) )
|
||||
return polygon;
|
||||
#endif
|
||||
|
||||
PointBuffer<Point> points1;
|
||||
PointBuffer<Point> points2( qMin( 256, polygon.size() ) );
|
||||
|
||||
points1.setPoints( polygon.size(), polygon.data() );
|
||||
|
||||
clipEdge< LeftEdge<Point, T> >( closePolygon, points1, points2 );
|
||||
clipEdge< RightEdge<Point, T> >( closePolygon, points2, points1 );
|
||||
clipEdge< TopEdge<Point, T> >( closePolygon, points1, points2 );
|
||||
clipEdge< BottomEdge<Point, T> >( closePolygon, points2, points1 );
|
||||
|
||||
Polygon p;
|
||||
p.resize( points1.size() );
|
||||
::memcpy( p.data(), points1.data(), points1.size() * sizeof( Point ) );
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
template <class Edge>
|
||||
inline void clipEdge( bool closePolygon,
|
||||
PointBuffer<Point> &points, PointBuffer<Point> &clippedPoints ) const
|
||||
{
|
||||
clippedPoints.reset();
|
||||
|
||||
if ( points.size() < 2 )
|
||||
{
|
||||
if ( points.size() == 1 )
|
||||
clippedPoints.add( points[0] );
|
||||
return;
|
||||
}
|
||||
|
||||
const Edge edge( d_clipRect.x(), d_clipRect.x() + d_clipRect.width(),
|
||||
d_clipRect.y(), d_clipRect.y() + d_clipRect.height() );
|
||||
|
||||
int lastPos, start;
|
||||
if ( closePolygon )
|
||||
{
|
||||
start = 0;
|
||||
lastPos = points.size() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = 1;
|
||||
lastPos = 0;
|
||||
|
||||
if ( edge.isInside( points[0] ) )
|
||||
clippedPoints.add( points[0] );
|
||||
}
|
||||
|
||||
const uint nPoints = points.size();
|
||||
for ( uint i = start; i < nPoints; i++ )
|
||||
{
|
||||
const Point &p1 = points[i];
|
||||
const Point &p2 = points[lastPos];
|
||||
|
||||
if ( edge.isInside( p1 ) )
|
||||
{
|
||||
if ( edge.isInside( p2 ) )
|
||||
{
|
||||
clippedPoints.add( p1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
clippedPoints.add( edge.intersection( p1, p2 ) );
|
||||
clippedPoints.add( p1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( edge.isInside( p2 ) )
|
||||
{
|
||||
clippedPoints.add( edge.intersection( p1, p2 ) );
|
||||
}
|
||||
}
|
||||
lastPos = i;
|
||||
}
|
||||
}
|
||||
|
||||
const Rect d_clipRect;
|
||||
};
|
||||
|
||||
class QwtCircleClipper
|
||||
{
|
||||
public:
|
||||
QwtCircleClipper( const QRectF &r );
|
||||
QVector<QwtInterval> clipCircle( const QPointF &, double radius ) const;
|
||||
|
||||
private:
|
||||
enum Edge
|
||||
{
|
||||
Left,
|
||||
Top,
|
||||
Right,
|
||||
Bottom,
|
||||
|
||||
NEdges
|
||||
};
|
||||
|
||||
QList<QPointF> cuttingPoints(
|
||||
Edge, const QPointF &pos, double radius ) const;
|
||||
|
||||
double toAngle( const QPointF &, const QPointF & ) const;
|
||||
|
||||
const QRectF d_rect;
|
||||
};
|
||||
|
||||
|
||||
QwtCircleClipper::QwtCircleClipper( const QRectF &r ):
|
||||
d_rect( r )
|
||||
{
|
||||
}
|
||||
|
||||
QVector<QwtInterval> QwtCircleClipper::clipCircle(
|
||||
const QPointF &pos, double radius ) const
|
||||
{
|
||||
QList<QPointF> points;
|
||||
for ( int edge = 0; edge < NEdges; edge++ )
|
||||
points += cuttingPoints( static_cast<Edge>(edge), pos, radius );
|
||||
|
||||
QVector<QwtInterval> intv;
|
||||
if ( points.size() <= 0 )
|
||||
{
|
||||
QRectF cRect( 0, 0, 2 * radius, 2 * radius );
|
||||
cRect.moveCenter( pos );
|
||||
if ( d_rect.contains( cRect ) )
|
||||
intv += QwtInterval( 0.0, 2 * M_PI );
|
||||
}
|
||||
else
|
||||
{
|
||||
QList<double> angles;
|
||||
for ( int i = 0; i < points.size(); i++ )
|
||||
angles += toAngle( pos, points[i] );
|
||||
qSort( angles );
|
||||
|
||||
const int in = d_rect.contains( qwtPolar2Pos( pos, radius,
|
||||
angles[0] + ( angles[1] - angles[0] ) / 2 ) );
|
||||
|
||||
if ( in )
|
||||
{
|
||||
for ( int i = 0; i < angles.size() - 1; i += 2 )
|
||||
intv += QwtInterval( angles[i], angles[i+1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 1; i < angles.size() - 1; i += 2 )
|
||||
intv += QwtInterval( angles[i], angles[i+1] );
|
||||
intv += QwtInterval( angles.last(), angles.first() );
|
||||
}
|
||||
}
|
||||
|
||||
return intv;
|
||||
}
|
||||
|
||||
double QwtCircleClipper::toAngle(
|
||||
const QPointF &from, const QPointF &to ) const
|
||||
{
|
||||
if ( from.x() == to.x() )
|
||||
return from.y() <= to.y() ? M_PI / 2.0 : 3 * M_PI / 2.0;
|
||||
|
||||
const double m = qAbs( ( to.y() - from.y() ) / ( to.x() - from.x() ) );
|
||||
|
||||
double angle = qAtan( m );
|
||||
if ( to.x() > from.x() )
|
||||
{
|
||||
if ( to.y() > from.y() )
|
||||
angle = 2 * M_PI - angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( to.y() > from.y() )
|
||||
angle = M_PI + angle;
|
||||
else
|
||||
angle = M_PI - angle;
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
QList<QPointF> QwtCircleClipper::cuttingPoints(
|
||||
Edge edge, const QPointF &pos, double radius ) const
|
||||
{
|
||||
QList<QPointF> points;
|
||||
|
||||
if ( edge == Left || edge == Right )
|
||||
{
|
||||
const double x = ( edge == Left ) ? d_rect.left() : d_rect.right();
|
||||
if ( qAbs( pos.x() - x ) < radius )
|
||||
{
|
||||
const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.x() - x ) );
|
||||
const double m_y1 = pos.y() + off;
|
||||
if ( m_y1 >= d_rect.top() && m_y1 <= d_rect.bottom() )
|
||||
points += QPointF( x, m_y1 );
|
||||
|
||||
const double m_y2 = pos.y() - off;
|
||||
if ( m_y2 >= d_rect.top() && m_y2 <= d_rect.bottom() )
|
||||
points += QPointF( x, m_y2 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const double y = ( edge == Top ) ? d_rect.top() : d_rect.bottom();
|
||||
if ( qAbs( pos.y() - y ) < radius )
|
||||
{
|
||||
const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.y() - y ) );
|
||||
const double x1 = pos.x() + off;
|
||||
if ( x1 >= d_rect.left() && x1 <= d_rect.right() )
|
||||
points += QPointF( x1, y );
|
||||
|
||||
const double m_x2 = pos.x() - off;
|
||||
if ( m_x2 >= d_rect.left() && m_x2 <= d_rect.right() )
|
||||
points += QPointF( m_x2, y );
|
||||
}
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sutherland-Hodgman polygon clipping
|
||||
|
||||
\param clipRect Clip rectangle
|
||||
\param polygon Polygon
|
||||
\param closePolygon True, when the polygon is closed
|
||||
|
||||
\return Clipped polygon
|
||||
*/
|
||||
QPolygon QwtClipper::clipPolygon(
|
||||
const QRectF &clipRect, const QPolygon &polygon, bool closePolygon )
|
||||
{
|
||||
const int minX = qCeil( clipRect.left() );
|
||||
const int maxX = qFloor( clipRect.right() );
|
||||
const int minY = qCeil( clipRect.top() );
|
||||
const int maxY = qFloor( clipRect.bottom() );
|
||||
|
||||
const QRect r( minX, minY, maxX - minX, maxY - minY );
|
||||
|
||||
QwtPolygonClipper<QPolygon, QRect, QPoint, int> clipper( r );
|
||||
return clipper.clipPolygon( polygon, closePolygon );
|
||||
}
|
||||
/*!
|
||||
Sutherland-Hodgman polygon clipping
|
||||
|
||||
\param clipRect Clip rectangle
|
||||
\param polygon Polygon
|
||||
\param closePolygon True, when the polygon is closed
|
||||
|
||||
\return Clipped polygon
|
||||
*/
|
||||
QPolygon QwtClipper::clipPolygon(
|
||||
const QRect &clipRect, const QPolygon &polygon, bool closePolygon )
|
||||
{
|
||||
QwtPolygonClipper<QPolygon, QRect, QPoint, int> clipper( clipRect );
|
||||
return clipper.clipPolygon( polygon, closePolygon );
|
||||
}
|
||||
|
||||
/*!
|
||||
Sutherland-Hodgman polygon clipping
|
||||
|
||||
\param clipRect Clip rectangle
|
||||
\param polygon Polygon
|
||||
\param closePolygon True, when the polygon is closed
|
||||
|
||||
\return Clipped polygon
|
||||
*/
|
||||
QPolygonF QwtClipper::clipPolygonF(
|
||||
const QRectF &clipRect, const QPolygonF &polygon, bool closePolygon )
|
||||
{
|
||||
QwtPolygonClipper<QPolygonF, QRectF, QPointF, double> clipper( clipRect );
|
||||
return clipper.clipPolygon( polygon, closePolygon );
|
||||
}
|
||||
|
||||
/*!
|
||||
Circle clipping
|
||||
|
||||
clipCircle() divides a circle into intervals of angles representing arcs
|
||||
of the circle. When the circle is completely inside the clip rectangle
|
||||
an interval [0.0, 2 * M_PI] is returned.
|
||||
|
||||
\param clipRect Clip rectangle
|
||||
\param center Center of the circle
|
||||
\param radius Radius of the circle
|
||||
|
||||
\return Arcs of the circle
|
||||
*/
|
||||
QVector<QwtInterval> QwtClipper::clipCircle( const QRectF &clipRect,
|
||||
const QPointF ¢er, double radius )
|
||||
{
|
||||
QwtCircleClipper clipper( clipRect );
|
||||
return clipper.clipCircle( center, radius );
|
||||
}
|
||||
40
third/3rd_qwt/qwt_clipper.h
Normal file
40
third/3rd_qwt/qwt_clipper.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_CLIPPER_H
|
||||
#define QWT_CLIPPER_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_interval.h"
|
||||
#include <qpolygon.h>
|
||||
#include <qvector.h>
|
||||
|
||||
class QRect;
|
||||
class QRectF;
|
||||
|
||||
/*!
|
||||
\brief Some clipping algorithms
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtClipper
|
||||
{
|
||||
public:
|
||||
static QPolygon clipPolygon( const QRect &,
|
||||
const QPolygon &, bool closePolygon = false );
|
||||
static QPolygon clipPolygon( const QRectF &,
|
||||
const QPolygon &, bool closePolygon = false );
|
||||
|
||||
static QPolygonF clipPolygonF( const QRectF &,
|
||||
const QPolygonF &, bool closePolygon = false );
|
||||
|
||||
static QVector<QwtInterval> clipCircle(
|
||||
const QRectF &, const QPointF &, double radius );
|
||||
};
|
||||
|
||||
#endif
|
||||
499
third/3rd_qwt/qwt_color_map.cpp
Normal file
499
third/3rd_qwt/qwt_color_map.cpp
Normal file
@@ -0,0 +1,499 @@
|
||||
/* -*- 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_color_map.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_interval.h"
|
||||
#include <qnumeric.h>
|
||||
|
||||
class QwtLinearColorMap::ColorStops
|
||||
{
|
||||
public:
|
||||
ColorStops():
|
||||
d_doAlpha( false )
|
||||
{
|
||||
d_stops.reserve( 256 );
|
||||
}
|
||||
|
||||
void insert( double pos, const QColor &color );
|
||||
QRgb rgb( QwtLinearColorMap::Mode, double pos ) const;
|
||||
|
||||
QVector<double> stops() const;
|
||||
|
||||
private:
|
||||
|
||||
class ColorStop
|
||||
{
|
||||
public:
|
||||
ColorStop():
|
||||
pos( 0.0 ),
|
||||
rgb( 0 )
|
||||
{
|
||||
};
|
||||
|
||||
ColorStop( double p, const QColor &c ):
|
||||
pos( p ),
|
||||
rgb( c.rgba() )
|
||||
{
|
||||
r = qRed( rgb );
|
||||
g = qGreen( rgb );
|
||||
b = qBlue( rgb );
|
||||
a = qAlpha( rgb );
|
||||
|
||||
/*
|
||||
when mapping a value to rgb we will have to calcualate:
|
||||
- const int v = int( ( s1.v0 + ratio * s1.vStep ) + 0.5 );
|
||||
|
||||
Thus adding 0.5 ( for rounding ) can be done in advance
|
||||
*/
|
||||
r0 = r + 0.5;
|
||||
g0 = g + 0.5;
|
||||
b0 = b + 0.5;
|
||||
a0 = a + 0.5;
|
||||
|
||||
rStep = gStep = bStep = aStep = 0.0;
|
||||
posStep = 0.0;
|
||||
}
|
||||
|
||||
void updateSteps( const ColorStop &nextStop )
|
||||
{
|
||||
rStep = nextStop.r - r;
|
||||
gStep = nextStop.g - g;
|
||||
bStep = nextStop.b - b;
|
||||
aStep = nextStop.a - a;
|
||||
posStep = nextStop.pos - pos;
|
||||
}
|
||||
|
||||
double pos;
|
||||
QRgb rgb;
|
||||
int r, g, b, a;
|
||||
|
||||
// precalculated values
|
||||
double rStep, gStep, bStep, aStep;
|
||||
double r0, g0, b0, a0;
|
||||
double posStep;
|
||||
};
|
||||
|
||||
inline int findUpper( double pos ) const;
|
||||
QVector<ColorStop> d_stops;
|
||||
bool d_doAlpha;
|
||||
};
|
||||
|
||||
void QwtLinearColorMap::ColorStops::insert( double pos, const QColor &color )
|
||||
{
|
||||
// Lookups need to be very fast, insertions are not so important.
|
||||
// Anyway, a balanced tree is what we need here. TODO ...
|
||||
|
||||
if ( pos < 0.0 || pos > 1.0 )
|
||||
return;
|
||||
|
||||
int index;
|
||||
if ( d_stops.size() == 0 )
|
||||
{
|
||||
index = 0;
|
||||
d_stops.resize( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
index = findUpper( pos );
|
||||
if ( index == d_stops.size() ||
|
||||
qAbs( d_stops[index].pos - pos ) >= 0.001 )
|
||||
{
|
||||
d_stops.resize( d_stops.size() + 1 );
|
||||
for ( int i = d_stops.size() - 1; i > index; i-- )
|
||||
d_stops[i] = d_stops[i-1];
|
||||
}
|
||||
}
|
||||
|
||||
d_stops[index] = ColorStop( pos, color );
|
||||
if ( color.alpha() != 255 )
|
||||
d_doAlpha = true;
|
||||
|
||||
if ( index > 0 )
|
||||
d_stops[index-1].updateSteps( d_stops[index] );
|
||||
|
||||
if ( index < d_stops.size() - 1 )
|
||||
d_stops[index].updateSteps( d_stops[index+1] );
|
||||
}
|
||||
|
||||
inline QVector<double> QwtLinearColorMap::ColorStops::stops() const
|
||||
{
|
||||
QVector<double> positions( d_stops.size() );
|
||||
for ( int i = 0; i < d_stops.size(); i++ )
|
||||
positions[i] = d_stops[i].pos;
|
||||
return positions;
|
||||
}
|
||||
|
||||
inline int QwtLinearColorMap::ColorStops::findUpper( double pos ) const
|
||||
{
|
||||
int index = 0;
|
||||
int n = d_stops.size();
|
||||
|
||||
const ColorStop *stops = d_stops.data();
|
||||
|
||||
while ( n > 0 )
|
||||
{
|
||||
const int half = n >> 1;
|
||||
const int middle = index + half;
|
||||
|
||||
if ( stops[middle].pos <= pos )
|
||||
{
|
||||
index = middle + 1;
|
||||
n -= half + 1;
|
||||
}
|
||||
else
|
||||
n = half;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
inline QRgb QwtLinearColorMap::ColorStops::rgb(
|
||||
QwtLinearColorMap::Mode mode, double pos ) const
|
||||
{
|
||||
if ( pos <= 0.0 )
|
||||
return d_stops[0].rgb;
|
||||
if ( pos >= 1.0 )
|
||||
return d_stops[ d_stops.size() - 1 ].rgb;
|
||||
|
||||
const int index = findUpper( pos );
|
||||
if ( mode == FixedColors )
|
||||
{
|
||||
return d_stops[index-1].rgb;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ColorStop &s1 = d_stops[index-1];
|
||||
|
||||
const double ratio = ( pos - s1.pos ) / ( s1.posStep );
|
||||
|
||||
const int r = int( s1.r0 + ratio * s1.rStep );
|
||||
const int g = int( s1.g0 + ratio * s1.gStep );
|
||||
const int b = int( s1.b0 + ratio * s1.bStep );
|
||||
|
||||
if ( d_doAlpha )
|
||||
{
|
||||
if ( s1.aStep )
|
||||
{
|
||||
const int a = int( s1.a0 + ratio * s1.aStep );
|
||||
return qRgba( r, g, b, a );
|
||||
}
|
||||
else
|
||||
{
|
||||
return qRgba( r, g, b, s1.a );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return qRgb( r, g, b );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtColorMap::QwtColorMap( Format format ):
|
||||
d_format( format )
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtColorMap::~QwtColorMap()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Build and return a color map of 256 colors
|
||||
|
||||
The color table is needed for rendering indexed images in combination
|
||||
with using colorIndex().
|
||||
|
||||
\param interval Range for the values
|
||||
\return A color table, that can be used for a QImage
|
||||
*/
|
||||
QVector<QRgb> QwtColorMap::colorTable( const QwtInterval &interval ) const
|
||||
{
|
||||
QVector<QRgb> table( 256 );
|
||||
|
||||
if ( interval.isValid() )
|
||||
{
|
||||
const double step = interval.width() / ( table.size() - 1 );
|
||||
for ( int i = 0; i < table.size(); i++ )
|
||||
table[i] = rgb( interval, interval.minValue() + step * i );
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
class QwtLinearColorMap::PrivateData
|
||||
{
|
||||
public:
|
||||
ColorStops colorStops;
|
||||
QwtLinearColorMap::Mode mode;
|
||||
};
|
||||
|
||||
/*!
|
||||
Build a color map with two stops at 0.0 and 1.0. The color
|
||||
at 0.0 is Qt::blue, at 1.0 it is Qt::yellow.
|
||||
|
||||
\param format Preferred format of the color map
|
||||
*/
|
||||
QwtLinearColorMap::QwtLinearColorMap( QwtColorMap::Format format ):
|
||||
QwtColorMap( format )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
d_data->mode = ScaledColors;
|
||||
|
||||
setColorInterval( Qt::blue, Qt::yellow );
|
||||
}
|
||||
|
||||
/*!
|
||||
Build a color map with two stops at 0.0 and 1.0.
|
||||
|
||||
\param color1 Color used for the minimum value of the value interval
|
||||
\param color2 Color used for the maximum value of the value interval
|
||||
\param format Preferred format for the color map
|
||||
*/
|
||||
QwtLinearColorMap::QwtLinearColorMap( const QColor &color1,
|
||||
const QColor &color2, QwtColorMap::Format format ):
|
||||
QwtColorMap( format )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
d_data->mode = ScaledColors;
|
||||
setColorInterval( color1, color2 );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtLinearColorMap::~QwtLinearColorMap()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the mode of the color map
|
||||
|
||||
FixedColors means the color is calculated from the next lower
|
||||
color stop. ScaledColors means the color is calculated
|
||||
by interpolating the colors of the adjacent stops.
|
||||
|
||||
\sa mode()
|
||||
*/
|
||||
void QwtLinearColorMap::setMode( Mode mode )
|
||||
{
|
||||
d_data->mode = mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Mode of the color map
|
||||
\sa setMode()
|
||||
*/
|
||||
QwtLinearColorMap::Mode QwtLinearColorMap::mode() const
|
||||
{
|
||||
return d_data->mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the color range
|
||||
|
||||
Add stops at 0.0 and 1.0.
|
||||
|
||||
\param color1 Color used for the minimum value of the value interval
|
||||
\param color2 Color used for the maximum value of the value interval
|
||||
|
||||
\sa color1(), color2()
|
||||
*/
|
||||
void QwtLinearColorMap::setColorInterval(
|
||||
const QColor &color1, const QColor &color2 )
|
||||
{
|
||||
d_data->colorStops = ColorStops();
|
||||
d_data->colorStops.insert( 0.0, color1 );
|
||||
d_data->colorStops.insert( 1.0, color2 );
|
||||
}
|
||||
|
||||
/*!
|
||||
Add a color stop
|
||||
|
||||
The value has to be in the range [0.0, 1.0].
|
||||
F.e. a stop at position 17.0 for a range [10.0,20.0] must be
|
||||
passed as: (17.0 - 10.0) / (20.0 - 10.0)
|
||||
|
||||
\param value Value between [0.0, 1.0]
|
||||
\param color Color stop
|
||||
*/
|
||||
void QwtLinearColorMap::addColorStop( double value, const QColor& color )
|
||||
{
|
||||
if ( value >= 0.0 && value <= 1.0 )
|
||||
d_data->colorStops.insert( value, color );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Positions of color stops in increasing order
|
||||
*/
|
||||
QVector<double> QwtLinearColorMap::colorStops() const
|
||||
{
|
||||
return d_data->colorStops.stops();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the first color of the color range
|
||||
\sa setColorInterval()
|
||||
*/
|
||||
QColor QwtLinearColorMap::color1() const
|
||||
{
|
||||
return QColor( d_data->colorStops.rgb( d_data->mode, 0.0 ) );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the second color of the color range
|
||||
\sa setColorInterval()
|
||||
*/
|
||||
QColor QwtLinearColorMap::color2() const
|
||||
{
|
||||
return QColor( d_data->colorStops.rgb( d_data->mode, 1.0 ) );
|
||||
}
|
||||
|
||||
/*!
|
||||
Map a value of a given interval into a RGB value
|
||||
|
||||
\param interval Range for all values
|
||||
\param value Value to map into a RGB value
|
||||
|
||||
\return RGB value for value
|
||||
*/
|
||||
QRgb QwtLinearColorMap::rgb(
|
||||
const QwtInterval &interval, double value ) const
|
||||
{
|
||||
if ( qIsNaN(value) )
|
||||
return 0u;
|
||||
|
||||
const double width = interval.width();
|
||||
if ( width <= 0.0 )
|
||||
return 0u;
|
||||
|
||||
const double ratio = ( value - interval.minValue() ) / width;
|
||||
return d_data->colorStops.rgb( d_data->mode, ratio );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Map a value of a given interval into a color index
|
||||
|
||||
\param interval Range for all values
|
||||
\param value Value to map into a color index
|
||||
|
||||
\return Index, between 0 and 255
|
||||
*/
|
||||
unsigned char QwtLinearColorMap::colorIndex(
|
||||
const QwtInterval &interval, double value ) const
|
||||
{
|
||||
const double width = interval.width();
|
||||
|
||||
if ( qIsNaN(value) || width <= 0.0 || value <= interval.minValue() )
|
||||
return 0;
|
||||
|
||||
if ( value >= interval.maxValue() )
|
||||
return 255;
|
||||
|
||||
const double ratio = ( value - interval.minValue() ) / width;
|
||||
|
||||
unsigned char index;
|
||||
if ( d_data->mode == FixedColors )
|
||||
index = static_cast<unsigned char>( ratio * 255 ); // always floor
|
||||
else
|
||||
index = static_cast<unsigned char>( ratio * 255 + 0.5 );
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
class QwtAlphaColorMap::PrivateData
|
||||
{
|
||||
public:
|
||||
QColor color;
|
||||
QRgb rgb;
|
||||
QRgb rgbMax;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
\param color Color of the map
|
||||
*/
|
||||
QwtAlphaColorMap::QwtAlphaColorMap( const QColor &color ):
|
||||
QwtColorMap( QwtColorMap::RGB )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
setColor( color );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtAlphaColorMap::~QwtAlphaColorMap()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the color
|
||||
|
||||
\param color Color
|
||||
\sa color()
|
||||
*/
|
||||
void QwtAlphaColorMap::setColor( const QColor &color )
|
||||
{
|
||||
d_data->color = color;
|
||||
d_data->rgb = color.rgb() & qRgba( 255, 255, 255, 0 );
|
||||
d_data->rgbMax = d_data->rgb | ( 255 << 24 );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the color
|
||||
\sa setColor()
|
||||
*/
|
||||
QColor QwtAlphaColorMap::color() const
|
||||
{
|
||||
return d_data->color;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Map a value of a given interval into a alpha value
|
||||
|
||||
alpha := (value - interval.minValue()) / interval.width();
|
||||
|
||||
\param interval Range for all values
|
||||
\param value Value to map into a RGB value
|
||||
\return RGB value, with an alpha value
|
||||
*/
|
||||
QRgb QwtAlphaColorMap::rgb( const QwtInterval &interval, double value ) const
|
||||
{
|
||||
if ( qIsNaN(value) )
|
||||
return 0u;
|
||||
|
||||
const double width = interval.width();
|
||||
if ( width <= 0.0 )
|
||||
return 0u;
|
||||
|
||||
if ( value <= interval.minValue() )
|
||||
return d_data->rgb;
|
||||
|
||||
if ( value >= interval.maxValue() )
|
||||
return d_data->rgbMax;
|
||||
|
||||
const double ratio = ( value - interval.minValue() ) / width;
|
||||
return d_data->rgb | ( qRound( 255 * ratio ) << 24 );
|
||||
}
|
||||
|
||||
/*!
|
||||
Dummy function, needed to be implemented as it is pure virtual
|
||||
in QwtColorMap. Color indices make no sense in combination with
|
||||
an alpha channel.
|
||||
|
||||
\return Always 0
|
||||
*/
|
||||
unsigned char QwtAlphaColorMap::colorIndex(
|
||||
const QwtInterval &, double ) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
202
third/3rd_qwt/qwt_color_map.h
Normal file
202
third/3rd_qwt/qwt_color_map.h
Normal file
@@ -0,0 +1,202 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_COLOR_MAP_H
|
||||
#define QWT_COLOR_MAP_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_interval.h"
|
||||
#include <qcolor.h>
|
||||
#include <qvector.h>
|
||||
|
||||
/*!
|
||||
\brief QwtColorMap is used to map values into colors.
|
||||
|
||||
For displaying 3D data on a 2D plane the 3rd dimension is often
|
||||
displayed using colors, like f.e in a spectrogram.
|
||||
|
||||
Each color map is optimized to return colors for only one of the
|
||||
following image formats:
|
||||
|
||||
- QImage::Format_Indexed8\n
|
||||
- QImage::Format_ARGB32\n
|
||||
|
||||
\sa QwtPlotSpectrogram, QwtScaleWidget
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtColorMap
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
Format for color mapping
|
||||
\sa rgb(), colorIndex(), colorTable()
|
||||
*/
|
||||
|
||||
enum Format
|
||||
{
|
||||
//! The map is intended to map into RGB values.
|
||||
RGB,
|
||||
|
||||
/*!
|
||||
The map is intended to map into 8 bit values, that
|
||||
are indices into the color table.
|
||||
*/
|
||||
Indexed
|
||||
};
|
||||
|
||||
QwtColorMap( Format = QwtColorMap::RGB );
|
||||
virtual ~QwtColorMap();
|
||||
|
||||
Format format() const;
|
||||
|
||||
/*!
|
||||
Map a value of a given interval into a RGB value.
|
||||
|
||||
\param interval Range for the values
|
||||
\param value Value
|
||||
\return RGB value, corresponding to value
|
||||
*/
|
||||
virtual QRgb rgb( const QwtInterval &interval,
|
||||
double value ) const = 0;
|
||||
|
||||
/*!
|
||||
Map a value of a given interval into a color index
|
||||
|
||||
\param interval Range for the values
|
||||
\param value Value
|
||||
\return color index, corresponding to value
|
||||
*/
|
||||
virtual unsigned char colorIndex(
|
||||
const QwtInterval &interval, double value ) const = 0;
|
||||
|
||||
QColor color( const QwtInterval &, double value ) const;
|
||||
virtual QVector<QRgb> colorTable( const QwtInterval & ) const;
|
||||
|
||||
private:
|
||||
Format d_format;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief QwtLinearColorMap builds a color map from color stops.
|
||||
|
||||
A color stop is a color at a specific position. The valid
|
||||
range for the positions is [0.0, 1.0]. When mapping a value
|
||||
into a color it is translated into this interval according to mode().
|
||||
*/
|
||||
class QWT_EXPORT QwtLinearColorMap: public QwtColorMap
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
Mode of color map
|
||||
\sa setMode(), mode()
|
||||
*/
|
||||
enum Mode
|
||||
{
|
||||
//! Return the color from the next lower color stop
|
||||
FixedColors,
|
||||
|
||||
//! Interpolating the colors of the adjacent stops.
|
||||
ScaledColors
|
||||
};
|
||||
|
||||
QwtLinearColorMap( QwtColorMap::Format = QwtColorMap::RGB );
|
||||
QwtLinearColorMap( const QColor &color1, const QColor &color2,
|
||||
QwtColorMap::Format = QwtColorMap::RGB );
|
||||
|
||||
virtual ~QwtLinearColorMap();
|
||||
|
||||
void setMode( Mode );
|
||||
Mode mode() const;
|
||||
|
||||
void setColorInterval( const QColor &color1, const QColor &color2 );
|
||||
void addColorStop( double value, const QColor& );
|
||||
QVector<double> colorStops() const;
|
||||
|
||||
QColor color1() const;
|
||||
QColor color2() const;
|
||||
|
||||
virtual QRgb rgb( const QwtInterval &, double value ) const;
|
||||
virtual unsigned char colorIndex(
|
||||
const QwtInterval &, double value ) const;
|
||||
|
||||
class ColorStops;
|
||||
|
||||
private:
|
||||
// Disabled copy constructor and operator=
|
||||
QwtLinearColorMap( const QwtLinearColorMap & );
|
||||
QwtLinearColorMap &operator=( const QwtLinearColorMap & );
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief QwtAlphaColorMap varies the alpha value of a color
|
||||
*/
|
||||
class QWT_EXPORT QwtAlphaColorMap: public QwtColorMap
|
||||
{
|
||||
public:
|
||||
QwtAlphaColorMap( const QColor & = QColor( Qt::gray ) );
|
||||
virtual ~QwtAlphaColorMap();
|
||||
|
||||
void setColor( const QColor & );
|
||||
QColor color() const;
|
||||
|
||||
virtual QRgb rgb( const QwtInterval &, double value ) const;
|
||||
|
||||
private:
|
||||
QwtAlphaColorMap( const QwtAlphaColorMap & );
|
||||
QwtAlphaColorMap &operator=( const QwtAlphaColorMap & );
|
||||
|
||||
virtual unsigned char colorIndex(
|
||||
const QwtInterval &, double value ) const;
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
Map a value into a color
|
||||
|
||||
\param interval Valid interval for values
|
||||
\param value Value
|
||||
|
||||
\return Color corresponding to value
|
||||
|
||||
\warning This method is slow for Indexed color maps. If it is
|
||||
necessary to map many values, its better to get the
|
||||
color table once and find the color using colorIndex().
|
||||
*/
|
||||
inline QColor QwtColorMap::color(
|
||||
const QwtInterval &interval, double value ) const
|
||||
{
|
||||
if ( d_format == RGB )
|
||||
{
|
||||
return QColor::fromRgba( rgb( interval, value ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned int index = colorIndex( interval, value );
|
||||
|
||||
const QVector<QRgb> rgbTable = colorTable( interval );
|
||||
return rgbTable[index]; // slow
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Intended format of the color map
|
||||
\sa Format
|
||||
*/
|
||||
inline QwtColorMap::Format QwtColorMap::format() const
|
||||
{
|
||||
return d_format;
|
||||
}
|
||||
|
||||
#endif
|
||||
293
third/3rd_qwt/qwt_column_symbol.cpp
Normal file
293
third/3rd_qwt/qwt_column_symbol.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
/* -*- 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_column_symbol.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_painter.h"
|
||||
#include <qpainter.h>
|
||||
#include <qpalette.h>
|
||||
|
||||
static void qwtDrawBox( QPainter *p, const QRectF &rect,
|
||||
const QPalette &pal, double lw )
|
||||
{
|
||||
if ( lw > 0.0 )
|
||||
{
|
||||
if ( rect.width() == 0.0 )
|
||||
{
|
||||
p->setPen( pal.dark().color() );
|
||||
p->drawLine( rect.topLeft(), rect.bottomLeft() );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( rect.height() == 0.0 )
|
||||
{
|
||||
p->setPen( pal.dark().color() );
|
||||
p->drawLine( rect.topLeft(), rect.topRight() );
|
||||
return;
|
||||
}
|
||||
|
||||
lw = qMin( lw, rect.height() / 2.0 - 1.0 );
|
||||
lw = qMin( lw, rect.width() / 2.0 - 1.0 );
|
||||
|
||||
const QRectF outerRect = rect.adjusted( 0, 0, 1, 1 );
|
||||
QPolygonF polygon( outerRect );
|
||||
|
||||
if ( outerRect.width() > 2 * lw &&
|
||||
outerRect.height() > 2 * lw )
|
||||
{
|
||||
const QRectF innerRect = outerRect.adjusted( lw, lw, -lw, -lw );
|
||||
polygon = polygon.subtracted( innerRect );
|
||||
}
|
||||
|
||||
p->setPen( Qt::NoPen );
|
||||
|
||||
p->setBrush( pal.dark() );
|
||||
p->drawPolygon( polygon );
|
||||
}
|
||||
|
||||
const QRectF windowRect = rect.adjusted( lw, lw, -lw + 1, -lw + 1 );
|
||||
if ( windowRect.isValid() )
|
||||
p->fillRect( windowRect, pal.window() );
|
||||
}
|
||||
|
||||
static void qwtDrawPanel( QPainter *painter, const QRectF &rect,
|
||||
const QPalette &pal, double lw )
|
||||
{
|
||||
if ( lw > 0.0 )
|
||||
{
|
||||
if ( rect.width() == 0.0 )
|
||||
{
|
||||
painter->setPen( pal.window().color() );
|
||||
painter->drawLine( rect.topLeft(), rect.bottomLeft() );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( rect.height() == 0.0 )
|
||||
{
|
||||
painter->setPen( pal.window().color() );
|
||||
painter->drawLine( rect.topLeft(), rect.topRight() );
|
||||
return;
|
||||
}
|
||||
|
||||
lw = qMin( lw, rect.height() / 2.0 - 1.0 );
|
||||
lw = qMin( lw, rect.width() / 2.0 - 1.0 );
|
||||
|
||||
const QRectF outerRect = rect.adjusted( 0, 0, 1, 1 );
|
||||
const QRectF innerRect = outerRect.adjusted( lw, lw, -lw, -lw );
|
||||
|
||||
QPolygonF lines[2];
|
||||
|
||||
lines[0] += outerRect.bottomLeft();
|
||||
lines[0] += outerRect.topLeft();
|
||||
lines[0] += outerRect.topRight();
|
||||
lines[0] += innerRect.topRight();
|
||||
lines[0] += innerRect.topLeft();
|
||||
lines[0] += innerRect.bottomLeft();
|
||||
|
||||
lines[1] += outerRect.topRight();
|
||||
lines[1] += outerRect.bottomRight();
|
||||
lines[1] += outerRect.bottomLeft();
|
||||
lines[1] += innerRect.bottomLeft();
|
||||
lines[1] += innerRect.bottomRight();
|
||||
lines[1] += innerRect.topRight();
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
|
||||
painter->setBrush( pal.light() );
|
||||
painter->drawPolygon( lines[0] );
|
||||
painter->setBrush( pal.dark() );
|
||||
painter->drawPolygon( lines[1] );
|
||||
}
|
||||
|
||||
painter->fillRect( rect.adjusted( lw, lw, -lw + 1, -lw + 1 ), pal.window() );
|
||||
}
|
||||
|
||||
class QwtColumnSymbol::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
style( QwtColumnSymbol::Box ),
|
||||
frameStyle( QwtColumnSymbol::Raised ),
|
||||
palette( Qt::gray ),
|
||||
lineWidth( 2 )
|
||||
{
|
||||
}
|
||||
|
||||
QwtColumnSymbol::Style style;
|
||||
QwtColumnSymbol::FrameStyle frameStyle;
|
||||
|
||||
QPalette palette;
|
||||
int lineWidth;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
\param style Style of the symbol
|
||||
\sa setStyle(), style(), Style
|
||||
*/
|
||||
QwtColumnSymbol::QwtColumnSymbol( Style style )
|
||||
{
|
||||
d_data = new PrivateData();
|
||||
d_data->style = style;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtColumnSymbol::~QwtColumnSymbol()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Specify the symbol style
|
||||
|
||||
\param style Style
|
||||
\sa style(), setPalette()
|
||||
*/
|
||||
void QwtColumnSymbol::setStyle( Style style )
|
||||
{
|
||||
d_data->style = style;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Current symbol style
|
||||
\sa setStyle()
|
||||
*/
|
||||
QwtColumnSymbol::Style QwtColumnSymbol::style() const
|
||||
{
|
||||
return d_data->style;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign a palette for the symbol
|
||||
|
||||
\param palette Palette
|
||||
\sa palette(), setStyle()
|
||||
*/
|
||||
void QwtColumnSymbol::setPalette( const QPalette &palette )
|
||||
{
|
||||
d_data->palette = palette;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Current palette
|
||||
\sa setPalette()
|
||||
*/
|
||||
const QPalette& QwtColumnSymbol::palette() const
|
||||
{
|
||||
return d_data->palette;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the frame, that is used for the Box style.
|
||||
|
||||
\param frameStyle Frame style
|
||||
\sa frameStyle(), setLineWidth(), setStyle()
|
||||
*/
|
||||
void QwtColumnSymbol::setFrameStyle( FrameStyle frameStyle )
|
||||
{
|
||||
d_data->frameStyle = frameStyle;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Current frame style, that is used for the Box style.
|
||||
\sa setFrameStyle(), lineWidth(), setStyle()
|
||||
*/
|
||||
QwtColumnSymbol::FrameStyle QwtColumnSymbol::frameStyle() const
|
||||
{
|
||||
return d_data->frameStyle;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the line width of the frame, that is used for the Box style.
|
||||
|
||||
\param width Width
|
||||
\sa lineWidth(), setFrameStyle()
|
||||
*/
|
||||
void QwtColumnSymbol::setLineWidth( int width )
|
||||
{
|
||||
if ( width < 0 )
|
||||
width = 0;
|
||||
|
||||
d_data->lineWidth = width;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Line width of the frame, that is used for the Box style.
|
||||
\sa setLineWidth(), frameStyle(), setStyle()
|
||||
*/
|
||||
int QwtColumnSymbol::lineWidth() const
|
||||
{
|
||||
return d_data->lineWidth;
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the symbol depending on its style.
|
||||
|
||||
\param painter Painter
|
||||
\param rect Directed rectangle
|
||||
|
||||
\sa drawBox()
|
||||
*/
|
||||
void QwtColumnSymbol::draw( QPainter *painter,
|
||||
const QwtColumnRect &rect ) const
|
||||
{
|
||||
painter->save();
|
||||
|
||||
switch ( d_data->style )
|
||||
{
|
||||
case QwtColumnSymbol::Box:
|
||||
{
|
||||
drawBox( painter, rect );
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the symbol when it is in Box style.
|
||||
|
||||
\param painter Painter
|
||||
\param rect Directed rectangle
|
||||
|
||||
\sa draw()
|
||||
*/
|
||||
void QwtColumnSymbol::drawBox( QPainter *painter,
|
||||
const QwtColumnRect &rect ) const
|
||||
{
|
||||
QRectF r = rect.toRect();
|
||||
if ( QwtPainter::roundingAlignment( painter ) )
|
||||
{
|
||||
r.setLeft( qRound( r.left() ) );
|
||||
r.setRight( qRound( r.right() ) );
|
||||
r.setTop( qRound( r.top() ) );
|
||||
r.setBottom( qRound( r.bottom() ) );
|
||||
}
|
||||
|
||||
switch ( d_data->frameStyle )
|
||||
{
|
||||
case QwtColumnSymbol::Raised:
|
||||
{
|
||||
qwtDrawPanel( painter, r, d_data->palette, d_data->lineWidth );
|
||||
break;
|
||||
}
|
||||
case QwtColumnSymbol::Plain:
|
||||
{
|
||||
qwtDrawBox( painter, r, d_data->palette, d_data->lineWidth );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
painter->fillRect( r.adjusted( 0, 0, 1, 1 ), d_data->palette.window() );
|
||||
}
|
||||
}
|
||||
}
|
||||
161
third/3rd_qwt/qwt_column_symbol.h
Normal file
161
third/3rd_qwt/qwt_column_symbol.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_COLUMN_SYMBOL_H
|
||||
#define QWT_COLUMN_SYMBOL_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_interval.h"
|
||||
#include <qpen.h>
|
||||
#include <qsize.h>
|
||||
#include <qrect.h>
|
||||
|
||||
class QPainter;
|
||||
class QPalette;
|
||||
class QRect;
|
||||
class QwtText;
|
||||
|
||||
/*!
|
||||
\brief Directed rectangle representing bounding rectangle and orientation
|
||||
of a column.
|
||||
*/
|
||||
class QWT_EXPORT QwtColumnRect
|
||||
{
|
||||
public:
|
||||
//! Direction of the column
|
||||
enum Direction
|
||||
{
|
||||
//! From left to right
|
||||
LeftToRight,
|
||||
|
||||
//! From right to left
|
||||
RightToLeft,
|
||||
|
||||
//! From bottom to top
|
||||
BottomToTop,
|
||||
|
||||
//! From top to bottom
|
||||
TopToBottom
|
||||
};
|
||||
|
||||
//! Build an rectangle with invalid intervals directed BottomToTop.
|
||||
QwtColumnRect():
|
||||
direction( BottomToTop )
|
||||
{
|
||||
}
|
||||
|
||||
//! \return A normalized QRect built from the intervals
|
||||
QRectF toRect() const
|
||||
{
|
||||
QRectF r( hInterval.minValue(), vInterval.minValue(),
|
||||
hInterval.maxValue() - hInterval.minValue(),
|
||||
vInterval.maxValue() - vInterval.minValue() );
|
||||
r = r.normalized();
|
||||
|
||||
if ( hInterval.borderFlags() & QwtInterval::ExcludeMinimum )
|
||||
r.adjust( 1, 0, 0, 0 );
|
||||
if ( hInterval.borderFlags() & QwtInterval::ExcludeMaximum )
|
||||
r.adjust( 0, 0, -1, 0 );
|
||||
if ( vInterval.borderFlags() & QwtInterval::ExcludeMinimum )
|
||||
r.adjust( 0, 1, 0, 0 );
|
||||
if ( vInterval.borderFlags() & QwtInterval::ExcludeMaximum )
|
||||
r.adjust( 0, 0, 0, -1 );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//! \return Orientation
|
||||
Qt::Orientation orientation() const
|
||||
{
|
||||
if ( direction == LeftToRight || direction == RightToLeft )
|
||||
return Qt::Horizontal;
|
||||
|
||||
return Qt::Vertical;
|
||||
}
|
||||
|
||||
//! Interval for the horizontal coordinates
|
||||
QwtInterval hInterval;
|
||||
|
||||
//! Interval for the vertical coordinates
|
||||
QwtInterval vInterval;
|
||||
|
||||
//! Direction
|
||||
Direction direction;
|
||||
};
|
||||
|
||||
//! A drawing primitive for columns
|
||||
class QWT_EXPORT QwtColumnSymbol
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
Style
|
||||
\sa setStyle(), style()
|
||||
*/
|
||||
enum Style
|
||||
{
|
||||
//! No Style, the symbol draws nothing
|
||||
NoStyle = -1,
|
||||
|
||||
/*!
|
||||
The column is painted with a frame depending on the frameStyle()
|
||||
and lineWidth() using the palette().
|
||||
*/
|
||||
Box,
|
||||
|
||||
/*!
|
||||
Styles >= QwtColumnSymbol::UserStyle are reserved for derived
|
||||
classes of QwtColumnSymbol that overload draw() with
|
||||
additional application specific symbol types.
|
||||
*/
|
||||
UserStyle = 1000
|
||||
};
|
||||
|
||||
/*!
|
||||
Frame Style used in Box style().
|
||||
\sa Style, setFrameStyle(), frameStyle(), setStyle(), setPalette()
|
||||
*/
|
||||
enum FrameStyle
|
||||
{
|
||||
//! No frame
|
||||
NoFrame,
|
||||
|
||||
//! A plain frame style
|
||||
Plain,
|
||||
|
||||
//! A raised frame style
|
||||
Raised
|
||||
};
|
||||
|
||||
public:
|
||||
QwtColumnSymbol( Style = NoStyle );
|
||||
virtual ~QwtColumnSymbol();
|
||||
|
||||
void setFrameStyle( FrameStyle );
|
||||
FrameStyle frameStyle() const;
|
||||
|
||||
void setLineWidth( int width );
|
||||
int lineWidth() const;
|
||||
|
||||
void setPalette( const QPalette & );
|
||||
const QPalette &palette() const;
|
||||
|
||||
void setStyle( Style );
|
||||
Style style() const;
|
||||
|
||||
virtual void draw( QPainter *, const QwtColumnRect & ) const;
|
||||
|
||||
protected:
|
||||
void drawBox( QPainter *, const QwtColumnRect & ) const;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData* d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
308
third/3rd_qwt/qwt_compass.cpp
Normal file
308
third/3rd_qwt/qwt_compass.cpp
Normal file
@@ -0,0 +1,308 @@
|
||||
/* -*- 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_compass.h"
|
||||
#include "qwt_compass_rose.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_scale_draw.h"
|
||||
#include "qwt_painter.h"
|
||||
#include "qwt_dial_needle.h"
|
||||
#include <qpainter.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qevent.h>
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
|
||||
Initializes a label map for multiples of 45 degrees
|
||||
*/
|
||||
QwtCompassScaleDraw::QwtCompassScaleDraw()
|
||||
{
|
||||
enableComponent( QwtAbstractScaleDraw::Backbone, false );
|
||||
enableComponent( QwtAbstractScaleDraw::Ticks, false );
|
||||
|
||||
d_labelMap.insert( 0.0, QString::fromLatin1( "N" ) );
|
||||
d_labelMap.insert( 45.0, QString::fromLatin1( "NE" ) );
|
||||
d_labelMap.insert( 90.0, QString::fromLatin1( "E" ) );
|
||||
d_labelMap.insert( 135.0, QString::fromLatin1( "SE" ) );
|
||||
d_labelMap.insert( 180.0, QString::fromLatin1( "S" ) );
|
||||
d_labelMap.insert( 225.0, QString::fromLatin1( "SW" ) );
|
||||
d_labelMap.insert( 270.0, QString::fromLatin1( "W" ) );
|
||||
d_labelMap.insert( 315.0, QString::fromLatin1( "NW" ) );
|
||||
|
||||
#if 0
|
||||
d_labelMap.insert( 22.5, QString::fromLatin1( "NNE" ) );
|
||||
d_labelMap.insert( 67.5, QString::fromLatin1( "NEE" ) );
|
||||
d_labelMap.insert( 112.5, QString::fromLatin1( "SEE" ) );
|
||||
d_labelMap.insert( 157.5, QString::fromLatin1( "SSE" ) );
|
||||
d_labelMap.insert( 202.5, QString::fromLatin1( "SSW" ) );
|
||||
d_labelMap.insert( 247.5, QString::fromLatin1( "SWW" ) );
|
||||
d_labelMap.insert( 292.5, QString::fromLatin1( "NWW" ) );
|
||||
d_labelMap.insert( 337.5, QString::fromLatin1( "NNW" ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
|
||||
\param map Value to label map
|
||||
*/
|
||||
QwtCompassScaleDraw::QwtCompassScaleDraw( const QMap<double, QString> &map ):
|
||||
d_labelMap( map )
|
||||
{
|
||||
enableComponent( QwtAbstractScaleDraw::Backbone, false );
|
||||
enableComponent( QwtAbstractScaleDraw::Ticks, false );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set a map, mapping values to labels
|
||||
\param map Value to label map
|
||||
|
||||
The values of the major ticks are found by looking into this
|
||||
map. The default map consists of the labels N, NE, E, SE, S, SW, W, NW.
|
||||
|
||||
\warning The map will have no effect for values that are no major
|
||||
tick values. Major ticks can be changed by QwtScaleDraw::setScale
|
||||
|
||||
\sa labelMap(), scaleDraw(), setScale()
|
||||
*/
|
||||
void QwtCompassScaleDraw::setLabelMap( const QMap<double, QString> &map )
|
||||
{
|
||||
d_labelMap = map;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\return map, mapping values to labels
|
||||
\sa setLabelMap()
|
||||
*/
|
||||
QMap<double, QString> QwtCompassScaleDraw::labelMap() const
|
||||
{
|
||||
return d_labelMap;
|
||||
}
|
||||
|
||||
/*!
|
||||
Map a value to a corresponding label
|
||||
|
||||
\param value Value that will be mapped
|
||||
|
||||
label() looks in the labelMap() for a corresponding label for value
|
||||
or returns an null text.
|
||||
|
||||
\return Label
|
||||
\sa labelMap(), setLabelMap()
|
||||
*/
|
||||
|
||||
QwtText QwtCompassScaleDraw::label( double value ) const
|
||||
{
|
||||
if ( qFuzzyCompare( value + 1.0, 1.0 ) )
|
||||
value = 0.0;
|
||||
|
||||
if ( value < 0.0 )
|
||||
value += 360.0;
|
||||
|
||||
if ( d_labelMap.contains( value ) )
|
||||
return d_labelMap[value];
|
||||
|
||||
return QwtText();
|
||||
}
|
||||
|
||||
class QwtCompass::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
rose( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
~PrivateData()
|
||||
{
|
||||
delete rose;
|
||||
}
|
||||
|
||||
QwtCompassRose *rose;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
\param parent Parent widget
|
||||
|
||||
Create a compass widget with a scale, no needle and no rose.
|
||||
The default origin is 270.0 with no valid value. It accepts
|
||||
mouse and keyboard inputs and has no step size. The default mode
|
||||
is QwtDial::RotateNeedle.
|
||||
*/
|
||||
QwtCompass::QwtCompass( QWidget* parent ):
|
||||
QwtDial( parent )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
|
||||
setScaleDraw( new QwtCompassScaleDraw() );
|
||||
|
||||
setOrigin( 270.0 );
|
||||
setWrapping( true );
|
||||
|
||||
setScaleMaxMajor( 36 );
|
||||
setScaleMaxMinor( 10 );
|
||||
|
||||
setScale( 0.0, 360.0 ); // degrees as default
|
||||
setTotalSteps( 360 );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtCompass::~QwtCompass()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Draw the contents of the scale
|
||||
|
||||
\param painter Painter
|
||||
\param center Center of the content circle
|
||||
\param radius Radius of the content circle
|
||||
*/
|
||||
void QwtCompass::drawScaleContents( QPainter *painter,
|
||||
const QPointF ¢er, double radius ) const
|
||||
{
|
||||
QPalette::ColorGroup cg;
|
||||
if ( isEnabled() )
|
||||
cg = hasFocus() ? QPalette::Active : QPalette::Inactive;
|
||||
else
|
||||
cg = QPalette::Disabled;
|
||||
|
||||
double north = origin();
|
||||
if ( isValid() )
|
||||
{
|
||||
if ( mode() == RotateScale )
|
||||
north -= value();
|
||||
}
|
||||
|
||||
const int margin = 4;
|
||||
drawRose( painter, center, radius - margin, 360.0 - north, cg );
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the compass rose
|
||||
|
||||
\param painter Painter
|
||||
\param center Center of the compass
|
||||
\param radius of the circle, where to paint the rose
|
||||
\param north Direction pointing north, in degrees counter clockwise
|
||||
\param cg Color group
|
||||
*/
|
||||
void QwtCompass::drawRose( QPainter *painter, const QPointF ¢er,
|
||||
double radius, double north, QPalette::ColorGroup cg ) const
|
||||
{
|
||||
if ( d_data->rose )
|
||||
d_data->rose->draw( painter, center, radius, north, cg );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set a rose for the compass
|
||||
\param rose Compass rose
|
||||
\warning The rose will be deleted, when a different rose is
|
||||
set or in ~QwtCompass
|
||||
\sa rose()
|
||||
*/
|
||||
void QwtCompass::setRose( QwtCompassRose *rose )
|
||||
{
|
||||
if ( rose != d_data->rose )
|
||||
{
|
||||
if ( d_data->rose )
|
||||
delete d_data->rose;
|
||||
|
||||
d_data->rose = rose;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return rose
|
||||
\sa setRose()
|
||||
*/
|
||||
const QwtCompassRose *QwtCompass::rose() const
|
||||
{
|
||||
return d_data->rose;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return rose
|
||||
\sa setRose()
|
||||
*/
|
||||
QwtCompassRose *QwtCompass::rose()
|
||||
{
|
||||
return d_data->rose;
|
||||
}
|
||||
|
||||
/*!
|
||||
Handles key events
|
||||
|
||||
Beside the keys described in QwtDial::keyPressEvent numbers
|
||||
from 1-9 (without 5) set the direction according to their
|
||||
position on the num pad.
|
||||
|
||||
\sa isReadOnly()
|
||||
*/
|
||||
void QwtCompass::keyPressEvent( QKeyEvent *kev )
|
||||
{
|
||||
if ( isReadOnly() )
|
||||
return;
|
||||
|
||||
#if 0
|
||||
if ( kev->key() == Key_5 )
|
||||
{
|
||||
invalidate(); // signal ???
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
double newValue = value();
|
||||
|
||||
if ( kev->key() >= Qt::Key_1 && kev->key() <= Qt::Key_9 )
|
||||
{
|
||||
if ( mode() != RotateNeedle || kev->key() == Qt::Key_5 )
|
||||
return;
|
||||
|
||||
switch ( kev->key() )
|
||||
{
|
||||
case Qt::Key_6:
|
||||
newValue = 180.0 * 0.0;
|
||||
break;
|
||||
case Qt::Key_3:
|
||||
newValue = 180.0 * 0.25;
|
||||
break;
|
||||
case Qt::Key_2:
|
||||
newValue = 180.0 * 0.5;
|
||||
break;
|
||||
case Qt::Key_1:
|
||||
newValue = 180.0 * 0.75;
|
||||
break;
|
||||
case Qt::Key_4:
|
||||
newValue = 180.0 * 1.0;
|
||||
break;
|
||||
case Qt::Key_7:
|
||||
newValue = 180.0 * 1.25;
|
||||
break;
|
||||
case Qt::Key_8:
|
||||
newValue = 180.0 * 1.5;
|
||||
break;
|
||||
case Qt::Key_9:
|
||||
newValue = 180.0 * 1.75;
|
||||
break;
|
||||
}
|
||||
newValue -= origin();
|
||||
setValue( newValue );
|
||||
}
|
||||
else
|
||||
{
|
||||
QwtDial::keyPressEvent( kev );
|
||||
}
|
||||
}
|
||||
83
third/3rd_qwt/qwt_compass.h
Normal file
83
third/3rd_qwt/qwt_compass.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_COMPASS_H
|
||||
#define QWT_COMPASS_H 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_dial.h"
|
||||
#include "qwt_round_scale_draw.h"
|
||||
#include <qstring.h>
|
||||
#include <qmap.h>
|
||||
|
||||
class QwtCompassRose;
|
||||
|
||||
/*!
|
||||
\brief A special scale draw made for QwtCompass
|
||||
|
||||
QwtCompassScaleDraw maps values to strings using
|
||||
a special map, that can be modified by the application
|
||||
|
||||
The default map consists of the labels N, NE, E, SE, S, SW, W, NW.
|
||||
|
||||
\sa QwtCompass
|
||||
*/
|
||||
class QWT_EXPORT QwtCompassScaleDraw: public QwtRoundScaleDraw
|
||||
{
|
||||
public:
|
||||
explicit QwtCompassScaleDraw();
|
||||
explicit QwtCompassScaleDraw( const QMap<double, QString> &map );
|
||||
|
||||
void setLabelMap( const QMap<double, QString> &map );
|
||||
QMap<double, QString> labelMap() const;
|
||||
|
||||
virtual QwtText label( double value ) const;
|
||||
|
||||
private:
|
||||
QMap<double, QString> d_labelMap;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A Compass Widget
|
||||
|
||||
QwtCompass is a widget to display and enter directions. It consists
|
||||
of a scale, an optional needle and rose.
|
||||
|
||||
\image html dials1.png
|
||||
|
||||
\note The examples/dials example shows how to use QwtCompass.
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtCompass: public QwtDial
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QwtCompass( QWidget* parent = NULL );
|
||||
virtual ~QwtCompass();
|
||||
|
||||
void setRose( QwtCompassRose *rose );
|
||||
const QwtCompassRose *rose() const;
|
||||
QwtCompassRose *rose();
|
||||
|
||||
protected:
|
||||
virtual void drawRose( QPainter *, const QPointF ¢er,
|
||||
double radius, double north, QPalette::ColorGroup ) const;
|
||||
|
||||
virtual void drawScaleContents( QPainter *,
|
||||
const QPointF ¢er, double radius ) const;
|
||||
|
||||
virtual void keyPressEvent( QKeyEvent * );
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
270
third/3rd_qwt/qwt_compass_rose.cpp
Normal file
270
third/3rd_qwt/qwt_compass_rose.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/* -*- 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_compass_rose.h"
|
||||
#include "qwt_point_polar.h"
|
||||
#include "qwt_painter.h"
|
||||
#include "qpainterpath.h"
|
||||
#include "qpainter.h"
|
||||
|
||||
static QPointF qwtIntersection(
|
||||
QPointF p11, QPointF p12, QPointF p21, QPointF p22 )
|
||||
{
|
||||
const QLineF line1( p11, p12 );
|
||||
const QLineF line2( p21, p22 );
|
||||
|
||||
QPointF pos;
|
||||
if ( line1.intersect( line2, &pos ) == QLineF::NoIntersection )
|
||||
return QPointF();
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
class QwtSimpleCompassRose::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
width( 0.2 ),
|
||||
numThorns( 8 ),
|
||||
numThornLevels( -1 ),
|
||||
shrinkFactor( 0.9 )
|
||||
{
|
||||
}
|
||||
|
||||
double width;
|
||||
int numThorns;
|
||||
int numThornLevels;
|
||||
double shrinkFactor;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
\param numThorns Number of thorns
|
||||
\param numThornLevels Number of thorn levels
|
||||
*/
|
||||
QwtSimpleCompassRose::QwtSimpleCompassRose(
|
||||
int numThorns, int numThornLevels )
|
||||
{
|
||||
d_data = new PrivateData();
|
||||
d_data->numThorns = numThorns;
|
||||
d_data->numThornLevels = numThornLevels;
|
||||
|
||||
const QColor dark( 128, 128, 255 );
|
||||
const QColor light( 192, 255, 255 );
|
||||
|
||||
QPalette palette;
|
||||
palette.setColor( QPalette::Dark, dark );
|
||||
palette.setColor( QPalette::Light, light );
|
||||
|
||||
setPalette( palette );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtSimpleCompassRose::~QwtSimpleCompassRose()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the Factor how to shrink the thorns with each level
|
||||
The default value is 0.9.
|
||||
|
||||
\param factor Shrink factor
|
||||
\sa shrinkFactor()
|
||||
*/
|
||||
void QwtSimpleCompassRose::setShrinkFactor( double factor )
|
||||
{
|
||||
d_data->shrinkFactor = factor;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Factor how to shrink the thorns with each level
|
||||
\sa setShrinkFactor()
|
||||
*/
|
||||
double QwtSimpleCompassRose::shrinkFactor() const
|
||||
{
|
||||
return d_data->shrinkFactor;
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the rose
|
||||
|
||||
\param painter Painter
|
||||
\param center Center point
|
||||
\param radius Radius of the rose
|
||||
\param north Position
|
||||
\param cg Color group
|
||||
*/
|
||||
void QwtSimpleCompassRose::draw( QPainter *painter, const QPointF ¢er,
|
||||
double radius, double north, QPalette::ColorGroup cg ) const
|
||||
{
|
||||
QPalette pal = palette();
|
||||
pal.setCurrentColorGroup( cg );
|
||||
|
||||
drawRose( painter, pal, center, radius, north, d_data->width,
|
||||
d_data->numThorns, d_data->numThornLevels, d_data->shrinkFactor );
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the rose
|
||||
|
||||
\param painter Painter
|
||||
\param palette Palette
|
||||
\param center Center of the rose
|
||||
\param radius Radius of the rose
|
||||
\param north Position pointing to north
|
||||
\param width Width of the rose
|
||||
\param numThorns Number of thorns
|
||||
\param numThornLevels Number of thorn levels
|
||||
\param shrinkFactor Factor to shrink the thorns with each level
|
||||
*/
|
||||
void QwtSimpleCompassRose::drawRose(
|
||||
QPainter *painter,
|
||||
const QPalette &palette,
|
||||
const QPointF ¢er, double radius, double north, double width,
|
||||
int numThorns, int numThornLevels, double shrinkFactor )
|
||||
{
|
||||
if ( numThorns < 4 )
|
||||
numThorns = 4;
|
||||
|
||||
if ( numThorns % 4 )
|
||||
numThorns += 4 - numThorns % 4;
|
||||
|
||||
if ( numThornLevels <= 0 )
|
||||
numThornLevels = numThorns / 4;
|
||||
|
||||
if ( shrinkFactor >= 1.0 )
|
||||
shrinkFactor = 1.0;
|
||||
|
||||
if ( shrinkFactor <= 0.5 )
|
||||
shrinkFactor = 0.5;
|
||||
|
||||
painter->save();
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
|
||||
for ( int j = 1; j <= numThornLevels; j++ )
|
||||
{
|
||||
double step = qPow( 2.0, j ) * M_PI / numThorns;
|
||||
if ( step > M_PI_2 )
|
||||
break;
|
||||
|
||||
double r = radius;
|
||||
for ( int k = 0; k < 3; k++ )
|
||||
{
|
||||
if ( j + k < numThornLevels )
|
||||
r *= shrinkFactor;
|
||||
}
|
||||
|
||||
double leafWidth = r * width;
|
||||
if ( 2.0 * M_PI / step > 32 )
|
||||
leafWidth = 16;
|
||||
|
||||
const double origin = qwtRadians( north );
|
||||
for ( double angle = origin;
|
||||
angle < 2.0 * M_PI + origin; angle += step )
|
||||
{
|
||||
const QPointF p = qwtPolar2Pos( center, r, angle );
|
||||
const QPointF p1 = qwtPolar2Pos( center, leafWidth, angle + M_PI_2 );
|
||||
const QPointF p2 = qwtPolar2Pos( center, leafWidth, angle - M_PI_2 );
|
||||
const QPointF p3 = qwtPolar2Pos( center, r, angle + step / 2.0 );
|
||||
const QPointF p4 = qwtPolar2Pos( center, r, angle - step / 2.0 );
|
||||
|
||||
QPainterPath darkPath;
|
||||
darkPath.moveTo( center );
|
||||
darkPath.lineTo( p );
|
||||
darkPath.lineTo( qwtIntersection( center, p3, p1, p ) );
|
||||
|
||||
painter->setBrush( palette.brush( QPalette::Dark ) );
|
||||
painter->drawPath( darkPath );
|
||||
|
||||
QPainterPath lightPath;
|
||||
lightPath.moveTo( center );
|
||||
lightPath.lineTo( p );
|
||||
lightPath.lineTo( qwtIntersection( center, p4, p2, p ) );
|
||||
|
||||
painter->setBrush( palette.brush( QPalette::Light ) );
|
||||
painter->drawPath( lightPath );
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the width of the rose heads. Lower value make thinner heads.
|
||||
The range is limited from 0.03 to 0.4.
|
||||
|
||||
\param width Width
|
||||
*/
|
||||
void QwtSimpleCompassRose::setWidth( double width )
|
||||
{
|
||||
d_data->width = width;
|
||||
if ( d_data->width < 0.03 )
|
||||
d_data->width = 0.03;
|
||||
|
||||
if ( d_data->width > 0.4 )
|
||||
d_data->width = 0.4;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Width of the rose
|
||||
\sa setWidth()
|
||||
*/
|
||||
double QwtSimpleCompassRose::width() const
|
||||
{
|
||||
return d_data->width;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the number of thorns on one level
|
||||
The number is aligned to a multiple of 4, with a minimum of 4
|
||||
|
||||
\param numThorns Number of thorns
|
||||
\sa numThorns(), setNumThornLevels()
|
||||
*/
|
||||
void QwtSimpleCompassRose::setNumThorns( int numThorns )
|
||||
{
|
||||
if ( numThorns < 4 )
|
||||
numThorns = 4;
|
||||
|
||||
if ( numThorns % 4 )
|
||||
numThorns += 4 - numThorns % 4;
|
||||
|
||||
d_data->numThorns = numThorns;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of thorns
|
||||
\sa setNumThorns(), setNumThornLevels()
|
||||
*/
|
||||
int QwtSimpleCompassRose::numThorns() const
|
||||
{
|
||||
return d_data->numThorns;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the of thorns levels
|
||||
|
||||
\param numThornLevels Number of thorns levels
|
||||
\sa setNumThorns(), numThornLevels()
|
||||
*/
|
||||
void QwtSimpleCompassRose::setNumThornLevels( int numThornLevels )
|
||||
{
|
||||
d_data->numThornLevels = numThornLevels;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of thorn levels
|
||||
\sa setNumThorns(), setNumThornLevels()
|
||||
*/
|
||||
int QwtSimpleCompassRose::numThornLevels() const
|
||||
{
|
||||
return d_data->numThornLevels;
|
||||
}
|
||||
89
third/3rd_qwt/qwt_compass_rose.h
Normal file
89
third/3rd_qwt/qwt_compass_rose.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_COMPASS_ROSE_H
|
||||
#define QWT_COMPASS_ROSE_H 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qpalette.h>
|
||||
|
||||
class QPainter;
|
||||
|
||||
/*!
|
||||
\brief Abstract base class for a compass rose
|
||||
*/
|
||||
class QWT_EXPORT QwtCompassRose
|
||||
{
|
||||
public:
|
||||
//! Destructor
|
||||
virtual ~QwtCompassRose() {};
|
||||
|
||||
//! Assign a palette
|
||||
virtual void setPalette( const QPalette &p )
|
||||
{
|
||||
d_palette = p;
|
||||
}
|
||||
|
||||
//! \return Current palette
|
||||
const QPalette &palette() const
|
||||
{
|
||||
return d_palette;
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the rose
|
||||
|
||||
\param painter Painter
|
||||
\param center Center point
|
||||
\param radius Radius of the rose
|
||||
\param north Position
|
||||
\param colorGroup Color group
|
||||
*/
|
||||
virtual void draw( QPainter *painter,
|
||||
const QPointF ¢er, double radius, double north,
|
||||
QPalette::ColorGroup colorGroup = QPalette::Active ) const = 0;
|
||||
|
||||
private:
|
||||
QPalette d_palette;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A simple rose for QwtCompass
|
||||
*/
|
||||
class QWT_EXPORT QwtSimpleCompassRose: public QwtCompassRose
|
||||
{
|
||||
public:
|
||||
QwtSimpleCompassRose( int numThorns = 8, int numThornLevels = -1 );
|
||||
virtual ~QwtSimpleCompassRose();
|
||||
|
||||
void setWidth( double );
|
||||
double width() const;
|
||||
|
||||
void setNumThorns( int );
|
||||
int numThorns() const;
|
||||
|
||||
void setNumThornLevels( int );
|
||||
int numThornLevels() const;
|
||||
|
||||
void setShrinkFactor( double factor );
|
||||
double shrinkFactor() const;
|
||||
|
||||
virtual void draw( QPainter *, const QPointF ¢er, double radius,
|
||||
double north, QPalette::ColorGroup = QPalette::Active ) const;
|
||||
|
||||
static void drawRose( QPainter *, const QPalette &,
|
||||
const QPointF ¢er, double radius, double north, double width,
|
||||
int numThorns, int numThornLevels, double shrinkFactor );
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
42
third/3rd_qwt/qwt_compat.h
Normal file
42
third/3rd_qwt/qwt_compat.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _QWT_COMPAT_H_
|
||||
#define _QWT_COMPAT_H_
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_interval.h"
|
||||
#include "qwt_point_3d.h"
|
||||
#include <qlist.h>
|
||||
#include <qvector.h>
|
||||
#include <qpoint.h>
|
||||
#include <qsize.h>
|
||||
#include <qrect.h>
|
||||
#include <qpolygon.h>
|
||||
|
||||
// A couple of definition for Qwt5 compatibility
|
||||
|
||||
#define qwtMax qMax
|
||||
#define qwtMin qMin
|
||||
#define qwtAbs qAbs
|
||||
#define qwtRound qRound
|
||||
|
||||
#define QwtArray QVector
|
||||
|
||||
typedef QList<double> QwtValueList;
|
||||
typedef QPointF QwtDoublePoint;
|
||||
typedef QSizeF QwtDoubleSize;
|
||||
typedef QRectF QwtDoubleRect;
|
||||
|
||||
typedef QPolygon QwtPolygon;
|
||||
typedef QPolygonF QwtPolygonF;
|
||||
typedef QwtInterval QwtDoubleInterval;
|
||||
typedef QwtPoint3D QwtDoublePoint3D;
|
||||
|
||||
#endif
|
||||
784
third/3rd_qwt/qwt_counter.cpp
Normal file
784
third/3rd_qwt/qwt_counter.cpp
Normal file
@@ -0,0 +1,784 @@
|
||||
/* -*- 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_arrow_button.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_counter.h"
|
||||
#include <qlayout.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qvalidator.h>
|
||||
#include <qevent.h>
|
||||
#include <qstyle.h>
|
||||
|
||||
class QwtCounter::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
minimum( 0.0 ),
|
||||
maximum( 0.0 ),
|
||||
singleStep( 1.0 ),
|
||||
isValid( false ),
|
||||
value( 0.0 ),
|
||||
wrapping( false )
|
||||
{
|
||||
increment[Button1] = 1;
|
||||
increment[Button2] = 10;
|
||||
increment[Button3] = 100;
|
||||
}
|
||||
|
||||
QwtArrowButton *buttonDown[ButtonCnt];
|
||||
QwtArrowButton *buttonUp[ButtonCnt];
|
||||
QLineEdit *valueEdit;
|
||||
|
||||
int increment[ButtonCnt];
|
||||
int numButtons;
|
||||
|
||||
double minimum;
|
||||
double maximum;
|
||||
double singleStep;
|
||||
|
||||
bool isValid;
|
||||
double value;
|
||||
|
||||
bool wrapping;
|
||||
};
|
||||
|
||||
/*!
|
||||
The counter is initialized with a range is set to [0.0, 1.0] with
|
||||
0.01 as single step size. The value is invalid.
|
||||
|
||||
The default number of buttons is set to 2. The default increments are:
|
||||
\li Button 1: 1 step
|
||||
\li Button 2: 10 steps
|
||||
\li Button 3: 100 steps
|
||||
|
||||
\param parent
|
||||
*/
|
||||
QwtCounter::QwtCounter( QWidget *parent ):
|
||||
QWidget( parent )
|
||||
{
|
||||
initCounter();
|
||||
}
|
||||
|
||||
void QwtCounter::initCounter()
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout( this );
|
||||
layout->setSpacing( 0 );
|
||||
layout->setMargin( 0 );
|
||||
|
||||
for ( int i = ButtonCnt - 1; i >= 0; i-- )
|
||||
{
|
||||
QwtArrowButton *btn =
|
||||
new QwtArrowButton( i + 1, Qt::DownArrow, this );
|
||||
btn->setFocusPolicy( Qt::NoFocus );
|
||||
btn->installEventFilter( this );
|
||||
layout->addWidget( btn );
|
||||
|
||||
connect( btn, SIGNAL(released()), SLOT(btnReleased()) );
|
||||
connect( btn, SIGNAL(clicked()), SLOT(btnClicked()) );
|
||||
|
||||
d_data->buttonDown[i] = btn;
|
||||
}
|
||||
|
||||
d_data->valueEdit = new QLineEdit( this );
|
||||
d_data->valueEdit->setReadOnly( false );
|
||||
d_data->valueEdit->setValidator( new QDoubleValidator( d_data->valueEdit ) );
|
||||
layout->addWidget( d_data->valueEdit );
|
||||
|
||||
connect( d_data->valueEdit, SIGNAL(editingFinished()), SLOT(textChanged()) );
|
||||
|
||||
layout->setStretchFactor( d_data->valueEdit, 10 );
|
||||
|
||||
for ( int i = 0; i < ButtonCnt; i++ )
|
||||
{
|
||||
QwtArrowButton *btn =
|
||||
new QwtArrowButton( i + 1, Qt::UpArrow, this );
|
||||
btn->setFocusPolicy( Qt::NoFocus );
|
||||
btn->installEventFilter( this );
|
||||
layout->addWidget( btn );
|
||||
|
||||
connect( btn, SIGNAL(released()), SLOT(btnReleased()) );
|
||||
connect( btn, SIGNAL(clicked()), SLOT(btnClicked()) );
|
||||
|
||||
d_data->buttonUp[i] = btn;
|
||||
}
|
||||
|
||||
setNumButtons( 2 );
|
||||
setRange( 0.0, 1.0 );
|
||||
setSingleStep( 0.001 );
|
||||
setValue( 0.0 );
|
||||
|
||||
setSizePolicy(
|
||||
QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
|
||||
|
||||
setFocusProxy( d_data->valueEdit );
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtCounter::~QwtCounter()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the counter to be in valid/invalid state
|
||||
|
||||
When the counter is set to invalid, no numbers are displayed and
|
||||
the buttons are disabled.
|
||||
|
||||
\param on If true the counter will be set as valid
|
||||
|
||||
\sa setValue(), isValid()
|
||||
*/
|
||||
void QwtCounter::setValid( bool on )
|
||||
{
|
||||
if ( on != d_data->isValid )
|
||||
{
|
||||
d_data->isValid = on;
|
||||
|
||||
updateButtons();
|
||||
|
||||
if ( d_data->isValid )
|
||||
{
|
||||
showNumber( value() );
|
||||
Q_EMIT valueChanged( value() );
|
||||
}
|
||||
else
|
||||
{
|
||||
d_data->valueEdit->setText( QString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return True, if the value is valid
|
||||
\sa setValid(), setValue()
|
||||
*/
|
||||
bool QwtCounter::isValid() const
|
||||
{
|
||||
return d_data->isValid;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Allow/disallow the user to manually edit the value
|
||||
|
||||
\param on True disable editing
|
||||
\sa isReadOnly()
|
||||
*/
|
||||
void QwtCounter::setReadOnly( bool on )
|
||||
{
|
||||
d_data->valueEdit->setReadOnly( on );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return True, when the line line edit is read only. (default is no)
|
||||
\sa setReadOnly()
|
||||
*/
|
||||
bool QwtCounter::isReadOnly() const
|
||||
{
|
||||
return d_data->valueEdit->isReadOnly();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set a new value without adjusting to the step raster
|
||||
|
||||
The state of the counter is set to be valid.
|
||||
|
||||
\param value New value
|
||||
|
||||
\sa isValid(), value(), valueChanged()
|
||||
\warning The value is clipped when it lies outside the range.
|
||||
*/
|
||||
|
||||
void QwtCounter::setValue( double value )
|
||||
{
|
||||
const double vmin = qMin( d_data->minimum, d_data->maximum );
|
||||
const double vmax = qMax( d_data->minimum, d_data->maximum );
|
||||
|
||||
value = qBound( vmin, value, vmax );
|
||||
|
||||
if ( !d_data->isValid || value != d_data->value )
|
||||
{
|
||||
d_data->isValid = true;
|
||||
d_data->value = value;
|
||||
|
||||
showNumber( value );
|
||||
updateButtons();
|
||||
|
||||
Q_EMIT valueChanged( value );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Current value of the counter
|
||||
\sa setValue(), valueChanged()
|
||||
*/
|
||||
double QwtCounter::value() const
|
||||
{
|
||||
return d_data->value;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the minimum and maximum values
|
||||
|
||||
The maximum is adjusted if necessary to ensure that the range remains valid.
|
||||
The value might be modified to be inside of the range.
|
||||
|
||||
\param min Minimum value
|
||||
\param max Maximum value
|
||||
|
||||
\sa minimum(), maximum()
|
||||
*/
|
||||
void QwtCounter::setRange( double min, double max )
|
||||
{
|
||||
max = qMax( min, max );
|
||||
|
||||
if ( d_data->maximum == max && d_data->minimum == min )
|
||||
return;
|
||||
|
||||
d_data->minimum = min;
|
||||
d_data->maximum = max;
|
||||
|
||||
setSingleStep( singleStep() );
|
||||
|
||||
const double value = qBound( min, d_data->value, max );
|
||||
|
||||
if ( value != d_data->value )
|
||||
{
|
||||
d_data->value = value;
|
||||
|
||||
if ( d_data->isValid )
|
||||
{
|
||||
showNumber( value );
|
||||
Q_EMIT valueChanged( value );
|
||||
}
|
||||
}
|
||||
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the minimum value of the range
|
||||
|
||||
\param value Minimum value
|
||||
\sa setRange(), setMaximum(), minimum()
|
||||
|
||||
\note The maximum is adjusted if necessary to ensure that the range remains valid.
|
||||
*/
|
||||
void QwtCounter::setMinimum( double value )
|
||||
{
|
||||
setRange( value, maximum() );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The minimum of the range
|
||||
\sa setRange(), setMinimum(), maximum()
|
||||
*/
|
||||
double QwtCounter::minimum() const
|
||||
{
|
||||
return d_data->minimum;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the maximum value of the range
|
||||
|
||||
\param value Maximum value
|
||||
\sa setRange(), setMinimum(), maximum()
|
||||
*/
|
||||
void QwtCounter::setMaximum( double value )
|
||||
{
|
||||
setRange( minimum(), value );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The maximum of the range
|
||||
\sa setRange(), setMaximum(), minimum()
|
||||
*/
|
||||
double QwtCounter::maximum() const
|
||||
{
|
||||
return d_data->maximum;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the step size of the counter
|
||||
|
||||
A value <= 0.0 disables stepping
|
||||
|
||||
\param stepSize Single step size
|
||||
\sa singleStep()
|
||||
*/
|
||||
void QwtCounter::setSingleStep( double stepSize )
|
||||
{
|
||||
d_data->singleStep = qMax( stepSize, 0.0 );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Single step size
|
||||
\sa setSingleStep()
|
||||
*/
|
||||
double QwtCounter::singleStep() const
|
||||
{
|
||||
return d_data->singleStep;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief En/Disable wrapping
|
||||
|
||||
If wrapping is true stepping up from maximum() value will take
|
||||
you to the minimum() value and vice versa.
|
||||
|
||||
\param on En/Disable wrapping
|
||||
\sa wrapping()
|
||||
*/
|
||||
void QwtCounter::setWrapping( bool on )
|
||||
{
|
||||
d_data->wrapping = on;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return True, when wrapping is set
|
||||
\sa setWrapping()
|
||||
*/
|
||||
bool QwtCounter::wrapping() const
|
||||
{
|
||||
return d_data->wrapping;
|
||||
}
|
||||
|
||||
/*!
|
||||
Specify the number of buttons on each side of the label
|
||||
|
||||
\param numButtons Number of buttons
|
||||
\sa numButtons()
|
||||
*/
|
||||
void QwtCounter::setNumButtons( int numButtons )
|
||||
{
|
||||
if ( numButtons < 0 || numButtons > QwtCounter::ButtonCnt )
|
||||
return;
|
||||
|
||||
for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
|
||||
{
|
||||
if ( i < numButtons )
|
||||
{
|
||||
d_data->buttonDown[i]->show();
|
||||
d_data->buttonUp[i]->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
d_data->buttonDown[i]->hide();
|
||||
d_data->buttonUp[i]->hide();
|
||||
}
|
||||
}
|
||||
|
||||
d_data->numButtons = numButtons;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The number of buttons on each side of the widget.
|
||||
\sa setNumButtons()
|
||||
*/
|
||||
int QwtCounter::numButtons() const
|
||||
{
|
||||
return d_data->numButtons;
|
||||
}
|
||||
|
||||
/*!
|
||||
Specify the number of steps by which the value
|
||||
is incremented or decremented when a specified button
|
||||
is pushed.
|
||||
|
||||
\param button Button index
|
||||
\param numSteps Number of steps
|
||||
|
||||
\sa incSteps()
|
||||
*/
|
||||
void QwtCounter::setIncSteps( QwtCounter::Button button, int numSteps )
|
||||
{
|
||||
if ( button >= 0 && button < QwtCounter::ButtonCnt )
|
||||
d_data->increment[ button ] = numSteps;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The number of steps by which a specified button increments the value
|
||||
or 0 if the button is invalid.
|
||||
\param button Button index
|
||||
|
||||
\sa setIncSteps()
|
||||
*/
|
||||
int QwtCounter::incSteps( QwtCounter::Button button ) const
|
||||
{
|
||||
if ( button >= 0 && button < QwtCounter::ButtonCnt )
|
||||
return d_data->increment[ button ];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Set the number of increment steps for button 1
|
||||
\param nSteps Number of steps
|
||||
*/
|
||||
void QwtCounter::setStepButton1( int nSteps )
|
||||
{
|
||||
setIncSteps( QwtCounter::Button1, nSteps );
|
||||
}
|
||||
|
||||
//! returns the number of increment steps for button 1
|
||||
int QwtCounter::stepButton1() const
|
||||
{
|
||||
return incSteps( QwtCounter::Button1 );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the number of increment steps for button 2
|
||||
\param nSteps Number of steps
|
||||
*/
|
||||
void QwtCounter::setStepButton2( int nSteps )
|
||||
{
|
||||
setIncSteps( QwtCounter::Button2, nSteps );
|
||||
}
|
||||
|
||||
//! returns the number of increment steps for button 2
|
||||
int QwtCounter::stepButton2() const
|
||||
{
|
||||
return incSteps( QwtCounter::Button2 );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the number of increment steps for button 3
|
||||
\param nSteps Number of steps
|
||||
*/
|
||||
void QwtCounter::setStepButton3( int nSteps )
|
||||
{
|
||||
setIncSteps( QwtCounter::Button3, nSteps );
|
||||
}
|
||||
|
||||
//! returns the number of increment steps for button 3
|
||||
int QwtCounter::stepButton3() const
|
||||
{
|
||||
return incSteps( QwtCounter::Button3 );
|
||||
}
|
||||
|
||||
//! Set from lineedit
|
||||
void QwtCounter::textChanged()
|
||||
{
|
||||
bool converted = false;
|
||||
|
||||
const double value = d_data->valueEdit->text().toDouble( &converted );
|
||||
if ( converted )
|
||||
setValue( value );
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle QEvent::PolishRequest events
|
||||
\param event Event
|
||||
\return see QWidget::event()
|
||||
*/
|
||||
bool QwtCounter::event( QEvent *event )
|
||||
{
|
||||
if ( event->type() == QEvent::PolishRequest )
|
||||
{
|
||||
const int w = d_data->valueEdit->fontMetrics().width( "W" ) + 8;
|
||||
for ( int i = 0; i < ButtonCnt; i++ )
|
||||
{
|
||||
d_data->buttonDown[i]->setMinimumWidth( w );
|
||||
d_data->buttonUp[i]->setMinimumWidth( w );
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::event( event );
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle key events
|
||||
|
||||
- Ctrl + Qt::Key_Home\n
|
||||
Step to minimum()
|
||||
- Ctrl + Qt::Key_End\n
|
||||
Step to maximum()
|
||||
- Qt::Key_Up\n
|
||||
Increment by incSteps(QwtCounter::Button1)
|
||||
- Qt::Key_Down\n
|
||||
Decrement by incSteps(QwtCounter::Button1)
|
||||
- Qt::Key_PageUp\n
|
||||
Increment by incSteps(QwtCounter::Button2)
|
||||
- Qt::Key_PageDown\n
|
||||
Decrement by incSteps(QwtCounter::Button2)
|
||||
- Shift + Qt::Key_PageUp\n
|
||||
Increment by incSteps(QwtCounter::Button3)
|
||||
- Shift + Qt::Key_PageDown\n
|
||||
Decrement by incSteps(QwtCounter::Button3)
|
||||
|
||||
\param event Key event
|
||||
*/
|
||||
void QwtCounter::keyPressEvent ( QKeyEvent *event )
|
||||
{
|
||||
bool accepted = true;
|
||||
|
||||
switch ( event->key() )
|
||||
{
|
||||
case Qt::Key_Home:
|
||||
{
|
||||
if ( event->modifiers() & Qt::ControlModifier )
|
||||
setValue( minimum() );
|
||||
else
|
||||
accepted = false;
|
||||
break;
|
||||
}
|
||||
case Qt::Key_End:
|
||||
{
|
||||
if ( event->modifiers() & Qt::ControlModifier )
|
||||
setValue( maximum() );
|
||||
else
|
||||
accepted = false;
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Up:
|
||||
{
|
||||
incrementValue( d_data->increment[0] );
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Down:
|
||||
{
|
||||
incrementValue( -d_data->increment[0] );
|
||||
break;
|
||||
}
|
||||
case Qt::Key_PageUp:
|
||||
case Qt::Key_PageDown:
|
||||
{
|
||||
int increment = d_data->increment[0];
|
||||
if ( d_data->numButtons >= 2 )
|
||||
increment = d_data->increment[1];
|
||||
if ( d_data->numButtons >= 3 )
|
||||
{
|
||||
if ( event->modifiers() & Qt::ShiftModifier )
|
||||
increment = d_data->increment[2];
|
||||
}
|
||||
if ( event->key() == Qt::Key_PageDown )
|
||||
increment = -increment;
|
||||
incrementValue( increment );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( accepted )
|
||||
{
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget::keyPressEvent ( event );
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle wheel events
|
||||
\param event Wheel event
|
||||
*/
|
||||
void QwtCounter::wheelEvent( QWheelEvent *event )
|
||||
{
|
||||
event->accept();
|
||||
|
||||
if ( d_data->numButtons <= 0 )
|
||||
return;
|
||||
|
||||
int increment = d_data->increment[0];
|
||||
if ( d_data->numButtons >= 2 )
|
||||
{
|
||||
if ( event->modifiers() & Qt::ControlModifier )
|
||||
increment = d_data->increment[1];
|
||||
}
|
||||
if ( d_data->numButtons >= 3 )
|
||||
{
|
||||
if ( event->modifiers() & Qt::ShiftModifier )
|
||||
increment = d_data->increment[2];
|
||||
}
|
||||
|
||||
for ( int i = 0; i < d_data->numButtons; i++ )
|
||||
{
|
||||
if ( d_data->buttonDown[i]->geometry().contains( event->pos() ) ||
|
||||
d_data->buttonUp[i]->geometry().contains( event->pos() ) )
|
||||
{
|
||||
increment = d_data->increment[i];
|
||||
}
|
||||
}
|
||||
|
||||
const int wheel_delta = 120;
|
||||
|
||||
#if 1
|
||||
int delta = event->delta();
|
||||
if ( delta >= 2 * wheel_delta )
|
||||
delta /= 2; // Never saw an abs(delta) < 240
|
||||
#endif
|
||||
|
||||
incrementValue( delta / wheel_delta * increment );
|
||||
}
|
||||
|
||||
void QwtCounter::incrementValue( int numSteps )
|
||||
{
|
||||
const double min = d_data->minimum;
|
||||
const double max = d_data->maximum;
|
||||
double stepSize = d_data->singleStep;
|
||||
|
||||
if ( !d_data->isValid || min >= max || stepSize <= 0.0 )
|
||||
return;
|
||||
|
||||
|
||||
#if 1
|
||||
stepSize = qMax( stepSize, 1.0e-10 * ( max - min ) );
|
||||
#endif
|
||||
|
||||
double value = d_data->value + numSteps * stepSize;
|
||||
|
||||
if ( d_data->wrapping )
|
||||
{
|
||||
const double range = max - min;
|
||||
|
||||
if ( value < min )
|
||||
{
|
||||
value += ::ceil( ( min - value ) / range ) * range;
|
||||
}
|
||||
else if ( value > max )
|
||||
{
|
||||
value -= ::ceil( ( value - max ) / range ) * range;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = qBound( min, value, max );
|
||||
}
|
||||
|
||||
value = min + qRound( ( value - min ) / stepSize ) * stepSize;
|
||||
|
||||
if ( stepSize > 1e-12 )
|
||||
{
|
||||
if ( qFuzzyCompare( value + 1.0, 1.0 ) )
|
||||
{
|
||||
// correct rounding error if value = 0
|
||||
value = 0.0;
|
||||
}
|
||||
else if ( qFuzzyCompare( value, max ) )
|
||||
{
|
||||
// correct rounding error at the border
|
||||
value = max;
|
||||
}
|
||||
}
|
||||
|
||||
if ( value != d_data->value )
|
||||
{
|
||||
d_data->value = value;
|
||||
showNumber( d_data->value );
|
||||
updateButtons();
|
||||
|
||||
Q_EMIT valueChanged( d_data->value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Update buttons according to the current value
|
||||
|
||||
When the QwtCounter under- or over-flows, the focus is set to the smallest
|
||||
up- or down-button and counting is disabled.
|
||||
|
||||
Counting is re-enabled on a button release event (mouse or space bar).
|
||||
*/
|
||||
void QwtCounter::updateButtons()
|
||||
{
|
||||
if ( d_data->isValid )
|
||||
{
|
||||
// 1. save enabled state of the smallest down- and up-button
|
||||
// 2. change enabled state on under- or over-flow
|
||||
|
||||
for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
|
||||
{
|
||||
d_data->buttonDown[i]->setEnabled( value() > minimum() );
|
||||
d_data->buttonUp[i]->setEnabled( value() < maximum() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
|
||||
{
|
||||
d_data->buttonDown[i]->setEnabled( false );
|
||||
d_data->buttonUp[i]->setEnabled( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Display number string
|
||||
|
||||
\param number Number
|
||||
*/
|
||||
void QwtCounter::showNumber( double number )
|
||||
{
|
||||
QString text;
|
||||
text.setNum( number );
|
||||
|
||||
const int cursorPos = d_data->valueEdit->cursorPosition();
|
||||
d_data->valueEdit->setText( text );
|
||||
d_data->valueEdit->setCursorPosition( cursorPos );
|
||||
}
|
||||
|
||||
//! Button clicked
|
||||
void QwtCounter::btnClicked()
|
||||
{
|
||||
for ( int i = 0; i < ButtonCnt; i++ )
|
||||
{
|
||||
if ( d_data->buttonUp[i] == sender() )
|
||||
incrementValue( d_data->increment[i] );
|
||||
|
||||
if ( d_data->buttonDown[i] == sender() )
|
||||
incrementValue( -d_data->increment[i] );
|
||||
}
|
||||
}
|
||||
|
||||
//! Button released
|
||||
void QwtCounter::btnReleased()
|
||||
{
|
||||
Q_EMIT buttonReleased( value() );
|
||||
}
|
||||
|
||||
//! A size hint
|
||||
QSize QwtCounter::sizeHint() const
|
||||
{
|
||||
QString tmp;
|
||||
|
||||
int w = tmp.setNum( minimum() ).length();
|
||||
int w1 = tmp.setNum( maximum() ).length();
|
||||
if ( w1 > w )
|
||||
w = w1;
|
||||
w1 = tmp.setNum( minimum() + singleStep() ).length();
|
||||
if ( w1 > w )
|
||||
w = w1;
|
||||
w1 = tmp.setNum( maximum() - singleStep() ).length();
|
||||
if ( w1 > w )
|
||||
w = w1;
|
||||
|
||||
tmp.fill( '9', w );
|
||||
|
||||
QFontMetrics fm( d_data->valueEdit->font() );
|
||||
w = fm.width( tmp ) + 2;
|
||||
if ( d_data->valueEdit->hasFrame() )
|
||||
w += 2 * style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
|
||||
|
||||
// Now we replace default sizeHint contribution of d_data->valueEdit by
|
||||
// what we really need.
|
||||
|
||||
w += QWidget::sizeHint().width() - d_data->valueEdit->sizeHint().width();
|
||||
|
||||
const int h = qMin( QWidget::sizeHint().height(),
|
||||
d_data->valueEdit->minimumSizeHint().height() );
|
||||
return QSize( w, h );
|
||||
}
|
||||
161
third/3rd_qwt/qwt_counter.h
Normal file
161
third/3rd_qwt/qwt_counter.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_COUNTER_H
|
||||
#define QWT_COUNTER_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qwidget.h>
|
||||
|
||||
/*!
|
||||
\brief The Counter Widget
|
||||
|
||||
A Counter consists of a label displaying a number and
|
||||
one ore more (up to three) push buttons on each side
|
||||
of the label which can be used to increment or decrement
|
||||
the counter's value.
|
||||
|
||||
A counter has a range from a minimum value to a maximum value
|
||||
and a step size. When the wrapping property is set
|
||||
the counter is circular.
|
||||
|
||||
The number of steps by which a button increments or decrements the value
|
||||
can be specified using setIncSteps(). The number of buttons can be
|
||||
changed with setNumButtons().
|
||||
|
||||
Example:
|
||||
\code
|
||||
#include <qwt_counter.h>
|
||||
|
||||
QwtCounter *counter = new QwtCounter(parent);
|
||||
|
||||
counter->setRange(0.0, 100.0); // From 0.0 to 100
|
||||
counter->setSingleStep( 1.0 ); // Step size 1.0
|
||||
counter->setNumButtons(2); // Two buttons each side
|
||||
counter->setIncSteps(QwtCounter::Button1, 1); // Button 1 increments 1 step
|
||||
counter->setIncSteps(QwtCounter::Button2, 20); // Button 2 increments 20 steps
|
||||
|
||||
connect(counter, SIGNAL(valueChanged(double)), myClass, SLOT(newValue(double)));
|
||||
\endcode
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtCounter : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( double value READ value WRITE setValue )
|
||||
Q_PROPERTY( double minimum READ minimum WRITE setMinimum )
|
||||
Q_PROPERTY( double maximum READ maximum WRITE setMaximum )
|
||||
Q_PROPERTY( double singleStep READ singleStep WRITE setSingleStep )
|
||||
|
||||
Q_PROPERTY( int numButtons READ numButtons WRITE setNumButtons )
|
||||
Q_PROPERTY( int stepButton1 READ stepButton1 WRITE setStepButton1 )
|
||||
Q_PROPERTY( int stepButton2 READ stepButton2 WRITE setStepButton2 )
|
||||
Q_PROPERTY( int stepButton3 READ stepButton3 WRITE setStepButton3 )
|
||||
|
||||
Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly )
|
||||
Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping )
|
||||
|
||||
public:
|
||||
//! Button index
|
||||
enum Button
|
||||
{
|
||||
//! Button intended for minor steps
|
||||
Button1,
|
||||
|
||||
//! Button intended for medium steps
|
||||
Button2,
|
||||
|
||||
//! Button intended for large steps
|
||||
Button3,
|
||||
|
||||
//! Number of buttons
|
||||
ButtonCnt
|
||||
};
|
||||
|
||||
explicit QwtCounter( QWidget *parent = NULL );
|
||||
virtual ~QwtCounter();
|
||||
|
||||
void setValid( bool );
|
||||
bool isValid() const;
|
||||
|
||||
void setWrapping( bool );
|
||||
bool wrapping() const;
|
||||
|
||||
bool isReadOnly() const;
|
||||
void setReadOnly( bool );
|
||||
|
||||
void setNumButtons( int );
|
||||
int numButtons() const;
|
||||
|
||||
void setIncSteps( QwtCounter::Button, int numSteps );
|
||||
int incSteps( QwtCounter::Button ) const;
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
double singleStep() const;
|
||||
void setSingleStep( double stepSize );
|
||||
|
||||
void setRange( double min, double max );
|
||||
|
||||
double minimum() const;
|
||||
void setMinimum( double );
|
||||
|
||||
double maximum() const;
|
||||
void setMaximum( double );
|
||||
|
||||
void setStepButton1( int nSteps );
|
||||
int stepButton1() const;
|
||||
|
||||
void setStepButton2( int nSteps );
|
||||
int stepButton2() const;
|
||||
|
||||
void setStepButton3( int nSteps );
|
||||
int stepButton3() const;
|
||||
|
||||
double value() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setValue( double );
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
/*!
|
||||
This signal is emitted when a button has been released
|
||||
\param value The new value
|
||||
*/
|
||||
void buttonReleased ( double value );
|
||||
|
||||
/*!
|
||||
This signal is emitted when the counter's value has changed
|
||||
\param value The new value
|
||||
*/
|
||||
void valueChanged ( double value );
|
||||
|
||||
protected:
|
||||
virtual bool event( QEvent * );
|
||||
virtual void wheelEvent( QWheelEvent * );
|
||||
virtual void keyPressEvent( QKeyEvent * );
|
||||
|
||||
private Q_SLOTS:
|
||||
void btnReleased();
|
||||
void btnClicked();
|
||||
void textChanged();
|
||||
|
||||
private:
|
||||
void incrementValue( int numSteps );
|
||||
void initCounter();
|
||||
void updateButtons();
|
||||
void showNumber( double );
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
454
third/3rd_qwt/qwt_curve_fitter.cpp
Normal file
454
third/3rd_qwt/qwt_curve_fitter.cpp
Normal file
@@ -0,0 +1,454 @@
|
||||
/* -*- 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_curve_fitter.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_spline.h"
|
||||
#include <qstack.h>
|
||||
#include <qvector.h>
|
||||
|
||||
#if QT_VERSION < 0x040601
|
||||
#define qFabs(x) ::fabs(x)
|
||||
#endif
|
||||
|
||||
//! Constructor
|
||||
QwtCurveFitter::QwtCurveFitter()
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtCurveFitter::~QwtCurveFitter()
|
||||
{
|
||||
}
|
||||
|
||||
class QwtSplineCurveFitter::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
fitMode( QwtSplineCurveFitter::Auto ),
|
||||
splineSize( 250 )
|
||||
{
|
||||
}
|
||||
|
||||
QwtSpline spline;
|
||||
QwtSplineCurveFitter::FitMode fitMode;
|
||||
int splineSize;
|
||||
};
|
||||
|
||||
//! Constructor
|
||||
QwtSplineCurveFitter::QwtSplineCurveFitter()
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtSplineCurveFitter::~QwtSplineCurveFitter()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Select the algorithm used for building the spline
|
||||
|
||||
\param mode Mode representing a spline algorithm
|
||||
\sa fitMode()
|
||||
*/
|
||||
void QwtSplineCurveFitter::setFitMode( FitMode mode )
|
||||
{
|
||||
d_data->fitMode = mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Mode representing a spline algorithm
|
||||
\sa setFitMode()
|
||||
*/
|
||||
QwtSplineCurveFitter::FitMode QwtSplineCurveFitter::fitMode() const
|
||||
{
|
||||
return d_data->fitMode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign a spline
|
||||
|
||||
\param spline Spline
|
||||
\sa spline()
|
||||
*/
|
||||
void QwtSplineCurveFitter::setSpline( const QwtSpline &spline )
|
||||
{
|
||||
d_data->spline = spline;
|
||||
d_data->spline.reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Spline
|
||||
\sa setSpline()
|
||||
*/
|
||||
const QwtSpline &QwtSplineCurveFitter::spline() const
|
||||
{
|
||||
return d_data->spline;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Spline
|
||||
\sa setSpline()
|
||||
*/
|
||||
QwtSpline &QwtSplineCurveFitter::spline()
|
||||
{
|
||||
return d_data->spline;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign a spline size ( has to be at least 10 points )
|
||||
|
||||
\param splineSize Spline size
|
||||
\sa splineSize()
|
||||
*/
|
||||
void QwtSplineCurveFitter::setSplineSize( int splineSize )
|
||||
{
|
||||
d_data->splineSize = qMax( splineSize, 10 );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Spline size
|
||||
\sa setSplineSize()
|
||||
*/
|
||||
int QwtSplineCurveFitter::splineSize() const
|
||||
{
|
||||
return d_data->splineSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
Find a curve which has the best fit to a series of data points
|
||||
|
||||
\param points Series of data points
|
||||
\return Curve points
|
||||
*/
|
||||
QPolygonF QwtSplineCurveFitter::fitCurve( const QPolygonF &points ) const
|
||||
{
|
||||
const int size = points.size();
|
||||
if ( size <= 2 )
|
||||
return points;
|
||||
|
||||
FitMode fitMode = d_data->fitMode;
|
||||
if ( fitMode == Auto )
|
||||
{
|
||||
fitMode = Spline;
|
||||
|
||||
const QPointF *p = points.data();
|
||||
for ( int i = 1; i < size; i++ )
|
||||
{
|
||||
if ( p[i].x() <= p[i-1].x() )
|
||||
{
|
||||
fitMode = ParametricSpline;
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if ( fitMode == ParametricSpline )
|
||||
return fitParametric( points );
|
||||
else
|
||||
return fitSpline( points );
|
||||
}
|
||||
|
||||
QPolygonF QwtSplineCurveFitter::fitSpline( const QPolygonF &points ) const
|
||||
{
|
||||
d_data->spline.setPoints( points );
|
||||
if ( !d_data->spline.isValid() )
|
||||
return points;
|
||||
|
||||
QPolygonF fittedPoints( d_data->splineSize );
|
||||
|
||||
const double x1 = points[0].x();
|
||||
const double x2 = points[int( points.size() - 1 )].x();
|
||||
const double dx = x2 - x1;
|
||||
const double delta = dx / ( d_data->splineSize - 1 );
|
||||
|
||||
for ( int i = 0; i < d_data->splineSize; i++ )
|
||||
{
|
||||
QPointF &p = fittedPoints[i];
|
||||
|
||||
const double v = x1 + i * delta;
|
||||
const double sv = d_data->spline.value( v );
|
||||
|
||||
p.setX( v );
|
||||
p.setY( sv );
|
||||
}
|
||||
d_data->spline.reset();
|
||||
|
||||
return fittedPoints;
|
||||
}
|
||||
|
||||
QPolygonF QwtSplineCurveFitter::fitParametric( const QPolygonF &points ) const
|
||||
{
|
||||
int i;
|
||||
const int size = points.size();
|
||||
|
||||
QPolygonF fittedPoints( d_data->splineSize );
|
||||
QPolygonF splinePointsX( size );
|
||||
QPolygonF splinePointsY( size );
|
||||
|
||||
const QPointF *p = points.data();
|
||||
QPointF *spX = splinePointsX.data();
|
||||
QPointF *spY = splinePointsY.data();
|
||||
|
||||
double param = 0.0;
|
||||
for ( i = 0; i < size; i++ )
|
||||
{
|
||||
const double x = p[i].x();
|
||||
const double y = p[i].y();
|
||||
if ( i > 0 )
|
||||
{
|
||||
const double delta = qSqrt( qwtSqr( x - spX[i-1].y() )
|
||||
+ qwtSqr( y - spY[i-1].y() ) );
|
||||
param += qMax( delta, 1.0 );
|
||||
}
|
||||
spX[i].setX( param );
|
||||
spX[i].setY( x );
|
||||
spY[i].setX( param );
|
||||
spY[i].setY( y );
|
||||
}
|
||||
|
||||
d_data->spline.setPoints( splinePointsX );
|
||||
if ( !d_data->spline.isValid() )
|
||||
return points;
|
||||
|
||||
const double deltaX =
|
||||
splinePointsX[size - 1].x() / ( d_data->splineSize - 1 );
|
||||
for ( i = 0; i < d_data->splineSize; i++ )
|
||||
{
|
||||
const double dtmp = i * deltaX;
|
||||
fittedPoints[i].setX( d_data->spline.value( dtmp ) );
|
||||
}
|
||||
|
||||
d_data->spline.setPoints( splinePointsY );
|
||||
if ( !d_data->spline.isValid() )
|
||||
return points;
|
||||
|
||||
const double deltaY =
|
||||
splinePointsY[size - 1].x() / ( d_data->splineSize - 1 );
|
||||
for ( i = 0; i < d_data->splineSize; i++ )
|
||||
{
|
||||
const double dtmp = i * deltaY;
|
||||
fittedPoints[i].setY( d_data->spline.value( dtmp ) );
|
||||
}
|
||||
|
||||
return fittedPoints;
|
||||
}
|
||||
|
||||
class QwtWeedingCurveFitter::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
tolerance( 1.0 ),
|
||||
chunkSize( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
double tolerance;
|
||||
uint chunkSize;
|
||||
};
|
||||
|
||||
class QwtWeedingCurveFitter::Line
|
||||
{
|
||||
public:
|
||||
Line( int i1 = 0, int i2 = 0 ):
|
||||
from( i1 ),
|
||||
to( i2 )
|
||||
{
|
||||
}
|
||||
|
||||
int from;
|
||||
int to;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
\param tolerance Tolerance
|
||||
\sa setTolerance(), tolerance()
|
||||
*/
|
||||
QwtWeedingCurveFitter::QwtWeedingCurveFitter( double tolerance )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
setTolerance( tolerance );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtWeedingCurveFitter::~QwtWeedingCurveFitter()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign the tolerance
|
||||
|
||||
The tolerance is the maximum distance, that is acceptable
|
||||
between the original curve and the smoothed curve.
|
||||
|
||||
Increasing the tolerance will reduce the number of the
|
||||
resulting points.
|
||||
|
||||
\param tolerance Tolerance
|
||||
|
||||
\sa tolerance()
|
||||
*/
|
||||
void QwtWeedingCurveFitter::setTolerance( double tolerance )
|
||||
{
|
||||
d_data->tolerance = qMax( tolerance, 0.0 );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Tolerance
|
||||
\sa setTolerance()
|
||||
*/
|
||||
double QwtWeedingCurveFitter::tolerance() const
|
||||
{
|
||||
return d_data->tolerance;
|
||||
}
|
||||
|
||||
/*!
|
||||
Limit the number of points passed to a run of the algorithm
|
||||
|
||||
The runtime of the Douglas Peucker algorithm increases non linear
|
||||
with the number of points. For a chunk size > 0 the polygon
|
||||
is split into pieces passed to the algorithm one by one.
|
||||
|
||||
\param numPoints Maximum for the number of points passed to the algorithm
|
||||
|
||||
\sa chunkSize()
|
||||
*/
|
||||
void QwtWeedingCurveFitter::setChunkSize( uint numPoints )
|
||||
{
|
||||
if ( numPoints > 0 )
|
||||
numPoints = qMax( numPoints, 3U );
|
||||
|
||||
d_data->chunkSize = numPoints;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Maximum for the number of points passed to a run
|
||||
of the algorithm - or 0, when unlimited
|
||||
\sa setChunkSize()
|
||||
*/
|
||||
uint QwtWeedingCurveFitter::chunkSize() const
|
||||
{
|
||||
return d_data->chunkSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
\param points Series of data points
|
||||
\return Curve points
|
||||
*/
|
||||
QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const
|
||||
{
|
||||
if ( points.isEmpty() )
|
||||
return points;
|
||||
|
||||
QPolygonF fittedPoints;
|
||||
if ( d_data->chunkSize == 0 )
|
||||
{
|
||||
fittedPoints = simplify( points );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < points.size(); i += d_data->chunkSize )
|
||||
{
|
||||
const QPolygonF p = points.mid( i, d_data->chunkSize );
|
||||
fittedPoints += simplify( p );
|
||||
}
|
||||
}
|
||||
|
||||
return fittedPoints;
|
||||
}
|
||||
|
||||
QPolygonF QwtWeedingCurveFitter::simplify( const QPolygonF &points ) const
|
||||
{
|
||||
const double toleranceSqr = d_data->tolerance * d_data->tolerance;
|
||||
|
||||
QStack<Line> stack;
|
||||
stack.reserve( 500 );
|
||||
|
||||
const QPointF *p = points.data();
|
||||
const int nPoints = points.size();
|
||||
|
||||
QVector<bool> usePoint( nPoints, false );
|
||||
|
||||
stack.push( Line( 0, nPoints - 1 ) );
|
||||
|
||||
while ( !stack.isEmpty() )
|
||||
{
|
||||
const Line r = stack.pop();
|
||||
|
||||
// initialize line segment
|
||||
const double vecX = p[r.to].x() - p[r.from].x();
|
||||
const double vecY = p[r.to].y() - p[r.from].y();
|
||||
|
||||
const double vecLength = qSqrt( vecX * vecX + vecY * vecY );
|
||||
|
||||
const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0;
|
||||
const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0;
|
||||
|
||||
double maxDistSqr = 0.0;
|
||||
int nVertexIndexMaxDistance = r.from + 1;
|
||||
for ( int i = r.from + 1; i < r.to; i++ )
|
||||
{
|
||||
//compare to anchor
|
||||
const double fromVecX = p[i].x() - p[r.from].x();
|
||||
const double fromVecY = p[i].y() - p[r.from].y();
|
||||
|
||||
double distToSegmentSqr;
|
||||
if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 )
|
||||
{
|
||||
distToSegmentSqr = fromVecX * fromVecX + fromVecY * fromVecY;
|
||||
}
|
||||
else
|
||||
{
|
||||
const double toVecX = p[i].x() - p[r.to].x();
|
||||
const double toVecY = p[i].y() - p[r.to].y();
|
||||
const double toVecLength = toVecX * toVecX + toVecY * toVecY;
|
||||
|
||||
const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY );
|
||||
if ( s < 0.0 )
|
||||
{
|
||||
distToSegmentSqr = toVecLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
distToSegmentSqr = qFabs( toVecLength - s * s );
|
||||
}
|
||||
}
|
||||
|
||||
if ( maxDistSqr < distToSegmentSqr )
|
||||
{
|
||||
maxDistSqr = distToSegmentSqr;
|
||||
nVertexIndexMaxDistance = i;
|
||||
}
|
||||
}
|
||||
if ( maxDistSqr <= toleranceSqr )
|
||||
{
|
||||
usePoint[r.from] = true;
|
||||
usePoint[r.to] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.push( Line( r.from, nVertexIndexMaxDistance ) );
|
||||
stack.push( Line( nVertexIndexMaxDistance, r.to ) );
|
||||
}
|
||||
}
|
||||
|
||||
QPolygonF stripped;
|
||||
for ( int i = 0; i < nPoints; i++ )
|
||||
{
|
||||
if ( usePoint[i] )
|
||||
stripped += p[i];
|
||||
}
|
||||
|
||||
return stripped;
|
||||
}
|
||||
139
third/3rd_qwt/qwt_curve_fitter.h
Normal file
139
third/3rd_qwt/qwt_curve_fitter.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_CURVE_FITTER_H
|
||||
#define QWT_CURVE_FITTER_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qpolygon.h>
|
||||
#include <qrect.h>
|
||||
|
||||
class QwtSpline;
|
||||
|
||||
/*!
|
||||
\brief Abstract base class for a curve fitter
|
||||
*/
|
||||
class QWT_EXPORT QwtCurveFitter
|
||||
{
|
||||
public:
|
||||
virtual ~QwtCurveFitter();
|
||||
|
||||
/*!
|
||||
Find a curve which has the best fit to a series of data points
|
||||
|
||||
\param polygon Series of data points
|
||||
\return Curve points
|
||||
*/
|
||||
virtual QPolygonF fitCurve( const QPolygonF &polygon ) const = 0;
|
||||
|
||||
protected:
|
||||
QwtCurveFitter();
|
||||
|
||||
private:
|
||||
QwtCurveFitter( const QwtCurveFitter & );
|
||||
QwtCurveFitter &operator=( const QwtCurveFitter & );
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A curve fitter using cubic splines
|
||||
*/
|
||||
class QWT_EXPORT QwtSplineCurveFitter: public QwtCurveFitter
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
Spline type
|
||||
The default setting is Auto
|
||||
\sa setFitMode(), FitMode()
|
||||
*/
|
||||
enum FitMode
|
||||
{
|
||||
/*!
|
||||
Use the default spline algorithm for polygons with
|
||||
increasing x values ( p[i-1] < p[i] ), otherwise use
|
||||
a parametric spline algorithm.
|
||||
*/
|
||||
Auto,
|
||||
|
||||
//! Use a default spline algorithm
|
||||
Spline,
|
||||
|
||||
//! Use a parametric spline algorithm
|
||||
ParametricSpline
|
||||
};
|
||||
|
||||
QwtSplineCurveFitter();
|
||||
virtual ~QwtSplineCurveFitter();
|
||||
|
||||
void setFitMode( FitMode );
|
||||
FitMode fitMode() const;
|
||||
|
||||
void setSpline( const QwtSpline& );
|
||||
const QwtSpline &spline() const;
|
||||
QwtSpline &spline();
|
||||
|
||||
void setSplineSize( int );
|
||||
int splineSize() const;
|
||||
|
||||
virtual QPolygonF fitCurve( const QPolygonF & ) const;
|
||||
|
||||
private:
|
||||
QPolygonF fitSpline( const QPolygonF & ) const;
|
||||
QPolygonF fitParametric( const QPolygonF & ) const;
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A curve fitter implementing Douglas and Peucker algorithm
|
||||
|
||||
The purpose of the Douglas and Peucker algorithm is that given a 'curve'
|
||||
composed of line segments to find a curve not too dissimilar but that
|
||||
has fewer points. The algorithm defines 'too dissimilar' based on the
|
||||
maximum distance (tolerance) between the original curve and the
|
||||
smoothed curve.
|
||||
|
||||
The runtime of the algorithm increases non linear ( worst case O( n*n ) )
|
||||
and might be very slow for huge polygons. To avoid performance issues
|
||||
it might be useful to split the polygon ( setChunkSize() ) and to run the algorithm
|
||||
for these smaller parts. The disadvantage of having no interpolation
|
||||
at the borders is for most use cases irrelevant.
|
||||
|
||||
The smoothed curve consists of a subset of the points that defined the
|
||||
original curve.
|
||||
|
||||
In opposite to QwtSplineCurveFitter the Douglas and Peucker algorithm reduces
|
||||
the number of points. By adjusting the tolerance parameter according to the
|
||||
axis scales QwtSplineCurveFitter can be used to implement different
|
||||
level of details to speed up painting of curves of many points.
|
||||
*/
|
||||
class QWT_EXPORT QwtWeedingCurveFitter: public QwtCurveFitter
|
||||
{
|
||||
public:
|
||||
QwtWeedingCurveFitter( double tolerance = 1.0 );
|
||||
virtual ~QwtWeedingCurveFitter();
|
||||
|
||||
void setTolerance( double );
|
||||
double tolerance() const;
|
||||
|
||||
void setChunkSize( uint );
|
||||
uint chunkSize() const;
|
||||
|
||||
virtual QPolygonF fitCurve( const QPolygonF & ) const;
|
||||
|
||||
private:
|
||||
virtual QPolygonF simplify( const QPolygonF & ) const;
|
||||
|
||||
class Line;
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
764
third/3rd_qwt/qwt_date.cpp
Normal file
764
third/3rd_qwt/qwt_date.cpp
Normal file
@@ -0,0 +1,764 @@
|
||||
/* -*- 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_date.h"
|
||||
#include <qdebug.h>
|
||||
#include <qlocale.h>
|
||||
#include <math.h>
|
||||
#include <limits>
|
||||
#include <limits.h>
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
|
||||
typedef qint64 QwtJulianDay;
|
||||
static const QwtJulianDay minJulianDayD = Q_INT64_C( -784350574879 );
|
||||
static const QwtJulianDay maxJulianDayD = Q_INT64_C( 784354017364 );
|
||||
|
||||
#else
|
||||
|
||||
// QDate stores the Julian day as unsigned int, but
|
||||
// but it is QDate::fromJulianDay( int ). That's why
|
||||
// we have the range [ 1, INT_MAX ]
|
||||
typedef int QwtJulianDay;
|
||||
static const QwtJulianDay minJulianDayD = 1;
|
||||
static const QwtJulianDay maxJulianDayD = std::numeric_limits<int>::max();
|
||||
|
||||
#endif
|
||||
|
||||
static QString qwtExpandedFormat( const QString & format,
|
||||
const QDateTime &dateTime, QwtDate::Week0Type week0Type )
|
||||
{
|
||||
const int week = QwtDate::weekNumber( dateTime.date(), week0Type );
|
||||
|
||||
QString weekNo;
|
||||
weekNo.setNum( week );
|
||||
|
||||
QString weekNoWW;
|
||||
if ( weekNo.length() == 1 )
|
||||
weekNoWW += "0";
|
||||
|
||||
weekNoWW += weekNo;
|
||||
|
||||
QString fmt = format;
|
||||
fmt.replace( "ww", weekNoWW );
|
||||
fmt.replace( "w", weekNo );
|
||||
|
||||
if ( week == 1 && dateTime.date().month() != 1 )
|
||||
{
|
||||
// in case of week 1, we might need to increment the year
|
||||
|
||||
static QString s_yyyy = "yyyy";
|
||||
static QString s_yy = "yy";
|
||||
|
||||
// week 1 might start in the previous year
|
||||
|
||||
bool doReplaceYear = fmt.contains( s_yy );
|
||||
|
||||
if ( doReplaceYear )
|
||||
{
|
||||
if ( fmt.contains( 'M' ) )
|
||||
{
|
||||
// in case of also having 'M' we have a conflict about
|
||||
// which year to show
|
||||
|
||||
doReplaceYear = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// in case of also having 'd' or 'dd' we have a conflict about
|
||||
// which year to show
|
||||
|
||||
int numD = 0;
|
||||
|
||||
for ( int i = 0; i < fmt.size(); i++ )
|
||||
{
|
||||
if ( fmt[i] == 'd' )
|
||||
{
|
||||
numD++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( numD > 0 && numD <= 2 )
|
||||
break;
|
||||
|
||||
numD = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( numD > 0 && numD <= 2 )
|
||||
doReplaceYear = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( doReplaceYear )
|
||||
{
|
||||
const QDate dt( dateTime.date().year() + 1, 1, 1 );
|
||||
|
||||
if ( fmt.contains( s_yyyy ) )
|
||||
{
|
||||
fmt.replace( s_yyyy, dt.toString( s_yyyy ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt.replace( s_yy, dt.toString( s_yyyy ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
static inline Qt::DayOfWeek qwtFirstDayOfWeek()
|
||||
{
|
||||
#if QT_VERSION >= 0x040800
|
||||
return QLocale().firstDayOfWeek();
|
||||
#else
|
||||
|
||||
switch( QLocale().country() )
|
||||
{
|
||||
case QLocale::Maldives:
|
||||
return Qt::Friday;
|
||||
|
||||
case QLocale::Afghanistan:
|
||||
case QLocale::Algeria:
|
||||
case QLocale::Bahrain:
|
||||
case QLocale::Djibouti:
|
||||
case QLocale::Egypt:
|
||||
case QLocale::Eritrea:
|
||||
case QLocale::Ethiopia:
|
||||
case QLocale::Iran:
|
||||
case QLocale::Iraq:
|
||||
case QLocale::Jordan:
|
||||
case QLocale::Kenya:
|
||||
case QLocale::Kuwait:
|
||||
case QLocale::LibyanArabJamahiriya:
|
||||
case QLocale::Morocco:
|
||||
case QLocale::Oman:
|
||||
case QLocale::Qatar:
|
||||
case QLocale::SaudiArabia:
|
||||
case QLocale::Somalia:
|
||||
case QLocale::Sudan:
|
||||
case QLocale::Tunisia:
|
||||
case QLocale::Yemen:
|
||||
return Qt::Saturday;
|
||||
|
||||
case QLocale::AmericanSamoa:
|
||||
case QLocale::Argentina:
|
||||
case QLocale::Azerbaijan:
|
||||
case QLocale::Botswana:
|
||||
case QLocale::Canada:
|
||||
case QLocale::China:
|
||||
case QLocale::FaroeIslands:
|
||||
case QLocale::Georgia:
|
||||
case QLocale::Greenland:
|
||||
case QLocale::Guam:
|
||||
case QLocale::HongKong:
|
||||
case QLocale::Iceland:
|
||||
case QLocale::India:
|
||||
case QLocale::Ireland:
|
||||
case QLocale::Israel:
|
||||
case QLocale::Jamaica:
|
||||
case QLocale::Japan:
|
||||
case QLocale::Kyrgyzstan:
|
||||
case QLocale::Lao:
|
||||
case QLocale::Malta:
|
||||
case QLocale::MarshallIslands:
|
||||
case QLocale::Macau:
|
||||
case QLocale::Mongolia:
|
||||
case QLocale::NewZealand:
|
||||
case QLocale::NorthernMarianaIslands:
|
||||
case QLocale::Pakistan:
|
||||
case QLocale::Philippines:
|
||||
case QLocale::RepublicOfKorea:
|
||||
case QLocale::Singapore:
|
||||
case QLocale::SyrianArabRepublic:
|
||||
case QLocale::Taiwan:
|
||||
case QLocale::Thailand:
|
||||
case QLocale::TrinidadAndTobago:
|
||||
case QLocale::UnitedStates:
|
||||
case QLocale::UnitedStatesMinorOutlyingIslands:
|
||||
case QLocale::USVirginIslands:
|
||||
case QLocale::Uzbekistan:
|
||||
case QLocale::Zimbabwe:
|
||||
return Qt::Sunday;
|
||||
|
||||
default:
|
||||
return Qt::Monday;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void qwtFloorTime(
|
||||
QwtDate::IntervalType intervalType, QDateTime &dt )
|
||||
{
|
||||
// when dt is inside the special hour where DST is ending
|
||||
// an hour is no unique. Therefore we have to
|
||||
// use UTC time.
|
||||
|
||||
const Qt::TimeSpec timeSpec = dt.timeSpec();
|
||||
|
||||
if ( timeSpec == Qt::LocalTime )
|
||||
dt = dt.toTimeSpec( Qt::UTC );
|
||||
|
||||
const QTime t = dt.time();
|
||||
switch( intervalType )
|
||||
{
|
||||
case QwtDate::Second:
|
||||
{
|
||||
dt.setTime( QTime( t.hour(), t.minute(), t.second() ) );
|
||||
break;
|
||||
}
|
||||
case QwtDate::Minute:
|
||||
{
|
||||
dt.setTime( QTime( t.hour(), t.minute(), 0 ) );
|
||||
break;
|
||||
}
|
||||
case QwtDate::Hour:
|
||||
{
|
||||
dt.setTime( QTime( t.hour(), 0, 0 ) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( timeSpec == Qt::LocalTime )
|
||||
dt = dt.toTimeSpec( Qt::LocalTime );
|
||||
}
|
||||
|
||||
static inline QDateTime qwtToTimeSpec(
|
||||
const QDateTime &dt, Qt::TimeSpec spec )
|
||||
{
|
||||
if ( dt.timeSpec() == spec )
|
||||
return dt;
|
||||
|
||||
const qint64 jd = dt.date().toJulianDay();
|
||||
if ( jd < 0 || jd >= INT_MAX )
|
||||
{
|
||||
// the conversion between local time and UTC
|
||||
// is internally limited. To avoid
|
||||
// overflows we simply ignore the difference
|
||||
// for those dates
|
||||
|
||||
QDateTime dt2 = dt;
|
||||
dt2.setTimeSpec( spec );
|
||||
return dt2;
|
||||
}
|
||||
|
||||
return dt.toTimeSpec( spec );
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static inline double qwtToJulianDay( int year, int month, int day )
|
||||
{
|
||||
// code from QDate but using doubles to avoid overflows
|
||||
// for large values
|
||||
|
||||
const int m1 = ( month - 14 ) / 12;
|
||||
const int m2 = ( 367 * ( month - 2 - 12 * m1 ) ) / 12;
|
||||
const double y1 = ::floor( ( 4900.0 + year + m1 ) / 100 );
|
||||
|
||||
return ::floor( ( 1461.0 * ( year + 4800 + m1 ) ) / 4 ) + m2
|
||||
- ::floor( ( 3 * y1 ) / 4 ) + day - 32075;
|
||||
}
|
||||
|
||||
static inline qint64 qwtFloorDiv64( qint64 a, int b )
|
||||
{
|
||||
if ( a < 0 )
|
||||
a -= b - 1;
|
||||
|
||||
return a / b;
|
||||
}
|
||||
|
||||
static inline qint64 qwtFloorDiv( int a, int b )
|
||||
{
|
||||
if ( a < 0 )
|
||||
a -= b - 1;
|
||||
|
||||
return a / b;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline QDate qwtToDate( int year, int month = 1, int day = 1 )
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
return QDate( year, month, day );
|
||||
#else
|
||||
if ( year > 100000 )
|
||||
{
|
||||
// code from QDate but using doubles to avoid overflows
|
||||
// for large values
|
||||
|
||||
const int m1 = ( month - 14 ) / 12;
|
||||
const int m2 = ( 367 * ( month - 2 - 12 * m1 ) ) / 12;
|
||||
const double y1 = ::floor( ( 4900.0 + year + m1 ) / 100 );
|
||||
|
||||
const double jd = ::floor( ( 1461.0 * ( year + 4800 + m1 ) ) / 4 ) + m2
|
||||
- ::floor( ( 3 * y1 ) / 4 ) + day - 32075;
|
||||
|
||||
if ( jd > maxJulianDayD )
|
||||
{
|
||||
qWarning() << "qwtToDate: overflow";
|
||||
return QDate();
|
||||
}
|
||||
|
||||
return QDate::fromJulianDay( static_cast<QwtJulianDay>( jd ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QDate( year, month, day );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
Translate from double to QDateTime
|
||||
|
||||
\param value Number of milliseconds since the epoch,
|
||||
1970-01-01T00:00:00 UTC
|
||||
\param timeSpec Time specification
|
||||
\return Datetime value
|
||||
|
||||
\sa toDouble(), QDateTime::setMSecsSinceEpoch()
|
||||
\note The return datetime for Qt::OffsetFromUTC will be Qt::UTC
|
||||
*/
|
||||
QDateTime QwtDate::toDateTime( double value, Qt::TimeSpec timeSpec )
|
||||
{
|
||||
const int msecsPerDay = 86400000;
|
||||
|
||||
const double days = static_cast<qint64>( ::floor( value / msecsPerDay ) );
|
||||
|
||||
const double jd = QwtDate::JulianDayForEpoch + days;
|
||||
if ( ( jd > maxJulianDayD ) || ( jd < minJulianDayD ) )
|
||||
{
|
||||
qWarning() << "QwtDate::toDateTime: overflow";
|
||||
return QDateTime();
|
||||
}
|
||||
|
||||
const QDate d = QDate::fromJulianDay( static_cast<QwtJulianDay>( jd ) );
|
||||
|
||||
const int msecs = static_cast<int>( value - days * msecsPerDay );
|
||||
|
||||
static const QTime timeNull( 0, 0, 0, 0 );
|
||||
|
||||
QDateTime dt( d, timeNull.addMSecs( msecs ), Qt::UTC );
|
||||
|
||||
if ( timeSpec == Qt::LocalTime )
|
||||
dt = qwtToTimeSpec( dt, timeSpec );
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
/*!
|
||||
Translate from QDateTime to double
|
||||
|
||||
\param dateTime Datetime value
|
||||
\return Number of milliseconds since 1970-01-01T00:00:00 UTC has passed.
|
||||
|
||||
\sa toDateTime(), QDateTime::toMSecsSinceEpoch()
|
||||
\warning For values very far below or above 1970-01-01 UTC rounding errors
|
||||
will happen due to the limited significance of a double.
|
||||
*/
|
||||
double QwtDate::toDouble( const QDateTime &dateTime )
|
||||
{
|
||||
const int msecsPerDay = 86400000;
|
||||
|
||||
const QDateTime dt = qwtToTimeSpec( dateTime, Qt::UTC );
|
||||
|
||||
const double days = dt.date().toJulianDay() - QwtDate::JulianDayForEpoch;
|
||||
|
||||
const QTime time = dt.time();
|
||||
const double secs = 3600.0 * time.hour() +
|
||||
60.0 * time.minute() + time.second();
|
||||
|
||||
return days * msecsPerDay + time.msec() + 1000.0 * secs;
|
||||
}
|
||||
|
||||
/*!
|
||||
Ceil a datetime according the interval type
|
||||
|
||||
\param dateTime Datetime value
|
||||
\param intervalType Interval type, how to ceil.
|
||||
F.e. when intervalType = QwtDate::Months, the result
|
||||
will be ceiled to the next beginning of a month
|
||||
\return Ceiled datetime
|
||||
\sa floor()
|
||||
*/
|
||||
QDateTime QwtDate::ceil( const QDateTime &dateTime, IntervalType intervalType )
|
||||
{
|
||||
if ( dateTime.date() >= QwtDate::maxDate() )
|
||||
return dateTime;
|
||||
|
||||
QDateTime dt = dateTime;
|
||||
|
||||
switch ( intervalType )
|
||||
{
|
||||
case QwtDate::Millisecond:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case QwtDate::Second:
|
||||
{
|
||||
qwtFloorTime( QwtDate::Second, dt );
|
||||
if ( dt < dateTime )
|
||||
dt = dt.addSecs( 1 );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtDate::Minute:
|
||||
{
|
||||
qwtFloorTime( QwtDate::Minute, dt );
|
||||
if ( dt < dateTime )
|
||||
dt = dt.addSecs( 60 );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtDate::Hour:
|
||||
{
|
||||
qwtFloorTime( QwtDate::Hour, dt );
|
||||
if ( dt < dateTime )
|
||||
dt = dt.addSecs( 3600 );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtDate::Day:
|
||||
{
|
||||
dt.setTime( QTime( 0, 0 ) );
|
||||
if ( dt < dateTime )
|
||||
dt = dt.addDays( 1 );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtDate::Week:
|
||||
{
|
||||
dt.setTime( QTime( 0, 0 ) );
|
||||
if ( dt < dateTime )
|
||||
dt = dt.addDays( 1 );
|
||||
|
||||
int days = qwtFirstDayOfWeek() - dt.date().dayOfWeek();
|
||||
if ( days < 0 )
|
||||
days += 7;
|
||||
|
||||
dt = dt.addDays( days );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtDate::Month:
|
||||
{
|
||||
dt.setTime( QTime( 0, 0 ) );
|
||||
dt.setDate( qwtToDate( dateTime.date().year(),
|
||||
dateTime.date().month() ) );
|
||||
|
||||
if ( dt < dateTime )
|
||||
dt = dt.addMonths( 1 );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtDate::Year:
|
||||
{
|
||||
dt.setTime( QTime( 0, 0 ) );
|
||||
|
||||
const QDate d = dateTime.date();
|
||||
|
||||
int year = d.year();
|
||||
if ( d.month() > 1 || d.day() > 1 || !dateTime.time().isNull() )
|
||||
year++;
|
||||
|
||||
if ( year == 0 )
|
||||
year++; // there is no year 0
|
||||
|
||||
dt.setDate( qwtToDate( year ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
/*!
|
||||
Floor a datetime according the interval type
|
||||
|
||||
\param dateTime Datetime value
|
||||
\param intervalType Interval type, how to ceil.
|
||||
F.e. when intervalType = QwtDate::Months,
|
||||
the result will be ceiled to the next
|
||||
beginning of a month
|
||||
\return Floored datetime
|
||||
\sa floor()
|
||||
*/
|
||||
QDateTime QwtDate::floor( const QDateTime &dateTime,
|
||||
IntervalType intervalType )
|
||||
{
|
||||
if ( dateTime.date() <= QwtDate::minDate() )
|
||||
return dateTime;
|
||||
|
||||
QDateTime dt = dateTime;
|
||||
|
||||
switch ( intervalType )
|
||||
{
|
||||
case QwtDate::Millisecond:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case QwtDate::Second:
|
||||
case QwtDate::Minute:
|
||||
case QwtDate::Hour:
|
||||
{
|
||||
qwtFloorTime( intervalType, dt );
|
||||
break;
|
||||
}
|
||||
case QwtDate::Day:
|
||||
{
|
||||
dt.setTime( QTime( 0, 0 ) );
|
||||
break;
|
||||
}
|
||||
case QwtDate::Week:
|
||||
{
|
||||
dt.setTime( QTime( 0, 0 ) );
|
||||
|
||||
int days = dt.date().dayOfWeek() - qwtFirstDayOfWeek();
|
||||
if ( days < 0 )
|
||||
days += 7;
|
||||
|
||||
dt = dt.addDays( -days );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtDate::Month:
|
||||
{
|
||||
dt.setTime( QTime( 0, 0 ) );
|
||||
|
||||
const QDate date = qwtToDate( dt.date().year(),
|
||||
dt.date().month() );
|
||||
dt.setDate( date );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtDate::Year:
|
||||
{
|
||||
dt.setTime( QTime( 0, 0 ) );
|
||||
|
||||
const QDate date = qwtToDate( dt.date().year() );
|
||||
dt.setDate( date );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
/*!
|
||||
Minimum for the supported date range
|
||||
|
||||
The range of valid dates depends on how QDate stores the
|
||||
Julian day internally.
|
||||
|
||||
- For Qt4 it is "Tue Jan 2 -4713"
|
||||
- For Qt5 it is "Thu Jan 1 -2147483648"
|
||||
|
||||
\return minimum of the date range
|
||||
\sa maxDate()
|
||||
*/
|
||||
QDate QwtDate::minDate()
|
||||
{
|
||||
static QDate date;
|
||||
if ( !date.isValid() )
|
||||
date = QDate::fromJulianDay( minJulianDayD );
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/*!
|
||||
Maximum for the supported date range
|
||||
|
||||
The range of valid dates depends on how QDate stores the
|
||||
Julian day internally.
|
||||
|
||||
- For Qt4 it is "Tue Jun 3 5874898"
|
||||
- For Qt5 it is "Tue Dec 31 2147483647"
|
||||
|
||||
\return maximum of the date range
|
||||
\sa minDate()
|
||||
\note The maximum differs between Qt4 and Qt5
|
||||
*/
|
||||
QDate QwtDate::maxDate()
|
||||
{
|
||||
static QDate date;
|
||||
if ( !date.isValid() )
|
||||
date = QDate::fromJulianDay( maxJulianDayD );
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Date of the first day of the first week for a year
|
||||
|
||||
The first day of a week depends on the current locale
|
||||
( QLocale::firstDayOfWeek() ).
|
||||
|
||||
\param year Year
|
||||
\param type Option how to identify the first week
|
||||
\return First day of week 0
|
||||
|
||||
\sa QLocale::firstDayOfWeek(), weekNumber()
|
||||
*/
|
||||
QDate QwtDate::dateOfWeek0( int year, Week0Type type )
|
||||
{
|
||||
const Qt::DayOfWeek firstDayOfWeek = qwtFirstDayOfWeek();
|
||||
|
||||
QDate dt0( year, 1, 1 );
|
||||
|
||||
// floor to the first day of the week
|
||||
int days = dt0.dayOfWeek() - firstDayOfWeek;
|
||||
if ( days < 0 )
|
||||
days += 7;
|
||||
|
||||
dt0 = dt0.addDays( -days );
|
||||
|
||||
if ( type == QwtDate::FirstThursday )
|
||||
{
|
||||
// according to ISO 8601 the first week is defined
|
||||
// by the first thursday.
|
||||
|
||||
int d = Qt::Thursday - firstDayOfWeek;
|
||||
if ( d < 0 )
|
||||
d += 7;
|
||||
|
||||
if ( dt0.addDays( d ).year() < year )
|
||||
dt0 = dt0.addDays( 7 );
|
||||
}
|
||||
|
||||
return dt0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Find the week number of a date
|
||||
|
||||
- QwtDate::FirstThursday\n
|
||||
Corresponding to ISO 8601 ( see QDate::weekNumber() ).
|
||||
|
||||
- QwtDate::FirstDay\n
|
||||
Number of weeks that have begun since dateOfWeek0().
|
||||
|
||||
\param date Date
|
||||
\param type Option how to identify the first week
|
||||
|
||||
\return Week number, starting with 1
|
||||
*/
|
||||
int QwtDate::weekNumber( const QDate &date, Week0Type type )
|
||||
{
|
||||
int weekNo;
|
||||
|
||||
if ( type == QwtDate::FirstDay )
|
||||
{
|
||||
QDate day0;
|
||||
|
||||
if ( date.month() == 12 && date.day() >= 24 )
|
||||
{
|
||||
// week 1 usually starts in the previous years.
|
||||
// and we have to check if we are already there
|
||||
|
||||
day0 = dateOfWeek0( date.year() + 1, type );
|
||||
if ( day0.daysTo( date ) < 0 )
|
||||
day0 = dateOfWeek0( date.year(), type );
|
||||
}
|
||||
else
|
||||
{
|
||||
day0 = dateOfWeek0( date.year(), type );
|
||||
}
|
||||
|
||||
weekNo = day0.daysTo( date ) / 7 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
weekNo = date.weekNumber();
|
||||
}
|
||||
|
||||
return weekNo;
|
||||
}
|
||||
|
||||
/*!
|
||||
Offset in seconds from Coordinated Universal Time
|
||||
|
||||
The offset depends on the time specification of dateTime:
|
||||
|
||||
- Qt::UTC
|
||||
0, dateTime has no offset
|
||||
- Qt::OffsetFromUTC
|
||||
returns dateTime.utcOffset()
|
||||
- Qt::LocalTime:
|
||||
number of seconds from the UTC
|
||||
|
||||
For Qt::LocalTime the offset depends on the timezone and
|
||||
daylight savings.
|
||||
|
||||
\param dateTime Datetime value
|
||||
\return Offset in seconds
|
||||
*/
|
||||
int QwtDate::utcOffset( const QDateTime &dateTime )
|
||||
{
|
||||
int seconds = 0;
|
||||
|
||||
switch( dateTime.timeSpec() )
|
||||
{
|
||||
case Qt::UTC:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case Qt::OffsetFromUTC:
|
||||
{
|
||||
seconds = dateTime.utcOffset();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
const QDateTime dt1( dateTime.date(), dateTime.time(), Qt::UTC );
|
||||
seconds = dateTime.secsTo( dt1 );
|
||||
}
|
||||
}
|
||||
|
||||
return seconds;
|
||||
}
|
||||
|
||||
/*!
|
||||
Translate a datetime into a string
|
||||
|
||||
Beside the format expressions documented in QDateTime::toString()
|
||||
the following expressions are supported:
|
||||
|
||||
- w\n
|
||||
week number: ( 1 - 53 )
|
||||
- ww\n
|
||||
week number with a leading zero ( 01 - 53 )
|
||||
|
||||
As week 1 usually starts in the previous year a special rule
|
||||
is applied for formats, where the year is expected to match the
|
||||
week number - even if the date belongs to the previous year.
|
||||
|
||||
\param dateTime Datetime value
|
||||
\param format Format string
|
||||
\param week0Type Specification of week 0
|
||||
|
||||
\return Datetime string
|
||||
\sa QDateTime::toString(), weekNumber(), QwtDateScaleDraw
|
||||
*/
|
||||
QString QwtDate::toString( const QDateTime &dateTime,
|
||||
const QString & format, Week0Type week0Type )
|
||||
{
|
||||
QString fmt = format;
|
||||
if ( fmt.contains( 'w' ) )
|
||||
{
|
||||
fmt = qwtExpandedFormat( fmt, dateTime, week0Type );
|
||||
}
|
||||
|
||||
return dateTime.toString( fmt );
|
||||
}
|
||||
128
third/3rd_qwt/qwt_date.h
Normal file
128
third/3rd_qwt/qwt_date.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _QWT_DATE_H_
|
||||
#define _QWT_DATE_H_
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qdatetime.h>
|
||||
|
||||
/*!
|
||||
\brief A collection of methods around date/time values
|
||||
|
||||
Qt offers convenient classes for dealing with date/time values,
|
||||
but Qwt uses coordinate systems that are based on doubles.
|
||||
QwtDate offers methods to translate from QDateTime to double and v.v.
|
||||
|
||||
A double is interpreted as the number of milliseconds since
|
||||
1970-01-01T00:00:00 Universal Coordinated Time - also known
|
||||
as "The Epoch".
|
||||
|
||||
While the range of the Julian day in Qt4 is limited to [0, MAX_INT],
|
||||
Qt5 stores it as qint64 offering a huge range of valid dates.
|
||||
As the significance of a double is below this ( assuming a
|
||||
fraction of 52 bits ) the translation is not
|
||||
bijective with rounding errors for dates very far from Epoch.
|
||||
For a resolution of 1 ms those start to happen for dates above the
|
||||
year 144683.
|
||||
|
||||
An axis for a date/time interval is expected to be aligned
|
||||
and divided in time/date units like seconds, minutes, ...
|
||||
QwtDate offers several algorithms that are needed to
|
||||
calculate these axes.
|
||||
|
||||
\sa QwtDateScaleEngine, QwtDateScaleDraw, QDate, QTime
|
||||
*/
|
||||
class QWT_EXPORT QwtDate
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
How to identify the first week of year differs between
|
||||
countries.
|
||||
*/
|
||||
enum Week0Type
|
||||
{
|
||||
/*!
|
||||
According to ISO 8601 the first week of a year is defined
|
||||
as "the week with the year's first Thursday in it".
|
||||
|
||||
FirstThursday corresponds to the numbering that is
|
||||
implemented in QDate::weekNumber().
|
||||
*/
|
||||
FirstThursday,
|
||||
|
||||
/*!
|
||||
"The week with January 1.1 in it."
|
||||
|
||||
In the U.S. this definition is more common than
|
||||
FirstThursday.
|
||||
*/
|
||||
FirstDay
|
||||
};
|
||||
|
||||
/*!
|
||||
Classification of an time interval
|
||||
|
||||
Time intervals needs to be classified to decide how to
|
||||
align and divide it.
|
||||
*/
|
||||
enum IntervalType
|
||||
{
|
||||
//! The interval is related to milliseconds
|
||||
Millisecond,
|
||||
|
||||
//! The interval is related to seconds
|
||||
Second,
|
||||
|
||||
//! The interval is related to minutes
|
||||
Minute,
|
||||
|
||||
//! The interval is related to hours
|
||||
Hour,
|
||||
|
||||
//! The interval is related to days
|
||||
Day,
|
||||
|
||||
//! The interval is related to weeks
|
||||
Week,
|
||||
|
||||
//! The interval is related to months
|
||||
Month,
|
||||
|
||||
//! The interval is related to years
|
||||
Year
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
//! The Julian day of "The Epoch"
|
||||
JulianDayForEpoch = 2440588
|
||||
};
|
||||
|
||||
static QDate minDate();
|
||||
static QDate maxDate();
|
||||
|
||||
static QDateTime toDateTime( double value,
|
||||
Qt::TimeSpec = Qt::UTC );
|
||||
|
||||
static double toDouble( const QDateTime & );
|
||||
|
||||
static QDateTime ceil( const QDateTime &, IntervalType );
|
||||
static QDateTime floor( const QDateTime &, IntervalType );
|
||||
|
||||
static QDate dateOfWeek0( int year, Week0Type );
|
||||
static int weekNumber( const QDate &, Week0Type );
|
||||
|
||||
static int utcOffset( const QDateTime & );
|
||||
|
||||
static QString toString( const QDateTime &,
|
||||
const QString & format, Week0Type );
|
||||
};
|
||||
|
||||
#endif
|
||||
278
third/3rd_qwt/qwt_date_scale_draw.cpp
Normal file
278
third/3rd_qwt/qwt_date_scale_draw.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
/* -*- 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_date_scale_draw.h"
|
||||
|
||||
class QwtDateScaleDraw::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData( Qt::TimeSpec spec ):
|
||||
timeSpec( spec ),
|
||||
utcOffset( 0 ),
|
||||
week0Type( QwtDate::FirstThursday )
|
||||
{
|
||||
dateFormats[ QwtDate::Millisecond ] = "hh:mm:ss:zzz\nddd dd MMM yyyy";
|
||||
dateFormats[ QwtDate::Second ] = "hh:mm:ss\nddd dd MMM yyyy";
|
||||
dateFormats[ QwtDate::Minute ] = "hh:mm\nddd dd MMM yyyy";
|
||||
dateFormats[ QwtDate::Hour ] = "hh:mm\nddd dd MMM yyyy";
|
||||
dateFormats[ QwtDate::Day ] = "ddd dd MMM yyyy";
|
||||
dateFormats[ QwtDate::Week ] = "Www yyyy";
|
||||
dateFormats[ QwtDate::Month ] = "MMM yyyy";
|
||||
dateFormats[ QwtDate::Year ] = "yyyy";
|
||||
}
|
||||
|
||||
Qt::TimeSpec timeSpec;
|
||||
int utcOffset;
|
||||
QwtDate::Week0Type week0Type;
|
||||
QString dateFormats[ QwtDate::Year + 1 ];
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
|
||||
The default setting is to display tick labels for the
|
||||
given time specification. The first week of a year is defined like
|
||||
for QwtDate::FirstThursday.
|
||||
|
||||
\param timeSpec Time specification
|
||||
|
||||
\sa setTimeSpec(), setWeek0Type()
|
||||
*/
|
||||
QwtDateScaleDraw::QwtDateScaleDraw( Qt::TimeSpec timeSpec )
|
||||
{
|
||||
d_data = new PrivateData( timeSpec );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtDateScaleDraw::~QwtDateScaleDraw()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the time specification used for the tick labels
|
||||
|
||||
\param timeSpec Time specification
|
||||
\sa timeSpec(), setUtcOffset(), toDateTime()
|
||||
*/
|
||||
void QwtDateScaleDraw::setTimeSpec( Qt::TimeSpec timeSpec )
|
||||
{
|
||||
d_data->timeSpec = timeSpec;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Time specification used for the tick labels
|
||||
\sa setTimeSpec(), utcOffset(), toDateTime()
|
||||
*/
|
||||
Qt::TimeSpec QwtDateScaleDraw::timeSpec() const
|
||||
{
|
||||
return d_data->timeSpec;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the offset in seconds from Coordinated Universal Time
|
||||
|
||||
\param seconds Offset in seconds
|
||||
|
||||
\note The offset has no effect beside for the time specification
|
||||
Qt::OffsetFromUTC.
|
||||
|
||||
\sa QDate::utcOffset(), setTimeSpec(), toDateTime()
|
||||
*/
|
||||
void QwtDateScaleDraw::setUtcOffset( int seconds )
|
||||
{
|
||||
d_data->utcOffset = seconds;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Offset in seconds from Coordinated Universal Time
|
||||
\note The offset has no effect beside for the time specification
|
||||
Qt::OffsetFromUTC.
|
||||
|
||||
\sa QDate::setUtcOffset(), setTimeSpec(), toDateTime()
|
||||
*/
|
||||
int QwtDateScaleDraw::utcOffset() const
|
||||
{
|
||||
return d_data->utcOffset;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets how to identify the first week of a year.
|
||||
|
||||
\param week0Type Mode how to identify the first week of a year
|
||||
|
||||
\sa week0Type().
|
||||
\note week0Type has no effect beside for intervals classified as
|
||||
QwtDate::Week.
|
||||
*/
|
||||
void QwtDateScaleDraw::setWeek0Type( QwtDate::Week0Type week0Type )
|
||||
{
|
||||
d_data->week0Type = week0Type;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Setting how to identify the first week of a year.
|
||||
\sa setWeek0Type()
|
||||
*/
|
||||
QwtDate::Week0Type QwtDateScaleDraw::week0Type() const
|
||||
{
|
||||
return d_data->week0Type;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the default format string for an datetime interval type
|
||||
|
||||
\param intervalType Interval type
|
||||
\param format Default format string
|
||||
|
||||
\sa dateFormat(), dateFormatOfDate(), QwtDate::toString()
|
||||
*/
|
||||
void QwtDateScaleDraw::setDateFormat(
|
||||
QwtDate::IntervalType intervalType, const QString &format )
|
||||
{
|
||||
if ( intervalType >= QwtDate::Millisecond &&
|
||||
intervalType <= QwtDate::Year )
|
||||
{
|
||||
d_data->dateFormats[ intervalType ] = format;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\param intervalType Interval type
|
||||
\return Default format string for an datetime interval type
|
||||
\sa setDateFormat(), dateFormatOfDate()
|
||||
*/
|
||||
QString QwtDateScaleDraw::dateFormat(
|
||||
QwtDate::IntervalType intervalType ) const
|
||||
{
|
||||
if ( intervalType >= QwtDate::Millisecond &&
|
||||
intervalType <= QwtDate::Year )
|
||||
{
|
||||
return d_data->dateFormats[ intervalType ];
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
/*!
|
||||
Format string for the representation of a datetime
|
||||
|
||||
dateFormatOfDate() is intended to be overloaded for
|
||||
situations, where formats are individual for specific
|
||||
datetime values.
|
||||
|
||||
The default setting ignores dateTime and return
|
||||
the default format for the interval type.
|
||||
|
||||
\param dateTime Datetime value
|
||||
\param intervalType Interval type
|
||||
\return Format string
|
||||
|
||||
\sa setDateFormat(), QwtDate::toString()
|
||||
*/
|
||||
QString QwtDateScaleDraw::dateFormatOfDate( const QDateTime &dateTime,
|
||||
QwtDate::IntervalType intervalType ) const
|
||||
{
|
||||
Q_UNUSED( dateTime )
|
||||
|
||||
if ( intervalType >= QwtDate::Millisecond &&
|
||||
intervalType <= QwtDate::Year )
|
||||
{
|
||||
return d_data->dateFormats[ intervalType ];
|
||||
}
|
||||
|
||||
return d_data->dateFormats[ QwtDate::Second ];
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Convert a value into its representing label
|
||||
|
||||
The value is converted to a datetime value using toDateTime()
|
||||
and converted to a plain text using QwtDate::toString().
|
||||
|
||||
\param value Value
|
||||
\return Label string.
|
||||
|
||||
\sa dateFormatOfDate()
|
||||
*/
|
||||
QwtText QwtDateScaleDraw::label( double value ) const
|
||||
{
|
||||
const QDateTime dt = toDateTime( value );
|
||||
const QString fmt = dateFormatOfDate(
|
||||
dt, intervalType( scaleDiv() ) );
|
||||
|
||||
return QwtDate::toString( dt, fmt, d_data->week0Type );
|
||||
}
|
||||
|
||||
/*!
|
||||
Find the less detailed datetime unit, where no rounding
|
||||
errors happen.
|
||||
|
||||
\param scaleDiv Scale division
|
||||
\return Interval type
|
||||
|
||||
\sa dateFormatOfDate()
|
||||
*/
|
||||
QwtDate::IntervalType QwtDateScaleDraw::intervalType(
|
||||
const QwtScaleDiv &scaleDiv ) const
|
||||
{
|
||||
int intvType = QwtDate::Year;
|
||||
|
||||
bool alignedToWeeks = true;
|
||||
|
||||
const QList<double> ticks = scaleDiv.ticks( QwtScaleDiv::MajorTick );
|
||||
for ( int i = 0; i < ticks.size(); i++ )
|
||||
{
|
||||
const QDateTime dt = toDateTime( ticks[i] );
|
||||
for ( int j = QwtDate::Second; j <= intvType; j++ )
|
||||
{
|
||||
const QDateTime dt0 = QwtDate::floor( dt,
|
||||
static_cast<QwtDate::IntervalType>( j ) );
|
||||
|
||||
if ( dt0 != dt )
|
||||
{
|
||||
if ( j == QwtDate::Week )
|
||||
{
|
||||
alignedToWeeks = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
intvType = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( intvType == QwtDate::Millisecond )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( intvType == QwtDate::Week && !alignedToWeeks )
|
||||
intvType = QwtDate::Day;
|
||||
|
||||
return static_cast<QwtDate::IntervalType>( intvType );
|
||||
}
|
||||
|
||||
/*!
|
||||
Translate a double value into a QDateTime object.
|
||||
|
||||
\return QDateTime object initialized with timeSpec() and utcOffset().
|
||||
\sa timeSpec(), utcOffset(), QwtDate::toDateTime()
|
||||
*/
|
||||
QDateTime QwtDateScaleDraw::toDateTime( double value ) const
|
||||
{
|
||||
QDateTime dt = QwtDate::toDateTime( value, d_data->timeSpec );
|
||||
if ( d_data->timeSpec == Qt::OffsetFromUTC )
|
||||
{
|
||||
dt = dt.addSecs( d_data->utcOffset );
|
||||
dt.setUtcOffset( d_data->utcOffset );
|
||||
}
|
||||
|
||||
return dt;
|
||||
}
|
||||
86
third/3rd_qwt/qwt_date_scale_draw.h
Normal file
86
third/3rd_qwt/qwt_date_scale_draw.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _QWT_DATE_SCALE_DRAW_H_
|
||||
#define _QWT_DATE_SCALE_DRAW_H_ 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_scale_draw.h"
|
||||
#include "qwt_date.h"
|
||||
|
||||
/*!
|
||||
\brief A class for drawing datetime scales
|
||||
|
||||
QwtDateScaleDraw displays values as datetime labels.
|
||||
The format of the labels depends on the alignment of
|
||||
the major tick labels.
|
||||
|
||||
The default format strings are:
|
||||
|
||||
- Millisecond\n
|
||||
"hh:mm:ss:zzz\nddd dd MMM yyyy"
|
||||
- Second\n
|
||||
"hh:mm:ss\nddd dd MMM yyyy"
|
||||
- Minute\n
|
||||
"hh:mm\nddd dd MMM yyyy"
|
||||
- Hour\n
|
||||
"hh:mm\nddd dd MMM yyyy"
|
||||
- Day\n
|
||||
"ddd dd MMM yyyy"
|
||||
- Week\n
|
||||
"Www yyyy"
|
||||
- Month\n
|
||||
"MMM yyyy"
|
||||
- Year\n
|
||||
"yyyy"
|
||||
|
||||
The format strings can be modified using setDateFormat()
|
||||
or individually for each tick label by overloading dateFormatOfDate(),
|
||||
|
||||
Usually QwtDateScaleDraw is used in combination with
|
||||
QwtDateScaleEngine, that calculates scales for datetime
|
||||
intervals.
|
||||
|
||||
\sa QwtDateScaleEngine, QwtPlot::setAxisScaleDraw()
|
||||
*/
|
||||
class QWT_EXPORT QwtDateScaleDraw: public QwtScaleDraw
|
||||
{
|
||||
public:
|
||||
QwtDateScaleDraw( Qt::TimeSpec = Qt::LocalTime );
|
||||
virtual ~QwtDateScaleDraw();
|
||||
|
||||
void setDateFormat( QwtDate::IntervalType, const QString & );
|
||||
QString dateFormat( QwtDate::IntervalType ) const;
|
||||
|
||||
void setTimeSpec( Qt::TimeSpec );
|
||||
Qt::TimeSpec timeSpec() const;
|
||||
|
||||
void setUtcOffset( int seconds );
|
||||
int utcOffset() const;
|
||||
|
||||
void setWeek0Type( QwtDate::Week0Type );
|
||||
QwtDate::Week0Type week0Type() const;
|
||||
|
||||
virtual QwtText label( double ) const;
|
||||
|
||||
QDateTime toDateTime( double ) const;
|
||||
|
||||
protected:
|
||||
virtual QwtDate::IntervalType
|
||||
intervalType( const QwtScaleDiv & ) const;
|
||||
|
||||
virtual QString dateFormatOfDate( const QDateTime &,
|
||||
QwtDate::IntervalType ) const;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
1309
third/3rd_qwt/qwt_date_scale_engine.cpp
Normal file
1309
third/3rd_qwt/qwt_date_scale_engine.cpp
Normal file
File diff suppressed because it is too large
Load Diff
86
third/3rd_qwt/qwt_date_scale_engine.h
Normal file
86
third/3rd_qwt/qwt_date_scale_engine.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _QWT_DATE_SCALE_ENGINE_H_
|
||||
#define _QWT_DATE_SCALE_ENGINE_H_ 1
|
||||
|
||||
#include "qwt_date.h"
|
||||
#include "qwt_scale_engine.h"
|
||||
|
||||
/*!
|
||||
\brief A scale engine for date/time values
|
||||
|
||||
QwtDateScaleEngine builds scales from a time intervals.
|
||||
Together with QwtDateScaleDraw it can be used for
|
||||
axes according to date/time values.
|
||||
|
||||
Years, months, weeks, days, hours and minutes are organized
|
||||
in steps with non constant intervals. QwtDateScaleEngine
|
||||
classifies intervals and aligns the boundaries and tick positions
|
||||
according to this classification.
|
||||
|
||||
QwtDateScaleEngine supports representations depending
|
||||
on Qt::TimeSpec specifications. The valid range for scales
|
||||
is limited by the range of QDateTime, that differs
|
||||
between Qt4 and Qt5.
|
||||
|
||||
Datetime values are expected as the number of milliseconds since
|
||||
1970-01-01T00:00:00 Universal Coordinated Time - also known
|
||||
as "The Epoch", that can be converted to QDateTime using
|
||||
QwtDate::toDateTime().
|
||||
|
||||
\sa QwtDate, QwtPlot::setAxisScaleEngine(),
|
||||
QwtAbstractScale::setScaleEngine()
|
||||
*/
|
||||
class QWT_EXPORT QwtDateScaleEngine: public QwtLinearScaleEngine
|
||||
{
|
||||
public:
|
||||
QwtDateScaleEngine( Qt::TimeSpec = Qt::LocalTime );
|
||||
virtual ~QwtDateScaleEngine();
|
||||
|
||||
void setTimeSpec( Qt::TimeSpec );
|
||||
Qt::TimeSpec timeSpec() const;
|
||||
|
||||
void setUtcOffset( int seconds );
|
||||
int utcOffset() const;
|
||||
|
||||
void setWeek0Type( QwtDate::Week0Type );
|
||||
QwtDate::Week0Type week0Type() const;
|
||||
|
||||
void setMaxWeeks( int );
|
||||
int maxWeeks() const;
|
||||
|
||||
virtual void autoScale( int maxNumSteps,
|
||||
double &x1, double &x2, double &stepSize ) const;
|
||||
|
||||
virtual QwtScaleDiv divideScale(
|
||||
double x1, double x2,
|
||||
int maxMajorSteps, int maxMinorSteps,
|
||||
double stepSize = 0.0 ) const;
|
||||
|
||||
virtual QwtDate::IntervalType intervalType(
|
||||
const QDateTime &, const QDateTime &, int maxSteps ) const;
|
||||
|
||||
QDateTime toDateTime( double ) const;
|
||||
|
||||
protected:
|
||||
virtual QDateTime alignDate( const QDateTime &, double stepSize,
|
||||
QwtDate::IntervalType, bool up ) const;
|
||||
|
||||
private:
|
||||
QwtScaleDiv buildScaleDiv( const QDateTime &, const QDateTime &,
|
||||
int maxMajorSteps, int maxMinorSteps,
|
||||
QwtDate::IntervalType ) const;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
871
third/3rd_qwt/qwt_dial.cpp
Normal file
871
third/3rd_qwt/qwt_dial.cpp
Normal file
@@ -0,0 +1,871 @@
|
||||
/* -*- 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_dial.h"
|
||||
#include "qwt_dial_needle.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_scale_engine.h"
|
||||
#include "qwt_scale_map.h"
|
||||
#include "qwt_round_scale_draw.h"
|
||||
#include "qwt_painter.h"
|
||||
#include <qpainter.h>
|
||||
#include <qpalette.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qevent.h>
|
||||
#include <qalgorithms.h>
|
||||
#include <qmath.h>
|
||||
#include <qstyle.h>
|
||||
#include <qstyleoption.h>
|
||||
#include <qapplication.h>
|
||||
|
||||
static inline double qwtAngleDist( double a1, double a2 )
|
||||
{
|
||||
double dist = qAbs( a2 - a1 );
|
||||
if ( dist > 360.0 )
|
||||
dist -= 360.0;
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
static inline bool qwtIsOnArc( double angle, double min, double max )
|
||||
{
|
||||
if ( min < max )
|
||||
{
|
||||
return ( angle >= min ) && ( angle <= max );
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( angle >= min ) || ( angle <= max );
|
||||
}
|
||||
}
|
||||
|
||||
static inline double qwtBoundedAngle( double min, double angle, double max )
|
||||
{
|
||||
double from = qwtNormalizeDegrees( min );
|
||||
double to = qwtNormalizeDegrees( max );
|
||||
|
||||
double a;
|
||||
|
||||
if ( qwtIsOnArc( angle, from, to ) )
|
||||
{
|
||||
a = angle;
|
||||
if ( a < min )
|
||||
a += 360.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( qwtAngleDist( angle, from ) <
|
||||
qwtAngleDist( angle, to ) )
|
||||
{
|
||||
a = min;
|
||||
}
|
||||
else
|
||||
{
|
||||
a = max;
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
class QwtDial::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
frameShadow( Sunken ),
|
||||
lineWidth( 0 ),
|
||||
mode( RotateNeedle ),
|
||||
origin( 90.0 ),
|
||||
minScaleArc( 0.0 ),
|
||||
maxScaleArc( 0.0 ),
|
||||
needle( NULL ),
|
||||
arcOffset( 0.0 ),
|
||||
mouseOffset( 0.0 )
|
||||
{
|
||||
}
|
||||
|
||||
~PrivateData()
|
||||
{
|
||||
delete needle;
|
||||
}
|
||||
Shadow frameShadow;
|
||||
int lineWidth;
|
||||
|
||||
QwtDial::Mode mode;
|
||||
|
||||
double origin;
|
||||
double minScaleArc;
|
||||
double maxScaleArc;
|
||||
|
||||
QwtDialNeedle *needle;
|
||||
|
||||
double arcOffset;
|
||||
double mouseOffset;
|
||||
|
||||
QPixmap pixmapCache;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
\param parent Parent widget
|
||||
|
||||
Create a dial widget with no needle. The scale is initialized
|
||||
to [ 0.0, 360.0 ] and 360 steps ( QwtAbstractSlider::setTotalSteps() ).
|
||||
The origin of the scale is at 90°,
|
||||
|
||||
The value is set to 0.0.
|
||||
|
||||
The default mode is QwtDial::RotateNeedle.
|
||||
*/
|
||||
QwtDial::QwtDial( QWidget* parent ):
|
||||
QwtAbstractSlider( parent )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
|
||||
setFocusPolicy( Qt::TabFocus );
|
||||
|
||||
QPalette p = palette();
|
||||
for ( int i = 0; i < QPalette::NColorGroups; i++ )
|
||||
{
|
||||
const QPalette::ColorGroup colorGroup =
|
||||
static_cast<QPalette::ColorGroup>( i );
|
||||
|
||||
// Base: background color of the circle inside the frame.
|
||||
// WindowText: background color of the circle inside the scale
|
||||
|
||||
p.setColor( colorGroup, QPalette::WindowText,
|
||||
p.color( colorGroup, QPalette::Base ) );
|
||||
}
|
||||
setPalette( p );
|
||||
|
||||
QwtRoundScaleDraw* scaleDraw = new QwtRoundScaleDraw();
|
||||
scaleDraw->setRadius( 0 );
|
||||
|
||||
setScaleDraw( scaleDraw );
|
||||
|
||||
setScaleArc( 0.0, 360.0 ); // scale as a full circle
|
||||
|
||||
setScaleMaxMajor( 10 );
|
||||
setScaleMaxMinor( 5 );
|
||||
|
||||
setValue( 0.0 );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtDial::~QwtDial()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the frame shadow value from the frame style.
|
||||
|
||||
\param shadow Frame shadow
|
||||
\sa setLineWidth(), QFrame::setFrameShadow()
|
||||
*/
|
||||
void QwtDial::setFrameShadow( Shadow shadow )
|
||||
{
|
||||
if ( shadow != d_data->frameShadow )
|
||||
{
|
||||
invalidateCache();
|
||||
|
||||
d_data->frameShadow = shadow;
|
||||
if ( lineWidth() > 0 )
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Frame shadow
|
||||
/sa setFrameShadow(), lineWidth(), QFrame::frameShadow()
|
||||
*/
|
||||
QwtDial::Shadow QwtDial::frameShadow() const
|
||||
{
|
||||
return d_data->frameShadow;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the line width of the frame
|
||||
|
||||
\param lineWidth Line width
|
||||
\sa setFrameShadow()
|
||||
*/
|
||||
void QwtDial::setLineWidth( int lineWidth )
|
||||
{
|
||||
if ( lineWidth < 0 )
|
||||
lineWidth = 0;
|
||||
|
||||
if ( d_data->lineWidth != lineWidth )
|
||||
{
|
||||
invalidateCache();
|
||||
|
||||
d_data->lineWidth = lineWidth;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Line width of the frame
|
||||
\sa setLineWidth(), frameShadow(), lineWidth()
|
||||
*/
|
||||
int QwtDial::lineWidth() const
|
||||
{
|
||||
return d_data->lineWidth;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return bounding rectangle of the circle inside the frame
|
||||
\sa setLineWidth(), scaleInnerRect(), boundingRect()
|
||||
*/
|
||||
QRect QwtDial::innerRect() const
|
||||
{
|
||||
const int lw = lineWidth();
|
||||
return boundingRect().adjusted( lw, lw, -lw, -lw );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return bounding rectangle of the dial including the frame
|
||||
\sa setLineWidth(), scaleInnerRect(), innerRect()
|
||||
*/
|
||||
QRect QwtDial::boundingRect() const
|
||||
{
|
||||
const QRect cr = contentsRect();
|
||||
|
||||
const int dim = qMin( cr.width(), cr.height() );
|
||||
|
||||
QRect inner( 0, 0, dim, dim );
|
||||
inner.moveCenter( cr.center() );
|
||||
|
||||
return inner;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return rectangle inside the scale
|
||||
\sa setLineWidth(), boundingRect(), innerRect()
|
||||
*/
|
||||
QRect QwtDial::scaleInnerRect() const
|
||||
{
|
||||
QRect rect = innerRect();
|
||||
|
||||
const QwtAbstractScaleDraw *sd = scaleDraw();
|
||||
if ( sd )
|
||||
{
|
||||
int scaleDist = qCeil( sd->extent( font() ) );
|
||||
scaleDist++; // margin
|
||||
|
||||
rect.adjust( scaleDist, scaleDist, -scaleDist, -scaleDist );
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the mode of the dial.
|
||||
\param mode New mode
|
||||
|
||||
In case of QwtDial::RotateNeedle the needle is rotating, in case of
|
||||
QwtDial::RotateScale, the needle points to origin()
|
||||
and the scale is rotating.
|
||||
|
||||
The default mode is QwtDial::RotateNeedle.
|
||||
|
||||
\sa mode(), setValue(), setOrigin()
|
||||
*/
|
||||
void QwtDial::setMode( Mode mode )
|
||||
{
|
||||
if ( mode != d_data->mode )
|
||||
{
|
||||
invalidateCache();
|
||||
|
||||
d_data->mode = mode;
|
||||
sliderChange();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Mode of the dial.
|
||||
\sa setMode(), origin(), setScaleArc(), value()
|
||||
*/
|
||||
QwtDial::Mode QwtDial::mode() const
|
||||
{
|
||||
return d_data->mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Invalidate the internal caches used to speed up repainting
|
||||
*/
|
||||
void QwtDial::invalidateCache()
|
||||
{
|
||||
d_data->pixmapCache = QPixmap();
|
||||
}
|
||||
|
||||
/*!
|
||||
Paint the dial
|
||||
\param event Paint event
|
||||
*/
|
||||
void QwtDial::paintEvent( QPaintEvent *event )
|
||||
{
|
||||
QPainter painter( this );
|
||||
painter.setClipRegion( event->region() );
|
||||
|
||||
QStyleOption opt;
|
||||
opt.init(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
|
||||
|
||||
if ( d_data->mode == QwtDial::RotateScale )
|
||||
{
|
||||
painter.save();
|
||||
painter.setRenderHint( QPainter::Antialiasing, true );
|
||||
|
||||
drawContents( &painter );
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
const QRect r = contentsRect();
|
||||
if ( r.size() != d_data->pixmapCache.size() )
|
||||
{
|
||||
d_data->pixmapCache = QwtPainter::backingStore( this, r.size() );
|
||||
d_data->pixmapCache.fill( Qt::transparent );
|
||||
|
||||
QPainter p( &d_data->pixmapCache );
|
||||
p.setRenderHint( QPainter::Antialiasing, true );
|
||||
p.translate( -r.topLeft() );
|
||||
|
||||
if ( d_data->mode != QwtDial::RotateScale )
|
||||
drawContents( &p );
|
||||
|
||||
if ( lineWidth() > 0 )
|
||||
drawFrame( &p );
|
||||
|
||||
if ( d_data->mode != QwtDial::RotateNeedle )
|
||||
drawNeedle( &p );
|
||||
}
|
||||
|
||||
painter.drawPixmap( r.topLeft(), d_data->pixmapCache );
|
||||
|
||||
if ( d_data->mode == QwtDial::RotateNeedle )
|
||||
drawNeedle( &painter );
|
||||
|
||||
if ( hasFocus() )
|
||||
drawFocusIndicator( &painter );
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the focus indicator
|
||||
\param painter Painter
|
||||
*/
|
||||
void QwtDial::drawFocusIndicator( QPainter *painter ) const
|
||||
{
|
||||
QwtPainter::drawFocusRect( painter, this, boundingRect() );
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the frame around the dial
|
||||
|
||||
\param painter Painter
|
||||
\sa lineWidth(), frameShadow()
|
||||
*/
|
||||
void QwtDial::drawFrame( QPainter *painter )
|
||||
{
|
||||
QwtPainter::drawRoundFrame( painter, boundingRect(),
|
||||
palette(), lineWidth(), d_data->frameShadow );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Draw the contents inside the frame
|
||||
|
||||
QPalette::Window is the background color outside of the frame.
|
||||
QPalette::Base is the background color inside the frame.
|
||||
QPalette::WindowText is the background color inside the scale.
|
||||
|
||||
\param painter Painter
|
||||
|
||||
\sa boundingRect(), innerRect(),
|
||||
scaleInnerRect(), QWidget::setPalette()
|
||||
*/
|
||||
void QwtDial::drawContents( QPainter *painter ) const
|
||||
{
|
||||
if ( testAttribute( Qt::WA_NoSystemBackground ) ||
|
||||
palette().brush( QPalette::Base ) !=
|
||||
palette().brush( QPalette::Window ) )
|
||||
{
|
||||
const QRectF br = boundingRect();
|
||||
|
||||
painter->save();
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( palette().brush( QPalette::Base ) );
|
||||
painter->drawEllipse( br );
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
const QRectF insideScaleRect = scaleInnerRect();
|
||||
if ( palette().brush( QPalette::WindowText ) !=
|
||||
palette().brush( QPalette::Base ) )
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( palette().brush( QPalette::WindowText ) );
|
||||
painter->drawEllipse( insideScaleRect );
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
const QPointF center = insideScaleRect.center();
|
||||
const double radius = 0.5 * insideScaleRect.width();
|
||||
|
||||
painter->save();
|
||||
drawScale( painter, center, radius );
|
||||
painter->restore();
|
||||
|
||||
painter->save();
|
||||
drawScaleContents( painter, center, radius );
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the needle
|
||||
|
||||
\param painter Painter
|
||||
\param center Center of the dial
|
||||
\param radius Length for the needle
|
||||
\param direction Direction of the needle in degrees, counter clockwise
|
||||
\param colorGroup ColorGroup
|
||||
*/
|
||||
void QwtDial::drawNeedle( QPainter *painter, const QPointF ¢er,
|
||||
double radius, double direction, QPalette::ColorGroup colorGroup ) const
|
||||
{
|
||||
if ( d_data->needle )
|
||||
{
|
||||
direction = 360.0 - direction; // counter clockwise
|
||||
d_data->needle->draw( painter, center, radius, direction, colorGroup );
|
||||
}
|
||||
}
|
||||
|
||||
void QwtDial::drawNeedle( QPainter *painter ) const
|
||||
{
|
||||
if ( !isValid() )
|
||||
return;
|
||||
|
||||
QPalette::ColorGroup colorGroup;
|
||||
if ( isEnabled() )
|
||||
colorGroup = hasFocus() ? QPalette::Active : QPalette::Inactive;
|
||||
else
|
||||
colorGroup = QPalette::Disabled;
|
||||
|
||||
const QRectF sr = scaleInnerRect();
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint( QPainter::Antialiasing, true );
|
||||
drawNeedle( painter, sr.center(), 0.5 * sr.width(),
|
||||
scaleMap().transform( value() ) + 270.0, colorGroup );
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the scale
|
||||
|
||||
\param painter Painter
|
||||
\param center Center of the dial
|
||||
\param radius Radius of the scale
|
||||
*/
|
||||
void QwtDial::drawScale( QPainter *painter,
|
||||
const QPointF ¢er, double radius ) const
|
||||
{
|
||||
QwtRoundScaleDraw *sd = const_cast<QwtRoundScaleDraw *>( scaleDraw() );
|
||||
if ( sd == NULL )
|
||||
return;
|
||||
|
||||
sd->setRadius( radius );
|
||||
sd->moveCenter( center );
|
||||
|
||||
QPalette pal = palette();
|
||||
|
||||
const QColor textColor = pal.color( QPalette::Text );
|
||||
pal.setColor( QPalette::WindowText, textColor ); // ticks, backbone
|
||||
|
||||
painter->setFont( font() );
|
||||
painter->setPen( QPen( textColor, sd->penWidth() ) );
|
||||
|
||||
painter->setBrush( Qt::red );
|
||||
sd->draw( painter, pal );
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the contents inside the scale
|
||||
|
||||
Paints nothing.
|
||||
|
||||
\param painter Painter
|
||||
\param center Center of the contents circle
|
||||
\param radius Radius of the contents circle
|
||||
*/
|
||||
void QwtDial::drawScaleContents( QPainter *painter,
|
||||
const QPointF ¢er, double radius ) const
|
||||
{
|
||||
Q_UNUSED(painter);
|
||||
Q_UNUSED(center);
|
||||
Q_UNUSED(radius);
|
||||
}
|
||||
|
||||
/*!
|
||||
Set a needle for the dial
|
||||
|
||||
\param needle Needle
|
||||
|
||||
\warning The needle will be deleted, when a different needle is
|
||||
set or in ~QwtDial()
|
||||
*/
|
||||
void QwtDial::setNeedle( QwtDialNeedle *needle )
|
||||
{
|
||||
if ( needle != d_data->needle )
|
||||
{
|
||||
if ( d_data->needle )
|
||||
delete d_data->needle;
|
||||
|
||||
d_data->needle = needle;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return needle
|
||||
\sa setNeedle()
|
||||
*/
|
||||
const QwtDialNeedle *QwtDial::needle() const
|
||||
{
|
||||
return d_data->needle;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return needle
|
||||
\sa setNeedle()
|
||||
*/
|
||||
QwtDialNeedle *QwtDial::needle()
|
||||
{
|
||||
return d_data->needle;
|
||||
}
|
||||
|
||||
//! \return the scale draw
|
||||
QwtRoundScaleDraw *QwtDial::scaleDraw()
|
||||
{
|
||||
return static_cast<QwtRoundScaleDraw *>( abstractScaleDraw() );
|
||||
}
|
||||
|
||||
//! \return the scale draw
|
||||
const QwtRoundScaleDraw *QwtDial::scaleDraw() const
|
||||
{
|
||||
return static_cast<const QwtRoundScaleDraw *>( abstractScaleDraw() );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set an individual scale draw
|
||||
|
||||
The motivation for setting a scale draw is often
|
||||
to overload QwtRoundScaleDraw::label() to return
|
||||
individual tick labels.
|
||||
|
||||
\param scaleDraw Scale draw
|
||||
\warning The previous scale draw is deleted
|
||||
*/
|
||||
void QwtDial::setScaleDraw( QwtRoundScaleDraw *scaleDraw )
|
||||
{
|
||||
setAbstractScaleDraw( scaleDraw );
|
||||
sliderChange();
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the arc of the scale
|
||||
|
||||
\param minArc Lower limit
|
||||
\param maxArc Upper limit
|
||||
|
||||
\sa minScaleArc(), maxScaleArc()
|
||||
*/
|
||||
void QwtDial::setScaleArc( double minArc, double maxArc )
|
||||
{
|
||||
if ( minArc != 360.0 && minArc != -360.0 )
|
||||
minArc = ::fmod( minArc, 360.0 );
|
||||
if ( maxArc != 360.0 && maxArc != -360.0 )
|
||||
maxArc = ::fmod( maxArc, 360.0 );
|
||||
|
||||
double minScaleArc = qMin( minArc, maxArc );
|
||||
double maxScaleArc = qMax( minArc, maxArc );
|
||||
|
||||
if ( maxScaleArc - minScaleArc > 360.0 )
|
||||
maxScaleArc = minScaleArc + 360.0;
|
||||
|
||||
if ( ( minScaleArc != d_data->minScaleArc ) ||
|
||||
( maxScaleArc != d_data->maxScaleArc ) )
|
||||
{
|
||||
d_data->minScaleArc = minScaleArc;
|
||||
d_data->maxScaleArc = maxScaleArc;
|
||||
|
||||
invalidateCache();
|
||||
sliderChange();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the lower limit for the scale arc
|
||||
|
||||
\param min Lower limit of the scale arc
|
||||
\sa setScaleArc(), setMaxScaleArc()
|
||||
*/
|
||||
void QwtDial::setMinScaleArc( double min )
|
||||
{
|
||||
setScaleArc( min, d_data->maxScaleArc );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Lower limit of the scale arc
|
||||
\sa setScaleArc()
|
||||
*/
|
||||
double QwtDial::minScaleArc() const
|
||||
{
|
||||
return d_data->minScaleArc;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the upper limit for the scale arc
|
||||
|
||||
\param max Upper limit of the scale arc
|
||||
\sa setScaleArc(), setMinScaleArc()
|
||||
*/
|
||||
void QwtDial::setMaxScaleArc( double max )
|
||||
{
|
||||
setScaleArc( d_data->minScaleArc, max );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Upper limit of the scale arc
|
||||
\sa setScaleArc()
|
||||
*/
|
||||
double QwtDial::maxScaleArc() const
|
||||
{
|
||||
return d_data->maxScaleArc;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the origin
|
||||
|
||||
The origin is the angle where scale and needle is relative to.
|
||||
|
||||
\param origin New origin
|
||||
\sa origin()
|
||||
*/
|
||||
void QwtDial::setOrigin( double origin )
|
||||
{
|
||||
invalidateCache();
|
||||
|
||||
d_data->origin = origin;
|
||||
sliderChange();
|
||||
}
|
||||
|
||||
/*!
|
||||
The origin is the angle where scale and needle is relative to.
|
||||
|
||||
\return Origin of the dial
|
||||
\sa setOrigin()
|
||||
*/
|
||||
double QwtDial::origin() const
|
||||
{
|
||||
return d_data->origin;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Size hint
|
||||
\sa minimumSizeHint()
|
||||
*/
|
||||
QSize QwtDial::sizeHint() const
|
||||
{
|
||||
int sh = 0;
|
||||
if ( scaleDraw() )
|
||||
sh = qCeil( scaleDraw()->extent( font() ) );
|
||||
|
||||
const int d = 6 * sh + 2 * lineWidth();
|
||||
|
||||
QSize hint( d, d );
|
||||
if ( !isReadOnly() )
|
||||
hint = hint.expandedTo( QApplication::globalStrut() );
|
||||
|
||||
return hint;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Minimum size hint
|
||||
\sa sizeHint()
|
||||
*/
|
||||
QSize QwtDial::minimumSizeHint() const
|
||||
{
|
||||
int sh = 0;
|
||||
if ( scaleDraw() )
|
||||
sh = qCeil( scaleDraw()->extent( font() ) );
|
||||
|
||||
const int d = 3 * sh + 2 * lineWidth();
|
||||
|
||||
return QSize( d, d );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Determine what to do when the user presses a mouse button.
|
||||
|
||||
\param pos Mouse position
|
||||
|
||||
\retval True, when the inner circle contains pos
|
||||
\sa scrolledTo()
|
||||
*/
|
||||
bool QwtDial::isScrollPosition( const QPoint &pos ) const
|
||||
{
|
||||
const QRegion region( innerRect(), QRegion::Ellipse );
|
||||
if ( region.contains( pos ) && ( pos != innerRect().center() ) )
|
||||
{
|
||||
double angle = QLineF( rect().center(), pos ).angle();
|
||||
if ( d_data->mode == QwtDial::RotateScale )
|
||||
angle = 360.0 - angle;
|
||||
|
||||
double valueAngle =
|
||||
qwtNormalizeDegrees( 90.0 - scaleMap().transform( value() ) );
|
||||
|
||||
d_data->mouseOffset = qwtNormalizeDegrees( angle - valueAngle );
|
||||
d_data->arcOffset = scaleMap().p1();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Determine the value for a new position of the
|
||||
slider handle.
|
||||
|
||||
\param pos Mouse position
|
||||
|
||||
\return Value for the mouse position
|
||||
\sa isScrollPosition()
|
||||
*/
|
||||
double QwtDial::scrolledTo( const QPoint &pos ) const
|
||||
{
|
||||
double angle = QLineF( rect().center(), pos ).angle();
|
||||
if ( d_data->mode == QwtDial::RotateScale )
|
||||
{
|
||||
angle += scaleMap().p1() - d_data->arcOffset;
|
||||
angle = 360.0 - angle;
|
||||
}
|
||||
|
||||
angle = qwtNormalizeDegrees( angle - d_data->mouseOffset );
|
||||
angle = qwtNormalizeDegrees( 90.0 - angle );
|
||||
|
||||
if ( scaleMap().pDist() >= 360.0 )
|
||||
{
|
||||
if ( angle < scaleMap().p1() )
|
||||
angle += 360.0;
|
||||
|
||||
if ( !wrapping() )
|
||||
{
|
||||
double boundedAngle = angle;
|
||||
|
||||
const double arc = angle - scaleMap().transform( value() );
|
||||
if ( qAbs( arc ) > 180.0 )
|
||||
{
|
||||
boundedAngle = ( arc > 0 )
|
||||
? scaleMap().p1() : scaleMap().p2();
|
||||
}
|
||||
|
||||
d_data->mouseOffset += ( boundedAngle - angle );
|
||||
|
||||
angle = boundedAngle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const double boundedAngle =
|
||||
qwtBoundedAngle( scaleMap().p1(), angle, scaleMap().p2() );
|
||||
|
||||
if ( !wrapping() )
|
||||
d_data->mouseOffset += ( boundedAngle - angle );
|
||||
|
||||
angle = boundedAngle;
|
||||
}
|
||||
|
||||
return scaleMap().invTransform( angle );
|
||||
}
|
||||
|
||||
/*!
|
||||
Change Event handler
|
||||
\param event Change event
|
||||
|
||||
Invalidates internal paint caches if necessary
|
||||
*/
|
||||
void QwtDial::changeEvent( QEvent *event )
|
||||
{
|
||||
switch( event->type() )
|
||||
{
|
||||
case QEvent::EnabledChange:
|
||||
case QEvent::FontChange:
|
||||
case QEvent::StyleChange:
|
||||
case QEvent::PaletteChange:
|
||||
case QEvent::LanguageChange:
|
||||
case QEvent::LocaleChange:
|
||||
{
|
||||
invalidateCache();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QwtAbstractSlider::changeEvent( event );
|
||||
}
|
||||
|
||||
/*!
|
||||
Wheel Event handler
|
||||
\param event Wheel event
|
||||
*/
|
||||
void QwtDial::wheelEvent( QWheelEvent *event )
|
||||
{
|
||||
const QRegion region( innerRect(), QRegion::Ellipse );
|
||||
if ( region.contains( event->pos() ) )
|
||||
QwtAbstractSlider::wheelEvent( event );
|
||||
}
|
||||
|
||||
void QwtDial::setAngleRange( double angle, double span )
|
||||
{
|
||||
QwtRoundScaleDraw *sd = const_cast<QwtRoundScaleDraw *>( scaleDraw() );
|
||||
if ( sd )
|
||||
{
|
||||
angle = qwtNormalizeDegrees( angle - 270.0 );
|
||||
sd->setAngleRange( angle, angle + span );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Invalidate the internal caches and call
|
||||
QwtAbstractSlider::scaleChange()
|
||||
*/
|
||||
void QwtDial::scaleChange()
|
||||
{
|
||||
invalidateCache();
|
||||
QwtAbstractSlider::scaleChange();
|
||||
}
|
||||
|
||||
void QwtDial::sliderChange()
|
||||
{
|
||||
setAngleRange( d_data->origin + d_data->minScaleArc,
|
||||
d_data->maxScaleArc - d_data->minScaleArc );
|
||||
|
||||
if ( mode() == RotateScale )
|
||||
{
|
||||
const double arc = scaleMap().transform( value() ) - scaleMap().p1();
|
||||
setAngleRange( d_data->origin - arc,
|
||||
d_data->maxScaleArc - d_data->minScaleArc );
|
||||
}
|
||||
|
||||
QwtAbstractSlider::sliderChange();
|
||||
}
|
||||
168
third/3rd_qwt/qwt_dial.h
Normal file
168
third/3rd_qwt/qwt_dial.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_DIAL_H
|
||||
#define QWT_DIAL_H 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_abstract_slider.h"
|
||||
#include "qwt_abstract_scale_draw.h"
|
||||
#include <qframe.h>
|
||||
#include <qpalette.h>
|
||||
|
||||
class QwtDialNeedle;
|
||||
class QwtRoundScaleDraw;
|
||||
|
||||
/*!
|
||||
\brief QwtDial class provides a rounded range control.
|
||||
|
||||
QwtDial is intended as base class for dial widgets like
|
||||
speedometers, compass widgets, clocks ...
|
||||
|
||||
\image html dials2.png
|
||||
|
||||
A dial contains a scale and a needle indicating the current value
|
||||
of the dial. Depending on Mode one of them is fixed and the
|
||||
other is rotating. If not isReadOnly() the
|
||||
dial can be rotated by dragging the mouse or using keyboard inputs
|
||||
(see QwtAbstractSlider::keyPressEvent()). A dial might be wrapping, what means
|
||||
a rotation below/above one limit continues on the other limit (f.e compass).
|
||||
The scale might cover any arc of the dial, its values are related to
|
||||
the origin() of the dial.
|
||||
|
||||
Often dials have to be updated very often according to values from external
|
||||
devices. For these high refresh rates QwtDial caches as much as possible.
|
||||
For derived classes it might be necessary to clear these caches manually
|
||||
according to attribute changes using invalidateCache().
|
||||
|
||||
\sa QwtCompass, QwtAnalogClock, QwtDialNeedle
|
||||
\note The controls and dials examples shows different types of dials.
|
||||
\note QDial is more similar to QwtKnob than to QwtDial
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtDial: public QwtAbstractSlider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_ENUMS( Shadow Mode Direction )
|
||||
|
||||
Q_PROPERTY( int lineWidth READ lineWidth WRITE setLineWidth )
|
||||
Q_PROPERTY( Shadow frameShadow READ frameShadow WRITE setFrameShadow )
|
||||
Q_PROPERTY( Mode mode READ mode WRITE setMode )
|
||||
Q_PROPERTY( double origin READ origin WRITE setOrigin )
|
||||
Q_PROPERTY( double minScaleArc READ minScaleArc WRITE setMinScaleArc )
|
||||
Q_PROPERTY( double maxScaleArc READ maxScaleArc WRITE setMaxScaleArc )
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
\brief Frame shadow
|
||||
|
||||
Unfortunately it is not possible to use QFrame::Shadow
|
||||
as a property of a widget that is not derived from QFrame.
|
||||
The following enum is made for the designer only. It is safe
|
||||
to use QFrame::Shadow instead.
|
||||
*/
|
||||
enum Shadow
|
||||
{
|
||||
//! QFrame::Plain
|
||||
Plain = QFrame::Plain,
|
||||
|
||||
//! QFrame::Raised
|
||||
Raised = QFrame::Raised,
|
||||
|
||||
//! QFrame::Sunken
|
||||
Sunken = QFrame::Sunken
|
||||
};
|
||||
|
||||
//! Mode controlling whether the needle or the scale is rotating
|
||||
enum Mode
|
||||
{
|
||||
//! The needle is rotating
|
||||
RotateNeedle,
|
||||
|
||||
//! The needle is fixed, the scales are rotating
|
||||
RotateScale
|
||||
};
|
||||
|
||||
explicit QwtDial( QWidget *parent = NULL );
|
||||
virtual ~QwtDial();
|
||||
|
||||
void setFrameShadow( Shadow );
|
||||
Shadow frameShadow() const;
|
||||
|
||||
void setLineWidth( int );
|
||||
int lineWidth() const;
|
||||
|
||||
void setMode( Mode );
|
||||
Mode mode() const;
|
||||
|
||||
void setScaleArc( double minArc, double maxArc );
|
||||
|
||||
void setMinScaleArc( double );
|
||||
double minScaleArc() const;
|
||||
|
||||
void setMaxScaleArc( double );
|
||||
double maxScaleArc() const;
|
||||
|
||||
virtual void setOrigin( double );
|
||||
double origin() const;
|
||||
|
||||
void setNeedle( QwtDialNeedle * );
|
||||
const QwtDialNeedle *needle() const;
|
||||
QwtDialNeedle *needle();
|
||||
|
||||
QRect boundingRect() const;
|
||||
QRect innerRect() const;
|
||||
|
||||
virtual QRect scaleInnerRect() const;
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
virtual QSize minimumSizeHint() const;
|
||||
|
||||
void setScaleDraw( QwtRoundScaleDraw * );
|
||||
|
||||
QwtRoundScaleDraw *scaleDraw();
|
||||
const QwtRoundScaleDraw *scaleDraw() const;
|
||||
|
||||
protected:
|
||||
virtual void wheelEvent( QWheelEvent * );
|
||||
virtual void paintEvent( QPaintEvent * );
|
||||
virtual void changeEvent( QEvent * );
|
||||
|
||||
virtual void drawFrame( QPainter * );
|
||||
virtual void drawContents( QPainter * ) const;
|
||||
virtual void drawFocusIndicator( QPainter * ) const;
|
||||
|
||||
void invalidateCache();
|
||||
|
||||
virtual void drawScale( QPainter *,
|
||||
const QPointF ¢er, double radius ) const;
|
||||
|
||||
virtual void drawScaleContents( QPainter *painter,
|
||||
const QPointF ¢er, double radius ) const;
|
||||
|
||||
virtual void drawNeedle( QPainter *, const QPointF &,
|
||||
double radius, double direction, QPalette::ColorGroup ) const;
|
||||
|
||||
virtual double scrolledTo( const QPoint & ) const;
|
||||
virtual bool isScrollPosition( const QPoint & ) const;
|
||||
|
||||
virtual void sliderChange();
|
||||
virtual void scaleChange();
|
||||
|
||||
private:
|
||||
void setAngleRange( double angle, double span );
|
||||
void drawNeedle( QPainter * ) const;
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
441
third/3rd_qwt/qwt_dial_needle.cpp
Normal file
441
third/3rd_qwt/qwt_dial_needle.cpp
Normal file
@@ -0,0 +1,441 @@
|
||||
/* -*- 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_dial_needle.h"
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_painter.h"
|
||||
#include "qapplication.h"
|
||||
#include "qpainterpath.h"
|
||||
#include "qpainter.h"
|
||||
|
||||
#if QT_VERSION < 0x040601
|
||||
#define qFastSin(x) qSin(x)
|
||||
#define qFastCos(x) qCos(x)
|
||||
#endif
|
||||
|
||||
static void qwtDrawStyle1Needle( QPainter *painter,
|
||||
const QPalette &palette, QPalette::ColorGroup colorGroup,
|
||||
double length )
|
||||
{
|
||||
const double r[] = { 0.4, 0.3, 1, 0.8, 1, 0.3, 0.4 };
|
||||
const double a[] = { -45, -20, -15, 0, 15, 20, 45 };
|
||||
|
||||
QPainterPath path;
|
||||
for ( int i = 0; i < 7; i++ )
|
||||
{
|
||||
const double angle = a[i] / 180.0 * M_PI;
|
||||
const double radius = r[i] * length;
|
||||
|
||||
const double x = radius * qFastCos( angle );
|
||||
const double y = radius * qFastSin( angle );
|
||||
|
||||
path.lineTo( x, -y );
|
||||
}
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( palette.brush( colorGroup, QPalette::Light ) );
|
||||
painter->drawPath( path );
|
||||
}
|
||||
|
||||
static void qwtDrawStyle2Needle( QPainter *painter,
|
||||
const QPalette &palette, QPalette::ColorGroup colorGroup, double length )
|
||||
{
|
||||
const double ratioX = 0.7;
|
||||
const double ratioY = 0.3;
|
||||
|
||||
QPainterPath path1;
|
||||
path1.lineTo( ratioX * length, 0.0 );
|
||||
path1.lineTo( length, ratioY * length );
|
||||
|
||||
QPainterPath path2;
|
||||
path2.lineTo( ratioX * length, 0.0 );
|
||||
path2.lineTo( length, -ratioY * length );
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
|
||||
painter->setBrush( palette.brush( colorGroup, QPalette::Light ) );
|
||||
painter->drawPath( path1 );
|
||||
|
||||
painter->setBrush( palette.brush( colorGroup, QPalette::Dark ) );
|
||||
painter->drawPath( path2 );
|
||||
}
|
||||
|
||||
static void qwtDrawShadedPointer( QPainter *painter,
|
||||
const QColor &lightColor, const QColor &darkColor,
|
||||
double length, double width )
|
||||
{
|
||||
const double peak = qMax( length / 10.0, 5.0 );
|
||||
|
||||
const double knobWidth = width + 8;
|
||||
QRectF knobRect( 0, 0, knobWidth, knobWidth );
|
||||
knobRect.moveCenter( QPointF(0, 0) );
|
||||
|
||||
QPainterPath path1;
|
||||
path1.lineTo( 0.0, 0.5 * width );
|
||||
path1.lineTo( length - peak, 0.5 * width );
|
||||
path1.lineTo( length, 0.0 );
|
||||
path1.lineTo( 0.0, 0.0 );
|
||||
|
||||
QPainterPath arcPath1;
|
||||
arcPath1.arcTo( knobRect, 0.0, -90.0 );
|
||||
|
||||
path1 = path1.united( arcPath1 );
|
||||
|
||||
QPainterPath path2;
|
||||
path2.lineTo( 0.0, -0.5 * width );
|
||||
path2.lineTo( length - peak, -0.5 * width );
|
||||
path2.lineTo( length, 0.0 );
|
||||
path2.lineTo( 0.0, 0.0 );
|
||||
|
||||
QPainterPath arcPath2;
|
||||
arcPath2.arcTo( knobRect, 0.0, 90.0 );
|
||||
|
||||
path2 = path2.united( arcPath2 );
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
|
||||
painter->setBrush( lightColor );
|
||||
painter->drawPath( path1 );
|
||||
|
||||
painter->setBrush( darkColor );
|
||||
painter->drawPath( path2 );
|
||||
}
|
||||
|
||||
static void qwtDrawArrowNeedle( QPainter *painter,
|
||||
const QPalette &palette, QPalette::ColorGroup colorGroup,
|
||||
double length, double width )
|
||||
{
|
||||
if ( width <= 0 )
|
||||
width = qMax( length * 0.06, 9.0 );
|
||||
|
||||
const double peak = qMax( 2.0, 0.4 * width );
|
||||
|
||||
QPainterPath path;
|
||||
path.moveTo( 0.0, 0.5 * width );
|
||||
path.lineTo( length - peak, 0.3 * width );
|
||||
path.lineTo( length, 0.0 );
|
||||
path.lineTo( length - peak, -0.3 * width );
|
||||
path.lineTo( 0.0, -0.5 * width );
|
||||
|
||||
QRectF br = path.boundingRect();
|
||||
|
||||
QPalette pal( palette.color( QPalette::Mid ) );
|
||||
QColor c1 = pal.color( QPalette::Light );
|
||||
QColor c2 = pal.color( QPalette::Dark );
|
||||
|
||||
QLinearGradient gradient( br.topLeft(), br.bottomLeft() );
|
||||
gradient.setColorAt( 0.0, c1 );
|
||||
gradient.setColorAt( 0.5, c1 );
|
||||
gradient.setColorAt( 0.5001, c2 );
|
||||
gradient.setColorAt( 1.0, c2 );
|
||||
|
||||
QPen pen( gradient, 1 );
|
||||
pen.setJoinStyle( Qt::MiterJoin );
|
||||
|
||||
painter->setPen( pen );
|
||||
painter->setBrush( palette.brush( colorGroup, QPalette::Mid ) );
|
||||
|
||||
painter->drawPath( path );
|
||||
}
|
||||
|
||||
static void qwtDrawTriangleNeedle( QPainter *painter,
|
||||
const QPalette &palette, QPalette::ColorGroup colorGroup,
|
||||
double length )
|
||||
{
|
||||
const double width = qRound( length / 3.0 );
|
||||
|
||||
QPainterPath path[4];
|
||||
|
||||
path[0].lineTo( length, 0.0 );
|
||||
path[0].lineTo( 0.0, width / 2 );
|
||||
|
||||
path[1].lineTo( length, 0.0 );
|
||||
path[1].lineTo( 0.0, -width / 2 );
|
||||
|
||||
path[2].lineTo( -length, 0.0 );
|
||||
path[2].lineTo( 0.0, width / 2 );
|
||||
|
||||
path[3].lineTo( -length, 0.0 );
|
||||
path[3].lineTo( 0.0, -width / 2 );
|
||||
|
||||
|
||||
const int colorOffset = 10;
|
||||
const QColor darkColor = palette.color( colorGroup, QPalette::Dark );
|
||||
const QColor lightColor = palette.color( colorGroup, QPalette::Light );
|
||||
|
||||
QColor color[4];
|
||||
color[0] = darkColor.light( 100 + colorOffset );
|
||||
color[1] = darkColor.dark( 100 + colorOffset );
|
||||
color[2] = lightColor.light( 100 + colorOffset );
|
||||
color[3] = lightColor.dark( 100 + colorOffset );
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
painter->setBrush( color[i] );
|
||||
painter->drawPath( path[i] );
|
||||
}
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtDialNeedle::QwtDialNeedle():
|
||||
d_palette( QApplication::palette() )
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtDialNeedle::~QwtDialNeedle()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the palette for the needle.
|
||||
|
||||
\param palette New Palette
|
||||
*/
|
||||
void QwtDialNeedle::setPalette( const QPalette &palette )
|
||||
{
|
||||
d_palette = palette;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the palette of the needle.
|
||||
*/
|
||||
const QPalette &QwtDialNeedle::palette() const
|
||||
{
|
||||
return d_palette;
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the needle
|
||||
|
||||
\param painter Painter
|
||||
\param center Center of the dial, start position for the needle
|
||||
\param length Length of the needle
|
||||
\param direction Direction of the needle, in degrees counter clockwise
|
||||
\param colorGroup Color group, used for painting
|
||||
*/
|
||||
void QwtDialNeedle::draw( QPainter *painter,
|
||||
const QPointF ¢er, double length, double direction,
|
||||
QPalette::ColorGroup colorGroup ) const
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->translate( center );
|
||||
painter->rotate( -direction );
|
||||
|
||||
drawNeedle( painter, length, colorGroup );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
//! Draw the knob
|
||||
void QwtDialNeedle::drawKnob( QPainter *painter,
|
||||
double width, const QBrush &brush, bool sunken ) const
|
||||
{
|
||||
QPalette palette( brush.color() );
|
||||
|
||||
QColor c1 = palette.color( QPalette::Light );
|
||||
QColor c2 = palette.color( QPalette::Dark );
|
||||
|
||||
if ( sunken )
|
||||
qSwap( c1, c2 );
|
||||
|
||||
QRectF rect( 0.0, 0.0, width, width );
|
||||
rect.moveCenter( painter->combinedTransform().map( QPointF() ) );
|
||||
|
||||
QLinearGradient gradient( rect.topLeft(), rect.bottomRight() );
|
||||
gradient.setColorAt( 0.0, c1 );
|
||||
gradient.setColorAt( 0.3, c1 );
|
||||
gradient.setColorAt( 0.7, c2 );
|
||||
gradient.setColorAt( 1.0, c2 );
|
||||
|
||||
painter->save();
|
||||
|
||||
painter->resetTransform();
|
||||
|
||||
painter->setPen( QPen( gradient, 1 ) );
|
||||
painter->setBrush( brush );
|
||||
painter->drawEllipse( rect );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
\param style Style
|
||||
\param hasKnob With/Without knob
|
||||
\param mid Middle color
|
||||
\param base Base color
|
||||
*/
|
||||
QwtDialSimpleNeedle::QwtDialSimpleNeedle( Style style, bool hasKnob,
|
||||
const QColor &mid, const QColor &base ):
|
||||
d_style( style ),
|
||||
d_hasKnob( hasKnob ),
|
||||
d_width( -1 )
|
||||
{
|
||||
QPalette palette;
|
||||
palette.setColor( QPalette::Mid, mid );
|
||||
palette.setColor( QPalette::Base, base );
|
||||
|
||||
setPalette( palette );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the width of the needle
|
||||
\param width Width
|
||||
\sa width()
|
||||
*/
|
||||
void QwtDialSimpleNeedle::setWidth( double width )
|
||||
{
|
||||
d_width = width;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the width of the needle
|
||||
\sa setWidth()
|
||||
*/
|
||||
double QwtDialSimpleNeedle::width() const
|
||||
{
|
||||
return d_width;
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the needle
|
||||
|
||||
\param painter Painter
|
||||
\param length Length of the needle
|
||||
\param colorGroup Color group, used for painting
|
||||
*/
|
||||
void QwtDialSimpleNeedle::drawNeedle( QPainter *painter,
|
||||
double length, QPalette::ColorGroup colorGroup ) const
|
||||
{
|
||||
double knobWidth = 0.0;
|
||||
double width = d_width;
|
||||
|
||||
if ( d_style == Arrow )
|
||||
{
|
||||
if ( width <= 0.0 )
|
||||
width = qMax(length * 0.06, 6.0);
|
||||
|
||||
qwtDrawArrowNeedle( painter,
|
||||
palette(), colorGroup, length, width );
|
||||
|
||||
knobWidth = qMin( width * 2.0, 0.2 * length );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( width <= 0.0 )
|
||||
width = 5.0;
|
||||
|
||||
QPen pen ( palette().brush( colorGroup, QPalette::Mid ), width );
|
||||
pen.setCapStyle( Qt::FlatCap );
|
||||
|
||||
painter->setPen( pen );
|
||||
painter->drawLine( QPointF( 0.0, 0.0 ), QPointF( length, 0.0 ) );
|
||||
|
||||
knobWidth = qMax( width * 3.0, 5.0 );
|
||||
}
|
||||
|
||||
if ( d_hasKnob && knobWidth > 0.0 )
|
||||
{
|
||||
drawKnob( painter, knobWidth,
|
||||
palette().brush( colorGroup, QPalette::Base ), false );
|
||||
}
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtCompassMagnetNeedle::QwtCompassMagnetNeedle( Style style,
|
||||
const QColor &light, const QColor &dark ):
|
||||
d_style( style )
|
||||
{
|
||||
QPalette palette;
|
||||
palette.setColor( QPalette::Light, light );
|
||||
palette.setColor( QPalette::Dark, dark );
|
||||
palette.setColor( QPalette::Base, Qt::gray );
|
||||
|
||||
setPalette( palette );
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the needle
|
||||
|
||||
\param painter Painter
|
||||
\param length Length of the needle
|
||||
\param colorGroup Color group, used for painting
|
||||
*/
|
||||
void QwtCompassMagnetNeedle::drawNeedle( QPainter *painter,
|
||||
double length, QPalette::ColorGroup colorGroup ) const
|
||||
{
|
||||
if ( d_style == ThinStyle )
|
||||
{
|
||||
const double width = qMax( length / 6.0, 3.0 );
|
||||
|
||||
const int colorOffset = 10;
|
||||
|
||||
const QColor light = palette().color( colorGroup, QPalette::Light );
|
||||
const QColor dark = palette().color( colorGroup, QPalette::Dark );
|
||||
|
||||
qwtDrawShadedPointer( painter,
|
||||
dark.light( 100 + colorOffset ),
|
||||
dark.dark( 100 + colorOffset ),
|
||||
length, width );
|
||||
|
||||
painter->rotate( 180.0 );
|
||||
|
||||
qwtDrawShadedPointer( painter,
|
||||
light.light( 100 + colorOffset ),
|
||||
light.dark( 100 + colorOffset ),
|
||||
length, width );
|
||||
|
||||
const QBrush baseBrush = palette().brush( colorGroup, QPalette::Base );
|
||||
drawKnob( painter, width, baseBrush, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
qwtDrawTriangleNeedle( painter, palette(), colorGroup, length );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
\param style Arrow style
|
||||
\param light Light color
|
||||
\param dark Dark color
|
||||
*/
|
||||
QwtCompassWindArrow::QwtCompassWindArrow( Style style,
|
||||
const QColor &light, const QColor &dark ):
|
||||
d_style( style )
|
||||
{
|
||||
QPalette palette;
|
||||
palette.setColor( QPalette::Light, light );
|
||||
palette.setColor( QPalette::Dark, dark );
|
||||
|
||||
setPalette( palette );
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the needle
|
||||
|
||||
\param painter Painter
|
||||
\param length Length of the needle
|
||||
\param colorGroup Color group, used for painting
|
||||
*/
|
||||
void QwtCompassWindArrow::drawNeedle( QPainter *painter,
|
||||
double length, QPalette::ColorGroup colorGroup ) const
|
||||
{
|
||||
if ( d_style == Style1 )
|
||||
qwtDrawStyle1Needle( painter, palette(), colorGroup, length );
|
||||
else
|
||||
qwtDrawStyle2Needle( painter, palette(), colorGroup, length );
|
||||
}
|
||||
187
third/3rd_qwt/qwt_dial_needle.h
Normal file
187
third/3rd_qwt/qwt_dial_needle.h
Normal file
@@ -0,0 +1,187 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_DIAL_NEEDLE_H
|
||||
#define QWT_DIAL_NEEDLE_H 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qpalette.h>
|
||||
|
||||
class QPainter;
|
||||
class QPoint;
|
||||
|
||||
/*!
|
||||
\brief Base class for needles that can be used in a QwtDial.
|
||||
|
||||
QwtDialNeedle is a pointer that indicates a value by pointing
|
||||
to a specific direction.
|
||||
|
||||
\sa QwtDial, QwtCompass
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtDialNeedle
|
||||
{
|
||||
public:
|
||||
QwtDialNeedle();
|
||||
virtual ~QwtDialNeedle();
|
||||
|
||||
virtual void setPalette( const QPalette & );
|
||||
const QPalette &palette() const;
|
||||
|
||||
virtual void draw( QPainter *painter, const QPointF ¢er,
|
||||
double length, double direction,
|
||||
QPalette::ColorGroup = QPalette::Active ) const;
|
||||
|
||||
protected:
|
||||
/*!
|
||||
\brief Draw the needle
|
||||
|
||||
The origin of the needle is at position (0.0, 0.0 )
|
||||
pointing in direction 0.0 ( = east ).
|
||||
|
||||
The painter is already initialized with translation and
|
||||
rotation.
|
||||
|
||||
\param painter Painter
|
||||
\param length Length of the needle
|
||||
\param colorGroup Color group, used for painting
|
||||
|
||||
\sa setPalette(), palette()
|
||||
*/
|
||||
virtual void drawNeedle( QPainter *painter,
|
||||
double length, QPalette::ColorGroup colorGroup ) const = 0;
|
||||
|
||||
virtual void drawKnob( QPainter *, double width,
|
||||
const QBrush &, bool sunken ) const;
|
||||
|
||||
private:
|
||||
QPalette d_palette;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A needle for dial widgets
|
||||
|
||||
The following colors are used:
|
||||
|
||||
- QPalette::Mid\n
|
||||
Pointer
|
||||
- QPalette::Base\n
|
||||
Knob
|
||||
|
||||
\sa QwtDial, QwtCompass
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtDialSimpleNeedle: public QwtDialNeedle
|
||||
{
|
||||
public:
|
||||
//! Style of the needle
|
||||
enum Style
|
||||
{
|
||||
//! Arrow
|
||||
Arrow,
|
||||
|
||||
//! A straight line from the center
|
||||
Ray
|
||||
};
|
||||
|
||||
QwtDialSimpleNeedle( Style, bool hasKnob = true,
|
||||
const QColor &mid = Qt::gray, const QColor &base = Qt::darkGray );
|
||||
|
||||
void setWidth( double width );
|
||||
double width() const;
|
||||
|
||||
protected:
|
||||
virtual void drawNeedle( QPainter *, double length,
|
||||
QPalette::ColorGroup ) const;
|
||||
|
||||
private:
|
||||
Style d_style;
|
||||
bool d_hasKnob;
|
||||
double d_width;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A magnet needle for compass widgets
|
||||
|
||||
A magnet needle points to two opposite directions indicating
|
||||
north and south.
|
||||
|
||||
The following colors are used:
|
||||
- QPalette::Light\n
|
||||
Used for pointing south
|
||||
- QPalette::Dark\n
|
||||
Used for pointing north
|
||||
- QPalette::Base\n
|
||||
Knob (ThinStyle only)
|
||||
|
||||
\sa QwtDial, QwtCompass
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtCompassMagnetNeedle: public QwtDialNeedle
|
||||
{
|
||||
public:
|
||||
//! Style of the needle
|
||||
enum Style
|
||||
{
|
||||
//! A needle with a triangular shape
|
||||
TriangleStyle,
|
||||
|
||||
//! A thin needle
|
||||
ThinStyle
|
||||
};
|
||||
|
||||
QwtCompassMagnetNeedle( Style = TriangleStyle,
|
||||
const QColor &light = Qt::white, const QColor &dark = Qt::red );
|
||||
|
||||
protected:
|
||||
virtual void drawNeedle( QPainter *,
|
||||
double length, QPalette::ColorGroup ) const;
|
||||
|
||||
private:
|
||||
Style d_style;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief An indicator for the wind direction
|
||||
|
||||
QwtCompassWindArrow shows the direction where the wind comes from.
|
||||
|
||||
- QPalette::Light\n
|
||||
Used for Style1, or the light half of Style2
|
||||
- QPalette::Dark\n
|
||||
Used for the dark half of Style2
|
||||
|
||||
\sa QwtDial, QwtCompass
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtCompassWindArrow: public QwtDialNeedle
|
||||
{
|
||||
public:
|
||||
//! Style of the arrow
|
||||
enum Style
|
||||
{
|
||||
//! A needle pointing to the center
|
||||
Style1,
|
||||
|
||||
//! A needle pointing to the center
|
||||
Style2
|
||||
};
|
||||
|
||||
QwtCompassWindArrow( Style, const QColor &light = Qt::white,
|
||||
const QColor &dark = Qt::gray );
|
||||
|
||||
protected:
|
||||
virtual void drawNeedle( QPainter *,
|
||||
double length, QPalette::ColorGroup ) const;
|
||||
|
||||
private:
|
||||
Style d_style;
|
||||
};
|
||||
|
||||
#endif
|
||||
591
third/3rd_qwt/qwt_dyngrid_layout.cpp
Normal file
591
third/3rd_qwt/qwt_dyngrid_layout.cpp
Normal file
@@ -0,0 +1,591 @@
|
||||
/* -*- 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_dyngrid_layout.h"
|
||||
#include "qwt_math.h"
|
||||
#include <qvector.h>
|
||||
#include <qlist.h>
|
||||
|
||||
class QwtDynGridLayout::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
isDirty( true )
|
||||
{
|
||||
}
|
||||
|
||||
void updateLayoutCache();
|
||||
|
||||
mutable QList<QLayoutItem*> itemList;
|
||||
|
||||
uint maxColumns;
|
||||
uint numRows;
|
||||
uint numColumns;
|
||||
|
||||
Qt::Orientations expanding;
|
||||
|
||||
bool isDirty;
|
||||
QVector<QSize> itemSizeHints;
|
||||
};
|
||||
|
||||
void QwtDynGridLayout::PrivateData::updateLayoutCache()
|
||||
{
|
||||
itemSizeHints.resize( itemList.count() );
|
||||
|
||||
int index = 0;
|
||||
|
||||
for ( QList<QLayoutItem*>::iterator it = itemList.begin();
|
||||
it != itemList.end(); ++it, index++ )
|
||||
{
|
||||
itemSizeHints[ index ] = ( *it )->sizeHint();
|
||||
}
|
||||
|
||||
isDirty = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\param parent Parent widget
|
||||
\param margin Margin
|
||||
\param spacing Spacing
|
||||
*/
|
||||
|
||||
QwtDynGridLayout::QwtDynGridLayout( QWidget *parent,
|
||||
int margin, int spacing ):
|
||||
QLayout( parent )
|
||||
{
|
||||
init();
|
||||
|
||||
setSpacing( spacing );
|
||||
setMargin( margin );
|
||||
}
|
||||
|
||||
/*!
|
||||
\param spacing Spacing
|
||||
*/
|
||||
|
||||
QwtDynGridLayout::QwtDynGridLayout( int spacing )
|
||||
{
|
||||
init();
|
||||
setSpacing( spacing );
|
||||
}
|
||||
|
||||
/*!
|
||||
Initialize the layout with default values.
|
||||
*/
|
||||
void QwtDynGridLayout::init()
|
||||
{
|
||||
d_data = new QwtDynGridLayout::PrivateData;
|
||||
d_data->maxColumns = d_data->numRows = d_data->numColumns = 0;
|
||||
d_data->expanding = 0;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
|
||||
QwtDynGridLayout::~QwtDynGridLayout()
|
||||
{
|
||||
for ( int i = 0; i < d_data->itemList.size(); i++ )
|
||||
delete d_data->itemList[i];
|
||||
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
//! Invalidate all internal caches
|
||||
void QwtDynGridLayout::invalidate()
|
||||
{
|
||||
d_data->isDirty = true;
|
||||
QLayout::invalidate();
|
||||
}
|
||||
|
||||
/*!
|
||||
Limit the number of columns.
|
||||
\param maxColumns upper limit, 0 means unlimited
|
||||
\sa maxColumns()
|
||||
*/
|
||||
void QwtDynGridLayout::setMaxColumns( uint maxColumns )
|
||||
{
|
||||
d_data->maxColumns = maxColumns;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Return the upper limit for the number of columns.
|
||||
|
||||
0 means unlimited, what is the default.
|
||||
|
||||
\return Upper limit for the number of columns
|
||||
\sa setMaxColumns()
|
||||
*/
|
||||
uint QwtDynGridLayout::maxColumns() const
|
||||
{
|
||||
return d_data->maxColumns;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Add an item to the next free position.
|
||||
\param item Layout item
|
||||
*/
|
||||
void QwtDynGridLayout::addItem( QLayoutItem *item )
|
||||
{
|
||||
d_data->itemList.append( item );
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return true if this layout is empty.
|
||||
*/
|
||||
bool QwtDynGridLayout::isEmpty() const
|
||||
{
|
||||
return d_data->itemList.isEmpty();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return number of layout items
|
||||
*/
|
||||
uint QwtDynGridLayout::itemCount() const
|
||||
{
|
||||
return d_data->itemList.count();
|
||||
}
|
||||
|
||||
/*!
|
||||
Find the item at a specific index
|
||||
|
||||
\param index Index
|
||||
\return Item at a specific index
|
||||
\sa takeAt()
|
||||
*/
|
||||
QLayoutItem *QwtDynGridLayout::itemAt( int index ) const
|
||||
{
|
||||
if ( index < 0 || index >= d_data->itemList.count() )
|
||||
return NULL;
|
||||
|
||||
return d_data->itemList.at( index );
|
||||
}
|
||||
|
||||
/*!
|
||||
Find the item at a specific index and remove it from the layout
|
||||
|
||||
\param index Index
|
||||
\return Layout item, removed from the layout
|
||||
\sa itemAt()
|
||||
*/
|
||||
QLayoutItem *QwtDynGridLayout::takeAt( int index )
|
||||
{
|
||||
if ( index < 0 || index >= d_data->itemList.count() )
|
||||
return NULL;
|
||||
|
||||
d_data->isDirty = true;
|
||||
return d_data->itemList.takeAt( index );
|
||||
}
|
||||
|
||||
//! \return Number of items in the layout
|
||||
int QwtDynGridLayout::count() const
|
||||
{
|
||||
return d_data->itemList.count();
|
||||
}
|
||||
|
||||
/*!
|
||||
Set whether this layout can make use of more space than sizeHint().
|
||||
A value of Qt::Vertical or Qt::Horizontal means that it wants to grow in only
|
||||
one dimension, while Qt::Vertical | Qt::Horizontal means that it wants
|
||||
to grow in both dimensions. The default value is 0.
|
||||
|
||||
\param expanding Or'd orientations
|
||||
\sa expandingDirections()
|
||||
*/
|
||||
void QwtDynGridLayout::setExpandingDirections( Qt::Orientations expanding )
|
||||
{
|
||||
d_data->expanding = expanding;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Returns whether this layout can make use of more space than sizeHint().
|
||||
|
||||
A value of Qt::Vertical or Qt::Horizontal means that it wants to grow in only
|
||||
one dimension, while Qt::Vertical | Qt::Horizontal means that it wants
|
||||
to grow in both dimensions.
|
||||
|
||||
\return Orientations, where the layout expands
|
||||
\sa setExpandingDirections()
|
||||
*/
|
||||
Qt::Orientations QwtDynGridLayout::expandingDirections() const
|
||||
{
|
||||
return d_data->expanding;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reorganizes columns and rows and resizes managed items within
|
||||
a rectangle.
|
||||
|
||||
\param rect Layout geometry
|
||||
*/
|
||||
void QwtDynGridLayout::setGeometry( const QRect &rect )
|
||||
{
|
||||
QLayout::setGeometry( rect );
|
||||
|
||||
if ( isEmpty() )
|
||||
return;
|
||||
|
||||
d_data->numColumns = columnsForWidth( rect.width() );
|
||||
d_data->numRows = itemCount() / d_data->numColumns;
|
||||
if ( itemCount() % d_data->numColumns )
|
||||
d_data->numRows++;
|
||||
|
||||
QList<QRect> itemGeometries = layoutItems( rect, d_data->numColumns );
|
||||
|
||||
int index = 0;
|
||||
for ( QList<QLayoutItem*>::iterator it = d_data->itemList.begin();
|
||||
it != d_data->itemList.end(); ++it )
|
||||
{
|
||||
( *it )->setGeometry( itemGeometries[index] );
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Calculate the number of columns for a given width.
|
||||
|
||||
The calculation tries to use as many columns as possible
|
||||
( limited by maxColumns() )
|
||||
|
||||
\param width Available width for all columns
|
||||
\return Number of columns for a given width
|
||||
|
||||
\sa maxColumns(), setMaxColumns()
|
||||
*/
|
||||
uint QwtDynGridLayout::columnsForWidth( int width ) const
|
||||
{
|
||||
if ( isEmpty() )
|
||||
return 0;
|
||||
|
||||
uint maxColumns = itemCount();
|
||||
if ( d_data->maxColumns > 0 )
|
||||
maxColumns = qMin( d_data->maxColumns, maxColumns );
|
||||
|
||||
if ( maxRowWidth( maxColumns ) <= width )
|
||||
return maxColumns;
|
||||
|
||||
for ( uint numColumns = 2; numColumns <= maxColumns; numColumns++ )
|
||||
{
|
||||
const int rowWidth = maxRowWidth( numColumns );
|
||||
if ( rowWidth > width )
|
||||
return numColumns - 1;
|
||||
}
|
||||
|
||||
return 1; // At least 1 column
|
||||
}
|
||||
|
||||
/*!
|
||||
Calculate the width of a layout for a given number of
|
||||
columns.
|
||||
|
||||
\param numColumns Given number of columns
|
||||
\param itemWidth Array of the width hints for all items
|
||||
*/
|
||||
int QwtDynGridLayout::maxRowWidth( int numColumns ) const
|
||||
{
|
||||
int col;
|
||||
|
||||
QVector<int> colWidth( numColumns );
|
||||
for ( col = 0; col < numColumns; col++ )
|
||||
colWidth[col] = 0;
|
||||
|
||||
if ( d_data->isDirty )
|
||||
d_data->updateLayoutCache();
|
||||
|
||||
for ( int index = 0;
|
||||
index < d_data->itemSizeHints.count(); index++ )
|
||||
{
|
||||
col = index % numColumns;
|
||||
colWidth[col] = qMax( colWidth[col],
|
||||
d_data->itemSizeHints[int( index )].width() );
|
||||
}
|
||||
|
||||
int rowWidth = 2 * margin() + ( numColumns - 1 ) * spacing();
|
||||
for ( col = 0; col < numColumns; col++ )
|
||||
rowWidth += colWidth[col];
|
||||
|
||||
return rowWidth;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the maximum width of all layout items
|
||||
*/
|
||||
int QwtDynGridLayout::maxItemWidth() const
|
||||
{
|
||||
if ( isEmpty() )
|
||||
return 0;
|
||||
|
||||
if ( d_data->isDirty )
|
||||
d_data->updateLayoutCache();
|
||||
|
||||
int w = 0;
|
||||
for ( int i = 0; i < d_data->itemSizeHints.count(); i++ )
|
||||
{
|
||||
const int itemW = d_data->itemSizeHints[i].width();
|
||||
if ( itemW > w )
|
||||
w = itemW;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/*!
|
||||
Calculate the geometries of the layout items for a layout
|
||||
with numColumns columns and a given rectangle.
|
||||
|
||||
\param rect Rect where to place the items
|
||||
\param numColumns Number of columns
|
||||
\return item geometries
|
||||
*/
|
||||
|
||||
QList<QRect> QwtDynGridLayout::layoutItems( const QRect &rect,
|
||||
uint numColumns ) const
|
||||
{
|
||||
QList<QRect> itemGeometries;
|
||||
if ( numColumns == 0 || isEmpty() )
|
||||
return itemGeometries;
|
||||
|
||||
uint numRows = itemCount() / numColumns;
|
||||
if ( numColumns % itemCount() )
|
||||
numRows++;
|
||||
|
||||
if ( numRows == 0 )
|
||||
return itemGeometries;
|
||||
|
||||
QVector<int> rowHeight( numRows );
|
||||
QVector<int> colWidth( numColumns );
|
||||
|
||||
layoutGrid( numColumns, rowHeight, colWidth );
|
||||
|
||||
bool expandH, expandV;
|
||||
expandH = expandingDirections() & Qt::Horizontal;
|
||||
expandV = expandingDirections() & Qt::Vertical;
|
||||
|
||||
if ( expandH || expandV )
|
||||
stretchGrid( rect, numColumns, rowHeight, colWidth );
|
||||
|
||||
const int maxColumns = d_data->maxColumns;
|
||||
d_data->maxColumns = numColumns;
|
||||
const QRect alignedRect = alignmentRect( rect );
|
||||
d_data->maxColumns = maxColumns;
|
||||
|
||||
const int xOffset = expandH ? 0 : alignedRect.x();
|
||||
const int yOffset = expandV ? 0 : alignedRect.y();
|
||||
|
||||
QVector<int> colX( numColumns );
|
||||
QVector<int> rowY( numRows );
|
||||
|
||||
const int xySpace = spacing();
|
||||
|
||||
rowY[0] = yOffset + margin();
|
||||
for ( uint r = 1; r < numRows; r++ )
|
||||
rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace;
|
||||
|
||||
colX[0] = xOffset + margin();
|
||||
for ( uint c = 1; c < numColumns; c++ )
|
||||
colX[c] = colX[c-1] + colWidth[c-1] + xySpace;
|
||||
|
||||
const int itemCount = d_data->itemList.size();
|
||||
for ( int i = 0; i < itemCount; i++ )
|
||||
{
|
||||
const int row = i / numColumns;
|
||||
const int col = i % numColumns;
|
||||
|
||||
QRect itemGeometry( colX[col], rowY[row],
|
||||
colWidth[col], rowHeight[row] );
|
||||
itemGeometries.append( itemGeometry );
|
||||
}
|
||||
|
||||
return itemGeometries;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Calculate the dimensions for the columns and rows for a grid
|
||||
of numColumns columns.
|
||||
|
||||
\param numColumns Number of columns.
|
||||
\param rowHeight Array where to fill in the calculated row heights.
|
||||
\param colWidth Array where to fill in the calculated column widths.
|
||||
*/
|
||||
|
||||
void QwtDynGridLayout::layoutGrid( uint numColumns,
|
||||
QVector<int>& rowHeight, QVector<int>& colWidth ) const
|
||||
{
|
||||
if ( numColumns <= 0 )
|
||||
return;
|
||||
|
||||
if ( d_data->isDirty )
|
||||
d_data->updateLayoutCache();
|
||||
|
||||
for ( int index = 0; index < d_data->itemSizeHints.count(); index++ )
|
||||
{
|
||||
const int row = index / numColumns;
|
||||
const int col = index % numColumns;
|
||||
|
||||
const QSize &size = d_data->itemSizeHints[int( index )];
|
||||
|
||||
rowHeight[row] = ( col == 0 )
|
||||
? size.height() : qMax( rowHeight[row], size.height() );
|
||||
colWidth[col] = ( row == 0 )
|
||||
? size.width() : qMax( colWidth[col], size.width() );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return true: QwtDynGridLayout implements heightForWidth().
|
||||
\sa heightForWidth()
|
||||
*/
|
||||
bool QwtDynGridLayout::hasHeightForWidth() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The preferred height for this layout, given a width.
|
||||
\sa hasHeightForWidth()
|
||||
*/
|
||||
int QwtDynGridLayout::heightForWidth( int width ) const
|
||||
{
|
||||
if ( isEmpty() )
|
||||
return 0;
|
||||
|
||||
const uint numColumns = columnsForWidth( width );
|
||||
uint numRows = itemCount() / numColumns;
|
||||
if ( itemCount() % numColumns )
|
||||
numRows++;
|
||||
|
||||
QVector<int> rowHeight( numRows );
|
||||
QVector<int> colWidth( numColumns );
|
||||
|
||||
layoutGrid( numColumns, rowHeight, colWidth );
|
||||
|
||||
int h = 2 * margin() + ( numRows - 1 ) * spacing();
|
||||
for ( uint row = 0; row < numRows; row++ )
|
||||
h += rowHeight[row];
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/*!
|
||||
Stretch columns in case of expanding() & QSizePolicy::Horizontal and
|
||||
rows in case of expanding() & QSizePolicy::Vertical to fill the entire
|
||||
rect. Rows and columns are stretched with the same factor.
|
||||
|
||||
\param rect Bounding rectangle
|
||||
\param numColumns Number of columns
|
||||
\param rowHeight Array to be filled with the calculated row heights
|
||||
\param colWidth Array to be filled with the calculated column widths
|
||||
|
||||
\sa setExpanding(), expanding()
|
||||
*/
|
||||
void QwtDynGridLayout::stretchGrid( const QRect &rect,
|
||||
uint numColumns, QVector<int>& rowHeight, QVector<int>& colWidth ) const
|
||||
{
|
||||
if ( numColumns == 0 || isEmpty() )
|
||||
return;
|
||||
|
||||
bool expandH, expandV;
|
||||
expandH = expandingDirections() & Qt::Horizontal;
|
||||
expandV = expandingDirections() & Qt::Vertical;
|
||||
|
||||
if ( expandH )
|
||||
{
|
||||
int xDelta = rect.width() - 2 * margin() - ( numColumns - 1 ) * spacing();
|
||||
for ( uint col = 0; col < numColumns; col++ )
|
||||
xDelta -= colWidth[col];
|
||||
|
||||
if ( xDelta > 0 )
|
||||
{
|
||||
for ( uint col = 0; col < numColumns; col++ )
|
||||
{
|
||||
const int space = xDelta / ( numColumns - col );
|
||||
colWidth[col] += space;
|
||||
xDelta -= space;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( expandV )
|
||||
{
|
||||
uint numRows = itemCount() / numColumns;
|
||||
if ( itemCount() % numColumns )
|
||||
numRows++;
|
||||
|
||||
int yDelta = rect.height() - 2 * margin() - ( numRows - 1 ) * spacing();
|
||||
for ( uint row = 0; row < numRows; row++ )
|
||||
yDelta -= rowHeight[row];
|
||||
|
||||
if ( yDelta > 0 )
|
||||
{
|
||||
for ( uint row = 0; row < numRows; row++ )
|
||||
{
|
||||
const int space = yDelta / ( numRows - row );
|
||||
rowHeight[row] += space;
|
||||
yDelta -= space;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Return the size hint. If maxColumns() > 0 it is the size for
|
||||
a grid with maxColumns() columns, otherwise it is the size for
|
||||
a grid with only one row.
|
||||
|
||||
\return Size hint
|
||||
\sa maxColumns(), setMaxColumns()
|
||||
*/
|
||||
QSize QwtDynGridLayout::sizeHint() const
|
||||
{
|
||||
if ( isEmpty() )
|
||||
return QSize();
|
||||
|
||||
uint numColumns = itemCount();
|
||||
if ( d_data->maxColumns > 0 )
|
||||
numColumns = qMin( d_data->maxColumns, numColumns );
|
||||
|
||||
uint numRows = itemCount() / numColumns;
|
||||
if ( itemCount() % numColumns )
|
||||
numRows++;
|
||||
|
||||
QVector<int> rowHeight( numRows );
|
||||
QVector<int> colWidth( numColumns );
|
||||
|
||||
layoutGrid( numColumns, rowHeight, colWidth );
|
||||
|
||||
int h = 2 * margin() + ( numRows - 1 ) * spacing();
|
||||
for ( uint row = 0; row < numRows; row++ )
|
||||
h += rowHeight[row];
|
||||
|
||||
int w = 2 * margin() + ( numColumns - 1 ) * spacing();
|
||||
for ( uint col = 0; col < numColumns; col++ )
|
||||
w += colWidth[col];
|
||||
|
||||
return QSize( w, h );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of rows of the current layout.
|
||||
\sa numColumns()
|
||||
\warning The number of rows might change whenever the geometry changes
|
||||
*/
|
||||
uint QwtDynGridLayout::numRows() const
|
||||
{
|
||||
return d_data->numRows;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of columns of the current layout.
|
||||
\sa numRows()
|
||||
\warning The number of columns might change whenever the geometry changes
|
||||
*/
|
||||
uint QwtDynGridLayout::numColumns() const
|
||||
{
|
||||
return d_data->numColumns;
|
||||
}
|
||||
83
third/3rd_qwt/qwt_dyngrid_layout.h
Normal file
83
third/3rd_qwt/qwt_dyngrid_layout.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_DYNGRID_LAYOUT_H
|
||||
#define QWT_DYNGRID_LAYOUT_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qlayout.h>
|
||||
#include <qsize.h>
|
||||
#include <qlist.h>
|
||||
|
||||
/*!
|
||||
\brief The QwtDynGridLayout class lays out widgets in a grid,
|
||||
adjusting the number of columns and rows to the current size.
|
||||
|
||||
QwtDynGridLayout takes the space it gets, divides it up into rows and
|
||||
columns, and puts each of the widgets it manages into the correct cell(s).
|
||||
It lays out as many number of columns as possible (limited by maxColumns()).
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtDynGridLayout : public QLayout
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QwtDynGridLayout( QWidget *, int margin = 0, int spacing = -1 );
|
||||
explicit QwtDynGridLayout( int spacing = -1 );
|
||||
|
||||
virtual ~QwtDynGridLayout();
|
||||
|
||||
virtual void invalidate();
|
||||
|
||||
void setMaxColumns( uint maxColumns );
|
||||
uint maxColumns() const;
|
||||
|
||||
uint numRows () const;
|
||||
uint numColumns () const;
|
||||
|
||||
virtual void addItem( QLayoutItem * );
|
||||
|
||||
virtual QLayoutItem *itemAt( int index ) const;
|
||||
virtual QLayoutItem *takeAt( int index );
|
||||
virtual int count() const;
|
||||
|
||||
void setExpandingDirections( Qt::Orientations );
|
||||
virtual Qt::Orientations expandingDirections() const;
|
||||
QList<QRect> layoutItems( const QRect &, uint numColumns ) const;
|
||||
|
||||
virtual int maxItemWidth() const;
|
||||
|
||||
virtual void setGeometry( const QRect &rect );
|
||||
|
||||
virtual bool hasHeightForWidth() const;
|
||||
virtual int heightForWidth( int ) const;
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
virtual bool isEmpty() const;
|
||||
uint itemCount() const;
|
||||
|
||||
virtual uint columnsForWidth( int width ) const;
|
||||
|
||||
protected:
|
||||
|
||||
void layoutGrid( uint numColumns,
|
||||
QVector<int>& rowHeight, QVector<int>& colWidth ) const;
|
||||
void stretchGrid( const QRect &rect, uint numColumns,
|
||||
QVector<int>& rowHeight, QVector<int>& colWidth ) const;
|
||||
|
||||
private:
|
||||
void init();
|
||||
int maxRowWidth( int numColumns ) const;
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
265
third/3rd_qwt/qwt_event_pattern.cpp
Normal file
265
third/3rd_qwt/qwt_event_pattern.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/* -*- 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_event_pattern.h"
|
||||
#include <qevent.h>
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
\sa MousePatternCode, KeyPatternCode
|
||||
*/
|
||||
|
||||
QwtEventPattern::QwtEventPattern():
|
||||
d_mousePattern( MousePatternCount ),
|
||||
d_keyPattern( KeyPatternCount )
|
||||
{
|
||||
initKeyPattern();
|
||||
initMousePattern( 3 );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtEventPattern::~QwtEventPattern()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Set default mouse patterns, depending on the number of mouse buttons
|
||||
|
||||
\param numButtons Number of mouse buttons ( <= 3 )
|
||||
\sa MousePatternCode
|
||||
*/
|
||||
void QwtEventPattern::initMousePattern( int numButtons )
|
||||
{
|
||||
d_mousePattern.resize( MousePatternCount );
|
||||
|
||||
switch ( numButtons )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
setMousePattern( MouseSelect1, Qt::LeftButton );
|
||||
setMousePattern( MouseSelect2, Qt::LeftButton, Qt::ControlModifier );
|
||||
setMousePattern( MouseSelect3, Qt::LeftButton, Qt::AltModifier );
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
setMousePattern( MouseSelect1, Qt::LeftButton );
|
||||
setMousePattern( MouseSelect2, Qt::RightButton );
|
||||
setMousePattern( MouseSelect3, Qt::LeftButton, Qt::AltModifier );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
setMousePattern( MouseSelect1, Qt::LeftButton );
|
||||
setMousePattern( MouseSelect2, Qt::RightButton );
|
||||
setMousePattern( MouseSelect3, Qt::MidButton );
|
||||
}
|
||||
}
|
||||
|
||||
setMousePattern( MouseSelect4, d_mousePattern[MouseSelect1].button,
|
||||
d_mousePattern[MouseSelect1].modifiers | Qt::ShiftModifier );
|
||||
|
||||
setMousePattern( MouseSelect5, d_mousePattern[MouseSelect2].button,
|
||||
d_mousePattern[MouseSelect2].modifiers | Qt::ShiftModifier );
|
||||
|
||||
setMousePattern( MouseSelect6, d_mousePattern[MouseSelect3].button,
|
||||
d_mousePattern[MouseSelect3].modifiers | Qt::ShiftModifier );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set default mouse patterns.
|
||||
|
||||
\sa KeyPatternCode
|
||||
*/
|
||||
void QwtEventPattern::initKeyPattern()
|
||||
{
|
||||
d_keyPattern.resize( KeyPatternCount );
|
||||
|
||||
setKeyPattern( KeySelect1, Qt::Key_Return );
|
||||
setKeyPattern( KeySelect2, Qt::Key_Space );
|
||||
setKeyPattern( KeyAbort, Qt::Key_Escape );
|
||||
|
||||
setKeyPattern( KeyLeft, Qt::Key_Left );
|
||||
setKeyPattern( KeyRight, Qt::Key_Right );
|
||||
setKeyPattern( KeyUp, Qt::Key_Up );
|
||||
setKeyPattern( KeyDown, Qt::Key_Down );
|
||||
|
||||
setKeyPattern( KeyRedo, Qt::Key_Plus );
|
||||
setKeyPattern( KeyUndo, Qt::Key_Minus );
|
||||
setKeyPattern( KeyHome, Qt::Key_Escape );
|
||||
}
|
||||
|
||||
/*!
|
||||
Change one mouse pattern
|
||||
|
||||
\param pattern Index of the pattern
|
||||
\param button Button
|
||||
\param modifiers Keyboard modifiers
|
||||
|
||||
\sa QMouseEvent
|
||||
*/
|
||||
void QwtEventPattern::setMousePattern( MousePatternCode pattern,
|
||||
Qt::MouseButton button, Qt::KeyboardModifiers modifiers )
|
||||
{
|
||||
if ( pattern >= 0 && pattern < MousePatternCount )
|
||||
{
|
||||
d_mousePattern[ pattern ].button = button;
|
||||
d_mousePattern[ pattern ].modifiers = modifiers;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Change one key pattern
|
||||
|
||||
\param pattern Index of the pattern
|
||||
\param key Key
|
||||
\param modifiers Keyboard modifiers
|
||||
|
||||
\sa QKeyEvent
|
||||
*/
|
||||
void QwtEventPattern::setKeyPattern( KeyPatternCode pattern,
|
||||
int key, Qt::KeyboardModifiers modifiers )
|
||||
{
|
||||
if ( pattern >= 0 && pattern < KeyPatternCount )
|
||||
{
|
||||
d_keyPattern[ pattern ].key = key;
|
||||
d_keyPattern[ pattern ].modifiers = modifiers;
|
||||
}
|
||||
}
|
||||
|
||||
//! Change the mouse event patterns
|
||||
void QwtEventPattern::setMousePattern( const QVector<MousePattern> &pattern )
|
||||
{
|
||||
d_mousePattern = pattern;
|
||||
}
|
||||
|
||||
//! Change the key event patterns
|
||||
void QwtEventPattern::setKeyPattern( const QVector<KeyPattern> &pattern )
|
||||
{
|
||||
d_keyPattern = pattern;
|
||||
}
|
||||
|
||||
//! \return Mouse pattern
|
||||
const QVector<QwtEventPattern::MousePattern> &
|
||||
QwtEventPattern::mousePattern() const
|
||||
{
|
||||
return d_mousePattern;
|
||||
}
|
||||
|
||||
//! \return Key pattern
|
||||
const QVector<QwtEventPattern::KeyPattern> &
|
||||
QwtEventPattern::keyPattern() const
|
||||
{
|
||||
return d_keyPattern;
|
||||
}
|
||||
|
||||
//! \return Mouse pattern
|
||||
QVector<QwtEventPattern::MousePattern> &QwtEventPattern::mousePattern()
|
||||
{
|
||||
return d_mousePattern;
|
||||
}
|
||||
|
||||
//! \return Key pattern
|
||||
QVector<QwtEventPattern::KeyPattern> &QwtEventPattern::keyPattern()
|
||||
{
|
||||
return d_keyPattern;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Compare a mouse event with an event pattern.
|
||||
|
||||
A mouse event matches the pattern when both have the same button
|
||||
value and in the state value the same key flags(Qt::KeyButtonMask)
|
||||
are set.
|
||||
|
||||
\param code Index of the event pattern
|
||||
\param event Mouse event
|
||||
\return true if matches
|
||||
|
||||
\sa keyMatch()
|
||||
*/
|
||||
bool QwtEventPattern::mouseMatch( MousePatternCode code,
|
||||
const QMouseEvent *event ) const
|
||||
{
|
||||
if ( code >= 0 && code < MousePatternCount )
|
||||
return mouseMatch( d_mousePattern[ code ], event );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Compare a mouse event with an event pattern.
|
||||
|
||||
A mouse event matches the pattern when both have the same button
|
||||
value and in the state value the same key flags(Qt::KeyButtonMask)
|
||||
are set.
|
||||
|
||||
\param pattern Mouse event pattern
|
||||
\param event Mouse event
|
||||
\return true if matches
|
||||
|
||||
\sa keyMatch()
|
||||
*/
|
||||
|
||||
bool QwtEventPattern::mouseMatch( const MousePattern &pattern,
|
||||
const QMouseEvent *event ) const
|
||||
{
|
||||
if ( event == NULL )
|
||||
return false;
|
||||
|
||||
const MousePattern mousePattern( event->button(), event->modifiers() );
|
||||
return mousePattern == pattern;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Compare a key event with an event pattern.
|
||||
|
||||
A key event matches the pattern when both have the same key
|
||||
value and in the state value the same key flags (Qt::KeyButtonMask)
|
||||
are set.
|
||||
|
||||
\param code Index of the event pattern
|
||||
\param event Key event
|
||||
\return true if matches
|
||||
|
||||
\sa mouseMatch()
|
||||
*/
|
||||
bool QwtEventPattern::keyMatch( KeyPatternCode code,
|
||||
const QKeyEvent *event ) const
|
||||
{
|
||||
if ( code >= 0 && code < KeyPatternCount )
|
||||
return keyMatch( d_keyPattern[ code ], event );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Compare a key event with an event pattern.
|
||||
|
||||
A key event matches the pattern when both have the same key
|
||||
value and in the state value the same key flags (Qt::KeyButtonMask)
|
||||
are set.
|
||||
|
||||
\param pattern Key event pattern
|
||||
\param event Key event
|
||||
\return true if matches
|
||||
|
||||
\sa mouseMatch()
|
||||
*/
|
||||
|
||||
bool QwtEventPattern::keyMatch(
|
||||
const KeyPattern &pattern, const QKeyEvent *event ) const
|
||||
{
|
||||
if ( event == NULL )
|
||||
return false;
|
||||
|
||||
const KeyPattern keyPattern( event->key(), event->modifiers() );
|
||||
return keyPattern == pattern;
|
||||
}
|
||||
240
third/3rd_qwt/qwt_event_pattern.h
Normal file
240
third/3rd_qwt/qwt_event_pattern.h
Normal file
@@ -0,0 +1,240 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_EVENT_PATTERN
|
||||
#define QWT_EVENT_PATTERN 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qnamespace.h>
|
||||
#include <qvector.h>
|
||||
|
||||
class QMouseEvent;
|
||||
class QKeyEvent;
|
||||
|
||||
/*!
|
||||
\brief A collection of event patterns
|
||||
|
||||
QwtEventPattern introduces an level of indirection for mouse and
|
||||
keyboard inputs. Those are represented by symbolic names, so
|
||||
the application code can be configured by individual mappings.
|
||||
|
||||
\sa QwtPicker, QwtPickerMachine, QwtPlotZoomer
|
||||
*/
|
||||
class QWT_EXPORT QwtEventPattern
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
\brief Symbolic mouse input codes
|
||||
|
||||
QwtEventPattern implements 3 different settings for
|
||||
mice with 1, 2, or 3 buttons that can be activated
|
||||
using initMousePattern(). The default setting is for
|
||||
3 button mice.
|
||||
|
||||
Individual settings can be configured using setMousePattern().
|
||||
|
||||
\sa initMousePattern(), setMousePattern(), setKeyPattern()
|
||||
*/
|
||||
enum MousePatternCode
|
||||
{
|
||||
/*!
|
||||
The default setting for 1, 2 and 3 button mice is:
|
||||
|
||||
- Qt::LeftButton
|
||||
- Qt::LeftButton
|
||||
- Qt::LeftButton
|
||||
*/
|
||||
MouseSelect1,
|
||||
|
||||
/*!
|
||||
The default setting for 1, 2 and 3 button mice is:
|
||||
|
||||
- Qt::LeftButton + Qt::ControlModifier
|
||||
- Qt::RightButton
|
||||
- Qt::RightButton
|
||||
*/
|
||||
MouseSelect2,
|
||||
|
||||
/*!
|
||||
The default setting for 1, 2 and 3 button mice is:
|
||||
|
||||
- Qt::LeftButton + Qt::AltModifier
|
||||
- Qt::LeftButton + Qt::AltModifier
|
||||
- Qt::MidButton
|
||||
*/
|
||||
MouseSelect3,
|
||||
|
||||
/*!
|
||||
The default setting for 1, 2 and 3 button mice is:
|
||||
|
||||
- Qt::LeftButton + Qt::ShiftModifier
|
||||
- Qt::LeftButton + Qt::ShiftModifier
|
||||
- Qt::LeftButton + Qt::ShiftModifier
|
||||
*/
|
||||
MouseSelect4,
|
||||
|
||||
/*!
|
||||
The default setting for 1, 2 and 3 button mice is:
|
||||
|
||||
- Qt::LeftButton + Qt::ControlButton | Qt::ShiftModifier
|
||||
- Qt::RightButton + Qt::ShiftModifier
|
||||
- Qt::RightButton + Qt::ShiftModifier
|
||||
*/
|
||||
MouseSelect5,
|
||||
|
||||
/*!
|
||||
The default setting for 1, 2 and 3 button mice is:
|
||||
|
||||
- Qt::LeftButton + Qt::AltModifier + Qt::ShiftModifier
|
||||
- Qt::LeftButton + Qt::AltModifier | Qt::ShiftModifier
|
||||
- Qt::MidButton + Qt::ShiftModifier
|
||||
*/
|
||||
MouseSelect6,
|
||||
|
||||
//! Number of mouse patterns
|
||||
MousePatternCount
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Symbolic keyboard input codes
|
||||
|
||||
Individual settings can be configured using setKeyPattern()
|
||||
|
||||
\sa setKeyPattern(), setMousePattern()
|
||||
*/
|
||||
enum KeyPatternCode
|
||||
{
|
||||
//! Qt::Key_Return
|
||||
KeySelect1,
|
||||
|
||||
//! Qt::Key_Space
|
||||
KeySelect2,
|
||||
|
||||
//! Qt::Key_Escape
|
||||
KeyAbort,
|
||||
|
||||
//! Qt::Key_Left
|
||||
KeyLeft,
|
||||
|
||||
//! Qt::Key_Right
|
||||
KeyRight,
|
||||
|
||||
//! Qt::Key_Up
|
||||
KeyUp,
|
||||
|
||||
//! Qt::Key_Down
|
||||
KeyDown,
|
||||
|
||||
//! Qt::Key_Plus
|
||||
KeyRedo,
|
||||
|
||||
//! Qt::Key_Minus
|
||||
KeyUndo,
|
||||
|
||||
//! Qt::Key_Escape
|
||||
KeyHome,
|
||||
|
||||
//! Number of key patterns
|
||||
KeyPatternCount
|
||||
};
|
||||
|
||||
//! A pattern for mouse events
|
||||
class MousePattern
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
MousePattern( Qt::MouseButton btn = Qt::NoButton,
|
||||
Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ):
|
||||
button( btn ),
|
||||
modifiers( modifierCodes )
|
||||
{
|
||||
}
|
||||
|
||||
//! Button
|
||||
Qt::MouseButton button;
|
||||
|
||||
//! Keyboard modifier
|
||||
Qt::KeyboardModifiers modifiers;
|
||||
};
|
||||
|
||||
//! A pattern for key events
|
||||
class KeyPattern
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
KeyPattern( int keyCode = Qt::Key_unknown,
|
||||
Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ):
|
||||
key( keyCode ),
|
||||
modifiers( modifierCodes )
|
||||
{
|
||||
}
|
||||
|
||||
//! Key code
|
||||
int key;
|
||||
|
||||
//! Modifiers
|
||||
Qt::KeyboardModifiers modifiers;
|
||||
};
|
||||
|
||||
QwtEventPattern();
|
||||
virtual ~QwtEventPattern();
|
||||
|
||||
void initMousePattern( int numButtons );
|
||||
void initKeyPattern();
|
||||
|
||||
void setMousePattern( MousePatternCode, Qt::MouseButton button,
|
||||
Qt::KeyboardModifiers = Qt::NoModifier );
|
||||
|
||||
void setKeyPattern( KeyPatternCode, int key,
|
||||
Qt::KeyboardModifiers modifiers = Qt::NoModifier );
|
||||
|
||||
void setMousePattern( const QVector<MousePattern> & );
|
||||
void setKeyPattern( const QVector<KeyPattern> & );
|
||||
|
||||
const QVector<MousePattern> &mousePattern() const;
|
||||
const QVector<KeyPattern> &keyPattern() const;
|
||||
|
||||
QVector<MousePattern> &mousePattern();
|
||||
QVector<KeyPattern> &keyPattern();
|
||||
|
||||
bool mouseMatch( MousePatternCode, const QMouseEvent * ) const;
|
||||
bool keyMatch( KeyPatternCode, const QKeyEvent * ) const;
|
||||
|
||||
protected:
|
||||
virtual bool mouseMatch( const MousePattern &, const QMouseEvent * ) const;
|
||||
virtual bool keyMatch( const KeyPattern &, const QKeyEvent * ) const;
|
||||
|
||||
private:
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4251)
|
||||
#endif
|
||||
QVector<MousePattern> d_mousePattern;
|
||||
QVector<KeyPattern> d_keyPattern;
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
};
|
||||
|
||||
//! Compare operator
|
||||
inline bool operator==( QwtEventPattern::MousePattern b1,
|
||||
QwtEventPattern::MousePattern b2 )
|
||||
{
|
||||
return b1.button == b2.button && b1.modifiers == b2.modifiers;
|
||||
}
|
||||
|
||||
//! Compare operator
|
||||
inline bool operator==( QwtEventPattern::KeyPattern b1,
|
||||
QwtEventPattern::KeyPattern b2 )
|
||||
{
|
||||
return b1.key == b2.key && b1.modifiers == b2.modifiers;
|
||||
}
|
||||
|
||||
#endif
|
||||
41
third/3rd_qwt/qwt_global.h
Normal file
41
third/3rd_qwt/qwt_global.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_GLOBAL_H
|
||||
#define QWT_GLOBAL_H
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
// QWT_VERSION is (major << 16) + (minor << 8) + patch.
|
||||
|
||||
#define QWT_VERSION 0x060104
|
||||
#define QWT_VERSION_STR "6.1.4"
|
||||
|
||||
#if defined(_MSC_VER) /* MSVC Compiler */
|
||||
/* template-class specialization 'identifier' is already instantiated */
|
||||
#pragma warning(disable: 4660)
|
||||
/* inherits via dominance */
|
||||
#pragma warning(disable: 4250)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifdef QWT_DLL
|
||||
|
||||
#if defined(QWT_MAKEDLL) // create a Qwt DLL library
|
||||
#define QWT_EXPORT Q_DECL_EXPORT
|
||||
#else // use a Qwt DLL library
|
||||
#define QWT_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // QWT_DLL
|
||||
|
||||
#ifndef QWT_EXPORT
|
||||
#define QWT_EXPORT
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1009
third/3rd_qwt/qwt_graphic.cpp
Normal file
1009
third/3rd_qwt/qwt_graphic.cpp
Normal file
File diff suppressed because it is too large
Load Diff
176
third/3rd_qwt/qwt_graphic.h
Normal file
176
third/3rd_qwt/qwt_graphic.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_GRAPHIC_H
|
||||
#define QWT_GRAPHIC_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_null_paintdevice.h"
|
||||
#include <qmetatype.h>
|
||||
#include <qimage.h>
|
||||
#include <qpixmap.h>
|
||||
|
||||
class QwtPainterCommand;
|
||||
|
||||
/*!
|
||||
\brief A paint device for scalable graphics
|
||||
|
||||
QwtGraphic is the representation of a graphic that is tailored for
|
||||
scalability. Like QPicture it will be initialized by QPainter
|
||||
operations and can be replayed later to any target paint device.
|
||||
|
||||
While the usual image representations QImage and QPixmap are not
|
||||
scalable Qt offers two paint devices, that might be candidates
|
||||
for representing a vector graphic:
|
||||
|
||||
- QPicture\n
|
||||
Unfortunately QPicture had been forgotten, when Qt4
|
||||
introduced floating point based render engines. Its API
|
||||
is still on integers, what make it unusable for proper scaling.
|
||||
|
||||
- QSvgRenderer/QSvgGenerator\n
|
||||
Unfortunately QSvgRenderer hides to much information about
|
||||
its nodes in internal APIs, that are necessary for proper
|
||||
layout calculations. Also it is derived from QObject and
|
||||
can't be copied like QImage/QPixmap.
|
||||
|
||||
QwtGraphic maps all scalable drawing primitives to a QPainterPath
|
||||
and stores them together with the painter state changes
|
||||
( pen, brush, transformation ... ) in a list of QwtPaintCommands.
|
||||
For being a complete QPaintDevice it also stores pixmaps or images,
|
||||
what is somehow against the idea of the class, because these objects
|
||||
can't be scaled without a loss in quality.
|
||||
|
||||
The main issue about scaling a QwtGraphic object are the pens used for
|
||||
drawing the outlines of the painter paths. While non cosmetic pens
|
||||
( QPen::isCosmetic() ) are scaled with the same ratio as the path,
|
||||
cosmetic pens have a fixed width. A graphic might have paths with
|
||||
different pens - cosmetic and non-cosmetic.
|
||||
|
||||
QwtGraphic caches 2 different rectangles:
|
||||
|
||||
- control point rectangle\n
|
||||
The control point rectangle is the bounding rectangle of all
|
||||
control point rectangles of the painter paths, or the target
|
||||
rectangle of the pixmaps/images.
|
||||
|
||||
- bounding rectangle\n
|
||||
The bounding rectangle extends the control point rectangle by
|
||||
what is needed for rendering the outline with an unscaled pen.
|
||||
|
||||
Because the offset for drawing the outline depends on the shape
|
||||
of the painter path ( the peak of a triangle is different than the flat side )
|
||||
scaling with a fixed aspect ratio always needs to be calculated from the
|
||||
control point rectangle.
|
||||
|
||||
\sa QwtPainterCommand
|
||||
*/
|
||||
class QWT_EXPORT QwtGraphic: public QwtNullPaintDevice
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
Hint how to render a graphic
|
||||
\sa setRenderHint(), testRenderHint()
|
||||
*/
|
||||
enum RenderHint
|
||||
{
|
||||
/*!
|
||||
When rendering a QwtGraphic a specific scaling between
|
||||
the controlPointRect() and the coordinates of the target rectangle
|
||||
is set up internally in render().
|
||||
|
||||
When RenderPensUnscaled is set this specific scaling is applied
|
||||
for the control points only, but not for the pens.
|
||||
All other painter transformations ( set up by application code )
|
||||
are supposed to work like usual.
|
||||
|
||||
\sa render();
|
||||
*/
|
||||
RenderPensUnscaled = 0x1
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Render hints
|
||||
|
||||
The default setting is to disable all hints
|
||||
*/
|
||||
typedef QFlags<RenderHint> RenderHints;
|
||||
|
||||
QwtGraphic();
|
||||
QwtGraphic( const QwtGraphic & );
|
||||
|
||||
virtual ~QwtGraphic();
|
||||
|
||||
QwtGraphic& operator=( const QwtGraphic & );
|
||||
|
||||
void reset();
|
||||
|
||||
bool isNull() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
void render( QPainter * ) const;
|
||||
|
||||
void render( QPainter *, const QSizeF &,
|
||||
Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const;
|
||||
|
||||
void render( QPainter *, const QRectF &,
|
||||
Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const;
|
||||
|
||||
void render( QPainter *, const QPointF &,
|
||||
Qt::Alignment = Qt::AlignTop | Qt::AlignLeft ) const;
|
||||
|
||||
QPixmap toPixmap() const;
|
||||
QPixmap toPixmap( const QSize &,
|
||||
Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const;
|
||||
|
||||
QImage toImage() const;
|
||||
QImage toImage( const QSize &,
|
||||
Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const;
|
||||
|
||||
QRectF scaledBoundingRect( double sx, double sy ) const;
|
||||
|
||||
QRectF boundingRect() const;
|
||||
QRectF controlPointRect() const;
|
||||
|
||||
const QVector< QwtPainterCommand > &commands() const;
|
||||
void setCommands( QVector< QwtPainterCommand > & );
|
||||
|
||||
void setDefaultSize( const QSizeF & );
|
||||
QSizeF defaultSize() const;
|
||||
|
||||
void setRenderHint( RenderHint, bool on = true );
|
||||
bool testRenderHint( RenderHint ) const;
|
||||
|
||||
protected:
|
||||
virtual QSize sizeMetrics() const;
|
||||
|
||||
virtual void drawPath( const QPainterPath & );
|
||||
|
||||
virtual void drawPixmap( const QRectF &,
|
||||
const QPixmap &, const QRectF & );
|
||||
|
||||
virtual void drawImage( const QRectF &,
|
||||
const QImage &, const QRectF &, Qt::ImageConversionFlags );
|
||||
|
||||
virtual void updateState( const QPaintEngineState &state );
|
||||
|
||||
private:
|
||||
void updateBoundingRect( const QRectF & );
|
||||
void updateControlPointRect( const QRectF & );
|
||||
|
||||
class PathInfo;
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QwtGraphic::RenderHints )
|
||||
Q_DECLARE_METATYPE( QwtGraphic )
|
||||
|
||||
#endif
|
||||
354
third/3rd_qwt/qwt_interval.cpp
Normal file
354
third/3rd_qwt/qwt_interval.cpp
Normal file
@@ -0,0 +1,354 @@
|
||||
/* -*- 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_interval.h"
|
||||
#include "qwt_math.h"
|
||||
#include <qalgorithms.h>
|
||||
|
||||
/*!
|
||||
\brief Normalize the limits of the interval
|
||||
|
||||
If maxValue() < minValue() the limits will be inverted.
|
||||
\return Normalized interval
|
||||
|
||||
\sa isValid(), inverted()
|
||||
*/
|
||||
QwtInterval QwtInterval::normalized() const
|
||||
{
|
||||
if ( d_minValue > d_maxValue )
|
||||
{
|
||||
return inverted();
|
||||
}
|
||||
if ( d_minValue == d_maxValue && d_borderFlags == ExcludeMinimum )
|
||||
{
|
||||
return inverted();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
Invert the limits of the interval
|
||||
\return Inverted interval
|
||||
\sa normalized()
|
||||
*/
|
||||
QwtInterval QwtInterval::inverted() const
|
||||
{
|
||||
BorderFlags borderFlags = IncludeBorders;
|
||||
if ( d_borderFlags & ExcludeMinimum )
|
||||
borderFlags |= ExcludeMaximum;
|
||||
if ( d_borderFlags & ExcludeMaximum )
|
||||
borderFlags |= ExcludeMinimum;
|
||||
|
||||
return QwtInterval( d_maxValue, d_minValue, borderFlags );
|
||||
}
|
||||
|
||||
/*!
|
||||
Test if a value is inside an interval
|
||||
|
||||
\param value Value
|
||||
\return true, if value >= minValue() && value <= maxValue()
|
||||
*/
|
||||
bool QwtInterval::contains( double value ) const
|
||||
{
|
||||
if ( !isValid() )
|
||||
return false;
|
||||
|
||||
if ( value < d_minValue || value > d_maxValue )
|
||||
return false;
|
||||
|
||||
if ( value == d_minValue && d_borderFlags & ExcludeMinimum )
|
||||
return false;
|
||||
|
||||
if ( value == d_maxValue && d_borderFlags & ExcludeMaximum )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Unite 2 intervals
|
||||
QwtInterval QwtInterval::unite( const QwtInterval &other ) const
|
||||
{
|
||||
/*
|
||||
If one of the intervals is invalid return the other one.
|
||||
If both are invalid return an invalid default interval
|
||||
*/
|
||||
if ( !isValid() )
|
||||
{
|
||||
if ( !other.isValid() )
|
||||
return QwtInterval();
|
||||
else
|
||||
return other;
|
||||
}
|
||||
if ( !other.isValid() )
|
||||
return *this;
|
||||
|
||||
QwtInterval united;
|
||||
BorderFlags flags = IncludeBorders;
|
||||
|
||||
// minimum
|
||||
if ( d_minValue < other.minValue() )
|
||||
{
|
||||
united.setMinValue( d_minValue );
|
||||
flags &= d_borderFlags & ExcludeMinimum;
|
||||
}
|
||||
else if ( other.minValue() < d_minValue )
|
||||
{
|
||||
united.setMinValue( other.minValue() );
|
||||
flags &= other.borderFlags() & ExcludeMinimum;
|
||||
}
|
||||
else // d_minValue == other.minValue()
|
||||
{
|
||||
united.setMinValue( d_minValue );
|
||||
flags &= ( d_borderFlags & other.borderFlags() ) & ExcludeMinimum;
|
||||
}
|
||||
|
||||
// maximum
|
||||
if ( d_maxValue > other.maxValue() )
|
||||
{
|
||||
united.setMaxValue( d_maxValue );
|
||||
flags &= d_borderFlags & ExcludeMaximum;
|
||||
}
|
||||
else if ( other.maxValue() > d_maxValue )
|
||||
{
|
||||
united.setMaxValue( other.maxValue() );
|
||||
flags &= other.borderFlags() & ExcludeMaximum;
|
||||
}
|
||||
else // d_maxValue == other.maxValue() )
|
||||
{
|
||||
united.setMaxValue( d_maxValue );
|
||||
flags &= d_borderFlags & other.borderFlags() & ExcludeMaximum;
|
||||
}
|
||||
|
||||
united.setBorderFlags( flags );
|
||||
return united;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Intersect 2 intervals
|
||||
|
||||
\param other Interval to be intersect with
|
||||
\return Intersection
|
||||
*/
|
||||
QwtInterval QwtInterval::intersect( const QwtInterval &other ) const
|
||||
{
|
||||
if ( !other.isValid() || !isValid() )
|
||||
return QwtInterval();
|
||||
|
||||
QwtInterval i1 = *this;
|
||||
QwtInterval i2 = other;
|
||||
|
||||
// swap i1/i2, so that the minimum of i1
|
||||
// is smaller then the minimum of i2
|
||||
|
||||
if ( i1.minValue() > i2.minValue() )
|
||||
{
|
||||
qSwap( i1, i2 );
|
||||
}
|
||||
else if ( i1.minValue() == i2.minValue() )
|
||||
{
|
||||
if ( i1.borderFlags() & ExcludeMinimum )
|
||||
qSwap( i1, i2 );
|
||||
}
|
||||
|
||||
if ( i1.maxValue() < i2.minValue() )
|
||||
{
|
||||
return QwtInterval();
|
||||
}
|
||||
|
||||
if ( i1.maxValue() == i2.minValue() )
|
||||
{
|
||||
if ( i1.borderFlags() & ExcludeMaximum ||
|
||||
i2.borderFlags() & ExcludeMinimum )
|
||||
{
|
||||
return QwtInterval();
|
||||
}
|
||||
}
|
||||
|
||||
QwtInterval intersected;
|
||||
BorderFlags flags = IncludeBorders;
|
||||
|
||||
intersected.setMinValue( i2.minValue() );
|
||||
flags |= i2.borderFlags() & ExcludeMinimum;
|
||||
|
||||
if ( i1.maxValue() < i2.maxValue() )
|
||||
{
|
||||
intersected.setMaxValue( i1.maxValue() );
|
||||
flags |= i1.borderFlags() & ExcludeMaximum;
|
||||
}
|
||||
else if ( i2.maxValue() < i1.maxValue() )
|
||||
{
|
||||
intersected.setMaxValue( i2.maxValue() );
|
||||
flags |= i2.borderFlags() & ExcludeMaximum;
|
||||
}
|
||||
else // i1.maxValue() == i2.maxValue()
|
||||
{
|
||||
intersected.setMaxValue( i1.maxValue() );
|
||||
flags |= i1.borderFlags() & i2.borderFlags() & ExcludeMaximum;
|
||||
}
|
||||
|
||||
intersected.setBorderFlags( flags );
|
||||
return intersected;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Unite this interval with the given interval.
|
||||
|
||||
\param other Interval to be united with
|
||||
\return This interval
|
||||
*/
|
||||
QwtInterval& QwtInterval::operator|=( const QwtInterval &other )
|
||||
{
|
||||
*this = *this | other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Intersect this interval with the given interval.
|
||||
|
||||
\param other Interval to be intersected with
|
||||
\return This interval
|
||||
*/
|
||||
QwtInterval& QwtInterval::operator&=( const QwtInterval &other )
|
||||
{
|
||||
*this = *this & other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Test if two intervals overlap
|
||||
|
||||
\param other Interval
|
||||
\return True, when the intervals are intersecting
|
||||
*/
|
||||
bool QwtInterval::intersects( const QwtInterval &other ) const
|
||||
{
|
||||
if ( !isValid() || !other.isValid() )
|
||||
return false;
|
||||
|
||||
QwtInterval i1 = *this;
|
||||
QwtInterval i2 = other;
|
||||
|
||||
// swap i1/i2, so that the minimum of i1
|
||||
// is smaller then the minimum of i2
|
||||
|
||||
if ( i1.minValue() > i2.minValue() )
|
||||
{
|
||||
qSwap( i1, i2 );
|
||||
}
|
||||
else if ( i1.minValue() == i2.minValue() &&
|
||||
i1.borderFlags() & ExcludeMinimum )
|
||||
{
|
||||
qSwap( i1, i2 );
|
||||
}
|
||||
|
||||
if ( i1.maxValue() > i2.minValue() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ( i1.maxValue() == i2.minValue() )
|
||||
{
|
||||
return !( ( i1.borderFlags() & ExcludeMaximum ) ||
|
||||
( i2.borderFlags() & ExcludeMinimum ) );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Adjust the limit that is closer to value, so that value becomes
|
||||
the center of the interval.
|
||||
|
||||
\param value Center
|
||||
\return Interval with value as center
|
||||
*/
|
||||
QwtInterval QwtInterval::symmetrize( double value ) const
|
||||
{
|
||||
if ( !isValid() )
|
||||
return *this;
|
||||
|
||||
const double delta =
|
||||
qMax( qAbs( value - d_maxValue ), qAbs( value - d_minValue ) );
|
||||
|
||||
return QwtInterval( value - delta, value + delta );
|
||||
}
|
||||
|
||||
/*!
|
||||
Limit the interval, keeping the border modes
|
||||
|
||||
\param lowerBound Lower limit
|
||||
\param upperBound Upper limit
|
||||
|
||||
\return Limited interval
|
||||
*/
|
||||
QwtInterval QwtInterval::limited( double lowerBound, double upperBound ) const
|
||||
{
|
||||
if ( !isValid() || lowerBound > upperBound )
|
||||
return QwtInterval();
|
||||
|
||||
double minValue = qMax( d_minValue, lowerBound );
|
||||
minValue = qMin( minValue, upperBound );
|
||||
|
||||
double maxValue = qMax( d_maxValue, lowerBound );
|
||||
maxValue = qMin( maxValue, upperBound );
|
||||
|
||||
return QwtInterval( minValue, maxValue, d_borderFlags );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Extend the interval
|
||||
|
||||
If value is below minValue(), value becomes the lower limit.
|
||||
If value is above maxValue(), value becomes the upper limit.
|
||||
|
||||
extend() has no effect for invalid intervals
|
||||
|
||||
\param value Value
|
||||
\return extended interval
|
||||
|
||||
\sa isValid()
|
||||
*/
|
||||
QwtInterval QwtInterval::extend( double value ) const
|
||||
{
|
||||
if ( !isValid() )
|
||||
return *this;
|
||||
|
||||
return QwtInterval( qMin( value, d_minValue ),
|
||||
qMax( value, d_maxValue ), d_borderFlags );
|
||||
}
|
||||
|
||||
/*!
|
||||
Extend an interval
|
||||
|
||||
\param value Value
|
||||
\return Reference of the extended interval
|
||||
|
||||
\sa extend()
|
||||
*/
|
||||
QwtInterval& QwtInterval::operator|=( double value )
|
||||
{
|
||||
*this = *this | value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
QDebug operator<<( QDebug debug, const QwtInterval &interval )
|
||||
{
|
||||
const int flags = interval.borderFlags();
|
||||
|
||||
debug.nospace() << "QwtInterval("
|
||||
<< ( ( flags & QwtInterval::ExcludeMinimum ) ? "]" : "[" )
|
||||
<< interval.minValue() << "," << interval.maxValue()
|
||||
<< ( ( flags & QwtInterval::ExcludeMaximum ) ? "[" : "]" )
|
||||
<< ")";
|
||||
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
#endif
|
||||
320
third/3rd_qwt/qwt_interval.h
Normal file
320
third/3rd_qwt/qwt_interval.h
Normal file
@@ -0,0 +1,320 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_INTERVAL_H
|
||||
#define QWT_INTERVAL_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qmetatype.h>
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
#include <qdebug.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief A class representing an interval
|
||||
|
||||
The interval is represented by 2 doubles, the lower and the upper limit.
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtInterval
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
Flag indicating if a border is included or excluded
|
||||
\sa setBorderFlags(), borderFlags()
|
||||
*/
|
||||
enum BorderFlag
|
||||
{
|
||||
//! Min/Max values are inside the interval
|
||||
IncludeBorders = 0x00,
|
||||
|
||||
//! Min value is not included in the interval
|
||||
ExcludeMinimum = 0x01,
|
||||
|
||||
//! Max value is not included in the interval
|
||||
ExcludeMaximum = 0x02,
|
||||
|
||||
//! Min/Max values are not included in the interval
|
||||
ExcludeBorders = ExcludeMinimum | ExcludeMaximum
|
||||
};
|
||||
|
||||
//! Border flags
|
||||
typedef QFlags<BorderFlag> BorderFlags;
|
||||
|
||||
QwtInterval();
|
||||
QwtInterval( double minValue, double maxValue,
|
||||
BorderFlags = IncludeBorders );
|
||||
|
||||
void setInterval( double minValue, double maxValue,
|
||||
BorderFlags = IncludeBorders );
|
||||
|
||||
QwtInterval normalized() const;
|
||||
QwtInterval inverted() const;
|
||||
QwtInterval limited( double lowerBound, double upperBound ) const;
|
||||
|
||||
bool operator==( const QwtInterval & ) const;
|
||||
bool operator!=( const QwtInterval & ) const;
|
||||
|
||||
void setBorderFlags( BorderFlags );
|
||||
BorderFlags borderFlags() const;
|
||||
|
||||
double minValue() const;
|
||||
double maxValue() const;
|
||||
|
||||
double width() const;
|
||||
|
||||
void setMinValue( double );
|
||||
void setMaxValue( double );
|
||||
|
||||
bool contains( double value ) const;
|
||||
|
||||
bool intersects( const QwtInterval & ) const;
|
||||
QwtInterval intersect( const QwtInterval & ) const;
|
||||
QwtInterval unite( const QwtInterval & ) const;
|
||||
|
||||
QwtInterval operator|( const QwtInterval & ) const;
|
||||
QwtInterval operator&( const QwtInterval & ) const;
|
||||
|
||||
QwtInterval &operator|=( const QwtInterval & );
|
||||
QwtInterval &operator&=( const QwtInterval & );
|
||||
|
||||
QwtInterval extend( double value ) const;
|
||||
QwtInterval operator|( double ) const;
|
||||
QwtInterval &operator|=( double );
|
||||
|
||||
bool isValid() const;
|
||||
bool isNull() const;
|
||||
void invalidate();
|
||||
|
||||
QwtInterval symmetrize( double value ) const;
|
||||
|
||||
private:
|
||||
double d_minValue;
|
||||
double d_maxValue;
|
||||
BorderFlags d_borderFlags;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QwtInterval, Q_MOVABLE_TYPE);
|
||||
|
||||
/*!
|
||||
\brief Default Constructor
|
||||
|
||||
Creates an invalid interval [0.0, -1.0]
|
||||
\sa setInterval(), isValid()
|
||||
*/
|
||||
inline QwtInterval::QwtInterval():
|
||||
d_minValue( 0.0 ),
|
||||
d_maxValue( -1.0 ),
|
||||
d_borderFlags( IncludeBorders )
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
Build an interval with from min/max values
|
||||
|
||||
\param minValue Minimum value
|
||||
\param maxValue Maximum value
|
||||
\param borderFlags Include/Exclude borders
|
||||
*/
|
||||
inline QwtInterval::QwtInterval(
|
||||
double minValue, double maxValue, BorderFlags borderFlags ):
|
||||
d_minValue( minValue ),
|
||||
d_maxValue( maxValue ),
|
||||
d_borderFlags( borderFlags )
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign the limits of the interval
|
||||
|
||||
\param minValue Minimum value
|
||||
\param maxValue Maximum value
|
||||
\param borderFlags Include/Exclude borders
|
||||
*/
|
||||
inline void QwtInterval::setInterval(
|
||||
double minValue, double maxValue, BorderFlags borderFlags )
|
||||
{
|
||||
d_minValue = minValue;
|
||||
d_maxValue = maxValue;
|
||||
d_borderFlags = borderFlags;
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the border flags
|
||||
|
||||
\param borderFlags Or'd BorderMode flags
|
||||
\sa borderFlags()
|
||||
*/
|
||||
inline void QwtInterval::setBorderFlags( BorderFlags borderFlags )
|
||||
{
|
||||
d_borderFlags = borderFlags;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Border flags
|
||||
\sa setBorderFlags()
|
||||
*/
|
||||
inline QwtInterval::BorderFlags QwtInterval::borderFlags() const
|
||||
{
|
||||
return d_borderFlags;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign the lower limit of the interval
|
||||
|
||||
\param minValue Minimum value
|
||||
*/
|
||||
inline void QwtInterval::setMinValue( double minValue )
|
||||
{
|
||||
d_minValue = minValue;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign the upper limit of the interval
|
||||
|
||||
\param maxValue Maximum value
|
||||
*/
|
||||
inline void QwtInterval::setMaxValue( double maxValue )
|
||||
{
|
||||
d_maxValue = maxValue;
|
||||
}
|
||||
|
||||
//! \return Lower limit of the interval
|
||||
inline double QwtInterval::minValue() const
|
||||
{
|
||||
return d_minValue;
|
||||
}
|
||||
|
||||
//! \return Upper limit of the interval
|
||||
inline double QwtInterval::maxValue() const
|
||||
{
|
||||
return d_maxValue;
|
||||
}
|
||||
|
||||
/*!
|
||||
A interval is valid when minValue() <= maxValue().
|
||||
In case of QwtInterval::ExcludeBorders it is true
|
||||
when minValue() < maxValue()
|
||||
|
||||
\return True, when the interval is valid
|
||||
*/
|
||||
inline bool QwtInterval::isValid() const
|
||||
{
|
||||
if ( ( d_borderFlags & ExcludeBorders ) == 0 )
|
||||
return d_minValue <= d_maxValue;
|
||||
else
|
||||
return d_minValue < d_maxValue;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Return the width of an interval
|
||||
|
||||
The width of invalid intervals is 0.0, otherwise the result is
|
||||
maxValue() - minValue().
|
||||
|
||||
\return Interval width
|
||||
\sa isValid()
|
||||
*/
|
||||
inline double QwtInterval::width() const
|
||||
{
|
||||
return isValid() ? ( d_maxValue - d_minValue ) : 0.0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Intersection of two intervals
|
||||
|
||||
\param other Interval to intersect with
|
||||
\return Intersection of this and other
|
||||
|
||||
\sa intersect()
|
||||
*/
|
||||
inline QwtInterval QwtInterval::operator&(
|
||||
const QwtInterval &other ) const
|
||||
{
|
||||
return intersect( other );
|
||||
}
|
||||
|
||||
/*!
|
||||
Union of two intervals
|
||||
|
||||
\param other Interval to unite with
|
||||
\return Union of this and other
|
||||
|
||||
\sa unite()
|
||||
*/
|
||||
inline QwtInterval QwtInterval::operator|(
|
||||
const QwtInterval &other ) const
|
||||
{
|
||||
return unite( other );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Compare two intervals
|
||||
|
||||
\param other Interval to compare with
|
||||
\return True, when this and other are equal
|
||||
*/
|
||||
inline bool QwtInterval::operator==( const QwtInterval &other ) const
|
||||
{
|
||||
return ( d_minValue == other.d_minValue ) &&
|
||||
( d_maxValue == other.d_maxValue ) &&
|
||||
( d_borderFlags == other.d_borderFlags );
|
||||
}
|
||||
/*!
|
||||
\brief Compare two intervals
|
||||
|
||||
\param other Interval to compare with
|
||||
\return True, when this and other are not equal
|
||||
*/
|
||||
inline bool QwtInterval::operator!=( const QwtInterval &other ) const
|
||||
{
|
||||
return ( !( *this == other ) );
|
||||
}
|
||||
|
||||
/*!
|
||||
Extend an interval
|
||||
|
||||
\param value Value
|
||||
\return Extended interval
|
||||
\sa extend()
|
||||
*/
|
||||
inline QwtInterval QwtInterval::operator|( double value ) const
|
||||
{
|
||||
return extend( value );
|
||||
}
|
||||
|
||||
//! \return true, if isValid() && (minValue() >= maxValue())
|
||||
inline bool QwtInterval::isNull() const
|
||||
{
|
||||
return isValid() && d_minValue >= d_maxValue;
|
||||
}
|
||||
|
||||
/*!
|
||||
Invalidate the interval
|
||||
|
||||
The limits are set to interval [0.0, -1.0]
|
||||
\sa isValid()
|
||||
*/
|
||||
inline void QwtInterval::invalidate()
|
||||
{
|
||||
d_minValue = 0.0;
|
||||
d_maxValue = -1.0;
|
||||
}
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QwtInterval::BorderFlags )
|
||||
Q_DECLARE_METATYPE( QwtInterval )
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
QWT_EXPORT QDebug operator<<( QDebug, const QwtInterval & );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
319
third/3rd_qwt/qwt_interval_symbol.cpp
Normal file
319
third/3rd_qwt/qwt_interval_symbol.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
/* -*- 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_interval_symbol.h"
|
||||
#include "qwt_painter.h"
|
||||
#include "qwt_math.h"
|
||||
#include <qpainter.h>
|
||||
|
||||
#if QT_VERSION < 0x040601
|
||||
#define qAtan2(y, x) ::atan2(y, x)
|
||||
#define qFastSin(x) qSin(x)
|
||||
#define qFastCos(x) qCos(x)
|
||||
#endif
|
||||
|
||||
class QwtIntervalSymbol::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
style( QwtIntervalSymbol::NoSymbol ),
|
||||
width( 6 )
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==( const PrivateData &other ) const
|
||||
{
|
||||
return ( style == other.style )
|
||||
&& ( width == other.width )
|
||||
&& ( brush == other.brush )
|
||||
&& ( pen == other.pen );
|
||||
}
|
||||
|
||||
QwtIntervalSymbol::Style style;
|
||||
int width;
|
||||
|
||||
QPen pen;
|
||||
QBrush brush;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
|
||||
\param style Style of the symbol
|
||||
\sa setStyle(), style(), Style
|
||||
*/
|
||||
QwtIntervalSymbol::QwtIntervalSymbol( Style style )
|
||||
{
|
||||
d_data = new PrivateData();
|
||||
d_data->style = style;
|
||||
}
|
||||
|
||||
//! Copy constructor
|
||||
QwtIntervalSymbol::QwtIntervalSymbol( const QwtIntervalSymbol &other )
|
||||
{
|
||||
d_data = new PrivateData();
|
||||
*d_data = *other.d_data;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtIntervalSymbol::~QwtIntervalSymbol()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
//! \brief Assignment operator
|
||||
QwtIntervalSymbol &QwtIntervalSymbol::operator=(
|
||||
const QwtIntervalSymbol &other )
|
||||
{
|
||||
*d_data = *other.d_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \brief Compare two symbols
|
||||
bool QwtIntervalSymbol::operator==(
|
||||
const QwtIntervalSymbol &other ) const
|
||||
{
|
||||
return *d_data == *other.d_data;
|
||||
}
|
||||
|
||||
//! \brief Compare two symbols
|
||||
bool QwtIntervalSymbol::operator!=(
|
||||
const QwtIntervalSymbol &other ) const
|
||||
{
|
||||
return !( *d_data == *other.d_data );
|
||||
}
|
||||
|
||||
/*!
|
||||
Specify the symbol style
|
||||
|
||||
\param style Style
|
||||
\sa style(), Style
|
||||
*/
|
||||
void QwtIntervalSymbol::setStyle( Style style )
|
||||
{
|
||||
d_data->style = style;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Current symbol style
|
||||
\sa setStyle()
|
||||
*/
|
||||
QwtIntervalSymbol::Style QwtIntervalSymbol::style() const
|
||||
{
|
||||
return d_data->style;
|
||||
}
|
||||
|
||||
/*!
|
||||
Specify the width of the symbol
|
||||
It is used depending on the style.
|
||||
|
||||
\param width Width
|
||||
\sa width(), setStyle()
|
||||
*/
|
||||
void QwtIntervalSymbol::setWidth( int width )
|
||||
{
|
||||
d_data->width = width;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Width of the symbol.
|
||||
\sa setWidth(), setStyle()
|
||||
*/
|
||||
int QwtIntervalSymbol::width() const
|
||||
{
|
||||
return d_data->width;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign a brush
|
||||
|
||||
The brush is used for the Box style.
|
||||
|
||||
\param brush Brush
|
||||
\sa brush()
|
||||
*/
|
||||
void QwtIntervalSymbol::setBrush( const QBrush &brush )
|
||||
{
|
||||
d_data->brush = brush;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Brush
|
||||
\sa setBrush()
|
||||
*/
|
||||
const QBrush& QwtIntervalSymbol::brush() const
|
||||
{
|
||||
return d_data->brush;
|
||||
}
|
||||
|
||||
/*!
|
||||
Build and assign a pen
|
||||
|
||||
In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it
|
||||
non cosmetic ( see QPen::isCosmetic() ). This method has been introduced
|
||||
to hide this incompatibility.
|
||||
|
||||
\param color Pen color
|
||||
\param width Pen width
|
||||
\param style Pen style
|
||||
|
||||
\sa pen(), brush()
|
||||
*/
|
||||
void QwtIntervalSymbol::setPen( const QColor &color,
|
||||
qreal width, Qt::PenStyle style )
|
||||
{
|
||||
setPen( QPen( color, width, style ) );
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign a pen
|
||||
|
||||
\param pen Pen
|
||||
\sa pen(), setBrush()
|
||||
*/
|
||||
void QwtIntervalSymbol::setPen( const QPen &pen )
|
||||
{
|
||||
d_data->pen = pen;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Pen
|
||||
\sa setPen(), brush()
|
||||
*/
|
||||
const QPen& QwtIntervalSymbol::pen() const
|
||||
{
|
||||
return d_data->pen;
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw a symbol depending on its style
|
||||
|
||||
\param painter Painter
|
||||
\param orientation Orientation
|
||||
\param from Start point of the interval in target device coordinates
|
||||
\param to End point of the interval in target device coordinates
|
||||
|
||||
\sa setStyle()
|
||||
*/
|
||||
void QwtIntervalSymbol::draw( QPainter *painter, Qt::Orientation orientation,
|
||||
const QPointF &from, const QPointF &to ) const
|
||||
{
|
||||
const qreal pw = qMax( painter->pen().widthF(), qreal( 1.0 ) );
|
||||
|
||||
QPointF p1 = from;
|
||||
QPointF p2 = to;
|
||||
if ( QwtPainter::roundingAlignment( painter ) )
|
||||
{
|
||||
p1 = p1.toPoint();
|
||||
p2 = p2.toPoint();
|
||||
}
|
||||
|
||||
switch ( d_data->style )
|
||||
{
|
||||
case QwtIntervalSymbol::Bar:
|
||||
{
|
||||
QwtPainter::drawLine( painter, p1, p2 );
|
||||
if ( d_data->width > pw )
|
||||
{
|
||||
if ( ( orientation == Qt::Horizontal )
|
||||
&& ( p1.y() == p2.y() ) )
|
||||
{
|
||||
const double sw = d_data->width;
|
||||
|
||||
const double y = p1.y() - sw / 2;
|
||||
QwtPainter::drawLine( painter,
|
||||
p1.x(), y, p1.x(), y + sw );
|
||||
QwtPainter::drawLine( painter,
|
||||
p2.x(), y, p2.x(), y + sw );
|
||||
}
|
||||
else if ( ( orientation == Qt::Vertical )
|
||||
&& ( p1.x() == p2.x() ) )
|
||||
{
|
||||
const double sw = d_data->width;
|
||||
|
||||
const double x = p1.x() - sw / 2;
|
||||
QwtPainter::drawLine( painter,
|
||||
x, p1.y(), x + sw, p1.y() );
|
||||
QwtPainter::drawLine( painter,
|
||||
x, p2.y(), x + sw, p2.y() );
|
||||
}
|
||||
else
|
||||
{
|
||||
const double sw = d_data->width;
|
||||
|
||||
const double dx = p2.x() - p1.x();
|
||||
const double dy = p2.y() - p1.y();
|
||||
const double angle = qAtan2( dy, dx ) + M_PI_2;
|
||||
double dw2 = sw / 2.0;
|
||||
|
||||
const double cx = qFastCos( angle ) * dw2;
|
||||
const double sy = qFastSin( angle ) * dw2;
|
||||
|
||||
QwtPainter::drawLine( painter,
|
||||
p1.x() - cx, p1.y() - sy,
|
||||
p1.x() + cx, p1.y() + sy );
|
||||
QwtPainter::drawLine( painter,
|
||||
p2.x() - cx, p2.y() - sy,
|
||||
p2.x() + cx, p2.y() + sy );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QwtIntervalSymbol::Box:
|
||||
{
|
||||
if ( d_data->width <= pw )
|
||||
{
|
||||
QwtPainter::drawLine( painter, p1, p2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ( orientation == Qt::Horizontal )
|
||||
&& ( p1.y() == p2.y() ) )
|
||||
{
|
||||
const double sw = d_data->width;
|
||||
|
||||
const double y = p1.y() - d_data->width / 2;
|
||||
QwtPainter::drawRect( painter,
|
||||
p1.x(), y, p2.x() - p1.x(), sw );
|
||||
}
|
||||
else if ( ( orientation == Qt::Vertical )
|
||||
&& ( p1.x() == p2.x() ) )
|
||||
{
|
||||
const double sw = d_data->width;
|
||||
|
||||
const double x = p1.x() - d_data->width / 2;
|
||||
QwtPainter::drawRect( painter,
|
||||
x, p1.y(), sw, p2.y() - p1.y() );
|
||||
}
|
||||
else
|
||||
{
|
||||
const double sw = d_data->width;
|
||||
|
||||
const double dx = p2.x() - p1.x();
|
||||
const double dy = p2.y() - p1.y();
|
||||
const double angle = qAtan2( dy, dx ) + M_PI_2;
|
||||
double dw2 = sw / 2.0;
|
||||
|
||||
const double cx = qFastCos( angle ) * dw2;
|
||||
const double sy = qFastSin( angle ) * dw2;
|
||||
|
||||
QPolygonF polygon;
|
||||
polygon += QPointF( p1.x() - cx, p1.y() - sy );
|
||||
polygon += QPointF( p1.x() + cx, p1.y() + sy );
|
||||
polygon += QPointF( p2.x() + cx, p2.y() + sy );
|
||||
polygon += QPointF( p2.x() - cx, p2.y() - sy );
|
||||
|
||||
QwtPainter::drawPolygon( painter, polygon );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
86
third/3rd_qwt/qwt_interval_symbol.h
Normal file
86
third/3rd_qwt/qwt_interval_symbol.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_INTERVAL_SYMBOL_H
|
||||
#define QWT_INTERVAL_SYMBOL_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qpen.h>
|
||||
#include <qsize.h>
|
||||
|
||||
class QPainter;
|
||||
class QRect;
|
||||
class QPointF;
|
||||
|
||||
/*!
|
||||
\brief A drawing primitive for displaying an interval like an error bar
|
||||
|
||||
\sa QwtPlotIntervalCurve
|
||||
*/
|
||||
class QWT_EXPORT QwtIntervalSymbol
|
||||
{
|
||||
public:
|
||||
//! Symbol style
|
||||
enum Style
|
||||
{
|
||||
//! No Style. The symbol cannot be drawn.
|
||||
NoSymbol = -1,
|
||||
|
||||
/*!
|
||||
The symbol displays a line with caps at the beginning/end.
|
||||
The size of the caps depends on the symbol width().
|
||||
*/
|
||||
Bar,
|
||||
|
||||
/*!
|
||||
The symbol displays a plain rectangle using pen() and brush().
|
||||
The size of the rectangle depends on the translated interval and
|
||||
the width(),
|
||||
*/
|
||||
Box,
|
||||
|
||||
/*!
|
||||
Styles >= UserSymbol are reserved for derived
|
||||
classes of QwtIntervalSymbol that overload draw() with
|
||||
additional application specific symbol types.
|
||||
*/
|
||||
UserSymbol = 1000
|
||||
};
|
||||
|
||||
public:
|
||||
QwtIntervalSymbol( Style = NoSymbol );
|
||||
QwtIntervalSymbol( const QwtIntervalSymbol & );
|
||||
virtual ~QwtIntervalSymbol();
|
||||
|
||||
QwtIntervalSymbol &operator=( const QwtIntervalSymbol & );
|
||||
bool operator==( const QwtIntervalSymbol & ) const;
|
||||
bool operator!=( const QwtIntervalSymbol & ) const;
|
||||
|
||||
void setWidth( int );
|
||||
int width() const;
|
||||
|
||||
void setBrush( const QBrush & );
|
||||
const QBrush& brush() const;
|
||||
|
||||
void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine );
|
||||
void setPen( const QPen & );
|
||||
const QPen& pen() const;
|
||||
|
||||
void setStyle( Style );
|
||||
Style style() const;
|
||||
|
||||
virtual void draw( QPainter *, Qt::Orientation,
|
||||
const QPointF& from, const QPointF& to ) const;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData* d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
855
third/3rd_qwt/qwt_knob.cpp
Normal file
855
third/3rd_qwt/qwt_knob.cpp
Normal file
@@ -0,0 +1,855 @@
|
||||
/* -*- 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_knob.h"
|
||||
#include "qwt_round_scale_draw.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_painter.h"
|
||||
#include "qwt_scale_map.h"
|
||||
#include <qpainter.h>
|
||||
#include <qpalette.h>
|
||||
#include <qstyle.h>
|
||||
#include <qstyleoption.h>
|
||||
#include <qevent.h>
|
||||
#include <qmath.h>
|
||||
#include <qapplication.h>
|
||||
|
||||
#if QT_VERSION < 0x040601
|
||||
#define qAtan2(y, x) ::atan2(y, x)
|
||||
#define qFabs(x) ::fabs(x)
|
||||
#define qFastCos(x) qCos(x)
|
||||
#define qFastSin(x) qSin(x)
|
||||
#endif
|
||||
|
||||
static QSize qwtKnobSizeHint( const QwtKnob *knob, int min )
|
||||
{
|
||||
int knobWidth = knob->knobWidth();
|
||||
if ( knobWidth <= 0 )
|
||||
knobWidth = qMax( 3 * knob->markerSize(), min );
|
||||
|
||||
// Add the scale radial thickness to the knobWidth
|
||||
const int extent = qCeil( knob->scaleDraw()->extent( knob->font() ) );
|
||||
const int d = 2 * ( extent + 4 ) + knobWidth;
|
||||
|
||||
int left, right, top, bottom;
|
||||
knob->getContentsMargins( &left, &top, &right, &bottom );
|
||||
|
||||
return QSize( d + left + right, d + top + bottom );
|
||||
}
|
||||
|
||||
static inline double qwtToScaleAngle( double angle )
|
||||
{
|
||||
// the map is counter clockwise with the origin
|
||||
// at 90° using angles from -180° -> 180°
|
||||
|
||||
double a = 90.0 - angle;
|
||||
if ( a <= -180.0 )
|
||||
a += 360.0;
|
||||
else if ( a >= 180.0 )
|
||||
a -= 360.0;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static double qwtToDegrees( double value )
|
||||
{
|
||||
return qwtNormalizeDegrees( 90.0 - value );
|
||||
}
|
||||
|
||||
class QwtKnob::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
knobStyle( QwtKnob::Raised ),
|
||||
markerStyle( QwtKnob::Notch ),
|
||||
borderWidth( 2 ),
|
||||
borderDist( 4 ),
|
||||
scaleDist( 4 ),
|
||||
maxScaleTicks( 11 ),
|
||||
knobWidth( 0 ),
|
||||
alignment( Qt::AlignCenter ),
|
||||
markerSize( 8 ),
|
||||
totalAngle( 270.0 ),
|
||||
mouseOffset( 0.0 )
|
||||
{
|
||||
}
|
||||
|
||||
QwtKnob::KnobStyle knobStyle;
|
||||
QwtKnob::MarkerStyle markerStyle;
|
||||
|
||||
int borderWidth;
|
||||
int borderDist;
|
||||
int scaleDist;
|
||||
int maxScaleTicks;
|
||||
int knobWidth;
|
||||
Qt::Alignment alignment;
|
||||
int markerSize;
|
||||
|
||||
double totalAngle;
|
||||
|
||||
double mouseOffset;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
|
||||
Construct a knob with an angle of 270°. The style is
|
||||
QwtKnob::Raised and the marker style is QwtKnob::Notch.
|
||||
The width of the knob is set to 50 pixels.
|
||||
|
||||
\param parent Parent widget
|
||||
|
||||
\sa setTotalAngle()
|
||||
*/
|
||||
QwtKnob::QwtKnob( QWidget* parent ):
|
||||
QwtAbstractSlider( parent )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
|
||||
setScaleDraw( new QwtRoundScaleDraw() );
|
||||
|
||||
setTotalAngle( 270.0 );
|
||||
|
||||
setScale( 0.0, 10.0 );
|
||||
setValue( 0.0 );
|
||||
|
||||
setSizePolicy( QSizePolicy::MinimumExpanding,
|
||||
QSizePolicy::MinimumExpanding );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtKnob::~QwtKnob()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the knob type
|
||||
|
||||
\param knobStyle Knob type
|
||||
\sa knobStyle(), setBorderWidth()
|
||||
*/
|
||||
void QwtKnob::setKnobStyle( KnobStyle knobStyle )
|
||||
{
|
||||
if ( d_data->knobStyle != knobStyle )
|
||||
{
|
||||
d_data->knobStyle = knobStyle;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Marker type of the knob
|
||||
\sa setKnobStyle(), setBorderWidth()
|
||||
*/
|
||||
QwtKnob::KnobStyle QwtKnob::knobStyle() const
|
||||
{
|
||||
return d_data->knobStyle;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the marker type of the knob
|
||||
|
||||
\param markerStyle Marker type
|
||||
\sa markerStyle(), setMarkerSize()
|
||||
*/
|
||||
void QwtKnob::setMarkerStyle( MarkerStyle markerStyle )
|
||||
{
|
||||
if ( d_data->markerStyle != markerStyle )
|
||||
{
|
||||
d_data->markerStyle = markerStyle;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Marker type of the knob
|
||||
\sa setMarkerStyle(), setMarkerSize()
|
||||
*/
|
||||
QwtKnob::MarkerStyle QwtKnob::markerStyle() const
|
||||
{
|
||||
return d_data->markerStyle;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the total angle by which the knob can be turned
|
||||
\param angle Angle in degrees.
|
||||
|
||||
The angle has to be between [10, 360] degrees. Angles above
|
||||
360 ( so that the knob can be turned several times around its axis )
|
||||
have to be set using setNumTurns().
|
||||
|
||||
The default angle is 270 degrees.
|
||||
|
||||
\sa totalAngle(), setNumTurns()
|
||||
*/
|
||||
void QwtKnob::setTotalAngle ( double angle )
|
||||
{
|
||||
angle = qBound( 10.0, angle, 360.0 );
|
||||
|
||||
if ( angle != d_data->totalAngle )
|
||||
{
|
||||
d_data->totalAngle = angle;
|
||||
|
||||
scaleDraw()->setAngleRange( -0.5 * d_data->totalAngle,
|
||||
0.5 * d_data->totalAngle );
|
||||
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the total angle
|
||||
\sa setTotalAngle(), setNumTurns(), numTurns()
|
||||
*/
|
||||
double QwtKnob::totalAngle() const
|
||||
{
|
||||
return d_data->totalAngle;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the number of turns
|
||||
|
||||
When numTurns > 1 the knob can be turned several times around its axis
|
||||
- otherwise the total angle is floored to 360°.
|
||||
|
||||
\sa numTurns(), totalAngle(), setTotalAngle()
|
||||
*/
|
||||
|
||||
void QwtKnob::setNumTurns( int numTurns )
|
||||
{
|
||||
numTurns = qMax( numTurns, 1 );
|
||||
|
||||
if ( numTurns == 1 && d_data->totalAngle <= 360.0 )
|
||||
return;
|
||||
|
||||
const double angle = numTurns * 360.0;
|
||||
if ( angle != d_data->totalAngle )
|
||||
{
|
||||
d_data->totalAngle = angle;
|
||||
|
||||
scaleDraw()->setAngleRange( -0.5 * d_data->totalAngle,
|
||||
0.5 * d_data->totalAngle );
|
||||
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of turns.
|
||||
|
||||
When the total angle is below 360° numTurns() is ceiled to 1.
|
||||
\sa setNumTurns(), setTotalAngle(), totalAngle()
|
||||
*/
|
||||
int QwtKnob::numTurns() const
|
||||
{
|
||||
return qCeil( d_data->totalAngle / 360.0 );
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the scale draw of the knob
|
||||
|
||||
For changing the labels of the scales, it
|
||||
is necessary to derive from QwtRoundScaleDraw and
|
||||
overload QwtRoundScaleDraw::label().
|
||||
|
||||
\sa scaleDraw()
|
||||
*/
|
||||
void QwtKnob::setScaleDraw( QwtRoundScaleDraw *scaleDraw )
|
||||
{
|
||||
setAbstractScaleDraw( scaleDraw );
|
||||
setTotalAngle( d_data->totalAngle );
|
||||
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the scale draw of the knob
|
||||
\sa setScaleDraw()
|
||||
*/
|
||||
const QwtRoundScaleDraw *QwtKnob::scaleDraw() const
|
||||
{
|
||||
return static_cast<const QwtRoundScaleDraw *>( abstractScaleDraw() );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the scale draw of the knob
|
||||
\sa setScaleDraw()
|
||||
*/
|
||||
QwtRoundScaleDraw *QwtKnob::scaleDraw()
|
||||
{
|
||||
return static_cast<QwtRoundScaleDraw *>( abstractScaleDraw() );
|
||||
}
|
||||
|
||||
/*!
|
||||
Calculate the bounding rectangle of the knob without the scale
|
||||
|
||||
\return Bounding rectangle of the knob
|
||||
\sa knobWidth(), alignment(), QWidget::contentsRect()
|
||||
*/
|
||||
QRect QwtKnob::knobRect() const
|
||||
{
|
||||
const QRect cr = contentsRect();
|
||||
|
||||
const int extent = qCeil( scaleDraw()->extent( font() ) );
|
||||
const int d = extent + d_data->scaleDist;
|
||||
|
||||
int w = d_data->knobWidth;
|
||||
if ( w <= 0 )
|
||||
{
|
||||
const int dim = qMin( cr.width(), cr.height() );
|
||||
|
||||
w = dim - 2 * ( d );
|
||||
w = qMax( 0, w );
|
||||
}
|
||||
|
||||
QRect r( 0, 0, w, w );
|
||||
|
||||
if ( d_data->alignment & Qt::AlignLeft )
|
||||
{
|
||||
r.moveLeft( cr.left() + d );
|
||||
}
|
||||
else if ( d_data->alignment & Qt::AlignRight )
|
||||
{
|
||||
r.moveRight( cr.right() - d );
|
||||
}
|
||||
else
|
||||
{
|
||||
r.moveCenter( QPoint( cr.center().x(), r.center().y() ) );
|
||||
}
|
||||
|
||||
if ( d_data->alignment & Qt::AlignTop )
|
||||
{
|
||||
r.moveTop( cr.top() + d );
|
||||
}
|
||||
else if ( d_data->alignment & Qt::AlignBottom )
|
||||
{
|
||||
r.moveBottom( cr.bottom() - d );
|
||||
}
|
||||
else
|
||||
{
|
||||
r.moveCenter( QPoint( r.center().x(), cr.center().y() ) );
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Determine what to do when the user presses a mouse button.
|
||||
|
||||
\param pos Mouse position
|
||||
|
||||
\retval True, when pos is inside the circle of the knob.
|
||||
\sa scrolledTo()
|
||||
*/
|
||||
bool QwtKnob::isScrollPosition( const QPoint &pos ) const
|
||||
{
|
||||
const QRect kr = knobRect();
|
||||
|
||||
const QRegion region( kr, QRegion::Ellipse );
|
||||
if ( region.contains( pos ) && ( pos != kr.center() ) )
|
||||
{
|
||||
const double angle = QLineF( kr.center(), pos ).angle();
|
||||
const double valueAngle = qwtToDegrees( scaleMap().transform( value() ) );
|
||||
|
||||
d_data->mouseOffset = qwtNormalizeDegrees( angle - valueAngle );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Determine the value for a new position of the mouse
|
||||
|
||||
\param pos Mouse position
|
||||
|
||||
\return Value for the mouse position
|
||||
\sa isScrollPosition()
|
||||
*/
|
||||
double QwtKnob::scrolledTo( const QPoint &pos ) const
|
||||
{
|
||||
double angle = QLineF( rect().center(), pos ).angle();
|
||||
angle = qwtNormalizeDegrees( angle - d_data->mouseOffset );
|
||||
|
||||
if ( scaleMap().pDist() > 360.0 )
|
||||
{
|
||||
angle = qwtToDegrees( angle );
|
||||
|
||||
const double v = scaleMap().transform( value() );
|
||||
|
||||
int numTurns = qFloor( ( v - scaleMap().p1() ) / 360.0 );
|
||||
|
||||
double valueAngle = qwtNormalizeDegrees( v );
|
||||
if ( qAbs( valueAngle - angle ) > 180.0 )
|
||||
{
|
||||
numTurns += ( angle > valueAngle ) ? -1 : 1;
|
||||
}
|
||||
|
||||
angle += scaleMap().p1() + numTurns * 360.0;
|
||||
|
||||
if ( !wrapping() )
|
||||
{
|
||||
const double boundedAngle =
|
||||
qBound( scaleMap().p1(), angle, scaleMap().p2() );
|
||||
|
||||
d_data->mouseOffset += ( boundedAngle - angle );
|
||||
angle = boundedAngle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = qwtToScaleAngle( angle );
|
||||
|
||||
double boundedAngle = qBound( scaleMap().p1(), angle, scaleMap().p2() );
|
||||
|
||||
if ( !wrapping() )
|
||||
{
|
||||
const double currentAngle = scaleMap().transform( value() );
|
||||
|
||||
if ( ( currentAngle > 90.0 ) && ( boundedAngle < -90.0 ) )
|
||||
boundedAngle = scaleMap().p2();
|
||||
else if ( ( currentAngle < -90.0 ) && ( boundedAngle > 90.0 ) )
|
||||
boundedAngle = scaleMap().p1();
|
||||
|
||||
d_data->mouseOffset += ( boundedAngle - angle );
|
||||
}
|
||||
|
||||
angle = boundedAngle;
|
||||
}
|
||||
|
||||
return scaleMap().invTransform( angle );
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle QEvent::StyleChange and QEvent::FontChange;
|
||||
\param event Change event
|
||||
*/
|
||||
void QwtKnob::changeEvent( QEvent *event )
|
||||
{
|
||||
switch( event->type() )
|
||||
{
|
||||
case QEvent::StyleChange:
|
||||
case QEvent::FontChange:
|
||||
{
|
||||
updateGeometry();
|
||||
update();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Repaint the knob
|
||||
\param event Paint event
|
||||
*/
|
||||
void QwtKnob::paintEvent( QPaintEvent *event )
|
||||
{
|
||||
const QRectF knobRect = this->knobRect();
|
||||
|
||||
QPainter painter( this );
|
||||
painter.setClipRegion( event->region() );
|
||||
|
||||
QStyleOption opt;
|
||||
opt.init(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
|
||||
|
||||
painter.setRenderHint( QPainter::Antialiasing, true );
|
||||
|
||||
if ( !knobRect.contains( event->region().boundingRect() ) )
|
||||
{
|
||||
scaleDraw()->setRadius( 0.5 * knobRect.width() + d_data->scaleDist );
|
||||
scaleDraw()->moveCenter( knobRect.center() );
|
||||
|
||||
scaleDraw()->draw( &painter, palette() );
|
||||
}
|
||||
|
||||
drawKnob( &painter, knobRect );
|
||||
|
||||
drawMarker( &painter, knobRect,
|
||||
qwtNormalizeDegrees( scaleMap().transform( value() ) ) );
|
||||
|
||||
painter.setRenderHint( QPainter::Antialiasing, false );
|
||||
|
||||
if ( hasFocus() )
|
||||
drawFocusIndicator( &painter );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Draw the knob
|
||||
|
||||
\param painter painter
|
||||
\param knobRect Bounding rectangle of the knob (without scale)
|
||||
*/
|
||||
void QwtKnob::drawKnob( QPainter *painter, const QRectF &knobRect ) const
|
||||
{
|
||||
double dim = qMin( knobRect.width(), knobRect.height() );
|
||||
dim -= d_data->borderWidth * 0.5;
|
||||
|
||||
QRectF aRect( 0, 0, dim, dim );
|
||||
aRect.moveCenter( knobRect.center() );
|
||||
|
||||
QPen pen( Qt::NoPen );
|
||||
if ( d_data->borderWidth > 0 )
|
||||
{
|
||||
QColor c1 = palette().color( QPalette::Light );
|
||||
QColor c2 = palette().color( QPalette::Dark );
|
||||
|
||||
QLinearGradient gradient( aRect.topLeft(), aRect.bottomRight() );
|
||||
gradient.setColorAt( 0.0, c1 );
|
||||
gradient.setColorAt( 0.3, c1 );
|
||||
gradient.setColorAt( 0.7, c2 );
|
||||
gradient.setColorAt( 1.0, c2 );
|
||||
|
||||
pen = QPen( gradient, d_data->borderWidth );
|
||||
}
|
||||
|
||||
QBrush brush;
|
||||
switch( d_data->knobStyle )
|
||||
{
|
||||
case QwtKnob::Raised:
|
||||
{
|
||||
double off = 0.3 * knobRect.width();
|
||||
QRadialGradient gradient( knobRect.center(),
|
||||
knobRect.width(), knobRect.topLeft() + QPointF( off, off ) );
|
||||
|
||||
gradient.setColorAt( 0.0, palette().color( QPalette::Midlight ) );
|
||||
gradient.setColorAt( 1.0, palette().color( QPalette::Button ) );
|
||||
|
||||
brush = QBrush( gradient );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtKnob::Styled:
|
||||
{
|
||||
QRadialGradient gradient(knobRect.center().x() - knobRect.width() / 3,
|
||||
knobRect.center().y() - knobRect.height() / 2,
|
||||
knobRect.width() * 1.3,
|
||||
knobRect.center().x(),
|
||||
knobRect.center().y() - knobRect.height() / 2);
|
||||
|
||||
const QColor c = palette().color( QPalette::Button );
|
||||
gradient.setColorAt(0, c.lighter(110));
|
||||
gradient.setColorAt(qreal(0.5), c);
|
||||
gradient.setColorAt(qreal(0.501), c.darker(102));
|
||||
gradient.setColorAt(1, c.darker(115));
|
||||
|
||||
brush = QBrush( gradient );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtKnob::Sunken:
|
||||
{
|
||||
QLinearGradient gradient(
|
||||
knobRect.topLeft(), knobRect.bottomRight() );
|
||||
gradient.setColorAt( 0.0, palette().color( QPalette::Mid ) );
|
||||
gradient.setColorAt( 0.5, palette().color( QPalette::Button ) );
|
||||
gradient.setColorAt( 1.0, palette().color( QPalette::Midlight ) );
|
||||
brush = QBrush( gradient );
|
||||
|
||||
break;
|
||||
}
|
||||
case QwtKnob::Flat:
|
||||
default:
|
||||
brush = palette().brush( QPalette::Button );
|
||||
}
|
||||
|
||||
painter->setPen( pen );
|
||||
painter->setBrush( brush );
|
||||
painter->drawEllipse( aRect );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Draw the marker at the knob's front
|
||||
|
||||
\param painter Painter
|
||||
\param rect Bounding rectangle of the knob without scale
|
||||
\param angle Angle of the marker in degrees
|
||||
( clockwise, 0 at the 12 o'clock position )
|
||||
*/
|
||||
void QwtKnob::drawMarker( QPainter *painter,
|
||||
const QRectF &rect, double angle ) const
|
||||
{
|
||||
if ( d_data->markerStyle == NoMarker || !isValid() )
|
||||
return;
|
||||
|
||||
const double radians = qwtRadians( angle );
|
||||
const double sinA = -qFastSin( radians );
|
||||
const double cosA = qFastCos( radians );
|
||||
|
||||
const double xm = rect.center().x();
|
||||
const double ym = rect.center().y();
|
||||
const double margin = 4.0;
|
||||
|
||||
double radius = 0.5 * ( rect.width() - d_data->borderWidth ) - margin;
|
||||
if ( radius < 1.0 )
|
||||
radius = 1.0;
|
||||
|
||||
int markerSize = d_data->markerSize;
|
||||
if ( markerSize <= 0 )
|
||||
markerSize = qRound( 0.4 * radius );
|
||||
|
||||
switch ( d_data->markerStyle )
|
||||
{
|
||||
case Notch:
|
||||
case Nub:
|
||||
{
|
||||
const double dotWidth =
|
||||
qMin( double( markerSize ), radius);
|
||||
|
||||
const double dotCenterDist = radius - 0.5 * dotWidth;
|
||||
if ( dotCenterDist > 0.0 )
|
||||
{
|
||||
const QPointF center( xm - sinA * dotCenterDist,
|
||||
ym - cosA * dotCenterDist );
|
||||
|
||||
QRectF ellipse( 0.0, 0.0, dotWidth, dotWidth );
|
||||
ellipse.moveCenter( center );
|
||||
|
||||
QColor c1 = palette().color( QPalette::Light );
|
||||
QColor c2 = palette().color( QPalette::Mid );
|
||||
|
||||
if ( d_data->markerStyle == Notch )
|
||||
qSwap( c1, c2 );
|
||||
|
||||
QLinearGradient gradient(
|
||||
ellipse.topLeft(), ellipse.bottomRight() );
|
||||
gradient.setColorAt( 0.0, c1 );
|
||||
gradient.setColorAt( 1.0, c2 );
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( gradient );
|
||||
|
||||
painter->drawEllipse( ellipse );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Dot:
|
||||
{
|
||||
const double dotWidth =
|
||||
qMin( double( markerSize ), radius);
|
||||
|
||||
const double dotCenterDist = radius - 0.5 * dotWidth;
|
||||
if ( dotCenterDist > 0.0 )
|
||||
{
|
||||
const QPointF center( xm - sinA * dotCenterDist,
|
||||
ym - cosA * dotCenterDist );
|
||||
|
||||
QRectF ellipse( 0.0, 0.0, dotWidth, dotWidth );
|
||||
ellipse.moveCenter( center );
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( palette().color( QPalette::ButtonText ) );
|
||||
painter->drawEllipse( ellipse );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Tick:
|
||||
{
|
||||
const double rb = qMax( radius - markerSize, 1.0 );
|
||||
const double re = radius;
|
||||
|
||||
const QLineF line( xm - sinA * rb, ym - cosA * rb,
|
||||
xm - sinA * re, ym - cosA * re );
|
||||
|
||||
QPen pen( palette().color( QPalette::ButtonText ), 0 );
|
||||
pen.setCapStyle( Qt::FlatCap );
|
||||
painter->setPen( pen );
|
||||
painter->drawLine ( line );
|
||||
|
||||
break;
|
||||
}
|
||||
case Triangle:
|
||||
{
|
||||
const double rb = qMax( radius - markerSize, 1.0 );
|
||||
const double re = radius;
|
||||
|
||||
painter->translate( rect.center() );
|
||||
painter->rotate( angle - 90.0 );
|
||||
|
||||
QPolygonF polygon;
|
||||
polygon += QPointF( re, 0.0 );
|
||||
polygon += QPointF( rb, 0.5 * ( re - rb ) );
|
||||
polygon += QPointF( rb, -0.5 * ( re - rb ) );
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( palette().color( QPalette::ButtonText ) );
|
||||
painter->drawPolygon( polygon );
|
||||
|
||||
painter->resetTransform();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the focus indicator
|
||||
\param painter Painter
|
||||
*/
|
||||
void QwtKnob::drawFocusIndicator( QPainter *painter ) const
|
||||
{
|
||||
const QRect cr = contentsRect();
|
||||
|
||||
int w = d_data->knobWidth;
|
||||
if ( w <= 0 )
|
||||
{
|
||||
w = qMin( cr.width(), cr.height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
const int extent = qCeil( scaleDraw()->extent( font() ) );
|
||||
w += 2 * ( extent + d_data->scaleDist );
|
||||
}
|
||||
|
||||
QRect focusRect( 0, 0, w, w );
|
||||
focusRect.moveCenter( cr.center() );
|
||||
|
||||
QwtPainter::drawFocusRect( painter, this, focusRect );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the alignment of the knob
|
||||
|
||||
Similar to a QLabel::alignment() the flags decide how
|
||||
to align the knob inside of contentsRect().
|
||||
|
||||
The default setting is Qt::AlignCenter
|
||||
|
||||
\param alignment Or'd alignment flags
|
||||
|
||||
\sa alignment(), setKnobWidth(), knobRect()
|
||||
*/
|
||||
void QwtKnob::setAlignment( Qt::Alignment alignment )
|
||||
{
|
||||
if ( d_data->alignment != alignment )
|
||||
{
|
||||
d_data->alignment = alignment;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Alignment of the knob inside of contentsRect()
|
||||
\sa setAlignment(), knobWidth(), knobRect()
|
||||
*/
|
||||
Qt::Alignment QwtKnob::alignment() const
|
||||
{
|
||||
return d_data->alignment;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the knob's width.
|
||||
|
||||
Setting a fixed value for the diameter of the knob
|
||||
is helpful for aligning several knobs in a row.
|
||||
|
||||
\param width New width
|
||||
|
||||
\sa knobWidth(), setAlignment()
|
||||
\note Modifies the sizePolicy()
|
||||
*/
|
||||
void QwtKnob::setKnobWidth( int width )
|
||||
{
|
||||
width = qMax( width, 0 );
|
||||
|
||||
if ( width != d_data->knobWidth )
|
||||
{
|
||||
QSizePolicy::Policy policy;
|
||||
if ( width > 0 )
|
||||
policy = QSizePolicy::Minimum;
|
||||
else
|
||||
policy = QSizePolicy::MinimumExpanding;
|
||||
|
||||
setSizePolicy( policy, policy );
|
||||
|
||||
d_data->knobWidth = width;
|
||||
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
//! Return the width of the knob
|
||||
int QwtKnob::knobWidth() const
|
||||
{
|
||||
return d_data->knobWidth;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the knob's border width
|
||||
\param borderWidth new border width
|
||||
*/
|
||||
void QwtKnob::setBorderWidth( int borderWidth )
|
||||
{
|
||||
d_data->borderWidth = qMax( borderWidth, 0 );
|
||||
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
|
||||
//! Return the border width
|
||||
int QwtKnob::borderWidth() const
|
||||
{
|
||||
return d_data->borderWidth;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the size of the marker
|
||||
|
||||
When setting a size <= 0 the marker will
|
||||
automatically scaled to 40% of the radius of the knob.
|
||||
|
||||
\sa markerSize(), markerStyle()
|
||||
*/
|
||||
void QwtKnob::setMarkerSize( int size )
|
||||
{
|
||||
if ( d_data->markerSize != size )
|
||||
{
|
||||
d_data->markerSize = size;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Marker size
|
||||
\sa setMarkerSize()
|
||||
*/
|
||||
int QwtKnob::markerSize() const
|
||||
{
|
||||
return d_data->markerSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return sizeHint()
|
||||
*/
|
||||
QSize QwtKnob::sizeHint() const
|
||||
{
|
||||
const QSize hint = qwtKnobSizeHint( this, 50 );
|
||||
return hint.expandedTo( QApplication::globalStrut() );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Minimum size hint
|
||||
\sa sizeHint()
|
||||
*/
|
||||
QSize QwtKnob::minimumSizeHint() const
|
||||
{
|
||||
return qwtKnobSizeHint( this, 20 );
|
||||
}
|
||||
178
third/3rd_qwt/qwt_knob.h
Normal file
178
third/3rd_qwt/qwt_knob.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_KNOB_H
|
||||
#define QWT_KNOB_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_abstract_slider.h"
|
||||
|
||||
class QwtRoundScaleDraw;
|
||||
|
||||
/*!
|
||||
\brief The Knob Widget
|
||||
|
||||
The QwtKnob widget imitates look and behavior of a volume knob on a radio.
|
||||
It looks similar to QDial - not to QwtDial.
|
||||
|
||||
The value range of a knob might be divided into several turns.
|
||||
|
||||
The layout of the knob depends on the knobWidth().
|
||||
|
||||
- width > 0
|
||||
The diameter of the knob is fixed and the knob is aligned
|
||||
according to the alignment() flags inside of the contentsRect().
|
||||
|
||||
- width <= 0
|
||||
The knob is extended to the minimum of width/height of the contentsRect()
|
||||
and aligned in the other direction according to alignment().
|
||||
|
||||
Setting a fixed knobWidth() is helpful to align several knobs with different
|
||||
scale labels.
|
||||
|
||||
\image html knob.png
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtKnob: public QwtAbstractSlider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_ENUMS ( KnobStyle MarkerStyle )
|
||||
|
||||
Q_PROPERTY( KnobStyle knobStyle READ knobStyle WRITE setKnobStyle )
|
||||
Q_PROPERTY( int knobWidth READ knobWidth WRITE setKnobWidth )
|
||||
Q_PROPERTY( Qt::Alignment alignment READ alignment WRITE setAlignment )
|
||||
Q_PROPERTY( double totalAngle READ totalAngle WRITE setTotalAngle )
|
||||
Q_PROPERTY( int numTurns READ numTurns WRITE setNumTurns )
|
||||
Q_PROPERTY( MarkerStyle markerStyle READ markerStyle WRITE setMarkerStyle )
|
||||
Q_PROPERTY( int markerSize READ markerSize WRITE setMarkerSize )
|
||||
Q_PROPERTY( int borderWidth READ borderWidth WRITE setBorderWidth )
|
||||
|
||||
public:
|
||||
/*!
|
||||
\brief Style of the knob surface
|
||||
|
||||
Depending on the KnobStyle the surface of the knob is
|
||||
filled from the brushes of the widget palette().
|
||||
|
||||
\sa setKnobStyle(), knobStyle()
|
||||
*/
|
||||
enum KnobStyle
|
||||
{
|
||||
//! Fill the knob with a brush from QPalette::Button.
|
||||
Flat,
|
||||
|
||||
//! Build a gradient from QPalette::Midlight and QPalette::Button
|
||||
Raised,
|
||||
|
||||
/*!
|
||||
Build a gradient from QPalette::Midlight, QPalette::Button
|
||||
and QPalette::Midlight
|
||||
*/
|
||||
Sunken,
|
||||
|
||||
/*!
|
||||
Build a radial gradient from QPalette::Button
|
||||
like it is used for QDial in various Qt styles.
|
||||
*/
|
||||
Styled
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Marker type
|
||||
|
||||
The marker indicates the current value on the knob
|
||||
The default setting is a Notch marker.
|
||||
|
||||
\sa setMarkerStyle(), setMarkerSize()
|
||||
*/
|
||||
enum MarkerStyle
|
||||
{
|
||||
//! Don't paint any marker
|
||||
NoMarker = -1,
|
||||
|
||||
//! Paint a single tick in QPalette::ButtonText color
|
||||
Tick,
|
||||
|
||||
//! Paint a triangle in QPalette::ButtonText color
|
||||
Triangle,
|
||||
|
||||
//! Paint a circle in QPalette::ButtonText color
|
||||
Dot,
|
||||
|
||||
/*!
|
||||
Draw a raised ellipse with a gradient build from
|
||||
QPalette::Light and QPalette::Mid
|
||||
*/
|
||||
Nub,
|
||||
|
||||
/*!
|
||||
Draw a sunken ellipse with a gradient build from
|
||||
QPalette::Light and QPalette::Mid
|
||||
*/
|
||||
Notch
|
||||
};
|
||||
|
||||
explicit QwtKnob( QWidget* parent = NULL );
|
||||
virtual ~QwtKnob();
|
||||
|
||||
void setAlignment( Qt::Alignment );
|
||||
Qt::Alignment alignment() const;
|
||||
|
||||
void setKnobWidth( int );
|
||||
int knobWidth() const;
|
||||
|
||||
void setNumTurns( int );
|
||||
int numTurns() const;
|
||||
|
||||
void setTotalAngle ( double angle );
|
||||
double totalAngle() const;
|
||||
|
||||
void setKnobStyle( KnobStyle );
|
||||
KnobStyle knobStyle() const;
|
||||
|
||||
void setBorderWidth( int );
|
||||
int borderWidth() const;
|
||||
|
||||
void setMarkerStyle( MarkerStyle );
|
||||
MarkerStyle markerStyle() const;
|
||||
|
||||
void setMarkerSize( int );
|
||||
int markerSize() const;
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
virtual QSize minimumSizeHint() const;
|
||||
|
||||
void setScaleDraw( QwtRoundScaleDraw * );
|
||||
|
||||
const QwtRoundScaleDraw *scaleDraw() const;
|
||||
QwtRoundScaleDraw *scaleDraw();
|
||||
|
||||
QRect knobRect() const;
|
||||
|
||||
protected:
|
||||
virtual void paintEvent( QPaintEvent * );
|
||||
virtual void changeEvent( QEvent * );
|
||||
|
||||
virtual void drawKnob( QPainter *, const QRectF & ) const;
|
||||
|
||||
virtual void drawFocusIndicator( QPainter * ) const;
|
||||
|
||||
virtual void drawMarker( QPainter *,
|
||||
const QRectF &, double angle ) const;
|
||||
|
||||
virtual double scrolledTo( const QPoint & ) const;
|
||||
virtual bool isScrollPosition( const QPoint & ) const;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
827
third/3rd_qwt/qwt_legend.cpp
Normal file
827
third/3rd_qwt/qwt_legend.cpp
Normal file
@@ -0,0 +1,827 @@
|
||||
/* -*- 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_legend.h"
|
||||
#include "qwt_legend_label.h"
|
||||
#include "qwt_dyngrid_layout.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_plot_item.h"
|
||||
#include "qwt_painter.h"
|
||||
#include <qapplication.h>
|
||||
#include <qscrollbar.h>
|
||||
#include <qscrollarea.h>
|
||||
#include <qpainter.h>
|
||||
#include <qstyle.h>
|
||||
#include <qstyleoption.h>
|
||||
|
||||
class QwtLegendMap
|
||||
{
|
||||
public:
|
||||
inline bool isEmpty() const { return d_entries.isEmpty(); }
|
||||
|
||||
void insert( const QVariant &, const QList<QWidget *> & );
|
||||
void remove( const QVariant & );
|
||||
|
||||
void removeWidget( const QWidget * );
|
||||
|
||||
QList<QWidget *> legendWidgets( const QVariant & ) const;
|
||||
QVariant itemInfo( const QWidget * ) const;
|
||||
|
||||
private:
|
||||
// we don't know anything about itemInfo and therefore don't have
|
||||
// any key that can be used for a map or hashtab.
|
||||
// But a simple linear list is o.k. here, as we will never have
|
||||
// more than a few entries.
|
||||
|
||||
class Entry
|
||||
{
|
||||
public:
|
||||
QVariant itemInfo;
|
||||
QList<QWidget *> widgets;
|
||||
};
|
||||
|
||||
QList< Entry > d_entries;
|
||||
};
|
||||
|
||||
void QwtLegendMap::insert( const QVariant &itemInfo,
|
||||
const QList<QWidget *> &widgets )
|
||||
{
|
||||
for ( int i = 0; i < d_entries.size(); i++ )
|
||||
{
|
||||
Entry &entry = d_entries[i];
|
||||
if ( entry.itemInfo == itemInfo )
|
||||
{
|
||||
entry.widgets = widgets;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Entry newEntry;
|
||||
newEntry.itemInfo = itemInfo;
|
||||
newEntry.widgets = widgets;
|
||||
|
||||
d_entries += newEntry;
|
||||
}
|
||||
|
||||
void QwtLegendMap::remove( const QVariant &itemInfo )
|
||||
{
|
||||
for ( int i = 0; i < d_entries.size(); i++ )
|
||||
{
|
||||
Entry &entry = d_entries[i];
|
||||
if ( entry.itemInfo == itemInfo )
|
||||
{
|
||||
d_entries.removeAt( i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QwtLegendMap::removeWidget( const QWidget *widget )
|
||||
{
|
||||
QWidget *w = const_cast<QWidget *>( widget );
|
||||
|
||||
for ( int i = 0; i < d_entries.size(); i++ )
|
||||
d_entries[ i ].widgets.removeAll( w );
|
||||
}
|
||||
|
||||
QVariant QwtLegendMap::itemInfo( const QWidget *widget ) const
|
||||
{
|
||||
if ( widget != NULL )
|
||||
{
|
||||
QWidget *w = const_cast<QWidget *>( widget );
|
||||
|
||||
for ( int i = 0; i < d_entries.size(); i++ )
|
||||
{
|
||||
const Entry &entry = d_entries[i];
|
||||
if ( entry.widgets.indexOf( w ) >= 0 )
|
||||
return entry.itemInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QList<QWidget *> QwtLegendMap::legendWidgets( const QVariant &itemInfo ) const
|
||||
{
|
||||
if ( itemInfo.isValid() )
|
||||
{
|
||||
for ( int i = 0; i < d_entries.size(); i++ )
|
||||
{
|
||||
const Entry &entry = d_entries[i];
|
||||
if ( entry.itemInfo == itemInfo )
|
||||
return entry.widgets;
|
||||
}
|
||||
}
|
||||
|
||||
return QList<QWidget *>();
|
||||
}
|
||||
|
||||
class QwtLegend::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
itemMode( QwtLegendData::ReadOnly ),
|
||||
view( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
QwtLegendData::Mode itemMode;
|
||||
QwtLegendMap itemMap;
|
||||
|
||||
class LegendView;
|
||||
LegendView *view;
|
||||
};
|
||||
|
||||
class QwtLegend::PrivateData::LegendView: public QScrollArea
|
||||
{
|
||||
public:
|
||||
explicit LegendView( QWidget *parent ):
|
||||
QScrollArea( parent )
|
||||
{
|
||||
contentsWidget = new QWidget( this );
|
||||
contentsWidget->setObjectName( "QwtLegendViewContents" );
|
||||
|
||||
setWidget( contentsWidget );
|
||||
setWidgetResizable( false );
|
||||
|
||||
viewport()->setObjectName( "QwtLegendViewport" );
|
||||
|
||||
// QScrollArea::setWidget internally sets autoFillBackground to true
|
||||
// But we don't want a background.
|
||||
contentsWidget->setAutoFillBackground( false );
|
||||
viewport()->setAutoFillBackground( false );
|
||||
}
|
||||
|
||||
virtual bool event( QEvent *event )
|
||||
{
|
||||
if ( event->type() == QEvent::PolishRequest )
|
||||
{
|
||||
setFocusPolicy( Qt::NoFocus );
|
||||
}
|
||||
|
||||
if ( event->type() == QEvent::Resize )
|
||||
{
|
||||
// adjust the size to en/disable the scrollbars
|
||||
// before QScrollArea adjusts the viewport size
|
||||
|
||||
const QRect cr = contentsRect();
|
||||
|
||||
int w = cr.width();
|
||||
int h = contentsWidget->heightForWidth( cr.width() );
|
||||
if ( h > w )
|
||||
{
|
||||
w -= verticalScrollBar()->sizeHint().width();
|
||||
h = contentsWidget->heightForWidth( w );
|
||||
}
|
||||
|
||||
contentsWidget->resize( w, h );
|
||||
}
|
||||
|
||||
return QScrollArea::event( event );
|
||||
}
|
||||
|
||||
virtual bool viewportEvent( QEvent *event )
|
||||
{
|
||||
bool ok = QScrollArea::viewportEvent( event );
|
||||
|
||||
if ( event->type() == QEvent::Resize )
|
||||
{
|
||||
layoutContents();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
QSize viewportSize( int w, int h ) const
|
||||
{
|
||||
const int sbHeight = horizontalScrollBar()->sizeHint().height();
|
||||
const int sbWidth = verticalScrollBar()->sizeHint().width();
|
||||
|
||||
const int cw = contentsRect().width();
|
||||
const int ch = contentsRect().height();
|
||||
|
||||
int vw = cw;
|
||||
int vh = ch;
|
||||
|
||||
if ( w > vw )
|
||||
vh -= sbHeight;
|
||||
|
||||
if ( h > vh )
|
||||
{
|
||||
vw -= sbWidth;
|
||||
if ( w > vw && vh == ch )
|
||||
vh -= sbHeight;
|
||||
}
|
||||
return QSize( vw, vh );
|
||||
}
|
||||
|
||||
void layoutContents()
|
||||
{
|
||||
const QwtDynGridLayout *tl = qobject_cast<QwtDynGridLayout *>(
|
||||
contentsWidget->layout() );
|
||||
if ( tl == NULL )
|
||||
return;
|
||||
|
||||
const QSize visibleSize = viewport()->contentsRect().size();
|
||||
|
||||
const int minW = int( tl->maxItemWidth() ) + 2 * tl->margin();
|
||||
|
||||
int w = qMax( visibleSize.width(), minW );
|
||||
int h = qMax( tl->heightForWidth( w ), visibleSize.height() );
|
||||
|
||||
const int vpWidth = viewportSize( w, h ).width();
|
||||
if ( w > vpWidth )
|
||||
{
|
||||
w = qMax( vpWidth, minW );
|
||||
h = qMax( tl->heightForWidth( w ), visibleSize.height() );
|
||||
}
|
||||
|
||||
contentsWidget->resize( w, h );
|
||||
}
|
||||
|
||||
QWidget *contentsWidget;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
\param parent Parent widget
|
||||
*/
|
||||
QwtLegend::QwtLegend( QWidget *parent ):
|
||||
QwtAbstractLegend( parent )
|
||||
{
|
||||
setFrameStyle( NoFrame );
|
||||
|
||||
d_data = new QwtLegend::PrivateData;
|
||||
|
||||
d_data->view = new QwtLegend::PrivateData::LegendView( this );
|
||||
d_data->view->setObjectName( "QwtLegendView" );
|
||||
d_data->view->setFrameStyle( NoFrame );
|
||||
|
||||
QwtDynGridLayout *gridLayout = new QwtDynGridLayout(
|
||||
d_data->view->contentsWidget );
|
||||
gridLayout->setAlignment( Qt::AlignHCenter | Qt::AlignTop );
|
||||
|
||||
d_data->view->contentsWidget->installEventFilter( this );
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout( this );
|
||||
layout->setContentsMargins( 0, 0, 0, 0 );
|
||||
layout->addWidget( d_data->view );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtLegend::~QwtLegend()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the maximum number of entries in a row
|
||||
|
||||
F.e when the maximum is set to 1 all items are aligned
|
||||
vertically. 0 means unlimited
|
||||
|
||||
\param numColums Maximum number of entries in a row
|
||||
|
||||
\sa maxColumns(), QwtDynGridLayout::setMaxColumns()
|
||||
*/
|
||||
void QwtLegend::setMaxColumns( uint numColums )
|
||||
{
|
||||
QwtDynGridLayout *tl = qobject_cast<QwtDynGridLayout *>(
|
||||
d_data->view->contentsWidget->layout() );
|
||||
if ( tl )
|
||||
tl->setMaxColumns( numColums );
|
||||
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Maximum number of entries in a row
|
||||
\sa setMaxColumns(), QwtDynGridLayout::maxColumns()
|
||||
*/
|
||||
uint QwtLegend::maxColumns() const
|
||||
{
|
||||
uint maxCols = 0;
|
||||
|
||||
const QwtDynGridLayout *tl = qobject_cast<const QwtDynGridLayout *>(
|
||||
d_data->view->contentsWidget->layout() );
|
||||
if ( tl )
|
||||
maxCols = tl->maxColumns();
|
||||
|
||||
return maxCols;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the default mode for legend labels
|
||||
|
||||
Legend labels will be constructed according to the
|
||||
attributes in a QwtLegendData object. When it doesn't
|
||||
contain a value for the QwtLegendData::ModeRole the
|
||||
label will be initialized with the default mode of the legend.
|
||||
|
||||
\param mode Default item mode
|
||||
|
||||
\sa itemMode(), QwtLegendData::value(), QwtPlotItem::legendData()
|
||||
\note Changing the mode doesn't have any effect on existing labels.
|
||||
*/
|
||||
void QwtLegend::setDefaultItemMode( QwtLegendData::Mode mode )
|
||||
{
|
||||
d_data->itemMode = mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Default item mode
|
||||
\sa setDefaultItemMode()
|
||||
*/
|
||||
QwtLegendData::Mode QwtLegend::defaultItemMode() const
|
||||
{
|
||||
return d_data->itemMode;
|
||||
}
|
||||
|
||||
/*!
|
||||
The contents widget is the only child of the viewport of
|
||||
the internal QScrollArea and the parent widget of all legend items.
|
||||
|
||||
\return Container widget of the legend items
|
||||
*/
|
||||
QWidget *QwtLegend::contentsWidget()
|
||||
{
|
||||
return d_data->view->contentsWidget;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Horizontal scrollbar
|
||||
\sa verticalScrollBar()
|
||||
*/
|
||||
QScrollBar *QwtLegend::horizontalScrollBar() const
|
||||
{
|
||||
return d_data->view->horizontalScrollBar();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Vertical scrollbar
|
||||
\sa horizontalScrollBar()
|
||||
*/
|
||||
QScrollBar *QwtLegend::verticalScrollBar() const
|
||||
{
|
||||
return d_data->view->verticalScrollBar();
|
||||
}
|
||||
|
||||
/*!
|
||||
The contents widget is the only child of the viewport of
|
||||
the internal QScrollArea and the parent widget of all legend items.
|
||||
|
||||
\return Container widget of the legend items
|
||||
|
||||
*/
|
||||
const QWidget *QwtLegend::contentsWidget() const
|
||||
{
|
||||
return d_data->view->contentsWidget;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Update the entries for an item
|
||||
|
||||
\param itemInfo Info for an item
|
||||
\param legendData List of legend entry attributes for the item
|
||||
*/
|
||||
void QwtLegend::updateLegend( const QVariant &itemInfo,
|
||||
const QList<QwtLegendData> &legendData )
|
||||
{
|
||||
QList<QWidget *> widgetList = legendWidgets( itemInfo );
|
||||
|
||||
if ( widgetList.size() != legendData.size() )
|
||||
{
|
||||
QLayout *contentsLayout = d_data->view->contentsWidget->layout();
|
||||
|
||||
while ( widgetList.size() > legendData.size() )
|
||||
{
|
||||
QWidget *w = widgetList.takeLast();
|
||||
|
||||
contentsLayout->removeWidget( w );
|
||||
|
||||
// updates might be triggered by signals from the legend widget
|
||||
// itself. So we better don't delete it here.
|
||||
|
||||
w->hide();
|
||||
w->deleteLater();
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x040700
|
||||
widgetList.reserve( legendData.size() );
|
||||
#endif
|
||||
|
||||
for ( int i = widgetList.size(); i < legendData.size(); i++ )
|
||||
{
|
||||
QWidget *widget = createWidget( legendData[i] );
|
||||
|
||||
if ( contentsLayout )
|
||||
contentsLayout->addWidget( widget );
|
||||
|
||||
if ( isVisible() )
|
||||
{
|
||||
// QLayout does a delayed show, with the effect, that
|
||||
// the size hint will be wrong, when applications
|
||||
// call replot() right after changing the list
|
||||
// of plot items. So we better do the show now.
|
||||
|
||||
widget->setVisible( true );
|
||||
}
|
||||
|
||||
widgetList += widget;
|
||||
}
|
||||
|
||||
if ( widgetList.isEmpty() )
|
||||
{
|
||||
d_data->itemMap.remove( itemInfo );
|
||||
}
|
||||
else
|
||||
{
|
||||
d_data->itemMap.insert( itemInfo, widgetList );
|
||||
}
|
||||
|
||||
updateTabOrder();
|
||||
}
|
||||
|
||||
for ( int i = 0; i < legendData.size(); i++ )
|
||||
updateWidget( widgetList[i], legendData[i] );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Create a widget to be inserted into the legend
|
||||
|
||||
The default implementation returns a QwtLegendLabel.
|
||||
|
||||
\param legendData Attributes of the legend entry
|
||||
\return Widget representing data on the legend
|
||||
|
||||
\note updateWidget() will called soon after createWidget()
|
||||
with the same attributes.
|
||||
*/
|
||||
QWidget *QwtLegend::createWidget( const QwtLegendData &legendData ) const
|
||||
{
|
||||
Q_UNUSED( legendData );
|
||||
|
||||
QwtLegendLabel *label = new QwtLegendLabel();
|
||||
label->setItemMode( defaultItemMode() );
|
||||
|
||||
connect( label, SIGNAL(clicked()), SLOT(itemClicked()) );
|
||||
connect( label, SIGNAL(checked(bool)), SLOT(itemChecked(bool)) );
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Update the widget
|
||||
|
||||
\param widget Usually a QwtLegendLabel
|
||||
\param legendData Attributes to be displayed
|
||||
|
||||
\sa createWidget()
|
||||
\note When widget is no QwtLegendLabel updateWidget() does nothing.
|
||||
*/
|
||||
void QwtLegend::updateWidget( QWidget *widget, const QwtLegendData &legendData )
|
||||
{
|
||||
QwtLegendLabel *label = qobject_cast<QwtLegendLabel *>( widget );
|
||||
if ( label )
|
||||
{
|
||||
label->setData( legendData );
|
||||
if ( !legendData.value( QwtLegendData::ModeRole ).isValid() )
|
||||
{
|
||||
// use the default mode, when there is no specific
|
||||
// hint from the legend data
|
||||
|
||||
label->setItemMode( defaultItemMode() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QwtLegend::updateTabOrder()
|
||||
{
|
||||
QLayout *contentsLayout = d_data->view->contentsWidget->layout();
|
||||
if ( contentsLayout )
|
||||
{
|
||||
// set tab focus chain
|
||||
|
||||
QWidget *w = NULL;
|
||||
|
||||
for ( int i = 0; i < contentsLayout->count(); i++ )
|
||||
{
|
||||
QLayoutItem *item = contentsLayout->itemAt( i );
|
||||
if ( w && item->widget() )
|
||||
QWidget::setTabOrder( w, item->widget() );
|
||||
|
||||
w = item->widget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Return a size hint.
|
||||
QSize QwtLegend::sizeHint() const
|
||||
{
|
||||
QSize hint = d_data->view->contentsWidget->sizeHint();
|
||||
hint += QSize( 2 * frameWidth(), 2 * frameWidth() );
|
||||
|
||||
return hint;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The preferred height, for a width.
|
||||
\param width Width
|
||||
*/
|
||||
int QwtLegend::heightForWidth( int width ) const
|
||||
{
|
||||
width -= 2 * frameWidth();
|
||||
|
||||
int h = d_data->view->contentsWidget->heightForWidth( width );
|
||||
if ( h >= 0 )
|
||||
h += 2 * frameWidth();
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Handle QEvent::ChildRemoved andQEvent::LayoutRequest events
|
||||
for the contentsWidget().
|
||||
|
||||
\param object Object to be filtered
|
||||
\param event Event
|
||||
|
||||
\return Forwarded to QwtAbstractLegend::eventFilter()
|
||||
*/
|
||||
bool QwtLegend::eventFilter( QObject *object, QEvent *event )
|
||||
{
|
||||
if ( object == d_data->view->contentsWidget )
|
||||
{
|
||||
switch ( event->type() )
|
||||
{
|
||||
case QEvent::ChildRemoved:
|
||||
{
|
||||
const QChildEvent *ce =
|
||||
static_cast<const QChildEvent *>(event);
|
||||
|
||||
if ( ce->child()->isWidgetType() )
|
||||
{
|
||||
/*
|
||||
We are called from the ~QObject and ce->child() is
|
||||
no widget anymore. But all we need is the address
|
||||
to remove it from the map.
|
||||
*/
|
||||
QWidget *w = reinterpret_cast< QWidget * >( ce->child() );
|
||||
d_data->itemMap.removeWidget( w );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::LayoutRequest:
|
||||
{
|
||||
d_data->view->layoutContents();
|
||||
|
||||
if ( parentWidget() && parentWidget()->layout() == NULL )
|
||||
{
|
||||
/*
|
||||
We want the parent widget ( usually QwtPlot ) to recalculate
|
||||
its layout, when the contentsWidget has changed. But
|
||||
because of the scroll view we have to forward the LayoutRequest
|
||||
event manually.
|
||||
|
||||
We don't use updateGeometry() because it doesn't post LayoutRequest
|
||||
events when the legend is hidden. But we want the
|
||||
parent widget notified, so it can show/hide the legend
|
||||
depending on its items.
|
||||
*/
|
||||
QApplication::postEvent( parentWidget(),
|
||||
new QEvent( QEvent::LayoutRequest ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QwtAbstractLegend::eventFilter( object, event );
|
||||
}
|
||||
|
||||
/*!
|
||||
Called internally when the legend has been clicked on.
|
||||
Emits a clicked() signal.
|
||||
*/
|
||||
void QwtLegend::itemClicked()
|
||||
{
|
||||
QWidget *w = qobject_cast<QWidget *>( sender() );
|
||||
if ( w )
|
||||
{
|
||||
const QVariant itemInfo = d_data->itemMap.itemInfo( w );
|
||||
if ( itemInfo.isValid() )
|
||||
{
|
||||
const QList<QWidget *> widgetList =
|
||||
d_data->itemMap.legendWidgets( itemInfo );
|
||||
|
||||
const int index = widgetList.indexOf( w );
|
||||
if ( index >= 0 )
|
||||
Q_EMIT clicked( itemInfo, index );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Called internally when the legend has been checked
|
||||
Emits a checked() signal.
|
||||
*/
|
||||
void QwtLegend::itemChecked( bool on )
|
||||
{
|
||||
QWidget *w = qobject_cast<QWidget *>( sender() );
|
||||
if ( w )
|
||||
{
|
||||
const QVariant itemInfo = d_data->itemMap.itemInfo( w );
|
||||
if ( itemInfo.isValid() )
|
||||
{
|
||||
const QList<QWidget *> widgetList =
|
||||
d_data->itemMap.legendWidgets( itemInfo );
|
||||
|
||||
const int index = widgetList.indexOf( w );
|
||||
if ( index >= 0 )
|
||||
Q_EMIT checked( itemInfo, on, index );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Render the legend into a given rectangle.
|
||||
|
||||
\param painter Painter
|
||||
\param rect Bounding rectangle
|
||||
\param fillBackground When true, fill rect with the widget background
|
||||
|
||||
\sa renderLegend() is used by QwtPlotRenderer - not by QwtLegend itself
|
||||
*/
|
||||
void QwtLegend::renderLegend( QPainter *painter,
|
||||
const QRectF &rect, bool fillBackground ) const
|
||||
{
|
||||
if ( d_data->itemMap.isEmpty() )
|
||||
return;
|
||||
|
||||
if ( fillBackground )
|
||||
{
|
||||
if ( autoFillBackground() ||
|
||||
testAttribute( Qt::WA_StyledBackground ) )
|
||||
{
|
||||
QwtPainter::drawBackgound( painter, rect, this );
|
||||
}
|
||||
}
|
||||
|
||||
const QwtDynGridLayout *legendLayout =
|
||||
qobject_cast<QwtDynGridLayout *>( contentsWidget()->layout() );
|
||||
if ( legendLayout == NULL )
|
||||
return;
|
||||
|
||||
int left, right, top, bottom;
|
||||
getContentsMargins( &left, &top, &right, &bottom );
|
||||
|
||||
QRect layoutRect;
|
||||
layoutRect.setLeft( qCeil( rect.left() ) + left );
|
||||
layoutRect.setTop( qCeil( rect.top() ) + top );
|
||||
layoutRect.setRight( qFloor( rect.right() ) - right );
|
||||
layoutRect.setBottom( qFloor( rect.bottom() ) - bottom );
|
||||
|
||||
uint numCols = legendLayout->columnsForWidth( layoutRect.width() );
|
||||
const QList<QRect> itemRects =
|
||||
legendLayout->layoutItems( layoutRect, numCols );
|
||||
|
||||
int index = 0;
|
||||
|
||||
for ( int i = 0; i < legendLayout->count(); i++ )
|
||||
{
|
||||
QLayoutItem *item = legendLayout->itemAt( i );
|
||||
QWidget *w = item->widget();
|
||||
if ( w )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->setClipRect( itemRects[index], Qt::IntersectClip );
|
||||
renderItem( painter, w, itemRects[index], fillBackground );
|
||||
|
||||
index++;
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Render a legend entry into a given rectangle.
|
||||
|
||||
\param painter Painter
|
||||
\param widget Widget representing a legend entry
|
||||
\param rect Bounding rectangle
|
||||
\param fillBackground When true, fill rect with the widget background
|
||||
|
||||
\note When widget is not derived from QwtLegendLabel renderItem
|
||||
does nothing beside the background
|
||||
*/
|
||||
void QwtLegend::renderItem( QPainter *painter,
|
||||
const QWidget *widget, const QRectF &rect, bool fillBackground ) const
|
||||
{
|
||||
if ( fillBackground )
|
||||
{
|
||||
if ( widget->autoFillBackground() ||
|
||||
widget->testAttribute( Qt::WA_StyledBackground ) )
|
||||
{
|
||||
QwtPainter::drawBackgound( painter, rect, widget );
|
||||
}
|
||||
}
|
||||
|
||||
const QwtLegendLabel *label = qobject_cast<const QwtLegendLabel *>( widget );
|
||||
if ( label )
|
||||
{
|
||||
// icon
|
||||
|
||||
const QwtGraphic &icon = label->data().icon();
|
||||
const QSizeF sz = icon.defaultSize();
|
||||
|
||||
const QRectF iconRect( rect.x() + label->margin(),
|
||||
rect.center().y() - 0.5 * sz.height(),
|
||||
sz.width(), sz.height() );
|
||||
|
||||
icon.render( painter, iconRect, Qt::KeepAspectRatio );
|
||||
|
||||
// title
|
||||
|
||||
QRectF titleRect = rect;
|
||||
titleRect.setX( iconRect.right() + 2 * label->spacing() );
|
||||
|
||||
QFont labelFont = label->font();
|
||||
labelFont.resolve( QFont::AllPropertiesResolved );
|
||||
|
||||
painter->setFont( labelFont );
|
||||
painter->setPen( label->palette().color( QPalette::Text ) );
|
||||
|
||||
const_cast< QwtLegendLabel *>( label )->drawText( painter, titleRect );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return List of widgets associated to a item
|
||||
\param itemInfo Info about an item
|
||||
\sa legendWidget(), itemInfo(), QwtPlot::itemToInfo()
|
||||
*/
|
||||
QList<QWidget *> QwtLegend::legendWidgets( const QVariant &itemInfo ) const
|
||||
{
|
||||
return d_data->itemMap.legendWidgets( itemInfo );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return First widget in the list of widgets associated to an item
|
||||
\param itemInfo Info about an item
|
||||
\sa itemInfo(), QwtPlot::itemToInfo()
|
||||
\note Almost all types of items have only one widget
|
||||
*/
|
||||
QWidget *QwtLegend::legendWidget( const QVariant &itemInfo ) const
|
||||
{
|
||||
const QList<QWidget *> list = d_data->itemMap.legendWidgets( itemInfo );
|
||||
if ( list.isEmpty() )
|
||||
return NULL;
|
||||
|
||||
return list[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Find the item that is associated to a widget
|
||||
|
||||
\param widget Widget on the legend
|
||||
\return Associated item info
|
||||
\sa legendWidget()
|
||||
*/
|
||||
QVariant QwtLegend::itemInfo( const QWidget *widget ) const
|
||||
{
|
||||
return d_data->itemMap.itemInfo( widget );
|
||||
}
|
||||
|
||||
//! \return True, when no item is inserted
|
||||
bool QwtLegend::isEmpty() const
|
||||
{
|
||||
return d_data->itemMap.isEmpty();
|
||||
}
|
||||
|
||||
/*!
|
||||
Return the extent, that is needed for the scrollbars
|
||||
|
||||
\param orientation Orientation
|
||||
\return The width of the vertical scrollbar for Qt::Horizontal and v.v.
|
||||
*/
|
||||
int QwtLegend::scrollExtent( Qt::Orientation orientation ) const
|
||||
{
|
||||
int extent = 0;
|
||||
|
||||
if ( orientation == Qt::Horizontal )
|
||||
extent = verticalScrollBar()->sizeHint().width();
|
||||
else
|
||||
extent = horizontalScrollBar()->sizeHint().height();
|
||||
|
||||
return extent;
|
||||
}
|
||||
|
||||
117
third/3rd_qwt/qwt_legend.h
Normal file
117
third/3rd_qwt/qwt_legend.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_LEGEND_H
|
||||
#define QWT_LEGEND_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_abstract_legend.h"
|
||||
#include <qvariant.h>
|
||||
|
||||
class QScrollBar;
|
||||
|
||||
/*!
|
||||
\brief The legend widget
|
||||
|
||||
The QwtLegend widget is a tabular arrangement of legend items. Legend
|
||||
items might be any type of widget, but in general they will be
|
||||
a QwtLegendLabel.
|
||||
|
||||
\sa QwtLegendLabel, QwtPlotItem, QwtPlot
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtLegend : public QwtAbstractLegend
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QwtLegend( QWidget *parent = NULL );
|
||||
virtual ~QwtLegend();
|
||||
|
||||
void setMaxColumns( uint numColums );
|
||||
uint maxColumns() const;
|
||||
|
||||
void setDefaultItemMode( QwtLegendData::Mode );
|
||||
QwtLegendData::Mode defaultItemMode() const;
|
||||
|
||||
QWidget *contentsWidget();
|
||||
const QWidget *contentsWidget() const;
|
||||
|
||||
QWidget *legendWidget( const QVariant & ) const;
|
||||
QList<QWidget *> legendWidgets( const QVariant & ) const;
|
||||
|
||||
QVariant itemInfo( const QWidget * ) const;
|
||||
|
||||
virtual bool eventFilter( QObject *, QEvent * );
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
virtual int heightForWidth( int width ) const;
|
||||
|
||||
QScrollBar *horizontalScrollBar() const;
|
||||
QScrollBar *verticalScrollBar() const;
|
||||
|
||||
virtual void renderLegend( QPainter *,
|
||||
const QRectF &, bool fillBackground ) const;
|
||||
|
||||
virtual void renderItem( QPainter *,
|
||||
const QWidget *, const QRectF &, bool fillBackground ) const;
|
||||
|
||||
virtual bool isEmpty() const;
|
||||
virtual int scrollExtent( Qt::Orientation ) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/*!
|
||||
A signal which is emitted when the user has clicked on
|
||||
a legend label, which is in QwtLegendData::Clickable mode.
|
||||
|
||||
\param itemInfo Info for the item item of the
|
||||
selected legend item
|
||||
\param index Index of the legend label in the list of widgets
|
||||
that are associated with the plot item
|
||||
|
||||
\note clicks are disabled as default
|
||||
\sa setDefaultItemMode(), defaultItemMode(), QwtPlot::itemToInfo()
|
||||
*/
|
||||
void clicked( const QVariant &itemInfo, int index );
|
||||
|
||||
/*!
|
||||
A signal which is emitted when the user has clicked on
|
||||
a legend label, which is in QwtLegendData::Checkable mode
|
||||
|
||||
\param itemInfo Info for the item of the
|
||||
selected legend label
|
||||
\param index Index of the legend label in the list of widgets
|
||||
that are associated with the plot item
|
||||
\param on True when the legend label is checked
|
||||
|
||||
\note clicks are disabled as default
|
||||
\sa setDefaultItemMode(), defaultItemMode(), QwtPlot::itemToInfo()
|
||||
*/
|
||||
void checked( const QVariant &itemInfo, bool on, int index );
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual void updateLegend( const QVariant &,
|
||||
const QList<QwtLegendData> & );
|
||||
|
||||
protected Q_SLOTS:
|
||||
void itemClicked();
|
||||
void itemChecked( bool );
|
||||
|
||||
protected:
|
||||
virtual QWidget *createWidget( const QwtLegendData & ) const;
|
||||
virtual void updateWidget( QWidget *widget, const QwtLegendData & );
|
||||
|
||||
private:
|
||||
void updateTabOrder();
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
129
third/3rd_qwt/qwt_legend_data.cpp
Normal file
129
third/3rd_qwt/qwt_legend_data.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
/* -*- 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_legend_data.h"
|
||||
|
||||
//! Constructor
|
||||
QwtLegendData::QwtLegendData()
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtLegendData::~QwtLegendData()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the legend attributes
|
||||
|
||||
QwtLegendData actually is a QMap<int, QVariant> with some
|
||||
convenience interfaces
|
||||
|
||||
\param map Values
|
||||
\sa values()
|
||||
*/
|
||||
void QwtLegendData::setValues( const QMap<int, QVariant> &map )
|
||||
{
|
||||
d_map = map;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Legend attributes
|
||||
\sa setValues()
|
||||
*/
|
||||
const QMap<int, QVariant> &QwtLegendData::values() const
|
||||
{
|
||||
return d_map;
|
||||
}
|
||||
|
||||
/*!
|
||||
\param role Attribute role
|
||||
\return True, when the internal map has an entry for role
|
||||
*/
|
||||
bool QwtLegendData::hasRole( int role ) const
|
||||
{
|
||||
return d_map.contains( role );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set an attribute value
|
||||
|
||||
\param role Attribute role
|
||||
\param data Attribute value
|
||||
|
||||
\sa value()
|
||||
*/
|
||||
void QwtLegendData::setValue( int role, const QVariant &data )
|
||||
{
|
||||
d_map[role] = data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\param role Attribute role
|
||||
\return Attribute value for a specific role
|
||||
*/
|
||||
QVariant QwtLegendData::value( int role ) const
|
||||
{
|
||||
if ( !d_map.contains( role ) )
|
||||
return QVariant();
|
||||
|
||||
return d_map[role];
|
||||
}
|
||||
|
||||
//! \return True, when the internal map is empty
|
||||
bool QwtLegendData::isValid() const
|
||||
{
|
||||
return !d_map.isEmpty();
|
||||
}
|
||||
|
||||
//! \return Value of the TitleRole attribute
|
||||
QwtText QwtLegendData::title() const
|
||||
{
|
||||
QwtText text;
|
||||
|
||||
const QVariant titleValue = value( QwtLegendData::TitleRole );
|
||||
if ( titleValue.canConvert<QwtText>() )
|
||||
{
|
||||
text = qvariant_cast<QwtText>( titleValue );
|
||||
}
|
||||
else if ( titleValue.canConvert<QString>() )
|
||||
{
|
||||
text.setText( qvariant_cast<QString>( titleValue ) );
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
//! \return Value of the IconRole attribute
|
||||
QwtGraphic QwtLegendData::icon() const
|
||||
{
|
||||
const QVariant iconValue = value( QwtLegendData::IconRole );
|
||||
|
||||
QwtGraphic graphic;
|
||||
if ( iconValue.canConvert<QwtGraphic>() )
|
||||
{
|
||||
graphic = qvariant_cast<QwtGraphic>( iconValue );
|
||||
}
|
||||
|
||||
return graphic;
|
||||
}
|
||||
|
||||
//! \return Value of the ModeRole attribute
|
||||
QwtLegendData::Mode QwtLegendData::mode() const
|
||||
{
|
||||
const QVariant modeValue = value( QwtLegendData::ModeRole );
|
||||
if ( modeValue.canConvert<int>() )
|
||||
{
|
||||
const int mode = qvariant_cast<int>( modeValue );
|
||||
return static_cast<QwtLegendData::Mode>( mode );
|
||||
}
|
||||
|
||||
return QwtLegendData::ReadOnly;
|
||||
}
|
||||
|
||||
87
third/3rd_qwt/qwt_legend_data.h
Normal file
87
third/3rd_qwt/qwt_legend_data.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_LEGEND_DATA_H
|
||||
#define QWT_LEGEND_DATA_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_text.h"
|
||||
#include "qwt_graphic.h"
|
||||
#include <qvariant.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qmap.h>
|
||||
|
||||
/*!
|
||||
\brief Attributes of an entry on a legend
|
||||
|
||||
QwtLegendData is an abstract container ( like QAbstractModel )
|
||||
to exchange attributes, that are only known between to
|
||||
the plot item and the legend.
|
||||
|
||||
By overloading QwtPlotItem::legendData() any other set of attributes
|
||||
could be used, that can be handled by a modified ( or completely
|
||||
different ) implementation of a legend.
|
||||
|
||||
\sa QwtLegend, QwtPlotLegendItem
|
||||
\note The stockchart example implements a legend as a tree
|
||||
with checkable items
|
||||
*/
|
||||
class QWT_EXPORT QwtLegendData
|
||||
{
|
||||
public:
|
||||
//! Mode defining how a legend entry interacts
|
||||
enum Mode
|
||||
{
|
||||
//! The legend item is not interactive, like a label
|
||||
ReadOnly,
|
||||
|
||||
//! The legend item is clickable, like a push button
|
||||
Clickable,
|
||||
|
||||
//! The legend item is checkable, like a checkable button
|
||||
Checkable
|
||||
};
|
||||
|
||||
//! Identifier how to interprete a QVariant
|
||||
enum Role
|
||||
{
|
||||
// The value is a Mode
|
||||
ModeRole,
|
||||
|
||||
// The value is a title
|
||||
TitleRole,
|
||||
|
||||
// The value is an icon
|
||||
IconRole,
|
||||
|
||||
// Values < UserRole are reserved for internal use
|
||||
UserRole = 32
|
||||
};
|
||||
|
||||
QwtLegendData();
|
||||
~QwtLegendData();
|
||||
|
||||
void setValues( const QMap<int, QVariant> & );
|
||||
const QMap<int, QVariant> &values() const;
|
||||
|
||||
void setValue( int role, const QVariant & );
|
||||
QVariant value( int role ) const;
|
||||
|
||||
bool hasRole( int role ) const;
|
||||
bool isValid() const;
|
||||
|
||||
QwtGraphic icon() const;
|
||||
QwtText title() const;
|
||||
Mode mode() const;
|
||||
|
||||
private:
|
||||
QMap<int, QVariant> d_map;
|
||||
};
|
||||
|
||||
#endif
|
||||
421
third/3rd_qwt/qwt_legend_label.cpp
Normal file
421
third/3rd_qwt/qwt_legend_label.cpp
Normal file
@@ -0,0 +1,421 @@
|
||||
/* -*- 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_legend_label.h"
|
||||
#include "qwt_legend_data.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_painter.h"
|
||||
#include "qwt_symbol.h"
|
||||
#include "qwt_graphic.h"
|
||||
#include <qpainter.h>
|
||||
#include <qdrawutil.h>
|
||||
#include <qstyle.h>
|
||||
#include <qpen.h>
|
||||
#include <qevent.h>
|
||||
#include <qstyleoption.h>
|
||||
#include <qapplication.h>
|
||||
|
||||
static const int ButtonFrame = 2;
|
||||
static const int Margin = 2;
|
||||
|
||||
static QSize buttonShift( const QwtLegendLabel *w )
|
||||
{
|
||||
QStyleOption option;
|
||||
option.init( w );
|
||||
|
||||
const int ph = w->style()->pixelMetric(
|
||||
QStyle::PM_ButtonShiftHorizontal, &option, w );
|
||||
const int pv = w->style()->pixelMetric(
|
||||
QStyle::PM_ButtonShiftVertical, &option, w );
|
||||
return QSize( ph, pv );
|
||||
}
|
||||
|
||||
class QwtLegendLabel::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
itemMode( QwtLegendData::ReadOnly ),
|
||||
isDown( false ),
|
||||
spacing( Margin )
|
||||
{
|
||||
}
|
||||
|
||||
QwtLegendData::Mode itemMode;
|
||||
QwtLegendData legendData;
|
||||
bool isDown;
|
||||
|
||||
QPixmap icon;
|
||||
|
||||
int spacing;
|
||||
};
|
||||
|
||||
/*!
|
||||
Set the attributes of the legend label
|
||||
|
||||
\param legendData Attributes of the label
|
||||
\sa data()
|
||||
*/
|
||||
void QwtLegendLabel::setData( const QwtLegendData &legendData )
|
||||
{
|
||||
d_data->legendData = legendData;
|
||||
|
||||
const bool doUpdate = updatesEnabled();
|
||||
setUpdatesEnabled( false );
|
||||
|
||||
setText( legendData.title() );
|
||||
setIcon( legendData.icon().toPixmap() );
|
||||
|
||||
if ( legendData.hasRole( QwtLegendData::ModeRole ) )
|
||||
setItemMode( legendData.mode() );
|
||||
|
||||
if ( doUpdate )
|
||||
{
|
||||
setUpdatesEnabled( true );
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Attributes of the label
|
||||
\sa setData(), QwtPlotItem::legendData()
|
||||
*/
|
||||
const QwtLegendData &QwtLegendLabel::data() const
|
||||
{
|
||||
return d_data->legendData;
|
||||
}
|
||||
|
||||
/*!
|
||||
\param parent Parent widget
|
||||
*/
|
||||
QwtLegendLabel::QwtLegendLabel( QWidget *parent ):
|
||||
QwtTextLabel( parent )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
setMargin( Margin );
|
||||
setIndent( Margin );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtLegendLabel::~QwtLegendLabel()
|
||||
{
|
||||
delete d_data;
|
||||
d_data = NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the text to the legend item
|
||||
|
||||
\param text Text label
|
||||
\sa QwtTextLabel::text()
|
||||
*/
|
||||
void QwtLegendLabel::setText( const QwtText &text )
|
||||
{
|
||||
const int flags = Qt::AlignLeft | Qt::AlignVCenter
|
||||
| Qt::TextExpandTabs | Qt::TextWordWrap;
|
||||
|
||||
QwtText txt = text;
|
||||
txt.setRenderFlags( flags );
|
||||
|
||||
QwtTextLabel::setText( txt );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the item mode
|
||||
The default is QwtLegendData::ReadOnly
|
||||
|
||||
\param mode Item mode
|
||||
\sa itemMode()
|
||||
*/
|
||||
void QwtLegendLabel::setItemMode( QwtLegendData::Mode mode )
|
||||
{
|
||||
if ( mode != d_data->itemMode )
|
||||
{
|
||||
d_data->itemMode = mode;
|
||||
d_data->isDown = false;
|
||||
|
||||
setFocusPolicy( ( mode != QwtLegendData::ReadOnly )
|
||||
? Qt::TabFocus : Qt::NoFocus );
|
||||
setMargin( ButtonFrame + Margin );
|
||||
|
||||
updateGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Item mode
|
||||
\sa setItemMode()
|
||||
*/
|
||||
QwtLegendData::Mode QwtLegendLabel::itemMode() const
|
||||
{
|
||||
return d_data->itemMode;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign the icon
|
||||
|
||||
\param icon Pixmap representing a plot item
|
||||
|
||||
\sa icon(), QwtPlotItem::legendIcon()
|
||||
*/
|
||||
void QwtLegendLabel::setIcon( const QPixmap &icon )
|
||||
{
|
||||
d_data->icon = icon;
|
||||
|
||||
int indent = margin() + d_data->spacing;
|
||||
if ( icon.width() > 0 )
|
||||
indent += icon.width() + d_data->spacing;
|
||||
|
||||
setIndent( indent );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Pixmap representing a plot item
|
||||
\sa setIcon()
|
||||
*/
|
||||
QPixmap QwtLegendLabel::icon() const
|
||||
{
|
||||
return d_data->icon;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the spacing between icon and text
|
||||
|
||||
\param spacing Spacing
|
||||
\sa spacing(), QwtTextLabel::margin()
|
||||
*/
|
||||
void QwtLegendLabel::setSpacing( int spacing )
|
||||
{
|
||||
spacing = qMax( spacing, 0 );
|
||||
if ( spacing != d_data->spacing )
|
||||
{
|
||||
d_data->spacing = spacing;
|
||||
|
||||
int indent = margin() + d_data->spacing;
|
||||
if ( d_data->icon.width() > 0 )
|
||||
indent += d_data->icon.width() + d_data->spacing;
|
||||
|
||||
setIndent( indent );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Spacing between icon and text
|
||||
\sa setSpacing(), QwtTextLabel::margin()
|
||||
*/
|
||||
int QwtLegendLabel::spacing() const
|
||||
{
|
||||
return d_data->spacing;
|
||||
}
|
||||
|
||||
/*!
|
||||
Check/Uncheck a the item
|
||||
|
||||
\param on check/uncheck
|
||||
\sa setItemMode()
|
||||
*/
|
||||
void QwtLegendLabel::setChecked( bool on )
|
||||
{
|
||||
if ( d_data->itemMode == QwtLegendData::Checkable )
|
||||
{
|
||||
const bool isBlocked = signalsBlocked();
|
||||
blockSignals( true );
|
||||
|
||||
setDown( on );
|
||||
|
||||
blockSignals( isBlocked );
|
||||
}
|
||||
}
|
||||
|
||||
//! Return true, if the item is checked
|
||||
bool QwtLegendLabel::isChecked() const
|
||||
{
|
||||
return d_data->itemMode == QwtLegendData::Checkable && isDown();
|
||||
}
|
||||
|
||||
//! Set the item being down
|
||||
void QwtLegendLabel::setDown( bool down )
|
||||
{
|
||||
if ( down == d_data->isDown )
|
||||
return;
|
||||
|
||||
d_data->isDown = down;
|
||||
update();
|
||||
|
||||
if ( d_data->itemMode == QwtLegendData::Clickable )
|
||||
{
|
||||
if ( d_data->isDown )
|
||||
Q_EMIT pressed();
|
||||
else
|
||||
{
|
||||
Q_EMIT released();
|
||||
Q_EMIT clicked();
|
||||
}
|
||||
}
|
||||
|
||||
if ( d_data->itemMode == QwtLegendData::Checkable )
|
||||
Q_EMIT checked( d_data->isDown );
|
||||
}
|
||||
|
||||
//! Return true, if the item is down
|
||||
bool QwtLegendLabel::isDown() const
|
||||
{
|
||||
return d_data->isDown;
|
||||
}
|
||||
|
||||
//! Return a size hint
|
||||
QSize QwtLegendLabel::sizeHint() const
|
||||
{
|
||||
QSize sz = QwtTextLabel::sizeHint();
|
||||
sz.setHeight( qMax( sz.height(), d_data->icon.height() + 4 ) );
|
||||
|
||||
if ( d_data->itemMode != QwtLegendData::ReadOnly )
|
||||
{
|
||||
sz += buttonShift( this );
|
||||
sz = sz.expandedTo( QApplication::globalStrut() );
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
//! Paint event
|
||||
void QwtLegendLabel::paintEvent( QPaintEvent *e )
|
||||
{
|
||||
const QRect cr = contentsRect();
|
||||
|
||||
QPainter painter( this );
|
||||
painter.setClipRegion( e->region() );
|
||||
|
||||
if ( d_data->isDown )
|
||||
{
|
||||
qDrawWinButton( &painter, 0, 0, width(), height(),
|
||||
palette(), true );
|
||||
}
|
||||
|
||||
painter.save();
|
||||
|
||||
if ( d_data->isDown )
|
||||
{
|
||||
const QSize shiftSize = buttonShift( this );
|
||||
painter.translate( shiftSize.width(), shiftSize.height() );
|
||||
}
|
||||
|
||||
painter.setClipRect( cr );
|
||||
|
||||
drawContents( &painter );
|
||||
|
||||
if ( !d_data->icon.isNull() )
|
||||
{
|
||||
QRect iconRect = cr;
|
||||
iconRect.setX( iconRect.x() + margin() );
|
||||
if ( d_data->itemMode != QwtLegendData::ReadOnly )
|
||||
iconRect.setX( iconRect.x() + ButtonFrame );
|
||||
|
||||
iconRect.setSize( d_data->icon.size() );
|
||||
iconRect.moveCenter( QPoint( iconRect.center().x(), cr.center().y() ) );
|
||||
|
||||
painter.drawPixmap( iconRect, d_data->icon );
|
||||
}
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
//! Handle mouse press events
|
||||
void QwtLegendLabel::mousePressEvent( QMouseEvent *e )
|
||||
{
|
||||
if ( e->button() == Qt::LeftButton )
|
||||
{
|
||||
switch ( d_data->itemMode )
|
||||
{
|
||||
case QwtLegendData::Clickable:
|
||||
{
|
||||
setDown( true );
|
||||
return;
|
||||
}
|
||||
case QwtLegendData::Checkable:
|
||||
{
|
||||
setDown( !isDown() );
|
||||
return;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
QwtTextLabel::mousePressEvent( e );
|
||||
}
|
||||
|
||||
//! Handle mouse release events
|
||||
void QwtLegendLabel::mouseReleaseEvent( QMouseEvent *e )
|
||||
{
|
||||
if ( e->button() == Qt::LeftButton )
|
||||
{
|
||||
switch ( d_data->itemMode )
|
||||
{
|
||||
case QwtLegendData::Clickable:
|
||||
{
|
||||
setDown( false );
|
||||
return;
|
||||
}
|
||||
case QwtLegendData::Checkable:
|
||||
{
|
||||
return; // do nothing, but accept
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
QwtTextLabel::mouseReleaseEvent( e );
|
||||
}
|
||||
|
||||
//! Handle key press events
|
||||
void QwtLegendLabel::keyPressEvent( QKeyEvent *e )
|
||||
{
|
||||
if ( e->key() == Qt::Key_Space )
|
||||
{
|
||||
switch ( d_data->itemMode )
|
||||
{
|
||||
case QwtLegendData::Clickable:
|
||||
{
|
||||
if ( !e->isAutoRepeat() )
|
||||
setDown( true );
|
||||
return;
|
||||
}
|
||||
case QwtLegendData::Checkable:
|
||||
{
|
||||
if ( !e->isAutoRepeat() )
|
||||
setDown( !isDown() );
|
||||
return;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
QwtTextLabel::keyPressEvent( e );
|
||||
}
|
||||
|
||||
//! Handle key release events
|
||||
void QwtLegendLabel::keyReleaseEvent( QKeyEvent *e )
|
||||
{
|
||||
if ( e->key() == Qt::Key_Space )
|
||||
{
|
||||
switch ( d_data->itemMode )
|
||||
{
|
||||
case QwtLegendData::Clickable:
|
||||
{
|
||||
if ( !e->isAutoRepeat() )
|
||||
setDown( false );
|
||||
return;
|
||||
}
|
||||
case QwtLegendData::Checkable:
|
||||
{
|
||||
return; // do nothing, but accept
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
QwtTextLabel::keyReleaseEvent( e );
|
||||
}
|
||||
80
third/3rd_qwt/qwt_legend_label.h
Normal file
80
third/3rd_qwt/qwt_legend_label.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_LEGEND_LABEL_H
|
||||
#define QWT_LEGEND_LABEL_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_legend_data.h"
|
||||
#include "qwt_text.h"
|
||||
#include "qwt_text_label.h"
|
||||
#include <qpixmap.h>
|
||||
|
||||
class QwtLegendData;
|
||||
|
||||
/*!
|
||||
\brief A widget representing something on a QwtLegend.
|
||||
*/
|
||||
class QWT_EXPORT QwtLegendLabel: public QwtTextLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QwtLegendLabel( QWidget *parent = 0 );
|
||||
virtual ~QwtLegendLabel();
|
||||
|
||||
void setData( const QwtLegendData & );
|
||||
const QwtLegendData &data() const;
|
||||
|
||||
void setItemMode( QwtLegendData::Mode );
|
||||
QwtLegendData::Mode itemMode() const;
|
||||
|
||||
void setSpacing( int spacing );
|
||||
int spacing() const;
|
||||
|
||||
virtual void setText( const QwtText & );
|
||||
|
||||
void setIcon( const QPixmap & );
|
||||
QPixmap icon() const;
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
bool isChecked() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setChecked( bool on );
|
||||
|
||||
Q_SIGNALS:
|
||||
//! Signal, when the legend item has been clicked
|
||||
void clicked();
|
||||
|
||||
//! Signal, when the legend item has been pressed
|
||||
void pressed();
|
||||
|
||||
//! Signal, when the legend item has been released
|
||||
void released();
|
||||
|
||||
//! Signal, when the legend item has been toggled
|
||||
void checked( bool );
|
||||
|
||||
protected:
|
||||
void setDown( bool );
|
||||
bool isDown() const;
|
||||
|
||||
virtual void paintEvent( QPaintEvent * );
|
||||
virtual void mousePressEvent( QMouseEvent * );
|
||||
virtual void mouseReleaseEvent( QMouseEvent * );
|
||||
virtual void keyPressEvent( QKeyEvent * );
|
||||
virtual void keyReleaseEvent( QKeyEvent * );
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
492
third/3rd_qwt/qwt_magnifier.cpp
Normal file
492
third/3rd_qwt/qwt_magnifier.cpp
Normal file
@@ -0,0 +1,492 @@
|
||||
/* -*- 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_magnifier.h"
|
||||
#include "qwt_math.h"
|
||||
#include <qevent.h>
|
||||
#include <qwidget.h>
|
||||
|
||||
class QwtMagnifier::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
isEnabled( false ),
|
||||
wheelFactor( 0.9 ),
|
||||
wheelModifiers( Qt::NoModifier ),
|
||||
mouseFactor( 0.95 ),
|
||||
mouseButton( Qt::RightButton ),
|
||||
mouseButtonModifiers( Qt::NoModifier ),
|
||||
keyFactor( 0.9 ),
|
||||
zoomInKey( Qt::Key_Plus ),
|
||||
zoomInKeyModifiers( Qt::NoModifier ),
|
||||
zoomOutKey( Qt::Key_Minus ),
|
||||
zoomOutKeyModifiers( Qt::NoModifier ),
|
||||
mousePressed( false )
|
||||
{
|
||||
}
|
||||
|
||||
bool isEnabled;
|
||||
|
||||
double wheelFactor;
|
||||
Qt::KeyboardModifiers wheelModifiers;
|
||||
|
||||
double mouseFactor;
|
||||
|
||||
Qt::MouseButton mouseButton;
|
||||
Qt::KeyboardModifiers mouseButtonModifiers;
|
||||
|
||||
double keyFactor;
|
||||
|
||||
int zoomInKey;
|
||||
Qt::KeyboardModifiers zoomInKeyModifiers;
|
||||
|
||||
int zoomOutKey;
|
||||
Qt::KeyboardModifiers zoomOutKeyModifiers;
|
||||
|
||||
bool mousePressed;
|
||||
bool hasMouseTracking;
|
||||
QPoint mousePos;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
\param parent Widget to be magnified
|
||||
*/
|
||||
QwtMagnifier::QwtMagnifier( QWidget *parent ):
|
||||
QObject( parent )
|
||||
{
|
||||
d_data = new PrivateData();
|
||||
setEnabled( true );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtMagnifier::~QwtMagnifier()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief En/disable the magnifier
|
||||
|
||||
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 QwtMagnifier::setEnabled( bool on )
|
||||
{
|
||||
if ( d_data->isEnabled != on )
|
||||
{
|
||||
d_data->isEnabled = on;
|
||||
|
||||
QObject *o = parent();
|
||||
if ( o )
|
||||
{
|
||||
if ( d_data->isEnabled )
|
||||
o->installEventFilter( this );
|
||||
else
|
||||
o->removeEventFilter( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return true when enabled, false otherwise
|
||||
\sa setEnabled(), eventFilter()
|
||||
*/
|
||||
bool QwtMagnifier::isEnabled() const
|
||||
{
|
||||
return d_data->isEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the wheel factor
|
||||
|
||||
The wheel factor defines the ratio between the current range
|
||||
on the parent widget and the zoomed range for each step of the wheel.
|
||||
|
||||
Use values > 1 for magnification (i.e. 2.0) and values < 1 for
|
||||
scaling down (i.e. 1/2.0 = 0.5). You can use this feature for
|
||||
inverting the direction of the wheel.
|
||||
|
||||
The default value is 0.9.
|
||||
|
||||
\param factor Wheel factor
|
||||
\sa wheelFactor(), setWheelButtonState(),
|
||||
setMouseFactor(), setKeyFactor()
|
||||
*/
|
||||
void QwtMagnifier::setWheelFactor( double factor )
|
||||
{
|
||||
d_data->wheelFactor = factor;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Wheel factor
|
||||
\sa setWheelFactor()
|
||||
*/
|
||||
double QwtMagnifier::wheelFactor() const
|
||||
{
|
||||
return d_data->wheelFactor;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign keyboard modifiers for zooming in/out using the wheel.
|
||||
The default modifiers are Qt::NoModifiers.
|
||||
|
||||
\param modifiers Keyboard modifiers
|
||||
\sa wheelModifiers()
|
||||
*/
|
||||
void QwtMagnifier::setWheelModifiers( Qt::KeyboardModifiers modifiers )
|
||||
{
|
||||
d_data->wheelModifiers = modifiers;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Wheel modifiers
|
||||
\sa setWheelModifiers()
|
||||
*/
|
||||
Qt::KeyboardModifiers QwtMagnifier::wheelModifiers() const
|
||||
{
|
||||
return d_data->wheelModifiers;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the mouse factor
|
||||
|
||||
The mouse factor defines the ratio between the current range
|
||||
on the parent widget and the zoomed range for each vertical mouse movement.
|
||||
The default value is 0.95.
|
||||
|
||||
\param factor Wheel factor
|
||||
\sa mouseFactor(), setMouseButton(), setWheelFactor(), setKeyFactor()
|
||||
*/
|
||||
void QwtMagnifier::setMouseFactor( double factor )
|
||||
{
|
||||
d_data->mouseFactor = factor;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Mouse factor
|
||||
\sa setMouseFactor()
|
||||
*/
|
||||
double QwtMagnifier::mouseFactor() const
|
||||
{
|
||||
return d_data->mouseFactor;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign the mouse button, that is used for zooming in/out.
|
||||
The default value is Qt::RightButton.
|
||||
|
||||
\param button Button
|
||||
\param modifiers Keyboard modifiers
|
||||
|
||||
\sa getMouseButton()
|
||||
*/
|
||||
void QwtMagnifier::setMouseButton(
|
||||
Qt::MouseButton button, Qt::KeyboardModifiers modifiers )
|
||||
{
|
||||
d_data->mouseButton = button;
|
||||
d_data->mouseButtonModifiers = modifiers;
|
||||
}
|
||||
|
||||
//! \sa setMouseButton()
|
||||
void QwtMagnifier::getMouseButton(
|
||||
Qt::MouseButton &button, Qt::KeyboardModifiers &modifiers ) const
|
||||
{
|
||||
button = d_data->mouseButton;
|
||||
modifiers = d_data->mouseButtonModifiers;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the key factor
|
||||
|
||||
The key factor defines the ratio between the current range
|
||||
on the parent widget and the zoomed range for each key press of
|
||||
the zoom in/out keys. The default value is 0.9.
|
||||
|
||||
\param factor Key factor
|
||||
\sa keyFactor(), setZoomInKey(), setZoomOutKey(),
|
||||
setWheelFactor, setMouseFactor()
|
||||
*/
|
||||
void QwtMagnifier::setKeyFactor( double factor )
|
||||
{
|
||||
d_data->keyFactor = factor;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Key factor
|
||||
\sa setKeyFactor()
|
||||
*/
|
||||
double QwtMagnifier::keyFactor() const
|
||||
{
|
||||
return d_data->keyFactor;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign the key, that is used for zooming in.
|
||||
The default combination is Qt::Key_Plus + Qt::NoModifier.
|
||||
|
||||
\param key
|
||||
\param modifiers
|
||||
\sa getZoomInKey(), setZoomOutKey()
|
||||
*/
|
||||
void QwtMagnifier::setZoomInKey( int key,
|
||||
Qt::KeyboardModifiers modifiers )
|
||||
{
|
||||
d_data->zoomInKey = key;
|
||||
d_data->zoomInKeyModifiers = modifiers;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Retrieve the settings of the zoom in key
|
||||
|
||||
\param key Key code, see Qt::Key
|
||||
\param modifiers Keyboard modifiers
|
||||
|
||||
\sa setZoomInKey()
|
||||
*/
|
||||
void QwtMagnifier::getZoomInKey( int &key,
|
||||
Qt::KeyboardModifiers &modifiers ) const
|
||||
{
|
||||
key = d_data->zoomInKey;
|
||||
modifiers = d_data->zoomInKeyModifiers;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign the key, that is used for zooming out.
|
||||
The default combination is Qt::Key_Minus + Qt::NoModifier.
|
||||
|
||||
\param key
|
||||
\param modifiers
|
||||
\sa getZoomOutKey(), setZoomOutKey()
|
||||
*/
|
||||
void QwtMagnifier::setZoomOutKey( int key,
|
||||
Qt::KeyboardModifiers modifiers )
|
||||
{
|
||||
d_data->zoomOutKey = key;
|
||||
d_data->zoomOutKeyModifiers = modifiers;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Retrieve the settings of the zoom out key
|
||||
|
||||
\param key Key code, see Qt::Key
|
||||
\param modifiers Keyboard modifiers
|
||||
|
||||
\sa setZoomOutKey()
|
||||
*/
|
||||
void QwtMagnifier::getZoomOutKey( int &key,
|
||||
Qt::KeyboardModifiers &modifiers ) const
|
||||
{
|
||||
key = d_data->zoomOutKey;
|
||||
modifiers = d_data->zoomOutKeyModifiers;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Event filter
|
||||
|
||||
When isEnabled() is true, the mouse events of the
|
||||
observed widget are filtered.
|
||||
|
||||
\param object Object to be filtered
|
||||
\param event Event
|
||||
|
||||
\return Forwarded to QObject::eventFilter()
|
||||
|
||||
\sa widgetMousePressEvent(), widgetMouseReleaseEvent(),
|
||||
widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent()
|
||||
widgetKeyReleaseEvent()
|
||||
*/
|
||||
bool QwtMagnifier::eventFilter( QObject *object, QEvent *event )
|
||||
{
|
||||
if ( object && object == parent() )
|
||||
{
|
||||
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::Wheel:
|
||||
{
|
||||
widgetWheelEvent( static_cast<QWheelEvent *>( event ) );
|
||||
break;
|
||||
}
|
||||
case QEvent::KeyPress:
|
||||
{
|
||||
widgetKeyPressEvent( static_cast<QKeyEvent *>( event ) );
|
||||
break;
|
||||
}
|
||||
case QEvent::KeyRelease:
|
||||
{
|
||||
widgetKeyReleaseEvent( static_cast<QKeyEvent *>( event ) );
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
return QObject::eventFilter( object, event );
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a mouse press event for the observed widget.
|
||||
|
||||
\param mouseEvent Mouse event
|
||||
\sa eventFilter(), widgetMouseReleaseEvent(), widgetMouseMoveEvent()
|
||||
*/
|
||||
void QwtMagnifier::widgetMousePressEvent( QMouseEvent *mouseEvent )
|
||||
{
|
||||
if ( parentWidget() == NULL )
|
||||
return;
|
||||
|
||||
if ( ( mouseEvent->button() != d_data->mouseButton ) ||
|
||||
( mouseEvent->modifiers() != d_data->mouseButtonModifiers ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d_data->hasMouseTracking = parentWidget()->hasMouseTracking();
|
||||
|
||||
parentWidget()->setMouseTracking( true );
|
||||
d_data->mousePos = mouseEvent->pos();
|
||||
d_data->mousePressed = true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a mouse release event for the observed widget.
|
||||
|
||||
\param mouseEvent Mouse event
|
||||
|
||||
\sa eventFilter(), widgetMousePressEvent(), widgetMouseMoveEvent(),
|
||||
*/
|
||||
void QwtMagnifier::widgetMouseReleaseEvent( QMouseEvent *mouseEvent )
|
||||
{
|
||||
Q_UNUSED( mouseEvent );
|
||||
|
||||
if ( d_data->mousePressed && parentWidget() )
|
||||
{
|
||||
d_data->mousePressed = false;
|
||||
parentWidget()->setMouseTracking( d_data->hasMouseTracking );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a mouse move event for the observed widget.
|
||||
|
||||
\param mouseEvent Mouse event
|
||||
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
|
||||
*/
|
||||
void QwtMagnifier::widgetMouseMoveEvent( QMouseEvent *mouseEvent )
|
||||
{
|
||||
if ( !d_data->mousePressed )
|
||||
return;
|
||||
|
||||
const int dy = mouseEvent->pos().y() - d_data->mousePos.y();
|
||||
if ( dy != 0 )
|
||||
{
|
||||
double f = d_data->mouseFactor;
|
||||
if ( dy < 0 )
|
||||
f = 1 / f;
|
||||
|
||||
rescale( f );
|
||||
}
|
||||
|
||||
d_data->mousePos = mouseEvent->pos();
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a wheel event for the observed widget.
|
||||
|
||||
\param wheelEvent Wheel event
|
||||
\sa eventFilter()
|
||||
*/
|
||||
void QwtMagnifier::widgetWheelEvent( QWheelEvent *wheelEvent )
|
||||
{
|
||||
if ( wheelEvent->modifiers() != d_data->wheelModifiers )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( d_data->wheelFactor != 0.0 )
|
||||
{
|
||||
/*
|
||||
A positive delta indicates that the wheel was
|
||||
rotated forwards away from the user; a negative
|
||||
value indicates that the wheel was rotated
|
||||
backwards toward the user.
|
||||
Most mouse types work in steps of 15 degrees,
|
||||
in which case the delta value is a multiple
|
||||
of 120 (== 15 * 8).
|
||||
*/
|
||||
double f = qPow( d_data->wheelFactor,
|
||||
qAbs( wheelEvent->delta() / 120.0 ) );
|
||||
|
||||
if ( wheelEvent->delta() > 0 )
|
||||
f = 1 / f;
|
||||
|
||||
rescale( f );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a key press event for the observed widget.
|
||||
|
||||
\param keyEvent Key event
|
||||
\sa eventFilter(), widgetKeyReleaseEvent()
|
||||
*/
|
||||
void QwtMagnifier::widgetKeyPressEvent( QKeyEvent *keyEvent )
|
||||
{
|
||||
if ( keyEvent->key() == d_data->zoomInKey &&
|
||||
keyEvent->modifiers() == d_data->zoomInKeyModifiers )
|
||||
{
|
||||
rescale( d_data->keyFactor );
|
||||
}
|
||||
else if ( keyEvent->key() == d_data->zoomOutKey &&
|
||||
keyEvent->modifiers() == d_data->zoomOutKeyModifiers )
|
||||
{
|
||||
rescale( 1.0 / d_data->keyFactor );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a key release event for the observed widget.
|
||||
|
||||
\param keyEvent Key event
|
||||
\sa eventFilter(), widgetKeyReleaseEvent()
|
||||
*/
|
||||
void QwtMagnifier::widgetKeyReleaseEvent( QKeyEvent *keyEvent )
|
||||
{
|
||||
Q_UNUSED( keyEvent );
|
||||
}
|
||||
|
||||
//! \return Parent widget, where the rescaling happens
|
||||
QWidget *QwtMagnifier::parentWidget()
|
||||
{
|
||||
return qobject_cast<QWidget *>( parent() );
|
||||
}
|
||||
|
||||
//! \return Parent widget, where the rescaling happens
|
||||
const QWidget *QwtMagnifier::parentWidget() const
|
||||
{
|
||||
return qobject_cast<const QWidget *>( parent() );
|
||||
}
|
||||
|
||||
86
third/3rd_qwt/qwt_magnifier.h
Normal file
86
third/3rd_qwt/qwt_magnifier.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_MAGNIFIER_H
|
||||
#define QWT_MAGNIFIER_H 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qobject.h>
|
||||
|
||||
class QWidget;
|
||||
class QMouseEvent;
|
||||
class QWheelEvent;
|
||||
class QKeyEvent;
|
||||
|
||||
/*!
|
||||
\brief QwtMagnifier provides zooming, by magnifying in steps.
|
||||
|
||||
Using QwtMagnifier a plot can be zoomed in/out in steps using
|
||||
keys, the mouse wheel or moving a mouse button in vertical direction.
|
||||
*/
|
||||
class QWT_EXPORT QwtMagnifier: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QwtMagnifier( QWidget * );
|
||||
virtual ~QwtMagnifier();
|
||||
|
||||
QWidget *parentWidget();
|
||||
const QWidget *parentWidget() const;
|
||||
|
||||
void setEnabled( bool );
|
||||
bool isEnabled() const;
|
||||
|
||||
// mouse
|
||||
void setMouseFactor( double );
|
||||
double mouseFactor() const;
|
||||
|
||||
void setMouseButton( Qt::MouseButton, Qt::KeyboardModifiers = Qt::NoModifier );
|
||||
void getMouseButton( Qt::MouseButton &, Qt::KeyboardModifiers & ) const;
|
||||
|
||||
// mouse wheel
|
||||
void setWheelFactor( double );
|
||||
double wheelFactor() const;
|
||||
|
||||
void setWheelModifiers( Qt::KeyboardModifiers );
|
||||
Qt::KeyboardModifiers wheelModifiers() const;
|
||||
|
||||
// keyboard
|
||||
void setKeyFactor( double );
|
||||
double keyFactor() const;
|
||||
|
||||
void setZoomInKey( int key, Qt::KeyboardModifiers = Qt::NoModifier );
|
||||
void getZoomInKey( int &key, Qt::KeyboardModifiers & ) const;
|
||||
|
||||
void setZoomOutKey( int key, Qt::KeyboardModifiers = Qt::NoModifier );
|
||||
void getZoomOutKey( int &key, Qt::KeyboardModifiers & ) const;
|
||||
|
||||
virtual bool eventFilter( QObject *, QEvent * );
|
||||
|
||||
protected:
|
||||
/*!
|
||||
Rescale the parent widget
|
||||
\param factor Scale factor
|
||||
*/
|
||||
virtual void rescale( double factor ) = 0;
|
||||
|
||||
virtual void widgetMousePressEvent( QMouseEvent * );
|
||||
virtual void widgetMouseReleaseEvent( QMouseEvent * );
|
||||
virtual void widgetMouseMoveEvent( QMouseEvent * );
|
||||
virtual void widgetWheelEvent( QWheelEvent * );
|
||||
virtual void widgetKeyPressEvent( QKeyEvent * );
|
||||
virtual void widgetKeyReleaseEvent( QKeyEvent * );
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
74
third/3rd_qwt/qwt_math.cpp
Normal file
74
third/3rd_qwt/qwt_math.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/* -*- 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_math.h"
|
||||
|
||||
/*!
|
||||
\brief Find the smallest value in an array
|
||||
\param array Pointer to an array
|
||||
\param size Array size
|
||||
*/
|
||||
double qwtGetMin( const double *array, int size )
|
||||
{
|
||||
if ( size <= 0 )
|
||||
return 0.0;
|
||||
|
||||
double rv = array[0];
|
||||
for ( int i = 1; i < size; i++ )
|
||||
rv = qMin( rv, array[i] );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Find the largest value in an array
|
||||
\param array Pointer to an array
|
||||
\param size Array size
|
||||
*/
|
||||
double qwtGetMax( const double *array, int size )
|
||||
{
|
||||
if ( size <= 0 )
|
||||
return 0.0;
|
||||
|
||||
double rv = array[0];
|
||||
for ( int i = 1; i < size; i++ )
|
||||
rv = qMax( rv, array[i] );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Normalize an angle to be int the range [0.0, 2 * PI[
|
||||
\param radians Angle in radians
|
||||
\return Normalized angle in radians
|
||||
*/
|
||||
double qwtNormalizeRadians( double radians )
|
||||
{
|
||||
double a = ::fmod( radians, 2.0 * M_PI );
|
||||
if ( a < 0.0 )
|
||||
a += 2.0 * M_PI;
|
||||
|
||||
return a;
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Normalize an angle to be int the range [0.0, 360.0[
|
||||
\param radians Angle in degrees
|
||||
\return Normalized angle in degrees
|
||||
*/
|
||||
double qwtNormalizeDegrees( double degrees )
|
||||
{
|
||||
double a = ::fmod( degrees, 360.0 );
|
||||
if ( a < 0.0 )
|
||||
a += 360.0;
|
||||
|
||||
return a;
|
||||
}
|
||||
149
third/3rd_qwt/qwt_math.h
Normal file
149
third/3rd_qwt/qwt_math.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_MATH_H
|
||||
#define QWT_MATH_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/*
|
||||
Microsoft says:
|
||||
|
||||
Define _USE_MATH_DEFINES before including math.h to expose these macro
|
||||
definitions for common math constants. These are placed under an #ifdef
|
||||
since these commonly-defined names are not part of the C/C++ standards.
|
||||
*/
|
||||
#define _USE_MATH_DEFINES 1
|
||||
#endif
|
||||
|
||||
#include <qmath.h>
|
||||
#include "qwt_global.h"
|
||||
|
||||
#ifndef M_PI_2
|
||||
// For Qt <= 4.8.4 M_PI_2 is not known by MinGW-w64
|
||||
// when compiling with -std=c++11
|
||||
#define M_PI_2 (1.57079632679489661923)
|
||||
#endif
|
||||
|
||||
#ifndef LOG_MIN
|
||||
//! Minimum value for logarithmic scales
|
||||
#define LOG_MIN 1.0e-100
|
||||
#endif
|
||||
|
||||
#ifndef LOG_MAX
|
||||
//! Maximum value for logarithmic scales
|
||||
#define LOG_MAX 1.0e100
|
||||
#endif
|
||||
|
||||
QWT_EXPORT double qwtGetMin( const double *array, int size );
|
||||
QWT_EXPORT double qwtGetMax( const double *array, int size );
|
||||
|
||||
QWT_EXPORT double qwtNormalizeRadians( double radians );
|
||||
QWT_EXPORT double qwtNormalizeDegrees( double degrees );
|
||||
|
||||
/*!
|
||||
\brief Compare 2 values, relative to an interval
|
||||
|
||||
Values are "equal", when :
|
||||
\f$\cdot value2 - value1 <= abs(intervalSize * 10e^{-6})\f$
|
||||
|
||||
\param value1 First value to compare
|
||||
\param value2 Second value to compare
|
||||
\param intervalSize interval size
|
||||
|
||||
\return 0: if equal, -1: if value2 > value1, 1: if value1 > value2
|
||||
*/
|
||||
inline int qwtFuzzyCompare( double value1, double value2, double intervalSize )
|
||||
{
|
||||
const double eps = qAbs( 1.0e-6 * intervalSize );
|
||||
|
||||
if ( value2 - value1 > eps )
|
||||
return -1;
|
||||
|
||||
if ( value1 - value2 > eps )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool qwtFuzzyGreaterOrEqual( double d1, double d2 )
|
||||
{
|
||||
return ( d1 >= d2 ) || qFuzzyCompare( d1, d2 );
|
||||
}
|
||||
|
||||
inline bool qwtFuzzyLessOrEqual( double d1, double d2 )
|
||||
{
|
||||
return ( d1 <= d2 ) || qFuzzyCompare( d1, d2 );
|
||||
}
|
||||
|
||||
//! Return the sign
|
||||
inline int qwtSign( double x )
|
||||
{
|
||||
if ( x > 0.0 )
|
||||
return 1;
|
||||
else if ( x < 0.0 )
|
||||
return ( -1 );
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Return the square of a number
|
||||
inline double qwtSqr( double x )
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
|
||||
//! Approximation of arc tangent ( error below 0,005 radians )
|
||||
inline double qwtFastAtan( double x )
|
||||
{
|
||||
if ( x < -1.0 )
|
||||
return -M_PI_2 - x / ( x * x + 0.28 );
|
||||
|
||||
if ( x > 1.0 )
|
||||
return M_PI_2 - x / ( x * x + 0.28 );
|
||||
|
||||
return x / ( 1.0 + x * x * 0.28 );
|
||||
}
|
||||
|
||||
//! Approximation of arc tangent ( error below 0,005 radians )
|
||||
inline double qwtFastAtan2( double y, double x )
|
||||
{
|
||||
if ( x > 0 )
|
||||
return qwtFastAtan( y / x );
|
||||
|
||||
if ( x < 0 )
|
||||
{
|
||||
const double d = qwtFastAtan( y / x );
|
||||
return ( y >= 0 ) ? d + M_PI : d - M_PI;
|
||||
}
|
||||
|
||||
if ( y < 0.0 )
|
||||
return -M_PI_2;
|
||||
|
||||
if ( y > 0.0 )
|
||||
return M_PI_2;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//! Translate degrees into radians
|
||||
inline double qwtRadians( double degrees )
|
||||
{
|
||||
return degrees * M_PI / 180.0;
|
||||
}
|
||||
|
||||
//! Translate radians into degrees
|
||||
inline double qwtDegrees( double degrees )
|
||||
{
|
||||
return degrees * 180.0 / M_PI;
|
||||
}
|
||||
|
||||
#endif
|
||||
298
third/3rd_qwt/qwt_matrix_raster_data.cpp
Normal file
298
third/3rd_qwt/qwt_matrix_raster_data.cpp
Normal file
@@ -0,0 +1,298 @@
|
||||
/* -*- 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_matrix_raster_data.h"
|
||||
#include <qnumeric.h>
|
||||
#include <qmath.h>
|
||||
|
||||
class QwtMatrixRasterData::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
resampleMode(QwtMatrixRasterData::NearestNeighbour),
|
||||
numColumns(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline double value(int row, int col) const
|
||||
{
|
||||
return values.data()[ row * numColumns + col ];
|
||||
}
|
||||
|
||||
QwtMatrixRasterData::ResampleMode resampleMode;
|
||||
|
||||
QVector<double> values;
|
||||
int numColumns;
|
||||
int numRows;
|
||||
|
||||
double dx;
|
||||
double dy;
|
||||
};
|
||||
|
||||
//! Constructor
|
||||
QwtMatrixRasterData::QwtMatrixRasterData()
|
||||
{
|
||||
d_data = new PrivateData();
|
||||
update();
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtMatrixRasterData::~QwtMatrixRasterData()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the resampling algorithm
|
||||
|
||||
\param mode Resampling mode
|
||||
\sa resampleMode(), value()
|
||||
*/
|
||||
void QwtMatrixRasterData::setResampleMode( ResampleMode mode )
|
||||
{
|
||||
d_data->resampleMode = mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return resampling algorithm
|
||||
\sa setResampleMode(), value()
|
||||
*/
|
||||
QwtMatrixRasterData::ResampleMode QwtMatrixRasterData::resampleMode() const
|
||||
{
|
||||
return d_data->resampleMode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign the bounding interval for an axis
|
||||
|
||||
Setting the bounding intervals for the X/Y axis is mandatory
|
||||
to define the positions for the values of the value matrix.
|
||||
The interval in Z direction defines the possible range for
|
||||
the values in the matrix, what is f.e used by QwtPlotSpectrogram
|
||||
to map values to colors. The Z-interval might be the bounding
|
||||
interval of the values in the matrix, but usually it isn't.
|
||||
( f.e a interval of 0.0-100.0 for values in percentage )
|
||||
|
||||
\param axis X, Y or Z axis
|
||||
\param interval Interval
|
||||
|
||||
\sa QwtRasterData::interval(), setValueMatrix()
|
||||
*/
|
||||
void QwtMatrixRasterData::setInterval(
|
||||
Qt::Axis axis, const QwtInterval &interval )
|
||||
{
|
||||
QwtRasterData::setInterval( axis, interval );
|
||||
update();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign a value matrix
|
||||
|
||||
The positions of the values are calculated by dividing
|
||||
the bounding rectangle of the X/Y intervals into equidistant
|
||||
rectangles ( pixels ). Each value corresponds to the center of
|
||||
a pixel.
|
||||
|
||||
\param values Vector of values
|
||||
\param numColumns Number of columns
|
||||
|
||||
\sa valueMatrix(), numColumns(), numRows(), setInterval()()
|
||||
*/
|
||||
void QwtMatrixRasterData::setValueMatrix(
|
||||
const QVector<double> &values, int numColumns )
|
||||
{
|
||||
d_data->values = values;
|
||||
d_data->numColumns = qMax( numColumns, 0 );
|
||||
update();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Value matrix
|
||||
\sa setValueMatrix(), numColumns(), numRows(), setInterval()
|
||||
*/
|
||||
const QVector<double> QwtMatrixRasterData::valueMatrix() const
|
||||
{
|
||||
return d_data->values;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change a single value in the matrix
|
||||
|
||||
\param row Row index
|
||||
\param col Column index
|
||||
\param value New value
|
||||
|
||||
\sa value(), setValueMatrix()
|
||||
*/
|
||||
void QwtMatrixRasterData::setValue( int row, int col, double value )
|
||||
{
|
||||
if ( row >= 0 && row < d_data->numRows &&
|
||||
col >= 0 && col < d_data->numColumns )
|
||||
{
|
||||
const int index = row * d_data->numColumns + col;
|
||||
d_data->values.data()[ index ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of columns of the value matrix
|
||||
\sa valueMatrix(), numRows(), setValueMatrix()
|
||||
*/
|
||||
int QwtMatrixRasterData::numColumns() const
|
||||
{
|
||||
return d_data->numColumns;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Number of rows of the value matrix
|
||||
\sa valueMatrix(), numColumns(), setValueMatrix()
|
||||
*/
|
||||
int QwtMatrixRasterData::numRows() const
|
||||
{
|
||||
return d_data->numRows;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Calculate the pixel hint
|
||||
|
||||
pixelHint() returns the geometry of a pixel, that can be used
|
||||
to calculate the resolution and alignment of the plot item, that is
|
||||
representing the data.
|
||||
|
||||
- NearestNeighbour\n
|
||||
pixelHint() returns the surrounding pixel of the top left value
|
||||
in the matrix.
|
||||
|
||||
- BilinearInterpolation\n
|
||||
Returns an empty rectangle recommending
|
||||
to render in target device ( f.e. screen ) resolution.
|
||||
|
||||
\param area Requested area, ignored
|
||||
\return Calculated hint
|
||||
|
||||
\sa ResampleMode, setMatrix(), setInterval()
|
||||
*/
|
||||
QRectF QwtMatrixRasterData::pixelHint( const QRectF &area ) const
|
||||
{
|
||||
Q_UNUSED( area )
|
||||
|
||||
QRectF rect;
|
||||
if ( d_data->resampleMode == NearestNeighbour )
|
||||
{
|
||||
const QwtInterval intervalX = interval( Qt::XAxis );
|
||||
const QwtInterval intervalY = interval( Qt::YAxis );
|
||||
if ( intervalX.isValid() && intervalY.isValid() )
|
||||
{
|
||||
rect = QRectF( intervalX.minValue(), intervalY.minValue(),
|
||||
d_data->dx, d_data->dy );
|
||||
}
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the value at a raster position
|
||||
|
||||
\param x X value in plot coordinates
|
||||
\param y Y value in plot coordinates
|
||||
|
||||
\sa ResampleMode
|
||||
*/
|
||||
double QwtMatrixRasterData::value( double x, double y ) const
|
||||
{
|
||||
const QwtInterval xInterval = interval( Qt::XAxis );
|
||||
const QwtInterval yInterval = interval( Qt::YAxis );
|
||||
|
||||
if ( !( xInterval.contains(x) && yInterval.contains(y) ) )
|
||||
return qQNaN();
|
||||
|
||||
double value;
|
||||
|
||||
switch( d_data->resampleMode )
|
||||
{
|
||||
case BilinearInterpolation:
|
||||
{
|
||||
int col1 = qRound( (x - xInterval.minValue() ) / d_data->dx ) - 1;
|
||||
int row1 = qRound( (y - yInterval.minValue() ) / d_data->dy ) - 1;
|
||||
int col2 = col1 + 1;
|
||||
int row2 = row1 + 1;
|
||||
|
||||
if ( col1 < 0 )
|
||||
col1 = col2;
|
||||
else if ( col2 >= static_cast<int>( d_data->numColumns ) )
|
||||
col2 = col1;
|
||||
|
||||
if ( row1 < 0 )
|
||||
row1 = row2;
|
||||
else if ( row2 >= static_cast<int>( d_data->numRows ) )
|
||||
row2 = row1;
|
||||
|
||||
const double v11 = d_data->value( row1, col1 );
|
||||
const double v21 = d_data->value( row1, col2 );
|
||||
const double v12 = d_data->value( row2, col1 );
|
||||
const double v22 = d_data->value( row2, col2 );
|
||||
|
||||
const double x2 = xInterval.minValue() +
|
||||
( col2 + 0.5 ) * d_data->dx;
|
||||
const double y2 = yInterval.minValue() +
|
||||
( row2 + 0.5 ) * d_data->dy;
|
||||
|
||||
const double rx = ( x2 - x ) / d_data->dx;
|
||||
const double ry = ( y2 - y ) / d_data->dy;
|
||||
|
||||
const double vr1 = rx * v11 + ( 1.0 - rx ) * v21;
|
||||
const double vr2 = rx * v12 + ( 1.0 - rx ) * v22;
|
||||
|
||||
value = ry * vr1 + ( 1.0 - ry ) * vr2;
|
||||
|
||||
break;
|
||||
}
|
||||
case NearestNeighbour:
|
||||
default:
|
||||
{
|
||||
int row = int( (y - yInterval.minValue() ) / d_data->dy );
|
||||
int col = int( (x - xInterval.minValue() ) / d_data->dx );
|
||||
|
||||
// In case of intervals, where the maximum is included
|
||||
// we get out of bound for row/col, when the value for the
|
||||
// maximum is requested. Instead we return the value
|
||||
// from the last row/col
|
||||
|
||||
if ( row >= d_data->numRows )
|
||||
row = d_data->numRows - 1;
|
||||
|
||||
if ( col >= d_data->numColumns )
|
||||
col = d_data->numColumns - 1;
|
||||
|
||||
value = d_data->value( row, col );
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void QwtMatrixRasterData::update()
|
||||
{
|
||||
d_data->numRows = 0;
|
||||
d_data->dx = 0.0;
|
||||
d_data->dy = 0.0;
|
||||
|
||||
if ( d_data->numColumns > 0 )
|
||||
{
|
||||
d_data->numRows = d_data->values.size() / d_data->numColumns;
|
||||
|
||||
const QwtInterval xInterval = interval( Qt::XAxis );
|
||||
const QwtInterval yInterval = interval( Qt::YAxis );
|
||||
if ( xInterval.isValid() )
|
||||
d_data->dx = xInterval.width() / d_data->numColumns;
|
||||
if ( yInterval.isValid() )
|
||||
d_data->dy = yInterval.width() / d_data->numRows;
|
||||
}
|
||||
}
|
||||
74
third/3rd_qwt/qwt_matrix_raster_data.h
Normal file
74
third/3rd_qwt/qwt_matrix_raster_data.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_MATRIX_RASTER_DATA_H
|
||||
#define QWT_MATRIX_RASTER_DATA_H 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_raster_data.h"
|
||||
#include <qvector.h>
|
||||
|
||||
/*!
|
||||
\brief A class representing a matrix of values as raster data
|
||||
|
||||
QwtMatrixRasterData implements an interface for a matrix of
|
||||
equidistant values, that can be used by a QwtPlotRasterItem.
|
||||
It implements a couple of resampling algorithms, to provide
|
||||
values for positions, that or not on the value matrix.
|
||||
*/
|
||||
class QWT_EXPORT QwtMatrixRasterData: public QwtRasterData
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
\brief Resampling algorithm
|
||||
The default setting is NearestNeighbour;
|
||||
*/
|
||||
enum ResampleMode
|
||||
{
|
||||
/*!
|
||||
Return the value from the matrix, that is nearest to the
|
||||
the requested position.
|
||||
*/
|
||||
NearestNeighbour,
|
||||
|
||||
/*!
|
||||
Interpolate the value from the distances and values of the
|
||||
4 surrounding values in the matrix,
|
||||
*/
|
||||
BilinearInterpolation
|
||||
};
|
||||
|
||||
QwtMatrixRasterData();
|
||||
virtual ~QwtMatrixRasterData();
|
||||
|
||||
void setResampleMode(ResampleMode mode);
|
||||
ResampleMode resampleMode() const;
|
||||
|
||||
virtual void setInterval( Qt::Axis, const QwtInterval & );
|
||||
|
||||
void setValueMatrix( const QVector<double> &values, int numColumns );
|
||||
const QVector<double> valueMatrix() const;
|
||||
|
||||
void setValue( int row, int col, double value );
|
||||
|
||||
int numColumns() const;
|
||||
int numRows() const;
|
||||
|
||||
virtual QRectF pixelHint( const QRectF & ) const;
|
||||
|
||||
virtual double value( double x, double y ) const;
|
||||
|
||||
private:
|
||||
void update();
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
595
third/3rd_qwt/qwt_null_paintdevice.cpp
Normal file
595
third/3rd_qwt/qwt_null_paintdevice.cpp
Normal file
@@ -0,0 +1,595 @@
|
||||
/* -*- 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_null_paintdevice.h"
|
||||
#include <qpaintengine.h>
|
||||
#include <qpixmap.h>
|
||||
#include "qpainterpath.h"
|
||||
#include "qpainter.h"
|
||||
|
||||
class QwtNullPaintDevice::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
mode( QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
}
|
||||
|
||||
QwtNullPaintDevice::Mode mode;
|
||||
};
|
||||
|
||||
class QwtNullPaintDevice::PaintEngine: public QPaintEngine
|
||||
{
|
||||
public:
|
||||
PaintEngine();
|
||||
|
||||
virtual bool begin( QPaintDevice * );
|
||||
virtual bool end();
|
||||
|
||||
virtual Type type () const;
|
||||
virtual void updateState(const QPaintEngineState &);
|
||||
|
||||
virtual void drawRects(const QRect *, int );
|
||||
virtual void drawRects(const QRectF *, int );
|
||||
|
||||
virtual void drawLines(const QLine *, int );
|
||||
virtual void drawLines(const QLineF *, int );
|
||||
|
||||
virtual void drawEllipse(const QRectF &);
|
||||
virtual void drawEllipse(const QRect &);
|
||||
|
||||
virtual void drawPath(const QPainterPath &);
|
||||
|
||||
virtual void drawPoints(const QPointF *, int );
|
||||
virtual void drawPoints(const QPoint *, int );
|
||||
|
||||
virtual void drawPolygon(const QPointF *, int , PolygonDrawMode );
|
||||
virtual void drawPolygon(const QPoint *, int , PolygonDrawMode );
|
||||
|
||||
virtual void drawPixmap(const QRectF &,
|
||||
const QPixmap &, const QRectF &);
|
||||
|
||||
virtual void drawTextItem(const QPointF &, const QTextItem &);
|
||||
|
||||
virtual void drawTiledPixmap(const QRectF &,
|
||||
const QPixmap &, const QPointF &s);
|
||||
|
||||
virtual void drawImage(const QRectF &,
|
||||
const QImage &, const QRectF &, Qt::ImageConversionFlags );
|
||||
|
||||
private:
|
||||
QwtNullPaintDevice *nullDevice();
|
||||
};
|
||||
|
||||
QwtNullPaintDevice::PaintEngine::PaintEngine():
|
||||
QPaintEngine( QPaintEngine::AllFeatures )
|
||||
{
|
||||
}
|
||||
|
||||
bool QwtNullPaintDevice::PaintEngine::begin( QPaintDevice * )
|
||||
{
|
||||
setActive( true );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QwtNullPaintDevice::PaintEngine::end()
|
||||
{
|
||||
setActive( false );
|
||||
return true;
|
||||
}
|
||||
|
||||
QPaintEngine::Type QwtNullPaintDevice::PaintEngine::type() const
|
||||
{
|
||||
return QPaintEngine::User;
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawRects(
|
||||
const QRect *rects, int rectCount)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawRects( rects, rectCount );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawRects( rects, rectCount );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawRects(
|
||||
const QRectF *rects, int rectCount)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawRects( rects, rectCount );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawRects( rects, rectCount );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawLines(
|
||||
const QLine *lines, int lineCount)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawLines( lines, lineCount );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawLines( lines, lineCount );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawLines(
|
||||
const QLineF *lines, int lineCount)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawLines( lines, lineCount );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawLines( lines, lineCount );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawEllipse(
|
||||
const QRectF &rect)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawEllipse( rect );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawEllipse( rect );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawEllipse(
|
||||
const QRect &rect)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawEllipse( rect );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawEllipse( rect );
|
||||
}
|
||||
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawPath(
|
||||
const QPainterPath &path)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
device->drawPath( path );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawPoints(
|
||||
const QPointF *points, int pointCount)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawPoints( points, pointCount );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawPoints( points, pointCount );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawPoints(
|
||||
const QPoint *points, int pointCount)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawPoints( points, pointCount );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawPoints( points, pointCount );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawPolygon(
|
||||
const QPointF *points, int pointCount, PolygonDrawMode mode)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() == QwtNullPaintDevice::PathMode )
|
||||
{
|
||||
QPainterPath path;
|
||||
|
||||
if ( pointCount > 0 )
|
||||
{
|
||||
path.moveTo( points[0] );
|
||||
for ( int i = 1; i < pointCount; i++ )
|
||||
path.lineTo( points[i] );
|
||||
|
||||
if ( mode != PolylineMode )
|
||||
path.closeSubpath();
|
||||
}
|
||||
|
||||
device->drawPath( path );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawPolygon( points, pointCount, mode );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawPolygon(
|
||||
const QPoint *points, int pointCount, PolygonDrawMode mode)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() == QwtNullPaintDevice::PathMode )
|
||||
{
|
||||
QPainterPath path;
|
||||
|
||||
if ( pointCount > 0 )
|
||||
{
|
||||
path.moveTo( points[0] );
|
||||
for ( int i = 1; i < pointCount; i++ )
|
||||
path.lineTo( points[i] );
|
||||
|
||||
if ( mode != PolylineMode )
|
||||
path.closeSubpath();
|
||||
}
|
||||
|
||||
device->drawPath( path );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawPolygon( points, pointCount, mode );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawPixmap(
|
||||
const QRectF &rect, const QPixmap &pm, const QRectF &subRect )
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
device->drawPixmap( rect, pm, subRect );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawTextItem(
|
||||
const QPointF &pos, const QTextItem &textItem)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawTextItem( pos, textItem );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawTextItem( pos, textItem );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawTiledPixmap(
|
||||
const QRectF &rect, const QPixmap &pixmap,
|
||||
const QPointF &subRect)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
if ( device->mode() != QwtNullPaintDevice::NormalMode )
|
||||
{
|
||||
QPaintEngine::drawTiledPixmap( rect, pixmap, subRect );
|
||||
return;
|
||||
}
|
||||
|
||||
device->drawTiledPixmap( rect, pixmap, subRect );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::drawImage(
|
||||
const QRectF &rect, const QImage &image,
|
||||
const QRectF &subRect, Qt::ImageConversionFlags flags)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
device->drawImage( rect, image, subRect, flags );
|
||||
}
|
||||
|
||||
void QwtNullPaintDevice::PaintEngine::updateState(
|
||||
const QPaintEngineState &engineState)
|
||||
{
|
||||
QwtNullPaintDevice *device = nullDevice();
|
||||
if ( device == NULL )
|
||||
return;
|
||||
|
||||
device->updateState( engineState );
|
||||
}
|
||||
|
||||
inline QwtNullPaintDevice *QwtNullPaintDevice::PaintEngine::nullDevice()
|
||||
{
|
||||
if ( !isActive() )
|
||||
return NULL;
|
||||
|
||||
return static_cast<QwtNullPaintDevice *>( paintDevice() );
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtNullPaintDevice::QwtNullPaintDevice():
|
||||
d_engine( NULL )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtNullPaintDevice::~QwtNullPaintDevice()
|
||||
{
|
||||
delete d_engine;
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the render mode
|
||||
|
||||
\param mode New mode
|
||||
\sa mode()
|
||||
*/
|
||||
void QwtNullPaintDevice::setMode( Mode mode )
|
||||
{
|
||||
d_data->mode = mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Render mode
|
||||
\sa setMode()
|
||||
*/
|
||||
QwtNullPaintDevice::Mode QwtNullPaintDevice::mode() const
|
||||
{
|
||||
return d_data->mode;
|
||||
}
|
||||
|
||||
//! See QPaintDevice::paintEngine()
|
||||
QPaintEngine *QwtNullPaintDevice::paintEngine() const
|
||||
{
|
||||
if ( d_engine == NULL )
|
||||
{
|
||||
QwtNullPaintDevice *that =
|
||||
const_cast< QwtNullPaintDevice * >( this );
|
||||
|
||||
that->d_engine = new PaintEngine();
|
||||
}
|
||||
|
||||
return d_engine;
|
||||
}
|
||||
|
||||
/*!
|
||||
See QPaintDevice::metric()
|
||||
|
||||
\param deviceMetric Type of metric
|
||||
\return Metric information for the given paint device metric.
|
||||
|
||||
\sa sizeMetrics()
|
||||
*/
|
||||
int QwtNullPaintDevice::metric( PaintDeviceMetric deviceMetric ) const
|
||||
{
|
||||
int value;
|
||||
|
||||
switch ( deviceMetric )
|
||||
{
|
||||
case PdmWidth:
|
||||
{
|
||||
value = sizeMetrics().width();
|
||||
break;
|
||||
}
|
||||
case PdmHeight:
|
||||
{
|
||||
value = sizeMetrics().height();
|
||||
break;
|
||||
}
|
||||
case PdmNumColors:
|
||||
{
|
||||
value = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
case PdmDepth:
|
||||
{
|
||||
value = 32;
|
||||
break;
|
||||
}
|
||||
case PdmPhysicalDpiX:
|
||||
case PdmPhysicalDpiY:
|
||||
case PdmDpiY:
|
||||
case PdmDpiX:
|
||||
{
|
||||
value = 72;
|
||||
break;
|
||||
}
|
||||
case PdmWidthMM:
|
||||
{
|
||||
value = qRound( metric( PdmWidth ) * 25.4 / metric( PdmDpiX ) );
|
||||
break;
|
||||
}
|
||||
case PdmHeightMM:
|
||||
{
|
||||
value = qRound( metric( PdmHeight ) * 25.4 / metric( PdmDpiY ) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
value = 0;
|
||||
}
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawRects()
|
||||
void QwtNullPaintDevice::drawRects(
|
||||
const QRect *rects, int rectCount)
|
||||
{
|
||||
Q_UNUSED(rects);
|
||||
Q_UNUSED(rectCount);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawRects()
|
||||
void QwtNullPaintDevice::drawRects(
|
||||
const QRectF *rects, int rectCount)
|
||||
{
|
||||
Q_UNUSED(rects);
|
||||
Q_UNUSED(rectCount);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawLines()
|
||||
void QwtNullPaintDevice::drawLines(
|
||||
const QLine *lines, int lineCount)
|
||||
{
|
||||
Q_UNUSED(lines);
|
||||
Q_UNUSED(lineCount);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawLines()
|
||||
void QwtNullPaintDevice::drawLines(
|
||||
const QLineF *lines, int lineCount)
|
||||
{
|
||||
Q_UNUSED(lines);
|
||||
Q_UNUSED(lineCount);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawEllipse()
|
||||
void QwtNullPaintDevice::drawEllipse( const QRectF &rect )
|
||||
{
|
||||
Q_UNUSED(rect);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawEllipse()
|
||||
void QwtNullPaintDevice::drawEllipse( const QRect &rect )
|
||||
{
|
||||
Q_UNUSED(rect);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawPath()
|
||||
void QwtNullPaintDevice::drawPath( const QPainterPath &path )
|
||||
{
|
||||
Q_UNUSED(path);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawPoints()
|
||||
void QwtNullPaintDevice::drawPoints(
|
||||
const QPointF *points, int pointCount)
|
||||
{
|
||||
Q_UNUSED(points);
|
||||
Q_UNUSED(pointCount);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawPoints()
|
||||
void QwtNullPaintDevice::drawPoints(
|
||||
const QPoint *points, int pointCount)
|
||||
{
|
||||
Q_UNUSED(points);
|
||||
Q_UNUSED(pointCount);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawPolygon()
|
||||
void QwtNullPaintDevice::drawPolygon(
|
||||
const QPointF *points, int pointCount,
|
||||
QPaintEngine::PolygonDrawMode mode)
|
||||
{
|
||||
Q_UNUSED(points);
|
||||
Q_UNUSED(pointCount);
|
||||
Q_UNUSED(mode);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawPolygon()
|
||||
void QwtNullPaintDevice::drawPolygon(
|
||||
const QPoint *points, int pointCount,
|
||||
QPaintEngine::PolygonDrawMode mode)
|
||||
{
|
||||
Q_UNUSED(points);
|
||||
Q_UNUSED(pointCount);
|
||||
Q_UNUSED(mode);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawPixmap()
|
||||
void QwtNullPaintDevice::drawPixmap( const QRectF &rect,
|
||||
const QPixmap &pm, const QRectF &subRect )
|
||||
{
|
||||
Q_UNUSED(rect);
|
||||
Q_UNUSED(pm);
|
||||
Q_UNUSED(subRect);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawTextItem()
|
||||
void QwtNullPaintDevice::drawTextItem(
|
||||
const QPointF &pos, const QTextItem &textItem)
|
||||
{
|
||||
Q_UNUSED(pos);
|
||||
Q_UNUSED(textItem);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawTiledPixmap()
|
||||
void QwtNullPaintDevice::drawTiledPixmap(
|
||||
const QRectF &rect, const QPixmap &pixmap,
|
||||
const QPointF &subRect)
|
||||
{
|
||||
Q_UNUSED(rect);
|
||||
Q_UNUSED(pixmap);
|
||||
Q_UNUSED(subRect);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::drawImage()
|
||||
void QwtNullPaintDevice::drawImage(
|
||||
const QRectF &rect, const QImage &image,
|
||||
const QRectF &subRect, Qt::ImageConversionFlags flags)
|
||||
{
|
||||
Q_UNUSED(rect);
|
||||
Q_UNUSED(image);
|
||||
Q_UNUSED(subRect);
|
||||
Q_UNUSED(flags);
|
||||
}
|
||||
|
||||
//! See QPaintEngine::updateState()
|
||||
void QwtNullPaintDevice::updateState(
|
||||
const QPaintEngineState &state )
|
||||
{
|
||||
Q_UNUSED(state);
|
||||
}
|
||||
126
third/3rd_qwt/qwt_null_paintdevice.h
Normal file
126
third/3rd_qwt/qwt_null_paintdevice.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_NULL_PAINT_DEVICE_H
|
||||
#define QWT_NULL_PAINT_DEVICE_H 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qpaintdevice.h>
|
||||
#include <qpaintengine.h>
|
||||
|
||||
/*!
|
||||
\brief A null paint device doing nothing
|
||||
|
||||
Sometimes important layout/rendering geometries are not
|
||||
available or changeable from the public Qt class interface.
|
||||
( f.e hidden in the style implementation ).
|
||||
|
||||
QwtNullPaintDevice can be used to manipulate or filter out
|
||||
this information by analyzing the stream of paint primitives.
|
||||
|
||||
F.e. QwtNullPaintDevice is used by QwtPlotCanvas to identify
|
||||
styled backgrounds with rounded corners.
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtNullPaintDevice: public QPaintDevice
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
\brief Render mode
|
||||
|
||||
\sa setMode(), mode()
|
||||
*/
|
||||
enum Mode
|
||||
{
|
||||
/*!
|
||||
All vector graphic primitives are painted by
|
||||
the corresponding draw methods
|
||||
*/
|
||||
NormalMode,
|
||||
|
||||
/*!
|
||||
Vector graphic primitives ( beside polygons ) are mapped to a QPainterPath
|
||||
and are painted by drawPath. In PathMode mode
|
||||
only a few draw methods are called:
|
||||
|
||||
- drawPath()
|
||||
- drawPixmap()
|
||||
- drawImage()
|
||||
- drawPolygon()
|
||||
*/
|
||||
PolygonPathMode,
|
||||
|
||||
/*!
|
||||
Vector graphic primitives are mapped to a QPainterPath
|
||||
and are painted by drawPath. In PathMode mode
|
||||
only a few draw methods are called:
|
||||
|
||||
- drawPath()
|
||||
- drawPixmap()
|
||||
- drawImage()
|
||||
*/
|
||||
PathMode
|
||||
};
|
||||
|
||||
QwtNullPaintDevice();
|
||||
virtual ~QwtNullPaintDevice();
|
||||
|
||||
void setMode( Mode );
|
||||
Mode mode() const;
|
||||
|
||||
virtual QPaintEngine *paintEngine() const;
|
||||
|
||||
virtual int metric( PaintDeviceMetric ) const;
|
||||
|
||||
virtual void drawRects(const QRect *, int );
|
||||
virtual void drawRects(const QRectF *, int );
|
||||
|
||||
virtual void drawLines(const QLine *, int );
|
||||
virtual void drawLines(const QLineF *, int );
|
||||
|
||||
virtual void drawEllipse(const QRectF &);
|
||||
virtual void drawEllipse(const QRect &);
|
||||
|
||||
virtual void drawPath(const QPainterPath &);
|
||||
|
||||
virtual void drawPoints(const QPointF *, int );
|
||||
virtual void drawPoints(const QPoint *, int );
|
||||
|
||||
virtual void drawPolygon(
|
||||
const QPointF *, int , QPaintEngine::PolygonDrawMode );
|
||||
|
||||
virtual void drawPolygon(
|
||||
const QPoint *, int , QPaintEngine::PolygonDrawMode );
|
||||
|
||||
virtual void drawPixmap(const QRectF &,
|
||||
const QPixmap &, const QRectF &);
|
||||
|
||||
virtual void drawTextItem(const QPointF &, const QTextItem &);
|
||||
|
||||
virtual void drawTiledPixmap(const QRectF &,
|
||||
const QPixmap &, const QPointF & );
|
||||
|
||||
virtual void drawImage(const QRectF &,
|
||||
const QImage &, const QRectF &, Qt::ImageConversionFlags );
|
||||
|
||||
virtual void updateState( const QPaintEngineState & );
|
||||
|
||||
protected:
|
||||
//! \return Size needed to implement metric()
|
||||
virtual QSize sizeMetrics() const = 0;
|
||||
|
||||
private:
|
||||
class PaintEngine;
|
||||
PaintEngine *d_engine;
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
1312
third/3rd_qwt/qwt_painter.cpp
Normal file
1312
third/3rd_qwt/qwt_painter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
188
third/3rd_qwt/qwt_painter.h
Normal file
188
third/3rd_qwt/qwt_painter.h
Normal file
@@ -0,0 +1,188 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PAINTER_H
|
||||
#define QWT_PAINTER_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
|
||||
#include <qpoint.h>
|
||||
#include <qrect.h>
|
||||
#include <qpen.h>
|
||||
#include <qline.h>
|
||||
#include <qpalette.h>
|
||||
|
||||
class QPainter;
|
||||
class QBrush;
|
||||
class QColor;
|
||||
class QWidget;
|
||||
class QPolygonF;
|
||||
class QRectF;
|
||||
class QImage;
|
||||
class QPixmap;
|
||||
class QwtScaleMap;
|
||||
class QwtColorMap;
|
||||
class QwtInterval;
|
||||
|
||||
class QTextDocument;
|
||||
class QPainterPath;
|
||||
|
||||
/*!
|
||||
\brief A collection of QPainter workarounds
|
||||
*/
|
||||
class QWT_EXPORT QwtPainter
|
||||
{
|
||||
public:
|
||||
static void setPolylineSplitting( bool );
|
||||
static bool polylineSplitting();
|
||||
|
||||
static void setRoundingAlignment( bool );
|
||||
static bool roundingAlignment();
|
||||
static bool roundingAlignment(QPainter *);
|
||||
|
||||
static void drawText( QPainter *, double x, double y, const QString & );
|
||||
static void drawText( QPainter *, const QPointF &, const QString & );
|
||||
static void drawText( QPainter *, double x, double y, double w, double h,
|
||||
int flags, const QString & );
|
||||
static void drawText( QPainter *, const QRectF &,
|
||||
int flags, const QString & );
|
||||
|
||||
#ifndef QT_NO_RICHTEXT
|
||||
static void drawSimpleRichText( QPainter *, const QRectF &,
|
||||
int flags, const QTextDocument & );
|
||||
#endif
|
||||
|
||||
static void drawRect( QPainter *, double x, double y, double w, double h );
|
||||
static void drawRect( QPainter *, const QRectF &rect );
|
||||
static void fillRect( QPainter *, const QRectF &, const QBrush & );
|
||||
|
||||
static void drawEllipse( QPainter *, const QRectF & );
|
||||
static void drawPie( QPainter *, const QRectF &, int a, int alen );
|
||||
|
||||
static void drawLine( QPainter *, double x1, double y1, double x2, double y2 );
|
||||
static void drawLine( QPainter *, const QPointF &p1, const QPointF &p2 );
|
||||
static void drawLine( QPainter *, const QLineF & );
|
||||
|
||||
static void drawPolygon( QPainter *, const QPolygonF & );
|
||||
static void drawPolyline( QPainter *, const QPolygonF & );
|
||||
static void drawPolyline( QPainter *, const QPointF *, int pointCount );
|
||||
|
||||
static void drawPolygon( QPainter *, const QPolygon & );
|
||||
static void drawPolyline( QPainter *, const QPolygon & );
|
||||
static void drawPolyline( QPainter *, const QPoint *, int pointCount );
|
||||
|
||||
static void drawPoint( QPainter *, const QPoint & );
|
||||
static void drawPoints( QPainter *, const QPolygon & );
|
||||
static void drawPoints( QPainter *, const QPoint *, int pointCount );
|
||||
|
||||
static void drawPoint( QPainter *, double x, double y );
|
||||
static void drawPoint( QPainter *, const QPointF & );
|
||||
static void drawPoints( QPainter *, const QPolygonF & );
|
||||
static void drawPoints( QPainter *, const QPointF *, int pointCount );
|
||||
|
||||
static void drawPath( QPainter *, const QPainterPath & );
|
||||
static void drawImage( QPainter *, const QRectF &, const QImage & );
|
||||
static void drawPixmap( QPainter *, const QRectF &, const QPixmap & );
|
||||
|
||||
static void drawRoundFrame( QPainter *,
|
||||
const QRectF &, const QPalette &, int lineWidth, int frameStyle );
|
||||
|
||||
static void drawRoundedFrame( QPainter *,
|
||||
const QRectF &, double xRadius, double yRadius,
|
||||
const QPalette &, int lineWidth, int frameStyle );
|
||||
|
||||
static void drawFrame( QPainter *, const QRectF &rect,
|
||||
const QPalette &palette, QPalette::ColorRole foregroundRole,
|
||||
int frameWidth, int midLineWidth, int frameStyle );
|
||||
|
||||
static void drawFocusRect( QPainter *, const QWidget * );
|
||||
static void drawFocusRect( QPainter *, const QWidget *, const QRect & );
|
||||
|
||||
static void drawColorBar( QPainter *painter,
|
||||
const QwtColorMap &, const QwtInterval &,
|
||||
const QwtScaleMap &, Qt::Orientation, const QRectF & );
|
||||
|
||||
static bool isAligning( QPainter *painter );
|
||||
static bool isX11GraphicsSystem();
|
||||
|
||||
static void fillPixmap( const QWidget *,
|
||||
QPixmap &, const QPoint &offset = QPoint() );
|
||||
|
||||
static void drawBackgound( QPainter *painter,
|
||||
const QRectF &rect, const QWidget *widget );
|
||||
|
||||
static QPixmap backingStore( QWidget *, const QSize & );
|
||||
|
||||
private:
|
||||
static bool d_polylineSplitting;
|
||||
static bool d_roundingAlignment;
|
||||
};
|
||||
|
||||
//! Wrapper for QPainter::drawPoint()
|
||||
inline void QwtPainter::drawPoint( QPainter *painter, double x, double y )
|
||||
{
|
||||
QwtPainter::drawPoint( painter, QPointF( x, y ) );
|
||||
}
|
||||
|
||||
//! Wrapper for QPainter::drawPoints()
|
||||
inline void QwtPainter::drawPoints( QPainter *painter, const QPolygon &polygon )
|
||||
{
|
||||
drawPoints( painter, polygon.data(), polygon.size() );
|
||||
}
|
||||
|
||||
//! Wrapper for QPainter::drawPoints()
|
||||
inline void QwtPainter::drawPoints( QPainter *painter, const QPolygonF &polygon )
|
||||
{
|
||||
drawPoints( painter, polygon.data(), polygon.size() );
|
||||
}
|
||||
|
||||
//! Wrapper for QPainter::drawLine()
|
||||
inline void QwtPainter::drawLine( QPainter *painter,
|
||||
double x1, double y1, double x2, double y2 )
|
||||
{
|
||||
QwtPainter::drawLine( painter, QPointF( x1, y1 ), QPointF( x2, y2 ) );
|
||||
}
|
||||
|
||||
//! Wrapper for QPainter::drawLine()
|
||||
inline void QwtPainter::drawLine( QPainter *painter, const QLineF &line )
|
||||
{
|
||||
QwtPainter::drawLine( painter, line.p1(), line.p2() );
|
||||
}
|
||||
|
||||
/*!
|
||||
\return True, when line splitting for the raster paint engine is enabled.
|
||||
\sa setPolylineSplitting()
|
||||
*/
|
||||
inline bool QwtPainter::polylineSplitting()
|
||||
{
|
||||
return d_polylineSplitting;
|
||||
}
|
||||
|
||||
/*!
|
||||
Check whether coordinates should be rounded, before they are painted
|
||||
to a paint engine that rounds to integer values. For other paint engines
|
||||
( PDF, SVG ), this flag has no effect.
|
||||
|
||||
\return True, when rounding is enabled
|
||||
\sa setRoundingAlignment(), isAligning()
|
||||
*/
|
||||
inline bool QwtPainter::roundingAlignment()
|
||||
{
|
||||
return d_roundingAlignment;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return roundingAlignment() && isAligning(painter);
|
||||
\param painter Painter
|
||||
*/
|
||||
inline bool QwtPainter::roundingAlignment(QPainter *painter)
|
||||
{
|
||||
return d_roundingAlignment && isAligning(painter);
|
||||
}
|
||||
#endif
|
||||
237
third/3rd_qwt/qwt_painter_command.cpp
Normal file
237
third/3rd_qwt/qwt_painter_command.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/* -*- 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_painter_command.h"
|
||||
|
||||
//! Construct an invalid command
|
||||
QwtPainterCommand::QwtPainterCommand():
|
||||
d_type( Invalid )
|
||||
{
|
||||
}
|
||||
|
||||
//! Copy constructor
|
||||
QwtPainterCommand::QwtPainterCommand( const QPainterPath &path ):
|
||||
d_type( Path )
|
||||
{
|
||||
d_path = new QPainterPath( path );
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructor for Pixmap paint operation
|
||||
|
||||
\param rect Target rectangle
|
||||
\param pixmap Pixmap
|
||||
\param subRect Rectangle inside the pixmap
|
||||
|
||||
\sa QPainter::drawPixmap()
|
||||
*/
|
||||
QwtPainterCommand::QwtPainterCommand( const QRectF &rect,
|
||||
const QPixmap &pixmap, const QRectF& subRect ):
|
||||
d_type( Pixmap )
|
||||
{
|
||||
d_pixmapData = new PixmapData();
|
||||
d_pixmapData->rect = rect;
|
||||
d_pixmapData->pixmap = pixmap;
|
||||
d_pixmapData->subRect = subRect;
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructor for Image paint operation
|
||||
|
||||
\param rect Target rectangle
|
||||
\param image Image
|
||||
\param subRect Rectangle inside the image
|
||||
\param flags Conversion flags
|
||||
|
||||
\sa QPainter::drawImage()
|
||||
*/
|
||||
QwtPainterCommand::QwtPainterCommand( const QRectF &rect,
|
||||
const QImage &image, const QRectF& subRect,
|
||||
Qt::ImageConversionFlags flags ):
|
||||
d_type( Image )
|
||||
{
|
||||
d_imageData = new ImageData();
|
||||
d_imageData->rect = rect;
|
||||
d_imageData->image = image;
|
||||
d_imageData->subRect = subRect;
|
||||
d_imageData->flags = flags;
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructor for State paint operation
|
||||
\param state Paint engine state
|
||||
*/
|
||||
QwtPainterCommand::QwtPainterCommand( const QPaintEngineState &state ):
|
||||
d_type( State )
|
||||
{
|
||||
d_stateData = new StateData();
|
||||
|
||||
d_stateData->flags = state.state();
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyPen )
|
||||
d_stateData->pen = state.pen();
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyBrush )
|
||||
d_stateData->brush = state.brush();
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyBrushOrigin )
|
||||
d_stateData->brushOrigin = state.brushOrigin();
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyFont )
|
||||
d_stateData->font = state.font();
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyBackground )
|
||||
{
|
||||
d_stateData->backgroundMode = state.backgroundMode();
|
||||
d_stateData->backgroundBrush = state.backgroundBrush();
|
||||
}
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyTransform )
|
||||
d_stateData->transform = state.transform();
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyClipEnabled )
|
||||
d_stateData->isClipEnabled = state.isClipEnabled();
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyClipRegion )
|
||||
{
|
||||
d_stateData->clipRegion = state.clipRegion();
|
||||
d_stateData->clipOperation = state.clipOperation();
|
||||
}
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyClipPath )
|
||||
{
|
||||
d_stateData->clipPath = state.clipPath();
|
||||
d_stateData->clipOperation = state.clipOperation();
|
||||
}
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyHints )
|
||||
d_stateData->renderHints = state.renderHints();
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyCompositionMode )
|
||||
d_stateData->compositionMode = state.compositionMode();
|
||||
|
||||
if ( d_stateData->flags & QPaintEngine::DirtyOpacity )
|
||||
d_stateData->opacity = state.opacity();
|
||||
}
|
||||
|
||||
/*!
|
||||
Copy constructor
|
||||
\param other Command to be copied
|
||||
|
||||
*/
|
||||
QwtPainterCommand::QwtPainterCommand(const QwtPainterCommand &other)
|
||||
{
|
||||
copy( other );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtPainterCommand::~QwtPainterCommand()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
Assignment operator
|
||||
|
||||
\param other Command to be copied
|
||||
\return Modified command
|
||||
*/
|
||||
QwtPainterCommand &QwtPainterCommand::operator=(const QwtPainterCommand &other)
|
||||
{
|
||||
reset();
|
||||
copy( other );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void QwtPainterCommand::copy( const QwtPainterCommand &other )
|
||||
{
|
||||
d_type = other.d_type;
|
||||
|
||||
switch( other.d_type )
|
||||
{
|
||||
case Path:
|
||||
{
|
||||
d_path = new QPainterPath( *other.d_path );
|
||||
break;
|
||||
}
|
||||
case Pixmap:
|
||||
{
|
||||
d_pixmapData = new PixmapData( *other.d_pixmapData );
|
||||
break;
|
||||
}
|
||||
case Image:
|
||||
{
|
||||
d_imageData = new ImageData( *other.d_imageData );
|
||||
break;
|
||||
}
|
||||
case State:
|
||||
{
|
||||
d_stateData = new StateData( *other.d_stateData );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QwtPainterCommand::reset()
|
||||
{
|
||||
switch( d_type )
|
||||
{
|
||||
case Path:
|
||||
{
|
||||
delete d_path;
|
||||
break;
|
||||
}
|
||||
case Pixmap:
|
||||
{
|
||||
delete d_pixmapData;
|
||||
break;
|
||||
}
|
||||
case Image:
|
||||
{
|
||||
delete d_imageData;
|
||||
break;
|
||||
}
|
||||
case State:
|
||||
{
|
||||
delete d_stateData;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
d_type = Invalid;
|
||||
}
|
||||
|
||||
//! \return Painter path to be painted
|
||||
QPainterPath *QwtPainterCommand::path()
|
||||
{
|
||||
return d_path;
|
||||
}
|
||||
|
||||
//! \return Attributes how to paint a QPixmap
|
||||
QwtPainterCommand::PixmapData* QwtPainterCommand::pixmapData()
|
||||
{
|
||||
return d_pixmapData;
|
||||
}
|
||||
|
||||
//! \return Attributes how to paint a QImage
|
||||
QwtPainterCommand::ImageData* QwtPainterCommand::imageData()
|
||||
{
|
||||
return d_imageData;
|
||||
}
|
||||
|
||||
//! \return Attributes of a state change
|
||||
QwtPainterCommand::StateData* QwtPainterCommand::stateData()
|
||||
{
|
||||
return d_stateData;
|
||||
}
|
||||
174
third/3rd_qwt/qwt_painter_command.h
Normal file
174
third/3rd_qwt/qwt_painter_command.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PAINTER_COMMAND_H
|
||||
#define QWT_PAINTER_COMMAND_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qpaintengine.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qimage.h>
|
||||
#include <qpolygon.h>
|
||||
#include <qpainterpath.h>
|
||||
|
||||
class QPainterPath;
|
||||
|
||||
/*!
|
||||
QwtPainterCommand represents the attributes of a paint operation
|
||||
how it is used between QPainter and QPaintDevice
|
||||
|
||||
It is used by QwtGraphic to record and replay paint operations
|
||||
|
||||
\sa QwtGraphic::commands()
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtPainterCommand
|
||||
{
|
||||
public:
|
||||
//! Type of the paint command
|
||||
enum Type
|
||||
{
|
||||
//! Invalid command
|
||||
Invalid = -1,
|
||||
|
||||
//! Draw a QPainterPath
|
||||
Path,
|
||||
|
||||
//! Draw a QPixmap
|
||||
Pixmap,
|
||||
|
||||
//! Draw a QImage
|
||||
Image,
|
||||
|
||||
//! QPainter state change
|
||||
State
|
||||
};
|
||||
|
||||
//! Attributes how to paint a QPixmap
|
||||
struct PixmapData
|
||||
{
|
||||
QRectF rect;
|
||||
QPixmap pixmap;
|
||||
QRectF subRect;
|
||||
};
|
||||
|
||||
//! Attributes how to paint a QImage
|
||||
struct ImageData
|
||||
{
|
||||
QRectF rect;
|
||||
QImage image;
|
||||
QRectF subRect;
|
||||
Qt::ImageConversionFlags flags;
|
||||
};
|
||||
|
||||
//! Attributes of a state change
|
||||
struct StateData
|
||||
{
|
||||
QPaintEngine::DirtyFlags flags;
|
||||
|
||||
QPen pen;
|
||||
QBrush brush;
|
||||
QPointF brushOrigin;
|
||||
QBrush backgroundBrush;
|
||||
Qt::BGMode backgroundMode;
|
||||
QFont font;
|
||||
QMatrix matrix;
|
||||
QTransform transform;
|
||||
|
||||
Qt::ClipOperation clipOperation;
|
||||
QRegion clipRegion;
|
||||
QPainterPath clipPath;
|
||||
bool isClipEnabled;
|
||||
|
||||
QPainter::RenderHints renderHints;
|
||||
QPainter::CompositionMode compositionMode;
|
||||
qreal opacity;
|
||||
};
|
||||
|
||||
QwtPainterCommand();
|
||||
QwtPainterCommand(const QwtPainterCommand &);
|
||||
|
||||
QwtPainterCommand( const QPainterPath & );
|
||||
|
||||
QwtPainterCommand( const QRectF &rect,
|
||||
const QPixmap &, const QRectF& subRect );
|
||||
|
||||
QwtPainterCommand( const QRectF &rect,
|
||||
const QImage &, const QRectF& subRect,
|
||||
Qt::ImageConversionFlags );
|
||||
|
||||
QwtPainterCommand( const QPaintEngineState & );
|
||||
|
||||
~QwtPainterCommand();
|
||||
|
||||
QwtPainterCommand &operator=(const QwtPainterCommand & );
|
||||
|
||||
Type type() const;
|
||||
|
||||
QPainterPath *path();
|
||||
const QPainterPath *path() const;
|
||||
|
||||
PixmapData* pixmapData();
|
||||
const PixmapData* pixmapData() const;
|
||||
|
||||
ImageData* imageData();
|
||||
const ImageData* imageData() const;
|
||||
|
||||
StateData* stateData();
|
||||
const StateData* stateData() const;
|
||||
|
||||
private:
|
||||
void copy( const QwtPainterCommand & );
|
||||
void reset();
|
||||
|
||||
Type d_type;
|
||||
|
||||
union
|
||||
{
|
||||
QPainterPath *d_path;
|
||||
PixmapData *d_pixmapData;
|
||||
ImageData *d_imageData;
|
||||
StateData *d_stateData;
|
||||
};
|
||||
};
|
||||
|
||||
//! \return Type of the command
|
||||
inline QwtPainterCommand::Type QwtPainterCommand::type() const
|
||||
{
|
||||
return d_type;
|
||||
}
|
||||
|
||||
//! \return Painter path to be painted
|
||||
inline const QPainterPath *QwtPainterCommand::path() const
|
||||
{
|
||||
return d_path;
|
||||
}
|
||||
|
||||
//! \return Attributes how to paint a QPixmap
|
||||
inline const QwtPainterCommand::PixmapData *
|
||||
QwtPainterCommand::pixmapData() const
|
||||
{
|
||||
return d_pixmapData;
|
||||
}
|
||||
|
||||
//! \return Attributes how to paint a QImage
|
||||
inline const QwtPainterCommand::ImageData *
|
||||
QwtPainterCommand::imageData() const
|
||||
{
|
||||
return d_imageData;
|
||||
}
|
||||
|
||||
//! \return Attributes of a state change
|
||||
inline const QwtPainterCommand::StateData *
|
||||
QwtPainterCommand::stateData() const
|
||||
{
|
||||
return d_stateData;
|
||||
}
|
||||
|
||||
#endif
|
||||
542
third/3rd_qwt/qwt_panner.cpp
Normal file
542
third/3rd_qwt/qwt_panner.cpp
Normal file
@@ -0,0 +1,542 @@
|
||||
/* -*- 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"
|
||||
#include <qpainter.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qevent.h>
|
||||
#include <qcursor.h>
|
||||
#include <qbitmap.h>
|
||||
|
||||
static QVector<QwtPicker *> qwtActivePickers( QWidget *w )
|
||||
{
|
||||
QVector<QwtPicker *> pickers;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return pickers;
|
||||
}
|
||||
|
||||
class QwtPanner::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
button( Qt::LeftButton ),
|
||||
buttonModifiers( Qt::NoModifier ),
|
||||
abortKey( Qt::Key_Escape ),
|
||||
abortKeyModifiers( Qt::NoModifier ),
|
||||
#ifndef QT_NO_CURSOR
|
||||
cursor( NULL ),
|
||||
restoreCursor( NULL ),
|
||||
hasCursor( false ),
|
||||
#endif
|
||||
isEnabled( false )
|
||||
{
|
||||
orientations = Qt::Vertical | Qt::Horizontal;
|
||||
}
|
||||
|
||||
~PrivateData()
|
||||
{
|
||||
#ifndef QT_NO_CURSOR
|
||||
delete cursor;
|
||||
delete restoreCursor;
|
||||
#endif
|
||||
}
|
||||
|
||||
Qt::MouseButton button;
|
||||
Qt::KeyboardModifiers buttonModifiers;
|
||||
|
||||
int abortKey;
|
||||
Qt::KeyboardModifiers abortKeyModifiers;
|
||||
|
||||
QPoint initialPos;
|
||||
QPoint pos;
|
||||
|
||||
QPixmap pixmap;
|
||||
QBitmap contentsMask;
|
||||
|
||||
#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 )
|
||||
{
|
||||
d_data = new PrivateData();
|
||||
|
||||
setAttribute( Qt::WA_TransparentForMouseEvents );
|
||||
setAttribute( Qt::WA_NoSystemBackground );
|
||||
setFocusPolicy( Qt::NoFocus );
|
||||
hide();
|
||||
|
||||
setEnabled( true );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtPanner::~QwtPanner()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the mouse button and modifiers used for panning
|
||||
The defaults are Qt::LeftButton and Qt::NoModifier
|
||||
*/
|
||||
void QwtPanner::setMouseButton( Qt::MouseButton button,
|
||||
Qt::KeyboardModifiers modifiers )
|
||||
{
|
||||
d_data->button = button;
|
||||
d_data->buttonModifiers = modifiers;
|
||||
}
|
||||
|
||||
//! Get mouse button and modifiers used for panning
|
||||
void QwtPanner::getMouseButton( Qt::MouseButton &button,
|
||||
Qt::KeyboardModifiers &modifiers ) const
|
||||
{
|
||||
button = d_data->button;
|
||||
modifiers = d_data->buttonModifiers;
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the abort key
|
||||
The defaults are Qt::Key_Escape and Qt::NoModifiers
|
||||
|
||||
\param key Key ( See Qt::Keycode )
|
||||
\param modifiers Keyboard modifiers
|
||||
*/
|
||||
void QwtPanner::setAbortKey( int key,
|
||||
Qt::KeyboardModifiers modifiers )
|
||||
{
|
||||
d_data->abortKey = key;
|
||||
d_data->abortKeyModifiers = modifiers;
|
||||
}
|
||||
|
||||
//! Get the abort key and modifiers
|
||||
void QwtPanner::getAbortKey( int &key,
|
||||
Qt::KeyboardModifiers &modifiers ) const
|
||||
{
|
||||
key = d_data->abortKey;
|
||||
modifiers = d_data->abortKeyModifiers;
|
||||
}
|
||||
|
||||
/*!
|
||||
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 )
|
||||
{
|
||||
d_data->cursor = new QCursor( cursor );
|
||||
}
|
||||
#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
|
||||
|
||||
/*!
|
||||
\brief En/disable the panner
|
||||
|
||||
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 )
|
||||
{
|
||||
if ( d_data->isEnabled != on )
|
||||
{
|
||||
d_data->isEnabled = on;
|
||||
|
||||
QWidget *w = parentWidget();
|
||||
if ( w )
|
||||
{
|
||||
if ( d_data->isEnabled )
|
||||
{
|
||||
w->installEventFilter( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
w->removeEventFilter( this );
|
||||
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 )
|
||||
{
|
||||
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
|
||||
\sa orientations(), setOrientations()
|
||||
*/
|
||||
bool QwtPanner::isOrientationEnabled( Qt::Orientation o ) const
|
||||
{
|
||||
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 event Paint event
|
||||
*/
|
||||
void QwtPanner::paintEvent( QPaintEvent *event )
|
||||
{
|
||||
int dx = d_data->pos.x() - d_data->initialPos.x();
|
||||
int dy = d_data->pos.y() - d_data->initialPos.y();
|
||||
|
||||
QRectF r;
|
||||
r.setSize( d_data->pixmap.size() );
|
||||
#if QT_VERSION >= 0x050000
|
||||
r.setSize( r.size() / d_data->pixmap.devicePixelRatio() );
|
||||
#endif
|
||||
r.moveCenter( QPointF( r.center().x() + dx, r.center().y() + dy ) );
|
||||
|
||||
QPixmap pm = QwtPainter::backingStore( this, size() );
|
||||
QwtPainter::fillPixmap( parentWidget(), pm );
|
||||
|
||||
QPainter painter( &pm );
|
||||
|
||||
if ( !d_data->contentsMask.isNull() )
|
||||
{
|
||||
QPixmap masked = d_data->pixmap;
|
||||
masked.setMask( d_data->contentsMask );
|
||||
painter.drawPixmap( r.toRect(), masked );
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.drawPixmap( r.toRect(), d_data->pixmap );
|
||||
}
|
||||
|
||||
painter.end();
|
||||
|
||||
if ( !d_data->contentsMask.isNull() )
|
||||
pm.setMask( d_data->contentsMask );
|
||||
|
||||
painter.begin( this );
|
||||
painter.setClipRegion( event->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
|
||||
}
|
||||
|
||||
/*!
|
||||
\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.
|
||||
|
||||
\sa widgetMousePressEvent(), widgetMouseReleaseEvent(),
|
||||
widgetMouseMoveEvent()
|
||||
*/
|
||||
bool QwtPanner::eventFilter( QObject *object, QEvent *event )
|
||||
{
|
||||
if ( object == NULL || object != parentWidget() )
|
||||
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:;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a mouse press event for the observed widget.
|
||||
|
||||
\param mouseEvent Mouse event
|
||||
\sa eventFilter(), widgetMouseReleaseEvent(),
|
||||
widgetMouseMoveEvent(),
|
||||
*/
|
||||
void QwtPanner::widgetMousePressEvent( QMouseEvent *mouseEvent )
|
||||
{
|
||||
if ( ( mouseEvent->button() != d_data->button )
|
||||
|| ( mouseEvent->modifiers() != d_data->buttonModifiers ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget *w = parentWidget();
|
||||
if ( w == NULL )
|
||||
return;
|
||||
|
||||
#ifndef QT_NO_CURSOR
|
||||
showCursor( true );
|
||||
#endif
|
||||
|
||||
d_data->initialPos = d_data->pos = mouseEvent->pos();
|
||||
|
||||
setGeometry( parentWidget()->rect() );
|
||||
|
||||
// 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 );
|
||||
|
||||
d_data->pixmap = grab();
|
||||
d_data->contentsMask = contentsMask();
|
||||
|
||||
for ( int i = 0; i < pickers.size(); i++ )
|
||||
pickers[i]->setEnabled( true );
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a mouse move event for the observed widget.
|
||||
|
||||
\param mouseEvent Mouse event
|
||||
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent()
|
||||
*/
|
||||
void QwtPanner::widgetMouseMoveEvent( QMouseEvent *mouseEvent )
|
||||
{
|
||||
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() );
|
||||
|
||||
if ( pos != d_data->pos && rect().contains( pos ) )
|
||||
{
|
||||
d_data->pos = pos;
|
||||
update();
|
||||
|
||||
Q_EMIT moved( d_data->pos.x() - d_data->initialPos.x(),
|
||||
d_data->pos.y() - d_data->initialPos.y() );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a mouse release event for the observed widget.
|
||||
|
||||
\param mouseEvent Mouse event
|
||||
\sa eventFilter(), widgetMousePressEvent(),
|
||||
widgetMouseMoveEvent(),
|
||||
*/
|
||||
void QwtPanner::widgetMouseReleaseEvent( QMouseEvent *mouseEvent )
|
||||
{
|
||||
if ( isVisible() )
|
||||
{
|
||||
hide();
|
||||
#ifndef QT_NO_CURSOR
|
||||
showCursor( false );
|
||||
#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() );
|
||||
|
||||
d_data->pixmap = QPixmap();
|
||||
d_data->contentsMask = QBitmap();
|
||||
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() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a key press event for the observed widget.
|
||||
|
||||
\param keyEvent Key event
|
||||
\sa eventFilter(), widgetKeyReleaseEvent()
|
||||
*/
|
||||
void QwtPanner::widgetKeyPressEvent( QKeyEvent *keyEvent )
|
||||
{
|
||||
if ( ( keyEvent->key() == d_data->abortKey )
|
||||
&& ( keyEvent->modifiers() == d_data->abortKeyModifiers ) )
|
||||
{
|
||||
hide();
|
||||
|
||||
#ifndef QT_NO_CURSOR
|
||||
showCursor( false );
|
||||
#endif
|
||||
d_data->pixmap = QPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle a key release event for the observed widget.
|
||||
|
||||
\param keyEvent Key event
|
||||
\sa eventFilter(), widgetKeyReleaseEvent()
|
||||
*/
|
||||
void QwtPanner::widgetKeyReleaseEvent( QKeyEvent *keyEvent )
|
||||
{
|
||||
Q_UNUSED( keyEvent );
|
||||
}
|
||||
|
||||
#ifndef QT_NO_CURSOR
|
||||
void QwtPanner::showCursor( bool on )
|
||||
{
|
||||
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 ) )
|
||||
{
|
||||
delete d_data->restoreCursor;
|
||||
d_data->restoreCursor = new QCursor( w->cursor() );
|
||||
}
|
||||
w->setCursor( *d_data->cursor );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( d_data->restoreCursor )
|
||||
{
|
||||
w->setCursor( *d_data->restoreCursor );
|
||||
delete d_data->restoreCursor;
|
||||
d_data->restoreCursor = NULL;
|
||||
}
|
||||
else
|
||||
w->unsetCursor();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
103
third/3rd_qwt/qwt_panner.h
Normal file
103
third/3rd_qwt/qwt_panner.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PANNER_H
|
||||
#define QWT_PANNER_H 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qwidget.h>
|
||||
#include <qpixmap.h>
|
||||
|
||||
class QCursor;
|
||||
|
||||
/*!
|
||||
\brief QwtPanner provides panning of a widget
|
||||
|
||||
QwtPanner grabs the contents of a widget, that can be dragged
|
||||
in all directions. The offset between the start and the end position
|
||||
is emitted by the panned signal.
|
||||
|
||||
QwtPanner grabs the content of the widget into a pixmap and moves
|
||||
the pixmap around, without initiating any repaint events for the widget.
|
||||
Areas, that are not part of content are not painted while panning.
|
||||
This makes panning fast enough for widgets, where
|
||||
repaints are too slow for mouse movements.
|
||||
|
||||
For widgets, where repaints are very fast it might be better to
|
||||
implement panning manually by mapping mouse events into paint events.
|
||||
*/
|
||||
class QWT_EXPORT QwtPanner: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QwtPanner( QWidget* parent );
|
||||
virtual ~QwtPanner();
|
||||
|
||||
void setEnabled( bool );
|
||||
bool isEnabled() const;
|
||||
|
||||
void setMouseButton( Qt::MouseButton,
|
||||
Qt::KeyboardModifiers = Qt::NoModifier );
|
||||
void getMouseButton( Qt::MouseButton &button,
|
||||
Qt::KeyboardModifiers & ) const;
|
||||
|
||||
void setAbortKey( int key, Qt::KeyboardModifiers = Qt::NoModifier );
|
||||
void getAbortKey( int &key, Qt::KeyboardModifiers & ) const;
|
||||
|
||||
void setCursor( const QCursor & );
|
||||
const QCursor cursor() const;
|
||||
|
||||
void setOrientations( Qt::Orientations );
|
||||
Qt::Orientations orientations() const;
|
||||
|
||||
bool isOrientationEnabled( Qt::Orientation ) const;
|
||||
|
||||
virtual bool eventFilter( QObject *, QEvent * );
|
||||
|
||||
Q_SIGNALS:
|
||||
/*!
|
||||
Signal emitted, when panning is done
|
||||
|
||||
\param dx Offset in horizontal direction
|
||||
\param dy Offset in vertical direction
|
||||
*/
|
||||
void panned( int dx, int dy );
|
||||
|
||||
/*!
|
||||
Signal emitted, while the widget moved, but panning
|
||||
is not finished.
|
||||
|
||||
\param dx Offset in horizontal direction
|
||||
\param dy Offset in vertical direction
|
||||
*/
|
||||
void moved( int dx, int dy );
|
||||
|
||||
protected:
|
||||
virtual void widgetMousePressEvent( QMouseEvent * );
|
||||
virtual void widgetMouseReleaseEvent( QMouseEvent * );
|
||||
virtual void widgetMouseMoveEvent( QMouseEvent * );
|
||||
virtual void widgetKeyPressEvent( QKeyEvent * );
|
||||
virtual void widgetKeyReleaseEvent( QKeyEvent * );
|
||||
|
||||
virtual void paintEvent( QPaintEvent * );
|
||||
|
||||
virtual QBitmap contentsMask() const;
|
||||
virtual QPixmap grab() const;
|
||||
|
||||
private:
|
||||
#ifndef QT_NO_CURSOR
|
||||
void showCursor( bool );
|
||||
#endif
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
1588
third/3rd_qwt/qwt_picker.cpp
Normal file
1588
third/3rd_qwt/qwt_picker.cpp
Normal file
File diff suppressed because it is too large
Load Diff
332
third/3rd_qwt/qwt_picker.h
Normal file
332
third/3rd_qwt/qwt_picker.h
Normal file
@@ -0,0 +1,332 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PICKER
|
||||
#define QWT_PICKER 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_text.h"
|
||||
#include "qwt_event_pattern.h"
|
||||
#include <qobject.h>
|
||||
#include <qpen.h>
|
||||
#include <qfont.h>
|
||||
#include <qrect.h>
|
||||
#include <qpainterpath.h>
|
||||
|
||||
class QWidget;
|
||||
class QMouseEvent;
|
||||
class QWheelEvent;
|
||||
class QKeyEvent;
|
||||
class QwtPickerMachine;
|
||||
class QwtWidgetOverlay;
|
||||
|
||||
/*!
|
||||
\brief QwtPicker provides selections on a widget
|
||||
|
||||
QwtPicker filters all enter, leave, mouse and keyboard events of a widget
|
||||
and translates them into an array of selected points.
|
||||
|
||||
The way how the points are collected depends on type of state machine
|
||||
that is connected to the picker. Qwt offers a couple of predefined
|
||||
state machines for selecting:
|
||||
|
||||
- Nothing\n
|
||||
QwtPickerTrackerMachine
|
||||
- Single points\n
|
||||
QwtPickerClickPointMachine, QwtPickerDragPointMachine
|
||||
- Rectangles\n
|
||||
QwtPickerClickRectMachine, QwtPickerDragRectMachine
|
||||
- Polygons\n
|
||||
QwtPickerPolygonMachine
|
||||
|
||||
While these state machines cover the most common ways to collect points
|
||||
it is also possible to implement individual machines as well.
|
||||
|
||||
QwtPicker translates the picked points into a selection using the
|
||||
adjustedPoints() method. adjustedPoints() is intended to be reimplemented
|
||||
to fix up the selection according to application specific requirements.
|
||||
(F.e. when an application accepts rectangles of a fixed aspect ratio only.)
|
||||
|
||||
Optionally QwtPicker support the process of collecting points by a
|
||||
rubber band and tracker displaying a text for the current mouse
|
||||
position.
|
||||
|
||||
\par Example
|
||||
\code
|
||||
#include <qwt_picker.h>
|
||||
#include <qwt_picker_machine.h>
|
||||
|
||||
QwtPicker *picker = new QwtPicker(widget);
|
||||
picker->setStateMachine(new QwtPickerDragRectMachine);
|
||||
picker->setTrackerMode(QwtPicker::ActiveOnly);
|
||||
picker->setRubberBand(QwtPicker::RectRubberBand);
|
||||
\endcode
|
||||
\endpar
|
||||
|
||||
The state machine triggers the following commands:
|
||||
|
||||
- begin()\n
|
||||
Activate/Initialize the selection.
|
||||
- append()\n
|
||||
Add a new point
|
||||
- move() \n
|
||||
Change the position of the last point.
|
||||
- remove()\n
|
||||
Remove the last point.
|
||||
- end()\n
|
||||
Terminate the selection and call accept to validate the picked points.
|
||||
|
||||
The picker is active (isActive()), between begin() and end().
|
||||
In active state the rubber band is displayed, and the tracker is visible
|
||||
in case of trackerMode is ActiveOnly or AlwaysOn.
|
||||
|
||||
The cursor can be moved using the arrow keys. All selections can be aborted
|
||||
using the abort key. (QwtEventPattern::KeyPatternCode)
|
||||
|
||||
\warning In case of QWidget::NoFocus the focus policy of the observed
|
||||
widget is set to QWidget::WheelFocus and mouse tracking
|
||||
will be manipulated while the picker is active,
|
||||
or if trackerMode() is AlwayOn.
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtPicker: public QObject, public QwtEventPattern
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_ENUMS( RubberBand DisplayMode ResizeMode )
|
||||
|
||||
Q_PROPERTY( bool isEnabled READ isEnabled WRITE setEnabled )
|
||||
Q_PROPERTY( ResizeMode resizeMode READ resizeMode WRITE setResizeMode )
|
||||
|
||||
Q_PROPERTY( DisplayMode trackerMode READ trackerMode WRITE setTrackerMode )
|
||||
Q_PROPERTY( QPen trackerPen READ trackerPen WRITE setTrackerPen )
|
||||
Q_PROPERTY( QFont trackerFont READ trackerFont WRITE setTrackerFont )
|
||||
|
||||
Q_PROPERTY( RubberBand rubberBand READ rubberBand WRITE setRubberBand )
|
||||
Q_PROPERTY( QPen rubberBandPen READ rubberBandPen WRITE setRubberBandPen )
|
||||
|
||||
public:
|
||||
/*!
|
||||
Rubber band style
|
||||
|
||||
The default value is QwtPicker::NoRubberBand.
|
||||
\sa setRubberBand(), rubberBand()
|
||||
*/
|
||||
|
||||
enum RubberBand
|
||||
{
|
||||
//! No rubberband.
|
||||
NoRubberBand = 0,
|
||||
|
||||
//! A horizontal line ( only for QwtPickerMachine::PointSelection )
|
||||
HLineRubberBand,
|
||||
|
||||
//! A vertical line ( only for QwtPickerMachine::PointSelection )
|
||||
VLineRubberBand,
|
||||
|
||||
//! A crosshair ( only for QwtPickerMachine::PointSelection )
|
||||
CrossRubberBand,
|
||||
|
||||
//! A rectangle ( only for QwtPickerMachine::RectSelection )
|
||||
RectRubberBand,
|
||||
|
||||
//! An ellipse ( only for QwtPickerMachine::RectSelection )
|
||||
EllipseRubberBand,
|
||||
|
||||
//! A polygon ( only for QwtPickerMachine::PolygonSelection )
|
||||
PolygonRubberBand,
|
||||
|
||||
/*!
|
||||
Values >= UserRubberBand can be used to define additional
|
||||
rubber bands.
|
||||
*/
|
||||
UserRubberBand = 100
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Display mode
|
||||
\sa setTrackerMode(), trackerMode(), isActive()
|
||||
*/
|
||||
enum DisplayMode
|
||||
{
|
||||
//! Display never
|
||||
AlwaysOff,
|
||||
|
||||
//! Display always
|
||||
AlwaysOn,
|
||||
|
||||
//! Display only when the selection is active
|
||||
ActiveOnly
|
||||
};
|
||||
|
||||
/*!
|
||||
Controls what to do with the selected points of an active
|
||||
selection when the observed widget is resized.
|
||||
|
||||
The default value is QwtPicker::Stretch.
|
||||
\sa setResizeMode()
|
||||
*/
|
||||
|
||||
enum ResizeMode
|
||||
{
|
||||
//! All points are scaled according to the new size,
|
||||
Stretch,
|
||||
|
||||
//! All points remain unchanged.
|
||||
KeepSize
|
||||
};
|
||||
|
||||
explicit QwtPicker( QWidget *parent );
|
||||
explicit QwtPicker( RubberBand rubberBand,
|
||||
DisplayMode trackerMode, QWidget * );
|
||||
|
||||
virtual ~QwtPicker();
|
||||
|
||||
void setStateMachine( QwtPickerMachine * );
|
||||
const QwtPickerMachine *stateMachine() const;
|
||||
QwtPickerMachine *stateMachine();
|
||||
|
||||
void setRubberBand( RubberBand );
|
||||
RubberBand rubberBand() const;
|
||||
|
||||
void setTrackerMode( DisplayMode );
|
||||
DisplayMode trackerMode() const;
|
||||
|
||||
void setResizeMode( ResizeMode );
|
||||
ResizeMode resizeMode() const;
|
||||
|
||||
void setRubberBandPen( const QPen & );
|
||||
QPen rubberBandPen() const;
|
||||
|
||||
void setTrackerPen( const QPen & );
|
||||
QPen trackerPen() const;
|
||||
|
||||
void setTrackerFont( const QFont & );
|
||||
QFont trackerFont() const;
|
||||
|
||||
bool isEnabled() const;
|
||||
bool isActive() const;
|
||||
|
||||
virtual bool eventFilter( QObject *, QEvent * );
|
||||
|
||||
QWidget *parentWidget();
|
||||
const QWidget *parentWidget() const;
|
||||
|
||||
virtual QPainterPath pickArea() const;
|
||||
|
||||
virtual void drawRubberBand( QPainter * ) const;
|
||||
virtual void drawTracker( QPainter * ) const;
|
||||
|
||||
virtual QRegion rubberBandMask() const;
|
||||
|
||||
virtual QwtText trackerText( const QPoint &pos ) const;
|
||||
QPoint trackerPosition() const;
|
||||
virtual QRect trackerRect( const QFont & ) const;
|
||||
|
||||
QPolygon selection() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setEnabled( bool );
|
||||
|
||||
Q_SIGNALS:
|
||||
/*!
|
||||
A signal indicating, when the picker has been activated.
|
||||
Together with setEnabled() it can be used to implement
|
||||
selections with more than one picker.
|
||||
|
||||
\param on True, when the picker has been activated
|
||||
*/
|
||||
void activated( bool on );
|
||||
|
||||
/*!
|
||||
A signal emitting the selected points,
|
||||
at the end of a selection.
|
||||
|
||||
\param polygon Selected points
|
||||
*/
|
||||
void selected( const QPolygon &polygon );
|
||||
|
||||
/*!
|
||||
A signal emitted when a point has been appended to the selection
|
||||
|
||||
\param pos Position of the appended point.
|
||||
\sa append(). moved()
|
||||
*/
|
||||
void appended( const QPoint &pos );
|
||||
|
||||
/*!
|
||||
A signal emitted whenever the last appended point of the
|
||||
selection has been moved.
|
||||
|
||||
\param pos Position of the moved last point of the selection.
|
||||
\sa move(), appended()
|
||||
*/
|
||||
void moved( const QPoint &pos );
|
||||
|
||||
/*!
|
||||
A signal emitted whenever the last appended point of the
|
||||
selection has been removed.
|
||||
|
||||
\param pos Position of the point, that has been removed
|
||||
\sa remove(), appended()
|
||||
*/
|
||||
void removed( const QPoint &pos );
|
||||
/*!
|
||||
A signal emitted when the active selection has been changed.
|
||||
This might happen when the observed widget is resized.
|
||||
|
||||
\param selection Changed selection
|
||||
\sa stretchSelection()
|
||||
*/
|
||||
void changed( const QPolygon &selection );
|
||||
|
||||
protected:
|
||||
virtual QPolygon adjustedPoints( const QPolygon & ) const;
|
||||
|
||||
virtual void transition( const QEvent * );
|
||||
|
||||
virtual void begin();
|
||||
virtual void append( const QPoint & );
|
||||
virtual void move( const QPoint & );
|
||||
virtual void remove();
|
||||
virtual bool end( bool ok = true );
|
||||
|
||||
virtual bool accept( QPolygon & ) const;
|
||||
virtual void reset();
|
||||
|
||||
virtual void widgetMousePressEvent( QMouseEvent * );
|
||||
virtual void widgetMouseReleaseEvent( QMouseEvent * );
|
||||
virtual void widgetMouseDoubleClickEvent( QMouseEvent * );
|
||||
virtual void widgetMouseMoveEvent( QMouseEvent * );
|
||||
virtual void widgetWheelEvent( QWheelEvent * );
|
||||
virtual void widgetKeyPressEvent( QKeyEvent * );
|
||||
virtual void widgetKeyReleaseEvent( QKeyEvent * );
|
||||
virtual void widgetEnterEvent( QEvent * );
|
||||
virtual void widgetLeaveEvent( QEvent * );
|
||||
|
||||
virtual void stretchSelection(
|
||||
const QSize &oldSize, const QSize &newSize );
|
||||
|
||||
virtual void updateDisplay();
|
||||
|
||||
const QwtWidgetOverlay *rubberBandOverlay() const;
|
||||
const QwtWidgetOverlay *trackerOverlay() const;
|
||||
|
||||
const QPolygon &pickedPoints() const;
|
||||
|
||||
private:
|
||||
void init( QWidget *, RubberBand rubberBand, DisplayMode trackerMode );
|
||||
|
||||
void setMouseTracking( bool );
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
541
third/3rd_qwt/qwt_picker_machine.cpp
Normal file
541
third/3rd_qwt/qwt_picker_machine.cpp
Normal file
@@ -0,0 +1,541 @@
|
||||
/* -*- 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_picker_machine.h"
|
||||
#include "qwt_event_pattern.h"
|
||||
#include <qevent.h>
|
||||
|
||||
//! Constructor
|
||||
QwtPickerMachine::QwtPickerMachine( SelectionType type ):
|
||||
d_selectionType( type ),
|
||||
d_state( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtPickerMachine::~QwtPickerMachine()
|
||||
{
|
||||
}
|
||||
|
||||
//! Return the selection type
|
||||
QwtPickerMachine::SelectionType QwtPickerMachine::selectionType() const
|
||||
{
|
||||
return d_selectionType;
|
||||
}
|
||||
|
||||
//! Return the current state
|
||||
int QwtPickerMachine::state() const
|
||||
{
|
||||
return d_state;
|
||||
}
|
||||
|
||||
//! Change the current state
|
||||
void QwtPickerMachine::setState( int state )
|
||||
{
|
||||
d_state = state;
|
||||
}
|
||||
|
||||
//! Set the current state to 0.
|
||||
void QwtPickerMachine::reset()
|
||||
{
|
||||
setState( 0 );
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtPickerTrackerMachine::QwtPickerTrackerMachine():
|
||||
QwtPickerMachine( NoSelection )
|
||||
{
|
||||
}
|
||||
|
||||
//! Transition
|
||||
QList<QwtPickerMachine::Command> QwtPickerTrackerMachine::transition(
|
||||
const QwtEventPattern &, const QEvent *e )
|
||||
{
|
||||
QList<QwtPickerMachine::Command> cmdList;
|
||||
|
||||
switch ( e->type() )
|
||||
{
|
||||
case QEvent::Enter:
|
||||
case QEvent::MouseMove:
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
setState( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cmdList += Move;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::Leave:
|
||||
{
|
||||
cmdList += Remove;
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtPickerClickPointMachine::QwtPickerClickPointMachine():
|
||||
QwtPickerMachine( PointSelection )
|
||||
{
|
||||
}
|
||||
|
||||
//! Transition
|
||||
QList<QwtPickerMachine::Command> QwtPickerClickPointMachine::transition(
|
||||
const QwtEventPattern &eventPattern, const QEvent *event )
|
||||
{
|
||||
QList<QwtPickerMachine::Command> cmdList;
|
||||
|
||||
switch ( event->type() )
|
||||
{
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1,
|
||||
static_cast<const QMouseEvent *>( event ) ) )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
cmdList += End;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::KeyPress:
|
||||
{
|
||||
const QKeyEvent *keyEvent = static_cast<const QKeyEvent *> ( event );
|
||||
if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) )
|
||||
{
|
||||
if ( !keyEvent->isAutoRepeat() )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
cmdList += End;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtPickerDragPointMachine::QwtPickerDragPointMachine():
|
||||
QwtPickerMachine( PointSelection )
|
||||
{
|
||||
}
|
||||
|
||||
//! Transition
|
||||
QList<QwtPickerMachine::Command> QwtPickerDragPointMachine::transition(
|
||||
const QwtEventPattern &eventPattern, const QEvent *event )
|
||||
{
|
||||
QList<QwtPickerMachine::Command> cmdList;
|
||||
|
||||
switch ( event->type() )
|
||||
{
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1,
|
||||
static_cast<const QMouseEvent *>( event ) ) )
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
setState( 1 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::Wheel:
|
||||
{
|
||||
if ( state() != 0 )
|
||||
cmdList += Move;
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
if ( state() != 0 )
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::KeyPress:
|
||||
{
|
||||
const QKeyEvent *keyEvent = static_cast<const QKeyEvent *> ( event );
|
||||
if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) )
|
||||
{
|
||||
if ( !keyEvent->isAutoRepeat() )
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
setState( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtPickerClickRectMachine::QwtPickerClickRectMachine():
|
||||
QwtPickerMachine( RectSelection )
|
||||
{
|
||||
}
|
||||
|
||||
//! Transition
|
||||
QList<QwtPickerMachine::Command> QwtPickerClickRectMachine::transition(
|
||||
const QwtEventPattern &eventPattern, const QEvent *event )
|
||||
{
|
||||
QList<QwtPickerMachine::Command> cmdList;
|
||||
|
||||
switch ( event->type() )
|
||||
{
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1,
|
||||
static_cast<const QMouseEvent *>( event ) ) )
|
||||
{
|
||||
switch ( state() )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
setState( 1 );
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// Uh, strange we missed the MouseButtonRelease
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::Wheel:
|
||||
{
|
||||
if ( state() != 0 )
|
||||
cmdList += Move;
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1,
|
||||
static_cast<const QMouseEvent *>( event ) ) )
|
||||
{
|
||||
if ( state() == 1 )
|
||||
{
|
||||
cmdList += Append;
|
||||
setState( 2 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::KeyPress:
|
||||
{
|
||||
const QKeyEvent *keyEvent = static_cast<const QKeyEvent *> ( event );
|
||||
if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) )
|
||||
{
|
||||
if ( !keyEvent->isAutoRepeat() )
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
setState( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( state() == 1 )
|
||||
{
|
||||
cmdList += Append;
|
||||
setState( 2 );
|
||||
}
|
||||
else if ( state() == 2 )
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtPickerDragRectMachine::QwtPickerDragRectMachine():
|
||||
QwtPickerMachine( RectSelection )
|
||||
{
|
||||
}
|
||||
|
||||
//! Transition
|
||||
QList<QwtPickerMachine::Command> QwtPickerDragRectMachine::transition(
|
||||
const QwtEventPattern &eventPattern, const QEvent *event )
|
||||
{
|
||||
QList<QwtPickerMachine::Command> cmdList;
|
||||
|
||||
switch ( event->type() )
|
||||
{
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1,
|
||||
static_cast<const QMouseEvent *>( event ) ) )
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
cmdList += Append;
|
||||
setState( 2 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::Wheel:
|
||||
{
|
||||
if ( state() != 0 )
|
||||
cmdList += Move;
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
if ( state() == 2 )
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::KeyPress:
|
||||
{
|
||||
if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1,
|
||||
static_cast<const QKeyEvent *> ( event ) ) )
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
cmdList += Append;
|
||||
setState( 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtPickerPolygonMachine::QwtPickerPolygonMachine():
|
||||
QwtPickerMachine( PolygonSelection )
|
||||
{
|
||||
}
|
||||
|
||||
//! Transition
|
||||
QList<QwtPickerMachine::Command> QwtPickerPolygonMachine::transition(
|
||||
const QwtEventPattern &eventPattern, const QEvent *event )
|
||||
{
|
||||
QList<QwtPickerMachine::Command> cmdList;
|
||||
|
||||
switch ( event->type() )
|
||||
{
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1,
|
||||
static_cast<const QMouseEvent *>( event ) ) )
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
cmdList += Append;
|
||||
setState( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cmdList += Append;
|
||||
}
|
||||
}
|
||||
if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect2,
|
||||
static_cast<const QMouseEvent *>( event ) ) )
|
||||
{
|
||||
if ( state() == 1 )
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::Wheel:
|
||||
{
|
||||
if ( state() != 0 )
|
||||
cmdList += Move;
|
||||
break;
|
||||
}
|
||||
case QEvent::KeyPress:
|
||||
{
|
||||
const QKeyEvent *keyEvent = static_cast<const QKeyEvent *> ( event );
|
||||
if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) )
|
||||
{
|
||||
if ( !keyEvent->isAutoRepeat() )
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
cmdList += Append;
|
||||
setState( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cmdList += Append;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( eventPattern.keyMatch( QwtEventPattern::KeySelect2, keyEvent ) )
|
||||
{
|
||||
if ( !keyEvent->isAutoRepeat() )
|
||||
{
|
||||
if ( state() == 1 )
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
QwtPickerDragLineMachine::QwtPickerDragLineMachine():
|
||||
QwtPickerMachine( PolygonSelection )
|
||||
{
|
||||
}
|
||||
|
||||
//! Transition
|
||||
QList<QwtPickerMachine::Command> QwtPickerDragLineMachine::transition(
|
||||
const QwtEventPattern &eventPattern, const QEvent *event )
|
||||
{
|
||||
QList<QwtPickerMachine::Command> cmdList;
|
||||
|
||||
switch( event->type() )
|
||||
{
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1,
|
||||
static_cast<const QMouseEvent *>( event ) ) )
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
cmdList += Append;
|
||||
setState( 1 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::KeyPress:
|
||||
{
|
||||
if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1,
|
||||
static_cast<const QKeyEvent *> ( event ) ) )
|
||||
{
|
||||
if ( state() == 0 )
|
||||
{
|
||||
cmdList += Begin;
|
||||
cmdList += Append;
|
||||
cmdList += Append;
|
||||
setState( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::Wheel:
|
||||
{
|
||||
if ( state() != 0 )
|
||||
cmdList += Move;
|
||||
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
if ( state() != 0 )
|
||||
{
|
||||
cmdList += End;
|
||||
setState( 0 );
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return cmdList;
|
||||
}
|
||||
214
third/3rd_qwt/qwt_picker_machine.h
Normal file
214
third/3rd_qwt/qwt_picker_machine.h
Normal file
@@ -0,0 +1,214 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PICKER_MACHINE
|
||||
#define QWT_PICKER_MACHINE 1
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qlist.h>
|
||||
|
||||
class QEvent;
|
||||
class QwtEventPattern;
|
||||
|
||||
/*!
|
||||
\brief A state machine for QwtPicker selections
|
||||
|
||||
QwtPickerMachine accepts key and mouse events and translates them
|
||||
into selection commands.
|
||||
|
||||
\sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtPickerMachine
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
Type of a selection.
|
||||
\sa selectionType()
|
||||
*/
|
||||
enum SelectionType
|
||||
{
|
||||
//! The state machine not usable for any type of selection.
|
||||
NoSelection = -1,
|
||||
|
||||
//! The state machine is for selecting a single point.
|
||||
PointSelection,
|
||||
|
||||
//! The state machine is for selecting a rectangle (2 points).
|
||||
RectSelection,
|
||||
|
||||
//! The state machine is for selecting a polygon (many points).
|
||||
PolygonSelection
|
||||
};
|
||||
|
||||
//! Commands - the output of a state machine
|
||||
enum Command
|
||||
{
|
||||
Begin,
|
||||
Append,
|
||||
Move,
|
||||
Remove,
|
||||
End
|
||||
};
|
||||
|
||||
QwtPickerMachine( SelectionType );
|
||||
virtual ~QwtPickerMachine();
|
||||
|
||||
//! Transition
|
||||
virtual QList<Command> transition(
|
||||
const QwtEventPattern &, const QEvent * ) = 0;
|
||||
void reset();
|
||||
|
||||
int state() const;
|
||||
void setState( int );
|
||||
|
||||
SelectionType selectionType() const;
|
||||
|
||||
private:
|
||||
const SelectionType d_selectionType;
|
||||
int d_state;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A state machine for indicating mouse movements
|
||||
|
||||
QwtPickerTrackerMachine supports displaying information
|
||||
corresponding to mouse movements, but is not intended for
|
||||
selecting anything. Begin/End are related to Enter/Leave events.
|
||||
*/
|
||||
class QWT_EXPORT QwtPickerTrackerMachine: public QwtPickerMachine
|
||||
{
|
||||
public:
|
||||
QwtPickerTrackerMachine();
|
||||
|
||||
virtual QList<Command> transition(
|
||||
const QwtEventPattern &, const QEvent * );
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A state machine for point selections
|
||||
|
||||
Pressing QwtEventPattern::MouseSelect1 or
|
||||
QwtEventPattern::KeySelect1 selects a point.
|
||||
|
||||
\sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode
|
||||
*/
|
||||
class QWT_EXPORT QwtPickerClickPointMachine: public QwtPickerMachine
|
||||
{
|
||||
public:
|
||||
QwtPickerClickPointMachine();
|
||||
|
||||
virtual QList<Command> transition(
|
||||
const QwtEventPattern &, const QEvent * );
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A state machine for point selections
|
||||
|
||||
Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1
|
||||
starts the selection, releasing QwtEventPattern::MouseSelect1 or
|
||||
a second press of QwtEventPattern::KeySelect1 terminates it.
|
||||
*/
|
||||
class QWT_EXPORT QwtPickerDragPointMachine: public QwtPickerMachine
|
||||
{
|
||||
public:
|
||||
QwtPickerDragPointMachine();
|
||||
|
||||
virtual QList<Command> transition(
|
||||
const QwtEventPattern &, const QEvent * );
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A state machine for rectangle selections
|
||||
|
||||
Pressing QwtEventPattern::MouseSelect1 starts
|
||||
the selection, releasing it selects the first point. Pressing it
|
||||
again selects the second point and terminates the selection.
|
||||
Pressing QwtEventPattern::KeySelect1 also starts the
|
||||
selection, a second press selects the first point. A third one selects
|
||||
the second point and terminates the selection.
|
||||
|
||||
\sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtPickerClickRectMachine: public QwtPickerMachine
|
||||
{
|
||||
public:
|
||||
QwtPickerClickRectMachine();
|
||||
|
||||
virtual QList<Command> transition(
|
||||
const QwtEventPattern &, const QEvent * );
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A state machine for rectangle selections
|
||||
|
||||
Pressing QwtEventPattern::MouseSelect1 selects
|
||||
the first point, releasing it the second point.
|
||||
Pressing QwtEventPattern::KeySelect1 also selects the
|
||||
first point, a second press selects the second point and terminates
|
||||
the selection.
|
||||
|
||||
\sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtPickerDragRectMachine: public QwtPickerMachine
|
||||
{
|
||||
public:
|
||||
QwtPickerDragRectMachine();
|
||||
|
||||
virtual QList<Command> transition(
|
||||
const QwtEventPattern &, const QEvent * );
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A state machine for line selections
|
||||
|
||||
Pressing QwtEventPattern::MouseSelect1 selects
|
||||
the first point, releasing it the second point.
|
||||
Pressing QwtEventPattern::KeySelect1 also selects the
|
||||
first point, a second press selects the second point and terminates
|
||||
the selection.
|
||||
|
||||
A common use case of QwtPickerDragLineMachine are pickers for
|
||||
distance measurements.
|
||||
|
||||
\sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtPickerDragLineMachine: public QwtPickerMachine
|
||||
{
|
||||
public:
|
||||
QwtPickerDragLineMachine();
|
||||
|
||||
virtual QList<Command> transition(
|
||||
const QwtEventPattern &, const QEvent * );
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief A state machine for polygon selections
|
||||
|
||||
Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1
|
||||
starts the selection and selects the first point, or appends a point.
|
||||
Pressing QwtEventPattern::MouseSelect2 or QwtEventPattern::KeySelect2
|
||||
appends the last point and terminates the selection.
|
||||
|
||||
\sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtPickerPolygonMachine: public QwtPickerMachine
|
||||
{
|
||||
public:
|
||||
QwtPickerPolygonMachine();
|
||||
|
||||
virtual QList<Command> transition(
|
||||
const QwtEventPattern &, const QEvent * );
|
||||
};
|
||||
|
||||
#endif
|
||||
51
third/3rd_qwt/qwt_pixel_matrix.cpp
Normal file
51
third/3rd_qwt/qwt_pixel_matrix.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/* -*- 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_pixel_matrix.h"
|
||||
|
||||
/*!
|
||||
\brief Constructor
|
||||
|
||||
\param rect Bounding rectangle for the matrix
|
||||
*/
|
||||
QwtPixelMatrix::QwtPixelMatrix( const QRect& rect ):
|
||||
QBitArray( qMax( rect.width() * rect.height(), 0 ) ),
|
||||
d_rect( rect )
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtPixelMatrix::~QwtPixelMatrix()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the bounding rectangle of the matrix
|
||||
|
||||
\param rect Bounding rectangle
|
||||
|
||||
\note All bits are cleared
|
||||
*/
|
||||
void QwtPixelMatrix::setRect( const QRect& rect )
|
||||
{
|
||||
if ( rect != d_rect )
|
||||
{
|
||||
d_rect = rect;
|
||||
const int sz = qMax( rect.width() * rect.height(), 0 );
|
||||
resize( sz );
|
||||
}
|
||||
|
||||
fill( false );
|
||||
}
|
||||
|
||||
//! \return Bounding rectangle
|
||||
QRect QwtPixelMatrix::rect() const
|
||||
{
|
||||
return d_rect;
|
||||
}
|
||||
98
third/3rd_qwt/qwt_pixel_matrix.h
Normal file
98
third/3rd_qwt/qwt_pixel_matrix.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PIXEL_MATRIX_H
|
||||
#define QWT_PIXEL_MATRIX_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qbitarray.h>
|
||||
#include <qrect.h>
|
||||
|
||||
/*!
|
||||
\brief A bit field corresponding to the pixels of a rectangle
|
||||
|
||||
QwtPixelMatrix is intended to filter out duplicates in an
|
||||
unsorted array of points.
|
||||
*/
|
||||
class QWT_EXPORT QwtPixelMatrix: public QBitArray
|
||||
{
|
||||
public:
|
||||
QwtPixelMatrix( const QRect& rect );
|
||||
~QwtPixelMatrix();
|
||||
|
||||
void setRect( const QRect& rect );
|
||||
QRect rect() const;
|
||||
|
||||
bool testPixel( int x, int y ) const;
|
||||
bool testAndSetPixel( int x, int y, bool on );
|
||||
|
||||
int index( int x, int y ) const;
|
||||
|
||||
private:
|
||||
QRect d_rect;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Test if a pixel has been set
|
||||
|
||||
\param x X-coordinate
|
||||
\param y Y-coordinate
|
||||
|
||||
\return true, when pos is outside of rect(), or when the pixel
|
||||
has already been set.
|
||||
*/
|
||||
inline bool QwtPixelMatrix::testPixel( int x, int y ) const
|
||||
{
|
||||
const int idx = index( x, y );
|
||||
return ( idx >= 0 ) ? testBit( idx ) : true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set a pixel and test if a pixel has been set before
|
||||
|
||||
\param x X-coordinate
|
||||
\param y Y-coordinate
|
||||
\param on Set/Clear the pixel
|
||||
|
||||
\return true, when pos is outside of rect(), or when the pixel
|
||||
was set before.
|
||||
*/
|
||||
inline bool QwtPixelMatrix::testAndSetPixel( int x, int y, bool on )
|
||||
{
|
||||
const int idx = index( x, y );
|
||||
if ( idx < 0 )
|
||||
return true;
|
||||
|
||||
const bool onBefore = testBit( idx );
|
||||
setBit( idx, on );
|
||||
|
||||
return onBefore;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Calculate the index in the bit field corresponding to a position
|
||||
|
||||
\param x X-coordinate
|
||||
\param y Y-coordinate
|
||||
\return Index, when rect() contains pos - otherwise -1.
|
||||
*/
|
||||
inline int QwtPixelMatrix::index( int x, int y ) const
|
||||
{
|
||||
const int dx = x - d_rect.x();
|
||||
if ( dx < 0 || dx >= d_rect.width() )
|
||||
return -1;
|
||||
|
||||
const int dy = y - d_rect.y();
|
||||
if ( dy < 0 || dy >= d_rect.height() )
|
||||
return -1;
|
||||
|
||||
return dy * d_rect.width() + dx;
|
||||
}
|
||||
|
||||
#endif
|
||||
1184
third/3rd_qwt/qwt_plot.cpp
Normal file
1184
third/3rd_qwt/qwt_plot.cpp
Normal file
File diff suppressed because it is too large
Load Diff
313
third/3rd_qwt/qwt_plot.h
Normal file
313
third/3rd_qwt/qwt_plot.h
Normal file
@@ -0,0 +1,313 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PLOT_H
|
||||
#define QWT_PLOT_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_text.h"
|
||||
#include "qwt_plot_dict.h"
|
||||
#include "qwt_scale_map.h"
|
||||
#include "qwt_interval.h"
|
||||
#include <qframe.h>
|
||||
#include <qlist.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
class QwtPlotLayout;
|
||||
class QwtAbstractLegend;
|
||||
class QwtScaleWidget;
|
||||
class QwtScaleEngine;
|
||||
class QwtScaleDiv;
|
||||
class QwtScaleDraw;
|
||||
class QwtTextLabel;
|
||||
|
||||
/*!
|
||||
\brief A 2-D plotting widget
|
||||
|
||||
QwtPlot is a widget for plotting two-dimensional graphs.
|
||||
An unlimited number of plot items can be displayed on
|
||||
its canvas. Plot items might be curves (QwtPlotCurve), markers
|
||||
(QwtPlotMarker), the grid (QwtPlotGrid), or anything else derived
|
||||
from QwtPlotItem.
|
||||
A plot can have up to four axes, with each plot item attached to an x- and
|
||||
a y axis. The scales at the axes can be explicitly set (QwtScaleDiv), or
|
||||
are calculated from the plot items, using algorithms (QwtScaleEngine) which
|
||||
can be configured separately for each axis.
|
||||
|
||||
The simpleplot example is a good starting point to see how to set up a
|
||||
plot widget.
|
||||
|
||||
\image html plot.png
|
||||
|
||||
\par Example
|
||||
The following example shows (schematically) the most simple
|
||||
way to use QwtPlot. By default, only the left and bottom axes are
|
||||
visible and their scales are computed automatically.
|
||||
\code
|
||||
#include <qwt_plot.h>
|
||||
#include <qwt_plot_curve.h>
|
||||
|
||||
QwtPlot *myPlot = new QwtPlot( "Two Curves", parent );
|
||||
|
||||
// add curves
|
||||
QwtPlotCurve *curve1 = new QwtPlotCurve( "Curve 1" );
|
||||
QwtPlotCurve *curve2 = new QwtPlotCurve( "Curve 2" );
|
||||
|
||||
// connect or copy the data to the curves
|
||||
curve1->setData( ... );
|
||||
curve2->setData( ... );
|
||||
|
||||
curve1->attach( myPlot );
|
||||
curve2->attach( myPlot );
|
||||
|
||||
// finally, refresh the plot
|
||||
myPlot->replot();
|
||||
\endcode
|
||||
\endpar
|
||||
*/
|
||||
|
||||
class QWT_EXPORT QwtPlot: public QFrame, public QwtPlotDict
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( QBrush canvasBackground
|
||||
READ canvasBackground WRITE setCanvasBackground )
|
||||
Q_PROPERTY( bool autoReplot READ autoReplot WRITE setAutoReplot )
|
||||
|
||||
#if 0
|
||||
// This property is intended to configure the plot
|
||||
// widget from a special dialog in the deigner plugin.
|
||||
// Disabled until such a dialog has been implemented.
|
||||
|
||||
Q_PROPERTY( QString propertiesDocument
|
||||
READ grabProperties WRITE applyProperties )
|
||||
#endif
|
||||
|
||||
public:
|
||||
//! \brief Axis index
|
||||
enum Axis
|
||||
{
|
||||
//! Y axis left of the canvas
|
||||
yLeft,
|
||||
|
||||
//! Y axis right of the canvas
|
||||
yRight,
|
||||
|
||||
//! X axis below the canvas
|
||||
xBottom,
|
||||
|
||||
//! X axis above the canvas
|
||||
xTop,
|
||||
|
||||
//! Number of axes
|
||||
axisCnt
|
||||
};
|
||||
|
||||
/*!
|
||||
Position of the legend, relative to the canvas.
|
||||
|
||||
\sa insertLegend()
|
||||
*/
|
||||
enum LegendPosition
|
||||
{
|
||||
//! The legend will be left from the QwtPlot::yLeft axis.
|
||||
LeftLegend,
|
||||
|
||||
//! The legend will be right from the QwtPlot::yRight axis.
|
||||
RightLegend,
|
||||
|
||||
//! The legend will be below the footer
|
||||
BottomLegend,
|
||||
|
||||
//! The legend will be above the title
|
||||
TopLegend
|
||||
};
|
||||
|
||||
explicit QwtPlot( QWidget * = NULL );
|
||||
explicit QwtPlot( const QwtText &title, QWidget * = NULL );
|
||||
|
||||
virtual ~QwtPlot();
|
||||
|
||||
void applyProperties( const QString & );
|
||||
QString grabProperties() const;
|
||||
|
||||
void setAutoReplot( bool = true );
|
||||
bool autoReplot() const;
|
||||
|
||||
// Layout
|
||||
|
||||
void setPlotLayout( QwtPlotLayout * );
|
||||
|
||||
QwtPlotLayout *plotLayout();
|
||||
const QwtPlotLayout *plotLayout() const;
|
||||
|
||||
// Title
|
||||
|
||||
void setTitle( const QString & );
|
||||
void setTitle( const QwtText & );
|
||||
QwtText title() const;
|
||||
|
||||
QwtTextLabel *titleLabel();
|
||||
const QwtTextLabel *titleLabel() const;
|
||||
|
||||
// Footer
|
||||
|
||||
void setFooter( const QString & );
|
||||
void setFooter( const QwtText & );
|
||||
QwtText footer() const;
|
||||
|
||||
QwtTextLabel *footerLabel();
|
||||
const QwtTextLabel *footerLabel() const;
|
||||
|
||||
// Canvas
|
||||
|
||||
void setCanvas( QWidget * );
|
||||
|
||||
QWidget *canvas();
|
||||
const QWidget *canvas() const;
|
||||
|
||||
void setCanvasBackground( const QBrush & );
|
||||
QBrush canvasBackground() const;
|
||||
|
||||
virtual QwtScaleMap canvasMap( int axisId ) const;
|
||||
|
||||
double invTransform( int axisId, int pos ) const;
|
||||
double transform( int axisId, double value ) const;
|
||||
|
||||
// Axes
|
||||
|
||||
QwtScaleEngine *axisScaleEngine( int axisId );
|
||||
const QwtScaleEngine *axisScaleEngine( int axisId ) const;
|
||||
void setAxisScaleEngine( int axisId, QwtScaleEngine * );
|
||||
|
||||
void setAxisAutoScale( int axisId, bool on = true );
|
||||
bool axisAutoScale( int axisId ) const;
|
||||
|
||||
void enableAxis( int axisId, bool tf = true );
|
||||
bool axisEnabled( int axisId ) const;
|
||||
|
||||
void setAxisFont( int axisId, const QFont & );
|
||||
QFont axisFont( int axisId ) const;
|
||||
|
||||
void setAxisScale( int axisId, double min, double max, double stepSize = 0 );
|
||||
void setAxisScaleDiv( int axisId, const QwtScaleDiv & );
|
||||
void setAxisScaleDraw( int axisId, QwtScaleDraw * );
|
||||
|
||||
double axisStepSize( int axisId ) const;
|
||||
QwtInterval axisInterval( int axisId ) const;
|
||||
|
||||
const QwtScaleDiv &axisScaleDiv( int axisId ) const;
|
||||
|
||||
const QwtScaleDraw *axisScaleDraw( int axisId ) const;
|
||||
QwtScaleDraw *axisScaleDraw( int axisId );
|
||||
|
||||
const QwtScaleWidget *axisWidget( int axisId ) const;
|
||||
QwtScaleWidget *axisWidget( int axisId );
|
||||
|
||||
void setAxisLabelAlignment( int axisId, Qt::Alignment );
|
||||
void setAxisLabelRotation( int axisId, double rotation );
|
||||
|
||||
void setAxisTitle( int axisId, const QString & );
|
||||
void setAxisTitle( int axisId, const QwtText & );
|
||||
QwtText axisTitle( int axisId ) const;
|
||||
|
||||
void setAxisMaxMinor( int axisId, int maxMinor );
|
||||
int axisMaxMinor( int axisId ) const;
|
||||
|
||||
void setAxisMaxMajor( int axisId, int maxMajor );
|
||||
int axisMaxMajor( int axisId ) const;
|
||||
|
||||
// Legend
|
||||
|
||||
void insertLegend( QwtAbstractLegend *,
|
||||
LegendPosition = QwtPlot::RightLegend, double ratio = -1.0 );
|
||||
|
||||
QwtAbstractLegend *legend();
|
||||
const QwtAbstractLegend *legend() const;
|
||||
|
||||
void updateLegend();
|
||||
void updateLegend( const QwtPlotItem * );
|
||||
|
||||
// Misc
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
virtual QSize minimumSizeHint() const;
|
||||
|
||||
virtual void updateLayout();
|
||||
virtual void drawCanvas( QPainter * );
|
||||
|
||||
void updateAxes();
|
||||
void updateCanvasMargins();
|
||||
|
||||
virtual void getCanvasMarginsHint(
|
||||
const QwtScaleMap maps[], const QRectF &canvasRect,
|
||||
double &left, double &top, double &right, double &bottom) const;
|
||||
|
||||
virtual bool event( QEvent * );
|
||||
virtual bool eventFilter( QObject *, QEvent * );
|
||||
|
||||
virtual void drawItems( QPainter *, const QRectF &,
|
||||
const QwtScaleMap maps[axisCnt] ) const;
|
||||
|
||||
virtual QVariant itemToInfo( QwtPlotItem * ) const;
|
||||
virtual QwtPlotItem *infoToItem( const QVariant & ) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/*!
|
||||
A signal indicating, that an item has been attached/detached
|
||||
|
||||
\param plotItem Plot item
|
||||
\param on Attached/Detached
|
||||
*/
|
||||
void itemAttached( QwtPlotItem *plotItem, bool on );
|
||||
|
||||
/*!
|
||||
A signal with the attributes how to update
|
||||
the legend entries for a plot item.
|
||||
|
||||
\param itemInfo Info about a plot item, build from itemToInfo()
|
||||
\param data Attributes of the entries ( usually <= 1 ) for
|
||||
the plot item.
|
||||
|
||||
\sa itemToInfo(), infoToItem(), QwtAbstractLegend::updateLegend()
|
||||
*/
|
||||
void legendDataChanged( const QVariant &itemInfo,
|
||||
const QList<QwtLegendData> &data );
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual void replot();
|
||||
void autoRefresh();
|
||||
|
||||
protected:
|
||||
static bool axisValid( int axisId );
|
||||
|
||||
virtual void resizeEvent( QResizeEvent *e );
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateLegendItems( const QVariant &itemInfo,
|
||||
const QList<QwtLegendData> &legendData );
|
||||
|
||||
private:
|
||||
friend class QwtPlotItem;
|
||||
void attachItem( QwtPlotItem *, bool );
|
||||
|
||||
void initAxesData();
|
||||
void deleteAxesData();
|
||||
void updateScaleDiv();
|
||||
|
||||
void initPlot( const QwtText &title );
|
||||
|
||||
class AxisData;
|
||||
AxisData *d_axisData[axisCnt];
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
368
third/3rd_qwt/qwt_plot_abstract_barchart.cpp
Normal file
368
third/3rd_qwt/qwt_plot_abstract_barchart.cpp
Normal file
@@ -0,0 +1,368 @@
|
||||
/* -*- 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_plot_abstract_barchart.h"
|
||||
#include "qwt_scale_map.h"
|
||||
|
||||
static inline double qwtTransformWidth(
|
||||
const QwtScaleMap &map, double value, double width )
|
||||
{
|
||||
const double w2 = 0.5 * width;
|
||||
|
||||
const double v1 = map.transform( value - w2 );
|
||||
const double v2 = map.transform( value + w2 );
|
||||
|
||||
return qAbs( v2 - v1 );
|
||||
}
|
||||
|
||||
class QwtPlotAbstractBarChart::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
layoutPolicy( QwtPlotAbstractBarChart::AutoAdjustSamples ),
|
||||
layoutHint( 0.5 ),
|
||||
spacing( 10 ),
|
||||
margin( 5 ),
|
||||
baseline( 0.0 )
|
||||
{
|
||||
}
|
||||
|
||||
QwtPlotAbstractBarChart::LayoutPolicy layoutPolicy;
|
||||
double layoutHint;
|
||||
int spacing;
|
||||
int margin;
|
||||
double baseline;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
\param title Title of the chart
|
||||
*/
|
||||
QwtPlotAbstractBarChart::QwtPlotAbstractBarChart( const QwtText &title ):
|
||||
QwtPlotSeriesItem( title )
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
|
||||
setItemAttribute( QwtPlotItem::Legend, true );
|
||||
setItemAttribute( QwtPlotItem::AutoScale, true );
|
||||
setItemAttribute( QwtPlotItem::Margins, true );
|
||||
setZ( 19.0 );
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtPlotAbstractBarChart::~QwtPlotAbstractBarChart()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
The combination of layoutPolicy() and layoutHint() define how the width
|
||||
of the bars is calculated
|
||||
|
||||
\param policy Layout policy
|
||||
|
||||
\sa layoutPolicy(), layoutHint()
|
||||
*/
|
||||
void QwtPlotAbstractBarChart::setLayoutPolicy( LayoutPolicy policy )
|
||||
{
|
||||
if ( policy != d_data->layoutPolicy )
|
||||
{
|
||||
d_data->layoutPolicy = policy;
|
||||
itemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
The combination of layoutPolicy() and layoutHint() define how the width
|
||||
of the bars is calculated
|
||||
|
||||
\return Layout policy of the chart item
|
||||
\sa setLayoutPolicy(), layoutHint()
|
||||
*/
|
||||
QwtPlotAbstractBarChart::LayoutPolicy QwtPlotAbstractBarChart::layoutPolicy() const
|
||||
{
|
||||
return d_data->layoutPolicy;
|
||||
}
|
||||
|
||||
/*!
|
||||
The combination of layoutPolicy() and layoutHint() define how the width
|
||||
of the bars is calculated
|
||||
|
||||
\param hint Layout hint
|
||||
|
||||
\sa LayoutPolicy, layoutPolicy(), layoutHint()
|
||||
*/
|
||||
void QwtPlotAbstractBarChart::setLayoutHint( double hint )
|
||||
{
|
||||
hint = qMax( 0.0, hint );
|
||||
if ( hint != d_data->layoutHint )
|
||||
{
|
||||
d_data->layoutHint = hint;
|
||||
itemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
The combination of layoutPolicy() and layoutHint() define how the width
|
||||
of the bars is calculated
|
||||
|
||||
\return Layout policy of the chart item
|
||||
\sa LayoutPolicy, setLayoutHint(), layoutPolicy()
|
||||
*/
|
||||
double QwtPlotAbstractBarChart::layoutHint() const
|
||||
{
|
||||
return d_data->layoutHint;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the spacing
|
||||
|
||||
The spacing is the distance between 2 samples ( bars for QwtPlotBarChart or
|
||||
a group of bars for QwtPlotMultiBarChart ) in paint device coordinates.
|
||||
|
||||
\sa spacing()
|
||||
*/
|
||||
void QwtPlotAbstractBarChart::setSpacing( int spacing )
|
||||
{
|
||||
spacing = qMax( spacing, 0 );
|
||||
if ( spacing != d_data->spacing )
|
||||
{
|
||||
d_data->spacing = spacing;
|
||||
itemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Spacing between 2 samples ( bars or groups of bars )
|
||||
\sa setSpacing(), margin()
|
||||
*/
|
||||
int QwtPlotAbstractBarChart::spacing() const
|
||||
{
|
||||
return d_data->spacing;
|
||||
}
|
||||
/*!
|
||||
\brief Set the margin
|
||||
|
||||
The margin is the distance between the outmost bars and the contentsRect()
|
||||
of the canvas. The default setting is 5 pixels.
|
||||
|
||||
\param margin Margin
|
||||
|
||||
\sa spacing(), margin()
|
||||
*/
|
||||
void QwtPlotAbstractBarChart::setMargin( int margin )
|
||||
{
|
||||
margin = qMax( margin, 0 );
|
||||
if ( margin != d_data->margin )
|
||||
{
|
||||
d_data->margin = margin;
|
||||
itemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Margin between the outmost bars and the contentsRect()
|
||||
of the canvas.
|
||||
|
||||
\sa setMargin(), spacing()
|
||||
*/
|
||||
int QwtPlotAbstractBarChart::margin() const
|
||||
{
|
||||
return d_data->margin;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the baseline
|
||||
|
||||
The baseline is the origin for the chart. Each bar is
|
||||
painted from the baseline in the direction of the sample
|
||||
value. In case of a horizontal orientation() the baseline
|
||||
is interpreted as x - otherwise as y - value.
|
||||
|
||||
The default value for the baseline is 0.
|
||||
|
||||
\param value Value for the baseline
|
||||
|
||||
\sa baseline(), QwtPlotSeriesItem::orientation()
|
||||
*/
|
||||
void QwtPlotAbstractBarChart::setBaseline( double value )
|
||||
{
|
||||
if ( value != d_data->baseline )
|
||||
{
|
||||
d_data->baseline = value;
|
||||
itemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Value for the origin of the bar chart
|
||||
\sa setBaseline(), QwtPlotSeriesItem::orientation()
|
||||
*/
|
||||
double QwtPlotAbstractBarChart::baseline() const
|
||||
{
|
||||
return d_data->baseline;
|
||||
}
|
||||
|
||||
/*!
|
||||
Calculate the width for a sample in paint device coordinates
|
||||
|
||||
\param map Scale map for the corresponding scale
|
||||
\param canvasSize Size of the canvas in paint device coordinates
|
||||
\param boundingSize Bounding size of the chart in plot coordinates
|
||||
( used in AutoAdjustSamples mode )
|
||||
\param value Value of the sample
|
||||
|
||||
\return Sample width
|
||||
\sa layoutPolicy(), layoutHint()
|
||||
*/
|
||||
double QwtPlotAbstractBarChart::sampleWidth( const QwtScaleMap &map,
|
||||
double canvasSize, double boundingSize, double value ) const
|
||||
{
|
||||
double width;
|
||||
|
||||
switch( d_data->layoutPolicy )
|
||||
{
|
||||
case ScaleSamplesToAxes:
|
||||
{
|
||||
width = qwtTransformWidth( map, value, d_data->layoutHint );
|
||||
break;
|
||||
}
|
||||
case ScaleSampleToCanvas:
|
||||
{
|
||||
width = canvasSize * d_data->layoutHint;
|
||||
break;
|
||||
}
|
||||
case FixedSampleSize:
|
||||
{
|
||||
width = d_data->layoutHint;
|
||||
break;
|
||||
}
|
||||
case AutoAdjustSamples:
|
||||
default:
|
||||
{
|
||||
const size_t numSamples = dataSize();
|
||||
|
||||
double w = 1.0;
|
||||
if ( numSamples > 1 )
|
||||
{
|
||||
w = qAbs( boundingSize / ( numSamples - 1 ) );
|
||||
}
|
||||
|
||||
width = qwtTransformWidth( map, value, w );
|
||||
width -= d_data->spacing;
|
||||
width = qMax( width, d_data->layoutHint );
|
||||
}
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Calculate a hint for the canvas margin
|
||||
|
||||
Bar charts need to reserve some space for displaying the bars
|
||||
for the first and the last sample. The hint is calculated
|
||||
from the layoutHint() depending on the layoutPolicy().
|
||||
|
||||
The margins are in target device coordinates ( pixels on screen )
|
||||
|
||||
\param xMap Maps x-values into pixel coordinates.
|
||||
\param yMap Maps y-values into pixel coordinates.
|
||||
\param canvasRect Contents rectangle of the canvas in painter coordinates
|
||||
\param left Returns the left margin
|
||||
\param top Returns the top margin
|
||||
\param right Returns the right margin
|
||||
\param bottom Returns the bottom margin
|
||||
|
||||
\return Margin
|
||||
|
||||
\sa layoutPolicy(), layoutHint(), QwtPlotItem::Margins
|
||||
QwtPlot::getCanvasMarginsHint(), QwtPlot::updateCanvasMargins()
|
||||
*/
|
||||
void QwtPlotAbstractBarChart::getCanvasMarginHint( const QwtScaleMap &xMap,
|
||||
const QwtScaleMap &yMap, const QRectF &canvasRect,
|
||||
double &left, double &top, double &right, double &bottom ) const
|
||||
{
|
||||
double hint = -1.0;
|
||||
|
||||
switch( layoutPolicy() )
|
||||
{
|
||||
case ScaleSampleToCanvas:
|
||||
{
|
||||
if ( orientation() == Qt::Vertical )
|
||||
hint = 0.5 * canvasRect.width() * d_data->layoutHint;
|
||||
else
|
||||
hint = 0.5 * canvasRect.height() * d_data->layoutHint;
|
||||
|
||||
break;
|
||||
}
|
||||
case FixedSampleSize:
|
||||
{
|
||||
hint = 0.5 * d_data->layoutHint;
|
||||
break;
|
||||
}
|
||||
case AutoAdjustSamples:
|
||||
case ScaleSamplesToAxes:
|
||||
default:
|
||||
{
|
||||
const size_t numSamples = dataSize();
|
||||
if ( numSamples <= 0 )
|
||||
break;
|
||||
|
||||
// doesn't work for nonlinear scales
|
||||
|
||||
const QRectF br = dataRect();
|
||||
double spacing = 0.0;
|
||||
double sampleWidthS = 1.0;
|
||||
|
||||
if ( layoutPolicy() == ScaleSamplesToAxes )
|
||||
{
|
||||
sampleWidthS = qMax( d_data->layoutHint, 0.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
spacing = d_data->spacing;
|
||||
|
||||
if ( numSamples > 1 )
|
||||
{
|
||||
sampleWidthS = qAbs( br.width() / ( numSamples - 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
double ds, w;
|
||||
if ( orientation() == Qt::Vertical )
|
||||
{
|
||||
ds = qAbs( xMap.sDist() );
|
||||
w = canvasRect.width();
|
||||
}
|
||||
else
|
||||
{
|
||||
ds = qAbs( yMap.sDist() );
|
||||
w = canvasRect.height();
|
||||
}
|
||||
|
||||
const double sampleWidthP = ( w - spacing * ( numSamples - 1 ) )
|
||||
* sampleWidthS / ( ds + sampleWidthS );
|
||||
|
||||
hint = 0.5 * sampleWidthP;
|
||||
hint += qMax( d_data->margin, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( orientation() == Qt::Vertical )
|
||||
{
|
||||
left = right = hint;
|
||||
top = bottom = -1.0; // no hint
|
||||
}
|
||||
else
|
||||
{
|
||||
left = right = -1.0; // no hint
|
||||
top = bottom = hint;
|
||||
}
|
||||
}
|
||||
97
third/3rd_qwt/qwt_plot_abstract_barchart.h
Normal file
97
third/3rd_qwt/qwt_plot_abstract_barchart.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PLOT_ABSTRACT_BAR_CHART_H
|
||||
#define QWT_PLOT_ABSTRACT_BAR_CHART_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_plot_seriesitem.h"
|
||||
#include "qwt_series_data.h"
|
||||
|
||||
/*!
|
||||
\brief Abstract base class for bar chart items
|
||||
|
||||
In opposite to almost all other plot items bar charts can't be
|
||||
displayed inside of their bounding rectangle and need a special
|
||||
API how to calculate the width of the bars and how they affect
|
||||
the layout of the attached plot.
|
||||
*/
|
||||
class QWT_EXPORT QwtPlotAbstractBarChart: public QwtPlotSeriesItem
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
\brief Mode how to calculate the bar width
|
||||
|
||||
setLayoutPolicy(), setLayoutHint(), barWidthHint()
|
||||
*/
|
||||
enum LayoutPolicy
|
||||
{
|
||||
/*!
|
||||
The sample width is calculated by dividing the bounding rectangle
|
||||
by the number of samples. The layoutHint() is used as a minimum width
|
||||
in paint device coordinates.
|
||||
|
||||
\sa boundingRectangle()
|
||||
*/
|
||||
AutoAdjustSamples,
|
||||
|
||||
/*!
|
||||
layoutHint() defines an interval in axis coordinates
|
||||
*/
|
||||
ScaleSamplesToAxes,
|
||||
|
||||
/*!
|
||||
The bar width is calculated by multiplying layoutHint()
|
||||
with the height or width of the canvas.
|
||||
|
||||
\sa boundingRectangle()
|
||||
*/
|
||||
ScaleSampleToCanvas,
|
||||
|
||||
/*!
|
||||
layoutHint() defines a fixed width in paint device coordinates.
|
||||
*/
|
||||
FixedSampleSize
|
||||
};
|
||||
|
||||
explicit QwtPlotAbstractBarChart( const QwtText &title );
|
||||
virtual ~QwtPlotAbstractBarChart();
|
||||
|
||||
void setLayoutPolicy( LayoutPolicy );
|
||||
LayoutPolicy layoutPolicy() const;
|
||||
|
||||
void setLayoutHint( double );
|
||||
double layoutHint() const;
|
||||
|
||||
void setSpacing( int );
|
||||
int spacing() const;
|
||||
|
||||
void setMargin( int );
|
||||
int margin() const;
|
||||
|
||||
void setBaseline( double );
|
||||
double baseline() const;
|
||||
|
||||
virtual void getCanvasMarginHint(
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||||
const QRectF &canvasRect,
|
||||
double &left, double &top, double &right, double &bottom) const;
|
||||
|
||||
|
||||
protected:
|
||||
double sampleWidth( const QwtScaleMap &map,
|
||||
double canvasSize, double boundingSize,
|
||||
double value ) const;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
718
third/3rd_qwt/qwt_plot_axis.cpp
Normal file
718
third/3rd_qwt/qwt_plot_axis.cpp
Normal file
@@ -0,0 +1,718 @@
|
||||
/* -*- 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_plot.h"
|
||||
#include "qwt_math.h"
|
||||
#include "qwt_scale_widget.h"
|
||||
#include "qwt_scale_div.h"
|
||||
#include "qwt_scale_engine.h"
|
||||
|
||||
class QwtPlot::AxisData
|
||||
{
|
||||
public:
|
||||
bool isEnabled;
|
||||
bool doAutoScale;
|
||||
|
||||
double minValue;
|
||||
double maxValue;
|
||||
double stepSize;
|
||||
|
||||
int maxMajor;
|
||||
int maxMinor;
|
||||
|
||||
bool isValid;
|
||||
|
||||
QwtScaleDiv scaleDiv;
|
||||
QwtScaleEngine *scaleEngine;
|
||||
QwtScaleWidget *scaleWidget;
|
||||
};
|
||||
|
||||
//! Initialize axes
|
||||
void QwtPlot::initAxesData()
|
||||
{
|
||||
int axisId;
|
||||
|
||||
for ( axisId = 0; axisId < axisCnt; axisId++ )
|
||||
d_axisData[axisId] = new AxisData;
|
||||
|
||||
d_axisData[yLeft]->scaleWidget =
|
||||
new QwtScaleWidget( QwtScaleDraw::LeftScale, this );
|
||||
d_axisData[yRight]->scaleWidget =
|
||||
new QwtScaleWidget( QwtScaleDraw::RightScale, this );
|
||||
d_axisData[xTop]->scaleWidget =
|
||||
new QwtScaleWidget( QwtScaleDraw::TopScale, this );
|
||||
d_axisData[xBottom]->scaleWidget =
|
||||
new QwtScaleWidget( QwtScaleDraw::BottomScale, this );
|
||||
|
||||
d_axisData[yLeft]->scaleWidget->setObjectName( "QwtPlotAxisYLeft" );
|
||||
d_axisData[yRight]->scaleWidget->setObjectName( "QwtPlotAxisYRight" );
|
||||
d_axisData[xTop]->scaleWidget->setObjectName( "QwtPlotAxisXTop" );
|
||||
d_axisData[xBottom]->scaleWidget->setObjectName( "QwtPlotAxisXBottom" );
|
||||
|
||||
#if 1
|
||||
// better find the font sizes from the application font
|
||||
QFont fscl( fontInfo().family(), 10 );
|
||||
QFont fttl( fontInfo().family(), 12, QFont::Bold );
|
||||
#endif
|
||||
|
||||
for ( axisId = 0; axisId < axisCnt; axisId++ )
|
||||
{
|
||||
AxisData &d = *d_axisData[axisId];
|
||||
|
||||
d.scaleEngine = new QwtLinearScaleEngine;
|
||||
|
||||
d.scaleWidget->setTransformation(
|
||||
d.scaleEngine->transformation() );
|
||||
|
||||
d.scaleWidget->setFont( fscl );
|
||||
d.scaleWidget->setMargin( 2 );
|
||||
|
||||
QwtText text = d.scaleWidget->title();
|
||||
text.setFont( fttl );
|
||||
d.scaleWidget->setTitle( text );
|
||||
|
||||
d.doAutoScale = true;
|
||||
|
||||
d.minValue = 0.0;
|
||||
d.maxValue = 1000.0;
|
||||
d.stepSize = 0.0;
|
||||
|
||||
d.maxMinor = 5;
|
||||
d.maxMajor = 8;
|
||||
|
||||
|
||||
d.isValid = false;
|
||||
}
|
||||
|
||||
d_axisData[yLeft]->isEnabled = true;
|
||||
d_axisData[yRight]->isEnabled = false;
|
||||
d_axisData[xBottom]->isEnabled = true;
|
||||
d_axisData[xTop]->isEnabled = false;
|
||||
}
|
||||
|
||||
void QwtPlot::deleteAxesData()
|
||||
{
|
||||
for ( int axisId = 0; axisId < axisCnt; axisId++ )
|
||||
{
|
||||
delete d_axisData[axisId]->scaleEngine;
|
||||
delete d_axisData[axisId];
|
||||
d_axisData[axisId] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Scale widget of the specified axis, or NULL if axisId is invalid.
|
||||
\param axisId Axis index
|
||||
*/
|
||||
const QwtScaleWidget *QwtPlot::axisWidget( int axisId ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return d_axisData[axisId]->scaleWidget;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Scale widget of the specified axis, or NULL if axisId is invalid.
|
||||
\param axisId Axis index
|
||||
*/
|
||||
QwtScaleWidget *QwtPlot::axisWidget( int axisId )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return d_axisData[axisId]->scaleWidget;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the scale engine for an axis
|
||||
|
||||
\param axisId Axis index
|
||||
\param scaleEngine Scale engine
|
||||
|
||||
\sa axisScaleEngine()
|
||||
*/
|
||||
void QwtPlot::setAxisScaleEngine( int axisId, QwtScaleEngine *scaleEngine )
|
||||
{
|
||||
if ( axisValid( axisId ) && scaleEngine != NULL )
|
||||
{
|
||||
AxisData &d = *d_axisData[axisId];
|
||||
|
||||
delete d.scaleEngine;
|
||||
d.scaleEngine = scaleEngine;
|
||||
|
||||
d_axisData[axisId]->scaleWidget->setTransformation(
|
||||
scaleEngine->transformation() );
|
||||
|
||||
d.isValid = false;
|
||||
|
||||
autoRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\param axisId Axis index
|
||||
\return Scale engine for a specific axis
|
||||
*/
|
||||
QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return d_axisData[axisId]->scaleEngine;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
\param axisId Axis index
|
||||
\return Scale engine for a specific axis
|
||||
*/
|
||||
const QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return d_axisData[axisId]->scaleEngine;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
/*!
|
||||
\return \c True, if autoscaling is enabled
|
||||
\param axisId Axis index
|
||||
*/
|
||||
bool QwtPlot::axisAutoScale( int axisId ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return d_axisData[axisId]->doAutoScale;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return \c True, if a specified axis is enabled
|
||||
\param axisId Axis index
|
||||
*/
|
||||
bool QwtPlot::axisEnabled( int axisId ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return d_axisData[axisId]->isEnabled;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The font of the scale labels for a specified axis
|
||||
\param axisId Axis index
|
||||
*/
|
||||
QFont QwtPlot::axisFont( int axisId ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return axisWidget( axisId )->font();
|
||||
else
|
||||
return QFont();
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
\return The maximum number of major ticks for a specified axis
|
||||
\param axisId Axis index
|
||||
\sa setAxisMaxMajor(), QwtScaleEngine::divideScale()
|
||||
*/
|
||||
int QwtPlot::axisMaxMajor( int axisId ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return d_axisData[axisId]->maxMajor;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the maximum number of minor ticks for a specified axis
|
||||
\param axisId Axis index
|
||||
\sa setAxisMaxMinor(), QwtScaleEngine::divideScale()
|
||||
*/
|
||||
int QwtPlot::axisMaxMinor( int axisId ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return d_axisData[axisId]->maxMinor;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Return the scale division of a specified axis
|
||||
|
||||
axisScaleDiv(axisId).lowerBound(), axisScaleDiv(axisId).upperBound()
|
||||
are the current limits of the axis scale.
|
||||
|
||||
\param axisId Axis index
|
||||
\return Scale division
|
||||
|
||||
\sa QwtScaleDiv, setAxisScaleDiv(), QwtScaleEngine::divideScale()
|
||||
*/
|
||||
const QwtScaleDiv &QwtPlot::axisScaleDiv( int axisId ) const
|
||||
{
|
||||
return d_axisData[axisId]->scaleDiv;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Return the scale draw of a specified axis
|
||||
|
||||
\param axisId Axis index
|
||||
\return Specified scaleDraw for axis, or NULL if axis is invalid.
|
||||
*/
|
||||
const QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) const
|
||||
{
|
||||
if ( !axisValid( axisId ) )
|
||||
return NULL;
|
||||
|
||||
return axisWidget( axisId )->scaleDraw();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Return the scale draw of a specified axis
|
||||
|
||||
\param axisId Axis index
|
||||
\return Specified scaleDraw for axis, or NULL if axis is invalid.
|
||||
*/
|
||||
QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId )
|
||||
{
|
||||
if ( !axisValid( axisId ) )
|
||||
return NULL;
|
||||
|
||||
return axisWidget( axisId )->scaleDraw();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Return the step size parameter that has been set in setAxisScale.
|
||||
|
||||
This doesn't need to be the step size of the current scale.
|
||||
|
||||
\param axisId Axis index
|
||||
\return step size parameter value
|
||||
|
||||
\sa setAxisScale(), QwtScaleEngine::divideScale()
|
||||
*/
|
||||
double QwtPlot::axisStepSize( int axisId ) const
|
||||
{
|
||||
if ( !axisValid( axisId ) )
|
||||
return 0;
|
||||
|
||||
return d_axisData[axisId]->stepSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Return the current interval of the specified axis
|
||||
|
||||
This is only a convenience function for axisScaleDiv( axisId )->interval();
|
||||
|
||||
\param axisId Axis index
|
||||
\return Scale interval
|
||||
|
||||
\sa QwtScaleDiv, axisScaleDiv()
|
||||
*/
|
||||
QwtInterval QwtPlot::axisInterval( int axisId ) const
|
||||
{
|
||||
if ( !axisValid( axisId ) )
|
||||
return QwtInterval();
|
||||
|
||||
return d_axisData[axisId]->scaleDiv.interval();
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Title of a specified axis
|
||||
\param axisId Axis index
|
||||
*/
|
||||
QwtText QwtPlot::axisTitle( int axisId ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return axisWidget( axisId )->title();
|
||||
else
|
||||
return QwtText();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Enable or disable a specified axis
|
||||
|
||||
When an axis is disabled, this only means that it is not
|
||||
visible on the screen. Curves, markers and can be attached
|
||||
to disabled axes, and transformation of screen coordinates
|
||||
into values works as normal.
|
||||
|
||||
Only xBottom and yLeft are enabled by default.
|
||||
|
||||
\param axisId Axis index
|
||||
\param tf \c true (enabled) or \c false (disabled)
|
||||
*/
|
||||
void QwtPlot::enableAxis( int axisId, bool tf )
|
||||
{
|
||||
if ( axisValid( axisId ) && tf != d_axisData[axisId]->isEnabled )
|
||||
{
|
||||
d_axisData[axisId]->isEnabled = tf;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Transform the x or y coordinate of a position in the
|
||||
drawing region into a value.
|
||||
|
||||
\param axisId Axis index
|
||||
\param pos position
|
||||
|
||||
\return Position as axis coordinate
|
||||
|
||||
\warning The position can be an x or a y coordinate,
|
||||
depending on the specified axis.
|
||||
*/
|
||||
double QwtPlot::invTransform( int axisId, int pos ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return( canvasMap( axisId ).invTransform( pos ) );
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Transform a value into a coordinate in the plotting region
|
||||
|
||||
\param axisId Axis index
|
||||
\param value value
|
||||
\return X or Y coordinate in the plotting region corresponding
|
||||
to the value.
|
||||
*/
|
||||
double QwtPlot::transform( int axisId, double value ) const
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
return( canvasMap( axisId ).transform( value ) );
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the font of an axis
|
||||
|
||||
\param axisId Axis index
|
||||
\param font Font
|
||||
\warning This function changes the font of the tick labels,
|
||||
not of the axis title.
|
||||
*/
|
||||
void QwtPlot::setAxisFont( int axisId, const QFont &font )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
axisWidget( axisId )->setFont( font );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Enable autoscaling for a specified axis
|
||||
|
||||
This member function is used to switch back to autoscaling mode
|
||||
after a fixed scale has been set. Autoscaling is enabled by default.
|
||||
|
||||
\param axisId Axis index
|
||||
\param on On/Off
|
||||
\sa setAxisScale(), setAxisScaleDiv(), updateAxes()
|
||||
|
||||
\note The autoscaling flag has no effect until updateAxes() is executed
|
||||
( called by replot() ).
|
||||
*/
|
||||
void QwtPlot::setAxisAutoScale( int axisId, bool on )
|
||||
{
|
||||
if ( axisValid( axisId ) && ( d_axisData[axisId]->doAutoScale != on ) )
|
||||
{
|
||||
d_axisData[axisId]->doAutoScale = on;
|
||||
autoRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Disable autoscaling and specify a fixed scale for a selected axis.
|
||||
|
||||
In updateAxes() the scale engine calculates a scale division from the
|
||||
specified parameters, that will be assigned to the scale widget. So
|
||||
updates of the scale widget usually happen delayed with the next replot.
|
||||
|
||||
\param axisId Axis index
|
||||
\param min Minimum of the scale
|
||||
\param max Maximum of the scale
|
||||
\param stepSize Major step size. If <code>step == 0</code>, the step size is
|
||||
calculated automatically using the maxMajor setting.
|
||||
|
||||
\sa setAxisMaxMajor(), setAxisAutoScale(), axisStepSize(), QwtScaleEngine::divideScale()
|
||||
*/
|
||||
void QwtPlot::setAxisScale( int axisId, double min, double max, double stepSize )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
{
|
||||
AxisData &d = *d_axisData[axisId];
|
||||
|
||||
d.doAutoScale = false;
|
||||
d.isValid = false;
|
||||
|
||||
d.minValue = min;
|
||||
d.maxValue = max;
|
||||
d.stepSize = stepSize;
|
||||
|
||||
autoRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Disable autoscaling and specify a fixed scale for a selected axis.
|
||||
|
||||
The scale division will be stored locally only until the next call
|
||||
of updateAxes(). So updates of the scale widget usually happen delayed with
|
||||
the next replot.
|
||||
|
||||
\param axisId Axis index
|
||||
\param scaleDiv Scale division
|
||||
|
||||
\sa setAxisScale(), setAxisAutoScale()
|
||||
*/
|
||||
void QwtPlot::setAxisScaleDiv( int axisId, const QwtScaleDiv &scaleDiv )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
{
|
||||
AxisData &d = *d_axisData[axisId];
|
||||
|
||||
d.doAutoScale = false;
|
||||
d.scaleDiv = scaleDiv;
|
||||
d.isValid = true;
|
||||
|
||||
autoRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set a scale draw
|
||||
|
||||
\param axisId Axis index
|
||||
\param scaleDraw Object responsible for drawing scales.
|
||||
|
||||
By passing scaleDraw it is possible to extend QwtScaleDraw
|
||||
functionality and let it take place in QwtPlot. Please note
|
||||
that scaleDraw has to be created with new and will be deleted
|
||||
by the corresponding QwtScale member ( like a child object ).
|
||||
|
||||
\sa QwtScaleDraw, QwtScaleWidget
|
||||
\warning The attributes of scaleDraw will be overwritten by those of the
|
||||
previous QwtScaleDraw.
|
||||
*/
|
||||
|
||||
void QwtPlot::setAxisScaleDraw( int axisId, QwtScaleDraw *scaleDraw )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
{
|
||||
axisWidget( axisId )->setScaleDraw( scaleDraw );
|
||||
autoRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the alignment of the tick labels
|
||||
|
||||
\param axisId Axis index
|
||||
\param alignment Or'd Qt::AlignmentFlags see <qnamespace.h>
|
||||
|
||||
\sa QwtScaleDraw::setLabelAlignment()
|
||||
*/
|
||||
void QwtPlot::setAxisLabelAlignment( int axisId, Qt::Alignment alignment )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
axisWidget( axisId )->setLabelAlignment( alignment );
|
||||
}
|
||||
|
||||
/*!
|
||||
Rotate all tick labels
|
||||
|
||||
\param axisId Axis index
|
||||
\param rotation Angle in degrees. When changing the label rotation,
|
||||
the label alignment might be adjusted too.
|
||||
|
||||
\sa QwtScaleDraw::setLabelRotation(), setAxisLabelAlignment()
|
||||
*/
|
||||
void QwtPlot::setAxisLabelRotation( int axisId, double rotation )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
axisWidget( axisId )->setLabelRotation( rotation );
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the maximum number of minor scale intervals for a specified axis
|
||||
|
||||
\param axisId Axis index
|
||||
\param maxMinor Maximum number of minor steps
|
||||
|
||||
\sa axisMaxMinor()
|
||||
*/
|
||||
void QwtPlot::setAxisMaxMinor( int axisId, int maxMinor )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
{
|
||||
maxMinor = qBound( 0, maxMinor, 100 );
|
||||
|
||||
AxisData &d = *d_axisData[axisId];
|
||||
if ( maxMinor != d.maxMinor )
|
||||
{
|
||||
d.maxMinor = maxMinor;
|
||||
d.isValid = false;
|
||||
autoRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the maximum number of major scale intervals for a specified axis
|
||||
|
||||
\param axisId Axis index
|
||||
\param maxMajor Maximum number of major steps
|
||||
|
||||
\sa axisMaxMajor()
|
||||
*/
|
||||
void QwtPlot::setAxisMaxMajor( int axisId, int maxMajor )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
{
|
||||
maxMajor = qBound( 1, maxMajor, 10000 );
|
||||
|
||||
AxisData &d = *d_axisData[axisId];
|
||||
if ( maxMajor != d.maxMajor )
|
||||
{
|
||||
d.maxMajor = maxMajor;
|
||||
d.isValid = false;
|
||||
autoRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the title of a specified axis
|
||||
|
||||
\param axisId Axis index
|
||||
\param title axis title
|
||||
*/
|
||||
void QwtPlot::setAxisTitle( int axisId, const QString &title )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
axisWidget( axisId )->setTitle( title );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change the title of a specified axis
|
||||
|
||||
\param axisId Axis index
|
||||
\param title Axis title
|
||||
*/
|
||||
void QwtPlot::setAxisTitle( int axisId, const QwtText &title )
|
||||
{
|
||||
if ( axisValid( axisId ) )
|
||||
axisWidget( axisId )->setTitle( title );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Rebuild the axes scales
|
||||
|
||||
In case of autoscaling the boundaries of a scale are calculated
|
||||
from the bounding rectangles of all plot items, having the
|
||||
QwtPlotItem::AutoScale flag enabled ( QwtScaleEngine::autoScale() ).
|
||||
Then a scale division is calculated ( QwtScaleEngine::didvideScale() )
|
||||
and assigned to scale widget.
|
||||
|
||||
When the scale boundaries have been assigned with setAxisScale() a
|
||||
scale division is calculated ( QwtScaleEngine::didvideScale() )
|
||||
for this interval and assigned to the scale widget.
|
||||
|
||||
When the scale has been set explicitly by setAxisScaleDiv() the
|
||||
locally stored scale division gets assigned to the scale widget.
|
||||
|
||||
The scale widget indicates modifications by emitting a
|
||||
QwtScaleWidget::scaleDivChanged() signal.
|
||||
|
||||
updateAxes() is usually called by replot().
|
||||
|
||||
\sa setAxisAutoScale(), setAxisScale(), setAxisScaleDiv(), replot()
|
||||
QwtPlotItem::boundingRect()
|
||||
*/
|
||||
void QwtPlot::updateAxes()
|
||||
{
|
||||
// Find bounding interval of the item data
|
||||
// for all axes, where autoscaling is enabled
|
||||
|
||||
QwtInterval intv[axisCnt];
|
||||
|
||||
const QwtPlotItemList& itmList = itemList();
|
||||
|
||||
QwtPlotItemIterator it;
|
||||
for ( it = itmList.begin(); it != itmList.end(); ++it )
|
||||
{
|
||||
const QwtPlotItem *item = *it;
|
||||
|
||||
if ( !item->testItemAttribute( QwtPlotItem::AutoScale ) )
|
||||
continue;
|
||||
|
||||
if ( !item->isVisible() )
|
||||
continue;
|
||||
|
||||
if ( axisAutoScale( item->xAxis() ) || axisAutoScale( item->yAxis() ) )
|
||||
{
|
||||
const QRectF rect = item->boundingRect();
|
||||
|
||||
if ( rect.width() >= 0.0 )
|
||||
intv[item->xAxis()] |= QwtInterval( rect.left(), rect.right() );
|
||||
|
||||
if ( rect.height() >= 0.0 )
|
||||
intv[item->yAxis()] |= QwtInterval( rect.top(), rect.bottom() );
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust scales
|
||||
|
||||
for ( int axisId = 0; axisId < axisCnt; axisId++ )
|
||||
{
|
||||
AxisData &d = *d_axisData[axisId];
|
||||
|
||||
double minValue = d.minValue;
|
||||
double maxValue = d.maxValue;
|
||||
double stepSize = d.stepSize;
|
||||
|
||||
if ( d.doAutoScale && intv[axisId].isValid() )
|
||||
{
|
||||
d.isValid = false;
|
||||
|
||||
minValue = intv[axisId].minValue();
|
||||
maxValue = intv[axisId].maxValue();
|
||||
|
||||
d.scaleEngine->autoScale( d.maxMajor,
|
||||
minValue, maxValue, stepSize );
|
||||
}
|
||||
if ( !d.isValid )
|
||||
{
|
||||
d.scaleDiv = d.scaleEngine->divideScale(
|
||||
minValue, maxValue,
|
||||
d.maxMajor, d.maxMinor, stepSize );
|
||||
d.isValid = true;
|
||||
}
|
||||
|
||||
QwtScaleWidget *scaleWidget = axisWidget( axisId );
|
||||
scaleWidget->setScaleDiv( d.scaleDiv );
|
||||
|
||||
int startDist, endDist;
|
||||
scaleWidget->getBorderDistHint( startDist, endDist );
|
||||
scaleWidget->setBorderDist( startDist, endDist );
|
||||
}
|
||||
|
||||
for ( it = itmList.begin(); it != itmList.end(); ++it )
|
||||
{
|
||||
QwtPlotItem *item = *it;
|
||||
if ( item->testItemInterest( QwtPlotItem::ScaleInterest ) )
|
||||
{
|
||||
item->updateScaleDiv( axisScaleDiv( item->xAxis() ),
|
||||
axisScaleDiv( item->yAxis() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
459
third/3rd_qwt/qwt_plot_barchart.cpp
Normal file
459
third/3rd_qwt/qwt_plot_barchart.cpp
Normal file
@@ -0,0 +1,459 @@
|
||||
/* -*- 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_plot_barchart.h"
|
||||
#include "qwt_scale_map.h"
|
||||
#include "qwt_column_symbol.h"
|
||||
#include "qwt_painter.h"
|
||||
#include <qpainter.h>
|
||||
|
||||
class QwtPlotBarChart::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
symbol( NULL ),
|
||||
legendMode( QwtPlotBarChart::LegendChartTitle )
|
||||
{
|
||||
}
|
||||
|
||||
~PrivateData()
|
||||
{
|
||||
delete symbol;
|
||||
}
|
||||
|
||||
QwtColumnSymbol *symbol;
|
||||
QwtPlotBarChart::LegendMode legendMode;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
\param title Title of the curve
|
||||
*/
|
||||
QwtPlotBarChart::QwtPlotBarChart( const QwtText &title ):
|
||||
QwtPlotAbstractBarChart( title )
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
\param title Title of the curve
|
||||
*/
|
||||
QwtPlotBarChart::QwtPlotBarChart( const QString &title ):
|
||||
QwtPlotAbstractBarChart( QwtText( title ) )
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
QwtPlotBarChart::~QwtPlotBarChart()
|
||||
{
|
||||
delete d_data;
|
||||
}
|
||||
|
||||
void QwtPlotBarChart::init()
|
||||
{
|
||||
d_data = new PrivateData;
|
||||
setData( new QwtPointSeriesData() );
|
||||
}
|
||||
|
||||
//! \return QwtPlotItem::Rtti_PlotBarChart
|
||||
int QwtPlotBarChart::rtti() const
|
||||
{
|
||||
return QwtPlotItem::Rtti_PlotBarChart;
|
||||
}
|
||||
|
||||
/*!
|
||||
Initialize data with an array of points
|
||||
|
||||
\param samples Vector of points
|
||||
\note QVector is implicitly shared
|
||||
\note QPolygonF is derived from QVector<QPointF>
|
||||
*/
|
||||
void QwtPlotBarChart::setSamples(
|
||||
const QVector<QPointF> &samples )
|
||||
{
|
||||
setData( new QwtPointSeriesData( samples ) );
|
||||
}
|
||||
|
||||
/*!
|
||||
Initialize data with an array of doubles
|
||||
|
||||
The indices in the array are taken as x coordinate,
|
||||
while the doubles are interpreted as y values.
|
||||
|
||||
\param samples Vector of y coordinates
|
||||
\note QVector is implicitly shared
|
||||
*/
|
||||
void QwtPlotBarChart::setSamples(
|
||||
const QVector<double> &samples )
|
||||
{
|
||||
QVector<QPointF> points;
|
||||
for ( int i = 0; i < samples.size(); i++ )
|
||||
points += QPointF( i, samples[ i ] );
|
||||
|
||||
setData( new QwtPointSeriesData( points ) );
|
||||
}
|
||||
|
||||
/*!
|
||||
Assign a series of samples
|
||||
|
||||
setSamples() is just a wrapper for setData() without any additional
|
||||
value - beside that it is easier to find for the developer.
|
||||
|
||||
\param data Data
|
||||
\warning The item takes ownership of the data object, deleting
|
||||
it when its not used anymore.
|
||||
*/
|
||||
void QwtPlotBarChart::setSamples( QwtSeriesData<QPointF> *data )
|
||||
{
|
||||
setData( data );
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign a symbol
|
||||
|
||||
The bar chart will take the ownership of the symbol, hence the previously
|
||||
set symbol will be delete by setting a new one. If \p symbol is
|
||||
\c NULL no symbol will be drawn.
|
||||
|
||||
\param symbol Symbol
|
||||
\sa symbol()
|
||||
*/
|
||||
void QwtPlotBarChart::setSymbol( QwtColumnSymbol *symbol )
|
||||
{
|
||||
if ( symbol != d_data->symbol )
|
||||
{
|
||||
delete d_data->symbol;
|
||||
d_data->symbol = symbol;
|
||||
|
||||
legendChanged();
|
||||
itemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Current symbol or NULL, when no symbol has been assigned
|
||||
\sa setSymbol()
|
||||
*/
|
||||
const QwtColumnSymbol *QwtPlotBarChart::symbol() const
|
||||
{
|
||||
return d_data->symbol;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the mode that decides what to display on the legend
|
||||
|
||||
In case of LegendBarTitles barTitle() needs to be overloaded
|
||||
to return individual titles for each bar.
|
||||
|
||||
\param mode New mode
|
||||
\sa legendMode(), legendData(), barTitle(), QwtPlotItem::ItemAttribute
|
||||
*/
|
||||
void QwtPlotBarChart::setLegendMode( LegendMode mode )
|
||||
{
|
||||
if ( mode != d_data->legendMode )
|
||||
{
|
||||
d_data->legendMode = mode;
|
||||
legendChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Legend mode
|
||||
\sa setLegendMode()
|
||||
*/
|
||||
QwtPlotBarChart::LegendMode QwtPlotBarChart::legendMode() const
|
||||
{
|
||||
return d_data->legendMode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Bounding rectangle of all samples.
|
||||
For an empty series the rectangle is invalid.
|
||||
*/
|
||||
QRectF QwtPlotBarChart::boundingRect() const
|
||||
{
|
||||
const size_t numSamples = dataSize();
|
||||
if ( numSamples == 0 )
|
||||
return QwtPlotSeriesItem::boundingRect();
|
||||
|
||||
QRectF rect = QwtPlotSeriesItem::boundingRect();
|
||||
if ( rect.height() >= 0 )
|
||||
{
|
||||
const double baseLine = baseline();
|
||||
|
||||
if ( rect.bottom() < baseLine )
|
||||
rect.setBottom( baseLine );
|
||||
|
||||
if ( rect.top() > baseLine )
|
||||
rect.setTop( baseLine );
|
||||
}
|
||||
|
||||
if ( orientation() == Qt::Horizontal )
|
||||
rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw an interval of the bar chart
|
||||
|
||||
\param painter Painter
|
||||
\param xMap Maps x-values into pixel coordinates.
|
||||
\param yMap Maps y-values into pixel coordinates.
|
||||
\param canvasRect Contents rect of the canvas
|
||||
\param from Index of the first point to be painted
|
||||
\param to Index of the last point to be painted. If to < 0 the
|
||||
curve will be painted to its last point.
|
||||
|
||||
\sa drawSymbols()
|
||||
*/
|
||||
void QwtPlotBarChart::drawSeries( QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||||
const QRectF &canvasRect, int from, int to ) const
|
||||
{
|
||||
if ( to < 0 )
|
||||
to = dataSize() - 1;
|
||||
|
||||
if ( from < 0 )
|
||||
from = 0;
|
||||
|
||||
if ( from > to )
|
||||
return;
|
||||
|
||||
|
||||
const QRectF br = data()->boundingRect();
|
||||
const QwtInterval interval( br.left(), br.right() );
|
||||
|
||||
painter->save();
|
||||
|
||||
for ( int i = from; i <= to; i++ )
|
||||
{
|
||||
drawSample( painter, xMap, yMap,
|
||||
canvasRect, interval, i, sample( i ) );
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw a sample
|
||||
|
||||
\param painter Painter
|
||||
\param xMap x map
|
||||
\param yMap y map
|
||||
\param canvasRect Contents rect of the canvas
|
||||
\param boundingInterval Bounding interval of sample values
|
||||
\param index Index of the sample
|
||||
\param sample Value of the sample
|
||||
|
||||
\sa drawSeries()
|
||||
*/
|
||||
void QwtPlotBarChart::drawSample( QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||||
const QRectF &canvasRect, const QwtInterval &boundingInterval,
|
||||
int index, const QPointF &sample ) const
|
||||
{
|
||||
QwtColumnRect barRect;
|
||||
|
||||
if ( orientation() == Qt::Horizontal )
|
||||
{
|
||||
const double barHeight = sampleWidth( yMap, canvasRect.height(),
|
||||
boundingInterval.width(), sample.y() );
|
||||
|
||||
const double x1 = xMap.transform( baseline() );
|
||||
const double x2 = xMap.transform( sample.y() );
|
||||
|
||||
const double y = yMap.transform( sample.x() );
|
||||
const double y1 = y - 0.5 * barHeight;
|
||||
const double y2 = y + 0.5 * barHeight;
|
||||
|
||||
barRect.direction = ( x1 < x2 ) ?
|
||||
QwtColumnRect::LeftToRight : QwtColumnRect::RightToLeft;
|
||||
|
||||
barRect.hInterval = QwtInterval( x1, x2 ).normalized();
|
||||
barRect.vInterval = QwtInterval( y1, y2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
const double barWidth = sampleWidth( xMap, canvasRect.width(),
|
||||
boundingInterval.width(), sample.y() );
|
||||
|
||||
const double x = xMap.transform( sample.x() );
|
||||
const double x1 = x - 0.5 * barWidth;
|
||||
const double x2 = x + 0.5 * barWidth;
|
||||
|
||||
const double y1 = yMap.transform( baseline() );
|
||||
const double y2 = yMap.transform( sample.y() );
|
||||
|
||||
barRect.direction = ( y1 < y2 ) ?
|
||||
QwtColumnRect::TopToBottom : QwtColumnRect::BottomToTop;
|
||||
|
||||
barRect.hInterval = QwtInterval( x1, x2 );
|
||||
barRect.vInterval = QwtInterval( y1, y2 ).normalized();
|
||||
}
|
||||
|
||||
drawBar( painter, index, sample, barRect );
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw a bar
|
||||
|
||||
\param painter Painter
|
||||
\param sampleIndex Index of the sample represented by the bar
|
||||
\param sample Value of the sample
|
||||
\param rect Bounding rectangle of the bar
|
||||
*/
|
||||
void QwtPlotBarChart::drawBar( QPainter *painter,
|
||||
int sampleIndex, const QPointF &sample,
|
||||
const QwtColumnRect &rect ) const
|
||||
{
|
||||
const QwtColumnSymbol *specialSym =
|
||||
specialSymbol( sampleIndex, sample );
|
||||
|
||||
const QwtColumnSymbol *sym = specialSym;
|
||||
if ( sym == NULL )
|
||||
sym = d_data->symbol;
|
||||
|
||||
if ( sym )
|
||||
{
|
||||
sym->draw( painter, rect );
|
||||
}
|
||||
else
|
||||
{
|
||||
// we build a temporary default symbol
|
||||
QwtColumnSymbol columnSymbol( QwtColumnSymbol::Box );
|
||||
columnSymbol.setLineWidth( 1 );
|
||||
columnSymbol.setFrameStyle( QwtColumnSymbol::Plain );
|
||||
columnSymbol.draw( painter, rect );
|
||||
}
|
||||
|
||||
delete specialSym;
|
||||
}
|
||||
|
||||
/*!
|
||||
Needs to be overloaded to return a
|
||||
non default symbol for a specific sample
|
||||
|
||||
\param sampleIndex Index of the sample represented by the bar
|
||||
\param sample Value of the sample
|
||||
|
||||
\return NULL, indicating to use the default symbol
|
||||
*/
|
||||
QwtColumnSymbol *QwtPlotBarChart::specialSymbol(
|
||||
int sampleIndex, const QPointF &sample ) const
|
||||
{
|
||||
Q_UNUSED( sampleIndex );
|
||||
Q_UNUSED( sample );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Return the title of a bar
|
||||
|
||||
In LegendBarTitles mode the title is displayed on
|
||||
the legend entry corresponding to a bar.
|
||||
|
||||
The default implementation is a dummy, that is intended
|
||||
to be overloaded.
|
||||
|
||||
\param sampleIndex Index of the bar
|
||||
\return An empty text
|
||||
\sa LegendBarTitles
|
||||
*/
|
||||
QwtText QwtPlotBarChart::barTitle( int sampleIndex ) const
|
||||
{
|
||||
Q_UNUSED( sampleIndex );
|
||||
return QwtText();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Return all information, that is needed to represent
|
||||
the item on the legend
|
||||
|
||||
In case of LegendBarTitles an entry for each bar is returned,
|
||||
otherwise the chart is represented like any other plot item
|
||||
from its title() and the legendIcon().
|
||||
|
||||
\return Information, that is needed to represent the item on the legend
|
||||
\sa title(), setLegendMode(), barTitle(), QwtLegend, QwtPlotLegendItem
|
||||
*/
|
||||
QList<QwtLegendData> QwtPlotBarChart::legendData() const
|
||||
{
|
||||
QList<QwtLegendData> list;
|
||||
|
||||
if ( d_data->legendMode == LegendBarTitles )
|
||||
{
|
||||
const size_t numSamples = dataSize();
|
||||
for ( size_t i = 0; i < numSamples; i++ )
|
||||
{
|
||||
QwtLegendData data;
|
||||
|
||||
QVariant titleValue;
|
||||
qVariantSetValue( titleValue, barTitle( i ) );
|
||||
data.setValue( QwtLegendData::TitleRole, titleValue );
|
||||
|
||||
if ( !legendIconSize().isEmpty() )
|
||||
{
|
||||
QVariant iconValue;
|
||||
qVariantSetValue( iconValue,
|
||||
legendIcon( i, legendIconSize() ) );
|
||||
|
||||
data.setValue( QwtLegendData::IconRole, iconValue );
|
||||
}
|
||||
|
||||
list += data;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return QwtPlotAbstractBarChart::legendData();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return Icon representing a bar or the chart on the legend
|
||||
|
||||
When the legendMode() is LegendBarTitles the icon shows
|
||||
the bar corresponding to index - otherwise the bar
|
||||
displays the default symbol.
|
||||
|
||||
\param index Index of the legend entry
|
||||
\param size Icon size
|
||||
|
||||
\sa setLegendMode(), drawBar(),
|
||||
QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData()
|
||||
*/
|
||||
QwtGraphic QwtPlotBarChart::legendIcon(
|
||||
int index, const QSizeF &size ) const
|
||||
{
|
||||
QwtColumnRect column;
|
||||
column.hInterval = QwtInterval( 0.0, size.width() - 1.0 );
|
||||
column.vInterval = QwtInterval( 0.0, size.height() - 1.0 );
|
||||
|
||||
QwtGraphic icon;
|
||||
icon.setDefaultSize( size );
|
||||
icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
|
||||
|
||||
QPainter painter( &icon );
|
||||
painter.setRenderHint( QPainter::Antialiasing,
|
||||
testRenderHint( QwtPlotItem::RenderAntialiased ) );
|
||||
|
||||
int barIndex = -1;
|
||||
if ( d_data->legendMode == QwtPlotBarChart::LegendBarTitles )
|
||||
barIndex = index;
|
||||
|
||||
drawBar( &painter, barIndex, QPointF(), column );
|
||||
|
||||
return icon;
|
||||
}
|
||||
118
third/3rd_qwt/qwt_plot_barchart.h
Normal file
118
third/3rd_qwt/qwt_plot_barchart.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PLOT_BAR_CHART_H
|
||||
#define QWT_PLOT_BAR_CHART_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include "qwt_plot_abstract_barchart.h"
|
||||
#include "qwt_series_data.h"
|
||||
|
||||
class QwtColumnRect;
|
||||
class QwtColumnSymbol;
|
||||
|
||||
/*!
|
||||
\brief QwtPlotBarChart displays a series of a values as bars.
|
||||
|
||||
Each bar might be customized individually by implementing
|
||||
a specialSymbol(). Otherwise it is rendered using a default symbol.
|
||||
|
||||
Depending on its orientation() the bars are displayed horizontally
|
||||
or vertically. The bars cover the interval between the baseline()
|
||||
and the value.
|
||||
|
||||
By activating the LegendBarTitles mode each sample will have
|
||||
its own entry on the legend.
|
||||
|
||||
The most common use case of a bar chart is to display a
|
||||
list of y coordinates, where the x coordinate is simply the index
|
||||
in the list. But for other situations ( f.e. when values are related
|
||||
to dates ) it is also possible to set x coordinates explicitly.
|
||||
|
||||
\sa QwtPlotMultiBarChart, QwtPlotHistogram, QwtPlotCurve::Sticks,
|
||||
QwtPlotSeriesItem::orientation(), QwtPlotAbstractBarChart::baseline()
|
||||
*/
|
||||
class QWT_EXPORT QwtPlotBarChart:
|
||||
public QwtPlotAbstractBarChart, public QwtSeriesStore<QPointF>
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
\brief Legend modes.
|
||||
|
||||
The default setting is QwtPlotBarChart::LegendChartTitle.
|
||||
\sa setLegendMode(), legendMode()
|
||||
*/
|
||||
enum LegendMode
|
||||
{
|
||||
/*!
|
||||
One entry on the legend showing the default symbol
|
||||
and the title() of the chart
|
||||
|
||||
\sa QwtPlotItem::title()
|
||||
*/
|
||||
LegendChartTitle,
|
||||
|
||||
/*!
|
||||
One entry for each value showing the individual symbol
|
||||
of the corresponding bar and the bar title.
|
||||
|
||||
\sa specialSymbol(), barTitle()
|
||||
*/
|
||||
LegendBarTitles
|
||||
};
|
||||
|
||||
explicit QwtPlotBarChart( const QString &title = QString() );
|
||||
explicit QwtPlotBarChart( const QwtText &title );
|
||||
|
||||
virtual ~QwtPlotBarChart();
|
||||
|
||||
virtual int rtti() const;
|
||||
|
||||
void setSamples( const QVector<QPointF> & );
|
||||
void setSamples( const QVector<double> & );
|
||||
void setSamples( QwtSeriesData<QPointF> * );
|
||||
|
||||
void setSymbol( QwtColumnSymbol * );
|
||||
const QwtColumnSymbol *symbol() const;
|
||||
|
||||
void setLegendMode( LegendMode );
|
||||
LegendMode legendMode() const;
|
||||
|
||||
virtual void drawSeries( QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||||
const QRectF &canvasRect, int from, int to ) const;
|
||||
|
||||
virtual QRectF boundingRect() const;
|
||||
|
||||
virtual QwtColumnSymbol *specialSymbol(
|
||||
int sampleIndex, const QPointF& ) const;
|
||||
|
||||
virtual QwtText barTitle( int sampleIndex ) const;
|
||||
|
||||
protected:
|
||||
virtual void drawSample( QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||||
const QRectF &canvasRect, const QwtInterval &boundingInterval,
|
||||
int index, const QPointF& sample ) const;
|
||||
|
||||
virtual void drawBar( QPainter *,
|
||||
int sampleIndex, const QPointF& sample,
|
||||
const QwtColumnRect & ) const;
|
||||
|
||||
QList<QwtLegendData> legendData() const;
|
||||
QwtGraphic legendIcon( int index, const QSizeF & ) const;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
1114
third/3rd_qwt/qwt_plot_canvas.cpp
Normal file
1114
third/3rd_qwt/qwt_plot_canvas.cpp
Normal file
File diff suppressed because it is too large
Load Diff
171
third/3rd_qwt/qwt_plot_canvas.h
Normal file
171
third/3rd_qwt/qwt_plot_canvas.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/* -*- 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
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QWT_PLOT_CANVAS_H
|
||||
#define QWT_PLOT_CANVAS_H
|
||||
|
||||
#include "qwt_global.h"
|
||||
#include <qframe.h>
|
||||
#include <qpainterpath.h>
|
||||
|
||||
class QwtPlot;
|
||||
class QPixmap;
|
||||
|
||||
/*!
|
||||
\brief Canvas of a QwtPlot.
|
||||
|
||||
Canvas is the widget where all plot items are displayed
|
||||
|
||||
\sa QwtPlot::setCanvas(), QwtPlotGLCanvas
|
||||
*/
|
||||
class QWT_EXPORT QwtPlotCanvas : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( double borderRadius READ borderRadius WRITE setBorderRadius )
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
\brief Paint attributes
|
||||
|
||||
The default setting enables BackingStore and Opaque.
|
||||
|
||||
\sa setPaintAttribute(), testPaintAttribute()
|
||||
*/
|
||||
enum PaintAttribute
|
||||
{
|
||||
/*!
|
||||
\brief Paint double buffered reusing the content
|
||||
of the pixmap buffer when possible.
|
||||
|
||||
Using a backing store might improve the performance
|
||||
significantly, when working with widget overlays ( like rubber bands ).
|
||||
Disabling the cache might improve the performance for
|
||||
incremental paints (using QwtPlotDirectPainter ).
|
||||
|
||||
\sa backingStore(), invalidateBackingStore()
|
||||
*/
|
||||
BackingStore = 1,
|
||||
|
||||
/*!
|
||||
\brief Try to fill the complete contents rectangle
|
||||
of the plot canvas
|
||||
|
||||
When using styled backgrounds Qt assumes, that the
|
||||
canvas doesn't fill its area completely
|
||||
( f.e because of rounded borders ) and fills the area
|
||||
below the canvas. When this is done with gradients it might
|
||||
result in a serious performance bottleneck - depending on the size.
|
||||
|
||||
When the Opaque attribute is enabled the canvas tries to
|
||||
identify the gaps with some heuristics and to fill those only.
|
||||
|
||||
\warning Will not work for semitransparent backgrounds
|
||||
*/
|
||||
Opaque = 2,
|
||||
|
||||
/*!
|
||||
\brief Try to improve painting of styled backgrounds
|
||||
|
||||
QwtPlotCanvas supports the box model attributes for
|
||||
customizing the layout with style sheets. Unfortunately
|
||||
the design of Qt style sheets has no concept how to
|
||||
handle backgrounds with rounded corners - beside of padding.
|
||||
|
||||
When HackStyledBackground is enabled the plot canvas tries
|
||||
to separate the background from the background border
|
||||
by reverse engineering to paint the background before and
|
||||
the border after the plot items. In this order the border
|
||||
gets perfectly antialiased and you can avoid some pixel
|
||||
artifacts in the corners.
|
||||
*/
|
||||
HackStyledBackground = 4,
|
||||
|
||||
/*!
|
||||
When ImmediatePaint is set replot() calls repaint()
|
||||
instead of update().
|
||||
|
||||
\sa replot(), QWidget::repaint(), QWidget::update()
|
||||
*/
|
||||
ImmediatePaint = 8
|
||||
};
|
||||
|
||||
//! Paint attributes
|
||||
typedef QFlags<PaintAttribute> PaintAttributes;
|
||||
|
||||
/*!
|
||||
\brief Focus indicator
|
||||
The default setting is NoFocusIndicator
|
||||
\sa setFocusIndicator(), focusIndicator(), drawFocusIndicator()
|
||||
*/
|
||||
|
||||
enum FocusIndicator
|
||||
{
|
||||
//! Don't paint a focus indicator
|
||||
NoFocusIndicator,
|
||||
|
||||
/*!
|
||||
The focus is related to the complete canvas.
|
||||
Paint the focus indicator using drawFocusIndicator()
|
||||
*/
|
||||
CanvasFocusIndicator,
|
||||
|
||||
/*!
|
||||
The focus is related to an item (curve, point, ...) on
|
||||
the canvas. It is up to the application to display a
|
||||
focus indication using f.e. highlighting.
|
||||
*/
|
||||
ItemFocusIndicator
|
||||
};
|
||||
|
||||
explicit QwtPlotCanvas( QwtPlot * = NULL );
|
||||
virtual ~QwtPlotCanvas();
|
||||
|
||||
QwtPlot *plot();
|
||||
const QwtPlot *plot() const;
|
||||
|
||||
void setFocusIndicator( FocusIndicator );
|
||||
FocusIndicator focusIndicator() const;
|
||||
|
||||
void setBorderRadius( double );
|
||||
double borderRadius() const;
|
||||
|
||||
void setPaintAttribute( PaintAttribute, bool on = true );
|
||||
bool testPaintAttribute( PaintAttribute ) const;
|
||||
|
||||
const QPixmap *backingStore() const;
|
||||
void invalidateBackingStore();
|
||||
|
||||
virtual bool event( QEvent * );
|
||||
|
||||
Q_INVOKABLE QPainterPath borderPath( const QRect & ) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void replot();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent( QPaintEvent * );
|
||||
virtual void resizeEvent( QResizeEvent * );
|
||||
|
||||
virtual void drawFocusIndicator( QPainter * );
|
||||
virtual void drawBorder( QPainter * );
|
||||
|
||||
void updateStyleSheetInfo();
|
||||
|
||||
private:
|
||||
void drawCanvas( QPainter *, bool withBackground );
|
||||
|
||||
class PrivateData;
|
||||
PrivateData *d_data;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCanvas::PaintAttributes )
|
||||
|
||||
#endif
|
||||
1209
third/3rd_qwt/qwt_plot_curve.cpp
Normal file
1209
third/3rd_qwt/qwt_plot_curve.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user