37 #include <config-kleopatra.h>
51 #include <kmime/kmime_header_parsing.h>
53 #include <gpgme++/key.h>
58 #include <QButtonGroup>
60 #include <QGridLayout>
64 #include <QPushButton>
65 #include <QRadioButton>
66 #include <QStackedLayout>
67 #include <QVBoxLayout>
72 using namespace GpgME;
74 using namespace Kleo::Crypto;
75 using namespace Kleo::Crypto::Gui;
76 using namespace boost;
80 if ( !encrypt && sign )
81 return SignerResolvePage::SignOnly;
82 if ( !sign && encrypt )
83 return SignerResolvePage::EncryptOnly;
84 return SignerResolvePage::SignAndEncrypt;
87 static QString formatLabel( Protocol p,
const Key & key ) {
88 return i18nc(
"%1=protocol (S/Mime, OpenPGP), %2=certificate",
"Sign using %1: %2",
Formatting::displayName( p ),
92 static std::vector<Protocol> supportedProtocols() {
93 std::vector<Protocol> protocols;
95 protocols.push_back(
CMS );
100 AbstractSigningProtocolSelectionWidget::AbstractSigningProtocolSelectionWidget(
QWidget* p, Qt::WindowFlags f ) :
QWidget( p, f ) {
104 QVBoxLayout *
const layout =
new QVBoxLayout(
this );
105 layout->setMargin( 0 );
106 Q_FOREACH (
const Protocol i, supportedProtocols() ) {
107 QLabel *
const l =
new QLabel;
108 l->setText( formatLabel( i, Key() ) );
109 layout->addWidget( l );
115 QLabel *
const l = label( protocol );
117 l->setVisible( checked );
121 QLabel *
const l = label( protocol );
123 return l->isVisible();
127 std::vector<Protocol> res;
128 Q_FOREACH(
const Protocol i, supportedProtocols() )
138 m_buttonGroup =
new QButtonGroup(
this );
141 QVBoxLayout *
const layout =
new QVBoxLayout(
this );
142 layout->setMargin( 0 );
143 Q_FOREACH (
const Protocol i, supportedProtocols() ) {
144 QCheckBox *
const b =
new QCheckBox;
145 b->setText( formatLabel( i, Key() ) );
147 layout->addWidget( b );
148 m_buttonGroup->addButton( b );
154 assert( p != UnknownProtocol );
155 QCheckBox *
const b = button( p );
157 b->setChecked( checked );
161 assert( p != UnknownProtocol );
162 const QAbstractButton *
const b = button( p );
164 return b->isChecked();
168 std::vector<Protocol> res;
169 for ( std::map<Protocol,QCheckBox*>::const_iterator it = m_buttons.begin(), end = m_buttons.end();
172 if ( it->second->isChecked() )
173 res.push_back( it->first );
180 m_buttonGroup->setExclusive( exclusive );
184 QCheckBox * SigningProtocolSelectionWidget::button( Protocol p )
const
186 const std::map<Protocol,QCheckBox*>::const_iterator it = m_buttons.find( p );
187 return it == m_buttons.end() ? 0 : it->second;
190 QLabel * ReadOnlyProtocolSelectionWidget::label( Protocol p )
const
192 const std::map<Protocol,QLabel*>::const_iterator it = m_labels.find( p );
193 return it == m_labels.end() ? 0 : it->second;
197 return m_buttonGroup->exclusive();
201 QAbstractButton *
const b = button( prot );
203 b->setText( formatLabel( prot, key ) );
207 QLabel *
const l = label( prot );
208 l->setText( formatLabel( prot, key ) );
215 QString explanation()
const {
return QString(); }
216 bool isComplete()
const {
return true; }
217 QString customWindowTitle()
const {
return QString(); }
221 class SignerResolvePage::Private {
222 friend class ::Kleo::Crypto::Gui::SignerResolvePage;
229 void operationButtonClicked(
int operation );
230 void selectCertificates();
232 void updateModeSelectionWidgets();
234 bool protocolSelected( Protocol p )
const;
235 bool protocolSelectionActuallyUserMutable()
const;
238 QButtonGroup* signEncryptGroup;
239 QRadioButton* signAndEncryptRB;
240 QRadioButton* encryptOnlyRB;
241 QRadioButton* signOnlyRB;
242 QGroupBox* signingCertificateBox;
243 QLabel * signerLabelLabel;
244 QLabel * signerLabel;
245 QGroupBox * encryptBox;
246 QCheckBox * textArmorCO;
247 QCheckBox * removeUnencryptedCO;
248 QPushButton * selectCertificatesButton;
251 std::vector<Protocol> presetProtocols;
253 bool encryptionMutable;
263 bool SignerResolvePage::Private::protocolSelectionActuallyUserMutable()
const {
264 return (
q->protocolSelectionUserMutable() || presetProtocols.empty() ) &&
q->operation() == SignOnly;
270 , signingMutable( true )
271 , encryptionMutable( true )
272 , signingSelected( false )
273 , encryptionSelected( false )
274 , multipleProtocolsAllowed( false )
275 , protocolSelectionUserMutable( true )
276 , validator( new ValidatorImpl )
279 QVBoxLayout* layout =
new QVBoxLayout(
q );
280 layout->setSpacing( KDialog::spacingHint() );
282 signEncryptGroup =
new QButtonGroup(
q );
283 q->connect( signEncryptGroup, SIGNAL(buttonClicked(
int)),
q, SLOT(operationButtonClicked(
int)) );
285 signAndEncryptRB =
new QRadioButton;
286 signAndEncryptRB->setText( i18n(
"Sign and encrypt (OpenPGP only)" ) );
287 signAndEncryptRB->setChecked(
true );
288 signEncryptGroup->addButton( signAndEncryptRB, SignAndEncrypt );
289 layout->addWidget( signAndEncryptRB );
291 encryptOnlyRB =
new QRadioButton;
292 encryptOnlyRB->setText( i18n(
"Encrypt only" ) );
293 signEncryptGroup->addButton( encryptOnlyRB, EncryptOnly );
294 layout->addWidget( encryptOnlyRB );
296 signOnlyRB =
new QRadioButton;
297 signOnlyRB->setText( i18n(
"Sign only" ) );
298 signEncryptGroup->addButton( signOnlyRB, SignOnly );
299 layout->addWidget( signOnlyRB );
301 encryptBox =
new QGroupBox;
302 encryptBox->setTitle( i18n(
"Encryption Options" ) );
303 QBoxLayout *
const encryptLayout =
new QVBoxLayout( encryptBox );
304 textArmorCO =
new QCheckBox;
305 textArmorCO->setText( i18n(
"Text output (ASCII armor)" ) );
306 encryptLayout->addWidget( textArmorCO );
307 removeUnencryptedCO =
new QCheckBox;
308 removeUnencryptedCO->setText( i18n(
"Remove unencrypted original file when done" ) );
309 removeUnencryptedCO->setChecked(
false );
310 encryptLayout->addWidget( removeUnencryptedCO );
311 layout->addWidget( encryptBox );
313 signingCertificateBox =
new QGroupBox;
314 signingCertificateBox->setTitle( i18n(
"Signing Options" ) );
315 QGridLayout* signerLayout =
new QGridLayout( signingCertificateBox );
316 signerLayout->setColumnStretch( 1, 1 );
318 signerLabelLabel =
new QLabel;
319 signerLabelLabel->setText( i18n(
"Signer:" ) );
320 signerLayout->addWidget( signerLabelLabel, 1, 0 );
321 signerLabel =
new QLabel;
322 signerLayout->addWidget( signerLabel, 1, 1 );
323 signerLabelLabel->setVisible(
false );
324 signerLabel->setVisible(
false );
328 signerLayout->addWidget( signingProtocolSelectionWidget, 2, 0, 1, -1 );
331 signerLayout->addWidget( readOnlyProtocolSelectionWidget, 3, 0, 1, -1 );
333 selectCertificatesButton =
new QPushButton;
334 selectCertificatesButton->setText( i18n(
"Change Signing Certificates..." ) );
335 selectCertificatesButton->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
336 signerLayout->addWidget( selectCertificatesButton, 4, 0, 1, -1, Qt::AlignLeft );
337 q->connect( selectCertificatesButton, SIGNAL(clicked()),
338 q, SLOT(selectCertificates()) );
339 layout->addWidget( signingCertificateBox );
340 layout->addStretch();
355 SignerResolvePage::Private::~Private() {}
358 bool SignerResolvePage::Private::protocolSelected( Protocol p )
const {
359 assert( p != UnknownProtocol );
360 return signingProtocolSelectionWidget->isProtocolChecked( p );
365 certificates = certs;
366 Q_FOREACH (
const Protocol i, certs.keys() ) {
367 const Key key = certs.value( i );
368 readOnlyProtocolSelectionWidget->setCertificate( i, key );
369 signingProtocolSelectionWidget->setCertificate( i, key );
374 void SignerResolvePage::Private::updateUi() {
375 const bool ismutable = protocolSelectionActuallyUserMutable();
376 readOnlyProtocolSelectionWidget->setVisible( !ismutable );
377 signingProtocolSelectionWidget->setVisible( ismutable );
379 q->setExplanation( validator->explanation() );
380 emit
q->completeChanged();
382 const QString customTitle = validator->customWindowTitle();
383 if ( !customTitle.isEmpty() )
384 emit
q->windowTitleChanged( customTitle );
385 selectCertificatesButton->setEnabled(signingProtocolSelectionWidget->checkedProtocols().size()>0);
390 if ( d->protocolSelectionUserMutable == ismutable )
392 d->protocolSelectionUserMutable = ismutable;
393 d->updateModeSelectionWidgets();
397 return d->protocolSelectionUserMutable;
402 if ( d->multipleProtocolsAllowed == allowed )
404 d->multipleProtocolsAllowed = allowed;
405 d->updateModeSelectionWidgets();
410 return d->multipleProtocolsAllowed;
413 void SignerResolvePage::Private::updateModeSelectionWidgets()
415 const bool bothMutable = signingMutable && encryptionMutable;
416 const bool noSigningPossible = !signingSelected && !signingMutable;
417 const bool noEncryptionPossible = !encryptionSelected && !encryptionMutable;
418 signAndEncryptRB->setChecked( signingSelected && encryptionSelected );
419 signOnlyRB->setChecked( signingSelected && !encryptionSelected );
420 encryptOnlyRB->setChecked( encryptionSelected && !signingSelected );
421 const bool canSignAndEncrypt = !noSigningPossible && !noEncryptionPossible; bothMutable && presetProtocols != std::vector<Protocol>( 1,
CMS );
422 const bool canSignOnly = !encryptionSelected || encryptionMutable;
423 const bool canEncryptOnly = !signingSelected || signingMutable;
425 signAndEncryptRB->setEnabled( canSignAndEncrypt );
426 signOnlyRB->setEnabled( canSignOnly );
427 encryptOnlyRB->setEnabled( canEncryptOnly );
428 const bool buttonsVisible = signingMutable || encryptionMutable;
429 signOnlyRB->setVisible( buttonsVisible );
430 encryptOnlyRB->setVisible( buttonsVisible );
431 signAndEncryptRB->setVisible( buttonsVisible );
432 signingProtocolSelectionWidget->setExclusive( !multipleProtocolsAllowed );
433 signingCertificateBox->setVisible( !noSigningPossible );
434 encryptBox->setVisible( !noEncryptionPossible );
438 void SignerResolvePage::Private::selectCertificates()
441 dlg->setAllowedProtocols( QVector<Protocol>::fromStdVector( signingProtocolSelectionWidget->checkedProtocols() ) );
442 if ( dlg->exec() == QDialog::Accepted && dlg )
445 setCertificates( certs );
446 if ( signingPreferences && dlg->rememberAsDefault() ) {
447 signingPreferences->setPreferredCertificate(
OpenPGP, certs.value(
OpenPGP ) );
448 signingPreferences->setPreferredCertificate(
CMS, certs.value(
CMS ) );
456 void SignerResolvePage::Private::operationButtonClicked(
int mode_ )
459 signingCertificateBox->setEnabled( op != EncryptOnly );
460 encryptBox->setEnabled( op != SignOnly );
461 if ( op == SignAndEncrypt ) {
462 signingProtocolSelectionWidget->setProtocolChecked(
CMS,
false );
463 readOnlyProtocolSelectionWidget->setProtocolChecked(
CMS,
false );
464 signingProtocolSelectionWidget->setProtocolChecked(
OpenPGP,
true );
465 readOnlyProtocolSelectionWidget->setProtocolChecked(
OpenPGP,
true );
470 void SignerResolvePage::Private::setOperation( Operation op ) {
476 encryptOnlyRB->click();
479 signAndEncryptRB->click();
491 :
WizardPage( parent, f ),
d( new Private( this ) )
493 setTitle( i18n(
"<b>Choose Operation to be Performed</b>" ) );
497 d->updateModeSelectionWidgets();
504 const std::vector< std::vector<GpgME::Key> > & keys )
506 kleo_assert( signers.empty() || signers.size() == keys.size() );
508 switch ( signers.size() )
511 d->signerLabelLabel->setVisible(
false );
512 d->signerLabel->setVisible(
false );
515 d->signerLabelLabel->setVisible(
true );
516 d->signerLabel->setVisible(
true );
517 d->signerLabel->setText( signers.front().prettyAddress() );
520 kleo_assert( !
"Resolving multiple signers not implemented" );
528 std::vector<Protocol> protocols;
529 if ( protocol !=
CMS )
530 protocols.push_back(
OpenPGP );
532 protocols.push_back(
CMS );
540 d->presetProtocols = protocols;
541 Q_FOREACH (
const Protocol i, supportedProtocols() ) {
542 const bool checked = std::find( protocols.begin(), protocols.end(), i ) != protocols.end();
543 d->signingProtocolSelectionWidget->setProtocolChecked( i, checked );
544 d->readOnlyProtocolSelectionWidget->setProtocolChecked( i, checked );
546 d->updateModeSelectionWidgets();
550 return d->signingProtocolSelectionWidget->checkedProtocols();
555 std::vector<Key> result;
556 if ( protocol !=
CMS && d->signingProtocolSelectionWidget->isProtocolChecked(
OpenPGP ) && !d->certificates[
OpenPGP].isNull() )
557 result.push_back( d->certificates[
OpenPGP] );
558 if ( protocol !=
OpenPGP && d->signingProtocolSelectionWidget->isProtocolChecked(
CMS ) && !d->certificates[
CMS].isNull() )
559 result.push_back( d->certificates[
CMS] );
567 result.insert( result.end(), pgp.begin(), pgp.end() );
573 assert( d->validator );
574 return d->validator->isComplete();
579 return !d->signOnlyRB->isChecked();
584 d->encryptionSelected = selected;
585 d->updateModeSelectionWidgets();
586 d->setOperation( operationFromFlags( d->signingSelected, d->encryptionSelected ) );
591 return !d->encryptOnlyRB->isChecked();
596 d->signingSelected = selected;
597 d->updateModeSelectionWidgets();
598 d->setOperation( operationFromFlags( d->signingSelected, d->encryptionSelected ) );
603 return d->encryptionMutable;
608 return d->signingMutable;
613 d->encryptionMutable = ismutable;
614 d->updateModeSelectionWidgets();
619 d->signingMutable = ismutable;
620 d->updateModeSelectionWidgets();
624 std::vector<Protocol> res;
633 return d->textArmorCO->isChecked();
638 d->textArmorCO->setChecked( enabled );
643 return d->removeUnencryptedCO->isChecked();
648 d->removeUnencryptedCO->setChecked(
remove );
653 d->signingPreferences = prefs;
655 map[
OpenPGP] = prefs ? prefs->preferredCertificate(
OpenPGP ) : Key();
656 map[
CMS] = prefs ? prefs->preferredCertificate(
CMS ) : Key();
657 d->setCertificates( map );
662 return d->signingPreferences;
665 void SignerResolvePage::onNext()
669 #include "moc_signerresolvepage.cpp"
670 #include "moc_signerresolvepage_p.cpp"
Operation operation() const
void setAsciiArmorEnabled(bool enabled)
boost::shared_ptr< SigningPreferences > signingPreferences() const
bool multipleProtocolsAllowed() const
bool isEncryptionUserMutable() const
bool protocolSelectionUserMutable() const
void setValidator(const boost::shared_ptr< Validator > &)
boost::shared_ptr< Validator > validator() const
void setSigningUserMutable(bool ismutable)
void setRemoveUnencryptedFile(bool remove)
void setTitle(const QString &title)
void setEncryptionUserMutable(bool ismutable)
bool signingSelected() const
std::vector< GpgME::Protocol > selectedProtocolsWithoutSigningCertificate() const
SignerResolvePage(QWidget *parent=0, Qt::WindowFlags f=0)
void setMultipleProtocolsAllowed(bool allowed)
void setSignersAndCandidates(const std::vector< KMime::Types::Mailbox > &signers, const std::vector< std::vector< GpgME::Key > > &keys)
bool removeUnencryptedFile() const
std::vector< GpgME::Key > resolvedSigners() const
bool isAsciiArmorEnabled() const
#define kleo_assert(cond)
std::vector< GpgME::Protocol > selectedProtocols() const
void setSigningSelected(bool selected)
void setSigningPreferences(const boost::shared_ptr< SigningPreferences > &prefs)
void setProtocolSelectionUserMutable(bool ismutable)
void setPresetProtocols(const std::vector< GpgME::Protocol > &protocols)
void setEncryptionSelected(bool selected)
std::vector< GpgME::Key > signingCertificates(GpgME::Protocol protocol=GpgME::UnknownProtocol) const
void setPresetProtocol(GpgME::Protocol protocol)
bool encryptionSelected() const
bool isSigningUserMutable() const