Skip to content
Snippets Groups Projects
Commit dd2091a9 authored by Emmanuel Lepage Vallee's avatar Emmanuel Lepage Vallee
Browse files

certificate: Create the CertificateProxyModel

Refs #67838
parent 865cd292
Branches
Tags
No related merge requests found
...@@ -658,3 +658,16 @@ QVariant Certificate::detailResult(Certificate::Details detail) const ...@@ -658,3 +658,16 @@ QVariant Certificate::detailResult(Certificate::Details detail) const
}; };
return QVariant(); return QVariant();
} }
/**
* Get the details of this certificate as a QAbstractItemModel
*
* Please note that the object ownership will be transferred. To avoid memory
* leaks, the users of this object must delete it once they are done with it.
*/
QAbstractItemModel* Certificate::model() const
{
return CertificateModel::instance()->model(this);
}
#include <certificate.moc>
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
//Qt //Qt
#include <QUrl> #include <QUrl>
class QAbstractItemModel;
class CertificatePrivate; class CertificatePrivate;
...@@ -176,6 +177,7 @@ public: ...@@ -176,6 +177,7 @@ public:
Certificate::Type type() const; Certificate::Type type() const;
Certificate::CheckValues checkResult (Certificate::Checks check ) const; Certificate::CheckValues checkResult (Certificate::Checks check ) const;
QVariant detailResult(Certificate::Details detail) const; QVariant detailResult(Certificate::Details detail) const;
QAbstractItemModel* model() const;
QString getName (Certificate::Checks check ); QString getName (Certificate::Checks check );
QString getName (Certificate::Details details ); QString getName (Certificate::Details details );
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <QtCore/QThread> #include <QtCore/QThread>
#include <QtCore/QMutex> #include <QtCore/QMutex>
#include <QtCore/QMutexLocker> #include <QtCore/QMutexLocker>
#include <QtCore/QAbstractProxyModel>
//LibSTDC++ //LibSTDC++
#include <functional> #include <functional>
...@@ -34,21 +35,14 @@ ...@@ -34,21 +35,14 @@
struct CertificateNode { struct CertificateNode {
enum class Level { CertificateNode(int index, CertificateModel::NodeType level, CertificateNode* parent, Certificate* cert);
CATEGORY = 0,
CERTIFICATE = 1,
DETAILS_CATEGORY = 2,
DETAILS = 3,
};
CertificateNode(int index, Level level, CertificateNode* parent, Certificate* cert);
void setStrings(const QString& col1, const QVariant& col2, const QString& tooltip); void setStrings(const QString& col1, const QVariant& col2, const QString& tooltip);
//Attributes //Attributes
QVector<CertificateNode*> m_lChildren ; QVector<CertificateNode*> m_lChildren ;
CertificateNode* m_pParent ; CertificateNode* m_pParent ;
Certificate* m_pCertificate; Certificate* m_pCertificate;
CertificateNode::Level m_Level ; CertificateModel::NodeType m_Level ;
int m_Index ; int m_Index ;
QString m_Col1 ; QString m_Col1 ;
QVariant m_Col2 ; QVariant m_Col2 ;
...@@ -76,16 +70,23 @@ Q_SIGNALS: ...@@ -76,16 +70,23 @@ Q_SIGNALS:
void listLoaded(const QList<QByteArray>& list); void listLoaded(const QList<QByteArray>& list);
}; };
QByteArray BackgroundLoader::loadCert(const QByteArray& id) class CertificateProxyModel : public QAbstractProxyModel
{ {
if (m_lIdList.isEmpty()) //WARNING potential race Q_OBJECT
QList<QByteArray> m_lIdList = CertificateSerializationDelegate::instance()->listCertificates(); public:
CertificateProxyModel(CertificateModel* parent, CertificateNode* root);
if (m_lIdList.indexOf(id) == -1) //TODO use an hash map for this //Model implementation
return QByteArray(); virtual QModelIndex mapFromSource( const QModelIndex& sourceIndex ) const override;
virtual QModelIndex mapToSource ( const QModelIndex& proxyIndex ) const override;
virtual QModelIndex index ( int row, int column, const QModelIndex& parent=QModelIndex()) const override;
virtual QModelIndex parent ( const QModelIndex& index ) const override;
virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const override;
virtual int columnCount ( const QModelIndex& parent = QModelIndex() ) const override;
return CertificateSerializationDelegate::instance()->loadCertificate(id); private:
} CertificateNode* m_pRoot;
};
class CertificateModelPrivate class CertificateModelPrivate
{ {
...@@ -96,12 +97,15 @@ public: ...@@ -96,12 +97,15 @@ public:
//Helper //Helper
CertificateNode* defaultCategory(); CertificateNode* defaultCategory();
CertificateNode* addToTree(Certificate* cert, CertificateNode* category = nullptr); CertificateNode* addToTree(Certificate* cert, CertificateNode* category = nullptr);
QModelIndex createIndex(int r ,int c , void* p);
QAbstractItemModel* getModelCommon(CertificateNode* node);
//Attributes //Attributes
QVector<CertificateNode*> m_lTopLevelNodes ; QVector<CertificateNode*> m_lTopLevelNodes ;
QHash<QString,Certificate*> m_hCertificates ; QHash<QString,Certificate*> m_hCertificates ;
CertificateNode* m_pDefaultCategory; CertificateNode* m_pDefaultCategory;
QMutex m_CertLoader ; QMutex m_CertLoader ;
QHash<const Certificate*,CertificateNode*> m_hNodes ;
//Singleton //Singleton
static CertificateModel* m_spInstance; static CertificateModel* m_spInstance;
...@@ -110,6 +114,17 @@ private: ...@@ -110,6 +114,17 @@ private:
CertificateModel* q_ptr; CertificateModel* q_ptr;
}; };
QByteArray BackgroundLoader::loadCert(const QByteArray& id)
{
if (m_lIdList.isEmpty()) //WARNING potential race
QList<QByteArray> m_lIdList = CertificateSerializationDelegate::instance()->listCertificates();
if (m_lIdList.indexOf(id) == -1) //TODO use an hash map for this
return QByteArray();
return CertificateSerializationDelegate::instance()->loadCertificate(id);
}
CertificateModel* CertificateModelPrivate::m_spInstance = nullptr; CertificateModel* CertificateModelPrivate::m_spInstance = nullptr;
CertificateModelPrivate::~CertificateModelPrivate() CertificateModelPrivate::~CertificateModelPrivate()
...@@ -120,10 +135,10 @@ CertificateModelPrivate::~CertificateModelPrivate() ...@@ -120,10 +135,10 @@ CertificateModelPrivate::~CertificateModelPrivate()
} }
} }
CertificateNode::CertificateNode(int index, Level level, CertificateNode* parent, Certificate* cert) : CertificateNode::CertificateNode(int index, CertificateModel::NodeType level, CertificateNode* parent, Certificate* cert) :
m_pParent(parent), m_pCertificate(cert), m_Level(level), m_Index(index), m_IsLoaded(true) m_pParent(parent), m_pCertificate(cert), m_Level(level), m_Index(index), m_IsLoaded(true)
{ {
CertificateModel::instance()->d_ptr->m_hNodes[cert] = this;
} }
CertificateModelPrivate::CertificateModelPrivate(CertificateModel* parent) : q_ptr(parent), CertificateModelPrivate::CertificateModelPrivate(CertificateModel* parent) : q_ptr(parent),
...@@ -185,7 +200,7 @@ CertificateNode* CertificateModelPrivate::defaultCategory() ...@@ -185,7 +200,7 @@ CertificateNode* CertificateModelPrivate::defaultCategory()
if (!m_pDefaultCategory) { if (!m_pDefaultCategory) {
const int idx = m_hCertificates.size(); const int idx = m_hCertificates.size();
m_pDefaultCategory = new CertificateNode(idx, CertificateNode::Level::CATEGORY, nullptr, nullptr); m_pDefaultCategory = new CertificateNode(idx, CertificateModel::NodeType::CATEGORY, nullptr, nullptr);
m_pDefaultCategory->setStrings(QObject::tr("Default"),QObject::tr("Certificate not associated with a group"),QString()); m_pDefaultCategory->setStrings(QObject::tr("Default"),QObject::tr("Certificate not associated with a group"),QString());
q_ptr->beginInsertRows(QModelIndex(), idx, idx); q_ptr->beginInsertRows(QModelIndex(), idx, idx);
...@@ -196,6 +211,11 @@ CertificateNode* CertificateModelPrivate::defaultCategory() ...@@ -196,6 +211,11 @@ CertificateNode* CertificateModelPrivate::defaultCategory()
return m_pDefaultCategory; return m_pDefaultCategory;
} }
QModelIndex CertificateModelPrivate::createIndex(int r ,int c , void* p)
{
return q_ptr->createIndex(r,c,p);
}
CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, CertificateNode* category) CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, CertificateNode* category)
{ {
QMutexLocker(&this->m_CertLoader); QMutexLocker(&this->m_CertLoader);
...@@ -205,7 +225,7 @@ CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, Certifica ...@@ -205,7 +225,7 @@ CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, Certifica
const int idx = category->m_lChildren.size(); const int idx = category->m_lChildren.size();
CertificateNode* node = new CertificateNode(idx, CertificateNode::Level::CERTIFICATE, category, cert); CertificateNode* node = new CertificateNode(idx, CertificateModel::NodeType::CERTIFICATE, category, cert);
node->setStrings(QObject::tr("A certificate"),QObject::tr("An organisation"),QString()); node->setStrings(QObject::tr("A certificate"),QObject::tr("An organisation"),QString());
...@@ -221,8 +241,8 @@ CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, Certifica ...@@ -221,8 +241,8 @@ CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, Certifica
//Insert the check and details categories //Insert the check and details categories
q_ptr->beginInsertRows(index, 0, static_cast<int>(CertificateModel::Columns::NAME )); q_ptr->beginInsertRows(index, 0, static_cast<int>(CertificateModel::Columns::NAME ));
CertificateNode* details = new CertificateNode(static_cast<int>(CertificateModel::Columns::NAME ), CertificateNode::Level::DETAILS_CATEGORY, node, nullptr); CertificateNode* details = new CertificateNode(static_cast<int>(CertificateModel::Columns::NAME ), CertificateModel::NodeType::DETAILS_CATEGORY, node, nullptr);
CertificateNode* checks = new CertificateNode(static_cast<int>(CertificateModel::Columns::VALUE), CertificateNode::Level::DETAILS_CATEGORY, node, nullptr); CertificateNode* checks = new CertificateNode(static_cast<int>(CertificateModel::Columns::VALUE), CertificateModel::NodeType::DETAILS_CATEGORY, node, nullptr);
details->setStrings(QObject::tr("Details"),QString(),QObject::tr("The content of the certificate") ); details->setStrings(QObject::tr("Details"),QString(),QObject::tr("The content of the certificate") );
checks ->setStrings(QObject::tr("Checks") ,QString(),QObject::tr("Various security related information") ); checks ->setStrings(QObject::tr("Checks") ,QString(),QObject::tr("Various security related information") );
node->m_lChildren << details; node->m_lChildren << checks; node->m_lChildren << details; node->m_lChildren << checks;
...@@ -234,7 +254,7 @@ CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, Certifica ...@@ -234,7 +254,7 @@ CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, Certifica
const QModelIndex detailsI(q_ptr->createIndex(details->m_Index,static_cast<int>(CertificateModel::Columns::NAME ),details)); const QModelIndex detailsI(q_ptr->createIndex(details->m_Index,static_cast<int>(CertificateModel::Columns::NAME ),details));
q_ptr->beginInsertRows(detailsI, static_cast<int>(CertificateModel::Columns::NAME ), detailsC); q_ptr->beginInsertRows(detailsI, static_cast<int>(CertificateModel::Columns::NAME ), detailsC);
for (const Certificate::Details detail : EnumIterator<Certificate::Details>()) { for (const Certificate::Details detail : EnumIterator<Certificate::Details>()) {
CertificateNode* d = new CertificateNode(details->m_lChildren.size(), CertificateNode::Level::DETAILS, details, nullptr); CertificateNode* d = new CertificateNode(details->m_lChildren.size(), CertificateModel::NodeType::DETAILS, details, nullptr);
d->setStrings(cert->getName(detail),cert->detailResult(detail),cert->getDescription(detail) ); d->setStrings(cert->getName(detail),cert->detailResult(detail),cert->getDescription(detail) );
details->m_lChildren << d; details->m_lChildren << d;
} }
...@@ -245,7 +265,7 @@ CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, Certifica ...@@ -245,7 +265,7 @@ CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, Certifica
q_ptr->beginInsertRows(checksI, static_cast<int>(CertificateModel::Columns::NAME ), checksC); q_ptr->beginInsertRows(checksI, static_cast<int>(CertificateModel::Columns::NAME ), checksC);
for (const Certificate::Checks check : EnumIterator<Certificate::Checks>()) { for (const Certificate::Checks check : EnumIterator<Certificate::Checks>()) {
if (cert->checkResult(check) != Certificate::CheckValues::UNSUPPORTED) { if (cert->checkResult(check) != Certificate::CheckValues::UNSUPPORTED) {
CertificateNode* d = new CertificateNode(checks->m_lChildren.size(), CertificateNode::Level::DETAILS, checks, nullptr); CertificateNode* d = new CertificateNode(checks->m_lChildren.size(), CertificateModel::NodeType::DETAILS, checks, nullptr);
d->setStrings(cert->getName(check),static_cast<bool>(cert->checkResult(check)),cert->getDescription(check)); d->setStrings(cert->getName(check),static_cast<bool>(cert->checkResult(check)),cert->getDescription(check));
checks->m_lChildren << d; checks->m_lChildren << d;
} }
...@@ -278,6 +298,8 @@ QVariant CertificateModel::data( const QModelIndex& index, int role) const ...@@ -278,6 +298,8 @@ QVariant CertificateModel::data( const QModelIndex& index, int role) const
return index.column()?node->m_Col2:node->m_Col1; return index.column()?node->m_Col2:node->m_Col1;
case Qt::ToolTipRole: case Qt::ToolTipRole:
return node->m_ToolTip; return node->m_ToolTip;
case static_cast<int>(Role::NodeType):
return QVariant::fromValue(node->m_Level);
}; };
return QVariant(); return QVariant();
} }
...@@ -290,7 +312,7 @@ int CertificateModel::rowCount( const QModelIndex& parent) const ...@@ -290,7 +312,7 @@ int CertificateModel::rowCount( const QModelIndex& parent) const
const CertificateNode* node = static_cast<CertificateNode*>(parent.internalPointer()); const CertificateNode* node = static_cast<CertificateNode*>(parent.internalPointer());
//Load that info only when it is needed //Load that info only when it is needed
if (node->m_Level == CertificateNode::Level::CERTIFICATE && (!node->m_IsLoaded)) if (node->m_Level == CertificateModel::NodeType::CERTIFICATE && (!node->m_IsLoaded))
node->m_fLoader(); node->m_fLoader();
return node->m_lChildren.size(); return node->m_lChildren.size();
} }
...@@ -380,4 +402,108 @@ Certificate* CertificateModel::getCertificateFromContent(const QByteArray& rawCo ...@@ -380,4 +402,108 @@ Certificate* CertificateModel::getCertificateFromContent(const QByteArray& rawCo
return cert; return cert;
} }
CertificateProxyModel::CertificateProxyModel(CertificateModel* parent, CertificateNode* root) : QAbstractProxyModel(parent),m_pRoot(root)
{
setSourceModel(parent);
}
QModelIndex CertificateProxyModel::mapFromSource(const QModelIndex& sourceIndex) const
{
if (!sourceIndex.isValid())
return QModelIndex();
CertificateModel::NodeType type = qvariant_cast<CertificateModel::NodeType>(sourceIndex.data((int)CertificateModel::Role::NodeType));
switch (type) {
case CertificateModel::NodeType::CATEGORY :
case CertificateModel::NodeType::CERTIFICATE :
return QModelIndex();
case CertificateModel::NodeType::DETAILS_CATEGORY:
case CertificateModel::NodeType::DETAILS :
return createIndex(sourceIndex.row(),sourceIndex.column(),sourceIndex.internalPointer());
}
return QModelIndex();
}
QModelIndex CertificateProxyModel::mapToSource(const QModelIndex& proxyIndex) const
{
return CertificateModel::instance()->d_ptr->createIndex(proxyIndex.row(),proxyIndex.column(),proxyIndex.internalPointer());
}
QModelIndex CertificateProxyModel::index( int row, int column, const QModelIndex& parent) const
{
if ((parent.isValid() && parent.model() != this) || column > 1)
return QModelIndex();
CertificateNode* node = parent.isValid()?static_cast<CertificateNode*>(parent.internalPointer()):m_pRoot;
if ((!node) || row >= node->m_lChildren.size())
return QModelIndex();
return createIndex(row, column, node->m_lChildren[row]);
}
QModelIndex CertificateProxyModel::parent( const QModelIndex& index ) const
{
if ((index.model() != this) || (!index.isValid()))
return QModelIndex();
CertificateNode* node = static_cast<CertificateNode*>(index.internalPointer());
if (!node)
return QModelIndex();
return (node->m_pParent == m_pRoot)?QModelIndex() : createIndex(node->m_pParent->m_Index, index.column(), node->m_pParent);
}
int CertificateProxyModel::rowCount( const QModelIndex& parent ) const
{
return parent.isValid()? sourceModel()->rowCount(mapToSource(parent)) : m_pRoot->m_lChildren.size();
}
int CertificateProxyModel::columnCount( const QModelIndex& parent ) const
{
return sourceModel()->columnCount(mapToSource(parent));
}
QAbstractItemModel* CertificateModelPrivate::getModelCommon(CertificateNode* node)
{
if (node) {
if (node->m_Level == CertificateModel::NodeType::CERTIFICATE && (!node->m_IsLoaded))
node->m_fLoader();
CertificateProxyModel* m = new CertificateProxyModel(q_ptr,node);
return m;
}
return nullptr;
}
/**
* This model is a proxy of CertificateModel with only the current certificate
*
* Please note that the object ownership will be transferred. To avoid memory
* leaks, the users of this object must delete it once they are done with it.
*/
QAbstractItemModel* CertificateModel::model(const Certificate* cert) const
{
if (!cert)
return nullptr;
return d_ptr->getModelCommon(d_ptr->m_hNodes[cert]);
}
/**
* This model is a proxy of CertificateModel with only the current certificate
*
* Please note that the object ownership will be transferred. To avoid memory
* leaks, the users of this object must delete it once they are done with it.
*/
QAbstractItemModel* CertificateModel::model(const QModelIndex& idx) const
{
if ((!idx.isValid()) || (idx.model() != this))
return nullptr;
CertificateNode* node = static_cast<CertificateNode*>(idx.internalPointer());
return d_ptr->getModelCommon(node);
}
#include <certificatemodel.moc> #include <certificatemodel.moc>
...@@ -28,12 +28,25 @@ class LIB_EXPORT CertificateModel : public QAbstractItemModel ...@@ -28,12 +28,25 @@ class LIB_EXPORT CertificateModel : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT
public: public:
friend class CertificateProxyModel;
friend class CertificateNode;
enum class Role {
NodeType = 100,
};
enum class Columns { enum class Columns {
NAME = 0, NAME = 0,
VALUE = 1, VALUE = 1,
}; };
enum class NodeType {
CATEGORY = 0,
CERTIFICATE = 1,
DETAILS_CATEGORY = 2,
DETAILS = 3,
};
//Constructor //Constructor
explicit CertificateModel(QObject* parent = nullptr); explicit CertificateModel(QObject* parent = nullptr);
virtual ~CertificateModel(); virtual ~CertificateModel();
...@@ -49,6 +62,10 @@ public: ...@@ -49,6 +62,10 @@ public:
virtual QVariant headerData ( int section, Qt::Orientation, int role = Qt::DisplayRole ) const override; virtual QVariant headerData ( int section, Qt::Orientation, int role = Qt::DisplayRole ) const override;
virtual QHash<int,QByteArray> roleNames() const override; virtual QHash<int,QByteArray> roleNames() const override;
//Getters
QAbstractItemModel* model(const Certificate* cert) const;
QAbstractItemModel* model(const QModelIndex& idx) const;
//Mutator //Mutator
Certificate* getCertificate(const QUrl& path, Certificate::Type type = Certificate::Type::NONE); Certificate* getCertificate(const QUrl& path, Certificate::Type type = Certificate::Type::NONE);
Certificate* getCertificateFromContent(const QByteArray& rawContent, bool save = true); Certificate* getCertificateFromContent(const QByteArray& rawContent, bool save = true);
...@@ -60,5 +77,6 @@ private: ...@@ -60,5 +77,6 @@ private:
CertificateModelPrivate* d_ptr; CertificateModelPrivate* d_ptr;
Q_DECLARE_PRIVATE(CertificateModel) Q_DECLARE_PRIVATE(CertificateModel)
}; };
Q_DECLARE_METATYPE(CertificateModel::NodeType)
#endif #endif
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment