/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include #include #include #include "smtreemodel.h" #include "smtreeitem.h" #include "smglobals.h" SmTreeModel::SmTreeModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent), mRootItem(0){ mHeaders = headers; for(int i = 0; i < mHeaders.size(); ++i){ mHeaderData.insert(mHeaders.at(i), i); } mRootItem = new SmTreeItem(headers.count()); mDecorationIcon = SmGlobals::instance()->iconFor("folder"); } SmTreeModel::~SmTreeModel(){ delete mRootItem; } int SmTreeModel::rowCount(const QModelIndex &parent) const{ SmTreeItem *parentItem = itemAt(parent); return parentItem->childCount(); } int SmTreeModel::columnCount(const QModelIndex &parent) const{ Q_UNUSED(parent); return mRootItem->columnCount(); } QModelIndex SmTreeModel::index(int row, int column, const QModelIndex &parent) const{ if(!hasIndex(row, column, parent)){ return QModelIndex(); } SmTreeItem *parentItem; if(!parent.isValid()){ parentItem = mRootItem; }else{ parentItem = static_cast(parent.internalPointer()); } SmTreeItem *childItem = parentItem->child(row); if(childItem){ return createIndex(row, column, childItem); } return QModelIndex(); } QModelIndex SmTreeModel::parent(const QModelIndex &child) const{ if(!child.isValid()){ return QModelIndex(); } SmTreeItem *childItem = static_cast(child.internalPointer()); if(childItem == mRootItem){ return QModelIndex(); } SmTreeItem *parentItem = childItem->parent(); if(parentItem == mRootItem){ return QModelIndex(); } return createIndex(parentItem->row(), 0, parentItem); } Qt::ItemFlags SmTreeModel::flags(const QModelIndex &index) const{ if(!index.isValid()){ return 0; } return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable; } QVariant SmTreeModel::headerData(int section, Qt::Orientation orientation, int role) const{ if((orientation == Qt::Horizontal) && (role == Qt::DisplayRole) && (section > -1) && (section < mHeaders.count())){ return mHeaders.at(section); } return QVariant(); } const QHash SmTreeModel::headerData() const{ return mHeaderData; } bool SmTreeModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role){ if((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)){ mHeaders[section] = value.toString(); emit headerDataChanged(orientation, section, section); return true; } return false; } QVariant SmTreeModel::data(const QModelIndex &index, int role) const{ if(!index.isValid()){ return QVariant(); } SmTreeItem *item = itemAt(index); if(role == Qt::DisplayRole){ return item->data(index.column()); } if(role == Qt::EditRole){ return item->data(index.column()); } if(role == Qt::DecorationRole){ if(index.column() == 0){ return mDecorationIcon; } } return QVariant(); } bool SmTreeModel::setData(const QModelIndex &index, const QVariant &value, int role){ if(role != Qt::EditRole){ return false; } SmTreeItem *item = itemAt(index); item->setData(index.column(), value); emit dataChanged(index, index); return true; } QModelIndex SmTreeModel::find(const QVariant &value, int column, const QModelIndex &pIdx) const{ SmTreeItem *parentItem = 0; if(!pIdx.isValid()){ parentItem = root(); }else{ parentItem = static_cast(pIdx.internalPointer()); } for(int i = 0; i < parentItem->childCount(); ++i){ SmTreeItem *child = parentItem->child(i); if(child->data(column) == value){ return index(i, column, pIdx); } } return QModelIndex(); } QModelIndex SmTreeModel::findRecursive(const QVariant &value, int column, const QModelIndex &start) const{ if(!start.isValid()){ return QModelIndex(); } SmTreeItem *startItem = static_cast(start.internalPointer()); if(startItem->data(column) == value){ return start; } for(int i = 0; i < startItem->childCount(); ++i){ SmTreeItem *child = startItem->child(i); if(child->data(column) == value){ return createIndex(i, column, child); } if(child->childCount()){ return findRecursive(value, column, createIndex(i, column, child)); } } SmTreeItem *next = startItem->next(); if(next){ return findRecursive(value, column, createIndex(next->row(), column, next)); } return QModelIndex(); } bool SmTreeModel::matchRecursive(const QModelIndex &pIdx, const QRegExp ®ex, int column) const { if(!pIdx.isValid()){ return false; } // first try the parent itself QString value = pIdx.data().toString(); if(value.isEmpty()){ return false; } if(value.contains(regex)){ return true; } // no match, check for children SmTreeItem *item = static_cast(pIdx.internalPointer()); if(!item->childCount()){ //leaf, chech parents return checkParents(item, regex, column); } // we have children, traverse them bool retval = false; for(int i = 0; i < item->childCount(); ++i){ QModelIndex newIdx = createIndex(i, column, item->child(i)); retval = matchRecursive(newIdx, regex, column); if(retval){ break; } } return retval; } bool SmTreeModel::checkParents(const SmTreeItem *item, const QRegExp ®ex, int column) const { while(item != root()){ QString value = item->data(column).toString(); if(value.contains(regex)){ return true; } item = item->parent(); } return false; } bool SmTreeModel::setRoot(SmTreeItem *rootItem){ if(mRootItem){ beginResetModel(); delete mRootItem; mRootItem = rootItem; endResetModel(); return true; } return false; } QModelIndex SmTreeModel::rootIndex() const { return createIndex(0, 0, mRootItem); } SmTreeItem *SmTreeModel::parentItem(const QModelIndex &child) const{ QModelIndex parent = child.parent(); if(parent == QModelIndex()){ return mRootItem; } return static_cast(child.parent().internalPointer()); } void SmTreeModel::reparent(const QModelIndex &idx, const QModelIndex &newParent, bool sorted){ if(!idx.isValid()){ return; } SmTreeItem *item = static_cast(idx.internalPointer()); QList data; for(int i = 0; i < item->columnCount(); ++i){ data << item->data(i); } QPersistentModelIndex pNewParent = newParent; removeRows(idx.row(), 1, idx.parent()); addRow(data, pNewParent, sorted); } bool SmTreeModel::insertRows(int row, int count, const QModelIndex &pIdx){ SmTreeItem *parentItem = itemAt(pIdx); bool retval; if(row > parentItem->childCount()){ return false; } beginInsertRows(pIdx, row, row + count - 1); for(int i = row; i < row + count; ++i){ SmTreeItem *newItem = new SmTreeItem(mRootItem->columnCount(), parentItem); retval = parentItem->insertChild(i, newItem); } endInsertRows(); return retval; } bool SmTreeModel::removeRows(int row, int count, const QModelIndex &pIdx){ SmTreeItem *parentItem = itemAt(pIdx); bool retval; if(row > parentItem->childCount()){ return false; } beginRemoveRows(pIdx, row, row + count - 1); for(int i = row + count; i > row; --i){ retval = parentItem->removeChild(i - 1); } endRemoveRows(); return retval; } bool SmTreeModel::addRow(const QList &data, const QModelIndex &pIdx, bool sorted){ if(data.count() != mRootItem->columnCount()){ return false; } SmTreeItem *parentItem = itemAt(pIdx); int where = 0; if(sorted){ for(int i = 0; i < parentItem->childCount(); ++i){ if(parentItem->child(i)->data(0).toString() > data.at(0).toString()){ where = i; break; } } } if(insertRows(where, 1, pIdx)){ SmTreeItem *child = parentItem->child(where); for(int i = 0; i < data.count(); ++i){ child->setData(i, data.at(i)); } QModelIndex start = index(parentItem->childCount() - 1, 0, pIdx); QModelIndex end = index(parentItem->childCount() - 1, parentItem->columnCount() - 1, pIdx); emit dataChanged(start, end); return true; } return false; } bool SmTreeModel::appendRow(const QList &data, const QModelIndex &pIdx){ SmTreeItem *pItem = itemAt(pIdx); SmTreeItem *newItem = new SmTreeItem(data, pItem); beginResetModel(); pItem->appendChild(newItem); endResetModel(); return true; } SmTreeItem *SmTreeModel::itemAt(const QModelIndex &index) const{ if(index.isValid()){ SmTreeItem *item = static_cast(index.internalPointer()); if(item){ return item; } } return mRootItem; }