00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <QApplication>
00028 # include <algorithm>
00029 # include <boost/signals.hpp>
00030 # include <boost/bind.hpp>
00031 #endif
00032
00033 #include "DocumentModel.h"
00034 #include "Application.h"
00035 #include "BitmapFactory.h"
00036 #include "Document.h"
00037 #include "ViewProviderDocumentObject.h"
00038 #include <App/Document.h>
00039 #include <App/DocumentObject.h>
00040 #include <App/PropertyLinks.h>
00041
00042 using namespace Gui;
00043
00044 namespace Gui {
00045
00046 class ViewProviderIndex;
00047
00048
00049 class DocumentModelIndex : public Base::BaseClass
00050 {
00051 TYPESYSTEM_HEADER();
00052
00053 public:
00054 virtual ~DocumentModelIndex()
00055 { qDeleteAll(childItems); }
00056
00057 void reset()
00058 { qDeleteAll(childItems); childItems.clear(); }
00059 void setParent(DocumentModelIndex* parent)
00060 { parentItem = parent; }
00061 DocumentModelIndex *parent() const
00062 { return parentItem; }
00063 void appendChild(DocumentModelIndex *child)
00064 { childItems.append(child); child->setParent(this); }
00065 void removeChild(int row)
00066 { childItems.removeAt(row); }
00067
00068 DocumentModelIndex *child(int row)
00069 { return childItems.value(row); }
00070 int row() const
00071 {
00072 if (parentItem)
00073 return parentItem->childItems.indexOf
00074 (const_cast<DocumentModelIndex*>(this));
00075 return 0;
00076 }
00077 int childCount() const
00078 { return childItems.count(); }
00079 virtual QVariant data(int role) const
00080 { return QVariant(); }
00081 virtual bool setData (const QVariant & value, int role)
00082 {
00083 if (role == Qt::EditRole) {
00084 return true;
00085 }
00086
00087 return true;
00088 }
00089 virtual Qt::ItemFlags flags() const
00090 {
00091 return Qt::ItemIsSelectable|Qt::ItemIsEnabled;
00092 }
00093
00094 protected:
00095 DocumentModelIndex() : parentItem(0) {}
00096 DocumentModelIndex *parentItem;
00097 QList<DocumentModelIndex*> childItems;
00098 };
00099
00100 class ApplicationIndex : public DocumentModelIndex
00101 {
00102 TYPESYSTEM_HEADER();
00103
00104 public:
00105 ApplicationIndex(){}
00106 int findChild(const Gui::Document& d) const;
00107 Qt::ItemFlags flags() const
00108 { return Qt::ItemIsEnabled; }
00109 QVariant data(int role) const
00110 {
00111 if (role == Qt::DecorationRole) {
00112 return qApp->windowIcon();
00113 }
00114 else if (role == Qt::DisplayRole) {
00115 return DocumentModel::tr("Application");
00116 }
00117 return QVariant();
00118 }
00119 };
00120
00121 class DocumentIndex : public DocumentModelIndex
00122 {
00123 TYPESYSTEM_HEADER();
00124 static QIcon* documentIcon;
00125
00126 public:
00127 const Gui::Document& d;
00128 DocumentIndex(const Gui::Document& d) : d(d)
00129 {
00130 if (!documentIcon)
00131 documentIcon = new QIcon(Gui::BitmapFactory().pixmap("Document"));
00132 }
00133 int findViewProvider(const ViewProvider&) const;
00134 void findViewProviders(const ViewProvider&, QList<ViewProviderIndex*>&) const;
00135 QVariant data(int role) const
00136 {
00137 if (role == Qt::DecorationRole) {
00138 return *documentIcon;
00139 }
00140 else if (role == Qt::DisplayRole) {
00141 App::Document* doc = d.getDocument();
00142 return QString::fromUtf8(doc->Label.getValue());
00143 }
00144 else if (role == Qt::FontRole) {
00145 Document* doc = Application::Instance->activeDocument();
00146 QFont font;
00147 font.setBold(doc==&d);
00148 QVariant variant;
00149 variant.setValue<QFont>(font);
00150 return variant;
00151 }
00152
00153 return QVariant();
00154 }
00155 };
00156
00157
00158 class ViewProviderIndex : public DocumentModelIndex
00159 {
00160 TYPESYSTEM_HEADER();
00161
00162 public:
00163 const Gui::ViewProviderDocumentObject& v;
00164 ViewProviderIndex(const Gui::ViewProviderDocumentObject& v) : v(v){}
00165 void findViewProviders(const ViewProvider&, QList<ViewProviderIndex*>&) const;
00166 QVariant data(int role) const
00167 {
00168 if (role == Qt::DecorationRole) {
00169 return v.getIcon();
00170 }
00171 else if (role == Qt::DisplayRole) {
00172 App::DocumentObject* obj = v.getObject();
00173 return QString::fromUtf8(obj->Label.getValue());
00174 }
00175 else if (role == Qt::FontRole) {
00176 App::DocumentObject* obj = v.getObject();
00177 App::DocumentObject* act = obj->getDocument()->getActiveObject();
00178 QFont font;
00179 font.setBold(obj==act);
00180 QVariant variant;
00181 variant.setValue<QFont>(font);
00182 return variant;
00183 }
00184
00185 return QVariant();
00186 }
00187 };
00188
00189 int ApplicationIndex::findChild(const Gui::Document& d) const
00190 {
00191 int child=0;
00192 QList<DocumentModelIndex*>::const_iterator it;
00193 for (it = childItems.begin(); it != childItems.end(); ++it, ++child) {
00194 DocumentIndex* doc = static_cast<DocumentIndex*>(*it);
00195 if (&doc->d == &d)
00196 return child;
00197 }
00198
00199 return -1;
00200 }
00201
00202 QIcon* DocumentIndex::documentIcon = 0;
00203
00204 void DocumentIndex::findViewProviders(const ViewProvider& vp,
00205 QList<ViewProviderIndex*>& index) const
00206 {
00207 QList<DocumentModelIndex*>::const_iterator it;
00208 for (it = childItems.begin(); it != childItems.end(); ++it) {
00209 ViewProviderIndex* v = static_cast<ViewProviderIndex*>(*it);
00210 v->findViewProviders(vp, index);
00211 }
00212 }
00213
00214 int DocumentIndex::findViewProvider(const ViewProvider& vp) const
00215 {
00216 QList<DocumentModelIndex*>::const_iterator it;
00217 int index=0;
00218 for (it = childItems.begin(); it != childItems.end(); ++it, ++index) {
00219 ViewProviderIndex* v = static_cast<ViewProviderIndex*>(*it);
00220 if (&v->v == &vp)
00221 return index;
00222 }
00223
00224 return -1;
00225 }
00226
00227 void ViewProviderIndex::findViewProviders(const ViewProvider& vp,
00228 QList<ViewProviderIndex*>& index) const
00229 {
00230 if (&this->v == &vp)
00231 index.push_back(const_cast<ViewProviderIndex*>(this));
00232 QList<DocumentModelIndex*>::const_iterator it;
00233 for (it = childItems.begin(); it != childItems.end(); ++it) {
00234 ViewProviderIndex* v = static_cast<ViewProviderIndex*>(*it);
00235 v->findViewProviders(vp, index);
00236 }
00237 }
00238
00239 TYPESYSTEM_SOURCE_ABSTRACT(Gui::DocumentModelIndex, Base::BaseClass);
00240 TYPESYSTEM_SOURCE_ABSTRACT(Gui::ApplicationIndex,Gui::DocumentModelIndex);
00241 TYPESYSTEM_SOURCE_ABSTRACT(Gui::DocumentIndex, Gui::DocumentModelIndex);
00242 TYPESYSTEM_SOURCE_ABSTRACT(Gui::ViewProviderIndex, Gui::DocumentModelIndex);
00243
00244 struct DocumentModelP
00245 {
00246 DocumentModelP()
00247 { rootItem = new ApplicationIndex(); }
00248 ~DocumentModelP()
00249 { delete rootItem; }
00250 ApplicationIndex *rootItem;
00251 };
00252 }
00253
00254
00255
00256 DocumentModel::DocumentModel(QObject* parent)
00257 : QAbstractItemModel(parent), d(new DocumentModelP)
00258 {
00259 static bool inittype = false;
00260 if (!inittype) {
00261 inittype = true;
00262 DocumentModelIndex ::init();
00263 ApplicationIndex ::init();
00264 DocumentIndex ::init();
00265 ViewProviderIndex ::init();
00266 }
00267
00268
00269 Application::Instance->signalNewDocument.connect(boost::bind(&DocumentModel::slotNewDocument, this, _1));
00270 Application::Instance->signalDeleteDocument.connect(boost::bind(&DocumentModel::slotDeleteDocument, this, _1));
00271 Application::Instance->signalRenameDocument.connect(boost::bind(&DocumentModel::slotRenameDocument, this, _1));
00272 Application::Instance->signalActiveDocument.connect(boost::bind(&DocumentModel::slotActiveDocument, this, _1));
00273 Application::Instance->signalRelabelDocument.connect(boost::bind(&DocumentModel::slotRelabelDocument, this, _1));
00274 }
00275
00276 DocumentModel::~DocumentModel()
00277 {
00278 delete d; d = 0;
00279 }
00280
00281 void DocumentModel::slotNewDocument(const Gui::Document& Doc)
00282 {
00283 Doc.signalNewObject.connect(boost::bind(&DocumentModel::slotNewObject, this, _1));
00284 Doc.signalDeletedObject.connect(boost::bind(&DocumentModel::slotDeleteObject, this, _1));
00285 Doc.signalChangedObject.connect(boost::bind(&DocumentModel::slotChangeObject, this, _1, _2));
00286 Doc.signalRenamedObject.connect(boost::bind(&DocumentModel::slotRenameObject, this, _1));
00287 Doc.signalActivatedObject.connect(boost::bind(&DocumentModel::slotActiveObject, this, _1));
00288 Doc.signalInEdit.connect(boost::bind(&DocumentModel::slotInEdit, this, _1));
00289 Doc.signalResetEdit.connect(boost::bind(&DocumentModel::slotResetEdit, this, _1));
00290
00291 QModelIndex parent = createIndex(0,0,d->rootItem);
00292 int count_docs = d->rootItem->childCount();
00293 beginInsertRows(parent, count_docs, count_docs);
00294 d->rootItem->appendChild(new DocumentIndex(Doc));
00295 endInsertRows();
00296 }
00297
00298 void DocumentModel::slotDeleteDocument(const Gui::Document& Doc)
00299 {
00300 int row = d->rootItem->findChild(Doc);
00301 if (row > -1) {
00302 QModelIndex parent = createIndex(0,0,d->rootItem);
00303 beginRemoveRows(parent, row, row);
00304 DocumentModelIndex* item = d->rootItem->child(row);
00305 d->rootItem->removeChild(row);
00306 delete item;
00307 endRemoveRows();
00308 }
00309 }
00310
00311 void DocumentModel::slotRenameDocument(const Gui::Document& Doc)
00312 {
00313
00314 }
00315
00316 void DocumentModel::slotRelabelDocument(const Gui::Document& Doc)
00317 {
00318 int row = d->rootItem->findChild(Doc);
00319 if (row > -1) {
00320 QModelIndex parent = createIndex(0,0,d->rootItem);
00321 QModelIndex item = index (row, 0, parent);
00322 dataChanged(item, item);
00323 }
00324 }
00325
00326 void DocumentModel::slotActiveDocument(const Gui::Document& )
00327 {
00328
00329 QModelIndex parent = createIndex(0,0,d->rootItem);
00330 QModelIndex top = index (0, 0, parent);
00331 QModelIndex bottom = index (d->rootItem->childCount()-1, 0, parent);
00332 dataChanged(top, bottom);
00333 }
00334
00335 void DocumentModel::slotInEdit(const Gui::ViewProviderDocumentObject& v)
00336 {
00337 }
00338
00339 void DocumentModel::slotResetEdit(const Gui::ViewProviderDocumentObject& v)
00340 {
00341 }
00342
00343 void DocumentModel::slotNewObject(const Gui::ViewProviderDocumentObject& obj)
00344 {
00345 App::Document* doc = obj.getObject()->getDocument();
00346 Gui::Document* gdc = Application::Instance->getDocument(doc);
00347 int row = d->rootItem->findChild(*gdc);
00348 if (row > -1) {
00349 DocumentIndex* index = static_cast<DocumentIndex*>(d->rootItem->child(row));
00350 QModelIndex parent = createIndex(index->row(),0,index);
00351 int count_obj = index->childCount();
00352 beginInsertRows(parent, count_obj, count_obj);
00353 index->appendChild(new ViewProviderIndex(obj));
00354 endInsertRows();
00355 }
00356 }
00357
00358 void DocumentModel::slotDeleteObject(const Gui::ViewProviderDocumentObject& obj)
00359 {
00360 App::Document* doc = obj.getObject()->getDocument();
00361 Gui::Document* gdc = Application::Instance->getDocument(doc);
00362 int row = d->rootItem->findChild(*gdc);
00363 if (row > -1) {
00364 DocumentIndex* doc_index = static_cast<DocumentIndex*>(d->rootItem->child(row));
00365 QList<ViewProviderIndex*> views;
00366 doc_index->findViewProviders(obj, views);
00367 for (QList<ViewProviderIndex*>::iterator it = views.begin(); it != views.end(); ++it) {
00368 DocumentModelIndex* parentitem = (*it)->parent();
00369 QModelIndex parent = createIndex(doc_index->row(), 0, parentitem);
00370 int row = (*it)->row();
00371 beginRemoveRows(parent, row, row);
00372 parentitem->removeChild(row);
00373 delete *it;
00374 endRemoveRows();
00375 }
00376 }
00377 }
00378
00379 void DocumentModel::slotChangeObject(const Gui::ViewProviderDocumentObject& obj, const App::Property& Prop)
00380 {
00381 App::DocumentObject* fea = obj.getObject();
00382 if (&fea->Label == &Prop) {
00383 App::Document* doc = fea->getDocument();
00384 Gui::Document* gdc = Application::Instance->getDocument(doc);
00385 int row = d->rootItem->findChild(*gdc);
00386 if (row > -1) {
00387 DocumentIndex* doc_index = static_cast<DocumentIndex*>(d->rootItem->child(row));
00388 QList<ViewProviderIndex*> views;
00389 doc_index->findViewProviders(obj, views);
00390 for (QList<ViewProviderIndex*>::iterator it = views.begin(); it != views.end(); ++it) {
00391 DocumentModelIndex* parentitem = (*it)->parent();
00392 QModelIndex parent = createIndex(0,0,parentitem);
00393 int row = (*it)->row();
00394 QModelIndex item = index (row, 0, parent);
00395 dataChanged(item, item);
00396 }
00397 }
00398 }
00399 else if (isPropertyLink(Prop)) {
00400 App::Document* doc = fea->getDocument();
00401 Gui::Document* gdc = Application::Instance->getDocument(doc);
00402 std::vector<ViewProviderDocumentObject*> views = getLinkedObjects(*gdc, Prop);
00403
00404 int row = d->rootItem->findChild(*gdc);
00405 if (row > -1) {
00406 DocumentIndex* doc_index = static_cast<DocumentIndex*>(d->rootItem->child(row));
00407 QList<ViewProviderIndex*> obj_index;
00408 doc_index->findViewProviders(obj, obj_index);
00409
00410
00411 for (std::vector<ViewProviderDocumentObject*>::iterator vp = views.begin(); vp != views.end(); ++vp) {
00412 int row = doc_index->findViewProvider(**vp);
00413 if (row >= 0) {
00414 DocumentModelIndex* child = doc_index->child(row);
00415 QModelIndex parent = createIndex(doc_index->row(), 0, doc_index);
00416 beginRemoveRows(parent, row, row);
00417 doc_index->removeChild(row);
00418 delete child;
00419 endRemoveRows();
00420 }
00421 }
00422
00423 for (QList<ViewProviderIndex*>::iterator it = obj_index.begin(); it != obj_index.end(); ++it) {
00424 QModelIndex parent = createIndex((*it)->row(),0,*it);
00425 int count_obj = (*it)->childCount();
00426 beginInsertRows(parent, count_obj, count_obj + (int)views.size());
00427 for (std::vector<ViewProviderDocumentObject*>::iterator jt = views.begin(); jt != views.end(); ++jt)
00428 (*it)->appendChild(new ViewProviderIndex(**jt));
00429 endInsertRows();
00430 }
00431 }
00432 }
00433 }
00434
00435 void DocumentModel::slotRenameObject(const Gui::ViewProviderDocumentObject& obj)
00436 {
00437
00438 }
00439
00440 void DocumentModel::slotActiveObject(const Gui::ViewProviderDocumentObject& obj)
00441 {
00442
00443
00444 }
00445
00446 const Document* DocumentModel::getDocument(const QModelIndex& index) const
00447 {
00448 if (!index.isValid())
00449 return 0;
00450 Base::BaseClass* item = 0;
00451 item = static_cast<Base::BaseClass*>(index.internalPointer());
00452 if (item->getTypeId() == DocumentIndex::getClassTypeId()) {
00453 const Gui::Document& d = static_cast<DocumentIndex*>(item)->d;
00454 return (&d);
00455 }
00456
00457 return 0;
00458 }
00459
00460 bool DocumentModel::isPropertyLink(const App::Property& prop) const
00461 {
00462 if (prop.isDerivedFrom(App::PropertyLink::getClassTypeId()))
00463 return true;
00464 if (prop.isDerivedFrom(App::PropertyLinkList::getClassTypeId()))
00465 return true;
00466 return false;
00467 }
00468
00469 std::vector<ViewProviderDocumentObject*>
00470 DocumentModel::getLinkedObjects(const Gui::Document& doc, const App::Property& prop) const
00471 {
00472 std::vector<ViewProviderDocumentObject*> links;
00473 if (prop.isDerivedFrom(App::PropertyLink::getClassTypeId())) {
00474 App::DocumentObject* obj;
00475 obj = static_cast<const App::PropertyLink&>(prop).getValue();
00476 ViewProvider* view = doc.getViewProvider(obj);
00477 if (view && view->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
00478 links.push_back(static_cast<ViewProviderDocumentObject*>(view));
00479 }
00480 else if (prop.isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
00481 const std::vector<App::DocumentObject*>& refs = static_cast
00482 <const App::PropertyLinkList&>(prop).getValues();
00483 for (std::vector<App::DocumentObject*>::const_iterator it = refs.begin();it != refs.end(); ++it) {
00484 ViewProvider* view = doc.getViewProvider(*it);
00485 if (view && view->getTypeId().isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
00486 links.push_back(static_cast<ViewProviderDocumentObject*>(view));
00487 }
00488 }
00489
00490 return links;
00491 }
00492
00493 int DocumentModel::columnCount (const QModelIndex & ) const
00494 {
00495 return 1;
00496 }
00497
00498 QVariant DocumentModel::data (const QModelIndex & index, int role) const
00499 {
00500 if (!index.isValid())
00501 return QVariant();
00502 return static_cast<DocumentModelIndex*>(index.internalPointer())->data(role);
00503 }
00504
00505 bool DocumentModel::setData(const QModelIndex& index, const QVariant & value, int role)
00506 {
00507 if (!index.isValid())
00508 return false;
00509 return static_cast<DocumentModelIndex*>(index.internalPointer())->setData(value, role);
00510 }
00511
00512 Qt::ItemFlags DocumentModel::flags(const QModelIndex &index) const
00513 {
00514
00515
00516
00517 if (!index.isValid())
00518 return 0;
00519 return static_cast<DocumentModelIndex*>(index.internalPointer())->flags();
00520 }
00521
00522 QModelIndex DocumentModel::index (int row, int column, const QModelIndex & parent) const
00523 {
00524 DocumentModelIndex* item = 0;
00525 if (!parent.isValid())
00526 item = d->rootItem;
00527 else
00528 item = static_cast<DocumentModelIndex*>(parent.internalPointer())->child(row);
00529 if (!item)
00530 return QModelIndex();
00531 return createIndex(row, column, item);
00532 }
00533
00534 QModelIndex DocumentModel::parent (const QModelIndex & index) const
00535 {
00536 if (!index.isValid() || index.internalPointer() == d->rootItem)
00537 return QModelIndex();
00538 DocumentModelIndex* item = 0;
00539 item = static_cast<DocumentModelIndex*>(index.internalPointer());
00540 DocumentModelIndex* parent = item->parent();
00541 return createIndex(parent->row(), 0, parent);
00542 }
00543
00544 int DocumentModel::rowCount (const QModelIndex & parent) const
00545 {
00546 if (!parent.isValid())
00547 return 1;
00548 DocumentModelIndex* item = 0;
00549 item = static_cast<DocumentModelIndex*>(parent.internalPointer());
00550 return item->childCount();
00551 }
00552
00553 QVariant DocumentModel::headerData (int section, Qt::Orientation orientation, int role) const
00554 {
00555 if (orientation == Qt::Horizontal) {
00556 if (role != Qt::DisplayRole)
00557 return QVariant();
00558 return tr("Labels & Attributes");
00559 }
00560
00561 return QVariant();
00562 }
00563
00564 bool DocumentModel::setHeaderData (int, Qt::Orientation, const QVariant &, int)
00565 {
00566 return false;
00567 }