4
0
mirror of https://github.com/QuasarApp/qca.git synced 2025-05-12 10:49:32 +00:00

selector dialog now complete, allow viewing certs, other cleanup

svn path=/trunk/kdesupport/qca/; revision=698089
This commit is contained in:
Justin Karneges 2007-08-09 03:32:54 +00:00
parent c0f32502fa
commit c8446b08b6
11 changed files with 645 additions and 178 deletions

@ -1,30 +1,26 @@
have a graphical busy indicator for:
keystores are busy? (maybe a flashing thing in the status bar)
sign operation in progress (maybe just use an endless QProgressBar)
app icon (may need different sizes of this?) (a pen?)
store icons
system
user
application
smart card
pgp keyring
unknown store/entry icon (can use the same icon for both i think)
animation rather than text for keystore busy?
animation for signing in progress (maybe just use an endless QProgressBar?)
integrated logger window? also allow setting the log level
prompter should not call entrylist unless necessary. right now it starts
async mode on all stores, even if there is no prompting or anything going
on. qcatool has this problem also
report all 3 kinds of diagnostic text somewhere
plugin: plugin dialog invoked from file menu ? also show provider versions
keystore: invoked from keyselectdlg ?
secmessage: "details" button on error dialog?
further cleanup
don't remember pkcs12 password if it was wrong
when verifying a signature:
if the key is valid, import it and ask the user for a friendly name and
import into keyring
if the key is self-signed, ask the user to verify the fingerprint. if
validated, ask user for friendly name and import into keyring
ability to view CertItems, showing cert values and issuer hierarchy
report all 3 kinds of diagnostic text somewhere (plugin, keystore, secmessage)
integrated logger window? also allow setting the log level
items in loadstore ui should not be editable
don't show systemstore or pgpkeyrings
respect !usable state for items

@ -0,0 +1,85 @@
<ui version="4.0" >
<class>CertView</class>
<widget class="QDialog" name="CertView" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle" >
<string>View Certificate</string>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QComboBox" name="cb_chain" />
</item>
<item>
<widget class="QFrame" name="frame" >
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="lb_info" >
<property name="alignment" >
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>cb_chain</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CertView</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>284</x>
<y>278</y>
</hint>
<hint type="destinationlabel" >
<x>291</x>
<y>299</y>
</hint>
</hints>
</connection>
</connections>
</ui>

