From 38c51e3a29bab13192ee194e82954885c7dc8bad Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Fri, 13 Jul 2012 14:30:06 -0500 Subject: [PATCH] Significant enhancements to trace widget --- clients/tde/src/part/commanalyzer/layout.ui | 19 + clients/tde/src/part/commanalyzer/part.cpp | 352 +++++++---- clients/tde/src/part/commanalyzer/part.h | 6 +- clients/tde/src/widgets/tracewidget.cpp | 649 ++++++++++++++++++-- clients/tde/src/widgets/tracewidget.h | 120 +++- 5 files changed, 988 insertions(+), 158 deletions(-) diff --git a/clients/tde/src/part/commanalyzer/layout.ui b/clients/tde/src/part/commanalyzer/layout.ui index 29d9392..82b011e 100644 --- a/clients/tde/src/part/commanalyzer/layout.ui +++ b/clients/tde/src/part/commanalyzer/layout.ui @@ -75,6 +75,25 @@ + + + traceZoomWidget + + + + 7 + 7 + 1 + 1 + + + + + 80 + 80 + + + diff --git a/clients/tde/src/part/commanalyzer/part.cpp b/clients/tde/src/part/commanalyzer/part.cpp index 3e53429..c0200ec 100644 --- a/clients/tde/src/part/commanalyzer/part.cpp +++ b/clients/tde/src/part/commanalyzer/part.cpp @@ -21,6 +21,7 @@ #include #include //access() #include +#include #include "tracewidget.h" #include "floatspinbox.h" @@ -42,7 +43,8 @@ K_EXPORT_COMPONENT_FACTORY( libremotelab_commanalyzer, RemoteLab::Factory ) CommAnalyzerPart::CommAnalyzerPart( TQWidget *parentWidget, const char *widgetName, TQObject *parent, const char *name, const TQStringList& ) - : RemoteInstrumentPart( parent, name ), m_traceWidget(0), m_commHandlerState(-1), m_commHandlerMode(0), m_commHandlerCommandState(0), m_base(0), stopTraceUpdate(false) + : RemoteInstrumentPart( parent, name ), m_traceWidget(0), m_commHandlerState(-1), m_commHandlerMode(0), m_commHandlerCommandState(0), m_connectionActiveAndValid(false), + m_base(0), stopTraceUpdate(false) { // Initialize important base class variables m_clientLibraryName = CLIENT_LIBRARY; @@ -55,17 +57,46 @@ CommAnalyzerPart::CommAnalyzerPart( TQWidget *parentWidget, const char *widgetNa setWidget(new TQVBox(parentWidget, widgetName)); // Create timers + m_forcedUpdateTimer = new TQTimer(this); + connect(m_forcedUpdateTimer, SIGNAL(timeout()), this, SLOT(mainEventLoop())); m_updateTimeoutTimer = new TQTimer(this); connect(m_updateTimeoutTimer, SIGNAL(timeout()), this, SLOT(mainEventLoop())); // Create widgets m_base = new CommAnalyzerBase(widget()); m_traceWidget = m_base->traceWidget; - m_base->traceWidget->setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding)); - m_base->traceWidget->setTraceEnabled(0, true); + m_traceWidget->setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding)); + m_traceWidget->setTraceEnabled(0, true); m_traceWidget->setTraceName(0, "Trace 1"); m_traceWidget->setTraceHorizontalUnits(0, "Hz"); m_traceWidget->setTraceVerticalUnits(0, "dBm"); + m_traceWidget->setNumberOfCursors(4); + m_traceWidget->setCursorOrientation(0, TQt::Horizontal); + m_traceWidget->setCursorOrientation(1, TQt::Horizontal); + m_traceWidget->setCursorOrientation(2, TQt::Vertical); + m_traceWidget->setCursorOrientation(3, TQt::Vertical); + m_traceWidget->setCursorEnabled(0, true); + m_traceWidget->setCursorEnabled(1, true); + m_traceWidget->setCursorEnabled(2, true); + m_traceWidget->setCursorEnabled(3, true); + m_traceWidget->setCursorName(0, "Cursor H1"); + m_traceWidget->setCursorName(1, "Cursor H2"); + m_traceWidget->setCursorName(2, "Cursor V1"); + m_traceWidget->setCursorName(3, "Cursor V2"); + m_traceWidget->setCursorPosition(0, 25); + m_traceWidget->setCursorPosition(1, 75); + m_traceWidget->setCursorPosition(2, 25); + m_traceWidget->setCursorPosition(3, 75); + m_traceWidget->setZoomBoxEnabled(true); + + m_base->traceZoomWidget->setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding)); + m_base->traceZoomWidget->setTraceEnabled(0, true, false); + m_base->traceZoomWidget->setTraceName(0, "Trace 1"); + m_base->traceZoomWidget->setTraceHorizontalUnits(0, "Hz"); + m_base->traceZoomWidget->setTraceVerticalUnits(0, "dBm"); + connect(m_traceWidget, SIGNAL(zoomBoxChanged(const TQRectF&)), this, SLOT(updateZoomWidgetLimits(const TQRectF&))); + + m_base->saRefLevel->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed)); m_base->saRefLevel->setFloatMin(-128); m_base->saRefLevel->setFloatMax(128); m_base->saRefLevel->setLineStep(1); @@ -90,6 +121,7 @@ void CommAnalyzerPart::postInit() { bool CommAnalyzerPart::openURL(const KURL &url) { int ret; + m_connectionActiveAndValid = false; ret = connectToServer(url.url()); processLockouts(); return (ret != 0); @@ -102,10 +134,18 @@ bool CommAnalyzerPart::closeURL() { } void CommAnalyzerPart::processLockouts() { + if (m_connectionActiveAndValid) { + m_base->setEnabled(true); + } + else { + m_base->setEnabled(false); + } } void CommAnalyzerPart::disconnectFromServerCallback() { + m_forcedUpdateTimer->stop(); m_updateTimeoutTimer->stop(); + m_connectionActiveAndValid = false; } void CommAnalyzerPart::connectionFinishedCallback() { @@ -122,42 +162,73 @@ void CommAnalyzerPart::connectionFinishedCallback() { return; } -#define UPDATEDISPLAY_TIMEOUT m_connectionActiveAndValid = false; \ - m_tickerState = 0; \ - m_commHandlerState = 2; \ - m_commHandlerMode = 0; \ - m_socket->clearIncomingData(); \ - setStatusMessage(i18n("Server ping timeout. Please verify the status of your network connection.")); \ - m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); \ - m_instrumentMutex->unlock(); \ - return; - -#define COMMUNICATIONS_FAILED m_connectionActiveAndValid = false; \ - m_tickerState = 0; \ - m_commHandlerState = 2; \ - m_commHandlerMode = 0; \ - m_socket->clearIncomingData(); \ - setStatusMessage(i18n("Instrument communication failure. Please verify the status of your network connection.")); \ - m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); \ - m_instrumentMutex->unlock(); \ - return; - -#define SET_WATCHDOG_TIMER if (!m_updateTimeoutTimer->isActive()) m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); -#define PAT_WATCHDOG_TIMER m_updateTimeoutTimer->stop(); m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); - -#define SET_NEXT_STATE(x) if (m_commHandlerMode == 0) { \ - m_commHandlerState = x; \ - } \ - else { \ - m_commHandlerState = 255; \ - } +void CommAnalyzerPart::connectionStatusChangedCallback() { + processLockouts(); +} + +void CommAnalyzerPart::setTickerMessage(TQString message) { + m_connectionActiveAndValid = true; + TQString tickerChar; + switch (m_tickerState) { + case 0: + tickerChar = "-"; + break; + case 1: + tickerChar = "\\"; + break; + case 2: + tickerChar = "|"; + break; + case 3: + tickerChar = "/"; + break; + } + setStatusMessage(message + TQString("... %1").arg(tickerChar)); + m_tickerState++; + if (m_tickerState > 3) { + m_tickerState = 0; + } +} + +#define UPDATEDISPLAY_TIMEOUT m_connectionActiveAndValid = false; \ + m_tickerState = 0; \ + m_commHandlerState = 2; \ + m_commHandlerMode = 0; \ + m_socket->clearIncomingData(); \ + setStatusMessage(i18n("Server ping timeout. Please verify the status of your network connection.")); \ + m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); \ + m_instrumentMutex->unlock(); \ + return; + +#define COMMUNICATIONS_FAILED m_connectionActiveAndValid = false; \ + m_tickerState = 0; \ + m_commHandlerState = 2; \ + m_commHandlerMode = 0; \ + m_socket->clearIncomingData(); \ + setStatusMessage(i18n("Instrument communication failure. Please verify the status of your network connection.")); \ + m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); \ + m_instrumentMutex->unlock(); \ + return; + +#define SET_WATCHDOG_TIMER if (!m_updateTimeoutTimer->isActive()) m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); +#define PAT_WATCHDOG_TIMER m_updateTimeoutTimer->stop(); m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); \ + setTickerMessage(i18n("Connected")); + +#define SET_NEXT_STATE(x) if (m_commHandlerMode == 0) { \ + m_commHandlerState = x; \ + } \ + else { \ + m_commHandlerState = 255; \ + } + +#define EXEC_NEXT_STATE_IMMEDIATELY m_forcedUpdateTimer->start(0, TRUE); void CommAnalyzerPart::mainEventLoop() { TQDataStream ds(m_socket); ds.setPrintableData(true); if (!m_instrumentMutex->tryLock()) { - TQTimer::singleShot(0, this, SLOT(mainEventLoop())); // Handle the concurrently received call immediately after current execution + EXEC_NEXT_STATE_IMMEDIATELY return; } @@ -169,6 +240,7 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->writeEndOfFrame(); m_commHandlerState = 1; + EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == 1) { // Get response data @@ -182,6 +254,7 @@ void CommAnalyzerPart::mainEventLoop() { if (result == "ACK") { SET_NEXT_STATE(2) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -199,6 +272,7 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->writeEndOfFrame(); SET_NEXT_STATE(3) + EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == 3) { // Get response data @@ -211,11 +285,8 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->clearFrameTail(); if (result == "ACK") { - // Set spectrum analyzer mode - ds << TQString("SETMODESPECTRUMANALYZER"); - m_socket->writeEndOfFrame(); - SET_NEXT_STATE(4) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -228,31 +299,12 @@ void CommAnalyzerPart::mainEventLoop() { } } else if (m_commHandlerState == 4) { - // Get response data - if (m_socket->canReadFrame()) { - PAT_WATCHDOG_TIMER - - // Get command status - TQString result; - ds >> result; - m_socket->clearFrameTail(); - - if (result == "ACK") { - // Get number of samples in trace, step 1 - ds << TQString("GETTRACESAMPLECOUNT"); - m_socket->writeEndOfFrame(); - - SET_NEXT_STATE(5) - } - else { - COMMUNICATIONS_FAILED - } - } - else { - if (!m_updateTimeoutTimer->isActive()) { - UPDATEDISPLAY_TIMEOUT - } - } + // Get number of samples in trace, step 1 + ds << TQString("GETTRACESAMPLECOUNT"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(5) + EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == 5) { // Get response data @@ -267,12 +319,9 @@ void CommAnalyzerPart::mainEventLoop() { } m_socket->clearFrameTail(); - if (result == "ACK") { - // Get number of horizontal divisions, step 1 - ds << TQString("GETHORIZONTALDIVCOUNT"); - m_socket->writeEndOfFrame(); - + if (result == "ACK") { SET_NEXT_STATE(6) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -285,6 +334,14 @@ void CommAnalyzerPart::mainEventLoop() { } } else if (m_commHandlerState == 6) { + // Get number of horizontal divisions, step 1 + ds << TQString("GETHORIZONTALDIVCOUNT"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(7) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 7) { // Get response data if (m_socket->canReadFrame()) { PAT_WATCHDOG_TIMER @@ -298,11 +355,8 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->clearFrameTail(); if (result == "ACK") { - // Get number of vertical divisions, step 1 - ds << TQString("GETVERTICALDIVCOUNT"); - m_socket->writeEndOfFrame(); - - SET_NEXT_STATE(7) + SET_NEXT_STATE(8) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -314,7 +368,15 @@ void CommAnalyzerPart::mainEventLoop() { } } } - else if (m_commHandlerState == 7) { + else if (m_commHandlerState == 8) { + // Get number of vertical divisions, step 1 + ds << TQString("GETVERTICALDIVCOUNT"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(9) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 9) { // Get response data if (m_socket->canReadFrame()) { PAT_WATCHDOG_TIMER @@ -328,11 +390,8 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->clearFrameTail(); if (result == "ACK") { - // Get reference power level, step 1 - ds << TQString("GETREFERENCEPOWERLEVEL"); - m_socket->writeEndOfFrame(); - - SET_NEXT_STATE(8) + SET_NEXT_STATE(10) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -344,7 +403,15 @@ void CommAnalyzerPart::mainEventLoop() { } } } - else if (m_commHandlerState == 8) { + else if (m_commHandlerState == 10) { + // Get reference power level, step 1 + ds << TQString("GETREFERENCEPOWERLEVEL"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(11) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 11) { // Get response data if (m_socket->canReadFrame()) { PAT_WATCHDOG_TIMER @@ -358,11 +425,8 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->clearFrameTail(); if (result == "ACK") { - // Get vertical division scale, step 1 - ds << TQString("GETVERTDIVSCALE"); - m_socket->writeEndOfFrame(); - - SET_NEXT_STATE(9) + SET_NEXT_STATE(12) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -374,7 +438,15 @@ void CommAnalyzerPart::mainEventLoop() { } } } - else if (m_commHandlerState == 9) { + else if (m_commHandlerState == 12) { + // Get vertical division scale, step 1 + ds << TQString("GETVERTDIVSCALE"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(13) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 13) { // Get response data if (m_socket->canReadFrame()) { PAT_WATCHDOG_TIMER @@ -388,11 +460,8 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->clearFrameTail(); if (result == "ACK") { - // Get center frequency, step 1 - ds << TQString("GETCENTERFREQUENCY"); - m_socket->writeEndOfFrame(); - - SET_NEXT_STATE(10) + SET_NEXT_STATE(14) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -404,7 +473,15 @@ void CommAnalyzerPart::mainEventLoop() { } } } - else if (m_commHandlerState == 10) { + else if (m_commHandlerState == 14) { + // Get center frequency, step 1 + ds << TQString("GETCENTERFREQUENCY"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(15) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 15) { // Get response data if (m_socket->canReadFrame()) { PAT_WATCHDOG_TIMER @@ -418,11 +495,8 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->clearFrameTail(); if (result == "ACK") { - // Get frequency span, step 1 - ds << TQString("GETFREQUENCYSPAN"); - m_socket->writeEndOfFrame(); - - SET_NEXT_STATE(11) + SET_NEXT_STATE(16) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -434,7 +508,15 @@ void CommAnalyzerPart::mainEventLoop() { } } } - else if (m_commHandlerState == 11) { + else if (m_commHandlerState == 16) { + // Get frequency span, step 1 + ds << TQString("GETFREQUENCYSPAN"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(17) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 17) { // Get response data if (m_socket->canReadFrame()) { PAT_WATCHDOG_TIMER @@ -453,11 +535,8 @@ void CommAnalyzerPart::mainEventLoop() { } if (result == "ACK") { - // Get trace, step 1 - ds << TQString("GETSPECTRUMTRACE"); - m_socket->writeEndOfFrame(); - - SET_NEXT_STATE(12) + SET_NEXT_STATE(18) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -469,7 +548,15 @@ void CommAnalyzerPart::mainEventLoop() { } } } - else if (m_commHandlerState == 12) { + else if (m_commHandlerState == 18) { + // Get trace, step 1 + ds << TQString("GETSPECTRUMTRACE"); + m_socket->writeEndOfFrame(); + + SET_NEXT_STATE(19) + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerState == 19) { // Get response data if (m_socket->canReadFrame()) { PAT_WATCHDOG_TIMER @@ -486,12 +573,16 @@ void CommAnalyzerPart::mainEventLoop() { if (result == "ACK") { // Update display widget(s) m_traceWidget->setSamples(0, trace); + m_base->traceZoomWidget->setSamples(0, trace); postProcessTrace(); m_traceWidget->repaint(); + m_base->traceZoomWidget->repaint(); } if (result == "ACK") { - SET_NEXT_STATE(2) + //SET_NEXT_STATE(2) + SET_NEXT_STATE(18) + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -507,13 +598,15 @@ void CommAnalyzerPart::mainEventLoop() { // Execute pending command m_commHandlerMode = 2; m_socket->clearIncomingData(); + EXEC_NEXT_STATE_IMMEDIATELY } SET_WATCHDOG_TIMER } else if (m_commHandlerMode == 2) { if (m_commHandlerCommandState == 0) { m_commHandlerMode = 0; - m_commHandlerState = 2; + m_commHandlerState = 10; + EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerCommandState == 1) { // Set reference power level @@ -522,6 +615,7 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->writeEndOfFrame(); m_commHandlerCommandState = 2; + EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerCommandState == 2) { // Get response data @@ -534,11 +628,8 @@ void CommAnalyzerPart::mainEventLoop() { m_socket->clearFrameTail(); if (result == "ACK") { - // Get reference power level, step 1 - ds << TQString("GETREFERENCEPOWERLEVEL"); - m_socket->writeEndOfFrame(); - m_commHandlerCommandState = 3; + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -551,6 +642,14 @@ void CommAnalyzerPart::mainEventLoop() { } } else if (m_commHandlerCommandState == 3) { + // Get reference power level, step 1 + ds << TQString("GETREFERENCEPOWERLEVEL"); + m_socket->writeEndOfFrame(); + + m_commHandlerCommandState = 4; + EXEC_NEXT_STATE_IMMEDIATELY + } + else if (m_commHandlerCommandState == 4) { // Get response data if (m_socket->canReadFrame()) { PAT_WATCHDOG_TIMER @@ -568,7 +667,7 @@ void CommAnalyzerPart::mainEventLoop() { if (result == "ACK") { m_commHandlerCommandState = 0; - TQTimer::singleShot(0, this, SLOT(mainEventLoop())); + EXEC_NEXT_STATE_IMMEDIATELY } else { COMMUNICATIONS_FAILED @@ -587,6 +686,8 @@ void CommAnalyzerPart::mainEventLoop() { m_commHandlerCommandState = 0; } + processLockouts(); + m_instrumentMutex->unlock(); } @@ -594,10 +695,27 @@ void CommAnalyzerPart::postProcessTrace() { return; } +void CommAnalyzerPart::updateZoomWidgetLimits(const TQRectF& zoomRect) { + TQRectF fullZoomRect = m_traceWidget->displayLimits(0); + double widthSpan = fullZoomRect.width()-fullZoomRect.x(); + double heightSpan = fullZoomRect.height()-fullZoomRect.y(); + + TQRectF zoomLimitsRect((fullZoomRect.x()+(widthSpan*(zoomRect.x()/100.0))), (fullZoomRect.y()+(heightSpan*(zoomRect.y()/100.0))), (fullZoomRect.x()+(widthSpan*((zoomRect.x()/100.0)+(zoomRect.width()/100.0)))), (fullZoomRect.y()+(heightSpan*((zoomRect.y()/100.0)+(zoomRect.height()/100.0))))); + +printf("[RAJA DEBUG 760.0] Current full limits: x1: %f y1: %f x2: %f y2: %f\n\r", fullZoomRect.x(), fullZoomRect.y(), fullZoomRect.width(), fullZoomRect.height()); fflush(stdout); +printf("[RAJA DEBUG 760.1] Current zoom limits: x1: %f y1: %f x2: %f y2: %f\n\r", zoomLimitsRect.x(), zoomLimitsRect.y(), zoomLimitsRect.width(), zoomLimitsRect.height()); fflush(stdout); + + m_base->traceZoomWidget->setDisplayLimits(0, zoomLimitsRect); +} + void CommAnalyzerPart::updateGraticule() { m_traceWidget->setNumberOfSamples(0, m_samplesInTrace); m_traceWidget->setNumberOfHorizontalDivisions(m_hdivs); m_traceWidget->setNumberOfVerticalDivisions(m_vdivs); +printf("[RAJA DEBUG 750.0] m_hdivs: %d m_vdivs: %d m_vscale: %E\n\r", m_hdivs, m_vdivs, m_vscale); fflush(stdout); + m_base->traceZoomWidget->setNumberOfSamples(0, m_samplesInTrace); + m_base->traceZoomWidget->setNumberOfHorizontalDivisions(m_hdivs); + m_base->traceZoomWidget->setNumberOfVerticalDivisions(m_vdivs); m_leftFrequency = m_centerfreq - (m_spanfreq/2.0); m_rightFrequency = m_centerfreq + (m_spanfreq/2.0); @@ -611,7 +729,9 @@ void CommAnalyzerPart::updateGraticule() { freqpos = freqpos + freqincr; } m_traceWidget->setPositions(0, tracepositions); - m_traceWidget->setDisplayLimits(0, m_leftFrequency, m_rpower, m_rightFrequency, m_rpower-(m_vscale*m_hdivs)); + m_traceWidget->setDisplayLimits(0, TQRectF(m_leftFrequency, m_rpower, m_rightFrequency, m_rpower-(m_vscale*m_vdivs))); + m_base->traceZoomWidget->setPositions(0, tracepositions); + updateZoomWidgetLimits(m_traceWidget->zoomBox()); // Also update controls m_base->saRefLevel->blockSignals(true); @@ -620,10 +740,12 @@ void CommAnalyzerPart::updateGraticule() { } void CommAnalyzerPart::saRefLevelChanged(double newval) { - m_rpower = newval; - m_commHandlerMode = 1; - m_commHandlerCommandState = 1; - mainEventLoop(); + if (m_commHandlerMode < 2) { + m_rpower = newval; + m_commHandlerMode = 1; + m_commHandlerCommandState = 1; + mainEventLoop(); + } } KAboutData* CommAnalyzerPart::createAboutData() { diff --git a/clients/tde/src/part/commanalyzer/part.h b/clients/tde/src/part/commanalyzer/part.h index 252a67c..a45618c 100644 --- a/clients/tde/src/part/commanalyzer/part.h +++ b/clients/tde/src/part/commanalyzer/part.h @@ -17,6 +17,7 @@ class TraceWidget; class TQSocket; class TQTimer; class TQMutex; +class TQRectF; class CommAnalyzerBase; namespace RemoteLab @@ -35,6 +36,7 @@ namespace RemoteLab public slots: virtual bool openURL(const KURL &url); + void updateZoomWidgetLimits(const TQRectF& zoomRect); private slots: void postInit(); @@ -42,7 +44,8 @@ namespace RemoteLab void updateGraticule(); void connectionFinishedCallback(); void disconnectFromServerCallback(); -// void connectionStatusChangedCallback(); + void connectionStatusChangedCallback(); + void setTickerMessage(TQString message); void mainEventLoop(); virtual void postProcessTrace(); void saRefLevelChanged(double); @@ -52,6 +55,7 @@ namespace RemoteLab int m_commHandlerState; int m_commHandlerMode; int m_commHandlerCommandState; + TQTimer* m_forcedUpdateTimer; TQTimer* m_updateTimeoutTimer; bool m_connectionActiveAndValid; unsigned char m_tickerState; diff --git a/clients/tde/src/widgets/tracewidget.cpp b/clients/tde/src/widgets/tracewidget.cpp index 1fe3ff4..bf0cf92 100644 --- a/clients/tde/src/widgets/tracewidget.cpp +++ b/clients/tde/src/widgets/tracewidget.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -15,8 +16,82 @@ #include #define VERIFY_TRACE_ARRAY_SIZE if (traceNumber >= m_traceArray.count()) resizeTraceArray(traceNumber+1); +#define VERIFY_CURSOR_ARRAY_SIZE if (cursorNumber >= m_cursorArray.count()) resizeCursorArray(cursorNumber+1); -TraceData::TraceData(TQWidget* labelParent) { +#define CURSOR_DARKNESS_FACTOR 200 +#define ZOOM_SHADING_DARKNESS_FACTOR 200 + +TQRectF::TQRectF() { + m_valid = false; +} + +TQRectF::TQRectF(double x, double y, double w, double h) { + m_x = x; + m_y = y; + m_w = w; + m_h = h; + m_valid = true; +} + +double TQRectF::x() const { + return m_x; +} + +double TQRectF::y() const { + return m_y; +} + +double TQRectF::width() const { + return m_w; +} + +double TQRectF::height() const { + return m_h; +} + +void TQRectF::setX(double val) { + m_x = val; + m_valid = true; +} + +void TQRectF::setY(double val) { + m_y = val; + m_valid = true; +} + +void TQRectF::setWidth(double val) { + m_w = val; + m_valid = true; +} + +void TQRectF::setHeight(double val) { + m_h = val; + m_valid = true; +} + +bool TQRectF::isNull() const { + return !m_valid; +} + +bool TQRectF::operator!() const { + return isNull(); +} + +bool TQRectF::operator==(const TQRectF &r1) { + bool match = true; + if (r1.m_valid != m_valid) match = false; + if (r1.m_x != m_x) match = false; + if (r1.m_y != m_y) match = false; + if (r1.m_w != m_w) match = false; + if (r1.m_h != m_h) match = false; + return match; +} + +bool TQRectF::operator!=(const TQRectF &r1) { + return !operator==(r1); +} + +TraceData::TraceData(TQWidget* labelParent) : TQObject() { color = TQColor(0, 255, 0); numberOfSamples = 0; leftEdge = 0; @@ -29,14 +104,20 @@ TraceData::TraceData(TQWidget* labelParent) { enabled = false; if (labelParent) { - infoLabel = new TQLabel(labelParent); - infoLabel->setPaletteBackgroundColor(labelParent->paletteBackgroundColor()); - infoLabel->setPaletteForegroundColor(color); - infoLabel->setAlignment(TQt::AlignHCenter|TQt::AlignVCenter|TQt::SingleLine); - infoLabel->hide(); + paramLabel = new TQLabel(labelParent); + paramLabel->setPaletteBackgroundColor(labelParent->paletteBackgroundColor()); + paramLabel->setPaletteForegroundColor(color); + paramLabel->setAlignment(TQt::AlignHCenter|TQt::AlignVCenter|TQt::SingleLine); + paramLabel->hide(); + graphStatusLabel = new TQLabel(labelParent); + graphStatusLabel->setPaletteBackgroundColor(labelParent->paletteBackgroundColor()); + graphStatusLabel->setPaletteForegroundColor(color); + graphStatusLabel->setAlignment(TQt::AlignHCenter|TQt::AlignVCenter|TQt::SingleLine); + graphStatusLabel->hide(); } else { - infoLabel = NULL; + paramLabel = NULL; + graphStatusLabel = NULL; } } @@ -44,9 +125,6 @@ TraceData::~TraceData() { // } -// RAJA FIXME -// Add cursor support - // RAJA FIXME // Add offset (x and y) support @@ -56,7 +134,7 @@ TraceData::~TraceData() { void TraceData::drawTrace(TQPainter* p, int graticule_width, int graticule_height) { p->setPen(color); - if ((bottomEdge != topEdge) && (enabled)) { + if ((bottomEdge != topEdge) && (enabled) && (positionArray.count() >= numberOfSamples) && (sampleArray.count() >= numberOfSamples) && (numberOfSamples > 0)) { // Draw the points unsigned int n; int x,y,x2,y2; @@ -70,6 +148,146 @@ void TraceData::drawTrace(TQPainter* p, int graticule_width, int graticule_heigh } } +CursorData::CursorData(TraceWidget* parent, TQWidget* labelParent) : TQObject(), parentWidget(parent) { + color = TQColor(0, 255, 0); + enabled = false; + orientation = TQt::Vertical; + position = 50; + cursorName = i18n("Cursor "); + + if (labelParent) { + paramLabel = new TQLabel(labelParent); + paramLabel->setPaletteBackgroundColor(labelParent->paletteBackgroundColor()); + paramLabel->setPaletteForegroundColor(color); + paramLabel->setAlignment(TQt::AlignHCenter|TQt::AlignVCenter|TQt::SingleLine); + paramLabel->hide(); + singleIncrBtn = new TQPushButton(labelParent); + singleDecrBtn = new TQPushButton(labelParent); + multiIncrBtn = new TQPushButton(labelParent); + multiDecrBtn = new TQPushButton(labelParent); + singleIncrBtn->setText("+"); + singleDecrBtn->setText("-"); + multiIncrBtn->setText("++"); + multiDecrBtn->setText("--"); + singleIncrBtn->setAutoRepeat(true); + singleDecrBtn->setAutoRepeat(true); + multiIncrBtn->setAutoRepeat(true); + multiDecrBtn->setAutoRepeat(true); + singleIncrBtn->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed)); + singleDecrBtn->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed)); + multiIncrBtn->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed)); + multiDecrBtn->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed)); + singleIncrBtn->setPaletteBackgroundColor(labelParent->paletteBackgroundColor()); + singleIncrBtn->setPaletteForegroundColor(color); + singleDecrBtn->setPaletteBackgroundColor(labelParent->paletteBackgroundColor()); + singleDecrBtn->setPaletteForegroundColor(color); + multiIncrBtn->setPaletteBackgroundColor(labelParent->paletteBackgroundColor()); + multiIncrBtn->setPaletteForegroundColor(color); + multiDecrBtn->setPaletteBackgroundColor(labelParent->paletteBackgroundColor()); + multiDecrBtn->setPaletteForegroundColor(color); + singleIncrBtn->hide(); + singleDecrBtn->hide(); + multiIncrBtn->hide(); + multiDecrBtn->hide(); + connect(singleIncrBtn, SIGNAL(clicked()), this, SLOT(movePosOneTick())); + connect(singleDecrBtn, SIGNAL(clicked()), this, SLOT(moveNegOneTick())); + connect(multiIncrBtn, SIGNAL(clicked()), this, SLOT(movePosMultiTicks())); + connect(multiDecrBtn, SIGNAL(clicked()), this, SLOT(moveNegMultiTicks())); + } + else { + paramLabel = NULL; + singleIncrBtn = NULL; + singleDecrBtn = NULL; + multiIncrBtn = NULL; + multiDecrBtn = NULL; + } +} + +CursorData::~CursorData() { + // +} + +void CursorData::drawCursor(TQPainter* p, int graticule_width, int graticule_height) { + p->setPen(color.dark(parentWidget->m_cursorDarkness)); + + if (orientation == TQt::Vertical) { + int x = abs(((position)/(100.0))*(graticule_width)); + p->drawLine(x, 0, x, graticule_height); + } + else { + int y = abs(((position)/(100.0))*(graticule_height)); + p->drawLine(0, y, graticule_width, y); + } +} + +void CursorData::movePosOneTick() { + double increment; + if (orientation == TQt::Horizontal) { + increment = 100.0/parentWidget->m_graticuleWidget->height(); + } + else { + increment = 100.0/parentWidget->m_graticuleWidget->width(); + } + position += increment; + if (position < 0.0) position = 0.0; + if (position > 100.0) position = 100.0; + + parentWidget->updateCursorText(); + parentWidget->m_graticuleWidget->updateGraticule(); + parentWidget->m_graticuleWidget->repaint(true); +} + +void CursorData::moveNegOneTick() { + double increment; + if (orientation == TQt::Horizontal) { + increment = 100.0/parentWidget->m_graticuleWidget->height(); + } + else { + increment = 100.0/parentWidget->m_graticuleWidget->width(); + } + position -= increment; + if (position < 0.0) position = 0.0; + if (position > 100.0) position = 100.0; + + parentWidget->updateCursorText(); + parentWidget->m_graticuleWidget->updateGraticule(); + parentWidget->m_graticuleWidget->repaint(true); +} + +void CursorData::movePosMultiTicks() { + double increment; + if (orientation == TQt::Horizontal) { + increment = 100.0/parentWidget->m_graticuleWidget->height(); + } + else { + increment = 100.0/parentWidget->m_graticuleWidget->width(); + } + position += (increment*10.0); + if (position < 0.0) position = 0.0; + if (position > 100.0) position = 100.0; + + parentWidget->updateCursorText(); + parentWidget->m_graticuleWidget->updateGraticule(); + parentWidget->m_graticuleWidget->repaint(true); +} + +void CursorData::moveNegMultiTicks() { + double increment; + if (orientation == TQt::Horizontal) { + increment = 100.0/parentWidget->m_graticuleWidget->height(); + } + else { + increment = 100.0/parentWidget->m_graticuleWidget->width(); + } + position -= (increment*10.0); + if (position < 0.0) position = 0.0; + if (position > 100.0) position = 100.0; + + parentWidget->updateCursorText(); + parentWidget->m_graticuleWidget->updateGraticule(); + parentWidget->m_graticuleWidget->repaint(true); +} + GraticuleWidget::GraticuleWidget(TraceWidget* parent, const char* name) : TQWidget(parent, name), m_base(parent), m_graticulePixmap(0) { @@ -78,6 +296,7 @@ GraticuleWidget::GraticuleWidget(TraceWidget* parent, const char* name) : TQWidg setPaletteBackgroundColor(TQt::black); setPaletteForegroundColor(TQColor(0,128,0)); + setMouseTracking(true); } GraticuleWidget::~GraticuleWidget() { @@ -97,18 +316,18 @@ void GraticuleWidget::updateGraticule() { p.setPen(TQPen(foregroundColor(), 1, TQt::SolidLine)); p.fillRect(0, 0, m_graticulePixmap->width(), m_graticulePixmap->height(), backgroundColor()); p.setPen(TQPen(foregroundColor(), 1, TQt::DotLine)); - if (m_base->m_vertDivs > 0) { - s = m_graticulePixmap->width() / m_base->m_vertDivs; + if (m_base->m_horizDivs > 0) { + s = m_graticulePixmap->width() / m_base->m_horizDivs; x = 0; - for (d=0; dm_vertDivs; d++) { + for (d=0; dm_horizDivs; d++) { p.drawLine(x, 0, x, m_graticulePixmap->height()); x += s; } } - if (m_base->m_horizDivs > 0) { - s = m_graticulePixmap->height() / m_base->m_horizDivs; + if (m_base->m_vertDivs > 0) { + s = m_graticulePixmap->height() / m_base->m_vertDivs; y = 0; - for (d=0; dm_horizDivs; d++) { + for (d=0; dm_vertDivs; d++) { p.drawLine(0, y, m_graticulePixmap->width(), y); y += s; } @@ -116,6 +335,14 @@ void GraticuleWidget::updateGraticule() { p.setPen(TQPen(foregroundColor(), 1, TQt::SolidLine)); p.drawRect(0, 0, m_graticulePixmap->width(), m_graticulePixmap->height()); + // If there are 4 or more cursors, lightly shade the area returned by ZoomBox + TQRectF zoomBox = m_base->zoomBox(); + if (!zoomBox.isNull()) { + // Translate zoombox coordinates to local drawing coordinates + TQRect drawingRect(abs(((zoomBox.x())/(100.0))*(width())), abs(((zoomBox.y())/(100.0))*(height())), abs(((zoomBox.width())/(100.0))*(width())), abs(((zoomBox.height())/(100.0))*(height()))); + p.fillRect(drawingRect, TQBrush(foregroundColor().dark(m_base->m_zoomBoxDarkness), TQt::BDiagPattern)); + } + // Repaint the widget repaint(); } @@ -131,6 +358,11 @@ void GraticuleWidget::paintEvent(TQPaintEvent*) { for (uint trace=0;tracem_traceArray.count();trace++) { m_base->m_traceArray[trace]->drawTrace(&p, m_graticulePixmap->width(), m_graticulePixmap->height()); } + + // Draw the cursors + for (uint cursor=0;cursorm_cursorArray.count();cursor++) { + m_base->m_cursorArray[cursor]->drawCursor(&p, m_graticulePixmap->width(), m_graticulePixmap->height()); + } } else { p.fillRect(x(), y(), width(), height(), backgroundColor()); @@ -141,16 +373,72 @@ void GraticuleWidget::resizeEvent(TQResizeEvent *) { updateGraticule(); } +void GraticuleWidget::mousePressEvent(TQMouseEvent *) { + // +} + +void GraticuleWidget::mouseReleaseEvent(TQMouseEvent *) { + // +} + +void GraticuleWidget::mouseDoubleClickEvent(TQMouseEvent *) { + // +} + +void GraticuleWidget::mouseMoveEvent(TQMouseEvent *e) { + // Print current cursor location for all traces + if ((e->x() < width()) && (e->y() < height())) { + for (uint trace=0;tracem_traceArray.count();trace++) { + // Calculate location + double scaledYPos = (e->y()*100.0)/height(); + double scaledXPos = (e->x()*100.0)/width(); + double horizontal_range = (m_base->m_traceArray[trace]->rightEdge-m_base->m_traceArray[trace]->leftEdge); + double vertical_range = (m_base->m_traceArray[trace]->bottomEdge-m_base->m_traceArray[trace]->topEdge); + double realCursorYPosition = (m_base->m_traceArray[trace]->topEdge+((scaledYPos/100.0)*vertical_range)); + double realCursorXPosition = (m_base->m_traceArray[trace]->leftEdge+((scaledXPos/100.0)*horizontal_range)); + m_base->m_traceArray[trace]->graphStatusLabel->setText(TQString("%1
@%2,%3
").arg(m_base->m_traceArray[trace]->traceName).arg(TraceWidget::prettyFormat(realCursorXPosition, horizontal_range, m_base->m_traceArray[trace]->horizontalUnits)).arg(TraceWidget::prettyFormat(realCursorYPosition, vertical_range, m_base->m_traceArray[trace]->verticalUnits))); + } + } + else { + for (uint trace=0;tracem_traceArray.count();trace++) { + m_base->m_traceArray[trace]->graphStatusLabel->setText(""); + } + } +} + +void GraticuleWidget::enterEvent(TQEvent *) { + // +} + +void GraticuleWidget::leaveEvent(TQEvent *) { + for (uint trace=0;tracem_traceArray.count();trace++) { + m_base->m_traceArray[trace]->graphStatusLabel->setText(""); + } +} + TraceWidget::TraceWidget(TQWidget* parent, const char* name) : TQWidget(parent, name), m_horizDivs(0), - m_vertDivs(0) { + m_vertDivs(0), + m_cursorDarkness(CURSOR_DARKNESS_FACTOR), + m_zoomBoxDarkness(ZOOM_SHADING_DARKNESS_FACTOR), + m_zoomBoxEnabled(false) { setBackgroundMode(NoBackground); - m_primaryLayout = new TQVBoxLayout(this); + m_primaryLayout = new TQGridLayout(this); m_graticuleWidget = new GraticuleWidget(this); - m_primaryLayout->addWidget(m_graticuleWidget); - m_traceLabelLayout = new TQGridLayout(m_primaryLayout); + m_primaryLayout->addWidget(m_graticuleWidget, 0, 0); + m_rightPaneLayout = new TQGridLayout; + m_traceLabelLayout = new TQGridLayout; + m_infoLabelLayout = new TQGridLayout; + m_cursorLabelLayout = new TQGridLayout; + m_statusLabelLayout = new TQGridLayout; + m_primaryLayout->addLayout(m_traceLabelLayout, 1, 0); + m_primaryLayout->addLayout(m_rightPaneLayout, 0, 1); + m_primaryLayout->addLayout(m_statusLabelLayout, 1, 1); + m_rightPaneLayout->addLayout(m_cursorLabelLayout, 0, 0); + m_rightPaneLayout->addLayout(m_infoLabelLayout, 1, 0); m_traceLabelLayout->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum), 0, 255); + m_rightPaneLayout->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding), 255, 0); setPaletteBackgroundColor(TQt::black); setPaletteForegroundColor(TQColor(0,128,0)); @@ -177,23 +465,33 @@ void TraceWidget::setNumberOfHorizontalDivisions(unsigned int divisions) { m_horizDivs = divisions; m_graticuleWidget->updateGraticule(); updateTraceText(); + updateCursorText(); } void TraceWidget::setNumberOfVerticalDivisions(unsigned int divisions) { m_vertDivs = divisions; m_graticuleWidget->updateGraticule(); updateTraceText(); + updateCursorText(); } -void TraceWidget::setDisplayLimits(uint traceNumber, double x, double y, double w, double h) { +void TraceWidget::setDisplayLimits(uint traceNumber, TQRectF limits) { VERIFY_TRACE_ARRAY_SIZE - m_traceArray[traceNumber]->leftEdge = x; - m_traceArray[traceNumber]->rightEdge = w; - m_traceArray[traceNumber]->topEdge = y; - m_traceArray[traceNumber]->bottomEdge = h; + m_traceArray[traceNumber]->leftEdge = limits.x(); + m_traceArray[traceNumber]->rightEdge = limits.width(); + m_traceArray[traceNumber]->topEdge = limits.y(); + m_traceArray[traceNumber]->bottomEdge = limits.height(); + m_graticuleWidget->repaint(true); updateTraceText(); + updateCursorText(); +} + +TQRectF TraceWidget::displayLimits(uint traceNumber) { + VERIFY_TRACE_ARRAY_SIZE + + return TQRectF(m_traceArray[traceNumber]->leftEdge, m_traceArray[traceNumber]->topEdge, m_traceArray[traceNumber]->rightEdge, m_traceArray[traceNumber]->bottomEdge); } void TraceWidget::updateTraceText() { @@ -209,10 +507,39 @@ void TraceWidget::updateTraceText() { double vertical_units_per_division; horizontal_units_per_division = fabs(m_traceArray[trace]->rightEdge-m_traceArray[trace]->leftEdge)/m_horizDivs; - vertical_units_per_division = fabs(m_traceArray[trace]->topEdge-m_traceArray[trace]->bottomEdge)/m_vertDivs; - m_traceArray[trace]->infoLabel->setPaletteBackgroundColor(paletteBackgroundColor()); - m_traceArray[trace]->infoLabel->setPaletteForegroundColor(m_traceArray[trace]->color); - m_traceArray[trace]->infoLabel->setText(TQString("%1
%2 %3/div
%4 %5/div
").arg(m_traceArray[trace]->traceName).arg(horizontal_units_per_division).arg(m_traceArray[trace]->horizontalUnits).arg(vertical_units_per_division).arg(m_traceArray[trace]->verticalUnits)); + vertical_units_per_division = fabs(m_traceArray[trace]->bottomEdge-m_traceArray[trace]->topEdge)/m_vertDivs; + m_traceArray[trace]->paramLabel->setPaletteBackgroundColor(paletteBackgroundColor()); + m_traceArray[trace]->paramLabel->setPaletteForegroundColor(m_traceArray[trace]->color); + m_traceArray[trace]->graphStatusLabel->setPaletteBackgroundColor(paletteBackgroundColor()); + m_traceArray[trace]->graphStatusLabel->setPaletteForegroundColor(m_traceArray[trace]->color); + m_traceArray[trace]->paramLabel->setText(TQString("
%1
%2/div
%3/div").arg(m_traceArray[trace]->traceName).arg(prettyFormat(horizontal_units_per_division, horizontal_units_per_division, m_traceArray[trace]->horizontalUnits)).arg(prettyFormat(vertical_units_per_division, vertical_units_per_division, m_traceArray[trace]->verticalUnits))); + } +} + +void TraceWidget::updateCursorText() { + for (uint cursor=0;cursorparamLabel->setPaletteBackgroundColor(paletteBackgroundColor()); + m_cursorArray[cursor]->paramLabel->setPaletteForegroundColor(m_cursorArray[cursor]->color); + TQString cursorText; + cursorText = TQString("
%1").arg(m_cursorArray[cursor]->cursorName); + // If this is a horizontal cursor, list all vertical positions for all channels + // If this is a vertical cursor, list the horizontal positions for all channels + for (uint trace=0;tracerightEdge-m_traceArray[trace]->leftEdge); + double vertical_range = (m_traceArray[trace]->bottomEdge-m_traceArray[trace]->topEdge); + + if (m_cursorArray[cursor]->orientation == TQt::Horizontal) { + double realCursorPosition = (m_traceArray[trace]->topEdge+((m_cursorArray[cursor]->position/100.0)*vertical_range)); + cursorText.append(TQString("
%1: %2").arg(m_traceArray[trace]->traceName).arg(prettyFormat(realCursorPosition, vertical_range, m_traceArray[trace]->verticalUnits))); + } + else { + double realCursorPosition = (m_traceArray[trace]->leftEdge+((m_cursorArray[cursor]->position/100.0)*horizontal_range)); + cursorText.append(TQString("
%1: %2").arg(m_traceArray[trace]->traceName).arg(prettyFormat(realCursorPosition, horizontal_range, m_traceArray[trace]->horizontalUnits))); + } + } + + cursorText.append(""); + m_cursorArray[cursor]->paramLabel->setText(cursorText); } } @@ -227,6 +554,8 @@ void TraceWidget::setSamples(uint traceNumber, TQDoubleArray& tqda) { m_traceArray[traceNumber]->sampleArray = tqda; m_traceArray[traceNumber]->numberOfSamples = tqda.size(); + + m_graticuleWidget->repaint(true); } TQDoubleArray& TraceWidget::positions(uint traceNumber) { @@ -240,6 +569,8 @@ void TraceWidget::setPositions(uint traceNumber, TQDoubleArray& tqda) { m_traceArray[traceNumber]->positionArray = tqda; m_traceArray[traceNumber]->numberOfSamples = tqda.size(); + + m_graticuleWidget->repaint(true); } TQColor& TraceWidget::traceColor(uint traceNumber) { @@ -254,6 +585,7 @@ void TraceWidget::setTraceColor(uint traceNumber, TQColor& color) { m_traceArray[traceNumber]->color = color; m_graticuleWidget->updateGraticule(); + m_graticuleWidget->repaint(true); updateTraceText(); } @@ -263,18 +595,22 @@ bool TraceWidget::traceEnabled(uint traceNumber) { return m_traceArray[traceNumber]->enabled; } -void TraceWidget::setTraceEnabled(uint traceNumber, bool enabled) { +void TraceWidget::setTraceEnabled(uint traceNumber, bool enabled, bool showText) { VERIFY_TRACE_ARRAY_SIZE m_traceArray[traceNumber]->enabled = enabled; - if (enabled) { - m_traceArray[traceNumber]->infoLabel->show(); + if ((enabled) && (showText)) { + m_traceArray[traceNumber]->paramLabel->show(); + m_traceArray[traceNumber]->graphStatusLabel->show(); + } else { - m_traceArray[traceNumber]->infoLabel->hide(); + m_traceArray[traceNumber]->paramLabel->hide(); + m_traceArray[traceNumber]->graphStatusLabel->hide(); } m_graticuleWidget->updateGraticule(); + m_graticuleWidget->repaint(true); updateTraceText(); } @@ -317,6 +653,210 @@ void TraceWidget::setTraceVerticalUnits(uint traceNumber, TQString units) { updateTraceText(); } +double TraceWidget::cursorPosition(uint cursorNumber) { + VERIFY_CURSOR_ARRAY_SIZE + + return m_cursorArray[cursorNumber]->position; +} + +void TraceWidget::setCursorPosition(uint cursorNumber, double position) { + VERIFY_CURSOR_ARRAY_SIZE + + if (position < 0.0) position = 0.0; + if (position > 100.0) position = 100.0; + + m_cursorArray[cursorNumber]->position = position; + updateCursorText(); +} + +bool TraceWidget::cursorEnabled(uint cursorNumber) { + VERIFY_CURSOR_ARRAY_SIZE + + return m_cursorArray[cursorNumber]->enabled; +} + +void TraceWidget::setCursorEnabled(uint cursorNumber, bool enabled) { + VERIFY_CURSOR_ARRAY_SIZE + + m_cursorArray[cursorNumber]->enabled = enabled; + if (enabled) { + m_cursorArray[cursorNumber]->paramLabel->show(); + m_cursorArray[cursorNumber]->singleIncrBtn->show(); + m_cursorArray[cursorNumber]->singleDecrBtn->show(); + m_cursorArray[cursorNumber]->multiIncrBtn->show(); + m_cursorArray[cursorNumber]->multiDecrBtn->show(); + } + else { + m_cursorArray[cursorNumber]->paramLabel->hide(); + m_cursorArray[cursorNumber]->singleIncrBtn->hide(); + m_cursorArray[cursorNumber]->singleDecrBtn->hide(); + m_cursorArray[cursorNumber]->multiIncrBtn->hide(); + m_cursorArray[cursorNumber]->multiDecrBtn->hide(); + } + + m_graticuleWidget->updateGraticule(); + updateCursorText(); +} + +TQString TraceWidget::cursorName(uint cursorNumber) { + VERIFY_CURSOR_ARRAY_SIZE + + return m_cursorArray[cursorNumber]->cursorName; +} + +void TraceWidget::setCursorName(uint cursorNumber, TQString name) { + VERIFY_CURSOR_ARRAY_SIZE + + m_cursorArray[cursorNumber]->cursorName = name; + updateCursorText(); +} + +TQt::Orientation TraceWidget::cursorOrientation(uint cursorNumber) { + VERIFY_CURSOR_ARRAY_SIZE + + return m_cursorArray[cursorNumber]->orientation; +} + +void TraceWidget::setCursorOrientation(uint cursorNumber, TQt::Orientation orient) { + VERIFY_CURSOR_ARRAY_SIZE + + m_cursorArray[cursorNumber]->orientation = orient; + updateCursorText(); +} + +void TraceWidget::setNumberOfTraces(uint traceNumber) { + resizeTraceArray(traceNumber); +} + +void TraceWidget::setNumberOfCursors(uint cursorNumber) { + resizeCursorArray(cursorNumber); +} + +TQRectF TraceWidget::zoomBox() { + uint i; + + if ((m_cursorArray.count() < 4) || (!m_zoomBoxEnabled)) { + if (!m_zoomBoxPrev.isNull()) { + m_zoomBoxPrev = TQRectF(); + emit(zoomBoxChanged(m_zoomBoxPrev)); + } + return m_zoomBoxPrev; + } + else { + // Find the first two horizontal and first two vertical cursors + // If two of each cannot be found, return TQRectF() + double horiz[2]; + double vert[2]; + int j = 0; + int k = 0; + for (i=0;iorientation == TQt::Horizontal) { + if (j<2) { + vert[j] = m_cursorArray[i]->position; + j++; + } + } + else { + if (k<2) { + horiz[k] = m_cursorArray[i]->position; + k++; + } + } + if ((j>1) && (k>1)) { + break; + } + } + if ((j>1) && (k>1)) { + // Calculate zoom box + double leftBound = (horiz[0] < horiz[1])?horiz[0]:horiz[1]; + double topBound = (vert[0] < vert[1])?vert[0]:vert[1]; + TQRectF newRect(leftBound, topBound, fabs(horiz[0]-horiz[1]), fabs(vert[0]-vert[1])); + if (m_zoomBoxPrev != newRect) { + m_zoomBoxPrev = newRect; + emit(zoomBoxChanged(m_zoomBoxPrev)); + } + return m_zoomBoxPrev; + } + else { + if (!m_zoomBoxPrev.isNull()) { + m_zoomBoxPrev = TQRectF(); + emit(zoomBoxChanged(m_zoomBoxPrev)); + } + return m_zoomBoxPrev; + } + } +} + +void TraceWidget::setZoomBoxEnabled(bool enabled) { + m_zoomBoxEnabled = enabled; + m_graticuleWidget->updateGraticule(); +} + +TQString TraceWidget::prettyFormat(double value, double rangeDetectValue, TQString baseUnits, unsigned int precision) { + TQString result; + TQString unitMultiplier; + double valueMultiplier; + + if (fabs(rangeDetectValue) < 1e-9) { + unitMultiplier = "p"; + valueMultiplier = 1e+12; + } + else if (fabs(rangeDetectValue) < 1e-6) { + unitMultiplier = "n"; + valueMultiplier = 1e+9; + } + else if (fabs(rangeDetectValue) < 1e-3) { + unitMultiplier = "u"; + valueMultiplier = 1e+6; + } + else if (fabs(rangeDetectValue) < 1e-0) { + unitMultiplier = "m"; + valueMultiplier = 1e+3; + } + else if (fabs(rangeDetectValue) < 1e+3) { + unitMultiplier = ""; + valueMultiplier = 1e+0; + } + else if (fabs(rangeDetectValue) < 1e+6) { + unitMultiplier = "k"; + valueMultiplier = 1e-3; + } + else if (fabs(rangeDetectValue) < 1e+9) { + unitMultiplier = "M"; + valueMultiplier = 1e-6; + } + else if (fabs(rangeDetectValue) < 1e+12) { + unitMultiplier = "G"; + valueMultiplier = 1e-9; + } + else if (fabs(rangeDetectValue) < 1e+15) { + unitMultiplier = "T"; + valueMultiplier = 1e-12; + } + else { + unitMultiplier = ""; + valueMultiplier = 1.0; + } + + double scaledValue = value * valueMultiplier; + TQString valueString = TQString("%1").arg(scaledValue, 0, 'g', precision); + if (valueString.contains("-") && valueString.contains(".")) { + valueString.truncate(precision+2); + } + else if (valueString.contains("-")) { + valueString.truncate(precision+1); + } + else if (valueString.contains(".")) { + valueString.truncate(precision+1); + } + else { + valueString.truncate(precision); + } + result = TQString("%1%2%3").arg(valueString).arg(unitMultiplier).arg(baseUnits); + + return result; +} + void TraceWidget::resizeTraceArray(uint newsize) { uint oldcount = m_traceArray.count(); @@ -324,14 +864,51 @@ void TraceWidget::resizeTraceArray(uint newsize) { m_traceArray.resize(newsize); for (uint i=oldcount;iaddWidget(m_traceArray[i]->infoLabel, 0, i); + if (m_traceArray[i]->paramLabel) { + m_traceLabelLayout->addWidget(m_traceArray[i]->paramLabel, 0, i); + m_statusLabelLayout->addWidget(m_traceArray[i]->graphStatusLabel, i, 0); + } } } else { m_traceArray.resize(newsize); for (uint i=newsize;iremove(m_traceArray[i]->infoLabel); + if (m_traceArray[i]->paramLabel) { + m_traceLabelLayout->remove(m_traceArray[i]->paramLabel); + m_traceLabelLayout->remove(m_traceArray[i]->graphStatusLabel); + } delete m_traceArray[i]; } } +} + +void TraceWidget::resizeCursorArray(uint newsize) { + uint oldcount = m_cursorArray.count(); + + if (newsize > oldcount) { + m_cursorArray.resize(newsize); + for (uint i=oldcount;iparamLabel) { + m_cursorLabelLayout->addMultiCellWidget(m_cursorArray[i]->paramLabel, i*2, i*2, 0, 3); + m_cursorLabelLayout->addMultiCellWidget(m_cursorArray[i]->multiIncrBtn, (i*2)+1, (i*2)+1, 0, 0); + m_cursorLabelLayout->addMultiCellWidget(m_cursorArray[i]->singleIncrBtn, (i*2)+1, (i*2)+1, 1, 1); + m_cursorLabelLayout->addMultiCellWidget(m_cursorArray[i]->singleDecrBtn, (i*2)+1, (i*2)+1, 2, 2); + m_cursorLabelLayout->addMultiCellWidget(m_cursorArray[i]->multiDecrBtn, (i*2)+1, (i*2)+1, 3, 3); + } + } + } + else { + m_cursorArray.resize(newsize); + for (uint i=newsize;iparamLabel) { + m_cursorLabelLayout->remove(m_cursorArray[i]->paramLabel); + m_cursorLabelLayout->remove(m_cursorArray[i]->multiIncrBtn); + m_cursorLabelLayout->remove(m_cursorArray[i]->singleIncrBtn); + m_cursorLabelLayout->remove(m_cursorArray[i]->singleDecrBtn); + m_cursorLabelLayout->remove(m_cursorArray[i]->multiDecrBtn); + } + delete m_cursorArray[i]; + } + } } \ No newline at end of file diff --git a/clients/tde/src/widgets/tracewidget.h b/clients/tde/src/widgets/tracewidget.h index b16717c..9101895 100644 --- a/clients/tde/src/widgets/tracewidget.h +++ b/clients/tde/src/widgets/tracewidget.h @@ -9,16 +9,48 @@ class TQPixmap; class TQLabel; class TQVBoxLayout; class TQGridLayout; +class TQPushButton; class TraceWidget; -class TraceData +class TQRectF { + public: + TQRectF(); + TQRectF(double x, double y, double w, double h); + + double x() const; + double y() const; + double width() const; + double height() const; + bool isNull() const; + + bool operator!() const; + bool operator==(const TQRectF &r1); + bool operator!=(const TQRectF &r1); + + void setX(double); + void setY(double); + void setWidth(double); + void setHeight(double); + + private: + bool m_valid; + double m_x; + double m_y; + double m_w; + double m_h; +}; + +class TraceData : public TQObject +{ + Q_OBJECT + public: TraceData(TQWidget* labelParent=0); ~TraceData(); void drawTrace(TQPainter* p, int graticule_width, int graticule_height); - public: + private: TQDoubleArray sampleArray; TQDoubleArray positionArray; unsigned int numberOfSamples; @@ -31,11 +63,48 @@ class TraceData TQString traceName; TQString horizontalUnits; TQString verticalUnits; - TQLabel* infoLabel; + TQLabel* paramLabel; + TQLabel* graphStatusLabel; + + friend class TraceWidget; + friend class GraticuleWidget; }; typedef TQMemArray TraceList; +class CursorData : public TQObject +{ + Q_OBJECT + + public: + CursorData(TraceWidget* parent, TQWidget* labelParent=0); + ~CursorData(); + void drawCursor(TQPainter* p, int graticule_width, int graticule_height); + + public slots: + void movePosOneTick(); + void moveNegOneTick(); + void movePosMultiTicks(); + void moveNegMultiTicks(); + + private: + TQColor color; + bool enabled; + TQt::Orientation orientation; + double position; + TQString cursorName; + TQLabel* paramLabel; + TQPushButton* singleIncrBtn; + TQPushButton* singleDecrBtn; + TQPushButton* multiIncrBtn; + TQPushButton* multiDecrBtn; + TraceWidget* parentWidget; + + friend class TraceWidget; +}; + +typedef TQMemArray CursorList; + class GraticuleWidget : public TQWidget { Q_OBJECT @@ -47,6 +116,12 @@ class GraticuleWidget : public TQWidget protected: virtual void paintEvent(TQPaintEvent*); virtual void resizeEvent(TQResizeEvent *); + virtual void mousePressEvent(TQMouseEvent *); + virtual void mouseReleaseEvent(TQMouseEvent *); + virtual void mouseDoubleClickEvent(TQMouseEvent *); + virtual void mouseMoveEvent(TQMouseEvent *); + virtual void enterEvent(TQEvent *); + virtual void leaveEvent(TQEvent *); private slots: void updateGraticule(); @@ -56,6 +131,7 @@ class GraticuleWidget : public TQWidget TQPixmap* m_graticulePixmap; friend class TraceWidget; + friend class CursorData; }; class TraceWidget : public TQWidget @@ -69,7 +145,10 @@ class TraceWidget : public TQWidget void setNumberOfSamples(uint traceNumber, unsigned int samples); void setNumberOfHorizontalDivisions(unsigned int divisions); void setNumberOfVerticalDivisions(unsigned int divisions); - void setDisplayLimits(uint traceNumber, double x, double y, double w, double h); + void setDisplayLimits(uint traceNumber, TQRectF limits); + TQRectF displayLimits(uint traceNumber); + void setNumberOfTraces(uint traceNumber); + void setNumberOfCursors(uint traceNumber); TQDoubleArray& samples(uint traceNumber); void setSamples(uint traceNumber, TQDoubleArray&); @@ -78,7 +157,7 @@ class TraceWidget : public TQWidget TQColor& traceColor(uint traceNumber); void setTraceColor(uint traceNumber, TQColor&); bool traceEnabled(uint traceNumber); - void setTraceEnabled(uint traceNumber, bool enabled); + void setTraceEnabled(uint traceNumber, bool enabled, bool showText=true); TQString traceName(uint traceNumber); void setTraceName(uint traceNumber, TQString name); TQString traceHorizontalUnits(uint traceNumber); @@ -86,19 +165,48 @@ class TraceWidget : public TQWidget TQString traceVerticalUnits(uint traceNumber); void setTraceVerticalUnits(uint traceNumber, TQString units); + double cursorPosition(uint cursorNumber); + void setCursorPosition(uint cursorNumber, double position); + bool cursorEnabled(uint cursorNumber); + void setCursorEnabled(uint cursorNumber, bool enabled); + TQString cursorName(uint cursorNumber); + void setCursorName(uint cursorNumber, TQString name); + TQt::Orientation cursorOrientation(uint cursorNumber); + void setCursorOrientation(uint cursorNumber, TQt::Orientation orient); + + TQRectF zoomBox(); + void setZoomBoxEnabled(bool enabled); + + static TQString prettyFormat(double value, double rangeDetectValue, TQString baseUnits, unsigned int precision=3); + private slots: void updateTraceText(); + void updateCursorText(); + + signals: + void zoomBoxChanged(const TQRectF&); private: void resizeTraceArray(uint newsize); + void resizeCursorArray(uint newsize); private: unsigned int m_horizDivs; unsigned int m_vertDivs; + unsigned int m_cursorDarkness; + unsigned int m_zoomBoxDarkness; + bool m_zoomBoxEnabled; + TQRectF m_zoomBoxPrev; TraceList m_traceArray; - TQVBoxLayout* m_primaryLayout; + CursorList m_cursorArray; + TQGridLayout* m_primaryLayout; + TQGridLayout* m_rightPaneLayout; TQGridLayout* m_traceLabelLayout; + TQGridLayout* m_infoLabelLayout; + TQGridLayout* m_cursorLabelLayout; + TQGridLayout* m_statusLabelLayout; GraticuleWidget* m_graticuleWidget; friend class GraticuleWidget; + friend class CursorData; }; \ No newline at end of file