// Created on: 2021-04-27
// Created by: Natalia ERMOLAEVA
// Copyright (c) 2021 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement. 

#include <inspector/MessageView_Window.hxx>
#include <inspector/MessageView_VisibilityState.hxx>
#include <inspector/MessageView_ActionsTest.hxx>

#include <inspector/MessageModel_Actions.hxx>
#include <inspector/MessageModel_ItemAlert.hxx>
#include <inspector/MessageModel_ItemReport.hxx>
#include <inspector/MessageModel_ItemRoot.hxx>
#include <inspector/MessageModel_TreeModel.hxx>
#include <inspector/MessageView_MetricStatisticModel.hxx>

#include <inspector/TreeModel_Tools.hxx>

#include <inspector/ViewControl_PropertyView.hxx>
#include <inspector/ViewControl_TableModelValues.hxx>
#include <inspector/ViewControl_TreeView.hxx>
#include <inspector/Convert_Tools.hxx>

#include <inspector/View_Viewer.hxx>
#include <inspector/View_Widget.hxx>

#include <AIS_Shape.hxx>
#include <Graphic3d_Camera.hxx>
#include <Message.hxx>
#include <TCollection_AsciiString.hxx>

#include <inspector/ViewControl_Tools.hxx>
#include <inspector/View_Displayer.hxx>
#include <inspector/View_ToolBar.hxx>
#include <inspector/View_Widget.hxx>
#include <inspector/View_Window.hxx>
#include <inspector/View_Viewer.hxx>

#include <Standard_WarningsDisable.hxx>
#include <QApplication>
#include <QAction>
#include <QDockWidget>
#include <QFile>
#include <QFileDialog>
#include <QHeaderView>
#include <QLayout>
#include <QMainWindow>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
#include <QTextStream>
#include <QToolBar>
#include <QToolButton>
#include <QTreeView>
#include <QWidget>
#include <Standard_WarningsRestore.hxx>

const int DEFAULT_SHAPE_VIEW_WIDTH = 400;
const int DEFAULT_SHAPE_VIEW_HEIGHT = 450;
const int DEFAULT_SHAPE_VIEW_POSITION_X = 60;
const int DEFAULT_SHAPE_VIEW_POSITION_Y = 60;

const int MESSAGEVIEW_DEFAULT_TREE_VIEW_WIDTH = 950;
const int MESSAGEVIEW_DEFAULT_TREE_VIEW_HEIGHT = 500;

const int MESSAGEVIEW_DEFAULT_VIEW_WIDTH = 200;
const int MESSAGEVIEW_DEFAULT_VIEW_HEIGHT = 300;