@ -0,0 +1,166 @@
/*
Copyright (C) 2007 Justin Karneges <justin@affinix.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "certviewdlg.h"
#include <QtCore>
#include <QtGui>
#include <QtCrypto>
#include "ui_certview.h"
// from qcatool
class InfoType
{
public:
QCA::CertificateInfoType type;
QString varname;
QString shortname;
QString name;
QString desc;
InfoType()
{
}
InfoType(QCA::CertificateInfoType _type, const QString &_varname, const QString &_shortname, const QString &_name, const QString &_desc) :
type(_type),
varname(_varname),
shortname(_shortname),
name(_name),
desc(_desc)
{
}
};
static QList<InfoType> makeInfoTypeList(bool legacyEmail = false)
{
QList<InfoType> out;
out += InfoType(QCA::CommonName, "CommonName", "CN", CertViewDlg::tr("Common Name (CN)"), "Full name, domain, anything");
out += InfoType(QCA::Email, "Email", "", CertViewDlg::tr("Email Address"), "");
if(legacyEmail)
out += InfoType(QCA::EmailLegacy, "EmailLegacy", "", CertViewDlg::tr("PKCS#9 Email Address"), "");
out += InfoType(QCA::Organization, "Organization", "O", CertViewDlg::tr("Organization (O)"), "Company, group, etc");
out += InfoType(QCA::OrganizationalUnit, "OrganizationalUnit", "OU", CertViewDlg::tr("Organizational Unit (OU)"), "Division/branch of organization");
out += InfoType(QCA::Locality, "Locality", "", CertViewDlg::tr("Locality (L)"), "City, shire, part of a state");
out += InfoType(QCA::State, "State", "", CertViewDlg::tr("State (ST)"), "State within the country");
out += InfoType(QCA::Country, "Country", "C", CertViewDlg::tr("Country Code (C)"), "2-letter code");
out += InfoType(QCA::IncorporationLocality, "IncorporationLocality", "", CertViewDlg::tr("Incorporation Locality"), "For EV certificates");
out += InfoType(QCA::IncorporationState, "IncorporationState", "", CertViewDlg::tr("Incorporation State"), "For EV certificates");
out += InfoType(QCA::IncorporationCountry, "IncorporationCountry", "", CertViewDlg::tr("Incorporation Country"), "For EV certificates");
out += InfoType(QCA::URI, "URI", "", CertViewDlg::tr("URI"), "");
out += InfoType(QCA::DNS, "DNS", "", CertViewDlg::tr("Domain Name"), "Domain (dnsName)");
out += InfoType(QCA::IPAddress, "IPAddress", "", CertViewDlg::tr("IP Adddress"), "");
out += InfoType(QCA::XMPP, "XMPP", "", CertViewDlg::tr("XMPP Address (JID)"), "From RFC 3920 (id-on-xmppAddr)");
return out;
}
static QString try_print_info(const QString &name, const QStringList &values)
{
QString out;
if(!values.isEmpty())
{
QString value = values.join(", ");
out = QString(" ") + CertViewDlg::tr("%1: %2").arg(name, value) + '\n';
}
return out;
}
static QString print_info(const QString &title, const QCA::CertificateInfo &info)
{
QString out;
QList<InfoType> list = makeInfoTypeList();
out += title + '\n';
foreach(const InfoType &t, list)
out += try_print_info(t.name, info.values(t.type));
return out;
}
static QString cert_info_string(const QCA::Certificate &cert)
{
QString out;
out += CertViewDlg::tr("Serial Number: %1").arg(cert.serialNumber().toString()) + '\n';
out += print_info(CertViewDlg::tr("Subject"), cert.subjectInfo());
out += print_info(CertViewDlg::tr("Issuer"), cert.issuerInfo());
out += CertViewDlg::tr("Validity") + '\n';
out += QString(" ") + CertViewDlg::tr("Not before: %1").arg(cert.notValidBefore().toString()) + '\n';
out += QString(" ") + CertViewDlg::tr("Not after: %1").arg(cert.notValidAfter().toString()) + '\n';
return out;
}
class CertViewDlg::Private : public QObject
{
Q_OBJECT
public:
CertViewDlg *q;
Ui_CertView ui;
QCA::CertificateChain chain;
Private(CertViewDlg *_q) :
QObject(_q),
q(_q)
{
ui.setupUi(q);
connect(ui.cb_chain, SIGNAL(activated(int)), SLOT(cb_activated(int)));
ui.lb_info->setTextInteractionFlags(Qt::TextSelectableByMouse);
}
void update()
{
QStringList names = QCA::makeFriendlyNames(chain);
ui.cb_chain->clear();
foreach(const QString &s, names)
ui.cb_chain->insertItem(ui.cb_chain->count(), s);
updateInfo();
}
void updateInfo()
{
int x = ui.cb_chain->currentIndex();
if(x == -1)
{
ui.lb_info->setText("");
return;
}
ui.lb_info->setText(cert_info_string(chain[x]));
}
private slots:
void cb_activated(int)
{
updateInfo();
}
};
CertViewDlg::CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent) :
QDialog(parent)
{
d = new Private(this);
d->chain = chain;
d->update();
}
CertViewDlg::~CertViewDlg()
{
delete d;
}
#include "certviewdlg.moc"

@ -19,23 +19,26 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MYLISTVIEW_H
#define MYLISTVIEW_H
#ifndef CERTVIEWDLG_H
#define CERTVIEWDLG_H
#include <QListView>
#include <QDialog>
class QAbstractListModel;
namespace QCA
{
class CertificateChain;
}
class MyListView : public QListView
class CertViewDlg : public QDialog
{
Q_OBJECT
public:
MyListView(QWidget *parent = 0);
CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent = 0);
~CertViewDlg();
QAbstractListModel *model;
protected:
virtual void contextMenuEvent(QContextMenuEvent *event);
private:
class Private;
Private *d;
};
#endif

@ -5,8 +5,16 @@ QT += gui
include(pkcs11configdlg/pkcs11configdlg.pri)
HEADERS += prompter.h keyselectdlg.h mylistview.h keystoreview.h
SOURCES += prompter.cpp keyselectdlg.cpp main.cpp
HEADERS += \
prompter.h \
certviewdlg.h \
keyselectdlg.h
FORMS += keyselect.ui mainwin.ui
SOURCES += \
prompter.cpp \
certviewdlg.cpp \
keyselectdlg.cpp \
main.cpp
FORMS += certview.ui keyselect.ui mainwin.ui
RESOURCES += cmssigner.qrc

@ -27,27 +27,33 @@
</widget>
</item>
<item>
<widget class="KeyStoreView" name="lv_stores" />
<widget class="QTreeView" name="lv_stores" />
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
<property name="spacing" >
<number>6</number>
</property>
</widget>
<item>
<widget class="QLabel" name="lb_busy" />
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KeyStoreView</class>
<extends>QTreeView</extends>
<header>keystoreview.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>lv_stores</tabstop>
<tabstop>buttonBox</tabstop>

@ -26,21 +26,40 @@
#include <QtCrypto>
#include "ui_keyselect.h"
class KeyStoreModel : public QStandardItemModel
#define ONLY_SHOW_KEYBUNDLE
typedef QMap<KeySelectDlg::IconType,QPixmap> KeyStoreIconset;
class KeyStoreItemShared
{
Q_OBJECT
public:
QMap<KeySelectDlg::IconType,QPixmap> iconset;
KeyStoreIconset iconset;
QString notAvailableString;
};
QCA::KeyStoreManager ksm;
QList<QCA::KeyStore*> stores;
QList<QStandardItem*> storeItems;
QList< QList<QCA::KeyStoreEntry> > storeEntries;
QList< QList<QStandardItem*> > storeEntryItems;
class KeyStoreItem : public QStandardItem
{
public:
enum Type
{
Store = UserType,
Entry
};
QPixmap entryTypeToIcon(QCA::KeyStoreEntry::Type type)
enum Role
{
NameRole = Qt::UserRole,
SubTypeRole,
AvailabilityRole,
PositionRole
};
QPixmap entryTypeToIcon(QCA::KeyStoreEntry::Type type) const
{
QPixmap out;
if(!_shared)
return out;
const KeyStoreIconset &iconset = _shared->iconset;
switch(type)
{
case QCA::KeyStoreEntry::TypeKeyBundle: out = iconset[KeySelectDlg::IconKeyBundle]; break;
@ -53,9 +72,89 @@ public:
return out;
}
Type _type;
KeyStoreItemShared *_shared;
QCA::KeyStore *keyStore;
QCA::KeyStoreEntry keyStoreEntry;
KeyStoreItem(Type type, KeyStoreItemShared *shared) :
_type(type),
_shared(shared)
{
setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
}
void setStore(const QString &name, QCA::KeyStore::Type type)
{
setData(name, NameRole);
setData((int)type, SubTypeRole);
}
void setEntry(const QString &name, QCA::KeyStoreEntry::Type type, bool available, int pos)
{
setData(name, NameRole);
setData((int)type, SubTypeRole);
setData(available, AvailabilityRole);
setData(pos, PositionRole);
}
virtual QVariant data(int role) const
{
if(role == Qt::DisplayRole)
{
if(_type == Store)
{
return data(NameRole).toString();
}
else if(_type == Entry)
{
QString str = data(NameRole).toString();
if(_shared && !data(AvailabilityRole).toBool())
str += QString(" ") + _shared->notAvailableString;
return str;
}
else
return QStandardItem::data(role);
}
else if(role == Qt::DecorationRole)
{
if(_type == Entry)
{
QCA::KeyStoreEntry::Type type = (QCA::KeyStoreEntry::Type)data(SubTypeRole).toInt();
return entryTypeToIcon(type);
}
else
return QStandardItem::data(role);
}
else
return QStandardItem::data(role);
}
virtual int type() const
{
return _type;
}
virtual QStandardItem *clone() const
{
return new KeyStoreItem(*this);
}
};
class KeyStoreModel : public QStandardItemModel
{
Q_OBJECT
public:
KeyStoreItemShared shared;
QCA::KeyStoreManager ksm;
KeyStoreModel(QObject *parent = 0) :
QStandardItemModel(parent), ksm(this)
{
shared.notAvailableString = tr("(not available)");
// make sure keystores are started
QCA::KeyStoreManager::start();
@ -63,6 +162,19 @@ public:
QStringList list = ksm.keyStores();
foreach(const QString &s, list)
ks_available(s);
setSortRole(KeyStoreItem::PositionRole);
}
KeyStoreItem *itemFromStore(QCA::KeyStore *ks) const
{
for(int n = 0; n < rowCount(); ++n)
{
KeyStoreItem *i = (KeyStoreItem *)item(n);
if(i->keyStore == ks)
return i;
}
return 0;
}
private slots:
@ -70,63 +182,114 @@ private slots:
{
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
// TODO: only list non-pgp identity stores
//if(!ks->holdsIdentities() || ks->type() == QCA::KeyStore::PGPKeyring)
// return;
#ifdef ONLY_SHOW_KEYBUNDLE
// only list stores containing keybundles (non-pgp identities)
if(!ks->holdsIdentities() || ks->type() == QCA::KeyStore::PGPKeyring)
return;
#endif
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
stores += ks;
ks->startAsynchronousMode();
QStandardItem *item = new QStandardItem(ks->name());
storeItems += item;
storeEntries += QList<QCA::KeyStoreEntry>();
storeEntryItems += QList<QStandardItem*>();
appendRow(item);
KeyStoreItem *store_item = new KeyStoreItem(KeyStoreItem::Store, &shared);
store_item->setStore(ks->name(), ks->type());
store_item->keyStore = ks;
ks->startAsynchronousMode();
appendRow(store_item);
}
void ks_updated()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
int at = stores.indexOf(ks);
QList<QCA::KeyStoreEntry> entries = ks->entryList();
KeyStoreItem *store_item = itemFromStore(ks);
Q_ASSERT(store_item);
// TODO: only list keybundles
/*for(int n = 0; n < entries.count(); ++n)
QList<QCA::KeyStoreEntry> newEntries = ks->entryList();
#ifdef ONLY_SHOW_KEYBUNDLE
// ignore entries that are not keybundles
for(int n = 0; n < newEntries.count(); ++n)
{
if(entries[n].type() != QCA::KeyStoreEntry::TypeKeyBundle)
if(newEntries[n].type() != QCA::KeyStoreEntry::TypeKeyBundle)
{
entries.removeAt(n);
newEntries.removeAt(n);
--n; // adjust position
}
}*/
storeEntries[at] = entries;
storeEntryItems[at].clear();
// fake CRL, just to show off the icon
/*if(ks->type() == QCA::KeyStore::System)
{
QStandardItem *item = new QStandardItem(entryTypeToIcon(QCA::KeyStoreEntry::TypeCRL), "Santa's Naughty List");
storeEntryItems[at] += item;
storeItems[at]->appendRow(item);
}*/
foreach(const QCA::KeyStoreEntry &entry, entries)
{
QStandardItem *item = new QStandardItem(entryTypeToIcon(entry.type()), entry.name());
storeEntryItems[at] += item;
storeItems[at]->appendRow(item);
}
#endif
// update the store item itself
store_item->setStore(ks->name(), ks->type());
// handle removed child entries
for(int n = 0; n < store_item->rowCount(); ++n)
{
KeyStoreItem *i = (KeyStoreItem *)store_item->child(n);
// is the existing entry in the new list?
bool found = false;
foreach(const QCA::KeyStoreEntry &ne, newEntries)
{
if(ne.id() == i->keyStoreEntry.id())
{
found = true;
break;
}
}
// if not, remove it
if(!found)
{
store_item->removeRow(n);
--n; // adjust position
}
}
// handle added/updated child entries
for(int n = 0; n < newEntries.count(); ++n)
{
const QCA::KeyStoreEntry &ne = newEntries[n];
// was this entry in the original list?
KeyStoreItem *entry_item = 0;
for(int k = 0; k < store_item->rowCount(); ++k)
{
KeyStoreItem *i = (KeyStoreItem *)store_item->child(k);
if(i->keyStoreEntry.id() == ne.id())
{
entry_item = i;
break;
}
}
// if not, add it
if(!entry_item)
{
entry_item = new KeyStoreItem(KeyStoreItem::Entry, &shared);
entry_item->keyStoreEntry = ne;
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
store_item->appendRow(entry_item);
}
// if so, update it
else
{
entry_item->keyStoreEntry = ne;
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
}
}
store_item->sortChildren(0);
}
void ks_unavailable()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
Q_UNUSED(ks);
KeyStoreItem *store_item = itemFromStore(ks);
Q_ASSERT(store_item);
// TODO: remove from internal list and display
store_item->removeRows(0, store_item->rowCount());
removeRow(store_item->row());
delete ks;
}
};
@ -138,6 +301,7 @@ public:
Ui_KeySelect ui;
KeyStoreModel *model;
QCA::KeyStoreEntry cur_entry;
QAction *actionView;
Private(KeySelectDlg *_q) :
QObject(_q),
@ -146,51 +310,90 @@ public:
ui.setupUi(q);
model = new KeyStoreModel(this);
connect(&model->ksm, SIGNAL(busyStarted()), SLOT(ksm_busyStarted()));
connect(&model->ksm, SIGNAL(busyFinished()), SLOT(ksm_busyFinished()));
if(model->ksm.isBusy())
ksm_busyStarted();
ui.lv_stores->header()->hide();
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
ui.lv_stores->setModel(model);
ui.lv_stores->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui.lv_stores->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), SLOT(stores_selectionChanged(const QItemSelection &, const QItemSelection &)));
connect(ui.lv_stores, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(stores_customContextMenuRequested(const QPoint &)));
actionView = new QAction(tr("&View"), this);
connect(actionView, SIGNAL(triggered()), SLOT(view()));
actionView->setEnabled(false);
}
private slots:
void ksm_busyStarted()
{
ui.lb_busy->setText(tr("Looking for devices..."));
}
void ksm_busyFinished()
{
ui.lb_busy->setText("");
}
void stores_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
Q_UNUSED(deselected);
bool valid = false;
QCA::KeyStoreEntry entry;
KeyStoreItem *i = 0;
if(!selected.indexes().isEmpty())
{
QModelIndex index;
if(!selected.indexes().isEmpty())
index = selected.indexes().first();
if(index.isValid())
{
QModelIndex pindex = index.parent();
// are we clicking on an entry?
if(pindex.isValid())
{
int store_at = pindex.row();
int entry_at = index.row();
QModelIndex index = selected.indexes().first();
i = (KeyStoreItem *)model->itemFromIndex(index);
}
entry = model->storeEntries[store_at][entry_at];
if(entry.type() == QCA::KeyStoreEntry::TypeKeyBundle)
valid = true;
}
bool viewable = false;
bool choosable = false;
if(i && i->type() == KeyStoreItem::Entry)
{
QCA::KeyStoreEntry entry = i->keyStoreEntry;
if(entry.type() == QCA::KeyStoreEntry::TypeKeyBundle)
{
viewable = true;
choosable = true;
cur_entry = entry;
}
}
if(valid)
cur_entry = entry;
else
if(!choosable)
cur_entry = QCA::KeyStoreEntry();
actionView->setEnabled(viewable);
QPushButton *ok = ui.buttonBox->button(QDialogButtonBox::Ok);
if(valid && !ok->isEnabled())
if(choosable && !ok->isEnabled())
ok->setEnabled(true);
else if(!valid && ok->isEnabled())
else if(!choosable && ok->isEnabled())
ok->setEnabled(false);
}
void stores_customContextMenuRequested(const QPoint &pos)
{
QItemSelection selection = ui.lv_stores->selectionModel()->selection();
if(selection.indexes().isEmpty())
return;
QModelIndex index = selection.indexes().first();
KeyStoreItem *i = (KeyStoreItem *)model->itemFromIndex(index);
if(i && i->type() == KeyStoreItem::Entry)
{
QMenu menu(q);
menu.addAction(actionView);
menu.exec(ui.lv_stores->viewport()->mapToGlobal(pos));
}
}
void view()
{
emit q->viewCertificate(cur_entry.keyBundle().certificateChain());
}
};
KeySelectDlg::KeySelectDlg(QWidget *parent) :
@ -206,7 +409,7 @@ KeySelectDlg::~KeySelectDlg()
void KeySelectDlg::setIcon(IconType type, const QPixmap &icon)
{
d->model->iconset[type] = icon;
d->model->shared.iconset[type] = icon;
}
void KeySelectDlg::accept()

