backendconfigwidget.cpp
00001 /* -*- c++ -*- 00002 backendconfigwidget.cpp 00003 00004 This file is part of libkleopatra, the KDE keymanagement library 00005 Copyright (c) 2002,2004,2005 Klarälvdalens Datakonsult AB 00006 Copyright (c) 2002,2003 Marc Mutz <mutz@kde.org> 00007 00008 Libkleopatra is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU General Public License as 00010 published by the Free Software Foundation; either version 2 of the 00011 License, or (at your option) any later version. 00012 00013 Libkleopatra is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program; if not, write to the Free Software 00020 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 00022 In addition, as a special exception, the copyright holders give 00023 permission to link the code of this program with any edition of 00024 the TQt library by Trolltech AS, Norway (or with modified versions 00025 of TQt that use the same license as TQt), and distribute linked 00026 combinations including the two. You must obey the GNU General 00027 Public License in all respects for all of the code used other than 00028 TQt. If you modify this file, you may extend this exception to 00029 your version of the file, but you are not obligated to do so. If 00030 you do not wish to do so, delete this exception statement from 00031 your version. 00032 */ 00033 00034 #ifdef HAVE_CONFIG_H 00035 #include <config.h> 00036 #endif 00037 00038 #include "backendconfigwidget.h" 00039 #include "cryptoconfigdialog.h" 00040 00041 #include "kleo/cryptobackendfactory.h" 00042 #include "ui/keylistview.h" // for lvi_cast<> 00043 00044 #include <klistview.h> 00045 #include <kdialog.h> 00046 #include <klocale.h> 00047 #include <kdebug.h> 00048 #include <kmessagebox.h> 00049 #include <kapplication.h> 00050 #include <dcopclient.h> 00051 00052 #include <tqpushbutton.h> 00053 #include <tqlayout.h> 00054 #include <tqheader.h> 00055 #include <tqtimer.h> 00056 00057 #include <assert.h> 00058 00059 namespace Kleo { 00060 class BackendListView; 00061 } 00062 00063 class Kleo::BackendConfigWidget::Private { 00064 public: 00065 Kleo::BackendListView * listView; 00066 TQPushButton * configureButton; 00067 TQPushButton * rescanButton; 00068 Kleo::CryptoBackendFactory * backendFactory; 00069 }; 00070 00071 namespace Kleo { 00072 class BackendListViewItem; 00073 class ProtocolCheckListItem; 00074 } 00075 00076 class Kleo::BackendListView : public KListView 00077 { 00078 public: 00079 BackendListView( BackendConfigWidget* parent, const char* name = 0 ) 00080 : KListView( parent, name ) {} 00081 00083 const Kleo::CryptoBackend* currentBackend() const; 00084 00086 const Kleo::CryptoBackend* chosenBackend( const char * protocol ); 00087 00089 void deselectAll( const char * protocol, TQCheckListItem* except ); 00090 00091 void emitChanged() { static_cast<BackendConfigWidget *>( parentWidget() )->emitChanged( true ); } 00092 }; 00093 00094 // Toplevel listviewitem for a given backend (e.g. "GpgME", "Kgpg/gpg v2") 00095 class Kleo::BackendListViewItem : public TQListViewItem 00096 { 00097 public: 00098 BackendListViewItem( KListView* lv, TQListViewItem *prev, const CryptoBackend *cryptoBackend ) 00099 : TQListViewItem( lv, prev, cryptoBackend->displayName() ), mCryptoBackend( cryptoBackend ) 00100 {} 00101 00102 const CryptoBackend *cryptoBackend() const { return mCryptoBackend; } 00103 enum { RTTI = 0x2EAE3BE0, RTTI_MASK = 0xFFFFFFFF }; 00104 int rtti() const { return RTTI; } 00105 00106 private: 00107 const CryptoBackend *mCryptoBackend; 00108 }; 00109 00110 00111 // Checklist item under a BackendListViewItem 00112 // (e.g. "GpgME supports protocol OpenPGP") 00113 class Kleo::ProtocolCheckListItem : public TQCheckListItem 00114 { 00115 public: 00116 ProtocolCheckListItem( BackendListViewItem* blvi, 00117 TQListViewItem* prev, const char * protocolName, 00118 const CryptoBackend::Protocol* protocol ) // can be 0 00119 : TQCheckListItem( blvi, prev, itemText( protocolName, protocol ), 00120 TQCheckListItem::CheckBox ), 00121 mProtocol( protocol ), mProtocolName( protocolName ) 00122 {} 00123 00124 enum { RTTI = 0x2EAE3BE1, RTTI_MASK = 0xFFFFFFFF }; 00125 virtual int rtti() const { return RTTI; } 00126 00127 // can be 0 00128 const CryptoBackend::Protocol* protocol() const { return mProtocol; } 00129 const char * protocolName() const { return mProtocolName; } 00130 00131 protected: 00132 virtual void stateChange( bool b ) { 00133 BackendListView* lv = static_cast<BackendListView *>( listView() ); 00134 // "radio-button-like" behavior for the protocol checkboxes 00135 if ( b ) 00136 lv->deselectAll( mProtocolName, this ); 00137 lv->emitChanged(); 00138 TQCheckListItem::stateChange( b ); 00139 } 00140 00141 private: 00142 // Helper for the constructor. 00143 static TQString itemText( const char * protocolName, const CryptoBackend::Protocol* protocol ) { 00144 // First one is the generic name (find a nice one for OpenPGP, SMIME) 00145 const TQString protoName = qstricmp( protocolName, "openpgp" ) != 0 00146 ? qstricmp( protocolName, "smime" ) != 0 00147 ? TQString::fromLatin1( protocolName ) 00148 : i18n( "S/MIME" ) 00149 : i18n( "OpenPGP" ); 00150 // second one is implementation name (gpg, gpgsm...) 00151 const TQString impName = protocol ? protocol->displayName() : i18n( "failed" ); 00152 return i18n( "Items in Kleo::BackendConfigWidget listview (1: protocol; 2: implementation name)", 00153 "%1 (%2)" ).arg( protoName, impName ); 00154 } 00155 00156 const CryptoBackend::Protocol* mProtocol; // can be 0 00157 const char * mProtocolName; 00158 }; 00159 00160 const Kleo::CryptoBackend* Kleo::BackendListView::currentBackend() const { 00161 const TQListViewItem* curItem = currentItem(); 00162 if ( !curItem ) // can't happen 00163 return 0; 00164 if ( lvi_cast<Kleo::ProtocolCheckListItem>( curItem ) ) 00165 curItem = curItem->parent(); 00166 if ( const Kleo::BackendListViewItem * blvi = lvi_cast<Kleo::BackendListViewItem>( curItem ) ) 00167 return blvi->cryptoBackend(); 00168 return 0; 00169 } 00170 00171 // can't be const method due to TQListViewItemIterator (why?) 00172 const Kleo::CryptoBackend* Kleo::BackendListView::chosenBackend( const char * protocolName ) 00173 { 00174 for ( TQListViewItemIterator it( this /*, TQListViewItemIterator::Checked doesn't work*/ ) ; 00175 it.current() ; ++it ) 00176 if ( ProtocolCheckListItem * p = lvi_cast<ProtocolCheckListItem>( it.current() ) ) 00177 if ( p->isOn() && qstricmp( p->protocolName(), protocolName ) == 0 ) { 00178 // OK that's the one. Now go up to the parent backend 00179 // (need to do that in the listview since Protocol doesn't know it) 00180 if ( const BackendListViewItem * parItem = lvi_cast<BackendListViewItem>( it.current()->parent() ) ) 00181 return parItem->cryptoBackend(); 00182 } 00183 return 0; 00184 } 00185 00186 void Kleo::BackendListView::deselectAll( const char * protocolName, TQCheckListItem* except ) 00187 { 00188 for ( TQListViewItemIterator it( this /*, TQListViewItemIterator::Checked doesn't work*/ ) ; 00189 it.current() ; ++it ) { 00190 if ( it.current() == except ) continue; 00191 if ( ProtocolCheckListItem * p = lvi_cast<ProtocolCheckListItem>( it.current() ) ) 00192 if ( p->isOn() && qstricmp( p->protocolName(), protocolName ) == 0 ) 00193 p->setOn( false ); 00194 } 00195 } 00196 00198 00199 Kleo::BackendConfigWidget::BackendConfigWidget( CryptoBackendFactory * factory, TQWidget * parent, const char * name, WFlags f ) 00200 : TQWidget( parent, name, f ), d( 0 ) 00201 { 00202 assert( factory ); 00203 d = new Private(); 00204 d->backendFactory = factory; 00205 00206 TQHBoxLayout * hlay = 00207 new TQHBoxLayout( this, 0, KDialog::spacingHint() ); 00208 00209 d->listView = new BackendListView( this, "d->listView" ); 00210 d->listView->addColumn( i18n("Available Backends") ); 00211 d->listView->setAllColumnsShowFocus( true ); 00212 d->listView->setSorting( -1 ); 00213 d->listView->header()->setClickEnabled( false ); 00214 d->listView->setFullWidth( true ); 00215 00216 hlay->addWidget( d->listView, 1 ); 00217 00218 connect( d->listView, TQT_SIGNAL(selectionChanged(TQListViewItem*)), 00219 TQT_SLOT(slotSelectionChanged(TQListViewItem*)) ); 00220 00221 TQVBoxLayout * vlay = new TQVBoxLayout( hlay ); // inherits spacing 00222 00223 d->configureButton = new TQPushButton( i18n("Confi&gure..."), this ); 00224 d->configureButton->setAutoDefault( false ); 00225 vlay->addWidget( d->configureButton ); 00226 00227 connect( d->configureButton, TQT_SIGNAL(clicked()), 00228 TQT_SLOT(slotConfigureButtonClicked()) ); 00229 00230 d->rescanButton = new TQPushButton( i18n("Rescan"), this ); 00231 d->rescanButton->setAutoDefault( false ); 00232 vlay->addWidget( d->rescanButton ); 00233 00234 connect( d->rescanButton, TQT_SIGNAL(clicked()), 00235 TQT_SLOT(slotRescanButtonClicked()) ); 00236 00237 vlay->addStretch( 1 ); 00238 } 00239 00240 Kleo::BackendConfigWidget::~BackendConfigWidget() { 00241 delete d; d = 0; 00242 } 00243 00244 void Kleo::BackendConfigWidget::load() { 00245 d->listView->clear(); 00246 00247 unsigned int backendCount = 0; 00248 00249 // populate the plugin list: 00250 BackendListViewItem * top = 0; 00251 for ( unsigned int i = 0 ; const CryptoBackend * b = d->backendFactory->backend( i ) ; ++i ) { 00252 00253 top = new Kleo::BackendListViewItem( d->listView, top, b ); 00254 00255 ProtocolCheckListItem * last = 0; 00256 for ( int i = 0 ; const char * name = b->enumerateProtocols( i ) ; ++i ) { 00257 const CryptoBackend::Protocol * protocol = b->protocol( name ); 00258 00259 if ( protocol ) { 00260 last = new ProtocolCheckListItem( top, last, name, protocol ); 00261 last->setOn( protocol == d->backendFactory->protocol( name ) ); 00262 } else if ( b->supportsProtocol( name ) ) { 00263 last = new ProtocolCheckListItem( top, last, name, 0 ); 00264 last->setOn( false ); 00265 last->setEnabled( false ); 00266 } 00267 } 00268 00269 top->setOpen( true ); 00270 ++backendCount; 00271 } 00272 00273 if ( backendCount ) { 00274 d->listView->setCurrentItem( d->listView->firstChild() ); 00275 d->listView->setSelected( d->listView->firstChild(), true ); 00276 } 00277 00278 slotSelectionChanged( d->listView->firstChild() ); 00279 } 00280 00281 void Kleo::BackendConfigWidget::slotSelectionChanged( TQListViewItem * ) { 00282 const CryptoBackend* backend = d->listView->currentBackend(); 00283 if ( backend && !backend->config() ) 00284 kdDebug(5150) << "Backend w/o config object!" << endl; 00285 d->configureButton->setEnabled( backend && backend->config() ); 00286 } 00287 00288 00289 void Kleo::BackendConfigWidget::slotRescanButtonClicked() { 00290 TQStringList reasons; 00291 d->backendFactory->scanForBackends( &reasons ); 00292 if ( !reasons.empty() ) 00293 KMessageBox::informationList( this, 00294 i18n("The following problems where encountered during scanning:"), 00295 reasons, i18n("Scan Results") ); 00296 load(); 00297 emit changed( true ); 00298 } 00299 00300 void Kleo::BackendConfigWidget::slotConfigureButtonClicked() { 00301 const CryptoBackend* backend = d->listView->currentBackend(); 00302 if ( backend && backend->config() ) { 00303 Kleo::CryptoConfigDialog dlg( backend->config(), this ); 00304 int result = dlg.exec(); 00305 if ( result == TQDialog::Accepted ) { 00306 // Tell other users of gpgconf (e.g. the s/mime page) that the gpgconf data might have changed 00307 kapp->dcopClient()->emitDCOPSignal( "KPIM::CryptoConfig", "changed()", TQByteArray() ); 00308 // and schedule a rescan, in case the updates make a backend valid 00309 TQTimer::singleShot( 0, this, TQT_SLOT(slotRescanButtonClicked()) ); 00310 } 00311 } 00312 else // shouldn't happen, button is disabled 00313 kdWarning(5150) << "Can't configure backend, no config object available" << endl; 00314 } 00315 00316 void Kleo::BackendConfigWidget::save() const { 00317 for ( int i = 0 ; const char * name = d->backendFactory->enumerateProtocols( i ) ; ++i ) 00318 d->backendFactory->setProtocolBackend( name, d->listView->chosenBackend( name ) ); 00319 } 00320 00321 void Kleo::BackendConfigWidget::virtual_hook( int, void* ) {} 00322 00323 #include "backendconfigwidget.moc"