// =======================================================================
// function : Constructor
// purpose :
// =======================================================================
MessageView_Window::MessageView_Window (QWidget* theParent)
: QObject (theParent)
{
  myMainWindow = new QMainWindow (theParent);

  myTreeView = new ViewControl_TreeView (myMainWindow);
  ((ViewControl_TreeView*)myTreeView)->SetPredefinedSize (QSize (MESSAGEVIEW_DEFAULT_TREE_VIEW_WIDTH,
                                                                 MESSAGEVIEW_DEFAULT_TREE_VIEW_HEIGHT));
  MessageModel_TreeModel* aModel = new MessageModel_TreeModel (myTreeView);
  aModel->InitColumns();

  connect (myTreeView->header(), SIGNAL (sectionResized (int, int, int)),
           this, SLOT(onHeaderResized (int, int, int)));

  myTreeView->setModel (aModel);
  MessageView_VisibilityState* aVisibilityState = new MessageView_VisibilityState (aModel);
  aModel->SetVisibilityState (aVisibilityState);
  connect (aVisibilityState, SIGNAL (itemClicked (const QModelIndex&)),
           this, SLOT(onTreeViewVisibilityClicked(const QModelIndex&)));

  TreeModel_Tools::UseVisibilityColumn (myTreeView);
  TreeModel_Tools::SetDefaultHeaderSections (myTreeView);

  QItemSelectionModel* aSelectionModel = new QItemSelectionModel (aModel);
  myTreeView->setSelectionMode (QAbstractItemView::ExtendedSelection);
  myTreeView->setSelectionModel (aSelectionModel);
  connect (aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
           this, SLOT (onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&)));

  myTreeViewActions = new MessageModel_Actions (myMainWindow, aModel, aSelectionModel);
  myTestViewActions = new MessageView_ActionsTest (myMainWindow, aModel, aSelectionModel);

  myTreeView->setContextMenuPolicy (Qt::CustomContextMenu);
  connect (myTreeView, SIGNAL (customContextMenuRequested (const QPoint&)),
          this, SLOT (onTreeViewContextMenuRequested (const QPoint&)));

  connect (myTreeView->header(), SIGNAL (sectionResized (int, int, int)),
           this, SLOT(onHeaderResized (int, int, int)));

  QModelIndex aParentIndex = myTreeView->model()->index (0, 0);
  myTreeView->setExpanded (aParentIndex, true);

  myMainWindow->setCentralWidget (myTreeView);

  // property view
  myPropertyView = new ViewControl_PropertyView (myMainWindow);
  myPropertyPanelWidget = new QDockWidget (tr ("PropertyPanel"), myMainWindow);
  myPropertyPanelWidget->setObjectName (myPropertyPanelWidget->windowTitle());
  myPropertyPanelWidget->setTitleBarWidget (new QWidget(myMainWindow));
  myPropertyPanelWidget->setWidget (myPropertyView->GetControl());
  myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myPropertyPanelWidget);
  connect (myPropertyPanelWidget->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT (onPropertyPanelShown (bool)));
  connect (myPropertyView, SIGNAL (propertyViewDataChanged()), this, SLOT (onPropertyViewDataChanged()));

  myCustomView = new QTableView (myMainWindow);
  myCustomPanelWidget = new QDockWidget (tr ("PropertyPanel (custom)"), myMainWindow);
  myCustomPanelWidget->setObjectName (myCustomPanelWidget->windowTitle());
  myCustomPanelWidget->setTitleBarWidget (new QWidget(myMainWindow));
  myCustomPanelWidget->setWidget (myCustomView);
  myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myCustomPanelWidget);

  // view
  myViewWindow = new View_Window (myMainWindow, NULL, false);
  connect (myViewWindow, SIGNAL(eraseAllPerformed()), this, SLOT(onEraseAllPerformed()));
  aVisibilityState->SetDisplayer (myViewWindow->Displayer());
  aVisibilityState->SetPresentationType (View_PresentationType_Main);
  myViewWindow->ViewWidget()->SetPredefinedSize (MESSAGEVIEW_DEFAULT_VIEW_WIDTH, MESSAGEVIEW_DEFAULT_VIEW_HEIGHT);

  myViewDockWidget = new QDockWidget (tr ("View"), myMainWindow);
  myViewDockWidget->setObjectName (myViewDockWidget->windowTitle());
  myViewDockWidget->setWidget (myViewWindow);
  myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myViewDockWidget);

  myMainWindow->tabifyDockWidget (myCustomPanelWidget, myViewDockWidget);

  myMainWindow->resize (DEFAULT_SHAPE_VIEW_WIDTH, DEFAULT_SHAPE_VIEW_HEIGHT);
  myMainWindow->move (DEFAULT_SHAPE_VIEW_POSITION_X, DEFAULT_SHAPE_VIEW_POSITION_Y);

  updateVisibleColumns();
}

// =======================================================================
// function : SetParent
// purpose :
// =======================================================================
void MessageView_Window::SetParent (void* theParent)
{
  QWidget* aParent = (QWidget*)theParent;
  if (aParent)
  {
    QLayout* aLayout = aParent->layout();
    if (aLayout)
      aLayout->addWidget (GetMainWindow());
  }
  else
  {
    GetMainWindow()->setParent (0);
    GetMainWindow()->setVisible (true);
  }
}

// =======================================================================
// function : FillActionsMenu
// purpose :
// =======================================================================
void MessageView_Window::FillActionsMenu (void* theMenu)
{
  QMenu* aMenu = (QMenu*)theMenu;
  QList<QDockWidget*> aDockwidgets = myMainWindow->findChildren<QDockWidget*>();
  for (QList<QDockWidget*>::iterator it = aDockwidgets.begin(); it != aDockwidgets.end(); ++it)
  {
    QDockWidget* aDockWidget = *it;
    if (aDockWidget->parentWidget() == myMainWindow)
      aMenu->addAction (aDockWidget->toggleViewAction());
  }
}

