kmail Library API Documentation

folderdiaacltab.cpp

00001 // -*- mode: C++; c-file-style: "gnu" -*- 00033 #include "folderdiaacltab.h" 00034 #include "acljobs.h" 00035 #include "kmfolderimap.h" 00036 #include "kmfoldercachedimap.h" 00037 #include "kmacctcachedimap.h" 00038 #include "kmfolder.h" 00039 00040 #include <addressesdialog.h> 00041 #include <kabc/addresseelist.h> 00042 #include <kabc/distributionlist.h> 00043 #include <kabc/stdaddressbook.h> 00044 #include <kaddrbook.h> 00045 #include <kpushbutton.h> 00046 #include <kdebug.h> 00047 #include <klocale.h> 00048 00049 #include <qlayout.h> 00050 #include <qlabel.h> 00051 #include <qvbox.h> 00052 #include <qvbuttongroup.h> 00053 #include <qwidgetstack.h> 00054 #include <qradiobutton.h> 00055 #include <qwhatsthis.h> 00056 00057 #include <assert.h> 00058 #include <kmessagebox.h> 00059 00060 using namespace KMail; 00061 00062 // In case your kdelibs is < 3.3 00063 #ifndef I18N_NOOP2 00064 #define I18N_NOOP2( comment,x ) x 00065 #endif 00066 00067 // The set of standard permission sets 00068 static const struct { 00069 unsigned int permissions; 00070 const char* userString; 00071 } standardPermissions[] = { 00072 { 0, I18N_NOOP2( "Permissions", "None" ) }, 00073 { ACLJobs::List | ACLJobs::Read, I18N_NOOP2( "Permissions", "Read" ) }, 00074 { ACLJobs::List | ACLJobs::Read | ACLJobs::Insert | ACLJobs::Post, I18N_NOOP2( "Permissions", "Append" ) }, 00075 { ACLJobs::AllWrite, I18N_NOOP2( "Permissions", "Write" ) }, 00076 { ACLJobs::All, I18N_NOOP2( "Permissions", "All" ) } 00077 }; 00078 00079 00080 KMail::ACLEntryDialog::ACLEntryDialog( IMAPUserIdFormat userIdFormat, const QString& caption, QWidget* parent, const char* name ) 00081 : KDialogBase( parent, name, true /*modal*/, caption, 00082 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true /*sep*/ ) 00083 , mUserIdFormat( userIdFormat ) 00084 { 00085 QWidget *page = new QWidget( this ); 00086 setMainWidget(page); 00087 QGridLayout *topLayout = new QGridLayout( page, 3 /*rows*/, 3 /*cols*/, 0, spacingHint() ); 00088 00089 QLabel *label = new QLabel( i18n( "&User identifier:" ), page ); 00090 topLayout->addWidget( label, 0, 0 ); 00091 00092 mUserIdLineEdit = new KLineEdit( page ); 00093 topLayout->addWidget( mUserIdLineEdit, 0, 1 ); 00094 label->setBuddy( mUserIdLineEdit ); 00095 QWhatsThis::add( mUserIdLineEdit, i18n( "The User Identifier is the login of the user on the IMAP server. This can be a simple user name or the full email address of the user; the login for your own account on the server will tell you which one it is." ) ); 00096 00097 QPushButton* kabBtn = new QPushButton( "...", page ); 00098 topLayout->addWidget( kabBtn, 0, 2 ); 00099 00100 mButtonGroup = new QVButtonGroup( i18n( "Permissions" ), page ); 00101 topLayout->addMultiCellWidget( mButtonGroup, 1, 1, 0, 2 ); 00102 00103 for ( unsigned int i = 0; 00104 i < sizeof( standardPermissions ) / sizeof( *standardPermissions ); 00105 ++i ) { 00106 QRadioButton* cb = new QRadioButton( i18n( "Permissions", standardPermissions[i].userString ), mButtonGroup ); 00107 // We store the permission value (bitfield) as the id of the radiobutton in the group 00108 mButtonGroup->insert( cb, standardPermissions[i].permissions ); 00109 } 00110 topLayout->setRowStretch(2, 10); 00111 00112 connect( mUserIdLineEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotChanged() ) ); 00113 connect( kabBtn, SIGNAL( clicked() ), SLOT( slotSelectAddresses() ) ); 00114 connect( mButtonGroup, SIGNAL( clicked( int ) ), SLOT( slotChanged() ) ); 00115 enableButtonOK( false ); 00116 00117 mUserIdLineEdit->setFocus(); 00118 // Ensure the lineedit is rather wide so that email addresses can be read in it 00119 incInitialSize( QSize( 200, 0 ) ); 00120 } 00121 00122 void KMail::ACLEntryDialog::slotChanged() 00123 { 00124 enableButtonOK( !mUserIdLineEdit->text().isEmpty() && mButtonGroup->selected() != 0 ); 00125 } 00126 00127 static QString addresseeToUserId( const KABC::Addressee& addr, IMAPUserIdFormat userIdFormat ) 00128 { 00129 QString email = addr.preferredEmail(); 00130 if ( userIdFormat == FullEmail ) 00131 return email; 00132 else { // mUserIdFormat == UserName 00133 email.truncate( email.find( '@' ) ); 00134 return email; 00135 } 00136 } 00137 00138 void KMail::ACLEntryDialog::slotSelectAddresses() 00139 { 00140 KPIM::AddressesDialog dlg( this ); 00141 dlg.setShowCC( false ); 00142 dlg.setShowBCC( false ); 00143 if ( mUserIdFormat == FullEmail ) // otherwise we have no way to go back from userid to email 00144 dlg.setSelectedTo( userIds() ); 00145 if ( dlg.exec() != QDialog::Accepted ) 00146 return; 00147 00148 const QStringList distrLists = dlg.toDistributionLists(); 00149 QString txt; 00150 if ( !distrLists.isEmpty() ) { 00151 for( QStringList::ConstIterator it = distrLists.begin(); it != distrLists.end(); ++it ) { 00152 if ( !txt.isEmpty() ) 00153 txt += ", "; 00154 txt += *it; // put the distr list name here, don't expand until saving 00155 } 00156 } 00157 const KABC::Addressee::List lst = dlg.toAddresses(); 00158 if ( !lst.isEmpty() ) { 00159 for( QValueList<KABC::Addressee>::ConstIterator it = lst.begin(); it != lst.end(); ++it ) { 00160 if ( !txt.isEmpty() ) 00161 txt += ", "; 00162 txt += addresseeToUserId( *it, mUserIdFormat ); 00163 } 00164 } 00165 mUserIdLineEdit->setText( txt ); 00166 } 00167 00168 void KMail::ACLEntryDialog::setValues( const QString& userId, unsigned int permissions ) 00169 { 00170 mUserIdLineEdit->setText( userId ); 00171 mButtonGroup->setButton( permissions ); 00172 enableButtonOK( !userId.isEmpty() ); 00173 } 00174 00175 QString KMail::ACLEntryDialog::userId() const 00176 { 00177 return mUserIdLineEdit->text(); 00178 } 00179 00180 QStringList KMail::ACLEntryDialog::userIds() const 00181 { 00182 QStringList lst = QStringList::split( ",", mUserIdLineEdit->text() ); 00183 for( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) { 00184 // Strip white space (in particular, due to ", ") 00185 *it = (*it).stripWhiteSpace(); 00186 } 00187 return lst; 00188 } 00189 00190 unsigned int KMail::ACLEntryDialog::permissions() const 00191 { 00192 return mButtonGroup->selectedId(); 00193 } 00194 00195 // class KMail::FolderDiaACLTab::ListView : public KListView 00196 // { 00197 // public: 00198 // ListView( QWidget* parent, const char* name = 0 ) : KListView( parent, name ) {} 00199 // }; 00200 00201 class KMail::FolderDiaACLTab::ListViewItem : public KListViewItem 00202 { 00203 public: 00204 ListViewItem( QListView* listview ) 00205 : KListViewItem( listview, listview->lastItem() ), 00206 mModified( false ), mNew( false ) {} 00207 00208 void load( const ACLListEntry& entry ); 00209 void save( ACLList& list, KABC::DistributionListManager& manager, IMAPUserIdFormat userIdFormat ); 00210 00211 QString userId() const { return text( 0 ); } 00212 void setUserId( const QString& userId ) { setText( 0, userId ); } 00213 00214 unsigned int permissions() const { return mPermissions; } 00215 void setPermissions( unsigned int permissions ); 00216 00217 bool isModified() const { return mModified; } 00218 void setModified( bool b ) { mModified = b; } 00219 00220 // The fact that an item is new doesn't matter much. 00221 // This bool is only used to handle deletion differently 00222 bool isNew() const { return mNew; } 00223 void setNew( bool b ) { mNew = b; } 00224 00225 private: 00226 unsigned int mPermissions; 00227 QString mInternalRightsList; 00228 bool mModified; 00229 bool mNew; 00230 }; 00231 00232 // internalRightsList is only used if permissions doesn't match the standard set 00233 static QString permissionsToUserString( unsigned int permissions, const QString& internalRightsList ) 00234 { 00235 for ( unsigned int i = 0; 00236 i < sizeof( standardPermissions ) / sizeof( *standardPermissions ); 00237 ++i ) { 00238 if ( permissions == standardPermissions[i].permissions ) 00239 return i18n( "Permissions", standardPermissions[i].userString ); 00240 } 00241 if ( internalRightsList.isEmpty() ) 00242 return i18n( "Custom Permissions" ); // not very helpful, but shouldn't happen 00243 else 00244 return i18n( "Custom Permissions (%1)" ).arg( internalRightsList ); 00245 } 00246 00247 void KMail::FolderDiaACLTab::ListViewItem::setPermissions( unsigned int permissions ) 00248 { 00249 mPermissions = permissions; 00250 setText( 1, permissionsToUserString( permissions, QString::null ) ); 00251 } 00252 00253 void KMail::FolderDiaACLTab::ListViewItem::load( const ACLListEntry& entry ) 00254 { 00255 // Don't allow spaces in userids. If you need this, fix the slave->app communication, 00256 // since it uses space as a separator (imap4.cc, look for GETACL) 00257 // It's ok in distribution list names though, that's why this check is only done here 00258 // and also why there's no validator on the lineedit. 00259 if ( entry.userId.contains( ' ' ) ) 00260 kdWarning(5006) << "Userid contains a space!!! '" << entry.userId << "'" << endl; 00261 00262 setUserId( entry.userId ); 00263 mPermissions = entry.permissions; 00264 mInternalRightsList = entry.internalRightsList; 00265 setText( 1, permissionsToUserString( entry.permissions, entry.internalRightsList ) ); 00266 mModified = entry.changed; // for dimap, so that earlier changes are still marked as changes 00267 } 00268 00269 void KMail::FolderDiaACLTab::ListViewItem::save( ACLList& aclList, KABC::DistributionListManager& manager, IMAPUserIdFormat userIdFormat ) 00270 { 00271 // expand distribution lists 00272 // kaddrbook.cpp has a strange two-pass case-insensitive lookup; is it ok to be case sensitive? 00273 KABC::DistributionList* list = manager.list( userId() ); 00274 if ( list ) { 00275 Q_ASSERT( mModified ); // it has to be new, it couldn't be stored as a distr list name.... 00276 KABC::DistributionList::Entry::List entryList = list->entries(); 00277 KABC::DistributionList::Entry::List::ConstIterator it; // nice number of "::"! 00278 for( it = entryList.begin(); it != entryList.end(); ++it ) { 00279 QString email = (*it).email; 00280 if ( email.isEmpty() ) 00281 email = addresseeToUserId( (*it).addressee, userIdFormat ); 00282 ACLListEntry entry( email, QString::null, mPermissions ); 00283 entry.changed = true; 00284 aclList.append( entry ); 00285 } 00286 } else { // it wasn't a distribution list 00287 ACLListEntry entry( userId(), mInternalRightsList, mPermissions ); 00288 if ( mModified ) { 00289 entry.internalRightsList = QString::null; 00290 entry.changed = true; 00291 } 00292 aclList.append( entry ); 00293 } 00294 } 00295 00297 00298 KMail::FolderDiaACLTab::FolderDiaACLTab( KMFolderDialog* dlg, QWidget* parent, const char* name ) 00299 : FolderDiaTab( parent, name ), 00300 mImapAccount( 0 ), 00301 mUserRights( 0 ), 00302 mDlg( dlg ), 00303 mChanged( false ), mAccepting( false ), mSaving( false ) 00304 { 00305 QVBoxLayout* topLayout = new QVBoxLayout( this ); 00306 // We need a widget stack to show either a label ("no acl support", "please wait"...) 00307 // or a listview. 00308 mStack = new QWidgetStack( this ); 00309 topLayout->addWidget( mStack ); 00310 00311 mLabel = new QLabel( mStack ); 00312 mLabel->setAlignment( AlignHCenter | AlignVCenter | WordBreak ); 00313 mStack->addWidget( mLabel ); 00314 00315 mACLWidget = new QHBox( mStack ); 00316 mACLWidget->setSpacing( KDialog::spacingHint() ); 00317 mListView = new KListView( mACLWidget ); 00318 mListView->setAllColumnsShowFocus( true ); 00319 mStack->addWidget( mACLWidget ); 00320 mListView->addColumn( i18n( "User Id" ) ); 00321 mListView->addColumn( i18n( "Permissions" ) ); 00322 00323 connect( mListView, SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)), 00324 SLOT(slotEditACL(QListViewItem*)) ); 00325 connect( mListView, SIGNAL(returnPressed(QListViewItem*)), 00326 SLOT(slotEditACL(QListViewItem*)) ); 00327 connect( mListView, SIGNAL(selectionChanged(QListViewItem*)), 00328 SLOT(slotSelectionChanged(QListViewItem*)) ); 00329 00330 QVBox* buttonBox = new QVBox( mACLWidget ); 00331 buttonBox->setSpacing( KDialog::spacingHint() ); 00332 mAddACL = new KPushButton( i18n( "Add Entry" ), buttonBox ); 00333 mEditACL = new KPushButton( i18n( "Modify Entry" ), buttonBox ); 00334 mRemoveACL = new KPushButton( i18n( "Remove Entry" ), buttonBox ); 00335 QSpacerItem* spacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ); 00336 static_cast<QBoxLayout *>( buttonBox->layout() )->addItem( spacer ); 00337 00338 connect( mAddACL, SIGNAL( clicked() ), SLOT( slotAddACL() ) ); 00339 connect( mEditACL, SIGNAL( clicked() ), SLOT( slotEditACL() ) ); 00340 connect( mRemoveACL, SIGNAL( clicked() ), SLOT( slotRemoveACL() ) ); 00341 mEditACL->setEnabled( false ); 00342 mRemoveACL->setEnabled( false ); 00343 00344 connect( this, SIGNAL( changed(bool) ), SLOT( slotChanged(bool) ) ); 00345 } 00346 00347 // Warning before save() this will return the url of the _parent_ folder, when creating a new one 00348 KURL KMail::FolderDiaACLTab::imapURL() const 00349 { 00350 KURL url = mImapAccount->getUrl(); 00351 url.setPath( mImapPath ); 00352 return url; 00353 } 00354 00355 void KMail::FolderDiaACLTab::initializeWithValuesFromFolder( KMFolder* folder ) 00356 { 00357 // This can be simplified once KMFolderImap and KMFolderCachedImap have a common base class 00358 mFolderType = folder->folderType(); 00359 if ( mFolderType == KMFolderTypeImap ) { 00360 KMFolderImap* folderImap = static_cast<KMFolderImap*>( folder->storage() ); 00361 mImapPath = folderImap->imapPath(); 00362 mImapAccount = folderImap->account(); 00363 mUserRights = folderImap->userRights(); 00364 } 00365 else if ( mFolderType == KMFolderTypeCachedImap ) { 00366 KMFolderCachedImap* folderImap = static_cast<KMFolderCachedImap*>( folder->storage() ); 00367 mImapPath = folderImap->imapPath(); 00368 mImapAccount = folderImap->account(); 00369 mUserRights = folderImap->userRights(); 00370 } 00371 else 00372 assert( 0 ); // see KMFolderDialog constructor 00373 } 00374 00375 void KMail::FolderDiaACLTab::load() 00376 { 00377 if ( mDlg->folder() ) { 00378 // existing folder 00379 initializeWithValuesFromFolder( mDlg->folder() ); 00380 } else if ( mDlg->parentFolder() ) { 00381 // new folder 00382 initializeWithValuesFromFolder( mDlg->parentFolder() ); 00383 mChanged = true; // ensure that saving happens 00384 } 00385 00386 // KABC knows email addresses. 00387 // We want LDAP userids. 00388 // Depending on the IMAP server setup, the userid can be the full email address, 00389 // or just the username part of it. 00390 // To know which one it is, we currently have a hidden config option, 00391 // but the default value is determined from the current user's own id. 00392 QString defaultFormat = "fullemail"; 00393 // warning mImapAccount can be 0 if creating a subsubsubfolder with dimap... (bug?) 00394 if ( mImapAccount && mImapAccount->login().find('@') == -1 ) 00395 defaultFormat = "username"; // no @ found, so we assume it's just the username 00396 KConfigGroup configGroup( kmkernel->config(), "IMAP" ); 00397 QString str = configGroup.readEntry( "UserIdFormat", defaultFormat ); 00398 mUserIdFormat = FullEmail; 00399 if ( str == "username" ) 00400 mUserIdFormat = UserName; 00401 00402 if ( mFolderType == KMFolderTypeCachedImap ) { 00403 KMFolder* folder = mDlg->folder() ? mDlg->folder() : mDlg->parentFolder(); 00404 KMFolderCachedImap* folderImap = static_cast<KMFolderCachedImap*>( folder->storage() ); 00405 if ( mUserRights == -1 ) { // error 00406 mLabel->setText( i18n( "Error retrieving user permissions." ) ); 00407 } else if ( mUserRights == 0 ) { // not listed yet 00408 mLabel->setText( i18n( "Information not retrieved from server yet, please use \"Check Mail\"." ) ); 00409 // TODO: save mUserRights and mACLList into a config file so that this almost never happens 00410 } else { 00411 loadFinished( folderImap->aclList() ); 00412 } 00413 return; 00414 } 00415 00416 // Loading, for online IMAP, consists of four steps: 00417 // 1) connect 00418 // 2) get user rights 00419 // 3) load ACLs 00420 00421 // First ensure we are connected 00422 mStack->raiseWidget( mLabel ); 00423 if ( !mImapAccount ) { // hmmm? 00424 mLabel->setText( i18n( "Error: no IMAP account defined for this folder" ) ); 00425 return; 00426 } 00427 KMFolder* folder = mDlg->folder() ? mDlg->folder() : mDlg->parentFolder(); 00428 if ( folder && folder->storage() == mImapAccount->rootFolder() ) 00429 return; // nothing to be done for the (virtual) account folder 00430 mLabel->setText( i18n( "Connecting to server %1, please wait..." ).arg( mImapAccount->host() ) ); 00431 ImapAccountBase::ConnectionState state = mImapAccount->makeConnection(); 00432 if ( state == ImapAccountBase::Error ) { // Cancelled by user, or slave can't start 00433 slotConnectionResult( -1, QString::null ); 00434 } else if ( state == ImapAccountBase::Connecting ) { 00435 connect( mImapAccount, SIGNAL( connectionResult(int, const QString&) ), 00436 this, SLOT( slotConnectionResult(int, const QString&) ) ); 00437 } else { // Connected 00438 slotConnectionResult( 0, QString::null ); 00439 } 00440 } 00441 00442 void KMail::FolderDiaACLTab::slotConnectionResult( int errorCode, const QString& errorMsg ) 00443 { 00444 disconnect( mImapAccount, SIGNAL( connectionResult(int, const QString&) ), 00445 this, SLOT( slotConnectionResult(int, const QString&) ) ); 00446 if ( errorCode ) { 00447 if ( errorCode == -1 ) // unspecified error 00448 mLabel->setText( i18n( "Error connecting to server %1" ).arg( mImapAccount->host() ) ); 00449 else 00450 // Connection error (error message box already shown by the account) 00451 mLabel->setText( KIO::buildErrorString( errorCode, errorMsg ) ); 00452 return; 00453 } 00454 00455 if ( mUserRights == 0 ) { 00456 connect( mImapAccount, SIGNAL( receivedUserRights( KMFolder* ) ), 00457 this, SLOT( slotReceivedUserRights( KMFolder* ) ) ); 00458 KMFolder* folder = mDlg->folder() ? mDlg->folder() : mDlg->parentFolder(); 00459 mImapAccount->getUserRights( folder, mImapPath ); 00460 } 00461 else 00462 startListing(); 00463 } 00464 00465 void KMail::FolderDiaACLTab::slotReceivedUserRights( KMFolder* folder ) 00466 { 00467 if ( !mImapAccount->hasACLSupport() ) { 00468 mLabel->setText( i18n( "This IMAP server does not have support for access control lists (ACL)" ) ); 00469 return; 00470 } 00471 00472 if ( folder == mDlg->folder() ? mDlg->folder() : mDlg->parentFolder() ) { 00473 KMFolderImap* folderImap = static_cast<KMFolderImap*>( folder->storage() ); 00474 mUserRights = folderImap->userRights(); 00475 startListing(); 00476 } 00477 } 00478 00479 void KMail::FolderDiaACLTab::startListing() 00480 { 00481 // List ACLs of folder - or its parent, if creating a new folder 00482 mImapAccount->getACL( mDlg->folder() ? mDlg->folder() : mDlg->parentFolder(), mImapPath ); 00483 connect( mImapAccount, SIGNAL(receivedACL( KMFolder*, KIO::Job*, const KMail::ACLList& )), 00484 this, SLOT(slotReceivedACL( KMFolder*, KIO::Job*, const KMail::ACLList& )) ); 00485 } 00486 00487 void KMail::FolderDiaACLTab::slotReceivedACL( KMFolder* folder, KIO::Job* job, const KMail::ACLList& aclList ) 00488 { 00489 if ( folder == ( mDlg->folder() ? mDlg->folder() : mDlg->parentFolder() ) ) { 00490 disconnect( mImapAccount, SIGNAL(receivedACL( KMFolder*, KIO::Job*, const KMail::ACLList& )), 00491 this, SLOT(slotReceivedACL( KMFolder*, KIO::Job*, const KMail::ACLList& )) ); 00492 00493 if ( job && job->error() ) { 00494 if ( job->error() == KIO::ERR_UNSUPPORTED_ACTION ) 00495 mLabel->setText( i18n( "This IMAP server does not have support for access control lists (ACL)" ) ); 00496 else 00497 mLabel->setText( i18n( "Error retrieving access control list (ACL) from server\n%1" ).arg( job->errorString() ) ); 00498 return; 00499 } 00500 00501 loadFinished( aclList ); 00502 } 00503 } 00504 00505 void KMail::FolderDiaACLTab::loadListView( const ACLList& aclList ) 00506 { 00507 mListView->clear(); 00508 for( ACLList::const_iterator it = aclList.begin(); it != aclList.end(); ++it ) { 00509 // -1 means deleted (for cachedimap), don't show those 00510 if ( (*it).permissions > -1 ) { 00511 ListViewItem* item = new ListViewItem( mListView ); 00512 item->load( *it ); 00513 if ( !mDlg->folder() ) // new folder? everything is new then 00514 item->setModified( true ); 00515 } 00516 } 00517 } 00518 00519 void KMail::FolderDiaACLTab::loadFinished( const ACLList& aclList ) 00520 { 00521 loadListView( aclList ); 00522 if ( mDlg->folder() ) // not when creating a new folder 00523 mInitialACLList = aclList; 00524 mStack->raiseWidget( mACLWidget ); 00525 slotSelectionChanged( mListView->selectedItem() ); 00526 } 00527 00528 void KMail::FolderDiaACLTab::slotEditACL(QListViewItem* item) 00529 { 00530 if ( !item ) return; 00531 bool canAdmin = ( mUserRights & ACLJobs::Administer ); 00532 // Same logic as in slotSelectionChanged, but this is also needed for double-click IIRC 00533 if ( canAdmin && mImapAccount && item ) { 00534 // Don't allow users to remove their own admin permissions - there's no way back 00535 ListViewItem* ACLitem = static_cast<ListViewItem *>( item ); 00536 if ( mImapAccount->login() == ACLitem->userId() && ACLitem->permissions() == ACLJobs::All ) 00537 canAdmin = false; 00538 } 00539 if ( !canAdmin ) return; 00540 00541 ListViewItem* ACLitem = static_cast<ListViewItem *>( mListView->currentItem() ); 00542 ACLEntryDialog dlg( mUserIdFormat, i18n( "Modify Permissions" ), this ); 00543 dlg.setValues( ACLitem->userId(), ACLitem->permissions() ); 00544 if ( dlg.exec() == QDialog::Accepted ) { 00545 QStringList userIds = dlg.userIds(); 00546 Q_ASSERT( !userIds.isEmpty() ); // impossible, the OK button is disabled in that case 00547 ACLitem->setUserId( dlg.userIds().front() ); 00548 ACLitem->setPermissions( dlg.permissions() ); 00549 ACLitem->setModified( true ); 00550 emit changed(true); 00551 if ( userIds.count() > 1 ) { // more emails were added, append them 00552 userIds.pop_front(); 00553 addACLs( userIds, dlg.permissions() ); 00554 } 00555 } 00556 } 00557 00558 void KMail::FolderDiaACLTab::slotEditACL() 00559 { 00560 slotEditACL( mListView->currentItem() ); 00561 } 00562 00563 void KMail::FolderDiaACLTab::addACLs( const QStringList& userIds, unsigned int permissions ) 00564 { 00565 for( QStringList::const_iterator it = userIds.begin(); it != userIds.end(); ++it ) { 00566 ListViewItem* ACLitem = new ListViewItem( mListView ); 00567 ACLitem->setUserId( *it ); 00568 ACLitem->setPermissions( permissions ); 00569 ACLitem->setModified( true ); 00570 ACLitem->setNew( true ); 00571 } 00572 } 00573 00574 void KMail::FolderDiaACLTab::slotAddACL() 00575 { 00576 ACLEntryDialog dlg( mUserIdFormat, i18n( "Add Permissions" ), this ); 00577 if ( dlg.exec() == QDialog::Accepted ) { 00578 const QStringList userIds = dlg.userIds(); 00579 addACLs( dlg.userIds(), dlg.permissions() ); 00580 emit changed(true); 00581 } 00582 } 00583 00584 void KMail::FolderDiaACLTab::slotSelectionChanged(QListViewItem* item) 00585 { 00586 bool canAdmin = ( mUserRights & ACLJobs::Administer ); 00587 bool canAdminThisItem = canAdmin; 00588 if ( canAdmin && mImapAccount && item ) { 00589 // Don't allow users to remove their own admin permissions - there's no way back 00590 ListViewItem* ACLitem = static_cast<ListViewItem *>( item ); 00591 if ( mImapAccount->login() == ACLitem->userId() && ACLitem->permissions() == ACLJobs::All ) 00592 canAdminThisItem = false; 00593 } 00594 00595 bool lvVisible = mStack->visibleWidget() == mACLWidget; 00596 mAddACL->setEnabled( lvVisible && canAdmin && !mSaving ); 00597 mEditACL->setEnabled( item && lvVisible && canAdminThisItem && !mSaving ); 00598 mRemoveACL->setEnabled( item && lvVisible && canAdminThisItem && !mSaving ); 00599 } 00600 00601 void KMail::FolderDiaACLTab::slotRemoveACL() 00602 { 00603 ListViewItem* ACLitem = static_cast<ListViewItem *>( mListView->currentItem() ); 00604 if ( !ACLitem ) 00605 return; 00606 if ( !ACLitem->isNew() ) { 00607 if ( mImapAccount && mImapAccount->login() == ACLitem->userId() ) { 00608 if ( KMessageBox::Cancel == KMessageBox::warningContinueCancel( topLevelWidget(), 00609 i18n( "Do you really want to remove your own permissions for this folder? You will not be able to access it afterwards." ), i18n( "Remove" ) ) ) 00610 return; 00611 } 00612 mRemovedACLs.append( ACLitem->userId() ); 00613 } 00614 delete ACLitem; 00615 emit changed(true); 00616 } 00617 00618 KMail::FolderDiaTab::AcceptStatus KMail::FolderDiaACLTab::accept() 00619 { 00620 if ( !mChanged || !mImapAccount ) 00621 return Accepted; // (no change made), ok for accepting the dialog immediately 00622 // If there were changes, we need to apply them first (which is async) 00623 save(); 00624 if ( mFolderType == KMFolderTypeCachedImap ) 00625 return Accepted; // cached imap: changes saved immediately into the folder 00626 // disconnected imap: async job[s] running 00627 mAccepting = true; 00628 return Delayed; 00629 } 00630 00631 bool KMail::FolderDiaACLTab::save() 00632 { 00633 if ( !mChanged || !mImapAccount ) // no changes 00634 return true; 00635 assert( mDlg->folder() ); // should have been created already 00636 00637 // Expand distribution lists. This is necessary because after Apply 00638 // we would otherwise be able to "modify" the permissions for a distr list, 00639 // which wouldn't work since the ACLList and the server only know about the 00640 // individual addresses. 00641 // slotACLChanged would have trouble matching the item too. 00642 // After reloading we'd see the list expanded anyway, 00643 // so this is more consistent. 00644 // But we do it now and not when inserting it, because this allows to 00645 // immediately remove a wrongly inserted distr list without having to 00646 // remove 100 items. 00647 // Now, how to expand them? Playing with listviewitem iterators and inserting 00648 // listviewitems at the same time sounds dangerous, so let's just save into 00649 // ACLList and reload that. 00650 KABC::AddressBook *addressBook = KABC::StdAddressBook::self(); 00651 KABC::DistributionListManager manager( addressBook ); 00652 manager.load(); 00653 ACLList aclList; 00654 for ( QListViewItem* item = mListView->firstChild(); item; item = item->nextSibling() ) { 00655 ListViewItem* ACLitem = static_cast<ListViewItem *>( item ); 00656 ACLitem->save( aclList, manager, mUserIdFormat ); 00657 } 00658 loadListView( aclList ); 00659 00660 // Now compare with the initial ACLList, because if the user renamed a userid 00661 // we have to add the old userid to the "to be deleted" list. 00662 for( ACLList::ConstIterator init = mInitialACLList.begin(); init != mInitialACLList.end(); ++init ) { 00663 bool isInNewList = false; 00664 QString uid = (*init).userId; 00665 for( ACLList::ConstIterator it = aclList.begin(); it != aclList.end() && !isInNewList; ++it ) 00666 isInNewList = uid == (*it).userId; 00667 if ( !isInNewList && !mRemovedACLs.contains(uid) ) 00668 mRemovedACLs.append( uid ); 00669 } 00670 00671 for ( QStringList::ConstIterator rit = mRemovedACLs.begin(); rit != mRemovedACLs.end(); ++rit ) { 00672 // We use permissions == -1 to signify deleting. At least on cyrus, setacl(0) or deleteacl are the same, 00673 // but I'm not sure if that's true for all servers. 00674 ACLListEntry entry( *rit, QString::null, -1 ); 00675 entry.changed = true; 00676 aclList.append( entry ); 00677 } 00678 00679 // aclList is finally ready. We can save it (dimap) or apply it (imap). 00680 00681 if ( mFolderType == KMFolderTypeCachedImap ) { 00682 // Apply the changes to the aclList stored in the folder. 00683 // We have to do this now and not before, so that cancel really cancels. 00684 KMFolderCachedImap* folderImap = static_cast<KMFolderCachedImap*>( mDlg->folder()->storage() ); 00685 folderImap->setACLList( aclList ); 00686 return true; 00687 } 00688 00689 mACLList = aclList; 00690 00691 KMFolderImap* parentImap = mDlg->parentFolder() ? static_cast<KMFolderImap*>( mDlg->parentFolder()->storage() ) : 0; 00692 00693 if ( mDlg->isNewFolder() ) { 00694 // The folder isn't created yet, wait for it 00695 // It's a two-step process (mkdir+listDir) so we wait for the dir listing to be complete 00696 connect( parentImap, SIGNAL( directoryListingFinished(KMFolderImap*) ), 00697 this, SLOT( slotDirectoryListingFinished(KMFolderImap*) ) ); 00698 } else { 00699 slotDirectoryListingFinished( parentImap ); 00700 } 00701 return true; 00702 } 00703 00704 void KMail::FolderDiaACLTab::slotDirectoryListingFinished(KMFolderImap* f) 00705 { 00706 if ( !f || 00707 f != static_cast<KMFolderImap*>( mDlg->parentFolder()->storage() ) || 00708 !mDlg->folder() || 00709 !mDlg->folder()->storage() ) { 00710 emit readyForAccept(); 00711 return; 00712 } 00713 00714 // When creating a new folder with online imap, update mImapPath 00715 KMFolderImap* folderImap = static_cast<KMFolderImap*>( mDlg->folder()->storage() ); 00716 if ( !folderImap || folderImap->imapPath().isEmpty() ) 00717 return; 00718 mImapPath = folderImap->imapPath(); 00719 00720 KIO::Job* job = ACLJobs::multiSetACL( mImapAccount->slave(), imapURL(), mACLList ); 00721 ImapAccountBase::jobData jd; 00722 jd.total = 1; jd.done = 0; jd.parent = 0; 00723 mImapAccount->insertJob(job, jd); 00724 00725 connect(job, SIGNAL(result(KIO::Job *)), 00726 SLOT(slotMultiSetACLResult(KIO::Job *))); 00727 connect(job, SIGNAL(aclChanged( const QString&, int )), 00728 SLOT(slotACLChanged( const QString&, int )) ); 00729 } 00730 00731 void KMail::FolderDiaACLTab::slotMultiSetACLResult(KIO::Job* job) 00732 { 00733 ImapAccountBase::JobIterator it = mImapAccount->findJob( job ); 00734 if ( it == mImapAccount->jobsEnd() ) return; 00735 mImapAccount->removeJob( it ); 00736 00737 if ( job->error() ) { 00738 job->showErrorDialog( this ); 00739 if ( mAccepting ) { 00740 emit cancelAccept(); 00741 mAccepting = false; // don't emit readyForAccept anymore 00742 } 00743 } else { 00744 if ( mAccepting ) 00745 emit readyForAccept(); 00746 } 00747 } 00748 00749 void KMail::FolderDiaACLTab::slotACLChanged( const QString& userId, int permissions ) 00750 { 00751 // The job indicates success in changing the permissions for this user 00752 // -> we note that it's been done. 00753 bool ok = false; 00754 if ( permissions > -1 ) { 00755 for ( QListViewItem* item = mListView->firstChild(); item; item = item->nextSibling() ) { 00756 ListViewItem* ACLitem = static_cast<ListViewItem *>( item ); 00757 if ( ACLitem->userId() == userId ) { 00758 ACLitem->setModified( false ); 00759 ACLitem->setNew( false ); 00760 ok = true; 00761 break; 00762 } 00763 } 00764 } else { 00765 uint nr = mRemovedACLs.remove( userId ); 00766 ok = ( nr > 0 ); 00767 } 00768 if ( !ok ) 00769 kdWarning(5006) << k_funcinfo << " no item found for userId " << userId << endl; 00770 } 00771 00772 void KMail::FolderDiaACLTab::slotChanged( bool b ) 00773 { 00774 mChanged = b; 00775 } 00776 00777 bool KMail::FolderDiaACLTab::supports( KMFolder* refFolder ) 00778 { 00779 ImapAccountBase* imapAccount = 0; 00780 if ( refFolder->folderType() == KMFolderTypeImap ) 00781 imapAccount = static_cast<KMFolderImap*>( refFolder->storage() )->account(); 00782 else 00783 imapAccount = static_cast<KMFolderCachedImap*>( refFolder->storage() )->account(); 00784 return imapAccount && imapAccount->hasACLSupport(); // support for ACLs (or not tried connecting yet) 00785 } 00786 00787 #include "folderdiaacltab.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 1 15:19:17 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003