From 1ddc4b80da5a7a190548dac3b76bd41d49be1b4e Mon Sep 17 00:00:00 2001
From: Gennady Pospelov <g.pospelov@fz-juelich.de>
Date: Wed, 18 May 2016 14:54:27 +0200
Subject: [PATCH] Finally info label appears/disappears when tree is empty

---
 GUI/coregui/Models/FitParameterAbsModel.cpp   | 93 +++++++++++++++----
 GUI/coregui/Models/FitParameterAbsModel.h     |  7 +-
 GUI/coregui/Models/FitParameterItems.cpp      |  5 +
 GUI/coregui/Models/FitParameterItems.h        |  1 +
 GUI/coregui/Models/ModelPath.cpp              | 15 +++
 GUI/coregui/Models/ModelPath.h                |  2 +
 .../Views/FitWidgets/FitParameterWidget.cpp   | 68 +++++++++-----
 .../Views/FitWidgets/FitParameterWidget.h     |  5 +-
 .../Views/InfoWidgets/InfoLabelController.cpp |  4 +-
 9 files changed, 153 insertions(+), 47 deletions(-)

diff --git a/GUI/coregui/Models/FitParameterAbsModel.cpp b/GUI/coregui/Models/FitParameterAbsModel.cpp
index 6a5cbd38a07..3707b265921 100644
--- a/GUI/coregui/Models/FitParameterAbsModel.cpp
+++ b/GUI/coregui/Models/FitParameterAbsModel.cpp
@@ -21,6 +21,8 @@
 #include "JobModel.h"
 #include "FitModelHelper.h"
 #include "ParameterTreeItems.h"
+#include "GUIHelpers.h"
+#include "ModelPath.h"
 #include <QColor>
 #include <QMimeData>
 #include <QDebug>
