#include "stdafx.h" #include "ListItemModel.h" #define FIRST_COLUMN 0 bool CListItemModel::m_DarkMode = false; CListItemModel::CListItemModel(QObject *parent) : QAbstractItemModelEx(parent) { m_bUseIcons = false; } CListItemModel::~CListItemModel() { foreach(SListNode* pNode, m_List) delete pNode; } int CListItemModel::GetRow(SListNode* pNode) const { int Index = m_RevList.value(pNode, -1); ASSERT(Index != -1); ASSERT(m_List[Index] == pNode); return Index; } void CSimpleListModel::Sync(QList List) { QList New; QHash Old = m_Map; foreach (const QVariantMap& Cur, List) { QVariant ID = Cur["ID"]; int Row = -1; SListNode* pNode = static_cast(Old[ID]); if(!pNode) { pNode = static_cast(MkNode(ID)); pNode->Values.resize(columnCount()); pNode->IsBold = Cur["IsBold"].toBool(); pNode->Icon = Cur["Icon"]; New.append(pNode); } else { Old[ID] = NULL; Row = GetRow(pNode); } int Col = 0; bool State = false; bool Changed = false; QVariantMap Values = Cur["Values"].toMap(); for(int section = FIRST_COLUMN; section < columnCount(); section++) { if (!m_Columns.contains(section)) continue; // ignore columns which are hidden QVariant Value = Values[QString::number(section)]; SListNode::SValue& ColValue = pNode->Values[section]; if (ColValue.Raw != Value) { Changed = true; ColValue.Raw = Value; //ColValue.Formatted = } if(State != Changed) { if(State && Row != -1) emit dataChanged(createIndex(Row, Col), createIndex(Row, section-1)); State = Changed; Col = section; } Changed = false; } if(State && Row != -1) emit dataChanged(createIndex(Row, Col, pNode), createIndex(Row, columnCount()-1, pNode)); } CListItemModel::Sync(New, Old); } void CListItemModel::Sync(QList& New, QHash& Old) { int Removed = 0; int Begin = -1; int End = -1; for(int i = m_List.count()-1; i >= -1; i--) { QVariant ID = i >= 0 ? m_List[i]->ID : QVariant(); if(!ID.isNull() && (Old.value(ID) != NULL)) // remove it { m_Map.remove(ID); if(End == -1) End = i; } else if(End != -1) // keep it and remove whatis to be removed at once { Begin = i + 1; beginRemoveRows(QModelIndex(), Begin, End); for (int j = End; j >= Begin; j--) { Removed++; SListNode* pNode = m_List.takeAt(j); m_RevList.remove(pNode); delete pNode; } endRemoveRows(); End = -1; Begin = -1; } } // if something was removed we need to update the row cache if (Removed > 0) { ASSERT(m_RevList.size() == m_List.size()); for (int i = 0; i < m_List.count(); i++) m_RevList[m_List[i]] = i; } Begin = m_List.count(); for(QList::iterator I = New.begin(); I != New.end(); I++) { SListNode* pNode = *I; m_Map.insert(pNode->ID, pNode); int Index = m_List.size(); m_List.append(pNode); m_RevList.insert(pNode, Index); } End = m_List.count(); if(Begin < End) { beginInsertRows(QModelIndex(), Begin, End-1); endInsertRows(); } } QModelIndex CListItemModel::FindIndex(const QVariant& ID) { if(SListNode* pNode = m_Map.value(ID)) { int row = m_List.indexOf(pNode); ASSERT(row != -1); return createIndex(row, FIRST_COLUMN, pNode); } return QModelIndex(); } void CListItemModel::Clear() { //beginResetModel(); if (rowCount() == 0) return; beginRemoveRows(QModelIndex(), 0, rowCount()-1); foreach(SListNode* pNode, m_List) delete pNode; m_List.clear(); m_RevList.clear(); m_Map.clear(); endRemoveRows(); //endResetModel(); } QVariant CListItemModel::data(const QModelIndex &index, int role) const { return Data(index, role, index.column()); } QVariant CListItemModel::Data(const QModelIndex &index, int role, int section) const { if (!index.isValid()) return QVariant(); //if(role == Qt::SizeHintRole ) // return QSize(64,16); // for fixing height SListNode* pNode = static_cast(index.internalPointer()); switch(role) { case Qt::DisplayRole: { SListNode::SValue& Value = pNode->Values[section]; return Value.Formatted.isValid() ? Value.Formatted : Value.Raw; } case Qt::EditRole: // sort role { return pNode->Values[section].Raw; } case Qt::ToolTipRole: { QString ToolTip; emit ToolTipCallback(pNode->ID, ToolTip); if(!ToolTip.isNull()) return ToolTip; break; } case Qt::DecorationRole: { if (m_bUseIcons && section == FIRST_COLUMN) return pNode->Icon.isValid() ? pNode->Icon : GetDefaultIcon(); break; } case Qt::FontRole: { if (section == FIRST_COLUMN && pNode->IsBold) { QFont fnt; fnt.setBold(true); return fnt; } break; } case Qt::BackgroundRole: { if(!m_DarkMode) return pNode->Color.isValid() ? pNode->Color : QVariant(); break; } case Qt::ForegroundRole: { if(m_DarkMode) return pNode->Color.isValid() ? pNode->Color : QVariant(); else if (pNode->IsGray) { QColor Color = Qt::darkGray; return QBrush(Color); } break; } case Qt::UserRole: { switch(section) { case FIRST_COLUMN: return pNode->ID; } break; } } return QVariant(); } Qt::ItemFlags CListItemModel::flags(const QModelIndex &index) const { if (!index.isValid()) return 0; return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } QModelIndex CListItemModel::index(int row, int column, const QModelIndex &parent) const { if (!hasIndex(row, column, parent)) return QModelIndex(); if (parent.isValid()) return QModelIndex(); if(m_List.count() > row) return createIndex(row, column, m_List[row]); return QModelIndex(); } QModelIndex CListItemModel::parent(const QModelIndex &index) const { return QModelIndex(); } int CListItemModel::rowCount(const QModelIndex &parent) const { if (parent.column() > 0) return 0; if (parent.isValid()) return 0; return m_List.count(); } int CSimpleListModel::columnCount(const QModelIndex &parent) const { return m_Headers.count(); } QVariant CSimpleListModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { if (section < m_Headers.size()) return m_Headers.at(section); } return QVariant(); }