certmanager/lib

backendconfigwidget.cpp
1/*
2 backendconfigwidget.cpp
3
4 This file is part of libkleopatra, the KDE keymanagement library
5 Copyright (c) 2002,2004,2005 Klarälvdalens Datakonsult AB
6 Copyright (c) 2002,2003 Marc Mutz <mutz@kde.org>
7
8 Libkleopatra is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 Libkleopatra is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22 In addition, as a special exception, the copyright holders give
23 permission to link the code of this program with any edition of
24 the TQt library by Trolltech AS, Norway (or with modified versions
25 of TQt that use the same license as TQt), and distribute linked
26 combinations including the two. You must obey the GNU General
27 Public License in all respects for all of the code used other than
28 TQt. If you modify this file, you may extend this exception to
29 your version of the file, but you are not obligated to do so. If
30 you do not wish to do so, delete this exception statement from
31 your version.
32 */
33
34#ifdef HAVE_CONFIG_H
35#include <config.h>
36#endif
37
38#include "backendconfigwidget.h"
39#include "cryptoconfigdialog.h"
40
41#include "kleo/cryptobackendfactory.h"
42#include "ui/keylistview.h" // for lvi_cast<>
43
44#include <tdelistview.h>
45#include <kdialog.h>
46#include <tdelocale.h>
47#include <kdebug.h>
48#include <tdemessagebox.h>
49#include <tdeapplication.h>
50#include <dcopclient.h>
51
52#include <tqpushbutton.h>
53#include <tqlayout.h>
54#include <tqheader.h>
55#include <tqtimer.h>
56
57#include <assert.h>
58
59namespace Kleo {
60 class BackendListView;
61}
62
63class Kleo::BackendConfigWidget::Private {
64public:
65 Kleo::BackendListView * listView;
66 TQPushButton * configureButton;
67 TQPushButton * rescanButton;
68 Kleo::CryptoBackendFactory * backendFactory;
69};
70
71namespace Kleo {
72 class BackendListViewItem;
73 class ProtocolCheckListItem;
74}
75
76class Kleo::BackendListView : public TDEListView
77{
78public:
79 BackendListView( BackendConfigWidget* parent, const char* name = 0 )
80 : TDEListView( parent, name ) {}
81
83 const Kleo::CryptoBackend* currentBackend() const;
84
86 const Kleo::CryptoBackend* chosenBackend( const char * protocol );
87
89 void deselectAll( const char * protocol, TQCheckListItem* except );
90
91 void emitChanged() { static_cast<BackendConfigWidget *>( parentWidget() )->emitChanged( true ); }
92};
93
94// Toplevel listviewitem for a given backend (e.g. "GpgME", "Kgpg/gpg v2")
95class Kleo::BackendListViewItem : public TQListViewItem
96{
97public:
98 BackendListViewItem( TDEListView* lv, TQListViewItem *prev, const CryptoBackend *cryptoBackend )
99 : TQListViewItem( lv, prev, cryptoBackend->displayName() ), mCryptoBackend( cryptoBackend )
100 {}
101
102 const CryptoBackend *cryptoBackend() const { return mCryptoBackend; }
103 enum { RTTI = 0x2EAE3BE0, RTTI_MASK = 0xFFFFFFFF };
104 int rtti() const { return RTTI; }
105
106private:
107 const CryptoBackend *mCryptoBackend;
108};
109
110
111// Checklist item under a BackendListViewItem
112// (e.g. "GpgME supports protocol OpenPGP")
113class Kleo::ProtocolCheckListItem : public TQCheckListItem
114{
115public:
116 ProtocolCheckListItem( BackendListViewItem* blvi,
117 TQListViewItem* prev, const char * protocolName,
118 const CryptoBackend::Protocol* protocol ) // can be 0
119 : TQCheckListItem( blvi, prev, itemText( protocolName, protocol ),
120 TQCheckListItem::CheckBox ),
121 mProtocol( protocol ), mProtocolName( protocolName )
122 {}
123
124 enum { RTTI = 0x2EAE3BE1, RTTI_MASK = 0xFFFFFFFF };
125 virtual int rtti() const { return RTTI; }
126
127 // can be 0
128 const CryptoBackend::Protocol* protocol() const { return mProtocol; }
129 const char * protocolName() const { return mProtocolName; }
130
131protected:
132 virtual void stateChange( bool b ) {
133 BackendListView* lv = static_cast<BackendListView *>( listView() );
134 // "radio-button-like" behavior for the protocol checkboxes
135 if ( b )
136 lv->deselectAll( mProtocolName, this );
137 lv->emitChanged();
138 TQCheckListItem::stateChange( b );
139 }
140
141private:
142 // Helper for the constructor.
143 static TQString itemText( const char * protocolName, const CryptoBackend::Protocol* protocol ) {
144 // First one is the generic name (find a nice one for OpenPGP, SMIME)
145 const TQString protoName = tqstricmp( protocolName, "openpgp" ) != 0
146 ? tqstricmp( protocolName, "smime" ) != 0
147 ? TQString::fromLatin1( protocolName )
148 : i18n( "S/MIME" )
149 : i18n( "OpenPGP" );
150 // second one is implementation name (gpg, gpgsm...)
151 const TQString impName = protocol ? protocol->displayName() : i18n( "failed" );
152 return i18n( "Items in Kleo::BackendConfigWidget listview (1: protocol; 2: implementation name)",
153 "%1 (%2)" ).arg( protoName, impName );
154 }
155
156 const CryptoBackend::Protocol* mProtocol; // can be 0
157 const char * mProtocolName;
158};
159
160const Kleo::CryptoBackend* Kleo::BackendListView::currentBackend() const {
161 const TQListViewItem* curItem = currentItem();
162 if ( !curItem ) // can't happen
163 return 0;
164 if ( lvi_cast<Kleo::ProtocolCheckListItem>( curItem ) )
165 curItem = curItem->parent();
166 if ( const Kleo::BackendListViewItem * blvi = lvi_cast<Kleo::BackendListViewItem>( curItem ) )
167 return blvi->cryptoBackend();
168 return 0;
169}
170
171// can't be const method due to TQListViewItemIterator (why?)
172const Kleo::CryptoBackend* Kleo::BackendListView::chosenBackend( const char * protocolName )
173{
174 for ( TQListViewItemIterator it( this /*, TQListViewItemIterator::Checked doesn't work*/ ) ;
175 it.current() ; ++it )
176 if ( ProtocolCheckListItem * p = lvi_cast<ProtocolCheckListItem>( it.current() ) )
177 if ( p->isOn() && tqstricmp( p->protocolName(), protocolName ) == 0 ) {
178 // OK that's the one. Now go up to the parent backend
179 // (need to do that in the listview since Protocol doesn't know it)
180 if ( const BackendListViewItem * parItem = lvi_cast<BackendListViewItem>( it.current()->parent() ) )
181 return parItem->cryptoBackend();
182 }
183 return 0;
184}
185
186void Kleo::BackendListView::deselectAll( const char * protocolName, TQCheckListItem* except )
187{
188 for ( TQListViewItemIterator it( this /*, TQListViewItemIterator::Checked doesn't work*/ ) ;
189 it.current() ; ++it ) {
190 if ( it.current() == except ) continue;
191 if ( ProtocolCheckListItem * p = lvi_cast<ProtocolCheckListItem>( it.current() ) )
192 if ( p->isOn() && tqstricmp( p->protocolName(), protocolName ) == 0 )
193 p->setOn( false );
194 }
195}
196
198
199Kleo::BackendConfigWidget::BackendConfigWidget( CryptoBackendFactory * factory, TQWidget * parent, const char * name, WFlags f )
200 : TQWidget( parent, name, f ), d( 0 )
201{
202 assert( factory );
203 d = new Private();
204 d->backendFactory = factory;
205
206 TQHBoxLayout * hlay =
207 new TQHBoxLayout( this, 0, KDialog::spacingHint() );
208
209 d->listView = new BackendListView( this, "d->listView" );
210 d->listView->addColumn( i18n("Available Backends") );
211 d->listView->setAllColumnsShowFocus( true );
212 d->listView->setSorting( -1 );
213 d->listView->header()->setClickEnabled( false );
214 d->listView->setFullWidth( true );
215
216 hlay->addWidget( d->listView, 1 );
217
218 connect( d->listView, TQ_SIGNAL(selectionChanged(TQListViewItem*)),
219 TQ_SLOT(slotSelectionChanged(TQListViewItem*)) );
220
221 TQVBoxLayout * vlay = new TQVBoxLayout( hlay ); // inherits spacing
222
223 d->configureButton = new TQPushButton( i18n("Confi&gure..."), this );
224 d->configureButton->setAutoDefault( false );
225 vlay->addWidget( d->configureButton );
226
227 connect( d->configureButton, TQ_SIGNAL(clicked()),
228 TQ_SLOT(slotConfigureButtonClicked()) );
229
230 d->rescanButton = new TQPushButton( i18n("Rescan"), this );
231 d->rescanButton->setAutoDefault( false );
232 vlay->addWidget( d->rescanButton );
233
234 connect( d->rescanButton, TQ_SIGNAL(clicked()),
235 TQ_SLOT(slotRescanButtonClicked()) );
236
237 vlay->addStretch( 1 );
238}
239
240Kleo::BackendConfigWidget::~BackendConfigWidget() {
241 delete d; d = 0;
242}
243
244void Kleo::BackendConfigWidget::load() {
245 d->listView->clear();
246
247 unsigned int backendCount = 0;
248
249 // populate the plugin list:
250 BackendListViewItem * top = 0;
251 for ( unsigned int i = 0 ; const CryptoBackend * b = d->backendFactory->backend( i ) ; ++i ) {
252
253 top = new Kleo::BackendListViewItem( d->listView, top, b );
254
255 ProtocolCheckListItem * last = 0;
256 for ( int i = 0 ; const char * name = b->enumerateProtocols( i ) ; ++i ) {
257 const CryptoBackend::Protocol * protocol = b->protocol( name );
258
259 if ( protocol ) {
260 last = new ProtocolCheckListItem( top, last, name, protocol );
261 last->setOn( protocol == d->backendFactory->protocol( name ) );
262 } else if ( b->supportsProtocol( name ) ) {
263 last = new ProtocolCheckListItem( top, last, name, 0 );
264 last->setOn( false );
265 last->setEnabled( false );
266 }
267 }
268
269 top->setOpen( true );
270 ++backendCount;
271 }
272
273 if ( backendCount ) {
274 d->listView->setCurrentItem( d->listView->firstChild() );
275 d->listView->setSelected( d->listView->firstChild(), true );
276 }
277
278 slotSelectionChanged( d->listView->firstChild() );
279}
280
281void Kleo::BackendConfigWidget::slotSelectionChanged( TQListViewItem * ) {
282 const CryptoBackend* backend = d->listView->currentBackend();
283 if ( backend && !backend->config() )
284 kdDebug(5150) << "Backend w/o config object!" << endl;
285 d->configureButton->setEnabled( backend && backend->config() );
286}
287
288
289void Kleo::BackendConfigWidget::slotRescanButtonClicked() {
290 TQStringList reasons;
291 d->backendFactory->scanForBackends( &reasons );
292 if ( !reasons.empty() )
293 KMessageBox::informationList( this,
294 i18n("The following problems where encountered during scanning:"),
295 reasons, i18n("Scan Results") );
296 load();
297 emit changed( true );
298}
299
300void Kleo::BackendConfigWidget::slotConfigureButtonClicked() {
301 const CryptoBackend* backend = d->listView->currentBackend();
302 if ( backend && backend->config() ) {
303 Kleo::CryptoConfigDialog dlg( backend->config(), this );
304 int result = dlg.exec();
305 if ( result == TQDialog::Accepted ) {
306 // Tell other users of gpgconf (e.g. the s/mime page) that the gpgconf data might have changed
307 tdeApp->dcopClient()->emitDCOPSignal( "KPIM::CryptoConfig", "changed()", TQByteArray() );
308 // and schedule a rescan, in case the updates make a backend valid
309 TQTimer::singleShot( 0, this, TQ_SLOT(slotRescanButtonClicked()) );
310 }
311 }
312 else // shouldn't happen, button is disabled
313 kdWarning(5150) << "Can't configure backend, no config object available" << endl;
314}
315
316void Kleo::BackendConfigWidget::save() const {
317 for ( int i = 0 ; const char * name = d->backendFactory->enumerateProtocols( i ) ; ++i )
318 d->backendFactory->setProtocolBackend( name, d->listView->chosenBackend( name ) );
319}
320
321void Kleo::BackendConfigWidget::virtual_hook( int, void* ) {}
322
323#include "backendconfigwidget.moc"
Simple KDialogBase wrapper around CryptoConfigModule.