Commit 51d82b42 authored by David Thompson's avatar David Thompson

Make qtResourceBrowser more useful as a standalone widget.

+ Allow a subclassed qtDescriptivePhraseModel instance to be passed to
  its constructor.
+ Make the ParaView-specific visibility decorator available for other
  ParaView plugins to use.
+ Expose the qtResourceBrowser's QTreeView.
+ Move most of pqSMTKResourcePanel into qtResourceBrowser (Qt parts) and
  pqSMTKResourceBrowser (ParaView parts).
  This will allow easier customization, and particularly
  allows people to use the widget without it being central to
  a dock widget, making it simpler to configure components in
  the widget that are needed at construction time.
+ Also, make pqSMTKResourcePanel::Internal::m_phraseModel point to
  the base class (PhraseModel) rather than the particular subclass
  we use (ResourcePhraseModel).
+ Better nullptr testing to prevent crashes when invalid QModelIndex values
  are used.
+ Test whether the model passed to qtDescriptivePhraseDelegate::editorEvent
  is a QAbstractItemModel such as QSortFilterProxyModel; if it is, then map
  the index.
+ Store descriptive phrase pointers in QVariants and provide a way to
  obtain phrase pointers from a QModelIndex without access to the
  underlying QAbstractItemModel.
  This allows clean separation between our QAbstractItemModel subclass
  and classes that consume its QModelIndex instances.
  The separation makes it possible to pass a QAbstractProxyModel to
  use instead of a qtDescriptivePhraseModel so that searching can
  be exposed in the GUI.
