From ca1ebc7cba4c66e9798c295283fd9d280d551c72 Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Fri, 15 Dec 2017 21:15:17 +0100 Subject: [PATCH] LP-567 uavobjectbrowser: improve highlight handling keep track of when to check highlight and schedule timer accordingly old way would do that at a fixed periodicity leading to aliasing --- .../src/plugins/uavobjectbrowser/treeitem.cpp | 73 +++++++++++++------ .../src/plugins/uavobjectbrowser/treeitem.h | 7 +- .../uavobjectbrowser/uavobjecttreemodel.cpp | 3 +- 3 files changed, 57 insertions(+), 26 deletions(-) diff --git a/ground/gcs/src/plugins/uavobjectbrowser/treeitem.cpp b/ground/gcs/src/plugins/uavobjectbrowser/treeitem.cpp index 71b9cf690..5b4d17702 100644 --- a/ground/gcs/src/plugins/uavobjectbrowser/treeitem.cpp +++ b/ground/gcs/src/plugins/uavobjectbrowser/treeitem.cpp @@ -28,11 +28,12 @@ #include "treeitem.h" /* Constructor */ -HighLightManager::HighLightManager(long checkingInterval) +HighLightManager::HighLightManager() { - // Start the timer and connect it to the callback - m_expirationTimer.start(checkingInterval); - connect(&m_expirationTimer, SIGNAL(timeout()), this, SLOT(checkItemsExpired())); + // Initialize the timer and connect it to the callback + m_expirationTimer.setTimerType(Qt::PreciseTimer); + m_expirationTimer.setSingleShot(true); + connect(&m_expirationTimer, &QTimer::timeout, this, &HighLightManager::checkItemsExpired); } /* @@ -52,6 +53,20 @@ bool HighLightManager::add(TreeItem *itemToAdd) return false; } +bool HighLightManager::startTimer(QTime expirationTime) +{ + // Lock to ensure thread safety + QMutexLocker locker(&m_mutex); + + if (!m_expirationTimer.isActive()) { + int msec = QTime::currentTime().msecsTo(expirationTime); + // qDebug() << "start" << msec; + m_expirationTimer.start((msec < 10) ? 10 : msec); + return true; + } + return false; +} + /* * Called to remove item from list. * Returns true if item was removed, otherwise false. @@ -81,35 +96,48 @@ void HighLightManager::checkItemsExpired() // This is the timestamp to compare with QTime now = QTime::currentTime(); + QTime next; // Loop over all items, check if they expired. while (iter.hasNext()) { TreeItem *item = iter.next(); - if (item->getHiglightExpires() < now) { - // If expired, call removeHighlight + if (item->getHiglightExpires() <= now) { + // expired, call removeHighlight item->removeHighlight(); // Remove from list since it is restored. iter.remove(); + } else { + // not expired, check if next to expire + if (!next.isValid() || (next > item->getHiglightExpires())) { + next = item->getHiglightExpires(); + } } } + if (next.isValid()) { + int msec = QTime::currentTime().msecsTo(next); + // qDebug() << "restart" << msec; + m_expirationTimer.start((msec < 10) ? 10 : msec); + } } -int TreeItem::m_highlightTimeMs = 500; +int TreeItem::m_highlightTimeMs = 300; TreeItem::TreeItem(const QList &data, TreeItem *parent) : QObject(0), m_data(data), m_parent(parent), m_highlight(false), - m_changed(false) + m_changed(false), + m_highlightManager(0) {} TreeItem::TreeItem(const QVariant &data, TreeItem *parent) : QObject(0), m_parent(parent), m_highlight(false), - m_changed(false) + m_changed(false), + m_highlightManager(0) { m_data << data << "" << ""; } @@ -180,24 +208,27 @@ void TreeItem::apply() } /* - * Called after a value has changed to trigger highlightning of tree item. + * Called after a value has changed to trigger highlighting of tree item. */ void TreeItem::setHighlight(bool highlight) { - m_highlight = highlight; m_changed = false; - if (highlight) { - // Update the expires timestamp - m_highlightExpires = QTime::currentTime().addMSecs(m_highlightTimeMs); - - // Add to highlightmanager - if (m_highlightManager->add(this)) { - // Only emit signal if it was added + if (m_highlight != highlight) { + m_highlight = highlight; + if (highlight) { + // Add to highlight manager + if (m_highlightManager->add(this)) { + // Only emit signal if it was added + emit updateHighlight(this); + } + // Update expiration timeout + m_highlightExpires = QTime::currentTime().addMSecs(m_highlightTimeMs); + // start expiration timer if necessary + m_highlightManager->startTimer(m_highlightExpires); + } else if (m_highlightManager->remove(this)) { + // Only emit signal if it was removed emit updateHighlight(this); } - } else if (m_highlightManager->remove(this)) { - // Only emit signal if it was removed - emit updateHighlight(this); } // If we have a parent, call recursively to update highlight status of parents. diff --git a/ground/gcs/src/plugins/uavobjectbrowser/treeitem.h b/ground/gcs/src/plugins/uavobjectbrowser/treeitem.h index 253ec041c..ba7d4564f 100644 --- a/ground/gcs/src/plugins/uavobjectbrowser/treeitem.h +++ b/ground/gcs/src/plugins/uavobjectbrowser/treeitem.h @@ -49,7 +49,7 @@ class TreeItem; * non highlighted state in a linked list. * A timer traverses this list periodically to find out * if any of the items should be restored. All items are - * updated withan expiration timestamp when they expires. + * updated with an expiration timestamp when they expires. * An item that is beeing restored is removed from the * list and its removeHighlight() method is called. Items * that are not expired are left in the list til next time. @@ -60,8 +60,7 @@ class TreeItem; class HighLightManager : public QObject { Q_OBJECT public: - // Constructor taking the checking interval in ms. - HighLightManager(long checkingInterval); + HighLightManager(); // This is called when an item has been set to // highlighted = true. @@ -70,6 +69,8 @@ public: // This is called when an item is set to highlighted = false; bool remove(TreeItem *itemToRemove); + bool startTimer(QTime time); + private slots: // Timer callback method. void checkItemsExpired(); diff --git a/ground/gcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp b/ground/gcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp index 8f5941a48..77dbcabae 100644 --- a/ground/gcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp +++ b/ground/gcs/src/plugins/uavobjectbrowser/uavobjecttreemodel.cpp @@ -52,8 +52,7 @@ UAVObjectTreeModel::UAVObjectTreeModel(QObject *parent, bool categorize, bool sh Q_ASSERT(objManager); - // Create highlight manager, let it run every 300 ms. - m_highlightManager = new HighLightManager(300); + m_highlightManager = new HighLightManager(); connect(objManager, SIGNAL(newObject(UAVObject *)), this, SLOT(newObject(UAVObject *))); connect(objManager, SIGNAL(newInstance(UAVObject *)), this, SLOT(newObject(UAVObject *)));