/*************************************************************************** * Copyright (C) 2018 by Chinmoy Ranjan Pradhan #include #include #include #include "core/document.h" #include "core/observer.h" #include "core/page.h" #include "core/form.h" #include "core/signatureutils.h" struct SignatureItem { enum DataType { Root, RevisionInfo, ValidityStatus, SigningTime, Reason, FieldInfo }; SignatureItem(); SignatureItem( SignatureItem *parent, const Okular::FormFieldSignature *form, DataType type, int page ); ~SignatureItem(); SignatureItem(const SignatureItem &) = delete; SignatureItem &operator=(const SignatureItem &) = delete; QVector children; SignatureItem *parent; const Okular::FormFieldSignature *form; QString displayString; DataType type; int page; }; SignatureItem::SignatureItem() : parent( nullptr ), form( nullptr ), type( Root ), page( -1 ) { } SignatureItem::SignatureItem( SignatureItem *_parent, const Okular::FormFieldSignature *_form , DataType _type, int _page ) : parent( _parent ), form( _form ), type( _type ), page( _page ) { Q_ASSERT( parent ); parent->children.append( this ); } SignatureItem::~SignatureItem() { qDeleteAll( children ); } class SignatureModelPrivate : public Okular::DocumentObserver { public: SignatureModelPrivate( SignatureModel *qq ); ~SignatureModelPrivate() override; void notifySetup( const QVector &pages, int setupFlags ) override; QModelIndex indexForItem( SignatureItem *item ) const; SignatureModel *q; SignatureItem *root; QPointer document; }; SignatureModelPrivate::SignatureModelPrivate( SignatureModel *qq ) : q( qq ), root( new SignatureItem ) { } SignatureModelPrivate::~SignatureModelPrivate() { delete root; } static void updateFormFieldSignaturePointer( SignatureItem *item, const QVector &pages ) { if ( item->form ) { foreach ( Okular::FormField *f, pages[item->page]->formFields() ) { if ( item->form->id() == f->id() ) { item->form = static_cast( f ); break; } } if ( !item->form ) qWarning() << "Lost signature form field, something went wrong"; } foreach ( SignatureItem *child, item->children ) updateFormFieldSignaturePointer( child, pages ); } void SignatureModelPrivate::notifySetup( const QVector &pages, int setupFlags ) { if ( !( setupFlags & Okular::DocumentObserver::DocumentChanged ) ) { if ( setupFlags & Okular::DocumentObserver::UrlChanged ) { updateFormFieldSignaturePointer( root, pages ); } return; } q->beginResetModel(); qDeleteAll( root->children ); root->children.clear(); foreach ( auto page, pages ) { const int currentPage = page->number(); // get form fields page by page so that page number and index of the form can be determined. const QVector signatureFormFields = SignatureGuiUtils::getSignatureFormFields( document, false, currentPage ); if ( signatureFormFields.isEmpty() ) continue; for ( int i = 0; i < signatureFormFields.count(); i++ ) { const Okular::FormFieldSignature *sf = signatureFormFields[i]; const Okular::SignatureInfo &info = sf->signatureInfo(); // based on whether or not signature form is a nullptr it is decided if clicking on an item should change the viewport. auto *parentItem = new SignatureItem( root, sf, SignatureItem::RevisionInfo, currentPage ); parentItem->displayString = i18n( "Rev. %1: Signed By %2", i+1, info.signerName() ); auto childItem1 = new SignatureItem( parentItem, nullptr, SignatureItem::ValidityStatus, currentPage ); childItem1->displayString = SignatureGuiUtils::getReadableSignatureStatus( info.signatureStatus() ); auto childItem2 = new SignatureItem( parentItem, nullptr, SignatureItem::SigningTime, currentPage ); childItem2->displayString = i18n("Signing Time: %1", info.signingTime().toString( Qt::DefaultLocaleLongDate ) ); auto childItem3 = new SignatureItem( parentItem, nullptr, SignatureItem::Reason, currentPage ); childItem3->displayString = i18n("Reason: %1", !info.reason().isEmpty() ? info.reason() : i18n("Not Available") ); auto childItem4 = new SignatureItem( parentItem, sf, SignatureItem::FieldInfo, currentPage ); childItem4->displayString = i18n("Field: %1 on page %2", sf->name(), currentPage+1 ); } } q->endResetModel(); } QModelIndex SignatureModelPrivate::indexForItem( SignatureItem *item ) const { if ( item->parent ) { const int index = item->parent->children.indexOf( item ); if ( index >= 0 && index < item->parent->children.count() ) return q->createIndex( index, 0, item ); } return QModelIndex(); } SignatureModel::SignatureModel( Okular::Document *doc, QObject *parent ) : QAbstractItemModel( parent ), d_ptr( new SignatureModelPrivate( this ) ) { Q_D( SignatureModel ); d->document = doc; d->document->addObserver( d ); } SignatureModel::~SignatureModel() { Q_D( SignatureModel ); d->document->removeObserver( d ); } int SignatureModel::columnCount( const QModelIndex & ) const { return 1; } QVariant SignatureModel::data( const QModelIndex &index, int role ) const { Q_D( const SignatureModel ); if ( !index.isValid() ) return QVariant(); const SignatureItem *item = static_cast( index.internalPointer() ); if ( item == d->root ) return QVariant(); switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: return item->displayString; case Qt::DecorationRole: if ( item->type == SignatureItem::RevisionInfo ) { const Okular::SignatureInfo::SignatureStatus signatureStatus = item->form->signatureInfo().signatureStatus(); switch ( signatureStatus ) { case Okular::SignatureInfo::SignatureValid: return QIcon::fromTheme( QStringLiteral("dialog-ok") ); case Okular::SignatureInfo::SignatureInvalid: return QIcon::fromTheme( QStringLiteral("dialog-close") ); case Okular::SignatureInfo::SignatureDigestMismatch: return QIcon::fromTheme( QStringLiteral("dialog-warning") ); default: return QIcon::fromTheme( QStringLiteral("dialog-question") ); } } return QIcon(); case FormRole: return QVariant::fromValue(item->form); case PageRole: return item->page; } return QVariant(); } bool SignatureModel::hasChildren( const QModelIndex &parent ) const { if ( !parent.isValid() ) return true; const SignatureItem *item = static_cast( parent.internalPointer() ); return !item->children.isEmpty(); } QModelIndex SignatureModel::index( int row, int column, const QModelIndex &parent ) const { Q_D( const SignatureModel ); if ( row < 0 || column != 0 ) return QModelIndex(); const SignatureItem *item = parent.isValid() ? static_cast( parent.internalPointer() ) : d->root; if ( row < item->children.count() ) return createIndex( row, column, item->children.at( row ) ); return QModelIndex(); } QModelIndex SignatureModel::parent( const QModelIndex &index ) const { Q_D( const SignatureModel ); if ( !index.isValid() ) return QModelIndex(); const SignatureItem *item = static_cast( index.internalPointer() ); return d->indexForItem( item->parent ); } int SignatureModel::rowCount( const QModelIndex &parent ) const { Q_D( const SignatureModel ); const SignatureItem *item = parent.isValid() ? static_cast( parent.internalPointer() ) : d->root; return item->children.count(); } #include "moc_signaturemodel.cpp"