parent c07c2eba
......@@ -36,10 +36,11 @@ set(PQComponentsSrcs
pqSMTKPipelineSelectionBehavior.cxx
pqSMTKRegisterImportersBehavior.cxx
pqSMTKResource.cxx
pqSMTKResourceBrowser.cxx
pqSMTKResourcePanel.cxx
pqSMTKSaveResourceBehavior.cxx
pqSMTKSelectionFilterBehavior.cxx
pqSMTKWrapper.cxx
pqSMTKResourcePanel.cxx
)
set(PQComponentsHeaders
......@@ -58,10 +59,11 @@ set(PQComponentsHeaders
pqSMTKPipelineSelectionBehavior.h
pqSMTKRegisterImportersBehavior.h
pqSMTKResource.h
pqSMTKResourceBrowser.h
pqSMTKResourcePanel.h
pqSMTKSaveResourceBehavior.h
pqSMTKSelectionFilterBehavior.h
pqSMTKWrapper.h
pqSMTKResourcePanel.h
)
set(PQComponentsUIs
......
//=========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#ifndef smtk_extension_paraview_appcomponents_pqSMTKResourceBrowser_h
#define smtk_extension_paraview_appcomponents_pqSMTKResourceBrowser_h
#include "smtk/extension/paraview/appcomponents/Exports.h"
#include "smtk/extension/qt/qtResourceBrowser.h"
#include "smtk/view/VisibilityContent.h"
#include "smtk/PublicPointerDefs.h"
#include <QDockWidget>
class QAbstractItemModel;
class QItemSelection;
class pqSMTKResource;
class pqSMTKWrapper;
class pqRepresentation;
class pqServer;
class pqView;
/**\brief A widget that displays SMTK resources available to the application/user.
*
* This adds the following functionality to the qtResourceBrowser:
* + Phrases related to resources and components will be decorated with an
* eyeball icon for controlling their visibility in the active ParaView view.
* + The highlight on hover setting is controlled by a ParaView setting.
* + The smtk PhraseModel used to populate the widget is connected-to and
* disconnected-from resource managers as client-server connections are
* made and broken.
*/
class SMTKPQCOMPONENTSEXT_EXPORT pqSMTKResourceBrowser : public smtk::extension::qtResourceBrowser
{
Q_OBJECT
typedef smtk::extension::qtResourceBrowser Superclass;
public:
pqSMTKResourceBrowser(
const smtk::view::PhraseModelPtr& phraseModel = smtk::view::PhraseModelPtr(),
const std::string& modelViewName = "", QAbstractItemModel* model = nullptr,
QWidget* parent = nullptr);
~pqSMTKResourceBrowser() override;
/// This method may be used by other ParaView plugins that wish to expose
/// per-active-view visibility decorations on qtResourceBrowser widgets.
static int panelPhraseDecorator(smtk::view::VisibilityContent::Query qq, int val,
smtk::view::ConstPhraseContentPtr data, std::map<smtk::common::UUID, int>& visibleThings);
protected slots:
virtual void searchTextChanged(const QString& searchText);
virtual void resourceManagerAdded(pqSMTKWrapper* mgr, pqServer* server);
virtual void resourceManagerRemoved(pqSMTKWrapper* mgr, pqServer* server);
/// Used to update phrase model with new visibility info for the active view.
virtual void activeViewChanged(pqView*);
/// Used to keep list of resource representations in active view up-to-date.
virtual void representationAddedToActiveView(pqRepresentation*);
virtual void representationRemovedFromActiveView(pqRepresentation*);
/// Used to listen for self and others making changes to component visibilities in active view's representations.
virtual void componentVisibilityChanged(smtk::resource::ComponentPtr comp, bool visible);
/// Called when vtkSMTKSettings is modified, indicating highlight-on-hover behavior may change.
virtual void updateSettings();
};
#endif // smtk_extension_paraview_appcomponents_pqSMTKResourceBrowser_h
......@@ -7,20 +7,14 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#include "smtk/extension/paraview/appcomponents/Exports.h"
#ifndef smtk_extension_paraview_appcomponents_pqSMTKResourcePanel_h
#define smtk_extension_paraview_appcomponents_pqSMTKResourcePanel_h
#include "smtk/PublicPointerDefs.h"
#include "smtk/extension/paraview/appcomponents/pqSMTKResourceBrowser.h"
#include <QDockWidget>
class QItemSelection;
class pqSMTKResource;
class pqSMTKWrapper;
class pqRepresentation;
class pqServer;
class pqView;
class pqSMTKResourceBrowser;
/**\brief A panel that displays SMTK resources available to the application/user.
*
......@@ -34,26 +28,8 @@ public:
pqSMTKResourcePanel(QWidget* parent = nullptr);
~pqSMTKResourcePanel() override;
protected slots:
virtual void searchTextChanged(const QString& searchText);
virtual void resourceManagerAdded(pqSMTKWrapper* mgr, pqServer* server);
virtual void resourceManagerRemoved(pqSMTKWrapper* mgr, pqServer* server);
/// Used to update phrase model with new visibility info for the active view.
virtual void activeViewChanged(pqView*);
/// Used to keep list of resource representations in active view up-to-date.
virtual void representationAddedToActiveView(pqRepresentation*);
virtual void representationRemovedFromActiveView(pqRepresentation*);
/// Used to listen for self and others making changes to component visibilities in active view's representations.
virtual void componentVisibilityChanged(smtk::resource::ComponentPtr comp, bool visible);
/// Called when vtkSMTKSettings is modified, indicating highlight-on-hover behavior may change.
virtual void updateSettings();
protected:
class Internal;
Internal* m_p;
pqSMTKResourceBrowser* m_browser;
};
#endif // smtk_extension_paraview_appcomponents_pqSMTKResourcePanel_h
......@@ -22,6 +22,7 @@ set(QAttrLibSrcs
qtReferenceItem.cxx
qtResourceItem.cxx
qtResourceBrowser.cxx
qtResourceBrowserP.cxx
qtOperationLauncher.cxx
qtOperationView.cxx
#qtModelView.cxx
......@@ -118,13 +119,15 @@ set(QAttrLibMocHeaders
set(QAttrLibHeaders
${QAttrLibMocHeaders}
RedirectOutput.h
qtDirectoryItem.h
qtDoubleItem.h
qtIntItem.h
qtResourceBrowserP.h
qtSMTKUtilities.h
qtStringItem.h
qtTypeDeclarations.h
qtViewInterface.h
qtSMTKUtilities.h
RedirectOutput.h
)
#install the headers
......
......@@ -107,7 +107,7 @@ void ModelBrowser::addToGroup()
// Only keep the phrase alive as long as we must.
{
DescriptivePhrasePtr phrase = m_p->qmodel->getItem(qidx);
auto phrase = qidx.data(smtk::extension::qtDescriptivePhraseModel::PhrasePtrRole).value<DescriptivePhrasePtr>();
if (!phrase)
return;
......@@ -136,7 +136,7 @@ void ModelBrowser::removeFromGroup()
{
EntityRef relEnt;
{
DescriptivePhrasePtr phrase = m_p->qmodel->getItem(qidx);
auto phrase = qidx.data(smtk::extension::qtDescriptivePhraseModel::PhrasePtrRole).value<DescriptivePhrasePtr>();
if (phrase)
relEnt = phrase->relatedEntity();
}
......@@ -202,7 +202,7 @@ smtk::model::Group ModelBrowser::groupParentOfIndex(const QModelIndex& qidx)
(void)qidx;
smtk::model::Group group;
/*
DescriptivePhrasePtr phrase = m_p->qmodel->getItem(qidx);
auto phrase = qidx.data(smtk::extension::qtDescriptivePhraseModel::PhrasePtrRole).value<DescriptivePhrasePtr>();
if (phrase)
{
EntityPhrasePtr ephrase = smtk::dynamic_pointer_cast<EntityPhrase>(phrase);
......
......@@ -12,6 +12,7 @@
#include "smtk/extension/qt/qtDescriptivePhraseEditor.h"
#include "smtk/extension/qt/qtDescriptivePhraseModel.h"
#include <QAbstractProxyModel>
#include <QApplication>
#include <QMouseEvent>
#include <QPainter>
......@@ -363,9 +364,8 @@ bool qtDescriptivePhraseDelegate::eventFilter(QObject* editor, QEvent* evt)
return QStyledItemDelegate::eventFilter(editor, evt);
}
std::string qtDescriptivePhraseDelegate::determineAction(const QPoint& pPos, const QModelIndex& idx,
const QStyleOptionViewItem& option,
const smtk::extension::qtDescriptivePhraseModel* entityMod) const
std::string qtDescriptivePhraseDelegate::determineAction(
const QPoint& pPos, const QModelIndex& idx, const QStyleOptionViewItem& option) const
{
std::string res;
if (m_visibilityMode)
......@@ -386,7 +386,7 @@ std::string qtDescriptivePhraseDelegate::determineAction(const QPoint& pPos, con
bvis = px > option.rect.left() && px < (option.rect.left() + visiconsize.width()) &&
py > option.rect.top() && py < (option.rect.top() + option.rect.height());
}
if (!bvis && entityMod && entityMod->getItem(idx)->isRelatedColorMutable())
if (!bvis && idx.data(qtDescriptivePhraseModel::ColorMutableRole).toBool())
{
bcolor = px > (option.rect.left() + visiconsize.width() + 2) &&
px < (option.rect.left() + visiconsize.width() + 2 + m_swatchSize) &&
......@@ -418,10 +418,8 @@ bool qtDescriptivePhraseDelegate::editorEvent(
return res;
}
// pass in qComponentItemModel for mutability check
smtk::extension::qtDescriptivePhraseModel* entityMod =
dynamic_cast<smtk::extension::qtDescriptivePhraseModel*>(mod);
std::string whichIcon = this->determineAction(e->pos(), idx, option, entityMod);
std::string whichIcon;
whichIcon = this->determineAction(e->pos(), idx, option);
if (whichIcon == "visible")
{
......
......@@ -80,9 +80,8 @@ public:
// return which icon the Point position is on
// 'visible', 'color', or empty string;
std::string determineAction(const QPoint& pPos, const QModelIndex& idx,
const QStyleOptionViewItem& option,
const smtk::extension::qtDescriptivePhraseModel* entityMod = nullptr) const;
std::string determineAction(
const QPoint& pPos, const QModelIndex& idx, const QStyleOptionViewItem& option) const;
protected:
bool eventFilter(QObject* editor, QEvent* event) override;
......
......@@ -10,6 +10,7 @@
#include "smtk/extension/qt/qtDescriptivePhraseModel.h"
#include "smtk/extension/qt/qtActiveObjects.h"
#include "smtk/extension/qt/qtTypeDeclarations.h"
#include "smtk/view/DescriptivePhrase.h"
#include "smtk/view/PhraseModel.h"
......@@ -264,7 +265,13 @@ QVariant qtDescriptivePhraseModel::data(const QModelIndex& idx, int role) const
view::DescriptivePhrasePtr item = this->getItem(idx);
if (item)
{
if (role == TitleTextRole || role == Qt::DisplayRole)
if (role == PhrasePtrRole)
{
QVariant result;
result.setValue(item);
return result;
}
else if (role == TitleTextRole || role == Qt::DisplayRole)
{
return QVariant(item->title().c_str());
}
......@@ -731,7 +738,7 @@ Qt::DropActions qtDescriptivePhraseModel::supportedDropActions() const
void qtDescriptivePhraseModel::toggleVisibility(const QModelIndex& idx)
{
auto phrase = this->getItem(idx);
auto phrase = idx.data(PhrasePtrRole).value<smtk::view::DescriptivePhrase::Ptr>();
if (!phrase)
{
smtkErrorMacro(
......@@ -747,7 +754,7 @@ void qtDescriptivePhraseModel::toggleVisibility(const QModelIndex& idx)
void qtDescriptivePhraseModel::editColor(const QModelIndex& idx)
{
auto phrase = this->getItem(idx);
auto phrase = idx.data(PhrasePtrRole).value<smtk::view::DescriptivePhrase::Ptr>();
if (!phrase)
{
smtkErrorMacro(
......
......@@ -66,7 +66,8 @@ public:
PhraseCleanRole = Qt::UserRole + 105, //!< Is resource clean (0), dirty (1), or N/A (-1)?
ModelActiveRole = Qt::UserRole + 106, //!< Is resource the active resource?
TitleTextMutableRole = Qt::UserRole + 107, //!< Is the title editable?
ColorMutableRole = Qt::UserRole + 108 //!< Is the subject's color editable?
ColorMutableRole = Qt::UserRole + 108, //!< Is the subject's color editable?
PhrasePtrRole = Qt::UserRole + 109 //!< Grab the whole descriptive phrase!
};
void setPhraseModel(smtk::view::PhraseModelPtr model);
......@@ -134,6 +135,7 @@ protected:
/**\brief Iterate over all expanded entries in the tree.
*
* Note that if you call this method, you must include "smtk/extension/qt/qtTypeDeclarations.h".
*/
template <typename T, typename C>
bool qtDescriptivePhraseModel::foreach_phrase(
......@@ -142,7 +144,8 @@ bool qtDescriptivePhraseModel::foreach_phrase(
// visit parent, then children if we aren't told to terminate:
if (!visitor(this, top, collector))
{
view::DescriptivePhrasePtr phrase = this->getItem(top);
view::DescriptivePhrasePtr phrase =
top.data(PhrasePtrRole).value<smtk::view::DescriptivePhrasePtr>();
// Do not descend if top's corresponding phrase would have to invoke
// the subphrase generator to obtain the list of children... some phrases
// are cyclic graphs. In these cases, only descend if "onlyBuilt" is false.
......@@ -166,7 +169,8 @@ bool qtDescriptivePhraseModel::foreach_phrase(
// visit parent, then children if we aren't told to terminate:
if (!visitor(this, top, collector))
{
view::DescriptivePhrasePtr phrase = this->getItem(top);
view::DescriptivePhrasePtr phrase =
top.data(PhrasePtrRole).value<smtk::view::DescriptivePhrasePtr>();
// Do not descend if top's corresponding phrase would have to invoke
// the subphrase generator to obtain the list of children... some models
// are cyclic graphs. In these cases, only descend if "onlyBuilt" is false.
......
......@@ -12,6 +12,7 @@
#include "smtk/extension/qt/qtBaseView.h"
#include "smtk/extension/qt/qtOverlay.h"
#include "smtk/extension/qt/qtTypeDeclarations.h"
#include "smtk/extension/qt/qtUIManager.h"
#include "smtk/view/ComponentPhraseModel.h"
......@@ -681,7 +682,9 @@ bool qtReferenceItem::eventFilter(QObject* src, QEvent* event)
void qtReferenceItem::toggleCurrentItem()
{
auto cphr = m_p->m_qtModel->getItem(m_p->m_popupList->currentIndex());
auto cphr = m_p->m_popupList->currentIndex()
.data(smtk::extension::qtDescriptivePhraseModel::PhrasePtrRole)
.value<smtk::view::DescriptivePhrasePtr>();
if (cphr)
{
auto currentMembership = cphr->relatedVisibility();
......@@ -772,7 +775,8 @@ void qtReferenceItem::checkRemovedComponents(smtk::view::DescriptivePhrasePtr ph
for (auto ref : refs)
{
auto ridx = m_p->m_qtModel->index(ref, 0, qidx);
auto rphr = m_p->m_qtModel->getItem(ridx);
auto rphr = ridx.data(smtk::extension::qtDescriptivePhraseModel::PhrasePtrRole)
.value<smtk::view::DescriptivePhrasePtr>();
auto comp = rphr ? rphr->relatedComponent() : nullptr;
auto rsrc = rphr ? rphr->relatedResource() : nullptr;
if (comp && m_p->m_members.find(comp) != m_p->m_members.end())
......
......@@ -29,103 +29,24 @@
#include "smtk/resource/Manager.h"
#include "smtk/resource/Resource.h"
// #include "ui_qtResourceBrowser.h"
#include <QAbstractProxyModel>
#include <QColorDialog>
#include <QItemSelection>
#include <QItemSelectionModel>
#include <QPointer>
#include <QTreeView>
using namespace smtk::extension;
using qtDescriptivePhraseModel = smtk::extension::qtDescriptivePhraseModel;
class qtResourceBrowser::Internal // : public Ui::qtResourceBrowser
{
public:
Internal()
: m_selnSource("resource panel")
, m_selnLabel("selected")
, m_hoverLabel("hovered")
, m_resourceTreeStyle(-1)
, m_updatingPanelSelectionFromSMTK(false)
{
}
~Internal()
{
// Unregister our decorator before we become invalid.
m_phraseModel->setDecorator([](smtk::view::DescriptivePhrasePtr) {});
}
#include "smtk/extension/qt/qtResourceBrowserP.h"
#include "smtk/extension/qt/qtTypeDeclarations.h"
void setup(::qtResourceBrowser* parent, const std::string& viewName)
{
parent->setWindowTitle("Resources");
auto viewMap = qtSMTKUtilities::modelViewConstructors();
auto vcit = viewMap.find(viewName);
if (vcit == viewMap.end())
{
vcit = viewMap.find(""); // The default constructor.
}
qtModelViewConstructor ctor = vcit->second;
if (!ctor)
{
ctor = qtResourceBrowser::createDefaultView;
}
m_layout = new QVBoxLayout(parent);
m_layout->setObjectName("m_layout");
m_view = ctor(parent);
m_layout->addWidget(m_view);
m_phraseModel = smtk::view::ResourcePhraseModel::create();
m_model = new smtk::extension::qtDescriptivePhraseModel;
m_model->setPhraseModel(m_phraseModel);
m_delegate = new smtk::extension::qtDescriptivePhraseDelegate;
m_delegate->setTextVerticalPad(6);
m_delegate->setTitleFontWeight(1);
m_delegate->setDrawSubtitle(false);
m_view->setModel(m_model);
m_view->setItemDelegate(m_delegate);
m_view->setMouseTracking(true); // Needed to receive hover events.
QObject::connect(m_delegate, SIGNAL(requestVisibilityChange(const QModelIndex&)), m_model,
SLOT(toggleVisibility(const QModelIndex&)));
QObject::connect(m_delegate, SIGNAL(requestColorChange(const QModelIndex&)), parent,
SLOT(editObjectColor(const QModelIndex&)));
QObject::connect(m_view->selectionModel(),
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), parent,
SLOT(sendPanelSelectionToSMTK(const QItemSelection&, const QItemSelection&)));
}
using namespace smtk::extension;
QVBoxLayout* m_layout;
QTreeView* m_view;
QPointer<smtk::extension::qtDescriptivePhraseModel> m_model;
QPointer<smtk::extension::qtDescriptivePhraseDelegate> m_delegate;
std::map<smtk::resource::ManagerPtr, int> m_observers;
smtk::view::PhraseModel::Ptr m_phraseModel;
smtk::view::Selection::Ptr m_seln; // TODO: This assumes there is only 1 server connection
int m_selnHandle; // TODO: Same assumption as m_seln
int m_selnValue;
int m_hoverValue;
std::string m_selnSource; // TODO: This assumes there is only 1 panel (or that all should share)
std::string m_selnLabel;
std::string m_hoverLabel;
std::map<smtk::common::UUID, int> m_visibleThings;
int m_resourceTreeStyle; // Which subphrase generator should be used?
// Set to true when inside sendSMTKSelectionToPanel.
// Used to avoid updating the SMTK selection from the panel while
// the panel is being updated from SMTK:
bool m_updatingPanelSelectionFromSMTK;
};
qtResourceBrowser::qtResourceBrowser(const std::string& viewName, QWidget* parent)
qtResourceBrowser::qtResourceBrowser(const smtk::view::PhraseModelPtr& phraseModel,
const std::string& modelViewName, QAbstractItemModel* qmodel, QWidget* parent)
: Superclass(parent)
{
m_p = new Internal;
m_p->setup(this, viewName);
m_p->setup(this, phraseModel, modelViewName, qmodel, parent);
}
qtResourceBrowser::~qtResourceBrowser()
......@@ -146,6 +67,11 @@ QTreeView* qtResourceBrowser::createDefaultView(QWidget* parent)
return view;
}
QTreeView* qtResourceBrowser::view() const
{
return m_p->m_view;
}
smtk::view::PhraseModelPtr qtResourceBrowser::phraseModel() const
{
return m_p->m_phraseModel;
......@@ -159,22 +85,23 @@ void qtResourceBrowser::setPhraseModel(const smtk::view::PhraseModelPtr& model)
}
m_p->m_phraseModel = model;
// TODO: Is this all we need?
if (m_p->m_phraseModel && m_p->m_model)
auto dpmodel = m_p->descriptivePhraseModel();
if (m_p->m_phraseModel && dpmodel)
{
m_p->m_model->setPhraseModel(m_p->m_phraseModel);
m_p->m_model->rebuildSubphrases(QModelIndex());
dpmodel->setPhraseModel(m_p->m_phraseModel);
dpmodel->rebuildSubphrases(QModelIndex());
}
}
smtk::view::SubphraseGeneratorPtr qtResourceBrowser::phraseGenerator() const
{
auto root = m_p->m_model->getItem(QModelIndex());
auto root = m_p->m_phraseModel ? m_p->m_phraseModel->root() : nullptr;
return root ? root->findDelegate() : nullptr;
}
void qtResourceBrowser::setPhraseGenerator(smtk::view::SubphraseGeneratorPtr spg)
{
auto root = m_p->m_model->getItem(QModelIndex());
auto root = m_p->m_phraseModel ? m_p->m_phraseModel->root() : nullptr;
if (spg)
{
spg->setModel(m_p->m_phraseModel);
......@@ -236,7 +163,8 @@ void qtResourceBrowser::sendPanelSelectionToSMTK(const QItemSelection&, const QI
auto selected = m_p->m_view->selectionModel()->selection();
for (auto qslist : selected.indexes())
{
auto phrase = m_p->m_model->getItem(qslist);
auto phrase = qslist.data(qtDescriptivePhraseModel::PhrasePtrRole)
.value<smtk::view::DescriptivePhrasePtr>();
smtk::resource::Component::Ptr comp;
smtk::resource::Resource::Ptr rsrc;
if (phrase && (comp = phrase->relatedComponent()))
......@@ -262,7 +190,7 @@ void qtResourceBrowser::sendSMTKSelectionToPanel(
return;
}
auto qview = m_p->m_view;
auto qmodel = m_p->m_model;
auto qmodel = m_p->descriptivePhraseModel();
auto root = m_p->m_phraseModel->root();
QItemSelection qseln;
root->visitChildren(
......@@ -280,6 +208,15 @@ void qtResourceBrowser::sendSMTKSelectionToPanel(
return 0;
});
auto smodel = dynamic_cast<QAbstractProxyModel*>(qview->selectionModel()->model());
// If our top-level model is a proxy model, map the selected
// indices from the descriptive phrase space into the proxy's
// space.
if (smodel)
{
qseln = smodel->mapSelectionFromSource(qseln);
}
// Now update the Qt selection, being careful not to trigger SMTK updates:
m_p->m_updatingPanelSelectionFromSMTK = true;
qview->selectionModel()->select(
......@@ -332,7 +269,8 @@ void qtResourceBrowser::hoverRow(const QModelIndex& idx)
this->resetHover(csetAdd, csetDel);
// Discover what is currently hovered
auto phr = m_p->m_model->getItem(idx);
auto phr =
idx.data(qtDescriptivePhraseModel::PhrasePtrRole).value<smtk::view::DescriptivePhrasePtr>();
if (!phr)
{
return;
......@@ -400,7 +338,8 @@ void qtResourceBrowser::resetHover(
void qtResourceBrowser::editObjectColor(const QModelIndex& idx)
{
auto phrase = m_p->m_model->getItem(idx);
auto phrase =
idx.data(qtDescriptivePhraseModel::PhrasePtrRole).value<smtk::view::DescriptivePhrasePtr>();
if (phrase)
{
std::string dialogInstructions = "Choose Color for " +
......
......@@ -7,12 +7,16 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#ifndef smtk_extension_qtResourceBrowser_h
#define smtk_extension_qtResourceBrowser_h
#include "smtk/extension/qt/Exports.h"
#include "smtk/PublicPointerDefs.h"
#include <QWidget>
class QAbstractItemModel;
class QItemSelection;
class QTreeView;
......@@ -21,8 +25,25 @@ namespace smtk
namespace extension
{
class qtDescriptivePhraseModel;
/**\brief A panel that displays SMTK resources available to the application/user.
*
* This is a Qt widget that displays a tree or list view holding an SMTK
* descriptive phrase model.
*
* Its constructor accepts
* (1) an smtk::view::PhraseModel that you have configured,
* (2) the string name registered to a QAbstractItemView subclass constructor,
* (3) a QAbstactItemModel implementing qtDescriptivePhraseModel model index queries, and
* (4) a parent QWidget.
*
* This QAbstractItemModel class should either be a
* qtDescriptivePhraseModel or QAbstractProxyModel whose source is a
* qtDescriptivePhraseModel.
* Because of that, indices from the QAbstractItemModel will provide properties
* that can be used by a qtDescriptivePhraseDelegate instance, which this
* class creates and owns to control how the tree rows are rendered.
*/
class SMTKQTEXT_EXPORT qtResourceBrowser : public QWidget
{
......@@ -30,10 +51,13 @@ class SMTKQTEXT_EXPORT qtResourceBrowser : public QWidget
typedef QWidget Superclass;
public:
qtResourceBrowser(const std::string& viewName = "", QWidget* parent = nullptr);
qtResourceBrowser(const smtk::view::PhraseModelPtr& phraseModel = smtk::view::PhraseModelPtr(),
const std::string& modelViewName = "", QAbstractItemModel* model = nullptr,
QWidget* parent = nullptr);
~qtResourceBrowser() override;
static QTreeView* createDefaultView(QWidget* parent);
QTreeView* view() const;
smtk::view::PhraseModelPtr phraseModel() const;
void setPhraseModel(const smtk::view::PhraseModelPtr&);
......@@ -74,3 +98,4 @@ protected:
};
}
}
#endif // smtk_extension_qtResourceBrowser_h
//=========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#include "smtk/extension/qt/qtResourceBrowserP.h"
#include "smtk/extension/qt/qtDescriptivePhraseDelegate.h"
#include "smtk/extension/qt/qtDescriptivePhraseModel.h"
#include "smtk/extension/qt/qtSMTKUtilities.h"
#include "smtk/view/ResourcePhraseModel.h"
#include "smtk/io/Logger.h"
#include <QAbstractProxyModel>
#include <QMetaObject>
#include <QTreeView>
#include <QVBoxLayout>
using namespace smtk::extension;
qtResourceBrowser::Internal::Internal()
: m_selnSource("resource panel")
, m_selnLabel("selected")
, m_hoverLabel("hovered")
, m_resourceTreeStyle(-1)
, m_updatingPanelSelectionFromSMTK(false)
{
}
qtResourceBrowser::Internal::~Internal()
{
// Unregister our decorator before we become invalid.
m_phraseModel->setDecorator([](smtk::view::DescriptivePhrasePtr) {});
}
void qtResourceBrowser::Internal::setup(qtResourceBrowser* self,
const smtk::view::PhraseModelPtr& phraseModel, const std::string& viewName,
QAbstractItemModel* qmodel, QWidget* parent)
{
m_self = self;
// Keep or create a phrase model to present to users:
m_phraseModel = phraseModel ? phraseModel : smtk::view::ResourcePhraseModel::create();
// Create a QAbstractItemView subclass given viewName:
auto viewMap = qtSMTKUtilities::modelViewConstructors();
auto vcit = viewMap.find(viewName);
if (vcit == viewMap.end())
{
vcit = viewMap.find(""); // The default constructor.
}
qtModelViewConstructor ctor = vcit->second;
if (!ctor)
{
ctor = qtResourceBrowser::createDefaultView;
}
m_layout = new QVBoxLayout(m_self);
m_layout->setObjectName("m_layout");
m_view = ctor(parent);
m_layout->addWidget(m_view);
// Keep or create a QAbstractItemModel subclass (which had better be
// related somehow to a qtDescriptivePhraseModel).