10#include <config-libkleo.h>
12#include "keylistview.h"
14#include <kleo_ui_debug.h>
18#include <QFontMetrics>
24#include <gpgme++/key.h>
31static const int updateDelayMilliSecs = 500;
33class Q_DECL_HIDDEN KeyListView::KeyListViewPrivate
37 : updateTimer(nullptr)
41 std::vector<GpgME::Key> keyBuffer;
42 QTimer *updateTimer =
nullptr;
43 std::map<QByteArray, KeyListViewItem *> itemMap;
51} signalReplacements[] = {
57 SIGNAL(itemSelectionChanged()),
58 SLOT(slotEmitSelectionChanged()),
61 SIGNAL(customContextMenuRequested(
QPoint)),
62 SLOT(slotEmitContextMenu(
QPoint)),
65static const int numSignalReplacements =
sizeof signalReplacements /
sizeof *signalReplacements;
67KeyListView::KeyListView(
const ColumnStrategy *columnStrategy,
const DisplayStrategy *displayStrategy,
QWidget *parent,
Qt::WindowFlags f)
69 , mColumnStrategy(columnStrategy)
70 , mDisplayStrategy(displayStrategy)
71 , mHierarchical(false)
72 , d(new KeyListViewPrivate())
77 d->updateTimer =
new QTimer(
this);
78 d->updateTimer->setSingleShot(
true);
80 if (!columnStrategy) {
81 qCWarning(KLEO_UI_LOG) <<
"Kleo::KeyListView: need a column strategy to work with!";
87 for (
int col = 0; !columnStrategy->title(col).isEmpty(); ++col) {
88 headerItem()->setText(col, columnStrategy->title(col));
89 header()->resizeSection(col, columnStrategy->width(col, fm));
90 header()->setSectionResizeMode(col, columnStrategy->resizeMode(col));
93 setAllColumnsShowFocus(
false);
95 for (
int i = 0; i < numSignalReplacements; ++i) {
96 connect(
this, signalReplacements[i].source, signalReplacements[i].target);
100 viewport()->setToolTip(
QString());
103KeyListView::~KeyListView()
105 d->updateTimer->stop();
110 Q_ASSERT(d->itemMap.size() == 0);
112 delete mColumnStrategy;
113 mColumnStrategy =
nullptr;
114 delete mDisplayStrategy;
115 mDisplayStrategy =
nullptr;
121 if (
auto *item = lvi_cast<KeyListViewItem>(qlvi)) {
122 deregisterItem(item);
127void KeyListView::setHierarchical(
bool hier)
129 if (hier == mHierarchical) {
132 mHierarchical = hier;
136 scatterGathered(firstChild());
140void KeyListView::slotAddKey(
const GpgME::Key &key)
146 d->keyBuffer.push_back(key);
147 if (!d->updateTimer->isActive()) {
148 d->updateTimer->start(updateDelayMilliSecs);
152void KeyListView::slotUpdateTimeout()
154 if (d->keyBuffer.empty()) {
159 if (wasUpdatesEnabled) {
162 qCDebug(KLEO_UI_LOG) <<
"Kleo::KeyListView::slotUpdateTimeout(): processing" << d->keyBuffer.size() <<
"items en block";
163 if (hierarchical()) {
164 for (std::vector<GpgME::Key>::const_iterator it = d->keyBuffer.begin(); it != d->keyBuffer.end(); ++it) {
165 doHierarchicalInsert(*it);
169 for (std::vector<GpgME::Key>::const_iterator it = d->keyBuffer.begin(); it != d->keyBuffer.end(); ++it) {
170 (void)
new KeyListViewItem(
this, *it);
173 if (wasUpdatesEnabled) {
176 d->keyBuffer.clear();
179void KeyListView::clear()
181 d->updateTimer->stop();
182 d->keyBuffer.clear();
189void KeyListView::registerItem(KeyListViewItem *item)
195 const QByteArray fpr = item->key().primaryFingerprint();
197 d->itemMap.insert(std::make_pair(fpr, item));
201void KeyListView::deregisterItem(
const KeyListViewItem *item)
207 auto it = d->itemMap.find(item->key().primaryFingerprint());
208 if (it == d->itemMap.end()) {
214 if (it->second != item) {
215 qCWarning(KLEO_UI_LOG) <<
"deregisterItem:"
216 <<
"item " << item->key().primaryFingerprint()
217 <<
"it->second" << (it->second ? it->second->key().primaryFingerprint() :
"is null");
220 d->itemMap.erase(it);
223void KeyListView::doHierarchicalInsert(
const GpgME::Key &key)
225 const QByteArray fpr = key.primaryFingerprint();
229 KeyListViewItem *item =
nullptr;
231 if (KeyListViewItem *
parent = itemByFingerprint(key.chainID())) {
232 item =
new KeyListViewItem(
parent, key);
233 parent->setExpanded(
true);
237 item =
new KeyListViewItem(
this, key);
240 d->itemMap.insert(std::make_pair(fpr, item));
243void KeyListView::gatherScattered()
245 KeyListViewItem *item = firstChild();
247 KeyListViewItem *cur = item;
248 item = item->nextSibling();
249 if (cur->key().isRoot()) {
252 if (KeyListViewItem *
parent = itemByFingerprint(cur->key().chainID())) {
257 parent->setExpanded(
true);
262void KeyListView::scatterGathered(KeyListViewItem *
start)
264 KeyListViewItem *item =
start;
266 KeyListViewItem *cur = item;
267 item = item->nextSibling();
269 scatterGathered(lvi_cast<KeyListViewItem>(cur->
child(0)));
274 static_cast<KeyListViewItem *
>(cur->
parent())->takeItem(cur);
282KeyListViewItem *KeyListView::itemByFingerprint(
const QByteArray &s)
const
287 const std::map<QByteArray, KeyListViewItem *>::const_iterator it = d->itemMap.find(s);
288 if (it == d->itemMap.end()) {
294void KeyListView::slotRefreshKey(
const GpgME::Key &key)
296 const char *fpr = key.primaryFingerprint();
300 if (KeyListViewItem *item = itemByFingerprint(fpr)) {
312 if (!item || lvi_cast<KeyListViewItem>(item)) {
313 Q_EMIT doubleClicked(
static_cast<KeyListViewItem *
>(item), col);
319 if (!item || lvi_cast<KeyListViewItem>(item)) {
320 Q_EMIT returnPressed(
static_cast<KeyListViewItem *
>(item));
324void KeyListView::slotEmitSelectionChanged()
326 Q_EMIT selectionChanged(selectedItem());
329void KeyListView::slotEmitContextMenu(
const QPoint &pos)
332 if (!item || lvi_cast<KeyListViewItem>(item)) {
343KeyListViewItem::KeyListViewItem(KeyListView *parent,
const GpgME::Key &key)
350KeyListViewItem::KeyListViewItem(KeyListView *parent, KeyListViewItem *after,
const GpgME::Key &key)
357KeyListViewItem::KeyListViewItem(KeyListViewItem *parent,
const GpgME::Key &key)
360 Q_ASSERT(parent && parent->listView());
364KeyListViewItem::KeyListViewItem(KeyListViewItem *parent, KeyListViewItem *after,
const GpgME::Key &key)
367 Q_ASSERT(parent && parent->listView());
371KeyListViewItem::~KeyListViewItem()
384 if (KeyListView *lv = listView()) {
385 lv->deregisterItem(
this);
389void KeyListViewItem::setKey(
const GpgME::Key &key)
391 KeyListView *lv = listView();
393 lv->deregisterItem(
this);
397 lv->registerItem(
this);
402 const KeyListView::ColumnStrategy *cs = lv ? lv->columnStrategy() :
nullptr;
406 const KeyListView::DisplayStrategy *ds = lv->displayStrategy();
408 for (
int i = 0; i < numCols; ++i) {
410 const auto accessibleText = cs->accessibleText(key, i);
411 if (!accessibleText.isEmpty()) {
427QString KeyListViewItem::toolTip(
int col)
const
429 return listView() && listView()->columnStrategy() ? listView()->columnStrategy()->toolTip(key(), col) :
QString();
434 if (other.
type() != RTTI || !listView() || !listView()->columnStrategy()) {
437 const auto that =
static_cast<const KeyListViewItem *
>(&other);
438 return listView()->columnStrategy()->compare(this->key(), that->key(),
treeWidget()->sortColumn()) < 0;
444 if (
auto *item = lvi_cast<KeyListViewItem>(qlvi)) {
445 listView()->deregisterItem(item);
456KeyListView::ColumnStrategy::~ColumnStrategy()
460int KeyListView::ColumnStrategy::compare(
const GpgME::Key &key1,
const GpgME::Key &key2,
const int col)
const
465int KeyListView::ColumnStrategy::width(
int col,
const QFontMetrics &fm)
const
470QString KeyListView::ColumnStrategy::toolTip(
const GpgME::Key &key,
int col)
const
472 return text(key, col);
481KeyListView::DisplayStrategy::~DisplayStrategy()
486QFont KeyListView::DisplayStrategy::keyFont(
const GpgME::Key &,
const QFont &
font)
const
492QColor KeyListView::DisplayStrategy::keyForeground(
const GpgME::Key &,
const QColor &fg)
const
498QColor KeyListView::DisplayStrategy::keyBackground(
const GpgME::Key &,
const QColor &bg)
const
510KeyListView *KeyListViewItem::listView()
const
515KeyListViewItem *KeyListViewItem::nextSibling()
const
518 const int myIndex =
parent()->indexOfChild(
const_cast<KeyListViewItem *
>(
this));
519 return static_cast<KeyListViewItem *
>(
parent()->child(myIndex + 1));
521 const int myIndex = treeWidget()->indexOfTopLevelItem(
const_cast<KeyListViewItem *
>(
this));
522 return static_cast<KeyListViewItem *
>(treeWidget()->topLevelItem(myIndex + 1));
525KeyListViewItem *KeyListView::firstChild()
const
530KeyListViewItem *KeyListView::selectedItem()
const
536 return selection.
first();
544 if (
auto *i = lvi_cast<KeyListViewItem>(selectedItem)) {
551bool KeyListView::isMultiSelection()
const
559 if (selectedItem()) {
560 slotEmitReturnPressed(selectedItem());
566#include "moc_keylistview.cpp"
Q_SCRIPTABLE Q_NOREPLY void start()
bool isEmpty() const const
int horizontalAdvance(QChar ch) const const
bool isNull() const const
void append(QList< T > &&value)
bool isEmpty() const const
QObject * parent() const const
int localeAwareCompare(QStringView s1, QStringView s2)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
virtual void keyPressEvent(QKeyEvent *event) override
void setText(int column, const QString &text)