File indexing completed on 2024-04-21 05:50:47

0001 /*
0002     SPDX-FileCopyrightText: 2008 Rolf Eike Beer <kde@opensource.sf-tec.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 #include "keytreeview.h"
0007 
0008 #include "model/keylistproxymodel.h"
0009 #include "model/kgpgitemmodel.h"
0010 #include "model/kgpgitemnode.h"
0011 #include "transactions/kgpgexport.h"
0012 #include "transactions/kgpgimport.h"
0013 
0014 #include <KConfigGroup>
0015 #include <KLocalizedString>
0016 #include <KMessageBox>
0017 #include <KUrlMimeData>
0018 
0019 #include <QDrag>
0020 #include <QDragMoveEvent>
0021 #include <QDropEvent>
0022 #include <QHeaderView>
0023 #include <QMimeData>
0024 
0025 KeyTreeView::KeyTreeView(QWidget *parent, KeyListProxyModel *model)
0026     : QTreeView(parent), m_proxy(model)
0027 {
0028     setModel(model);
0029     setDragEnabled(true);
0030     setDragDropMode(DragDrop);
0031     setAcceptDrops(true);
0032     setEditTriggers(QTreeView::NoEditTriggers);
0033 }
0034 
0035 std::vector<KGpgNode *>
0036 KeyTreeView::selectedNodes(bool *psame, KgpgCore::KgpgItemType *pt) const
0037 {
0038     QModelIndexList selidx = selectedIndexes();
0039     std::vector<KGpgNode *> ndlist;
0040     KgpgItemType tp = {};
0041     bool sametype = true;
0042 
0043     if (selidx.isEmpty()) {
0044         if (pt != nullptr)
0045             *pt = tp;
0046         if (psame != nullptr)
0047             *psame = sametype;
0048         return ndlist;
0049     }
0050 
0051     tp = m_proxy->nodeForIndex(selidx[0])->getType();
0052 
0053     for (int i = 0; i < selidx.count(); i++) {
0054         if (selidx[i].column() != 0)
0055             continue;
0056         KGpgNode *nd = m_proxy->nodeForIndex(selidx[i]);
0057 
0058         if (nd->getType() != tp) {
0059             tp |= nd->getType();
0060             sametype = false;
0061         }
0062 
0063         ndlist.push_back(nd);
0064     }
0065 
0066     if (pt != nullptr)
0067         *pt = tp;
0068     if (psame != nullptr)
0069         *psame = sametype;
0070     return ndlist;
0071 }
0072 
0073 KGpgNode *
0074 KeyTreeView::selectedNode() const
0075 {
0076     QModelIndexList selidx = selectedIndexes();
0077 
0078     if (selidx.isEmpty())
0079         return nullptr;
0080 
0081     return m_proxy->nodeForIndex(selidx[0]);
0082 }
0083 
0084 void
0085 KeyTreeView::selectNode(KGpgNode *nd)
0086 {
0087     if (nd == nullptr)
0088         return;
0089 
0090     QModelIndex idx = m_proxy->nodeIndex(nd);
0091 
0092     selectionModel()->select(idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
0093     selectionModel()->setCurrentIndex(idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
0094 }
0095 
0096 void
0097 KeyTreeView::restoreLayout(KConfigGroup &cg)
0098 {
0099     QStringList cols(cg.readEntry("ColumnWidths", QStringList()));
0100     int i = 0;
0101 
0102     QStringList::ConstIterator it(cols.constBegin());
0103     const QStringList::ConstIterator itEnd(cols.constEnd());
0104     for (; it != itEnd; ++it)
0105         setColumnWidth(i++, (*it).toInt());
0106 
0107     while (i < model()->columnCount(QModelIndex())) {
0108         int width = 100;
0109         switch (i) {
0110         case KEYCOLUMN_NAME:
0111             width = 250;
0112             break;
0113         case KEYCOLUMN_EMAIL:
0114             width = 150;
0115             break;
0116         case KEYCOLUMN_TRUST:
0117             // the trust column needs to be only that big as the header which is done automatically
0118             i++;
0119             continue;
0120         }
0121         setColumnWidth(i, width);
0122         i++;
0123     }
0124 
0125     if (cg.hasKey("SortColumn")) {
0126         Qt::SortOrder order = cg.readEntry("SortAscending", true) ? Qt::AscendingOrder : Qt::DescendingOrder;
0127         sortByColumn(cg.readEntry("SortColumn", 0), order);
0128     }
0129 }
0130 
0131 void
0132 KeyTreeView::saveLayout(KConfigGroup &cg) const
0133 {
0134     QStringList widths;
0135 
0136     const int colCount = model()->columnCount();
0137 
0138     for (int i = 0; i < colCount; ++i) {
0139         widths << QString::number(columnWidth(i));
0140     }
0141     cg.writeEntry("ColumnWidths", widths);
0142         cg.writeEntry( "SortColumn", header ()->sortIndicatorSection () );
0143         cg.writeEntry( "SortAscending", ( header()->sortIndicatorOrder () == Qt::AscendingOrder ) );
0144 }
0145 
0146 void
0147 KeyTreeView::contentsDragMoveEvent(QDragMoveEvent *e)
0148 {
0149     e->setAccepted(e->mimeData()->hasUrls());
0150 }
0151 
0152 void
0153 KeyTreeView::contentsDropEvent(QDropEvent *o)
0154 {
0155     QList<QUrl> uriList = KUrlMimeData::urlsFromMimeData(o->mimeData());
0156     if (!uriList.isEmpty()) {
0157         if (KMessageBox::questionTwoActions(this, i18n("<p>Do you want to import file <b>%1</b> into your key ring?</p>",
0158                     uriList.first().path()), QString(), KGuiItem(i18n("Import")),
0159                     KGuiItem(i18n("Do Not Import"))) != KMessageBox::PrimaryAction)
0160             return;
0161 
0162         Q_EMIT importDrop(uriList);
0163     }
0164 }
0165 
0166 void
0167 KeyTreeView::startDrag(Qt::DropActions supportedActions)
0168 {
0169     const auto nodes = selectedNodes();
0170 
0171     if (nodes.empty())
0172         return;
0173 
0174     const KGpgNode * const nd = nodes.front();
0175     const QString keyid = nd->getId();
0176 
0177     if (!(nd->getType() & ITYPE_PUBLIC))
0178         return;
0179 
0180     KGpgExport *exp = new KGpgExport(this, QStringList(keyid));
0181     exp->start();
0182 
0183     int result = exp->waitForFinished();
0184 
0185     if (result == KGpgTransaction::TS_OK) {
0186         QMimeData *m = new QMimeData();
0187         m->setText(QString::fromLatin1( exp->getOutputData() ));
0188         QDrag *drag = new QDrag(this);
0189         drag->setMimeData(m);
0190         drag->exec(supportedActions, Qt::IgnoreAction);
0191         // do NOT delete drag.
0192     }
0193 
0194     delete exp;
0195 }
0196 
0197 void
0198 KeyTreeView::resizeColumnsToContents()
0199 {
0200     for (int i = m_proxy->columnCount() - 1; i >= 0; i--)
0201         resizeColumnToContents(i);
0202 }
0203 
0204 void
0205 KeyTreeView::keyPressEvent(QKeyEvent *event)
0206 {
0207     if (event->key() == Qt::Key_Return) {
0208         if (!event->isAutoRepeat())
0209             Q_EMIT returnPressed();
0210 
0211         return;
0212     }
0213     QTreeView::keyPressEvent(event);
0214 }
0215 
0216 bool
0217 KeyTreeView::isEditing() const
0218 {
0219     return (state() == EditingState);
0220 }