@@ -71,6 +73,7 @@ QModelIndex FitParameterAbsModel::index(int row, int column, const QModelIndex &
         return QModelIndex();
 
     SessionItem *parent_item = itemForIndex(parent);
+//    if(!isValidSourceItem(parent_item)) return QModelIndex();
     Q_ASSERT(parent_item);
 
     if(parent_item->modelType() == Constants::FitParameterContainerType) {
@@ -97,15 +100,22 @@ QModelIndex FitParameterAbsModel::index(int row, int column, const QModelIndex &
 
 QModelIndex FitParameterAbsModel::parent(const QModelIndex &child) const
 {
-    if(!m_root_item) return QModelIndex();
+    if(!m_root_item)
+        return QModelIndex();
 
     if (!child.isValid())
         return QModelIndex();
 
     if (SessionItem *child_item = itemForIndex(child)) {
         if (SessionItem *parent_item = child_item->parent()) {
+
+            if(!isValidSourceItem(parent_item)) return QModelIndex();
+
             if(parent_item->modelType()==Constants::FitParameterLinkType) {
                 SessionItem *fitPar = parent_item->parent();
+
+                if(!isValidSourceItem(fitPar)) return QModelIndex();
+
                 return createIndex(fitPar->parentRow(), 0, fitPar);
             }
         }
@@ -121,7 +131,9 @@ int FitParameterAbsModel::rowCount(const QModelIndex &parent) const
 
     if (parent.isValid() && parent.column() != 0)
         return 0;
+
     SessionItem *parent_item = itemForIndex(parent);
+    if(parent_item!=m_root_item && !isValidSourceItem(parent_item)) return 0;
 
     if(parent_item->modelType() == Constants::FitParameterContainerType) {
         return parent_item->rowCount();
@@ -297,6 +309,7 @@ void FitParameterAbsModel::onSourceDataChanged(const QModelIndex &topLeft, const
 
 void FitParameterAbsModel::onSourceRowsInserted(const QModelIndex &parent, int first, int last)
 {
+    if(!m_root_item) return;
 //    Q_UNUSED(parent);
 //    Q_UNUSED(first);
 //    Q_UNUSED(last);
@@ -317,6 +330,8 @@ void FitParameterAbsModel::onSourceRowsInserted(const QModelIndex &parent, int f
 
 void FitParameterAbsModel::onSourceBeginRemoveRows(const QModelIndex &parent, int first, int last)
 {
+    if(!m_root_item) return;
+
     qDebug() << "FitParameterAbsModel::onSourceBeginRemoveRows" << parent << first << last;
     JobModel *sourceModel = qobject_cast<JobModel *>(sender());
     Q_ASSERT(sourceModel);
@@ -327,31 +342,39 @@ void FitParameterAbsModel::onSourceBeginRemoveRows(const QModelIndex &parent, in
     // way #1
     beginResetModel();
 
-    QModelIndex itemIndex = sourceModel->index(first, 0, parent);
-    if(sourceModel->itemForIndex(itemIndex) == m_root_item)
-        m_root_item = 0;
+////    QModelIndex itemIndex = sourceModel->index(first, 0, parent);
+////    if(sourceModel->itemForIndex(itemIndex) == m_root_item)
+////        m_root_item = 0;
 
 
     endResetModel();
 
 
-    return;
+//    return;
 
     // way #2
-    if(SessionItem *sourceItem = sourceModel->itemForIndex(parent)) {
-        QModelIndex localIndex = indexOfItem(sourceItem);
-        beginRemoveRows(localIndex, 0, rowCount(localIndex));
-        endRemoveRows();
-
-        QModelIndex itemIndex = sourceModel->index(first, 0, parent);
-        if(sourceModel->itemForIndex(itemIndex) == m_root_item)
-            m_root_item = 0;
+//    if(SessionItem *sourceItem = sourceModel->itemForIndex(parent)) {
+//        QModelIndex localIndex = indexOfItem(sourceItem);
+//        if(localIndex.isValid()) {
+//            beginRemoveRows(localIndex, 0, rowCount(localIndex));
+//            endRemoveRows();
+//        }
+//    }
+}
 
-    }
+void FitParameterAbsModel::onSourceRowsRemoved(const QModelIndex &parent, int first, int last)
+{
+    qDebug() << "FitParameterAbsModel::onSourceRowsRemoved" << parent << first << last;
+    Q_UNUSED(parent);
+    Q_UNUSED(first);
+    Q_UNUSED(last);
+    beginResetModel();
+    endResetModel();
 }
 
 void FitParameterAbsModel::onSourceAboutToBeReset()
 {
+    if(!m_root_item) return;
     beginResetModel();
     endResetModel();
 }
@@ -364,8 +387,10 @@ void FitParameterAbsModel::connectModel(QAbstractItemModel *sourceModel, bool is
                 this, SLOT(onSourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
 //        connect(sourceModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
 //                   this, SLOT(onSourceRowsInserted(QModelIndex,int,int)));
-        connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
-                   this, SLOT(onSourceBeginRemoveRows(QModelIndex,int,int)));
+//        connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+//                   this, SLOT(onSourceBeginRemoveRows(QModelIndex,int,int)));
+        connect(sourceModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+                   this, SLOT(onSourceRowsRemoved(QModelIndex,int,int)));
         connect(sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(onSourceAboutToBeReset()));
 
 
@@ -377,13 +402,16 @@ void FitParameterAbsModel::connectModel(QAbstractItemModel *sourceModel, bool is
                 this, SLOT(onSourceDataChanged(QModelIndex,QModelIndex,QVector<int>)));
 //        disconnect(sourceModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
 //                   this, SLOT(onSourceRowsInserted(QModelIndex,int,int)));
-        disconnect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
-                   this, SLOT(onSourceBeginRemoveRows(QModelIndex,int,int)));
+//        disconnect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+//                   this, SLOT(onSourceBeginRemoveRows(QModelIndex,int,int)));
+        disconnect(sourceModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+                   this, SLOT(onSourceRowsRemoved(QModelIndex,int,int)));
         disconnect(sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(onSourceAboutToBeReset()));
     }
 }
 
-void FitParameterAbsModel::addColumn(FitParameterAbsModel::EColumn id, const QString &name, const QString &tooltip)
+void FitParameterAbsModel::addColumn(FitParameterAbsModel::EColumn id, const QString &name,
+                                     const QString &tooltip)
 {
     m_columnNames[id] = name;
     m_columnToolTips[id] = tooltip;
@@ -391,6 +419,7 @@ void FitParameterAbsModel::addColumn(FitParameterAbsModel::EColumn id, const QSt
 
 QModelIndex FitParameterAbsModel::indexOfItem(SessionItem *item) const
 {
+    if(!m_root_item) return QModelIndex();
 
     if(SessionItem *parent_item = item->parent()) {
         if(parent_item->modelType() == Constants::FitParameterContainerType) {
@@ -420,9 +449,33 @@ QModelIndex FitParameterAbsModel::indexOfItem(SessionItem *item) const
 
 SessionItem *FitParameterAbsModel::itemForIndex(const QModelIndex &index) const
 {
+    if(!m_root_item) return 0;
+
     if (index.isValid()) {
-        if (SessionItem *item = static_cast<SessionItem *>(index.internalPointer()))
+        SessionItem *item = static_cast<SessionItem *>(index.internalPointer());
+        if(item) {
+            if(!isValidSourceItem(item)) {
+                return 0;
+//                throw GUIHelpers::Error("FitParameterAbsModel::itemForIndex -> Error! Attempt to "
+//                                    "use destroyed item.");
+            }
+
             return item;
+        }
     }
     return m_root_item;
 }
+
+SessionModel *FitParameterAbsModel::sourceModel() const
+{
+    Q_ASSERT(m_root_item);
+    return m_root_item->model();
+}
+
+//! Returns true if given item still exists in source model
+bool FitParameterAbsModel::isValidSourceItem(SessionItem *item) const
+{
+    if(item == m_root_item) return true;
+    if(sourceModel() && ModelPath::isValidItem(sourceModel(), item, m_root_item->index())) return true;
+    return false;
+}
diff --git a/GUI/coregui/Models/FitParameterAbsModel.h b/GUI/coregui/Models/FitParameterAbsModel.h
index 4126c674720..0078fcfd2d7 100644
--- a/GUI/coregui/Models/FitParameterAbsModel.h
+++ b/GUI/coregui/Models/FitParameterAbsModel.h
@@ -20,7 +20,7 @@
 #include "WinDllMacros.h"
 #include <QAbstractItemModel>
 
-class JobModel;
+class SessionModel;
 class FitParameterContainerItem;
 class SessionItem;
 
@@ -61,10 +61,15 @@ public:
     QModelIndex indexOfItem(SessionItem *item) const;
     SessionItem *itemForIndex(const QModelIndex &index) const;
 
+    SessionModel *sourceModel() const;
+
+    bool isValidSourceItem(SessionItem *item) const;
+
 private slots:
     void onSourceDataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & roles);
     void onSourceRowsInserted(const QModelIndex & parent, int first, int last);
     void onSourceBeginRemoveRows(const QModelIndex & parent, int first, int last);
+    void onSourceRowsRemoved(const QModelIndex & parent, int first, int last);
     void onSourceAboutToBeReset();
 
 private:
diff --git a/GUI/coregui/Models/FitParameterItems.cpp b/GUI/coregui/Models/FitParameterItems.cpp
index 9f9c9168cba..b2dfb7e4804 100644
--- a/GUI/coregui/Models/FitParameterItems.cpp
+++ b/GUI/coregui/Models/FitParameterItems.cpp
@@ -178,3 +178,8 @@ FitParameterItem *FitParameterContainerItem::getFitParameterItem(const QString &
     }
     return nullptr;
 }
+
+bool FitParameterContainerItem::isEmpty()
+{
+    return getItems(T_FIT_PARAMETERS).isEmpty() ? true : false;
+}
diff --git a/GUI/coregui/Models/FitParameterItems.h b/GUI/coregui/Models/FitParameterItems.h
index 7b1488d6297..5d9ab0de7db 100644
--- a/GUI/coregui/Models/FitParameterItems.h
+++ b/GUI/coregui/Models/FitParameterItems.h
@@ -54,6 +54,7 @@ public:
     static const QString T_FIT_PARAMETERS;
     explicit FitParameterContainerItem();
     FitParameterItem *getFitParameterItem(const QString &link);
+    bool isEmpty();
 };
 
 #endif
diff --git a/GUI/coregui/Models/ModelPath.cpp b/GUI/coregui/Models/ModelPath.cpp
index aaf8cd281a6..84734324e91 100644
--- a/GUI/coregui/Models/ModelPath.cpp
+++ b/GUI/coregui/Models/ModelPath.cpp
@@ -150,6 +150,21 @@ SessionItem *ModelPath::getItemFromPath(const QString &relPath, SessionItem *par
     return parent->model()->itemForIndex(ModelPath::getIndexFromPath(parent->model(), fullPath));
 }
 
+//! Iterates through all the model and returns true if item is found. This is to
+
+bool ModelPath::isValidItem(SessionModel *model, SessionItem *item, const QModelIndex &parent)
+{
+    for(int i_row=0; i_row<model->rowCount(parent); ++i_row) {
+        QModelIndex index = model->index(i_row, 0, parent);
+        SessionItem *curr = model->itemForIndex(index);
+        if(curr == item) return true;
+
+        bool isvalid = isValidItem(model, item, index);
+        if(isvalid) return isvalid;
+    }
+    return false;
+}
+
 QStringList ModelPath::splitParameterName(const QString &par_name)
 {
     QStringList result;
diff --git a/GUI/coregui/Models/ModelPath.h b/GUI/coregui/Models/ModelPath.h
index d811ded3d1b..4b8ac90dee9 100644
--- a/GUI/coregui/Models/ModelPath.h
+++ b/GUI/coregui/Models/ModelPath.h
@@ -51,6 +51,8 @@ public:
 
     static SessionItem *getItemFromPath(const QString &relPath, SessionItem *parent);
 
+    static bool isValidItem(SessionModel *model, SessionItem *item, const QModelIndex &parent);
+
 private:
 
     static QStringList splitParameterName(const QString& par_name);
diff --git a/GUI/coregui/Views/FitWidgets/FitParameterWidget.cpp b/GUI/coregui/Views/FitWidgets/FitParameterWidget.cpp
index a076c130206..f0fd298137c 100644
--- a/GUI/coregui/Views/FitWidgets/FitParameterWidget.cpp
+++ b/GUI/coregui/Views/FitWidgets/FitParameterWidget.cpp
@@ -202,6 +202,14 @@ void FitParameterWidget::onAddToFitParAction(int ipar)
     }
 }
 
+void FitParameterWidget::onFitParameterModelChange()
+{
+    qDebug() << "FitParameterWidget::onFitParameterModelChange()";
+    spanParameters();
+    updateInfoLabel();
+}
+
+
 //! Context menu reimplemented to suppress the default one
 
 void FitParameterWidget::contextMenuEvent(QContextMenuEvent *event)
@@ -272,15 +280,18 @@ void FitParameterWidget::init_fit_model()
     m_treeView->setModel(m_fitParameterModel);
 
     connect(m_fitParameterModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
-            this, SLOT(spanParameters()));
+            this, SLOT(onFitParameterModelChange()));
 
-    spanParameters();
-    connectFitParametersSelection(true);
+//    connect(m_fitParameterModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+//               this, SLOT(onFitParameterModelChange()));
+    connect(m_fitParameterModel, SIGNAL(modelReset()), this, SLOT(onFitParameterModelChange()));
+
+//    connect(m_fitParameterModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+//               this, SLOT(onFitParameterModelChange()));
 
-//    InfoLabelWidget *label = new InfoLabelWidget(this);
-//    label->setPosition(0, 0);
+    onFitParameterModelChange();
 
-    m_infoLabel->setShown(true);
+    connectFitParametersSelection(true);
 }
 
 //! Adds to JobItem all fit containers, if necessary.
@@ -302,24 +313,6 @@ void FitParameterWidget::init_fit_containers()
     }
 }
 
-//! Makes first column in FitParameterItem's tree related to ParameterItem link occupy whole space.
-
-void FitParameterWidget::spanParameters()
-{
-    m_treeView->expandAll();
-    for (int i = 0; i < m_fitParameterModel->rowCount(QModelIndex()); i++){
-        QModelIndex parameter = m_fitParameterModel->index(i,0,QModelIndex());
-        if (!parameter.isValid())
-            break;
-        int childRowCount = m_fitParameterModel->rowCount(parameter);
-        if (childRowCount > 0){
-            for (int j = 0; j < childRowCount; j++) {
-                m_treeView->setFirstColumnSpanned(j, parameter, true);
-            }
-        }
-    }
-}
-
 //! Returns true if tuning widget contains selected ParameterItem's which can be used to create
 //! a fit parameter (i.e. it is not linked with some fit parameter already).
 
@@ -393,6 +386,33 @@ QVector<FitParameterLinkItem *> FitParameterWidget::selectedFitParameterLinks()
     return result;
 }
 
+//! Makes first column in FitParameterItem's tree related to ParameterItem link occupy whole space.
+
+void FitParameterWidget::spanParameters()
+{
+    m_treeView->expandAll();
+    for (int i = 0; i < m_fitParameterModel->rowCount(QModelIndex()); i++){
+        QModelIndex parameter = m_fitParameterModel->index(i,0,QModelIndex());
+        if (!parameter.isValid())
+            break;
+        int childRowCount = m_fitParameterModel->rowCount(parameter);
+        if (childRowCount > 0){
+            for (int j = 0; j < childRowCount; j++) {
+                m_treeView->setFirstColumnSpanned(j, parameter, true);
+            }
+        }
+    }
+}
+
+//! Places overlay label on top of tree view, if there is no fit parameters
+void FitParameterWidget::updateInfoLabel()
+{
+    Q_ASSERT(m_jobItem);
+    bool is_to_show_label = m_jobItem->fitParameterContainerItem()->isEmpty();
+    qDebug() << "FitParameterWidget::updateInfoLabel()" << m_jobItem->fitParameterContainerItem()->getItems(FitParameterContainerItem::T_FIT_PARAMETERS).size() << is_to_show_label << m_treeView;
+    m_infoLabel->setShown(is_to_show_label);
+}
+
 
 void FitParameterWidget::connectTuningWidgetSelection(bool active)
 {
diff --git a/GUI/coregui/Views/FitWidgets/FitParameterWidget.h b/GUI/coregui/Views/FitWidgets/FitParameterWidget.h
index f8808069a4a..065e5705f43 100644
--- a/GUI/coregui/Views/FitWidgets/FitParameterWidget.h
+++ b/GUI/coregui/Views/FitWidgets/FitParameterWidget.h
@@ -60,7 +60,7 @@ private slots:
     void onRemoveFromFitParAction();
     void onRemoveFitParAction();
     void onAddToFitParAction(int ipar);
-    void spanParameters();
+    void onFitParameterModelChange();
 
 protected:
     void contextMenuEvent(QContextMenuEvent *event);
@@ -83,6 +83,9 @@ private:
     QVector<FitParameterItem *> selectedFitParameters();
     QVector<FitParameterLinkItem *> selectedFitParameterLinks();
 
+    void spanParameters();
+    void updateInfoLabel();
+
     QTreeView *m_treeView;
     JobItem *m_jobItem;
     ParameterTuningWidget *m_tuningWidget;
diff --git a/GUI/coregui/Views/InfoWidgets/InfoLabelController.cpp b/GUI/coregui/Views/InfoWidgets/InfoLabelController.cpp
index 4c26e5ab04a..51f84d7a580 100644
--- a/GUI/coregui/Views/InfoWidgets/InfoLabelController.cpp
+++ b/GUI/coregui/Views/InfoWidgets/InfoLabelController.cpp
@@ -45,6 +45,7 @@ void InfoLabelController::setArea(QAbstractScrollArea *area)
 void InfoLabelController::setShown(bool shown)
 {
     if(shown) {
+        Q_ASSERT(m_area);
         if(!m_label) {
             m_label = new InfoLabelWidget(m_area);
             m_label->setText(m_text);
@@ -72,7 +73,8 @@ bool InfoLabelController::eventFilter(QObject *obj, QEvent *event)
 void InfoLabelController::updateLabelGeometry()
 {
     if(!m_label || !m_area) return;
-    qDebug() << "InfoLabelController::updateLabelGeometry()" << m_area->width(), m_area->height();
+    qDebug() << "InfoLabelController::updateLabelGeometry()" << m_area->width() << m_area->height() << m_area << m_text;
     m_label->setRectangle(QRect(0, 0, m_area->width(), m_area->height()));
     m_label->setPosition(0, 0);
+    m_label->show();
 }
-- 
GitLab