// =======================================================================
// function : GetPreferences
// purpose :
// =======================================================================
void MessageView_Window::GetPreferences (TInspectorAPI_PreferencesDataMap& theItem)
{
  theItem.Clear();
  theItem.Bind ("geometry",  TreeModel_Tools::ToString (myMainWindow->saveState()).toStdString().c_str());

  QMap<QString, QString> anItems;
  TreeModel_Tools::SaveState (myTreeView, anItems);
  for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
  {
    theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
  }

  anItems.clear();
  View_Window::SaveState(myViewWindow, anItems);
  for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
  {
    theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
  }
}

// =======================================================================
// function : SetPreferences
// purpose :
// =======================================================================
void MessageView_Window::SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem)
{
  for (TInspectorAPI_IteratorOfPreferencesDataMap anItemIt (theItem); anItemIt.More(); anItemIt.Next())
  {
    if (anItemIt.Key().IsEqual ("geometry"))
      myMainWindow->restoreState (TreeModel_Tools::ToByteArray (anItemIt.Value().ToCString()));
    else if (TreeModel_Tools::RestoreState (myTreeView, anItemIt.Key().ToCString(), anItemIt.Value().ToCString()))
      continue;
    else if (myViewWindow && View_Window::RestoreState(myViewWindow, anItemIt.Key().ToCString(), anItemIt.Value().ToCString()))
      continue;
  }
}

// =======================================================================
// function : UpdateContent
// purpose :
// =======================================================================
void MessageView_Window::UpdateContent()
{
  TCollection_AsciiString aName = "TKMessageView";
  if (myParameters->FindParameters (aName))
  {
    NCollection_List<Handle(Standard_Transient)> aParameters = myParameters->Parameters (aName);
    // Init will remove from parameters those, that are processed only one time (TShape)
    Init (aParameters);
    myParameters->SetParameters (aName, aParameters);
  }
  Handle(Message_Report) aDefaultReport = Message::DefaultReport();
  MessageModel_TreeModel* aViewModel = dynamic_cast<MessageModel_TreeModel*> (myTreeView->model());
  if (!aDefaultReport.IsNull() && !aViewModel->HasReport (aDefaultReport))
  {
    addReport (aDefaultReport);
  }

  updateTreeModel();
  updateVisibleColumns();
}

// =======================================================================
// function : Init
// purpose :
// =======================================================================
void MessageView_Window::Init (NCollection_List<Handle(Standard_Transient)>& theParameters)
{
  Handle(AIS_InteractiveContext) aContext;
  NCollection_List<Handle(Standard_Transient)> aParameters;

  Handle(Graphic3d_Camera) aViewCamera;

  for (NCollection_List<Handle(Standard_Transient)>::Iterator aParamsIt (theParameters);
       aParamsIt.More(); aParamsIt.Next())
  {
    Handle(Standard_Transient) anObject = aParamsIt.Value();
    Handle(Message_Report) aMessageReport = Handle(Message_Report)::DownCast (anObject);
    if (!aMessageReport.IsNull())
    {
      addReport (aMessageReport);
    }
    else if (!Handle(AIS_InteractiveContext)::DownCast (anObject).IsNull())
    {
      aParameters.Append (anObject);
      if (aContext.IsNull())
        aContext = Handle(AIS_InteractiveContext)::DownCast (anObject);
    }
    else if (!Handle(Graphic3d_Camera)::DownCast (anObject).IsNull())
    {
      aViewCamera = Handle(Graphic3d_Camera)::DownCast (anObject);
    }
  }
  MessageModel_TreeModel* aTreeModel = dynamic_cast<MessageModel_TreeModel*> (myTreeView->model());
  if (!aTreeModel)
    return;

  aTreeModel->EmitLayoutChanged();

  if (!aContext.IsNull())
  {
    myViewWindow->SetContext (View_ContextType_External, aContext);
  }
  theParameters = aParameters;
}

