MVC for tree view
This commit is contained in:
parent
1e2aface5a
commit
83a447f43f
|
@ -30,6 +30,8 @@
|
|||
# include <boost/bind.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include "DocumentModel.h"
|
||||
#include "Application.h"
|
||||
#include "BitmapFactory.h"
|
||||
|
@ -54,8 +56,6 @@ namespace Gui {
|
|||
virtual ~DocumentModelIndex()
|
||||
{ qDeleteAll(childItems); }
|
||||
|
||||
void reset()
|
||||
{ qDeleteAll(childItems); childItems.clear(); }
|
||||
void setParent(DocumentModelIndex* parent)
|
||||
{ parentItem = parent; }
|
||||
DocumentModelIndex *parent() const
|
||||
|
@ -64,7 +64,12 @@ namespace Gui {
|
|||
{ childItems.append(child); child->setParent(this); }
|
||||
void removeChild(int row)
|
||||
{ childItems.removeAt(row); }
|
||||
|
||||
QList<DocumentModelIndex*> removeAll()
|
||||
{
|
||||
QList<DocumentModelIndex*> list = childItems;
|
||||
childItems.clear();
|
||||
return list;
|
||||
}
|
||||
DocumentModelIndex *child(int row)
|
||||
{ return childItems.value(row); }
|
||||
int row() const
|
||||
|
@ -91,11 +96,18 @@ namespace Gui {
|
|||
return Qt::ItemIsSelectable|Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
protected:
|
||||
void reset()
|
||||
{ qDeleteAll(childItems); childItems.clear(); }
|
||||
|
||||
protected:
|
||||
DocumentModelIndex() : parentItem(0) {}
|
||||
DocumentModelIndex *parentItem;
|
||||
QList<DocumentModelIndex*> childItems;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Root node
|
||||
class ApplicationIndex : public DocumentModelIndex
|
||||
{
|
||||
|
@ -104,24 +116,22 @@ namespace Gui {
|
|||
public:
|
||||
ApplicationIndex(){}
|
||||
int findChild(const Gui::Document& d) const;
|
||||
Qt::ItemFlags flags() const
|
||||
{ return Qt::ItemIsEnabled; }
|
||||
QVariant data(int role) const
|
||||
{
|
||||
if (role == Qt::DecorationRole) {
|
||||
return qApp->windowIcon();
|
||||
}
|
||||
else if (role == Qt::DisplayRole) {
|
||||
return DocumentModel::tr("Application");
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
Qt::ItemFlags flags() const;
|
||||
QVariant data(int role) const;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Document nodes
|
||||
class DocumentIndex : public DocumentModelIndex
|
||||
{
|
||||
friend class ViewProviderIndex;
|
||||
TYPESYSTEM_HEADER();
|
||||
static QIcon* documentIcon;
|
||||
typedef boost::unordered_set<ViewProviderIndex*> IndexSet;
|
||||
std::map<const ViewProviderDocumentObject*, IndexSet> vp_nodes;
|
||||
void addToDocument(ViewProviderIndex*);
|
||||
void removeFromDocument(ViewProviderIndex*);
|
||||
|
||||
public:
|
||||
const Gui::Document& d;
|
||||
|
@ -130,30 +140,18 @@ namespace Gui {
|
|||
if (!documentIcon)
|
||||
documentIcon = new QIcon(Gui::BitmapFactory().pixmap("Document"));
|
||||
}
|
||||
int findViewProvider(const ViewProvider&) const;
|
||||
void findViewProviders(const ViewProvider&, QList<ViewProviderIndex*>&) const;
|
||||
QVariant data(int role) const
|
||||
~DocumentIndex()
|
||||
{
|
||||
if (role == Qt::DecorationRole) {
|
||||
return *documentIcon;
|
||||
}
|
||||
else if (role == Qt::DisplayRole) {
|
||||
App::Document* doc = d.getDocument();
|
||||
return QString::fromUtf8(doc->Label.getValue());
|
||||
}
|
||||
else if (role == Qt::FontRole) {
|
||||
Document* doc = Application::Instance->activeDocument();
|
||||
QFont font;
|
||||
font.setBold(doc==&d);
|
||||
QVariant variant;
|
||||
variant.setValue<QFont>(font);
|
||||
return variant;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
qDeleteAll(childItems); childItems.clear();
|
||||
}
|
||||
ViewProviderIndex* cloneViewProvider(const ViewProviderDocumentObject&) const;
|
||||
int rowOfViewProvider(const ViewProviderDocumentObject&) const;
|
||||
void findViewProviders(const ViewProviderDocumentObject&, QList<ViewProviderIndex*>&) const;
|
||||
QVariant data(int role) const;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Object nodes
|
||||
class ViewProviderIndex : public DocumentModelIndex
|
||||
{
|
||||
|
@ -161,31 +159,18 @@ namespace Gui {
|
|||
|
||||
public:
|
||||
const Gui::ViewProviderDocumentObject& v;
|
||||
ViewProviderIndex(const Gui::ViewProviderDocumentObject& v) : v(v){}
|
||||
void findViewProviders(const ViewProvider&, QList<ViewProviderIndex*>&) const;
|
||||
QVariant data(int role) const
|
||||
{
|
||||
if (role == Qt::DecorationRole) {
|
||||
return v.getIcon();
|
||||
}
|
||||
else if (role == Qt::DisplayRole) {
|
||||
App::DocumentObject* obj = v.getObject();
|
||||
return QString::fromUtf8(obj->Label.getValue());
|
||||
}
|
||||
else if (role == Qt::FontRole) {
|
||||
App::DocumentObject* obj = v.getObject();
|
||||
App::DocumentObject* act = obj->getDocument()->getActiveObject();
|
||||
QFont font;
|
||||
font.setBold(obj==act);
|
||||
QVariant variant;
|
||||
variant.setValue<QFont>(font);
|
||||
return variant;
|
||||
}
|
||||
ViewProviderIndex(const Gui::ViewProviderDocumentObject& v, DocumentIndex* d);
|
||||
~ViewProviderIndex();
|
||||
ViewProviderIndex* clone() const;
|
||||
void findViewProviders(const ViewProviderDocumentObject&, QList<ViewProviderIndex*>&) const;
|
||||
QVariant data(int role) const;
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
private:
|
||||
DocumentIndex* d;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
int ApplicationIndex::findChild(const Gui::Document& d) const
|
||||
{
|
||||
int child=0;
|
||||
|
@ -199,9 +184,50 @@ namespace Gui {
|
|||
return -1;
|
||||
}
|
||||
|
||||
Qt::ItemFlags ApplicationIndex::flags() const
|
||||
{
|
||||
return Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
QVariant ApplicationIndex::data(int role) const
|
||||
{
|
||||
if (role == Qt::DecorationRole) {
|
||||
return qApp->windowIcon();
|
||||
}
|
||||
else if (role == Qt::DisplayRole) {
|
||||
return DocumentModel::tr("Application");
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
QIcon* DocumentIndex::documentIcon = 0;
|
||||
|
||||
void DocumentIndex::findViewProviders(const ViewProvider& vp,
|
||||
void DocumentIndex::addToDocument(ViewProviderIndex* vp)
|
||||
{
|
||||
vp_nodes[&vp->v].insert(vp);
|
||||
}
|
||||
|
||||
void DocumentIndex::removeFromDocument(ViewProviderIndex* vp)
|
||||
{
|
||||
vp_nodes[&vp->v].erase(vp);
|
||||
}
|
||||
|
||||
ViewProviderIndex*
|
||||
DocumentIndex::cloneViewProvider(const ViewProviderDocumentObject& vp) const
|
||||
{
|
||||
std::map<const ViewProviderDocumentObject*, boost::unordered_set<ViewProviderIndex*> >::const_iterator it;
|
||||
it = vp_nodes.find(&vp);
|
||||
if (it != vp_nodes.end()) {
|
||||
boost::unordered_set<ViewProviderIndex*>::const_iterator v;
|
||||
v = it->second.begin();
|
||||
return (*v)->clone();
|
||||
}
|
||||
return new ViewProviderIndex(vp, const_cast<DocumentIndex*>(this));
|
||||
}
|
||||
|
||||
void DocumentIndex::findViewProviders(const ViewProviderDocumentObject& vp,
|
||||
QList<ViewProviderIndex*>& index) const
|
||||
{
|
||||
QList<DocumentModelIndex*>::const_iterator it;
|
||||
|
@ -211,7 +237,7 @@ namespace Gui {
|
|||
}
|
||||
}
|
||||
|
||||
int DocumentIndex::findViewProvider(const ViewProvider& vp) const
|
||||
int DocumentIndex::rowOfViewProvider(const ViewProviderDocumentObject& vp) const
|
||||
{
|
||||
QList<DocumentModelIndex*>::const_iterator it;
|
||||
int index=0;
|
||||
|
@ -224,8 +250,52 @@ namespace Gui {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void ViewProviderIndex::findViewProviders(const ViewProvider& vp,
|
||||
QList<ViewProviderIndex*>& index) const
|
||||
QVariant DocumentIndex::data(int role) const
|
||||
{
|
||||
if (role == Qt::DecorationRole) {
|
||||
return *documentIcon;
|
||||
}
|
||||
else if (role == Qt::DisplayRole) {
|
||||
App::Document* doc = d.getDocument();
|
||||
return QString::fromUtf8(doc->Label.getValue());
|
||||
}
|
||||
else if (role == Qt::FontRole) {
|
||||
Document* doc = Application::Instance->activeDocument();
|
||||
QFont font;
|
||||
font.setBold(doc==&d);
|
||||
QVariant variant;
|
||||
variant.setValue<QFont>(font);
|
||||
return variant;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
ViewProviderIndex::ViewProviderIndex(const Gui::ViewProviderDocumentObject& v, DocumentIndex* d)
|
||||
: v(v),d(d)
|
||||
{
|
||||
if (d) d->addToDocument(this);
|
||||
}
|
||||
|
||||
ViewProviderIndex::~ViewProviderIndex()
|
||||
{
|
||||
if (d) d->removeFromDocument(this);
|
||||
}
|
||||
|
||||
ViewProviderIndex* ViewProviderIndex::clone() const
|
||||
{
|
||||
ViewProviderIndex* copy = new ViewProviderIndex(this->v, this->d);
|
||||
for (QList<DocumentModelIndex*>::const_iterator it = childItems.begin(); it != childItems.end(); ++it) {
|
||||
ViewProviderIndex* c = static_cast<ViewProviderIndex*>(*it)->clone();
|
||||
copy->appendChild(c);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
void ViewProviderIndex::findViewProviders(const ViewProviderDocumentObject& vp,
|
||||
QList<ViewProviderIndex*>& index) const
|
||||
{
|
||||
if (&this->v == &vp)
|
||||
index.push_back(const_cast<ViewProviderIndex*>(this));
|
||||
|
@ -236,6 +306,30 @@ namespace Gui {
|
|||
}
|
||||
}
|
||||
|
||||
QVariant ViewProviderIndex::data(int role) const
|
||||
{
|
||||
if (role == Qt::DecorationRole) {
|
||||
return v.getIcon();
|
||||
}
|
||||
else if (role == Qt::DisplayRole) {
|
||||
App::DocumentObject* obj = v.getObject();
|
||||
return QString::fromUtf8(obj->Label.getValue());
|
||||
}
|
||||
else if (role == Qt::FontRole) {
|
||||
App::DocumentObject* obj = v.getObject();
|
||||
App::DocumentObject* act = obj->getDocument()->getActiveObject();
|
||||
QFont font;
|
||||
font.setBold(obj==act);
|
||||
QVariant variant;
|
||||
variant.setValue<QFont>(font);
|
||||
return variant;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Gui::DocumentModelIndex, Base::BaseClass);
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Gui::ApplicationIndex,Gui::DocumentModelIndex);
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Gui::DocumentIndex, Gui::DocumentModelIndex);
|
||||
|
@ -350,7 +444,7 @@ void DocumentModel::slotNewObject(const Gui::ViewProviderDocumentObject& obj)
|
|||
QModelIndex parent = createIndex(index->row(),0,index);
|
||||
int count_obj = index->childCount();
|
||||
beginInsertRows(parent, count_obj, count_obj);
|
||||
index->appendChild(new ViewProviderIndex(obj));
|
||||
index->appendChild(new ViewProviderIndex(obj, index));
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
|
@ -399,35 +493,47 @@ void DocumentModel::slotChangeObject(const Gui::ViewProviderDocumentObject& obj,
|
|||
else if (isPropertyLink(Prop)) {
|
||||
App::Document* doc = fea->getDocument();
|
||||
Gui::Document* gdc = Application::Instance->getDocument(doc);
|
||||
std::vector<ViewProviderDocumentObject*> views = getLinkedObjects(*gdc, Prop);
|
||||
std::vector<ViewProviderDocumentObject*> views = claimChildren(*gdc, obj);
|
||||
|
||||
int row = d->rootItem->findChild(*gdc);
|
||||
if (row > -1) {
|
||||
QList<DocumentModelIndex*> del_items;
|
||||
DocumentIndex* doc_index = static_cast<DocumentIndex*>(d->rootItem->child(row));
|
||||
QList<ViewProviderIndex*> obj_index;
|
||||
doc_index->findViewProviders(obj, obj_index);
|
||||
|
||||
// remove from top level in document
|
||||
for (std::vector<ViewProviderDocumentObject*>::iterator vp = views.begin(); vp != views.end(); ++vp) {
|
||||
int row = doc_index->findViewProvider(**vp);
|
||||
int row = doc_index->rowOfViewProvider(**vp);
|
||||
// is it a top-level child in the document
|
||||
if (row >= 0) {
|
||||
DocumentModelIndex* child = doc_index->child(row);
|
||||
del_items.push_back(child);
|
||||
QModelIndex parent = createIndex(doc_index->row(), 0, doc_index);
|
||||
beginRemoveRows(parent, row, row);
|
||||
doc_index->removeChild(row);
|
||||
delete child;
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
// get all occurrences of the view provider in the tree structure
|
||||
QList<ViewProviderIndex*> obj_index;
|
||||
doc_index->findViewProviders(obj, obj_index);
|
||||
for (QList<ViewProviderIndex*>::iterator it = obj_index.begin(); it != obj_index.end(); ++it) {
|
||||
QModelIndex parent = createIndex((*it)->row(),0,*it);
|
||||
int count_obj = (*it)->childCount();
|
||||
beginInsertRows(parent, count_obj, count_obj + (int)views.size());
|
||||
for (std::vector<ViewProviderDocumentObject*>::iterator jt = views.begin(); jt != views.end(); ++jt)
|
||||
(*it)->appendChild(new ViewProviderIndex(**jt));
|
||||
beginRemoveRows(parent, 0, count_obj);
|
||||
// remove all children but do not yet delete them
|
||||
QList<DocumentModelIndex*> items = (*it)->removeAll();
|
||||
endRemoveRows();
|
||||
|
||||
beginInsertRows(parent, 0, (int)views.size());
|
||||
for (std::vector<ViewProviderDocumentObject*>::iterator vp = views.begin(); vp != views.end(); ++vp) {
|
||||
ViewProviderIndex* clone = doc_index->cloneViewProvider(**vp);
|
||||
(*it)->appendChild(clone);
|
||||
}
|
||||
endInsertRows();
|
||||
|
||||
del_items.append(items);
|
||||
}
|
||||
|
||||
qDeleteAll(del_items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -461,33 +567,27 @@ bool DocumentModel::isPropertyLink(const App::Property& prop) const
|
|||
{
|
||||
if (prop.isDerivedFrom(App::PropertyLink::getClassTypeId()))
|
||||
return true;
|
||||
if (prop.isDerivedFrom(App::PropertyLinkSub::getClassTypeId()))
|
||||
return true;
|
||||
if (prop.isDerivedFrom(App::PropertyLinkList::getClassTypeId()))
|
||||
return true;
|
||||
if (prop.isDerivedFrom(App::PropertyLinkSubList::getClassTypeId()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<ViewProviderDocumentObject*>
|
||||
DocumentModel::getLinkedObjects(const Gui::Document& doc, const App::Property& prop) const
|
||||
DocumentModel::claimChildren(const Gui::Document& doc, const ViewProviderDocumentObject& obj) const
|
||||
{
|
||||
std::vector<ViewProviderDocumentObject*> links;
|
||||
if (prop.isDerivedFrom(App::PropertyLink::getClassTypeId())) {
|
||||
App::DocumentObject* obj;
|
||||
obj = static_cast<const App::PropertyLink&>(prop).getValue();
|
||||
ViewProvider* view = doc.getViewProvider(obj);
|
||||
std::vector<ViewProviderDocumentObject*> views;
|
||||
std::vector<App::DocumentObject*> childs = obj.claimChildren();
|
||||
for (std::vector<App::DocumentObject*>::iterator it = childs.begin(); it != childs.end(); ++it) {
|
||||
ViewProvider* view = doc.getViewProvider(*it);
|
||||
if (view && view->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
|
||||
links.push_back(static_cast<ViewProviderDocumentObject*>(view));
|
||||
}
|
||||
else if (prop.isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
|
||||
const std::vector<App::DocumentObject*>& refs = static_cast
|
||||
<const App::PropertyLinkList&>(prop).getValues();
|
||||
for (std::vector<App::DocumentObject*>::const_iterator it = refs.begin();it != refs.end(); ++it) {
|
||||
ViewProvider* view = doc.getViewProvider(*it);
|
||||
if (view && view->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
|
||||
links.push_back(static_cast<ViewProviderDocumentObject*>(view));
|
||||
}
|
||||
views.push_back(static_cast<ViewProviderDocumentObject*>(view));
|
||||
}
|
||||
|
||||
return links;
|
||||
return views;
|
||||
}
|
||||
|
||||
int DocumentModel::columnCount (const QModelIndex & /*parent*/) const
|
||||
|
|
|
@ -67,8 +67,8 @@ private:
|
|||
|
||||
const Document* getDocument(const QModelIndex&) const;
|
||||
bool isPropertyLink(const App::Property&) const;
|
||||
std::vector<ViewProviderDocumentObject*> getLinkedObjects
|
||||
(const Gui::Document&, const App::Property&) const;
|
||||
std::vector<ViewProviderDocumentObject*> claimChildren
|
||||
(const Document&, const ViewProviderDocumentObject&) const;
|
||||
|
||||
private:
|
||||
struct DocumentModelP *d;
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#include "Workbench.h"
|
||||
#include <Gui/MenuManager.h>
|
||||
#include <Gui/ToolBarManager.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/DockWindow.h>
|
||||
#include <Gui/DockWindowManager.h>
|
||||
#include <Gui/TreeView.h>
|
||||
|
||||
using namespace SandboxGui;
|
||||
|
||||
|
@ -44,6 +48,24 @@ TYPESYSTEM_SOURCE(SandboxGui::Workbench, Gui::StdWorkbench)
|
|||
|
||||
Workbench::Workbench()
|
||||
{
|
||||
// Tree view
|
||||
Gui::DockWindow* tree = new Gui::DockWindow(0, Gui::getMainWindow());
|
||||
tree->setWindowTitle(QString::fromAscii("Tree view"));
|
||||
Gui::TreeView* treeWidget = new Gui::TreeView(tree);
|
||||
treeWidget->setRootIsDecorated(false);
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/TreeView");
|
||||
treeWidget->setIndentation(hGrp->GetInt("Indentation", treeWidget->indentation()));
|
||||
|
||||
QGridLayout* pLayout = new QGridLayout(tree);
|
||||
pLayout->setSpacing(0);
|
||||
pLayout->setMargin (0);
|
||||
pLayout->addWidget(treeWidget, 0, 0);
|
||||
|
||||
tree->setObjectName
|
||||
(QString::fromAscii(QT_TRANSLATE_NOOP("QDockWidget","Tree view (MVC)")));
|
||||
tree->setMinimumWidth(210);
|
||||
Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance();
|
||||
pDockMgr->registerDockWindow("Std_TreeViewMVC", tree);
|
||||
}
|
||||
|
||||
Workbench::~Workbench()
|
||||
|
@ -109,6 +131,14 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
Gui::DockWindowItems* Workbench::setupDockWindows() const
|
||||
{
|
||||
Gui::DockWindowItems* root = Gui::StdWorkbench::setupDockWindows();
|
||||
root->setVisibility(false); // hide all dock windows by default
|
||||
root->addDockWidget("Std_TreeViewMVC", Qt::RightDockWidgetArea, true, true);
|
||||
return root;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ protected:
|
|||
Gui::MenuItem* setupMenuBar() const;
|
||||
Gui::ToolBarItem* setupToolBars() const;
|
||||
Gui::ToolBarItem* setupCommandBars() const;
|
||||
Gui::DockWindowItems* setupDockWindows() const;
|
||||
};
|
||||
|
||||
class SoWidgetShape : public SoShape {
|
||||
|
|
Loading…
Reference in New Issue
Block a user