Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34140258
keylistcontroller.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
29 KB
Subscribers
None
keylistcontroller.cpp
View Options
/* -*- mode: c++; c-basic-offset:4 -*-
controllers/keylistcontroller.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include
<config-kleopatra.h>
#include
"keylistcontroller.h"
#include
"tabwidget.h"
#include
<smartcard/readerstatus.h>
#include
<utils/action_data.h>
#include
<settings.h>
#include
"tooltippreferences.h"
#include
"kleopatra_debug.h"
#include
"commands/exportcertificatecommand.h"
#include
"commands/exportopenpgpcertstoservercommand.h"
#ifdef QGPGME_SUPPORTS_SECRET_KEY_EXPORT
# include "commands/exportsecretkeycommand.h"
#else
# include "commands/exportsecretkeycommand_old.h"
#endif
#include
"commands/importcertificatefromfilecommand.h"
#include
"commands/changepassphrasecommand.h"
#include
"commands/lookupcertificatescommand.h"
#include
"commands/reloadkeyscommand.h"
#include
"commands/refreshx509certscommand.h"
#include
"commands/refreshopenpgpcertscommand.h"
#include
"commands/detailscommand.h"
#include
"commands/deletecertificatescommand.h"
#include
"commands/decryptverifyfilescommand.h"
#include
"commands/signencryptfilescommand.h"
#include
"commands/signencryptfoldercommand.h"
#include
"commands/clearcrlcachecommand.h"
#include
"commands/dumpcrlcachecommand.h"
#include
"commands/dumpcertificatecommand.h"
#include
"commands/importcrlcommand.h"
#include
"commands/changeexpirycommand.h"
#include
"commands/changeownertrustcommand.h"
#include
"commands/changeroottrustcommand.h"
#include
"commands/certifycertificatecommand.h"
#include
"commands/revokecertificationcommand.h"
#include
"commands/adduseridcommand.h"
#include
"commands/newcertificatecommand.h"
#include
"commands/checksumverifyfilescommand.h"
#include
"commands/checksumcreatefilescommand.h"
#include
"commands/exportpaperkeycommand.h"
#include
"commands/revokekeycommand.h"
#include
<Libkleo/KeyCache>
#include
<Libkleo/KeyListModel>
#include
<Libkleo/Formatting>
#include
<gpgme++/key.h>
#include
<KActionCollection>
#include
<KLocalizedString>
#include
<QAbstractItemView>
#include
<QPointer>
#include
<QItemSelectionModel>
#include
<QAction>
#include
<algorithm>
#include
<iterator>
// needed for GPGME_VERSION_NUMBER
#include
<gpgme.h>
using
namespace
Kleo
;
using
namespace
Kleo
::
Commands
;
using
namespace
Kleo
::
SmartCard
;
using
namespace
GpgME
;
#ifndef QGPGME_SUPPORTS_SECRET_KEY_EXPORT
using
Kleo
::
Commands
::
Compat
::
ExportSecretKeyCommand
;
#endif
class
KeyListController
::
Private
{
friend
class
::
Kleo
::
KeyListController
;
KeyListController
*
const
q
;
public
:
explicit
Private
(
KeyListController
*
qq
);
~
Private
();
void
connectView
(
QAbstractItemView
*
view
);
void
connectCommand
(
Command
*
cmd
);
void
connectTabWidget
();
void
disconnectTabWidget
();
void
addCommand
(
Command
*
cmd
)
{
connectCommand
(
cmd
);
commands
.
insert
(
std
::
lower_bound
(
commands
.
begin
(),
commands
.
end
(),
cmd
),
cmd
);
}
void
addView
(
QAbstractItemView
*
view
)
{
connectView
(
view
);
views
.
insert
(
std
::
lower_bound
(
views
.
begin
(),
views
.
end
(),
view
),
view
);
}
void
removeView
(
QAbstractItemView
*
view
)
{
view
->
disconnect
(
q
);
view
->
selectionModel
()
->
disconnect
(
q
);
views
.
erase
(
std
::
remove
(
views
.
begin
(),
views
.
end
(),
view
),
views
.
end
());
}
public
:
void
slotDestroyed
(
QObject
*
o
)
{
qCDebug
(
KLEOPATRA_LOG
)
<<
(
void
*
)
o
;
views
.
erase
(
std
::
remove
(
views
.
begin
(),
views
.
end
(),
o
),
views
.
end
());
commands
.
erase
(
std
::
remove
(
commands
.
begin
(),
commands
.
end
(),
o
),
commands
.
end
());
}
void
slotDoubleClicked
(
const
QModelIndex
&
idx
);
void
slotActivated
(
const
QModelIndex
&
idx
);
void
slotSelectionChanged
(
const
QItemSelection
&
old
,
const
QItemSelection
&
new_
);
void
slotContextMenu
(
const
QPoint
&
pos
);
void
slotCommandFinished
();
void
slotAddKey
(
const
Key
&
key
);
void
slotAboutToRemoveKey
(
const
Key
&
key
);
void
slotProgress
(
const
QString
&
what
,
int
current
,
int
total
)
{
Q_EMIT
q
->
progress
(
current
,
total
);
if
(
!
what
.
isEmpty
())
{
Q_EMIT
q
->
message
(
what
);
}
}
void
slotActionTriggered
();
void
slotCurrentViewChanged
(
QAbstractItemView
*
view
)
{
if
(
view
&&
!
std
::
binary_search
(
views
.
cbegin
(),
views
.
cend
(),
view
))
{
qCDebug
(
KLEOPATRA_LOG
)
<<
"you need to register view"
<<
view
<<
"before trying to set it as the current view!"
;
addView
(
view
);
}
currentView
=
view
;
q
->
enableDisableActions
(
view
?
view
->
selectionModel
()
:
nullptr
);
}
private
:
int
toolTipOptions
()
const
;
private
:
static
Command
::
Restrictions
calculateRestrictionsMask
(
const
QItemSelectionModel
*
sm
);
private
:
struct
action_item
{
QPointer
<
QAction
>
action
;
Command
::
Restrictions
restrictions
;
Command
*
(
*
createCommand
)(
QAbstractItemView
*
,
KeyListController
*
);
};
std
::
vector
<
action_item
>
actions
;
std
::
vector
<
QAbstractItemView
*>
views
;
std
::
vector
<
Command
*>
commands
;
QPointer
<
QWidget
>
parentWidget
;
QPointer
<
TabWidget
>
tabWidget
;
QPointer
<
QAbstractItemView
>
currentView
;
QPointer
<
AbstractKeyListModel
>
flatModel
,
hierarchicalModel
;
};
KeyListController
::
Private
::
Private
(
KeyListController
*
qq
)
:
q
(
qq
),
actions
(),
views
(),
commands
(),
parentWidget
(),
tabWidget
(),
flatModel
(),
hierarchicalModel
()
{
connect
(
KeyCache
::
instance
().
get
(),
&
KeyCache
::
added
,
q
,
[
this
](
const
GpgME
::
Key
&
key
)
{
slotAddKey
(
key
);
});
connect
(
KeyCache
::
instance
().
get
(),
&
KeyCache
::
aboutToRemove
,
q
,
[
this
](
const
GpgME
::
Key
&
key
)
{
slotAboutToRemoveKey
(
key
);
});
}
KeyListController
::
Private
::~
Private
()
{}
KeyListController
::
KeyListController
(
QObject
*
p
)
:
QObject
(
p
),
d
(
new
Private
(
this
))
{
}
KeyListController
::~
KeyListController
()
{}
void
KeyListController
::
Private
::
slotAddKey
(
const
Key
&
key
)
{
// ### make model act on keycache directly...
if
(
flatModel
)
{
flatModel
->
addKey
(
key
);
}
if
(
hierarchicalModel
)
{
hierarchicalModel
->
addKey
(
key
);
}
}
void
KeyListController
::
Private
::
slotAboutToRemoveKey
(
const
Key
&
key
)
{
// ### make model act on keycache directly...
if
(
flatModel
)
{
flatModel
->
removeKey
(
key
);
}
if
(
hierarchicalModel
)
{
hierarchicalModel
->
removeKey
(
key
);
}
}
void
KeyListController
::
addView
(
QAbstractItemView
*
view
)
{
if
(
!
view
||
std
::
binary_search
(
d
->
views
.
cbegin
(),
d
->
views
.
cend
(),
view
))
{
return
;
}
d
->
addView
(
view
);
}
void
KeyListController
::
removeView
(
QAbstractItemView
*
view
)
{
if
(
!
view
||
!
std
::
binary_search
(
d
->
views
.
cbegin
(),
d
->
views
.
cend
(),
view
))
{
return
;
}
d
->
removeView
(
view
);
}
void
KeyListController
::
setCurrentView
(
QAbstractItemView
*
view
)
{
d
->
slotCurrentViewChanged
(
view
);
}
std
::
vector
<
QAbstractItemView
*>
KeyListController
::
views
()
const
{
return
d
->
views
;
}
void
KeyListController
::
setFlatModel
(
AbstractKeyListModel
*
model
)
{
if
(
model
==
d
->
flatModel
)
{
return
;
}
d
->
flatModel
=
model
;
if
(
model
)
{
model
->
clear
();
if
(
KeyCache
::
instance
()
->
initialized
())
{
model
->
addKeys
(
KeyCache
::
instance
()
->
keys
());
}
model
->
setToolTipOptions
(
d
->
toolTipOptions
());
}
}
void
KeyListController
::
setHierarchicalModel
(
AbstractKeyListModel
*
model
)
{
if
(
model
==
d
->
hierarchicalModel
)
{
return
;
}
d
->
hierarchicalModel
=
model
;
if
(
model
)
{
model
->
clear
();
if
(
KeyCache
::
instance
()
->
initialized
())
{
model
->
addKeys
(
KeyCache
::
instance
()
->
keys
());
}
model
->
setToolTipOptions
(
d
->
toolTipOptions
());
}
}
void
KeyListController
::
setTabWidget
(
TabWidget
*
tabWidget
)
{
if
(
tabWidget
==
d
->
tabWidget
)
{
return
;
}
d
->
disconnectTabWidget
();
d
->
tabWidget
=
tabWidget
;
d
->
connectTabWidget
();
d
->
slotCurrentViewChanged
(
tabWidget
?
tabWidget
->
currentView
()
:
nullptr
);
}
void
KeyListController
::
setParentWidget
(
QWidget
*
parent
)
{
d
->
parentWidget
=
parent
;
}
QWidget
*
KeyListController
::
parentWidget
()
const
{
return
d
->
parentWidget
;
}
static
const
struct
{
const
char
*
signal
;
const
char
*
slot
;
}
tabs2controller
[]
=
{
{
SIGNAL
(
viewAdded
(
QAbstractItemView
*
)),
SLOT
(
addView
(
QAbstractItemView
*
))
},
{
SIGNAL
(
viewAboutToBeRemoved
(
QAbstractItemView
*
)),
SLOT
(
removeView
(
QAbstractItemView
*
))
},
{
SIGNAL
(
currentViewChanged
(
QAbstractItemView
*
)),
SLOT
(
slotCurrentViewChanged
(
QAbstractItemView
*
))
},
};
static
const
unsigned
int
numTabs2Controller
=
sizeof
tabs2controller
/
sizeof
*
tabs2controller
;
void
KeyListController
::
Private
::
connectTabWidget
()
{
if
(
!
tabWidget
)
{
return
;
}
const
auto
views
=
tabWidget
->
views
();
std
::
for_each
(
views
.
cbegin
(),
views
.
cend
(),
[
this
](
QAbstractItemView
*
view
)
{
addView
(
view
);
});
for
(
unsigned
int
i
=
0
;
i
<
numTabs2Controller
;
++
i
)
{
connect
(
tabWidget
,
tabs2controller
[
i
].
signal
,
q
,
tabs2controller
[
i
].
slot
);
}
}
void
KeyListController
::
Private
::
disconnectTabWidget
()
{
if
(
!
tabWidget
)
{
return
;
}
for
(
unsigned
int
i
=
0
;
i
<
numTabs2Controller
;
++
i
)
{
disconnect
(
tabWidget
,
tabs2controller
[
i
].
signal
,
q
,
tabs2controller
[
i
].
slot
);
}
const
auto
views
=
tabWidget
->
views
();
std
::
for_each
(
views
.
cbegin
(),
views
.
cend
(),
[
this
](
QAbstractItemView
*
view
)
{
removeView
(
view
);
});
}
AbstractKeyListModel
*
KeyListController
::
flatModel
()
const
{
return
d
->
flatModel
;
}
AbstractKeyListModel
*
KeyListController
::
hierarchicalModel
()
const
{
return
d
->
hierarchicalModel
;
}
QAbstractItemView
*
KeyListController
::
currentView
()
const
{
return
d
->
currentView
;
}
TabWidget
*
KeyListController
::
tabWidget
()
const
{
return
d
->
tabWidget
;
}
void
KeyListController
::
createActions
(
KActionCollection
*
coll
)
{
const
std
::
vector
<
action_data
>
common_and_openpgp_action_data
=
{
// File menu
{
"file_new_certificate"
,
i18n
(
"New Key Pair..."
),
QString
(),
"view-certificate-add"
,
nullptr
,
nullptr
,
QStringLiteral
(
"Ctrl+N"
),
false
,
true
},
{
"file_export_certificates"
,
i18n
(
"Export..."
),
i18n
(
"Export the selected certificate (public key) to a file"
),
"view-certificate-export"
,
nullptr
,
nullptr
,
QStringLiteral
(
"Ctrl+E"
),
false
,
true
},
{
"file_export_certificates_to_server"
,
i18n
(
"Publish on Server..."
),
i18n
(
"Publish the selected certificate (public key) on a public keyserver"
),
"view-certificate-export-server"
,
nullptr
,
nullptr
,
QStringLiteral
(
"Ctrl+Shift+E"
),
false
,
true
},
{
"file_export_secret_keys"
,
i18n
(
"Backup Secret Keys..."
),
QString
(),
"view-certificate-export-secret"
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"file_export_paper_key"
,
i18n
(
"Print Secret Key..."
),
QString
(),
"document-print"
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"file_lookup_certificates"
,
i18n
(
"Lookup on Server..."
),
i18n
(
"Search for certificates online using a public keyserver"
),
"edit-find"
,
nullptr
,
nullptr
,
QStringLiteral
(
"Shift+Ctrl+I"
),
false
,
true
},
{
"file_import_certificates"
,
i18n
(
"Import..."
),
i18n
(
"Import a certificate from a file"
),
"view-certificate-import"
,
nullptr
,
nullptr
,
QStringLiteral
(
"Ctrl+I"
),
false
,
true
},
{
"file_decrypt_verify_files"
,
i18n
(
"Decrypt/Verify..."
),
i18n
(
"Decrypt and/or verify files"
),
"document-edit-decrypt-verify"
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"file_sign_encrypt_files"
,
i18n
(
"Sign/Encrypt..."
),
i18n
(
"Encrypt and/or sign files"
),
"document-edit-sign-encrypt"
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"file_sign_encrypt_folder"
,
i18n
(
"Sign/Encrypt Folder..."
),
i18n
(
"Encrypt and/or sign folders"
),
nullptr
/*"folder-edit-sign-encrypt"*/
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"file_checksum_create_files"
,
i18n
(
"Create Checksum Files..."
),
QString
(),
nullptr
/*"document-checksum-create"*/
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"file_checksum_verify_files"
,
i18n
(
"Verify Checksum Files..."
),
QString
(),
nullptr
/*"document-checksum-verify"*/
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
// View menu
{
"view_redisplay"
,
i18n
(
"Redisplay"
),
QString
(),
"view-refresh"
,
nullptr
,
nullptr
,
QStringLiteral
(
"F5"
),
false
,
true
},
{
"view_stop_operations"
,
i18n
(
"Stop Operation"
),
QString
(),
"process-stop"
,
this
,
SLOT
(
cancelCommands
()),
QStringLiteral
(
"Escape"
),
false
,
false
},
{
"view_certificate_details"
,
i18n
(
"Details"
),
QString
(),
"dialog-information"
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
// Certificate menu
#ifdef QGPGME_SUPPORTS_KEY_REVOCATION
{
"certificates_revoke"
,
i18n
(
"Revoke Certificate..."
),
i18n
(
"Revoke the selected OpenPGP certificate"
),
"view-certificate-revoke"
,
nullptr
,
nullptr
,
{},
false
,
true
},
#endif
{
"certificates_delete"
,
i18n
(
"Delete"
),
i18n
(
"Delete selected certificates"
),
"edit-delete"
,
nullptr
,
nullptr
,
QStringLiteral
(
"Delete"
),
false
,
true
},
{
"certificates_certify_certificate"
,
i18n
(
"Certify..."
),
i18n
(
"Certify the validity of the selected certificate"
),
"view-certificate-sign"
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"certificates_revoke_certification"
,
i18n
(
"Revoke Certification..."
),
i18n
(
"Revoke the certification of the selected certificate"
),
"view-certificate-revoke"
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"certificates_change_expiry"
,
i18n
(
"Change Expiry Date..."
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"certificates_change_owner_trust"
,
i18n
(
"Change Certification Trust..."
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"certificates_change_passphrase"
,
i18n
(
"Change Passphrase..."
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"certificates_add_userid"
,
i18n
(
"Add User ID..."
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
// Tools menu
{
"tools_refresh_openpgp_certificates"
,
i18n
(
"Refresh OpenPGP Certificates"
),
QString
(),
"view-refresh"
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
// Window menu
// (come from TabWidget)
// Help menu
// (come from MainWindow)
};
static
const
std
::
vector
<
action_data
>
cms_action_data
=
{
// Certificate menu
{
"certificates_trust_root"
,
i18n
(
"Trust Root Certificate"
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"certificates_distrust_root"
,
i18n
(
"Distrust Root Certificate"
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"certificates_dump_certificate"
,
i18n
(
"Technical Details"
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
// Tools menu
{
"tools_refresh_x509_certificates"
,
i18n
(
"Refresh S/MIME Certificates"
),
QString
(),
"view-refresh"
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"crl_clear_crl_cache"
,
i18n
(
"Clear CRL Cache"
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"crl_dump_crl_cache"
,
i18n
(
"Dump CRL Cache"
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
{
"crl_import_crl"
,
i18n
(
"Import CRL From File..."
),
QString
(),
nullptr
,
nullptr
,
nullptr
,
QString
(),
false
,
true
},
};
std
::
vector
<
action_data
>
action_data
=
common_and_openpgp_action_data
;
if
(
Settings
{}.
cmsEnabled
())
{
action_data
.
reserve
(
action_data
.
size
()
+
cms_action_data
.
size
());
std
::
copy
(
std
::
begin
(
cms_action_data
),
std
::
end
(
cms_action_data
),
std
::
back_inserter
(
action_data
));
}
make_actions_from_data
(
action_data
,
coll
);
if
(
QAction
*
action
=
coll
->
action
(
QStringLiteral
(
"view_stop_operations"
)))
{
connect
(
this
,
&
KeyListController
::
commandsExecuting
,
action
,
&
QAction
::
setEnabled
);
}
// ### somehow make this better...
registerActionForCommand
<
NewCertificateCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_new_certificate"
)));
//---
registerActionForCommand
<
LookupCertificatesCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_lookup_certificates"
)));
registerActionForCommand
<
ImportCertificateFromFileCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_import_certificates"
)));
//---
registerActionForCommand
<
ExportCertificateCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_export_certificates"
)));
registerActionForCommand
<
ExportSecretKeyCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_export_secret_keys"
)));
registerActionForCommand
<
ExportPaperKeyCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_export_paper_key"
)));
registerActionForCommand
<
ExportOpenPGPCertsToServerCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_export_certificates_to_server"
)));
//---
registerActionForCommand
<
DecryptVerifyFilesCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_decrypt_verify_files"
)));
registerActionForCommand
<
SignEncryptFilesCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_sign_encrypt_files"
)));
registerActionForCommand
<
SignEncryptFolderCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_sign_encrypt_folder"
)));
//---
registerActionForCommand
<
ChecksumCreateFilesCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_checksum_create_files"
)));
registerActionForCommand
<
ChecksumVerifyFilesCommand
>
(
coll
->
action
(
QStringLiteral
(
"file_checksum_verify_files"
)));
registerActionForCommand
<
ReloadKeysCommand
>
(
coll
->
action
(
QStringLiteral
(
"view_redisplay"
)));
//coll->action( "view_stop_operations" ) <-- already dealt with in make_actions_from_data()
registerActionForCommand
<
DetailsCommand
>
(
coll
->
action
(
QStringLiteral
(
"view_certificate_details"
)));
registerActionForCommand
<
ChangeOwnerTrustCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_change_owner_trust"
)));
registerActionForCommand
<
TrustRootCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_trust_root"
)));
registerActionForCommand
<
DistrustRootCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_distrust_root"
)));
//---
registerActionForCommand
<
CertifyCertificateCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_certify_certificate"
)));
if
(
RevokeCertificationCommand
::
isSupported
())
{
registerActionForCommand
<
RevokeCertificationCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_revoke_certification"
)));
}
//---
registerActionForCommand
<
ChangeExpiryCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_change_expiry"
)));
registerActionForCommand
<
ChangePassphraseCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_change_passphrase"
)));
registerActionForCommand
<
AddUserIDCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_add_userid"
)));
//---
#ifdef QGPGME_SUPPORTS_KEY_REVOCATION
registerActionForCommand
<
RevokeKeyCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_revoke"
)));
#endif
registerActionForCommand
<
DeleteCertificatesCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_delete"
)));
//---
registerActionForCommand
<
DumpCertificateCommand
>
(
coll
->
action
(
QStringLiteral
(
"certificates_dump_certificate"
)));
registerActionForCommand
<
RefreshX509CertsCommand
>
(
coll
->
action
(
QStringLiteral
(
"tools_refresh_x509_certificates"
)));
registerActionForCommand
<
RefreshOpenPGPCertsCommand
>
(
coll
->
action
(
QStringLiteral
(
"tools_refresh_openpgp_certificates"
)));
//---
registerActionForCommand
<
ImportCrlCommand
>
(
coll
->
action
(
QStringLiteral
(
"crl_import_crl"
)));
//---
registerActionForCommand
<
ClearCrlCacheCommand
>
(
coll
->
action
(
QStringLiteral
(
"crl_clear_crl_cache"
)));
registerActionForCommand
<
DumpCrlCacheCommand
>
(
coll
->
action
(
QStringLiteral
(
"crl_dump_crl_cache"
)));
enableDisableActions
(
nullptr
);
}
void
KeyListController
::
registerAction
(
QAction
*
action
,
Command
::
Restrictions
restrictions
,
Command
*
(
*
create
)(
QAbstractItemView
*
,
KeyListController
*
))
{
if
(
!
action
)
{
return
;
}
Q_ASSERT
(
!
action
->
isCheckable
());
// can be added later, for now, disallow
const
Private
::
action_item
ai
=
{
action
,
restrictions
,
create
};
connect
(
action
,
SIGNAL
(
triggered
()),
this
,
SLOT
(
slotActionTriggered
()));
d
->
actions
.
push_back
(
ai
);
}
void
KeyListController
::
registerCommand
(
Command
*
cmd
)
{
if
(
!
cmd
||
std
::
binary_search
(
d
->
commands
.
cbegin
(),
d
->
commands
.
cend
(),
cmd
))
{
return
;
}
d
->
addCommand
(
cmd
);
qCDebug
(
KLEOPATRA_LOG
)
<<
(
void
*
)
cmd
;
if
(
d
->
commands
.
size
()
==
1
)
{
Q_EMIT
commandsExecuting
(
true
);
}
}
bool
KeyListController
::
hasRunningCommands
()
const
{
return
!
d
->
commands
.
empty
();
}
bool
KeyListController
::
shutdownWarningRequired
()
const
{
return
std
::
any_of
(
d
->
commands
.
cbegin
(),
d
->
commands
.
cend
(),
std
::
mem_fn
(
&
Command
::
warnWhenRunningAtShutdown
));
}
// slot
void
KeyListController
::
cancelCommands
()
{
std
::
for_each
(
d
->
commands
.
begin
(),
d
->
commands
.
end
(),
std
::
mem_fn
(
&
Command
::
cancel
));
}
void
KeyListController
::
Private
::
connectView
(
QAbstractItemView
*
view
)
{
connect
(
view
,
&
QObject
::
destroyed
,
q
,
[
this
](
QObject
*
obj
)
{
slotDestroyed
(
obj
);
});
connect
(
view
,
&
QAbstractItemView
::
doubleClicked
,
q
,
[
this
](
const
QModelIndex
&
index
)
{
slotDoubleClicked
(
index
);
});
connect
(
view
,
&
QAbstractItemView
::
activated
,
q
,
[
this
](
const
QModelIndex
&
index
)
{
slotActivated
(
index
);
});
connect
(
view
->
selectionModel
(),
&
QItemSelectionModel
::
selectionChanged
,
q
,
[
this
](
const
QItemSelection
&
oldSel
,
const
QItemSelection
&
newSel
)
{
slotSelectionChanged
(
oldSel
,
newSel
);
});
view
->
setContextMenuPolicy
(
Qt
::
CustomContextMenu
);
connect
(
view
,
&
QWidget
::
customContextMenuRequested
,
q
,
[
this
](
const
QPoint
&
pos
)
{
slotContextMenu
(
pos
);
});
}
void
KeyListController
::
Private
::
connectCommand
(
Command
*
cmd
)
{
if
(
!
cmd
)
{
return
;
}
connect
(
cmd
,
&
QObject
::
destroyed
,
q
,
[
this
](
QObject
*
obj
)
{
slotDestroyed
(
obj
);
});
connect
(
cmd
,
&
Command
::
finished
,
q
,
[
this
]
{
slotCommandFinished
();
});
//connect( cmd, SIGNAL(canceled()), q, SLOT(slotCommandCanceled()) );
connect
(
cmd
,
&
Command
::
info
,
q
,
&
KeyListController
::
message
);
connect
(
cmd
,
&
Command
::
progress
,
q
,
[
this
](
const
QString
&
message
,
int
current
,
int
total
)
{
slotProgress
(
message
,
current
,
total
);
});
}
void
KeyListController
::
Private
::
slotDoubleClicked
(
const
QModelIndex
&
idx
)
{
QAbstractItemView
*
const
view
=
qobject_cast
<
QAbstractItemView
*>
(
q
->
sender
());
if
(
!
view
||
!
std
::
binary_search
(
views
.
cbegin
(),
views
.
cend
(),
view
))
{
return
;
}
DetailsCommand
*
const
c
=
new
DetailsCommand
(
view
,
q
);
if
(
parentWidget
)
{
c
->
setParentWidget
(
parentWidget
);
}
c
->
setIndex
(
idx
);
c
->
start
();
}
void
KeyListController
::
Private
::
slotActivated
(
const
QModelIndex
&
idx
)
{
Q_UNUSED
(
idx
)
QAbstractItemView
*
const
view
=
qobject_cast
<
QAbstractItemView
*>
(
q
->
sender
());
if
(
!
view
||
!
std
::
binary_search
(
views
.
cbegin
(),
views
.
cend
(),
view
))
{
return
;
}
}
void
KeyListController
::
Private
::
slotSelectionChanged
(
const
QItemSelection
&
old
,
const
QItemSelection
&
new_
)
{
Q_UNUSED
(
old
)
Q_UNUSED
(
new_
)
const
QItemSelectionModel
*
const
sm
=
qobject_cast
<
QItemSelectionModel
*>
(
q
->
sender
());
if
(
!
sm
)
{
return
;
}
q
->
enableDisableActions
(
sm
);
}
void
KeyListController
::
Private
::
slotContextMenu
(
const
QPoint
&
p
)
{
QAbstractItemView
*
const
view
=
qobject_cast
<
QAbstractItemView
*>
(
q
->
sender
());
if
(
view
&&
std
::
binary_search
(
views
.
cbegin
(),
views
.
cend
(),
view
))
{
Q_EMIT
q
->
contextMenuRequested
(
view
,
view
->
viewport
()
->
mapToGlobal
(
p
));
}
else
{
qCDebug
(
KLEOPATRA_LOG
)
<<
"sender is not a QAbstractItemView*!"
;
}
}
void
KeyListController
::
Private
::
slotCommandFinished
()
{
Command
*
const
cmd
=
qobject_cast
<
Command
*>
(
q
->
sender
());
if
(
!
cmd
||
!
std
::
binary_search
(
commands
.
cbegin
(),
commands
.
cend
(),
cmd
))
{
return
;
}
qCDebug
(
KLEOPATRA_LOG
)
<<
(
void
*
)
cmd
;
if
(
commands
.
size
()
==
1
)
{
Q_EMIT
q
->
commandsExecuting
(
false
);
}
}
void
KeyListController
::
enableDisableActions
(
const
QItemSelectionModel
*
sm
)
const
{
const
Command
::
Restrictions
restrictionsMask
=
d
->
calculateRestrictionsMask
(
sm
);
for
(
const
Private
::
action_item
&
ai
:
std
::
as_const
(
d
->
actions
))
if
(
ai
.
action
)
{
ai
.
action
->
setEnabled
(
ai
.
restrictions
==
(
ai
.
restrictions
&
restrictionsMask
));
}
}
static
bool
all_secret_are_not_owner_trust_ultimate
(
const
std
::
vector
<
Key
>
&
keys
)
{
for
(
const
Key
&
key
:
keys
)
if
(
key
.
hasSecret
()
&&
key
.
ownerTrust
()
==
Key
::
Ultimate
)
{
return
false
;
}
return
true
;
}
Command
::
Restrictions
find_root_restrictions
(
const
std
::
vector
<
Key
>
&
keys
)
{
bool
trusted
=
false
,
untrusted
=
false
;
for
(
const
Key
&
key
:
keys
)
if
(
key
.
isRoot
())
if
(
key
.
userID
(
0
).
validity
()
==
UserID
::
Ultimate
)
{
trusted
=
true
;
}
else
{
untrusted
=
true
;
}
else
{
return
Command
::
NoRestriction
;
}
if
(
trusted
)
if
(
untrusted
)
{
return
Command
::
NoRestriction
;
}
else
{
return
Command
::
MustBeTrustedRoot
;
}
else
if
(
untrusted
)
{
return
Command
::
MustBeUntrustedRoot
;
}
else
{
return
Command
::
NoRestriction
;
}
}
Command
::
Restrictions
KeyListController
::
Private
::
calculateRestrictionsMask
(
const
QItemSelectionModel
*
sm
)
{
if
(
!
sm
)
{
return
Command
::
NoRestriction
;
}
const
KeyListModelInterface
*
const
m
=
dynamic_cast
<
const
KeyListModelInterface
*>
(
sm
->
model
());
if
(
!
m
)
{
return
Command
::
NoRestriction
;
}
const
std
::
vector
<
Key
>
keys
=
m
->
keys
(
sm
->
selectedRows
());
if
(
keys
.
empty
())
{
return
Command
::
NoRestriction
;
}
Command
::
Restrictions
result
=
Command
::
NeedSelection
;
if
(
keys
.
size
()
==
1
)
{
result
|=
Command
::
OnlyOneKey
;
}
#if GPGME_VERSION_NUMBER >= 0x011102
// 1.17.2
// we need to check the primary subkey because Key::hasSecret() is also true if just the secret key stub of an offline key is available
const
auto
primaryKeyCanBeUsedForSecretKeyOperations
=
[](
const
auto
&
k
)
{
return
k
.
subkey
(
0
).
isSecret
();
};
#else
// older versions of GpgME did not always set the secret flag for card keys
const
auto
primaryKeyCanBeUsedForSecretKeyOperations
=
[](
const
auto
&
k
)
{
return
k
.
subkey
(
0
).
isSecret
()
||
k
.
subkey
(
0
).
isCardKey
();
};
#endif
if
(
std
::
all_of
(
keys
.
cbegin
(),
keys
.
cend
(),
primaryKeyCanBeUsedForSecretKeyOperations
))
{
result
|=
Command
::
NeedSecretKey
;
}
if
(
std
::
all_of
(
std
::
begin
(
keys
),
std
::
end
(
keys
),
[](
const
auto
&
k
)
{
return
k
.
subkey
(
0
).
isSecret
()
&&
!
k
.
subkey
(
0
).
isCardKey
();
}))
{
result
|=
Command
::
NeedSecretKeyData
;
}
if
(
std
::
all_of
(
keys
.
cbegin
(),
keys
.
cend
(),
[](
const
Key
&
key
)
{
return
key
.
protocol
()
==
OpenPGP
;
}))
{
result
|=
Command
::
MustBeOpenPGP
;
}
else
if
(
std
::
all_of
(
keys
.
cbegin
(),
keys
.
cend
(),
[](
const
Key
&
key
)
{
return
key
.
protocol
()
==
CMS
;
}))
{
result
|=
Command
::
MustBeCMS
;
}
if
(
all_secret_are_not_owner_trust_ultimate
(
keys
))
{
result
|=
Command
::
MayOnlyBeSecretKeyIfOwnerTrustIsNotYetUltimate
;
}
result
|=
find_root_restrictions
(
keys
);
if
(
const
ReaderStatus
*
rs
=
ReaderStatus
::
instance
())
{
if
(
!
rs
->
firstCardWithNullPin
().
empty
())
{
result
|=
Command
::
AnyCardHasNullPin
;
}
if
(
rs
->
anyCardCanLearnKeys
())
{
result
|=
Command
::
AnyCardCanLearnKeys
;
}
}
return
result
;
}
void
KeyListController
::
Private
::
slotActionTriggered
()
{
if
(
const
QObject
*
const
s
=
q
->
sender
())
{
const
auto
it
=
std
::
find_if
(
actions
.
cbegin
(),
actions
.
cend
(),
[
this
](
const
action_item
&
item
)
{
return
item
.
action
==
q
->
sender
();
});
if
(
it
!=
actions
.
end
())
if
(
Command
*
const
c
=
it
->
createCommand
(
this
->
currentView
,
q
))
{
if
(
parentWidget
)
{
c
->
setParentWidget
(
parentWidget
);
}
c
->
start
();
}
else
qCDebug
(
KLEOPATRA_LOG
)
<<
"createCommand() == NULL for action(?)
\"
"
<<
qPrintable
(
s
->
objectName
())
<<
"
\"
"
;
else
{
qCDebug
(
KLEOPATRA_LOG
)
<<
"I don't know anything about action(?)
\"
%s
\"
"
,
qPrintable
(
s
->
objectName
());
}
}
else
{
qCDebug
(
KLEOPATRA_LOG
)
<<
"not called through a signal/slot connection (sender() == NULL)"
;
}
}
int
KeyListController
::
Private
::
toolTipOptions
()
const
{
using
namespace
Kleo
::
Formatting
;
static
const
int
validityFlags
=
Validity
|
Issuer
|
ExpiryDates
|
CertificateUsage
;
static
const
int
ownerFlags
=
Subject
|
UserIDs
|
OwnerTrust
;
static
const
int
detailsFlags
=
StorageLocation
|
CertificateType
|
SerialNumber
|
Fingerprint
;
const
TooltipPreferences
prefs
;
int
flags
=
KeyID
;
flags
|=
prefs
.
showValidity
()
?
validityFlags
:
0
;
flags
|=
prefs
.
showOwnerInformation
()
?
ownerFlags
:
0
;
flags
|=
prefs
.
showCertificateDetails
()
?
detailsFlags
:
0
;
return
flags
;
}
void
KeyListController
::
updateConfig
()
{
const
int
opts
=
d
->
toolTipOptions
();
if
(
d
->
flatModel
)
{
d
->
flatModel
->
setToolTipOptions
(
opts
);
}
if
(
d
->
hierarchicalModel
)
{
d
->
hierarchicalModel
->
setToolTipOptions
(
opts
);
}
}
#include
"moc_keylistcontroller.cpp"
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Tue, Dec 9, 1:05 AM (1 d, 13 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
9b/f7/c6b8ffc5e00631018655ad4790fe
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment