You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
484 lines
16 KiB
484 lines
16 KiB
// -*- mode: C++; c-file-style: "gnu" -*- |
|
/** |
|
* folderdiaacltab.cpp |
|
* |
|
* Copyright (c) 2004 David Faure <faure@kde.org> |
|
* |
|
* |
|
* This program is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation; version 2 of the License |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
* |
|
* In addition, as a special exception, the copyright holders give |
|
* permission to link the code of this program with any edition of |
|
* the Qt library by Trolltech AS, Norway (or with modified versions |
|
* of Qt that use the same license as Qt), and distribute linked |
|
* combinations including the two. You must obey the GNU General |
|
* Public License in all respects for all of the code used other than |
|
* Qt. If you modify this file, you may extend this exception to |
|
* your version of the file, but you are not obligated to do so. If |
|
* you do not wish to do so, delete this exception statement from |
|
* your version. |
|
*/ |
|
|
|
#include "folderdiaacltab.h" |
|
#include "acljobs.h" |
|
#include "kmfolderimap.h" |
|
#include "kmfoldercachedimap.h" |
|
#include "kmacctcachedimap.h" |
|
#include "kmfolder.h" |
|
|
|
#include <kpushbutton.h> |
|
#include <kdebug.h> |
|
|
|
#include <qlayout.h> |
|
#include <qlabel.h> |
|
#include <qvbox.h> |
|
#include <qvbuttongroup.h> |
|
#include <qwidgetstack.h> |
|
#include <qradiobutton.h> |
|
#include <qwhatsthis.h> |
|
|
|
#include <assert.h> |
|
|
|
using namespace KMail; |
|
|
|
// In case your kdelibs is < 3.3 |
|
#ifndef I18N_NOOP2 |
|
#define I18N_NOOP2( comment,x ) x |
|
#endif |
|
|
|
// The set of standard permission sets |
|
static const struct { |
|
unsigned int permissions; |
|
const char* userString; |
|
} standardPermissions[] = { |
|
{ 0, I18N_NOOP2( "Permissions", "None" ) }, |
|
{ ACLJobs::List | ACLJobs::Read, I18N_NOOP2( "Permissions", "Read" ) }, |
|
{ ACLJobs::List | ACLJobs::Read | ACLJobs::Insert, I18N_NOOP2( "Permissions", "Append" ) }, |
|
{ ACLJobs::AllWrite, I18N_NOOP2( "Permissions", "Write" ) }, |
|
{ ACLJobs::All, I18N_NOOP2( "Permissions", "All" ) } |
|
}; |
|
|
|
|
|
KMail::ACLEntryDialog::ACLEntryDialog( const QString& caption, QWidget* parent, const char* name ) |
|
: KDialogBase( parent, name, true /*modal*/, caption, |
|
KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true /*sep*/ ) |
|
{ |
|
QWidget *page = new QWidget( this ); |
|
setMainWidget(page); |
|
QGridLayout *topLayout = new QGridLayout( page, 3, 2, 0, spacingHint() ); |
|
|
|
QLabel *label = new QLabel( i18n( "&User Identifier" ), page ); |
|
topLayout->addWidget( label, 0, 0 ); |
|
|
|
mUserIdLineEdit = new KLineEdit( page ); |
|
topLayout->addWidget( mUserIdLineEdit, 0, 1 ); |
|
label->setBuddy( mUserIdLineEdit ); |
|
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." ) ); |
|
|
|
mButtonGroup = new QVButtonGroup( i18n( "Permissions" ), page ); |
|
topLayout->addMultiCellWidget( mButtonGroup, 1, 1, 0, 1 ); |
|
|
|
for ( unsigned int i = 0; |
|
i < sizeof( standardPermissions ) / sizeof( *standardPermissions ); |
|
++i ) { |
|
QRadioButton* cb = new QRadioButton( i18n( "Permissions", standardPermissions[i].userString ), mButtonGroup ); |
|
// We store the permission value (bitfield) as the id of the radiobutton in the group |
|
mButtonGroup->insert( cb, standardPermissions[i].permissions ); |
|
} |
|
topLayout->setRowStretch(2, 10); |
|
|
|
connect( mUserIdLineEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotChanged() ) ); |
|
connect( mButtonGroup, SIGNAL( clicked( int ) ), SLOT( slotChanged() ) ); |
|
enableButtonOK( false ); |
|
} |
|
|
|
void KMail::ACLEntryDialog::slotChanged() |
|
{ |
|
enableButtonOK( !mUserIdLineEdit->text().isEmpty() && mButtonGroup->selected() != 0 ); |
|
} |
|
|
|
void KMail::ACLEntryDialog::setValues( const QString& userId, unsigned int permissions ) |
|
{ |
|
mUserIdLineEdit->setText( userId ); |
|
mButtonGroup->setButton( permissions ); |
|
enableButtonOK( !userId.isEmpty() ); |
|
} |
|
|
|
QString KMail::ACLEntryDialog::userId() const |
|
{ |
|
return mUserIdLineEdit->text(); |
|
} |
|
|
|
unsigned int KMail::ACLEntryDialog::permissions() const |
|
{ |
|
return mButtonGroup->selectedId(); |
|
} |
|
|
|
// class KMail::FolderDiaACLTab::ListView : public KListView |
|
// { |
|
// public: |
|
// ListView( QWidget* parent, const char* name = 0 ) : KListView( parent, name ) {} |
|
// }; |
|
|
|
class KMail::FolderDiaACLTab::ListViewItem : public KListViewItem |
|
{ |
|
public: |
|
ListViewItem( QListView* listview ) |
|
: KListViewItem( listview, listview->lastItem() ), |
|
mJob( 0 ), mModified( false ) {} |
|
|
|
void load( const ACLJobs::ACLListEntry& entry ); |
|
|
|
QString userId() const { return text( 0 ); } |
|
void setUserId( const QString& userId ) { setText( 0, userId ); } |
|
|
|
unsigned int permissions() const { return mPermissions; } |
|
void setPermissions( unsigned int permissions ); |
|
|
|
bool isModified() const { return mModified; } |
|
void setModified( bool b ) { mModified = b; } |
|
|
|
KIO::Job* job() const { return mJob; } |
|
void setJob( KIO::Job* job ) { mJob = job; } |
|
|
|
private: |
|
KIO::Job* mJob; |
|
unsigned int mPermissions; |
|
bool mModified; |
|
}; |
|
|
|
// internalRightsList is only used if permissions doesn't match the standard set |
|
static QString permissionsToUserString( unsigned int permissions, const QString& internalRightsList ) |
|
{ |
|
for ( unsigned int i = 0; |
|
i < sizeof( standardPermissions ) / sizeof( *standardPermissions ); |
|
++i ) { |
|
if ( permissions == standardPermissions[i].permissions ) |
|
return i18n( "Permissions", standardPermissions[i].userString ); |
|
} |
|
if ( internalRightsList.isEmpty() ) |
|
return i18n( "Custom Permissions" ); // not very helpful, but shouldn't happen |
|
else |
|
return i18n( "Custom Permissions (%1)" ).arg( internalRightsList ); |
|
} |
|
|
|
void KMail::FolderDiaACLTab::ListViewItem::setPermissions( unsigned int permissions ) |
|
{ |
|
mPermissions = permissions; |
|
setText( 1, permissionsToUserString( permissions, QString::null ) ); |
|
} |
|
|
|
void KMail::FolderDiaACLTab::ListViewItem::load( const ACLJobs::ACLListEntry& entry ) |
|
{ |
|
setUserId( entry.userid ); |
|
mPermissions = entry.permissions; |
|
setText( 1, permissionsToUserString( entry.permissions, entry.internalRightsList ) ); |
|
} |
|
|
|
//// |
|
|
|
KMail::FolderDiaACLTab::FolderDiaACLTab( KMFolderDialog* dlg, QWidget* parent, const char* name ) |
|
: FolderDiaTab( parent, name ), mDlg( dlg ), |
|
mJobCounter( 0 ), |
|
mChanged( false ), mAccepting( false ) |
|
{ |
|
QVBoxLayout* topLayout = new QVBoxLayout( this ); |
|
// We need a widget stack to show either a label ("no acl support", "please wait"...) |
|
// or a listview. |
|
mStack = new QWidgetStack( this ); |
|
topLayout->addWidget( mStack ); |
|
|
|
mLabel = new QLabel( mStack ); |
|
mLabel->setAlignment( AlignHCenter | AlignVCenter | WordBreak ); |
|
mStack->addWidget( mLabel ); |
|
|
|
mACLWidget = new QHBox( mStack ); |
|
mListView = new KListView( mACLWidget ); |
|
mListView->setAllColumnsShowFocus( true ); |
|
mStack->addWidget( mACLWidget ); |
|
mListView->addColumn( i18n( "User Id" ) ); |
|
mListView->addColumn( i18n( "Permissions" ) ); |
|
|
|
connect( mListView, SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)), |
|
SLOT(slotEditACL(QListViewItem*)) ); |
|
connect( mListView, SIGNAL(returnPressed(QListViewItem*)), |
|
SLOT(slotEditACL(QListViewItem*)) ); |
|
connect( mListView, SIGNAL(selectionChanged(QListViewItem*)), |
|
SLOT(slotSelectionChanged(QListViewItem*)) ); |
|
|
|
QVBox* buttonBox = new QVBox( mACLWidget ); |
|
mAddACL = new KPushButton( i18n( "Add entry" ), buttonBox ); |
|
mEditACL = new KPushButton( i18n( "Modify entry" ), buttonBox ); |
|
mRemoveACL = new KPushButton( i18n( "Remove entry" ), buttonBox ); |
|
QSpacerItem* spacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ); |
|
static_cast<QBoxLayout *>( buttonBox->layout() )->addItem( spacer ); |
|
|
|
connect( mAddACL, SIGNAL( clicked() ), SLOT( slotAddACL() ) ); |
|
connect( mEditACL, SIGNAL( clicked() ), SLOT( slotEditACL() ) ); |
|
connect( mRemoveACL, SIGNAL( clicked() ), SLOT( slotRemoveACL() ) ); |
|
mEditACL->setEnabled( false ); |
|
mRemoveACL->setEnabled( false ); |
|
|
|
connect( this, SIGNAL( changed(bool) ), SLOT( slotChanged(bool) ) ); |
|
} |
|
|
|
// This can probably be removed once KMFolderImap and KMFolderCachedImap have a common base class |
|
KMail::ImapAccountBase* KMail::FolderDiaACLTab::imapAccount() const |
|
{ |
|
KMFolder* folder = mDlg->folder(); |
|
if ( folder->folderType() == KMFolderTypeImap ) |
|
return static_cast<KMFolderImap*>( folder->storage() )->account(); |
|
else if ( folder->folderType() == KMFolderTypeCachedImap ) |
|
return static_cast<KMFolderCachedImap*>( folder->storage() )->account(); |
|
else |
|
assert( 0 ); // see KMFolderDialog constructor |
|
return 0; |
|
} |
|
|
|
#if 0 // not needed right now |
|
// This can probably be removed once KMFolderImap and KMFolderCachedImap have a common base class |
|
QString KMail::FolderDiaACLTab::imapPath() const |
|
{ |
|
KMFolder* folder = mDlg->folder(); |
|
if ( folder->folderType() == KMFolderTypeImap ) |
|
return static_cast<KMFolderImap*>( folder->storage() )->imapPath(); |
|
else if ( folder->folderType() == KMFolderTypeCachedImap ) |
|
return static_cast<KMFolderCachedImap*>( folder->storage() )->imapPath(); |
|
else |
|
assert( 0 ); // see KMFolderDialog constructor |
|
return 0; |
|
} |
|
#endif |
|
|
|
// This can probably be removed once KMFolderImap and KMFolderCachedImap have a common base class |
|
KURL KMail::FolderDiaACLTab::imapURL() const |
|
{ |
|
ImapAccountBase* account = imapAccount(); |
|
KURL url = account->getUrl(); |
|
KMFolder* folder = mDlg->folder(); |
|
if ( folder->folderType() == KMFolderTypeImap ) |
|
url.setPath( static_cast<KMFolderImap*>( folder->storage() )->imapPath() ); |
|
else if ( folder->folderType() == KMFolderTypeCachedImap ) |
|
url.setPath( static_cast<KMFolderCachedImap*>( folder->storage() )->imapPath() ); |
|
else |
|
assert( 0 ); // see KMFolderDialog constructor |
|
return url; |
|
} |
|
|
|
void KMail::FolderDiaACLTab::load() |
|
{ |
|
// First ensure we are connected |
|
ImapAccountBase* account = imapAccount(); |
|
mLabel->setText( i18n( "Connecting to server %1, please wait..." ).arg( account->host() ) ); |
|
mStack->raiseWidget( mLabel ); |
|
ImapAccountBase::ConnectionState state = account->makeConnection(); |
|
if ( state == ImapAccountBase::Error ) { // Cancelled by user, or slave can't start |
|
slotConnectionResult( 1 ); // any error code != 0 |
|
} else if ( state == ImapAccountBase::Connecting ) { |
|
connect( account, SIGNAL( connectionResult(int) ), |
|
this, SLOT( slotConnectionResult(int) ) ); |
|
} else { // Connected |
|
slotConnectionResult( 0 ); |
|
} |
|
} |
|
|
|
void KMail::FolderDiaACLTab::slotConnectionResult( int errorCode ) |
|
{ |
|
ImapAccountBase* account = imapAccount(); |
|
disconnect( account, SIGNAL( connectionResult(int) ), |
|
this, SLOT( slotConnectionResult(int) ) ); |
|
if ( errorCode ) { |
|
// Error (error message already shown by the account) |
|
mLabel->setText( i18n( "Error connecting to server %1" ).arg( account->host() ) ); |
|
return; |
|
} |
|
|
|
ACLJobs::GetACLJob* job = ACLJobs::getACL( account->slave(), imapURL() ); |
|
|
|
ImapAccountBase::jobData jd; |
|
jd.total = 1; jd.done = 0; jd.parent = NULL; |
|
account->insertJob(job, jd); |
|
|
|
connect(job, SIGNAL(result(KIO::Job *)), |
|
SLOT(slotGetACLResult(KIO::Job *))); |
|
} |
|
|
|
void KMail::FolderDiaACLTab::slotGetACLResult(KIO::Job *job) |
|
{ |
|
ImapAccountBase* account = imapAccount(); |
|
ImapAccountBase::JobIterator it = account->findJob( job ); |
|
if ( it == account->jobsEnd() ) return; |
|
account->removeJob( it ); |
|
if ( job->error() ) { |
|
mLabel->setText( i18n( "Error retrieving access control list (ACL) from server\n%1" ).arg( job->errorString() ) ); |
|
return; |
|
} |
|
|
|
ACLJobs::GetACLJob* aclJob = static_cast<ACLJobs::GetACLJob *>( job ); |
|
// Now we can populate the listview |
|
const QValueVector<ACLJobs::ACLListEntry>& aclList = aclJob->entries(); |
|
for( QValueVector<ACLJobs::ACLListEntry>::ConstIterator it = aclList.begin(); it != aclList.end(); ++it ) { |
|
ListViewItem* item = new ListViewItem( mListView ); |
|
item->load( *it ); |
|
} |
|
mStack->raiseWidget( mACLWidget ); |
|
slotSelectionChanged( mListView->selectedItem() ); |
|
} |
|
|
|
void KMail::FolderDiaACLTab::slotEditACL(QListViewItem* item) |
|
{ |
|
if ( !item ) return; |
|
ListViewItem* ACLitem = static_cast<ListViewItem *>( mListView->currentItem() ); |
|
ACLEntryDialog dlg( i18n( "Modify Permissions" ), this ); |
|
dlg.setValues( ACLitem->userId(), ACLitem->permissions() ); |
|
if ( dlg.exec() == QDialog::Accepted ) { |
|
ACLitem->setUserId( dlg.userId() ); |
|
ACLitem->setPermissions( dlg.permissions() ); |
|
ACLitem->setModified( true ); |
|
emit changed(true); |
|
} |
|
} |
|
|
|
void KMail::FolderDiaACLTab::slotEditACL() |
|
{ |
|
slotEditACL( mListView->currentItem() ); |
|
} |
|
|
|
void KMail::FolderDiaACLTab::slotAddACL() |
|
{ |
|
ACLEntryDialog dlg( i18n( "Add Permissions" ), this ); |
|
if ( dlg.exec() == QDialog::Accepted ) { |
|
ListViewItem* ACLitem = new ListViewItem( mListView ); |
|
ACLitem->setUserId( dlg.userId() ); |
|
ACLitem->setPermissions( dlg.permissions() ); |
|
ACLitem->setModified( true ); |
|
emit changed(true); |
|
} |
|
} |
|
|
|
void KMail::FolderDiaACLTab::slotSelectionChanged(QListViewItem* item) |
|
{ |
|
bool lvVisible = mStack->visibleWidget() == mACLWidget; |
|
mAddACL->setEnabled( lvVisible ); |
|
mEditACL->setEnabled( item && lvVisible ); |
|
mRemoveACL->setEnabled( item && lvVisible ); |
|
} |
|
|
|
void KMail::FolderDiaACLTab::ACLJobDone(KIO::Job* job) |
|
{ |
|
--mJobCounter; |
|
if ( job->error() ) { |
|
job->showErrorDialog( this ); |
|
if ( mAccepting ) { |
|
emit cancelAccept(); |
|
mAccepting = false; // don't emit readyForAccept anymore |
|
} |
|
} |
|
if ( mJobCounter == 0 && mAccepting ) |
|
emit readyForAccept(); |
|
} |
|
|
|
// Called by 'add' and 'edit' jobs fired from save() |
|
void KMail::FolderDiaACLTab::slotSetACLResult(KIO::Job* job) |
|
{ |
|
bool ok = false; |
|
for ( QListViewItem* item = mListView->firstChild(); item; item = item->nextSibling() ) { |
|
ListViewItem* ACLitem = static_cast<ListViewItem *>( item ); |
|
if ( ACLitem->job() == job ) { |
|
if ( !job->error() ) { |
|
// Success -> reset flags |
|
ACLitem->setModified( false ); |
|
} |
|
ACLitem->setJob( 0 ); |
|
ok = true; |
|
break; |
|
} |
|
} |
|
if ( !ok ) |
|
kdWarning(5006) << k_funcinfo << " no item found for job " << job << endl; |
|
ACLJobDone( job ); |
|
} |
|
|
|
void KMail::FolderDiaACLTab::slotDeleteACLResult(KIO::Job* job) |
|
{ |
|
if ( !job->error() ) { |
|
// Success -> remove from list |
|
ACLJobs::DeleteACLJob* delJob = static_cast<ACLJobs::DeleteACLJob *>( job ); |
|
Q_ASSERT( mRemovedACLs.contains( delJob->userId() ) ); |
|
mRemovedACLs.remove( delJob->userId() ); |
|
} |
|
ACLJobDone( job ); |
|
} |
|
|
|
void KMail::FolderDiaACLTab::slotRemoveACL() |
|
{ |
|
ListViewItem* ACLitem = static_cast<ListViewItem *>( mListView->currentItem() ); |
|
if ( !ACLitem ) |
|
return; |
|
mRemovedACLs.append( ACLitem->userId() ); |
|
delete ACLitem; |
|
emit changed(true); |
|
} |
|
|
|
bool KMail::FolderDiaACLTab::accept() |
|
{ |
|
if ( !mChanged ) |
|
return true; // no change, ok for accepting the dialog immediately |
|
// If there were changes, we need to apply them first (which is async) |
|
mAccepting = true; |
|
save(); |
|
return false; // i.e. don't close yet |
|
} |
|
|
|
void KMail::FolderDiaACLTab::save() |
|
{ |
|
if ( !mChanged ) |
|
return; |
|
mJobCounter = 0; |
|
ImapAccountBase* account = imapAccount(); |
|
for ( QListViewItem* item = mListView->firstChild(); item; item = item->nextSibling() ) { |
|
ListViewItem* ACLitem = static_cast<ListViewItem *>( item ); |
|
if ( ACLitem->isModified() ) { |
|
kdDebug(5006) << "Modified item: " << ACLitem->userId() << endl; |
|
|
|
KIO::Job* job = ACLJobs::setACL( account->slave(), imapURL(), ACLitem->userId(), ACLitem->permissions() ); |
|
ACLitem->setJob( job ); |
|
ImapAccountBase::jobData jd; |
|
jd.total = 1; jd.done = 0; jd.parent = NULL; |
|
account->insertJob(job, jd); |
|
|
|
connect(job, SIGNAL(result(KIO::Job *)), |
|
SLOT(slotSetACLResult(KIO::Job *))); |
|
++mJobCounter; |
|
} |
|
} |
|
for( QStringList::Iterator rit = mRemovedACLs.begin(); rit != mRemovedACLs.end(); ++rit ) { |
|
kdDebug(5006) << "Removed item: " << (*rit) << endl; |
|
KIO::Job* job = ACLJobs::deleteACL( account->slave(), imapURL(), (*rit) ); |
|
ImapAccountBase::jobData jd; |
|
jd.total = 1; jd.done = 0; jd.parent = NULL; |
|
account->insertJob(job, jd); |
|
|
|
connect(job, SIGNAL(result(KIO::Job *)), |
|
SLOT(slotDeleteACLResult(KIO::Job *))); |
|
++mJobCounter; |
|
} |
|
} |
|
|
|
void KMail::FolderDiaACLTab::slotChanged( bool b ) |
|
{ |
|
mChanged = b; |
|
} |
|
|
|
#include "folderdiaacltab.moc"
|
|
|