Sandboxie/SandboxiePlus/MiscHelpers/Common/ListItemModel.cpp

305 lines
6.3 KiB
C++

#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<QVariantMap> List)
{
QList<SListNode*> New;
QHash<QVariant, SListNode*> Old = m_Map;
foreach (const QVariantMap& Cur, List)
{
QVariant ID = Cur["ID"];
int Row = -1;
SListNode* pNode = static_cast<SListNode*>(Old[ID]);
if(!pNode)
{
pNode = static_cast<SListNode*>(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<SListNode*>& New, QHash<QVariant, SListNode*>& 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<SListNode*>::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<SListNode*>(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 Qt::NoItemFlags;
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();
}