Continues migration with DDS, Common
This commit is contained in:
1 parent
9b15cee841
commit
fa48db111e
668 files changed
+111841
-2
No files matched your search
+286
@@ -0,0 +1,286 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lts_base.h"
|
||||
|
||||
#include <LtsUtilsCore/data_modification_enum.h>
|
||||
|
||||
#include <QVector>
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace LtsWidgets
|
||||
{
|
||||
|
||||
template<class T>
|
||||
class LtsAbstractTableModel : public QAbstractTableModel
|
||||
{
|
||||
public:
|
||||
LtsAbstractTableModel(const QVector<QString> &header, QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_vecColumns(header)
|
||||
{}
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
|
||||
{
|
||||
if (role == Qt::DisplayRole && orientation == Qt::Horizontal && section>= 0 && section < m_vecColumns.size())
|
||||
return m_vecColumns[section];
|
||||
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
bool isEmpty(const QModelIndex &parent = QModelIndex())
|
||||
{
|
||||
return parent.isValid() ? true : m_vecData.isEmpty();
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
return parent.isValid() ? 0 : m_vecData.size();
|
||||
}
|
||||
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
return parent.isValid() ? 0 : m_vecColumns.size();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
beginResetModel();
|
||||
m_vecData.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
bool indexIsValid(const QModelIndex &idx) const
|
||||
{
|
||||
if (!idx.isValid())
|
||||
return false;
|
||||
if (idx.row() < 0 || idx.row() >= m_vecData.size())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool removeRow(int row)
|
||||
{
|
||||
return removeRows(row, 1);
|
||||
}
|
||||
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override
|
||||
{
|
||||
if (parent.isValid())
|
||||
return false;
|
||||
|
||||
if (row < 0 || row >= m_vecData.size())
|
||||
return false;
|
||||
|
||||
int range = std::min(row + count, m_vecData.size());
|
||||
|
||||
beginRemoveRows(QModelIndex(), row, range - 1);
|
||||
m_vecData.erase(m_vecData.begin() + row, m_vecData.begin() + range);
|
||||
endRemoveRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool insertRow(const T &item)
|
||||
{
|
||||
if (isFiltered(item, DataModification::eAdded) || isDeletedInternal(item))
|
||||
return false;
|
||||
beginInsertRows(QModelIndex(), m_vecData.size(), m_vecData.size());
|
||||
m_vecData.append(item);
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CONT>
|
||||
void insertRows(const CONT &items)
|
||||
{
|
||||
if (items.isEmpty())
|
||||
return;
|
||||
const int cntBefore = m_vecData.size();
|
||||
for (const auto &item : items)
|
||||
{
|
||||
if (isFiltered(item, DataModification::eAdded) || isDeletedInternal(item))
|
||||
continue;
|
||||
m_vecData += item;
|
||||
}
|
||||
const int cntAfter = m_vecData.size();
|
||||
if (cntBefore == cntAfter)
|
||||
return;
|
||||
beginInsertRows(QModelIndex(), cntBefore, cntAfter - 1);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void setData(const QVector<T> &vecData)
|
||||
{
|
||||
clear();
|
||||
insertRows(vecData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void update()
|
||||
{
|
||||
if (!m_vecData.isEmpty())
|
||||
emit dataChanged(index(0, 0), index(m_vecData.size() - 1, columnCount() - 1));
|
||||
}
|
||||
|
||||
T getRowData(int row) const
|
||||
{
|
||||
if (row < 0 || row >= m_vecData.size())
|
||||
return T();
|
||||
return m_vecData.at(row);
|
||||
}
|
||||
|
||||
bool setRowData(int row, const T &data)
|
||||
{
|
||||
if (row < 0 || row >= m_vecData.size())
|
||||
return false;
|
||||
|
||||
m_vecData[row] = data;
|
||||
emit dataChanged(index(row, 0), index(row, columnCount() - 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
QModelIndex findIndexForId(int id, int column = 0) const
|
||||
{
|
||||
const int row = findRowForId(id);
|
||||
if (row < 0)
|
||||
return QModelIndex();
|
||||
return index(row, column);
|
||||
}
|
||||
|
||||
int getId(const QModelIndex &mi) const
|
||||
{
|
||||
if (!indexIsValid(mi))
|
||||
return -1;
|
||||
return getIdInternal(m_vecData.at(mi.row()));
|
||||
}
|
||||
|
||||
protected:
|
||||
template <class C>
|
||||
class HasId
|
||||
{
|
||||
template <class CLS>
|
||||
static std::true_type testSignature(const int &(CLS::*)() const);
|
||||
template <class CLS>
|
||||
static std::true_type testSignature(int (CLS::*)() const);
|
||||
|
||||
template <class CLS>
|
||||
static decltype(testSignature(&CLS::id)) test(std::nullptr_t);
|
||||
|
||||
template <class CLS>
|
||||
static std::false_type test(...);
|
||||
|
||||
public:
|
||||
using type = decltype(test<C>(nullptr));
|
||||
static const bool value = type::value;
|
||||
};
|
||||
|
||||
|
||||
template <typename F = T, typename std::enable_if<HasId<F>::value, int>::type = 0>
|
||||
int getIdInternal(const F &data) const
|
||||
{
|
||||
return data.id();
|
||||
}
|
||||
|
||||
|
||||
virtual int getId(const T &data) const
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
Q_UNUSED(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
template < typename F = T, typename std::enable_if < !HasId<F>::value, int>::type = 0>
|
||||
int getIdInternal(const F &data) const
|
||||
{
|
||||
return getId(data);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
class HasIsDeleted
|
||||
{
|
||||
template <class CLS>
|
||||
static std::true_type testSignature(const bool &(CLS::*)() const);
|
||||
template <class CLS>
|
||||
static std::true_type testSignature(bool (CLS::*)() const);
|
||||
|
||||
template <class CLS>
|
||||
static decltype(testSignature(&CLS::isDeleted)) test(std::nullptr_t);
|
||||
|
||||
template <class CLS>
|
||||
static std::false_type test(...);
|
||||
|
||||
public:
|
||||
using type = decltype(test<C>(nullptr));
|
||||
static const bool value = type::value;
|
||||
};
|
||||
|
||||
template <typename F = T, typename std::enable_if<HasIsDeleted<F>::value, int>::type = 0>
|
||||
bool isDeletedInternal(const F &data) const
|
||||
{
|
||||
return data.isDeleted();
|
||||
}
|
||||
|
||||
virtual int isDeleted(const T &data) const
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
return false;
|
||||
}
|
||||
template < typename F = T, typename std::enable_if < !HasIsDeleted<F>::value, int>::type = 0>
|
||||
bool isDeletedInternal(const F &data) const
|
||||
{
|
||||
return isDeleted(data);
|
||||
}
|
||||
|
||||
|
||||
virtual bool isFiltered(const T &data, DataModification modType) const
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
Q_UNUSED(modType);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
virtual bool onDataChanged(const T &data, DataModification modType)
|
||||
{
|
||||
if (isFiltered(data, modType))
|
||||
return false;
|
||||
|
||||
const int id = getIdInternal(data);
|
||||
const int row = findRowForId(id);
|
||||
|
||||
|
||||
if (modType == DataModification::eRemoved || isDeletedInternal(data))
|
||||
{
|
||||
if (row >= 0)
|
||||
return removeRow(row);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (modType == DataModification::eAdded && row < 0)
|
||||
return insertRow(data);
|
||||
|
||||
return setRowData(row, data);
|
||||
}
|
||||
|
||||
int findRowForId(int id) const
|
||||
{
|
||||
for (int i = 0; i < m_vecData.size(); ++i)
|
||||
{
|
||||
if (getIdInternal(m_vecData.at(i)) == id)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
QVector<T> m_vecData;
|
||||
QVector<QString> m_vecColumns;
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user