@ -28,6 +28,7 @@ class QPixmap;
namespace QCA
{
class CertificateChain;
class KeyStoreEntry;
}
@ -51,12 +52,14 @@ public:
signals:
void selected(const QCA::KeyStoreEntry &entry);
void viewCertificate(const QCA::CertificateChain &chain);
protected slots:
virtual void accept();
private:
class Private;
friend class Private;
Private *d;
};

@ -1,41 +0,0 @@
/*
Copyright (C) 2007 Justin Karneges <justin@affinix.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef KEYSTOREVIEW_H
#define KEYSTOREVIEW_H
#include <QTreeView>
//class QAbstractListModel;
class KeyStoreView : public QTreeView
{
Q_OBJECT
public:
KeyStoreView(QWidget *parent = 0) : QTreeView(parent) {}
//QAbstractListModel *model;
/*protected:
virtual void contextMenuEvent(QContextMenuEvent *event);*/
};
#endif

@ -25,8 +25,8 @@
#include "ui_mainwin.h"
#include "prompter.h"
#include "certviewdlg.h"
#include "keyselectdlg.h"
#include "mylistview.h"
#include "pkcs11configdlg/pkcs11configdlg.h"
#define VERSION "0.0.1"
@ -219,7 +219,12 @@ public:
return QVariant();
if(role == Qt::DisplayRole)
return list[index.row()].name;
{
QString str = list[index.row()].name;
if(!list[index.row()].usable)
str += QString(" ") + tr("(not usable)");
return str;
}
else if(role == Qt::EditRole)
return list[index.row()].name;
else if(role == Qt::DecorationRole && g_icons)
@ -574,7 +579,7 @@ private slots:
QAction *actionView, *actionRename, *actionRemove;
MyListView::MyListView(QWidget *parent) :
/*MyListView::MyListView(QWidget *parent) :
QListView(parent)
{
}
@ -590,7 +595,7 @@ void MyListView::contextMenuEvent(QContextMenuEvent *event)
menu.addAction(actionRename);
menu.addAction(actionRemove);
menu.exec(event->globalPos());
}
}*/
class MyPrompter : public Prompter
{
@ -654,7 +659,7 @@ public:
actionRemove = new QAction(tr("Rem&ove"), this);
// TODO
actionView->setEnabled(false);
//actionView->setEnabled(false);
connect(ui.actionLoadIdentityFile, SIGNAL(triggered()), SLOT(load_file()));
connect(ui.actionLoadIdentityEntry, SIGNAL(triggered()), SLOT(load_device()));
@ -665,7 +670,7 @@ public:
connect(ui.pb_sign, SIGNAL(clicked()), SLOT(do_sign()));
connect(ui.pb_verify, SIGNAL(clicked()), SLOT(do_verify()));
//connect(actionView, SIGNAL(triggered()), SLOT(item_view()));
connect(actionView, SIGNAL(triggered()), SLOT(item_view()));
connect(actionRename, SIGNAL(triggered()), SLOT(item_rename()));
connect(actionRemove, SIGNAL(triggered()), SLOT(item_remove()));
@ -677,12 +682,15 @@ public:
ui.lv_users->setModel(users);
connect(ui.lv_users->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), SLOT(users_selectionChanged(const QItemSelection &, const QItemSelection &)));
ui.lv_users->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui.lv_users, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(users_customContextMenuRequested(const QPoint &)));
roots = new CertListModel(this);
ui.lv_authorities->setModel(roots);
// FIXME: is this redundant?
ui.lv_users->model = users;
ui.lv_authorities->model = roots;
//ui.lv_users->model = users;
//ui.lv_authorities->model = roots;
cms = new QCA::CMS(this);
@ -750,6 +758,7 @@ private slots:
w->setAttribute(Qt::WA_DeleteOnClose, true);
w->setWindowModality(Qt::WindowModal);
connect(w, SIGNAL(selected(const QCA::KeyStoreEntry &)), SLOT(load_device_finished(const QCA::KeyStoreEntry &)));
connect(w, SIGNAL(viewCertificate(const QCA::CertificateChain &)), SLOT(keyselect_viewCertificate(const QCA::CertificateChain &)));
w->setIcon(KeySelectDlg::IconCert, g_icons->cert);
w->setIcon(KeySelectDlg::IconCrl, g_icons->crl);
w->setIcon(KeySelectDlg::IconKeyBundle, g_icons->keybundle);
@ -856,31 +865,38 @@ private slots:
{
Q_UNUSED(deselected);
if(!selected.indexes().isEmpty() && !ui.pb_sign->isEnabled())
int at = -1;
if(!selected.indexes().isEmpty())
{
QModelIndex index = selected.indexes().first();
at = index.row();
}
if(at != -1 && users->list[at].usable && !ui.pb_sign->isEnabled())
ui.pb_sign->setEnabled(true);
else if(selected.indexes().isEmpty() && ui.pb_sign->isEnabled())
else if(ui.pb_sign->isEnabled())
ui.pb_sign->setEnabled(false);
}
/*void item_view()
void item_view()
{
if(ui.lv_identities->hasFocus())
if(ui.lv_users->hasFocus())
{
QItemSelection selection = ui.lv_identities->selectionModel()->selection();
QItemSelection selection = ui.lv_users->selectionModel()->selection();
if(selection.indexes().isEmpty())
return;
QModelIndex index = selection.indexes().first();
identity_view(index.row());
users_view(index.row());
}
else // lv_known
/*else // lv_authorities
{
QItemSelection selection = ui.lv_known->selectionModel()->selection();
if(selection.indexes().isEmpty())
return;
QModelIndex index = selection.indexes().first();
known_view(index.row());
}
}*/
}*/
}
void item_rename()
{
@ -927,6 +943,14 @@ private slots:
printf("identity_view: %d\n", at);
}*/
void users_view(int at)
{
CertItem &i = users->list[at];
CertViewDlg *w = new CertViewDlg(i.chain, this);
w->setAttribute(Qt::WA_DeleteOnClose, true);
w->show();
}
void users_rename(int at)
{
QModelIndex index = users->index(at);
@ -960,6 +984,27 @@ private slots:
roots->removeItem(at);
}
void keyselect_viewCertificate(const QCA::CertificateChain &chain)
{
// TODO: completion?
CertViewDlg *w = new CertViewDlg(chain, (QWidget *)sender());
w->setAttribute(Qt::WA_DeleteOnClose, true);
w->show();
}
void users_customContextMenuRequested(const QPoint &pos)
{
QItemSelection selection = ui.lv_users->selectionModel()->selection();
if(selection.indexes().isEmpty())
return;
QMenu menu(this);
menu.addAction(actionView);
menu.addAction(actionRename);
menu.addAction(actionRemove);
menu.exec(ui.lv_users->viewport()->mapToGlobal(pos));
}
void do_sign()
{
QItemSelection selection = ui.lv_users->selectionModel()->selection();

@ -37,7 +37,7 @@
<number>6</number>
</property>
<item>
<widget class="MyListView" name="lv_users" />
<widget class="QListView" name="lv_users" />
</item>
</layout>
</widget>
@ -53,7 +53,7 @@
<number>6</number>
</property>
<item>
<widget class="MyListView" name="lv_authorities" />
<widget class="QListView" name="lv_authorities" />
</item>
</layout>
</widget>
@ -210,13 +210,6 @@
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>MyListView</class>
<extends>QListView</extends>
<header>mylistview.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>lv_users</tabstop>