Make sure the content widget never replaces valid data with empty data.
authorChristian Kandeler <christian.kandeler@digia.com>
Fri, 26 Sep 2014 10:15:59 +0000 (12:15 +0200)
committerChristian Kandeler <christian.kandeler@digia.com>
Mon, 6 Oct 2014 10:22:26 +0000 (12:22 +0200)
This could happen because insertContents() is called once for
every run of the content provider, even if an invalidation happens
in between. Example sequence:
    run()
    invalidate() [removes result of first run]
    run()
    insertContents() [queued for first run, retrieves result of second run]
    insertContents() [queued for second run, retrieves empty data]
We now check in insertContents() whether the content provider has a
valid root item and do nothing if it does not. This means that
insertContents() will never replace the current model data with empty
data; only invalidateContents() can do that from now on.
Further improvements:
    - Only call insertContents() if the run was not aborted; this
      reduces the number of useless objects in the event queue.
    - Remove the m_rootItem member; it was only used in the run() function.
    - Only add the root item to the list at the end of a successful run;
      there is no reason this object should be accessible from the outside
      while there are still children being added to it.

Change-Id: I80e2ea93dd9bbc8ab7f406c989b61f16f11b6eea
Reviewed-by: Karsten Heimrich <karsten.heimrich@digia.com>
src/assistant/help/qhelpcontentwidget.cpp

index b3c7c9c..37abd88 100644 (file)
@@ -73,6 +73,7 @@ public:
 
 class QHelpContentProvider : public QThread
 {
+    Q_OBJECT
 public:
     QHelpContentProvider(QHelpEnginePrivate *helpEngine);
     ~QHelpContentProvider();
@@ -81,11 +82,13 @@ public:
     QHelpContentItem *rootItem();
     int nextChildCount() const;
 
+signals:
+    void finishedSuccessFully();
+
 private:
     void run();
 
     QHelpEnginePrivate *m_helpEngine;
-    QHelpContentItem *m_rootItem;
     QStringList m_filterAttributes;
     QQueue<QHelpContentItem*> m_rootItems;
     QMutex m_mutex;
@@ -196,7 +199,6 @@ QHelpContentProvider::QHelpContentProvider(QHelpEnginePrivate *helpEngine)
     : QThread(helpEngine)
 {
     m_helpEngine = helpEngine;
-    m_rootItem = 0;
     m_abort = false;
 }
 
@@ -253,8 +255,7 @@ void QHelpContentProvider::run()
     QHelpContentItem *item = 0;
 
     m_mutex.lock();
-    m_rootItem = new QHelpContentItem(QString(), QString(), 0);
-    m_rootItems.enqueue(m_rootItem);
+    QHelpContentItem * const rootItem = new QHelpContentItem(QString(), QString(), 0);
     QStringList atts = m_filterAttributes;
     const QStringList fileNames = m_helpEngine->orderedFileNameList;
     m_mutex.unlock();
@@ -262,9 +263,10 @@ void QHelpContentProvider::run()
     foreach (const QString &dbFileName, fileNames) {
         m_mutex.lock();
         if (m_abort) {
+            delete rootItem;
             m_abort = false;
             m_mutex.unlock();
-            break;
+            return;
         }
         m_mutex.unlock();
         QHelpDBReader reader(dbFileName,
@@ -292,8 +294,8 @@ CHECK_DEPTH:
                 if (depth == 0) {
                     m_mutex.lock();
                     item = new QHelpContentItem(title, link,
-                        m_helpEngine->fileNameReaderMap.value(dbFileName), m_rootItem);
-                    m_rootItem->appendChild(item);
+                        m_helpEngine->fileNameReaderMap.value(dbFileName), rootItem);
+                    rootItem->appendChild(item);
                     m_mutex.unlock();
                     stack.push(item);
                     _depth = 1;
@@ -317,8 +319,10 @@ CHECK_DEPTH:
         }
     }
     m_mutex.lock();
+    m_rootItems.enqueue(rootItem);
     m_abort = false;
     m_mutex.unlock();
+    emit finishedSuccessFully();
 }
 
 
@@ -353,7 +357,7 @@ QHelpContentModel::QHelpContentModel(QHelpEnginePrivate *helpEngine)
     d->rootItem = 0;
     d->qhelpContentProvider = new QHelpContentProvider(helpEngine);
 
-    connect(d->qhelpContentProvider, SIGNAL(finished()),
+    connect(d->qhelpContentProvider, SIGNAL(finishedSuccessFully()),
         this, SLOT(insertContents()), Qt::QueuedConnection);
     connect(helpEngine->q, SIGNAL(readersAboutToBeInvalidated()), this, SLOT(invalidateContents()));
 }
@@ -395,6 +399,9 @@ void QHelpContentModel::createContents(const QString &customFilterName)
 
 void QHelpContentModel::insertContents()
 {
+    QHelpContentItem * const newRootItem = d->qhelpContentProvider->rootItem();
+    if (!newRootItem)
+        return;
     int count;
     if (d->rootItem) {
         count = d->rootItem->childCount() - 1;
@@ -406,7 +413,7 @@ void QHelpContentModel::insertContents()
 
     count = d->qhelpContentProvider->nextChildCount() - 1;
     beginInsertRows(QModelIndex(), 0, count > 0 ? count : 0);
-    d->rootItem = d->qhelpContentProvider->rootItem();
+    d->rootItem = newRootItem;
     endInsertRows();
     emit contentsCreated();
 }
@@ -586,3 +593,5 @@ void QHelpContentWidget::showLink(const QModelIndex &index)
 }
 
 QT_END_NAMESPACE
+
+#include "qhelpcontentwidget.moc"