// =======================================================================
// function : updateTreeModel
// purpose :
// =======================================================================
void MessageView_Window::updateTreeModel()
{
  MessageModel_TreeModel* aViewModel = dynamic_cast<MessageModel_TreeModel*> (myTreeView->model());
  if (!aViewModel)
    return;

  aViewModel->UpdateTreeModel();
}

// =======================================================================
// function : addReport
// purpose :
// =======================================================================
void MessageView_Window::addReport (const Handle(Message_Report)& theReport,
                                    const TCollection_AsciiString& theReportDescription)
{
  MessageModel_TreeModel* aModel = dynamic_cast<MessageModel_TreeModel*> (myTreeView->model());
  aModel->AddReport (theReport, theReportDescription);
}

// =======================================================================
// function : onTreeViewVisibilityClicked
// purpose :
// =======================================================================
void MessageView_Window::onTreeViewVisibilityClicked(const QModelIndex& theIndex)
{
  MessageModel_TreeModel* aTreeModel = dynamic_cast<MessageModel_TreeModel*> (myTreeView->model());
  TreeModel_VisibilityState* aVisibilityState = aTreeModel->GetVisibilityState();
  if (!aVisibilityState->IsVisible (theIndex))
    myPropertyView->ClearActiveTablesSelection();
}

// =======================================================================
// function : onTreeViewSelectionChanged
// purpose :
// =======================================================================
void MessageView_Window::onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&)
{
  if (!myPropertyPanelWidget->toggleViewAction()->isChecked())
    return;

  updatePropertyPanelBySelection();
  updatePreviewPresentation();
}

// =======================================================================
// function : onTreeViewContextMenuRequested
// purpose :
// =======================================================================
void MessageView_Window::onTreeViewContextMenuRequested (const QPoint& thePosition)
{
  QMenu* aMenu = new QMenu (GetMainWindow());

  MessageModel_ItemRootPtr aRootItem;
  MessageModel_ItemReportPtr aReportItem;
  QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes();

  for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++)
  {
    QModelIndex anIndex = *aSelIt;
    if (anIndex.column() != 0)
      continue;

    TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
    if (!anItemBase)
      continue;

    aRootItem = itemDynamicCast<MessageModel_ItemRoot> (anItemBase);
    if (aRootItem)
      break;
    aReportItem = itemDynamicCast<MessageModel_ItemReport> (anItemBase);
    if (aReportItem)
      break;
  }
  if (aRootItem)
  {
    aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Create Default Report"),
                      SLOT (onCreateDefaultReport()), myMainWindow, this));
  }
  else if (aReportItem)
  {
    aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Export Report"), SLOT (onExportReport()), myMainWindow, this));

    QAction* anAction = ViewControl_Tools::CreateAction (tr ("WallClock Metric statistic"),
      SLOT (onMetricStatistic()), myMainWindow, this);
    anAction->setCheckable (true);
    aMenu->addAction (anAction);
  }
  aMenu->addSeparator();

  aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Preview children presentations"), SLOT (onPreviewChildren()), myMainWindow, this));
  aMenu->addSeparator();

  myTreeViewActions->AddMenuActions (aSelectedIndices, aMenu);
  addActivateMetricActions (aMenu);

  aMenu->addSeparator();
  myTestViewActions->AddMenuActions (aSelectedIndices, aMenu);

  QPoint aPoint = myTreeView->mapToGlobal (thePosition);
  aMenu->exec (aPoint);
}

// =======================================================================
// function : onPropertyPanelShown
// purpose :
// =======================================================================
void MessageView_Window::onPropertyPanelShown (bool isToggled)
{
  if (!isToggled)
    return;

  updatePropertyPanelBySelection();
}

// =======================================================================
// function : onPropertyViewDataChanged
// purpose :
// =======================================================================
void MessageView_Window::onPropertyViewDataChanged()
{
  QItemSelectionModel* aModel = myTreeView->selectionModel();
  if (!aModel)
    return;
  QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0);
  TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
  if (!anItemBase)
    return;

  updatePropertyPanelBySelection();
  updatePreviewPresentation();
}

