Wt examples
3.2.3
|
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 }