You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
865 lines
25 KiB
C
865 lines
25 KiB
C
2 years ago
|
/***************************************************************************
|
||
|
* Copyright (C) gempa GmbH *
|
||
|
* All rights reserved. *
|
||
|
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||
|
* *
|
||
|
* GNU Affero General Public License Usage *
|
||
|
* This file may be used under the terms of the GNU Affero *
|
||
|
* Public License version 3.0 as published by the Free Software Foundation *
|
||
|
* and appearing in the file LICENSE included in the packaging of this *
|
||
|
* file. Please review the following information to ensure the GNU Affero *
|
||
|
* Public License version 3.0 requirements will be met: *
|
||
|
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||
|
* *
|
||
|
* Other Usage *
|
||
|
* Alternatively, this file may be used in accordance with the terms and *
|
||
|
* conditions contained in a signed written agreement between you and *
|
||
|
* gempa GmbH. *
|
||
|
***************************************************************************/
|
||
|
|
||
|
|
||
|
|
||
|
#ifndef SEISCOMP_GUI_RECORDWIDGET_H
|
||
|
#define SEISCOMP_GUI_RECORDWIDGET_H
|
||
|
|
||
|
#include <QWidget>
|
||
|
#include <QFrame>
|
||
|
#include <QMouseEvent>
|
||
|
#include <QPaintEvent>
|
||
|
#include <QResizeEvent>
|
||
|
#include <QScrollBar>
|
||
|
#include <QHBoxLayout>
|
||
|
|
||
|
#ifndef Q_MOC_RUN
|
||
|
#include <seiscomp/core/record.h>
|
||
|
#include <seiscomp/datamodel/waveformstreamid.h>
|
||
|
#include <seiscomp/math/filter.h>
|
||
|
|
||
|
#include "recordpolyline.h"
|
||
|
#endif
|
||
|
|
||
|
|
||
|
namespace Seiscomp {
|
||
|
namespace Gui {
|
||
|
|
||
|
|
||
|
class RecordWidget;
|
||
|
|
||
|
|
||
|
//! \brief RecordMarker - marks a certain timestamp in the record
|
||
|
//! \brief sequence with a color and a type.
|
||
|
//!
|
||
|
//! Furthermore a marker can be moved on the stream. This class
|
||
|
//! is useful to correct picks visually.
|
||
|
class SC_GUI_API RecordMarker : public QObject {
|
||
|
|
||
|
Q_OBJECT
|
||
|
|
||
|
public:
|
||
|
RecordMarker(RecordWidget *parent,
|
||
|
const Seiscomp::Core::Time& pos,
|
||
|
Qt::Alignment = Qt::AlignVCenter);
|
||
|
|
||
|
RecordMarker(RecordWidget *parent,
|
||
|
const Seiscomp::Core::Time& pos,
|
||
|
const QString& text,
|
||
|
Qt::Alignment = Qt::AlignVCenter);
|
||
|
|
||
|
RecordMarker(RecordWidget *parent,
|
||
|
const RecordMarker&);
|
||
|
|
||
|
virtual ~RecordMarker();
|
||
|
|
||
|
|
||
|
protected:
|
||
|
void setParent(RecordWidget*);
|
||
|
|
||
|
|
||
|
public:
|
||
|
RecordWidget* parent() const;
|
||
|
|
||
|
void setColor(QColor c);
|
||
|
QColor color() const;
|
||
|
|
||
|
void setAlignment(Qt::Alignment);
|
||
|
Qt::Alignment alignment() const;
|
||
|
|
||
|
void setModifiedColor(QColor c);
|
||
|
QColor modifiedColor() const;
|
||
|
|
||
|
const Seiscomp::Core::Time& time() const;
|
||
|
|
||
|
void setCorrectedTime(const Seiscomp::Core::Time&);
|
||
|
const Seiscomp::Core::Time& correctedTime() const;
|
||
|
|
||
|
void setText(const QString&);
|
||
|
const QString& text() const;
|
||
|
|
||
|
void addAlias(const QString&);
|
||
|
|
||
|
void setDescription(const QString&);
|
||
|
const QString& description() const;
|
||
|
|
||
|
bool matches(const QString &text) const;
|
||
|
|
||
|
//! Returns the text to render
|
||
|
//! When description is empty then text is used else
|
||
|
//! the description itself is going to be rendered
|
||
|
const QString& renderText() const;
|
||
|
|
||
|
void setVisible(bool visible);
|
||
|
bool isVisible() const;
|
||
|
bool isHidden() const;
|
||
|
|
||
|
void setMovable(bool enable);
|
||
|
bool isMovable() const;
|
||
|
|
||
|
void setMoveCopy(bool enable);
|
||
|
bool isMoveCopyEnabled() const;
|
||
|
|
||
|
bool isEnabled() const;
|
||
|
|
||
|
//! Sets internal data to data. This can be used for
|
||
|
//! user data to store anything that a QVariant can store.
|
||
|
void setData(const QVariant& data);
|
||
|
|
||
|
//! Returns the user data set in setData
|
||
|
QVariant data() const;
|
||
|
|
||
|
//! Sets an id for the marker. This id is application depended
|
||
|
//! and can be chosen freely
|
||
|
void setId(int id);
|
||
|
|
||
|
//! Returns the id for the marker
|
||
|
int id() const;
|
||
|
|
||
|
bool isModified() const;
|
||
|
|
||
|
//! Sets the corrected time to the start time
|
||
|
void reset();
|
||
|
|
||
|
//! Sets the start time to the corrected time
|
||
|
void apply();
|
||
|
|
||
|
void update();
|
||
|
|
||
|
virtual RecordMarker *copy();
|
||
|
|
||
|
//! Draws the background of a marker. This method is called before
|
||
|
//! the traces are drawn.
|
||
|
virtual void drawBackground(QPainter &painter, RecordWidget *context,
|
||
|
int x, int y1, int y2,
|
||
|
QColor color, qreal lineWidth);
|
||
|
|
||
|
//! Draws the marker. This method is called after the traces are drawn.
|
||
|
virtual void draw(QPainter &painter, RecordWidget *context,
|
||
|
int x, int y1, int y2,
|
||
|
QColor color, qreal lineWidth);
|
||
|
|
||
|
virtual QString toolTip() const;
|
||
|
|
||
|
|
||
|
public slots:
|
||
|
virtual void setEnabled(bool enable);
|
||
|
|
||
|
|
||
|
private:
|
||
|
RecordWidget *_parent;
|
||
|
QColor _color;
|
||
|
QColor _modifierColor;
|
||
|
Seiscomp::Core::Time _time;
|
||
|
Seiscomp::Core::Time _correctedTime;
|
||
|
QString _text;
|
||
|
QString _description;
|
||
|
QVector<QString> _aliases;
|
||
|
bool _visible;
|
||
|
bool _moveable;
|
||
|
bool _moveCopy;
|
||
|
bool _enabled;
|
||
|
int _id;
|
||
|
Qt::Alignment _alignment;
|
||
|
QVariant _data;
|
||
|
|
||
|
friend class RecordWidget;
|
||
|
};
|
||
|
|
||
|
|
||
|
//!\brief RecordWidgetDecorator - decorates a RecordWidget
|
||
|
//!
|
||
|
//! This class can be used to draw custom decorations before
|
||
|
//! and after the RecordWidget paints its data.
|
||
|
class RecordWidgetDecorator : public QObject {
|
||
|
Q_OBJECT
|
||
|
|
||
|
public:
|
||
|
RecordWidgetDecorator(QObject *parent = 0);
|
||
|
|
||
|
|
||
|
public:
|
||
|
virtual void drawDecoration(QPainter *painter, RecordWidget *widget) = 0;
|
||
|
};
|
||
|
|
||
|
|
||
|
//!\brief RecordWidget - draws seismograms in a rectangular widget
|
||
|
//!
|
||
|
//! This class is only responsible for drawing, it gets records assigned as
|
||
|
//! pointers and is (optional) responsible for their (de)allocation. Only filtered
|
||
|
//! recordstreams are owned by the RecordWidget.
|
||
|
class SC_GUI_API RecordWidget : public QWidget {
|
||
|
Q_OBJECT
|
||
|
|
||
|
public:
|
||
|
enum DrawMode {
|
||
|
Single,
|
||
|
InRows,
|
||
|
Stacked,
|
||
|
SameOffset
|
||
|
};
|
||
|
|
||
|
enum ShadowWidgetFlags {
|
||
|
Raw = 0x01,
|
||
|
Filtered = 0x02
|
||
|
};
|
||
|
|
||
|
enum AxisPosition {
|
||
|
Left,
|
||
|
Right
|
||
|
};
|
||
|
|
||
|
enum RecordBorderDrawMode {
|
||
|
TopLine,
|
||
|
BottomLine,
|
||
|
Box
|
||
|
};
|
||
|
|
||
|
typedef Math::Filtering::InPlaceFilter<double> Filter;
|
||
|
|
||
|
struct Trace {
|
||
|
Trace() = default;
|
||
|
|
||
|
double dyMin{0}; // Data minimum value
|
||
|
double dyMax{0}; // Data maximum value
|
||
|
double dOffset{0}; // Data offset
|
||
|
double absMax{0};
|
||
|
int pyMin{0}; //
|
||
|
int pyMax{0};
|
||
|
double fyMin{-1};
|
||
|
double fyMax{1};
|
||
|
|
||
|
double yMin{0};
|
||
|
double yMax{0};
|
||
|
double yOffset{0}; // The used offset
|
||
|
|
||
|
float timingQuality{-1};
|
||
|
int timingQualityCount{0};
|
||
|
bool dirty{false};
|
||
|
bool visible{false};
|
||
|
AbstractRecordPolylinePtr poly;
|
||
|
QString status;
|
||
|
|
||
|
void reset() {
|
||
|
dyMin = dyMax = dOffset = absMax = 0;
|
||
|
fyMin = -1; fyMax = 1;
|
||
|
pyMin = pyMax = 0;
|
||
|
visible = false;
|
||
|
poly = nullptr;
|
||
|
}
|
||
|
|
||
|
bool validTrace() const {
|
||
|
return poly && !poly->isEmpty();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
RecordWidget(QWidget *parent=0);
|
||
|
RecordWidget(const DataModel::WaveformStreamID& streamID, QWidget *parent=0);
|
||
|
|
||
|
~RecordWidget();
|
||
|
|
||
|
public:
|
||
|
void enableRecordFiltering(int slot, bool enable);
|
||
|
bool isRecordFilteringEnabled(int slot);
|
||
|
|
||
|
bool isRecordVisible(int slot);
|
||
|
bool setRecordVisible(int slot, bool visible);
|
||
|
|
||
|
void setCustomBackgroundColor(QColor c);
|
||
|
void removeCustomBackgroundColor();
|
||
|
|
||
|
bool setRecords(int slot, RecordSequence*, bool owner = true);
|
||
|
bool setRecordID(int slot, const QString &id);
|
||
|
bool setRecordLabel(int slot, const QString &label);
|
||
|
bool setRecordColor(int slot, QColor c);
|
||
|
bool setRecordPen(int slot, const QPen &pen);
|
||
|
bool setRecordAntialiasing(int slot, bool antialiasing);
|
||
|
bool setRecordOptimization(int slot, bool enable);
|
||
|
bool setRecordStepFunction(int slot, bool enable);
|
||
|
bool setRecordBackgroundColor(int slot, QColor c);
|
||
|
bool removeRecordBackgroundColor(int slot);
|
||
|
bool setRecordFilter(int slot, const Filter *f);
|
||
|
bool setRecordScale(int slot, double scale);
|
||
|
bool setRecordUserData(int slot, QVariant data);
|
||
|
bool setRecordStatus(int slot, bool filtered, QString status);
|
||
|
|
||
|
RecordSequence *records() const;
|
||
|
RecordSequence *records(int slot) const;
|
||
|
RecordSequence *filteredRecords(int slot) const;
|
||
|
RecordSequence *takeRecords(int slot);
|
||
|
RecordSequence *createRecords(int slot, bool owner = true);
|
||
|
const Filter *recordFilter(int slot) const;
|
||
|
|
||
|
QString recordID(int slot) const;
|
||
|
QString recordLabel(int slot) const;
|
||
|
bool recordStepFunction(int slot) const;
|
||
|
QColor recordColor(int slot) const;
|
||
|
QPen recordPen(int slot) const;
|
||
|
const double *recordScale(int slot) const;
|
||
|
|
||
|
Trace *traceInfo(int slot, bool filtered = false);
|
||
|
const Trace *traceInfo(int slot, bool filtered = false) const;
|
||
|
|
||
|
QVariant recordUserData(int slot);
|
||
|
|
||
|
int setCurrentRecords(int slot);
|
||
|
int currentRecords() const;
|
||
|
|
||
|
public:
|
||
|
const QRect &canvasRect() const;
|
||
|
|
||
|
void setDrawMode(DrawMode mode);
|
||
|
DrawMode drawMode() const;
|
||
|
|
||
|
void setRecordBorderDrawMode(RecordBorderDrawMode mode);
|
||
|
RecordBorderDrawMode recordBorderDrawMode() const;
|
||
|
|
||
|
void setDrawOffset(bool f);
|
||
|
bool drawOffset() const { return _drawOffset; }
|
||
|
|
||
|
void setDrawSPS(bool f);
|
||
|
bool drawSPS() const { return _drawSPS; }
|
||
|
|
||
|
void setDrawRecordID(bool f);
|
||
|
bool drawRecordID() const { return _drawRecordID; }
|
||
|
|
||
|
void setRowSpacing(int);
|
||
|
int rowSpacing() const;
|
||
|
|
||
|
void setAxisSpacing(int);
|
||
|
int axisSpacing() const;
|
||
|
|
||
|
void setDrawAxis(bool f);
|
||
|
bool drawAxis() const { return _drawAxis; }
|
||
|
|
||
|
void setAxisWidth(int width);
|
||
|
int axisWidth() const;
|
||
|
|
||
|
void setAxisPosition(AxisPosition position);
|
||
|
AxisPosition axisPosition() const;
|
||
|
|
||
|
void setValuePrecision(int p);
|
||
|
int valuePrecision() const { return _valuePrecision; }
|
||
|
|
||
|
//! Sets a shadow widget that gets informed about record changes.
|
||
|
//! Available record slots are copied by reference
|
||
|
//! in that way that the listener is not the owner of the
|
||
|
//! data. Available marker are copied by value.
|
||
|
void setShadowWidget(RecordWidget *shadow, bool copyMarker,
|
||
|
int flags = Raw);
|
||
|
|
||
|
//! Returns the current shadow widget
|
||
|
RecordWidget *shadowWidget() const { return _shadowWidget; }
|
||
|
|
||
|
//! Sets the source widget for all markers.
|
||
|
//! This instance does not hold any marker but displays
|
||
|
//! the source widgets markers. All marker query function
|
||
|
//! are forwarded to source.
|
||
|
void setMarkerSourceWidget(RecordWidget *source);
|
||
|
|
||
|
//! Returns the current marker source widget
|
||
|
RecordWidget *markerSourceWidget() const { return _markerSourceWidget; }
|
||
|
|
||
|
void setDecorator(RecordWidgetDecorator *decorator);
|
||
|
RecordWidgetDecorator *decorator() const { return _decorator; }
|
||
|
|
||
|
//! Returns the fetched timing quality average
|
||
|
float timingQuality(int slot) const;
|
||
|
|
||
|
double timeScale() const { return _pixelPerSecond; }
|
||
|
double amplScale() const { return _amplScale; }
|
||
|
double tmin() const { return _tmin; }
|
||
|
double tmax() const { return _tmax; }
|
||
|
double amplMin() const { return _amplitudeRange[0]; }
|
||
|
double amplMax() const { return _amplitudeRange[1]; }
|
||
|
|
||
|
double smin() const { return _smin; }
|
||
|
double smax() const { return _smax; }
|
||
|
|
||
|
Seiscomp::Core::Time alignment() { return _alignment; }
|
||
|
|
||
|
Seiscomp::Core::Time centerTime();
|
||
|
|
||
|
//! Returns the trace plot position of the given slot
|
||
|
int streamYPos(int slot) const;
|
||
|
//! Returns the trace height of the given slot
|
||
|
int streamHeight(int slot) const;
|
||
|
|
||
|
//! Returns the amplitude range of the available data in the normalization
|
||
|
//! window
|
||
|
QPair<double,double> amplitudeDataRange(int slot) const;
|
||
|
|
||
|
//! Returns the amplitude range of the trace slot where first corresponds
|
||
|
//! to the lower pixel row and second to the upper pixel row
|
||
|
QPair<double,double> amplitudeRange(int slot) const;
|
||
|
|
||
|
void ensureVisibility(const Seiscomp::Core::Time &time, int pixelMargin);
|
||
|
|
||
|
//! Method to inform the widget about a newly inserted
|
||
|
//! record.
|
||
|
virtual void fed(int slot, const Seiscomp::Record *rec);
|
||
|
|
||
|
//! Causes the widget to rebuild its internal data
|
||
|
//! according its size and parameters
|
||
|
void setDirty();
|
||
|
|
||
|
//! Whether to show the current selected recordstream or
|
||
|
//! both recordstreams
|
||
|
void showAllRecords(bool enable);
|
||
|
|
||
|
//! Whether to show record borders
|
||
|
void showRecordBorders(bool enable);
|
||
|
|
||
|
//! Whether to show scaled or raw values. The default is false.
|
||
|
void showScaledValues(bool enable);
|
||
|
bool areScaledValuesShown() const { return _showScaledValues; }
|
||
|
|
||
|
//! Adds a marker to the widget. The ownership takes
|
||
|
//! the widget.
|
||
|
bool addMarker(RecordMarker*);
|
||
|
|
||
|
//! Inserts a marker at pos in the marker list
|
||
|
bool insertMarker(int pos, RecordMarker* marker);
|
||
|
|
||
|
int indexOfMarker(RecordMarker* marker) const;
|
||
|
|
||
|
//! Removes a record marker and returns the instance
|
||
|
RecordMarker *takeMarker(int pos);
|
||
|
RecordMarker *takeMarker(RecordMarker*);
|
||
|
|
||
|
//! Removes and deletes a record marker.
|
||
|
bool removeMarker(int pos);
|
||
|
bool removeMarker(RecordMarker*);
|
||
|
|
||
|
//! Returns the number of markers added to the widget.
|
||
|
int markerCount() const;
|
||
|
|
||
|
//! Returns the i-th marker.
|
||
|
RecordMarker* marker(int i) const;
|
||
|
|
||
|
//! Returns the marker with text set to txt
|
||
|
RecordMarker* marker(const QString& txt, bool movableOnly = false) const;
|
||
|
|
||
|
//! Returns the marker with text set to txt and which is enabled
|
||
|
RecordMarker* enabledMarker(const QString& txt) const;
|
||
|
|
||
|
//! Removes and deletes all marker inserted previously.
|
||
|
void clearMarker();
|
||
|
|
||
|
//! Sets the current marker
|
||
|
void setCurrentMarker(RecordMarker *);
|
||
|
|
||
|
//! Returns the currently focused marker
|
||
|
RecordMarker *currentMarker() const;
|
||
|
|
||
|
//! Returns the current marker under the mouse
|
||
|
RecordMarker *hoveredMarker() const;
|
||
|
|
||
|
//! Returns the marker under position p. If moveableOnly is set
|
||
|
//! to true, only movable markers are checked.
|
||
|
RecordMarker* markerAt(const QPoint& p, bool movableOnly = true, int maxDist = 5) const;
|
||
|
RecordMarker* markerAt(int x, int y, bool movableOnly = true, int maxDist = 5) const;
|
||
|
|
||
|
//! Returns the nearest marker left from time t
|
||
|
RecordMarker* lastMarker(const Seiscomp::Core::Time& t);
|
||
|
|
||
|
//! Returns the nearest marker right from time t
|
||
|
RecordMarker* nextMarker(const Seiscomp::Core::Time& t);
|
||
|
|
||
|
//! Returns the nearest marker at time t
|
||
|
RecordMarker* nearestMarker(const Seiscomp::Core::Time& t, int maxDist = -1);
|
||
|
|
||
|
//! Returns whether the widget has markers that are movable or not
|
||
|
bool hasMovableMarkers() const;
|
||
|
|
||
|
//! Sets the text to be displayed on the cursor
|
||
|
void setCursorText(const QString& text);
|
||
|
|
||
|
//! Returns the current cursor text
|
||
|
QString cursorText() const;
|
||
|
|
||
|
void setCursorPos(const QPoint&);
|
||
|
void setCursorPos(const Seiscomp::Core::Time&);
|
||
|
const Seiscomp::Core::Time& cursorPos() const;
|
||
|
|
||
|
const double *value(const Seiscomp::Core::Time&) const;
|
||
|
|
||
|
//! Returns the time on the left visible side of the widget
|
||
|
Seiscomp::Core::Time leftTime() const;
|
||
|
//! Returns the time on the right visible side of the widget
|
||
|
Seiscomp::Core::Time rightTime() const;
|
||
|
|
||
|
Seiscomp::Core::TimeWindow visibleTimeWindow() const;
|
||
|
Seiscomp::Core::TimeWindow selectedTimeWindow() const;
|
||
|
const Seiscomp::Core::TimeWindow & normalizationWindow() const;
|
||
|
|
||
|
bool isActive() const;
|
||
|
bool isFilteringEnabled() const;
|
||
|
bool isGlobalOffsetEnabled() const;
|
||
|
|
||
|
//! Maps a time to a position relative to the widget
|
||
|
int mapTime(const Core::Time&) const;
|
||
|
|
||
|
//! Maps a time to a position relative to the trace canvas
|
||
|
int mapCanvasTime(const Core::Time&) const;
|
||
|
|
||
|
//! Maps a widget position to a time
|
||
|
Core::Time unmapTime(int x) const;
|
||
|
|
||
|
const DataModel::WaveformStreamID& streamID() const;
|
||
|
|
||
|
void setSlotCount(int);
|
||
|
int slotCount() const;
|
||
|
|
||
|
//! Sets internal data to data. This can be used for
|
||
|
//! user data to store anything that a QVariant can store.
|
||
|
void setData(const QVariant& data);
|
||
|
|
||
|
//! Returns the user data set in setData
|
||
|
QVariant data() const;
|
||
|
|
||
|
|
||
|
public slots:
|
||
|
void setAmplAutoScaleEnabled(bool enable);
|
||
|
|
||
|
//! Sets clipping for drawmode InRows.
|
||
|
void setClippingEnabled(bool);
|
||
|
bool isClippingEnabled() const;
|
||
|
|
||
|
void enableGlobalOffset(bool enable);
|
||
|
|
||
|
void setSelected(double t1, double t2);
|
||
|
void setSelected(Seiscomp::Core::Time t1, Seiscomp::Core::Time t2);
|
||
|
|
||
|
void setScale(double, double=0);
|
||
|
void setTimeScale(double);
|
||
|
|
||
|
void setTimeRange(double, double);
|
||
|
void setAmplRange(double, double);
|
||
|
void setMinimumAmplRange(double, double);
|
||
|
|
||
|
void showTimeRange(double, double);
|
||
|
|
||
|
void translate(double);
|
||
|
|
||
|
void setEnabled(bool enabled);
|
||
|
void setAlignment(Seiscomp::Core::Time t);
|
||
|
void alignOnMarker(const QString& text);
|
||
|
|
||
|
void setAmplScale(double);
|
||
|
|
||
|
void enableFiltering(bool enable);
|
||
|
void setGridSpacing(double, double, double);
|
||
|
void setGridVSpacing(double, double, double);
|
||
|
void setGridVRange(double, double);
|
||
|
void setGridVScale(double);
|
||
|
|
||
|
void setActive(bool);
|
||
|
|
||
|
void setAutoMaxScale(bool);
|
||
|
|
||
|
void setNormalizationWindow(const Seiscomp::Core::TimeWindow&);
|
||
|
void setOffsetWindow(const Seiscomp::Core::TimeWindow&);
|
||
|
|
||
|
//! Sets the maximum slot index for which setFilter(filter) is
|
||
|
//! applied. The semantics of 'any' is bound to value -1.
|
||
|
void setFilterSlotMax(int max);
|
||
|
|
||
|
//! Sets the record filter. The filter will be cloned and will not
|
||
|
//! be touched by the widget. The caller is responsible to destroy
|
||
|
//! the filter used as parameter.
|
||
|
void setFilter(Filter* filter);
|
||
|
|
||
|
void updateRecords();
|
||
|
void clearRecords();
|
||
|
|
||
|
|
||
|
private slots:
|
||
|
void scroll(int);
|
||
|
|
||
|
|
||
|
signals:
|
||
|
//! This signal is emitted when a time (absolut time)
|
||
|
//! has been selected inside the widget. It does not
|
||
|
//! happen when a marker has been hit.
|
||
|
void selectedTime(Seiscomp::Core::Time);
|
||
|
|
||
|
//! This signal is emitted when a time range (absolut time)
|
||
|
//! has been selected inside the widget by holding
|
||
|
//! the left mouse button.
|
||
|
void selectedTimeRange(Seiscomp::Core::Time, Seiscomp::Core::Time);
|
||
|
|
||
|
//! This signal is emitted when a time range (absolut time)
|
||
|
//! is selected while still holding the left mouse button.
|
||
|
void selectedTimeRangeChanged(Seiscomp::Core::Time, Seiscomp::Core::Time);
|
||
|
|
||
|
//! Whenever a current (active) marker has changed
|
||
|
//! this signal will be emittet.
|
||
|
void currentMarkerChanged(Seiscomp::Gui::RecordMarker*);
|
||
|
|
||
|
void cursorMoved(QPoint p);
|
||
|
|
||
|
//! Whenever the cursor changes this signal is emitted.
|
||
|
//! The first parameter is the owner of the cursor and
|
||
|
//! the second parameter is the slot where the cursor has
|
||
|
//! been moved. This usually equals the current slot but
|
||
|
//! when drawing all slots in rows then it might differ.
|
||
|
void cursorUpdated(RecordWidget*, int);
|
||
|
void mouseOver(bool);
|
||
|
|
||
|
//! This signal is emitted when the user clicks with the
|
||
|
//! middle mousebutton into the trace
|
||
|
void clickedOnTime(Seiscomp::Core::Time);
|
||
|
|
||
|
void traceUpdated(Seiscomp::Gui::RecordWidget*);
|
||
|
|
||
|
//! This signal is emitted when the layout of the widget
|
||
|
//! changes. Whenever a new slot has been added or removed
|
||
|
//! and the drawingMode is InRows then a layoutRequest is made.
|
||
|
void layoutRequest();
|
||
|
|
||
|
void axisSettingsChanged(Seiscomp::Gui::RecordWidget*);
|
||
|
|
||
|
|
||
|
protected:
|
||
|
void init();
|
||
|
|
||
|
bool event(QEvent *);
|
||
|
|
||
|
void paintEvent(QPaintEvent*);
|
||
|
|
||
|
void mousePressEvent(QMouseEvent*);
|
||
|
void mouseReleaseEvent(QMouseEvent*);
|
||
|
void mouseDoubleClickEvent(QMouseEvent*);
|
||
|
void mouseMoveEvent(QMouseEvent*);
|
||
|
|
||
|
void resizeEvent(QResizeEvent*);
|
||
|
|
||
|
void enterEvent(QEvent*);
|
||
|
void leaveEvent(QEvent*);
|
||
|
|
||
|
void enabledChange(bool) { update(); }
|
||
|
|
||
|
virtual void changedRecords(int slot, RecordSequence*);
|
||
|
|
||
|
virtual void drawActiveCursor(QPainter &painter, int x, int y);
|
||
|
|
||
|
virtual void drawCustomBackground(QPainter &painter);
|
||
|
virtual void customPaintTracesBegin(QPainter &painter);
|
||
|
virtual void customPaintTracesEnd(QPainter &painter);
|
||
|
|
||
|
virtual void createPolyline(int slot, AbstractRecordPolylinePtr &polyline,
|
||
|
RecordSequence const *, double pixelPerSecond,
|
||
|
double amplMin, double amplMax, double amplOffset,
|
||
|
int height, bool optimization, bool highPrecision);
|
||
|
virtual const double *value(int slot, const Seiscomp::Core::Time&) const;
|
||
|
|
||
|
|
||
|
protected:
|
||
|
struct Stream {
|
||
|
enum Index {
|
||
|
Raw = 0,
|
||
|
Filtered = 1
|
||
|
};
|
||
|
|
||
|
Stream(bool owner);
|
||
|
~Stream();
|
||
|
|
||
|
void setDirty();
|
||
|
void free();
|
||
|
|
||
|
RecordSequence *records[2];
|
||
|
Trace traces[2];
|
||
|
bool ownRawRecords;
|
||
|
bool ownFilteredRecords;
|
||
|
bool visible;
|
||
|
bool filtering;
|
||
|
|
||
|
QString id;
|
||
|
QPen pen;
|
||
|
bool antialiasing;
|
||
|
bool stepFunction;
|
||
|
QColor customBackgroundColor;
|
||
|
bool hasCustomBackgroundColor;
|
||
|
bool optimize;
|
||
|
double scale;
|
||
|
|
||
|
// The value range axis, if enabled
|
||
|
QString axisLabel;
|
||
|
double axisSpacing[2];
|
||
|
bool axisDirty;
|
||
|
|
||
|
// Internal variables to track the current trace position
|
||
|
// in widget coordinated
|
||
|
int posY;
|
||
|
int height;
|
||
|
|
||
|
QVariant userData;
|
||
|
|
||
|
Filter *filter;
|
||
|
};
|
||
|
|
||
|
|
||
|
protected:
|
||
|
Stream *getStream(int);
|
||
|
const Stream *getStream(int) const;
|
||
|
|
||
|
bool createFilter();
|
||
|
bool createFilter(int slot);
|
||
|
void filterRecords(Stream *s);
|
||
|
bool setFilteredRecords(int slot, RecordSequence* seq, bool owner);
|
||
|
Record* filteredRecord(Filter *filter,
|
||
|
const Record*, const Record* = nullptr) const;
|
||
|
|
||
|
void prepareRecords(Stream *s);
|
||
|
void drawRecords(Stream *s, int slot);
|
||
|
void drawTrace(QPainter &painter,
|
||
|
const Trace *trace,
|
||
|
const RecordSequence *seq,
|
||
|
const QPen &pen,
|
||
|
const QPoint &paintOffset) const;
|
||
|
void drawRecordBorders(QPainter &painter, const RecordSequence *seq) const;
|
||
|
|
||
|
void drawAxis(QPainter &painter, const QPen &p);
|
||
|
|
||
|
int canvasWidth() const;
|
||
|
int canvasHeight() const;
|
||
|
|
||
|
|
||
|
private:
|
||
|
typedef QVector<Stream*> StreamMap;
|
||
|
|
||
|
QVariant _data;
|
||
|
DrawMode _drawMode;
|
||
|
RecordBorderDrawMode _recordBorderDrawMode;
|
||
|
Seiscomp::Core::Time _alignment;
|
||
|
bool _clipRows{true};
|
||
|
|
||
|
double _tmin; // time range min
|
||
|
double _tmax; // time range max
|
||
|
double _smin, _smax; // selection
|
||
|
double _pixelPerSecond;
|
||
|
double _amplScale; // pixel per amplitude unit (0=normalize)
|
||
|
double _gridHSpacing[2];
|
||
|
double _gridHOffset;
|
||
|
|
||
|
double _gridVRange[2];
|
||
|
double _gridVSpacing[2];
|
||
|
double _gridVOffset;
|
||
|
double _gridVScale;
|
||
|
|
||
|
double _amplitudeRange[2];
|
||
|
bool _useFixedAmplitudeRange{false};
|
||
|
bool _useMinAmplitudeRange{false};
|
||
|
|
||
|
bool _active{false};
|
||
|
bool _filtering{false};
|
||
|
bool _showScaledValues{false};
|
||
|
|
||
|
bool _drawRecords{false};
|
||
|
bool _drawRecordID{true};
|
||
|
bool _drawOffset{true};
|
||
|
bool _drawSPS{false};
|
||
|
bool _showAllRecords{false};
|
||
|
bool _showRecordBorders{false};
|
||
|
bool _autoMaxScale{false};
|
||
|
bool _enabled;
|
||
|
bool _useGlobalOffset{false};
|
||
|
bool _drawAxis;
|
||
|
|
||
|
int _tracePaintOffset;
|
||
|
int _axisWidth;
|
||
|
AxisPosition _axisPosition;
|
||
|
int _axisSpacing;
|
||
|
int _rowSpacing;
|
||
|
|
||
|
StreamMap _streams;
|
||
|
int _currentSlot;
|
||
|
int _requestedSlot;
|
||
|
int _maxFilterSlot;
|
||
|
int _currentCursorYPos;
|
||
|
int _valuePrecision;
|
||
|
|
||
|
QColor _customBackgroundColor;
|
||
|
bool _hasCustomBackground;
|
||
|
|
||
|
Seiscomp::DataModel::WaveformStreamID _streamID;
|
||
|
|
||
|
QVector<RecordMarker*> _marker;
|
||
|
RecordMarker *_activeMarker;
|
||
|
RecordMarker *_hoveredMarker;
|
||
|
|
||
|
QScrollBar *_scrollBar;
|
||
|
|
||
|
QRect _canvasRect;
|
||
|
int _margins[4];
|
||
|
QString _cursorText;
|
||
|
Seiscomp::Core::Time _cursorPos;
|
||
|
Seiscomp::Core::Time _startDragPos;
|
||
|
|
||
|
Seiscomp::Core::TimeWindow _normalizationWindow;
|
||
|
Seiscomp::Core::TimeWindow _offsetWindow;
|
||
|
|
||
|
RecordWidget *_shadowWidget;
|
||
|
RecordWidget *_markerSourceWidget;
|
||
|
|
||
|
RecordWidgetDecorator *_decorator;
|
||
|
|
||
|
int _shadowWidgetFlags;
|
||
|
};
|
||
|
|
||
|
|
||
|
inline const QRect &RecordWidget::canvasRect() const {
|
||
|
return _canvasRect;
|
||
|
}
|
||
|
|
||
|
inline int RecordWidget::rowSpacing() const {
|
||
|
return _rowSpacing;
|
||
|
}
|
||
|
|
||
|
inline int RecordWidget::axisSpacing() const {
|
||
|
return _axisSpacing;
|
||
|
}
|
||
|
|
||
|
inline int RecordWidget::axisWidth() const {
|
||
|
return _axisWidth;
|
||
|
}
|
||
|
|
||
|
inline RecordWidget::AxisPosition RecordWidget::axisPosition() const {
|
||
|
return _axisPosition;
|
||
|
}
|
||
|
|
||
|
inline int RecordWidget::canvasWidth() const {
|
||
|
return _canvasRect.width();
|
||
|
}
|
||
|
|
||
|
inline int RecordWidget::canvasHeight() const {
|
||
|
return _canvasRect.height();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
# endif
|