diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp index b7e706e60..d7627aa09 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp @@ -50,16 +50,22 @@ #include #include #include +#include using namespace Core; TestDataGen* ScopeGadgetWidget::testDataGen; +// ****************************************************************** + ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent) { //if(testDataGen == 0) // testDataGen = new TestDataGen(); + setMouseTracking(true); +// canvas()->setMouseTracking(true); + //Setup the timer that replots data replotTimer = new QTimer(this); connect(replotTimer, SIGNAL(timeout()), this, SLOT(replotNewData())); @@ -71,7 +77,6 @@ ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent) connect(cm, SIGNAL(deviceDisconnected()), this, SLOT(stopPlotting())); connect(cm, SIGNAL(deviceConnected(QIODevice*)), this, SLOT(startPlotting())); - m_csvLoggingStarted=0; m_csvLoggingEnabled=0; m_csvLoggingHeaderSaved=0; @@ -86,7 +91,63 @@ ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent) //Listen to autopilot connection events connect(cm, SIGNAL(deviceDisconnected()), this, SLOT(csvLoggingDisconnect())); connect(cm, SIGNAL(deviceConnected(QIODevice*)), this, SLOT(csvLoggingConnect())); +} +ScopeGadgetWidget::~ScopeGadgetWidget() +{ + if (replotTimer) + { + replotTimer->stop(); + + delete replotTimer; + replotTimer = NULL; + } + + // Get the object to de-monitor + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager *objManager = pm->getObject(); + foreach (QString uavObjName, m_connectedUAVObjects) + { + UAVDataObject *obj = dynamic_cast(objManager->getObject(uavObjName)); + disconnect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(uavObjectReceived(UAVObject*))); + } + + clearCurvePlots(); +} + +// ****************************************************************** + +void ScopeGadgetWidget::mousePressEvent(QMouseEvent *e) +{ + QwtPlot::mousePressEvent(e); +} + +void ScopeGadgetWidget::mouseReleaseEvent(QMouseEvent *e) +{ + QwtPlot::mouseReleaseEvent(e); +} + +void ScopeGadgetWidget::mouseDoubleClickEvent(QMouseEvent *e) +{ + mutex.lock(); + if (legend()) + deleteLegend(); + else + addLegend(); + mutex.unlock(); + update(); + + QwtPlot::mouseDoubleClickEvent(e); +} + +void ScopeGadgetWidget::mouseMoveEvent(QMouseEvent *e) +{ + QwtPlot::mouseMoveEvent(e); +} + +void ScopeGadgetWidget::wheelEvent(QWheelEvent *e) +{ + QwtPlot::wheelEvent(e); } /** @@ -94,7 +155,7 @@ ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent) */ void ScopeGadgetWidget::startPlotting() { - if(!replotTimer->isActive()) + if (!replotTimer->isActive()) replotTimer->start(m_refreshInterval); } @@ -103,6 +164,44 @@ void ScopeGadgetWidget::stopPlotting() replotTimer->stop(); } +void ScopeGadgetWidget::deleteLegend() +{ + if (!legend()) + return; + + disconnect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)), this, 0); + + insertLegend(NULL, QwtPlot::TopLegend); +} + +void ScopeGadgetWidget::addLegend() +{ + if (legend()) + return; + + // Show a legend at the top + QwtLegend *legend = new QwtLegend(); + legend->setItemMode(QwtLegend::CheckableItem); + legend->setFrameStyle(QFrame::Box | QFrame::Sunken); + legend->setToolTip(tr("Click legend to show/hide scope trace")); + + QPalette pal = legend->palette(); +// pal.setColor(QPalette::Window, QColor(64, 64, 64)); // background colour + pal.setColor(legend->backgroundRole(), QColor(100, 100, 100)); // background colour + pal.setColor(QPalette::Text, QColor(255, 255, 255)); // text colour + legend->setPalette(pal); + + insertLegend(legend, QwtPlot::TopLegend); + +// // Show a legend at the bottom +// QwtLegend *legend = new QwtLegend(); +// legend->setItemMode(QwtLegend::CheckableItem); +// legend->setFrameStyle(QFrame::Box | QFrame::Sunken); +// insertLegend(legend, QwtPlot::BottomLegend); + + connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)), this, SLOT(showCurve(QwtPlotItem *, bool))); +} + void ScopeGadgetWidget::preparePlot(PlotType plotType) { m_plotType = plotType; @@ -130,31 +229,8 @@ void ScopeGadgetWidget::preparePlot(PlotType plotType) grid->setPen(QPen(Qt::darkGray, 1, Qt::DotLine)); grid->attach(this); - // Show a legend at the top - if (!legend()) - { - QwtLegend *legend = new QwtLegend(); - legend->setItemMode(QwtLegend::CheckableItem); - legend->setFrameStyle(QFrame::Box | QFrame::Sunken); - legend->setToolTip(tr("Click legend to show/hide scope trace")); - - QPalette pal = legend->palette(); -// pal.setColor(QPalette::Window, QColor(64, 64, 64)); // background colour - pal.setColor(legend->backgroundRole(), QColor(100, 100, 100)); // background colour - pal.setColor(QPalette::Text, QColor(255, 255, 255)); // text colour - legend->setPalette(pal); - - insertLegend(legend, QwtPlot::TopLegend); - } - // Show a legend at the bottom -// if (legend() == 0) { -// QwtLegend *legend = new QwtLegend(); -// legend->setItemMode(QwtLegend::CheckableItem); -// legend->setFrameStyle(QFrame::Box | QFrame::Sunken); -// insertLegend(legend, QwtPlot::BottomLegend); -// } - - connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)),this, SLOT(showCurve(QwtPlotItem *, bool))); + // Add the legend + addLegend(); // Only start the timer if we are already connected Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager(); @@ -176,7 +252,9 @@ void ScopeGadgetWidget::showCurve(QwtPlotItem *item, bool on) if ( w && w->inherits("QwtLegendItem") ) ((QwtLegendItem *)w)->setChecked(on); - replot(); + mutex.lock(); + replot(); + mutex.unlock(); } void ScopeGadgetWidget::setupSequencialPlot() @@ -319,7 +397,9 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(uavObjectReceived(UAVObject*))); } - replot(); + mutex.lock(); + replot(); + mutex.unlock(); } //void ScopeGadgetWidget::removeCurvePlot(QString uavObject, QString uavField) @@ -333,7 +413,9 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField // delete plotData->curve; // delete plotData; // -// replot(); +// mutex.lock(); +// replot(); +// mutex.unlock(); //} void ScopeGadgetWidget::uavObjectReceived(UAVObject* obj) @@ -345,7 +427,10 @@ void ScopeGadgetWidget::uavObjectReceived(UAVObject* obj) void ScopeGadgetWidget::replotNewData() { - foreach(PlotData* plotData, m_curvesData.values()) { + QMutexLocker locker(&mutex); + + foreach(PlotData* plotData, m_curvesData.values()) + { plotData->removeStaleData(); plotData->curve->setData(*plotData->xData, *plotData->yData); } @@ -353,14 +438,15 @@ void ScopeGadgetWidget::replotNewData() QDateTime NOW = QDateTime::currentDateTime(); double toTime = NOW.toTime_t(); toTime += NOW.time().msec() / 1000.0; - if (m_plotType == ChronoPlot) { + if (m_plotType == ChronoPlot) setAxisScale(QwtPlot::xBottom, toTime - m_xWindowSize, toTime); - } - //qDebug() << "replotNewData from " << NOW.addSecs(- m_xWindowSize) << " to " << NOW; - csvLoggingInsertData(); - replot(); -} +// qDebug() << "replotNewData from " << NOW.addSecs(- m_xWindowSize) << " to " << NOW; + + csvLoggingInsertData(); + + replot(); +} void ScopeGadgetWidget::setupExamplePlot() { @@ -398,36 +484,14 @@ void ScopeGadgetWidget::setupExamplePlot() curve2->setData(x, cs, points); curve3->setData(x, sg, points); - - curve1->attach(this); curve2->attach(this); curve3->attach(this); - - // finally, refresh the plot - replot(); -} - - -ScopeGadgetWidget::~ScopeGadgetWidget() -{ - if (replotTimer) - replotTimer->stop(); - delete replotTimer; - replotTimer = 0; - - //Get the object to de-monitor - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager *objManager = pm->getObject(); - - foreach(QString uavObjName, m_connectedUAVObjects) { - UAVDataObject* obj = dynamic_cast(objManager->getObject(uavObjName)); - disconnect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(uavObjectReceived(UAVObject*))); - } - - clearCurvePlots(); + mutex.lock(); + replot(); + mutex.unlock(); } void ScopeGadgetWidget::clearCurvePlots() @@ -638,14 +702,13 @@ int ScopeGadgetWidget::csvLoggingInsertData() return 0; } + void ScopeGadgetWidget::csvLoggingSetName(QString newName) { m_csvLoggingName = newName; m_csvLoggingNameSet=1; } - - void ScopeGadgetWidget::csvLoggingConnect() { m_csvLoggingConnected=1; diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h index b2a0e273f..fd8aaf550 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h @@ -30,7 +30,6 @@ #include "plotdata.h" - #include "qwt/src/qwt.h" #include "qwt/src/qwt_plot.h" #include "qwt/src/qwt_plot_curve.h" @@ -40,7 +39,7 @@ #include #include #include - +#include /*! \brief This class is used to render the time values on the horizontal axis for the @@ -121,6 +120,13 @@ public: void setLoggingNewFileOnConnect(bool value){m_csvLoggingNewFileOnConnect=value;}; void setLoggingPath(QString value){m_csvLoggingPath=value;}; +protected: + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseDoubleClickEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void wheelEvent(QWheelEvent *e); + private slots: void uavObjectReceived(UAVObject*); void replotNewData(); @@ -162,9 +168,13 @@ private: QString m_csvLoggingPath; QFile m_csvLoggingFile; + QMutex mutex; + int csvLoggingInsertHeader(); int csvLoggingInsertData(); + void deleteLegend(); + void addLegend(); };