// =======================================================================
// function : onHeaderResized
// purpose :
// =======================================================================
void MessageView_Window::onHeaderResized (int theSectionId, int, int)
{
  TreeModel_ModelBase* aViewModel = dynamic_cast<TreeModel_ModelBase*> (myTreeView->model());

  TreeModel_HeaderSection* aSection = aViewModel->ChangeHeaderItem (theSectionId);
  aSection->SetWidth (myTreeView->columnWidth (theSectionId));
}

// =======================================================================
// function : onEraseAllPerformed
// purpose :
// =======================================================================
void MessageView_Window::onEraseAllPerformed()
{
  MessageModel_TreeModel* aTreeModel = dynamic_cast<MessageModel_TreeModel*> (myTreeView->model());

  aTreeModel->Reset();
  aTreeModel->EmitLayoutChanged();
}

// =======================================================================
// function : onExportReport
// purpose :
// =======================================================================
void MessageView_Window::onExportReport()
{
  QItemSelectionModel* aModel = myTreeView->selectionModel();
  if (!aModel)
    return;
  QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0);
  TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
  if (!anItemBase)
    return;
  MessageModel_ItemReportPtr aReportItem = itemDynamicCast<MessageModel_ItemReport>(anItemBase);
  if (!aReportItem)
    return;

  QString aFilter (tr ("Document file (*.json *)"));
  QString aSelectedFilter;
  QString aFileName = QFileDialog::getSaveFileName (0, tr ("Export report to file"), QString(), aFilter, &aSelectedFilter);

  Handle(Message_Report) aReport = aReportItem->GetReport();
  Standard_SStream aStream;
  aReport->DumpJson(aStream);

  QFile aLogFile(aFileName);
  if (!aLogFile.open(QFile::WriteOnly | QFile::Text))
  {
    return;
  }
  QTextStream anOut( &aLogFile );
  anOut << Standard_Dump::FormatJson (aStream).ToCString();
  aLogFile.close();
}

// =======================================================================
// function : onCreateDefaultReport
// purpose :
// =======================================================================
void MessageView_Window::onCreateDefaultReport()
{
  if (!Message::DefaultReport().IsNull())
  {
    return;
  }

  addReport (Message::DefaultReport (Standard_True));
}

// =======================================================================
// function : onPreviewChildren
// purpose :
// =======================================================================
void MessageView_Window::onPreviewChildren()
{
  QItemSelectionModel* aModel = myTreeView->selectionModel();
  if (!aModel)
    return;

  QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes();
  NCollection_List<Handle(Standard_Transient)> aPresentations;
  TreeModel_ModelBase::SubItemsPresentations (aSelectedIndices, aPresentations);

  displayer()->UpdatePreview (View_DisplayActionType_DisplayId, aPresentations);
}

// =======================================================================
// function : onMetricStatistic
// purpose :
// =======================================================================
void MessageView_Window::onMetricStatistic()
{
  QItemSelectionModel* aModel = myTreeView->selectionModel();
  if (!aModel)
  {
    return;
  }

  QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0);
  TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
  if (!anItemBase)
  {
    return;
  }

  MessageView_MetricStatisticModel* aUnitByNameModel = new MessageView_MetricStatisticModel (Message_MetricType_WallClock, myCustomView);
  aUnitByNameModel->Init (anItemBase);
  myCustomView->setModel (aUnitByNameModel);
}

// =======================================================================
// function : addActivateMetricActions
// purpose :
// =======================================================================
void MessageView_Window::addActivateMetricActions (QMenu* theMenu)
{
  Handle(Message_Report) aReport = Message::DefaultReport();
  if (aReport.IsNull())
  {
    return;
  }

  QMenu* aSubMenu = new QMenu ("Activate metric");
  for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++)
  {
    Message_MetricType aMetricType = (Message_MetricType)aMetricId;
    QAction* anAction = ViewControl_Tools::CreateAction (Message::MetricToString (aMetricType),
      SLOT (OnActivateMetric()), parent(), this);
    anAction->setCheckable (true);
    anAction->setChecked (aReport->ActiveMetrics().Contains (aMetricType));
    aSubMenu->addAction (anAction);
  }
  aSubMenu->addSeparator();
  aSubMenu->addAction (ViewControl_Tools::CreateAction ("Deactivate all", SLOT (OnDeactivateAllMetrics()), parent(), this));

  theMenu->addMenu (aSubMenu);
}

