Wt examples  3.2.3
/home/koen/project/wt/public-git/wt/examples/gitmodel/GitModel.C
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
00003  *
00004  * See the LICENSE file for terms of use.
00005  */
00006 
00007 #include "GitModel.h"
00008 
00009 using namespace Wt;
00010 
00011 GitModel::GitModel(WObject *parent)
00012   : WAbstractItemModel(parent)
00013 { }
00014 
00015 void GitModel::setRepositoryPath(const std::string& gitRepositoryPath)
00016 {
00017   git_.setRepositoryPath(gitRepositoryPath);
00018   loadRevision("master");
00019 }
00020 
00021 void GitModel::loadRevision(const std::string& revName)
00022 {
00023   Git::ObjectId treeRoot = git_.getCommitTree(revName);
00024 
00025   // You need to call this method before invalidating all existing
00026   // model indexes. Anyone listening for this event could temporarily
00027   // convert some model indexes to a raw index pointer, but this model
00028   // does not reimplement these methods.
00029   layoutAboutToBeChanged().emit();
00030 
00031   treeData_.clear();
00032   childPointer_.clear();
00033 
00034   // Store the tree root as treeData_[0]
00035   treeData_.push_back(Tree(-1, -1, treeRoot, git_.treeSize(treeRoot)));
00036 
00037   layoutChanged().emit();
00038 }
00039 
00040 WModelIndex GitModel::parent(const WModelIndex& index) const
00041 {
00042   // treeData_[0] indicates the top-level parent.
00043   if (!index.isValid() || index.internalId() == 0)
00044     return WModelIndex();
00045   else {
00046     // get the item that corresponds to the parent ...
00047     const Tree& item = treeData_[index.internalId()];
00048 
00049     // ... and construct that identifies the parent:
00050     //   row = child index in the grand parent
00051     //   internalId = id of the grand parent
00052     return createIndex(item.index(), 0, item.parentId()); 
00053   }
00054 }
00055 
00056 WModelIndex GitModel::index(int row, int column,
00057                             const WModelIndex& parent) const
00058 {
00059   int parentId;
00060 
00061   // the top-level parent has id=0.
00062   if (!parent.isValid())
00063     parentId = 0;
00064   else {
00065     // the internal id of the parent identifies the grand parent
00066     int grandParentId = parent.internalId();
00067 
00068     // lookup the parent id for the parent himself, based on grand parent
00069     // and child-index (=row) within the grand parent
00070     parentId = getTreeId(grandParentId, parent.row());
00071   }
00072 
00073   return createIndex(row, column, parentId);
00074 }
00075 
00076 int GitModel::getTreeId(int parentId, int childIndex) const
00077 {
00078   ChildIndex index(parentId, childIndex);
00079 
00080   ChildPointerMap::const_iterator i = childPointer_.find(index);
00081   if (i == childPointer_.end()) {
00082     // no tree object was already allocated, so do that now.
00083 
00084     // lookup the git SHA1 object Id (within the parent)
00085     const Tree& parentItem = treeData_[parentId];
00086     Git::Object o = git_.treeGetObject(parentItem.treeObject(), childIndex);
00087 
00088     // and add to treeData_ and childPointer_ data structures
00089     treeData_.push_back(Tree(parentId, childIndex, o.id, git_.treeSize(o.id)));
00090     int result = treeData_.size() - 1;
00091     childPointer_[index] = result;
00092     return result;
00093   } else
00094     return i->second;
00095 }
00096 
00097 int GitModel::columnCount(const WModelIndex& index) const
00098 {
00099   // currently only one column
00100   return 1;
00101 }
00102 
00103 int GitModel::rowCount(const WModelIndex& index) const
00104 {
00105   // we are looking for the git SHA1 id of a tree object (since only folders
00106   // may contain children).
00107   Git::ObjectId objectId;
00108   int treeId;
00109 
00110   if (index.isValid()) {
00111     // only column 0 items may contain children
00112     if (index.column() != 0)
00113       return 0;
00114 
00115     Git::Object o = getObject(index);
00116     if (o.type == Git::Tree) {
00117       objectId = o.id;
00118       treeId = getTreeId(index.internalId(), index.row());
00119     } else
00120       // not a folder: no children
00121       return 0;
00122   } else {
00123     treeId = 0;
00124     // the index corresponds to the root object
00125     if (treeData_.empty())
00126       // model not yet loaded !
00127       return 0;
00128     else
00129       objectId = treeData_[0].treeObject();
00130   }
00131 
00132   return treeData_[treeId].rowCount();
00133 }
00134 
00135 boost::any GitModel::data(const WModelIndex& index, int role) const
00136 {
00137   if (!index.isValid())
00138     return boost::any();
00139 
00140   /* Only 3 data roles on column 0 data are supported:
00141    * - DisplayRole: the file name
00142    * - DecorationRole: an icon (folder or file)
00143    * - ContentsRole: the file contents
00144    */
00145   if (index.column() == 0) {
00146     Git::Object object = getObject(index);
00147     if (role == DisplayRole) {
00148       if (object.type == Git::Tree)
00149         return object.name + '/';
00150       else
00151         return object.name;
00152     } else if (role == DecorationRole) {
00153       if (object.type == Git::Blob)
00154         return static_cast<const char*>("icons/git-blob.png");
00155       else if (object.type == Git::Tree)
00156         return static_cast<const char*>("icons/git-tree.png");
00157     } else if (role == ContentsRole) {
00158       if (object.type == Git::Blob)
00159         return git_.catFile(object.id);
00160     } else if (role == FilePathRole) {
00161       return boost::any();
00162     }
00163   }
00164 
00165   return boost::any();
00166 }
00167 
00168 boost::any GitModel::headerData(int section, Orientation orientation,
00169                                 int role) const
00170 {
00171   if (orientation == Horizontal && role == DisplayRole)
00172     return static_cast<const char*>("File");
00173   else
00174     return boost::any();
00175 }
00176 
00177 Git::Object GitModel::getObject(const WModelIndex& index) const
00178 {
00179   int parentId = index.internalId();
00180   const Tree& parentItem = treeData_[parentId];
00181   return git_.treeGetObject(parentItem.treeObject(), index.row());
00182 }

Generated on Thu Nov 1 2012 for the C++ Web Toolkit (Wt) by doxygen 1.7.5.1