// =======================================================================
// function : OnActivateMetric
// purpose :
// =======================================================================
void MessageView_Window::OnActivateMetric()
{
  QAction* anAction = (QAction*)(sender());

  Message_MetricType aMetricType;
  if (!Message::MetricFromString (anAction->text().toStdString().c_str(), aMetricType))
    return;

  Handle(Message_Report) aReport = Message::DefaultReport();
  const NCollection_IndexedMap<Message_MetricType>& anActiveMetrics = aReport->ActiveMetrics();
  aReport->SetActiveMetric (aMetricType, !anActiveMetrics.Contains (aMetricType));

  updateVisibleColumns();
}

// =======================================================================
// function : OnDeactivateAllMetrics
// purpose :
// =======================================================================
void MessageView_Window::OnDeactivateAllMetrics()
{
  Handle(Message_Report) aReport = Message::DefaultReport();
  if (aReport.IsNull())
    return;
  aReport->ClearMetrics();

  updateVisibleColumns();
}

// =======================================================================
// function : displayer
// purpose :
// =======================================================================
View_Displayer* MessageView_Window::displayer()
{
  return myViewWindow->Displayer();
}

// =======================================================================
// function : updatePropertyPanelBySelection
// purpose :
// =======================================================================
void MessageView_Window::updatePropertyPanelBySelection()
{
  ViewControl_TableModelValues* aTableValues = 0;

  QItemSelectionModel* aModel = myTreeView->selectionModel();
  if (!aModel)
    return;

  QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0);
  TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
  if (anItemBase)
  {
    Handle(TreeModel_ItemProperties) anItemProperties = anItemBase->Properties ();
    if (!anItemProperties.IsNull())
    {
      aTableValues = new ViewControl_TableModelValues();
      aTableValues->SetProperties (anItemProperties);
    }
  }
  myPropertyView->Init (aTableValues);
}

// =======================================================================
// function : updatePreviewPresentation
// purpose :
// =======================================================================
void MessageView_Window::updatePreviewPresentation()
{
  Handle(AIS_InteractiveContext) aContext = myViewWindow->ViewToolBar()->CurrentContext();
  if (aContext.IsNull())
    return;

  NCollection_List<Handle(Standard_Transient)> aPresentations;
  QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes();
  for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++)
  {
    QModelIndex anIndex = *aSelIt;
    if (anIndex.column() != 0)
      continue;

    TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
    if (!anItemBase)
      continue;

    anItemBase->Presentations (aPresentations);
  }

  displayer()->UpdatePreview (View_DisplayActionType_DisplayId, aPresentations);
}

// =======================================================================
// function : updateVisibleColumns
// purpose :
// =======================================================================
void MessageView_Window::updateVisibleColumns()
{
  MessageModel_TreeModel* aViewModel = dynamic_cast<MessageModel_TreeModel*> (myTreeView->model());

  NCollection_IndexedMap<Message_MetricType> anActiveMetrics;
  for (NCollection_List<MessageModel_ReportInformation>::Iterator anIterator (aViewModel->Reports()); anIterator.More(); anIterator.Next())
  {
    Handle(Message_Report) aReport = anIterator.Value().myReport;
    for (NCollection_IndexedMap<Message_MetricType>::Iterator aMetricsIterator (aReport->ActiveMetrics()); aMetricsIterator.More(); aMetricsIterator.Next())
    {
      if (anActiveMetrics.Contains (aMetricsIterator.Value()))
        continue;
      anActiveMetrics.Add (aMetricsIterator.Value());
    }
  }

  for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++)
  {
    Message_MetricType aMetricType = (Message_MetricType)aMetricId;
    QList<int> aMetricColumns;
    aViewModel->GetMetricColumns (aMetricType, aMetricColumns);
    bool isColumnHidden = !anActiveMetrics.Contains (aMetricType);
    for (int i = 0; i < aMetricColumns.size(); i++)
    {
      int aColumnId = aMetricColumns[i];
      myTreeView->setColumnHidden (aColumnId, isColumnHidden);
      TreeModel_HeaderSection* aSection = aViewModel->ChangeHeaderItem (aColumnId);
      aSection->SetIsHidden (isColumnHidden);
    }
  }
}