Support for listing/removing/adding/modifying ACLs in the folder properties dialog

(only for IMAP folders, but for both kind of them).

svn path=/trunk/kdepim/; revision=302136
wilder-work
David Faure 22 years ago
parent 4e3d9c33b8
commit b01a590ff5
  1. 2
      Makefile.am
  2. 202
      acljobs.cpp
  3. 144
      acljobs.h
  4. 484
      folderdiaacltab.cpp
  5. 133
      folderdiaacltab.h
  6. 33
      imapaccountbase.cpp
  7. 33
      imapaccountbase.h
  8. 91
      kmfolderdia.cpp
  9. 51
      kmfolderdia.h

@ -93,7 +93,7 @@ libkmailprivate_la_SOURCES = kmmessage.cpp kmmainwin.cpp configuredialog.cpp \
korganizeriface.stub messagecomposer.cpp \
globalsettings.kcfgc \
regexplineedit.cpp rulewidgethandlermanager.cpp \
headerlistquicksearch.cpp
headerlistquicksearch.cpp acljobs.cpp folderdiaacltab.cpp
kmail_SOURCES = main.cpp

@ -0,0 +1,202 @@
/**
* acljobs.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 "acljobs.h"
#include <kio/scheduler.h>
#include <kdebug.h>
using namespace KMail;
static unsigned int IMAPRightsToPermission( const QString& str ) {
unsigned int perm = 0;
bool foundSeenPerm = false;
uint len = str.length();
for (uint i = 0; i < len; ++i) {
QChar ch = str[i];
switch ( ch.latin1() ) {
case 'l': perm |= ACLJobs::List; break;
case 'r': perm |= ACLJobs::Read; break;
case 's': foundSeenPerm = true; break;
case 'w': perm |= ACLJobs::WriteFlags; break;
case 'i': perm |= ACLJobs::Insert; break;
case 'c': perm |= ACLJobs::Create; break;
case 'd': perm |= ACLJobs::Delete; break;
case 'a': perm |= ACLJobs::Administer; break;
default: break;
}
}
if ( ( perm & ACLJobs::Read ) && str.find( 's' ) == -1 ) {
// Reading without 'seen' is, well, annoying. Unusable, even.
// So we treat 'rs' as a single one.
// But if the permissions were set out of kmail, better check that both are set
kdWarning(5006) << "IMAPRightsToPermission: found read (r) but not seen (s). Things will not work well." << endl;
if ( perm & ACLJobs::Administer )
kdWarning(5006) << "You can change this yourself in the ACL dialog" << endl;
else
kdWarning(5006) << "Ask your admin for 's' permissions." << endl;
// Is the above correct enough to be turned into a KMessageBox?
}
return perm;
}
static QCString permissionsToIMAPRights( unsigned int permissions ) {
QCString str = "";
if ( permissions & ACLJobs::List )
str += 'l';
if ( permissions & ACLJobs::Read )
str += "rs";
if ( permissions & ACLJobs::WriteFlags )
str += 'w';
if ( permissions & ACLJobs::Insert )
str += 'i';
if ( permissions & ACLJobs::Create )
str += 'c';
if ( permissions & ACLJobs::Delete )
str += 'd';
if ( permissions & ACLJobs::Administer )
str += 'a';
return str;
}
#ifndef NDEBUG
QString ACLJobs::permissionsToString( unsigned int permissions )
{
QString str;
if ( permissions & ACLJobs::List )
str += "List ";
if ( permissions & ACLJobs::Read )
str += "Read ";
if ( permissions & ACLJobs::WriteFlags )
str += "Write ";
if ( permissions & ACLJobs::Insert )
str += "Insert ";
if ( permissions & ACLJobs::Create )
str += "Create ";
if ( permissions & ACLJobs::Delete )
str += "Delete ";
if ( permissions & ACLJobs::Administer )
str += "Administer ";
if ( !str.isEmpty() )
str.truncate( str.length() - 1 );
return str;
}
#endif
KIO::SimpleJob* ACLJobs::setACL( KIO::Slave* slave, const KURL& url, const QString& user, unsigned int permissions )
{
QString perm = QString::fromLatin1( permissionsToIMAPRights( permissions ) );
QByteArray packedArgs;
QDataStream stream( packedArgs, IO_WriteOnly );
stream << (int)'A' << (int)'S' << url << user << perm;
KIO::SimpleJob* job = KIO::special( url, packedArgs, false );
KIO::Scheduler::assignJobToSlave( slave, job );
return job;
}
ACLJobs::DeleteACLJob* ACLJobs::deleteACL( KIO::Slave* slave, const KURL& url, const QString& user )
{
QByteArray packedArgs;
QDataStream stream( packedArgs, IO_WriteOnly );
stream << (int)'A' << (int)'D' << url << user;
ACLJobs::DeleteACLJob* job = new ACLJobs::DeleteACLJob( url, user, packedArgs, false );
KIO::Scheduler::assignJobToSlave( slave, job );
return job;
}
ACLJobs::GetACLJob* ACLJobs::getACL( KIO::Slave* slave, const KURL& url )
{
QByteArray packedArgs;
QDataStream stream( packedArgs, IO_WriteOnly );
stream << (int)'A' << (int)'G' << url;
ACLJobs::GetACLJob* job = new ACLJobs::GetACLJob( url, packedArgs, false );
KIO::Scheduler::assignJobToSlave( slave, job );
return job;
}
ACLJobs::GetUserRightsJob* ACLJobs::getUserRights( KIO::Slave* slave, const KURL& url )
{
QByteArray packedArgs;
QDataStream stream( packedArgs, IO_WriteOnly );
stream << (int)'A' << (int)'M' << url;
ACLJobs::GetUserRightsJob* job = new ACLJobs::GetUserRightsJob( url, packedArgs, false );
KIO::Scheduler::assignJobToSlave( slave, job );
return job;
}
ACLJobs::GetACLJob::GetACLJob( const KURL& url, const QByteArray &packedArgs,
bool showProgressInfo )
: KIO::SimpleJob( url, KIO::CMD_SPECIAL, packedArgs, showProgressInfo )
{
connect( this, SIGNAL(infoMessage(KIO::Job*,const QString&)),
SLOT(slotInfoMessage(KIO::Job*,const QString&)) );
}
void ACLJobs::GetACLJob::slotInfoMessage( KIO::Job*, const QString& str )
{
// Parse the result
QStringList lst = QStringList::split( " ", str );
while ( lst.count() >= 2 ) // we take items 2 by 2
{
QString user = lst.front(); lst.pop_front();
QString imapRights = lst.front(); lst.pop_front();
unsigned int perm = IMAPRightsToPermission( imapRights );
m_entries.append( ACLListEntry( user, imapRights, perm ) );
}
}
ACLJobs::GetUserRightsJob::GetUserRightsJob( const KURL& url, const QByteArray &packedArgs,
bool showProgressInfo )
: KIO::SimpleJob( url, KIO::CMD_SPECIAL, packedArgs, showProgressInfo )
{
connect( this, SIGNAL(infoMessage(KIO::Job*,const QString&)),
SLOT(slotInfoMessage(KIO::Job*,const QString&)) );
}
void ACLJobs::GetUserRightsJob::slotInfoMessage( KIO::Job*, const QString& str )
{
// Parse the result
m_permissions = IMAPRightsToPermission( str );
}
ACLJobs::DeleteACLJob::DeleteACLJob( const KURL& url, const QString& userId,
const QByteArray &packedArgs,
bool showProgressInfo )
: KIO::SimpleJob( url, KIO::CMD_SPECIAL, packedArgs, showProgressInfo ),
mUserId( userId )
{
}
#include "acljobs.moc"

@ -0,0 +1,144 @@
/**
* acljobs.h
*
* 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.
*/
#ifndef KMACLJOBS_H
#define KMACLJOBS_H
#include <kio/job.h>
#include <qvaluevector.h>
namespace KMail {
/**
* This namespace contains functions that return jobs for ACL operations.
*
* The current implementation is tied to IMAP.
* If someone wants to extend this to other protocols, turn the class into a namespace
* and use virtual methods.
*/
namespace ACLJobs {
/// Bitfield modelling the possible permissions.
/// This is modelled after the imap4 permissions except that Read is "rs"
/// and "p" (post) isn't there. The semantics of the bits is protocol-dependent.
enum ACLPermissions {
List = 1,
Read = 2,
WriteFlags = 4,
Insert = 8,
Create = 16,
Delete = 32,
Administer = 64,
// alias for "all read/write permissions except admin"
AllWrite = List | Read | WriteFlags | Insert | Create | Delete,
// alias for "all permissions"
All = List | Read | WriteFlags | Insert | Create | Delete | Administer
};
/// Set the permissions for a given user on a given url
KIO::SimpleJob* setACL( KIO::Slave* slave, const KURL& url, const QString& user, unsigned int permissions );
class DeleteACLJob;
/// Delete the permissions for a given user on a given url
DeleteACLJob* deleteACL( KIO::Slave* slave, const KURL& url, const QString& user );
class GetACLJob;
/// List all ACLs for a given url
GetACLJob* getACL( KIO::Slave* slave, const KURL& url );
class GetUserRightsJob;
/// Get the users' rights for a given url
GetUserRightsJob* getUserRights( KIO::Slave* slave, const KURL& url );
/// One entry in the ACL list: user and permissions
struct ACLListEntry {
ACLListEntry() {} // for QValueVector
ACLListEntry( const QString& u, const QString& irl, unsigned int p )
: userid( u ), internalRightsList( irl ), permissions( p ) {}
QString userid;
QString internalRightsList; ///< protocol-dependent string (e.g. IMAP rights list)
unsigned int permissions; ///< based on the ACLPermissions enum
};
/// List all ACLs for a given url
class GetACLJob : public KIO::SimpleJob
{
Q_OBJECT
public:
GetACLJob( const KURL& url, const QByteArray &packedArgs,
bool showProgressInfo );
const QValueVector<ACLListEntry>& entries() const { return m_entries; }
protected slots:
void slotInfoMessage( KIO::Job*, const QString& );
private:
QValueVector<ACLListEntry> m_entries;
};
/// Get the users' rights for a given url
class GetUserRightsJob : public KIO::SimpleJob
{
Q_OBJECT
public:
GetUserRightsJob( const KURL& url, const QByteArray &packedArgs,
bool showProgressInfo );
unsigned int permissions() const { return m_permissions; }
protected slots:
void slotInfoMessage( KIO::Job*, const QString& );
private:
unsigned int m_permissions;
};
/// Delete the permissions for a given user on a given url
/// This class only exists to store the userid in the job
class DeleteACLJob : public KIO::SimpleJob
{
Q_OBJECT
public:
DeleteACLJob( const KURL& url, const QString& userId,
const QByteArray &packedArgs,
bool showProgressInfo );
QString userId() const { return mUserId; }
private:
QString mUserId;
};
#ifndef NDEBUG
QString permissionsToString( unsigned int permissions );
#endif
}
} // namespace
#endif /* KMACLJOBS_H */

@ -0,0 +1,484 @@
// -*- 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"

@ -0,0 +1,133 @@
// -*- mode: C++; c-file-style: "gnu" -*-
/**
* folderdiaacltab.h
*
* 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.
*/
#ifndef FOLDERDIAACL_H
#define FOLDERDIAACL_H
#include "kmfolderdia.h"
class KPushButton;
class QWidgetStack;
class QHBox;
class QVButtonGroup;
class KListView;
namespace KIO { class Job; }
namespace KMail {
class ImapAccountBase;
/**
* "New Access Control Entry" dialog.
* Internal class, only used by FolderDiaACLTab
*/
class ACLEntryDialog :public KDialogBase {
Q_OBJECT
public:
ACLEntryDialog( const QString& caption, QWidget* parent, const char* name = 0 );
void setValues( const QString& userId, unsigned int permissions );
QString userId() const;
unsigned int permissions() const;
private slots:
void slotChanged();
private:
QVButtonGroup* mButtonGroup;
KLineEdit* mUserIdLineEdit;
};
/**
* "Access Control" tab in the folder dialog
* Internal class, only used by KMFolderDialog
*/
class FolderDiaACLTab : public FolderDiaTab
{
Q_OBJECT
public:
FolderDiaACLTab( KMFolderDialog* dlg, QWidget* parent, const char* name = 0 );
virtual void load();
virtual void save();
virtual bool accept();
private slots:
// Network (KIO) slots
void slotConnectionResult( int );
void slotGetACLResult(KIO::Job *);
void slotSetACLResult(KIO::Job *);
void slotDeleteACLResult(KIO::Job *);
// User (KListView) slots
void slotEditACL(QListViewItem*);
void slotSelectionChanged(QListViewItem*);
// User (pushbuttons) slots
void slotAddACL();
void slotEditACL();
void slotRemoveACL();
void slotChanged( bool b );
private:
void ACLJobDone(KIO::Job* job);
KMail::ImapAccountBase* imapAccount() const;
KURL imapURL() const;
private:
// The widget containing the ACL widgets (listview and buttons)
QHBox* mACLWidget;
//class ListView;
class ListViewItem;
KListView* mListView;
KPushButton* mAddACL;
KPushButton* mEditACL;
KPushButton* mRemoveACL;
QStringList mRemovedACLs;
QLabel* mLabel;
QWidgetStack* mStack;
KMFolderDialog* mDlg;
int mJobCounter;
bool mChanged;
bool mAccepting; // i.e. close when done
};
} // end of namespace KMail
#endif /* FOLDERDIAACL_H */

@ -56,6 +56,7 @@ using KIO::PasswordDialog;
//using KIO::Scheduler; // use FQN below
#include <qregexp.h>
#include "acljobs.h"
namespace KMail {
@ -458,6 +459,38 @@ namespace KMail {
if (mSlave) removeJob(job);
}
//-----------------------------------------------------------------------------
void ImapAccountBase::getUserRights( const QString& imapPath )
{
KURL url = getUrl();
url.setPath(imapPath);
ACLJobs::GetUserRightsJob* job = ACLJobs::getUserRights( mSlave, url );
jobData jd;
jd.total = 1; jd.done = 0; jd.parent = NULL;
insertJob(job, jd);
connect(job, SIGNAL(result(KIO::Job *)),
SLOT(slotGetUserRightsResult(KIO::Job *)));
}
void ImapAccountBase::slotGetUserRightsResult( KIO::Job* _job )
{
ACLJobs::GetUserRightsJob* job = static_cast<ACLJobs::GetUserRightsJob *>( _job );
// result of a get-users-right-job
JobIterator it = findJob( job );
if ( it == jobsEnd() ) return;
if ( job->error() )
kdWarning(5006) << "slotGetUserRightsResult: " << job->errorString() << endl;
else {
kdDebug(5006) << "User Rights: " << ACLJobs::permissionsToString( job->permissions() ) << endl;
// TODO store the permissions somewhere (in the folder? storage?)
}
if (mSlave) removeJob(job);
}
//-----------------------------------------------------------------------------
void ImapAccountBase::slotSchedulerSlaveError(KIO::Slave *aSlave, int errorCode,
const QString &errorMsg)

@ -158,17 +158,25 @@ class AttachmentStrategy;
void listDirectory(QString path, bool onlySubscribed,
bool secondStep = FALSE, KMFolder* parent = NULL, bool reset = false);
/**
/**
* Starts the folderlisting for the root folder
*/
*/
virtual void listDirectory() = 0;
/**
* Subscribe (@p subscribe = TRUE) / Unsubscribe the folder
* identified by @p imapPath
* identified by @p imapPath.
* Emits subscriptionChanged signal on success.
*/
void changeSubscription(bool subscribe, QString imapPath);
/**
* Retrieve the users' right on the folder
* identified by @p imapPath.
* (async, will emit some signal)
*/
void getUserRights( const QString& imapPath );
/**
* The KIO-Slave died
*/
@ -179,15 +187,15 @@ class AttachmentStrategy;
*/
void killAllJobs( bool disconnectSlave=false ) = 0;
/**
* Init a new-mail-check for a single folder
*/
void processNewMailSingleFolder(KMFolder* folder);
/**
* Init a new-mail-check for a single folder
*/
void processNewMailSingleFolder(KMFolder* folder);
/**
* Check whether we're checking for new mail
* and the folder is included
*/
*/
bool checkingMail( KMFolder *folder );
bool checkingMail() { return NetworkAccount::checkingMail(); }
@ -200,13 +208,13 @@ class AttachmentStrategy;
/**
* Handles the result from a BODYSTRUCTURE fetch
*/
*/
void handleBodyStructure( QDataStream & stream, KMMessage * msg,
const AttachmentStrategy *as );
/**
* Reimplemented. Additionally set the folder label
*/
*/
virtual void setFolder(KMFolder*, bool addAccount = false);
public slots:
@ -256,6 +264,9 @@ class AttachmentStrategy;
*/
void slotSetStatusResult(KIO::Job * job);
/// Result of getUserRights() job
void slotGetUserRightsResult( KIO::Job* _job );
protected:
virtual QString protocol() const;
virtual unsigned short int defaultPort() const;
@ -264,7 +275,7 @@ class AttachmentStrategy;
/**
* Build KMMessageParts and DwBodyParts from the bodystructure-stream
*/
*/
void constructParts( QDataStream & stream, int count, KMMessagePart* parentKMPart,
DwBodyPart * parent, const DwMessage * dwmsg );

@ -32,6 +32,7 @@
#include <config.h>
#include "kmfolderdia.h"
#include "kmacctfolder.h"
#include "kmfoldermgr.h"
#include "identitycombo.h"
@ -41,6 +42,7 @@
#include "kmcommands.h"
#include "mailinglist-magic.h"
#include "kmfoldertree.h"
#include "folderdiaacltab.h"
#include <keditlistbox.h>
#include <klineedit.h>
@ -50,6 +52,7 @@
#include <kicondialog.h>
#include <kconfig.h>
#include <kdebug.h>
#include <klistview.h>
#include <qcheckbox.h>
#include <qlayout.h>
@ -60,7 +63,6 @@
#include <assert.h>
#include "kmfolderdia.h" //has to be later because of KMFolder* fdcls
#include "kmfolderdia.moc"
using namespace KMail;
@ -77,44 +79,101 @@ KMFolderDialog::KMFolderDialog(KMFolder *aFolder, KMFolderDir *aFolderDir,
{
kdDebug(5006)<<"KMFolderDialog::KMFolderDialog()" << endl;
ConfigModuleTab* tab;
FolderDiaTab* tab;
QVBox* box;
box = addVBoxPage( i18n("General") );
tab = new FolderDiaGeneralTab( this, aParent, aName, box );
//connect( tab, SIGNAL(changed( bool )),
// this, SIGNAL(changed( bool )) );
mTabs.append( tab );
addTab( tab );
box = addVBoxPage( i18n("Mailing List") );
tab = new FolderDiaMailingListTab( this, box );
addTab( tab );
if ( mFolder->folderType() == KMFolderTypeImap || mFolder->folderType() == KMFolderTypeCachedImap )
{
//KMFolderImap* imapFolder = static_cast<KMFolderImap*>(folder->storage());
// TODO check if the capabilities of the IMAP server include "acl"
box = addVBoxPage( i18n("Access Control") );
tab = new FolderDiaACLTab( this, box );
addTab( tab );
}
for ( unsigned int i = 0 ; i < mTabs.count() ; ++i )
mTabs[i]->load();
}
void KMFolderDialog::addTab( FolderDiaTab* tab )
{
connect( tab, SIGNAL( readyForAccept() ),
this, SLOT( slotReadyForAccept() ) );
connect( tab, SIGNAL( cancelAccept() ),
this, SLOT( slotCancelAccept() ) );
//connect( tab, SIGNAL(changed( bool )),
// this, SIGNAL(changed( bool )) );
// this, SLOT(slotChanged( bool )) );
mTabs.append( tab );
}
// Not used yet (no button), but ready to be used :)
void KMFolderDialog::slotApply()
{
for ( unsigned int i = 0 ; i < mTabs.count() ; ++i )
mTabs[i]->load();
mTabs[i]->save();
KDialogBase::slotApply();
}
// Called when pressing Ok
// We want to apply the changes first (which is async), before closing the dialog,
// in case of errors during the upload.
void KMFolderDialog::slotOk()
{
mDelayedSavingTabs = 0; // number of tabs which need delayed saving
for ( unsigned int i = 0 ; i < mTabs.count() ; ++i )
mTabs[i]->save();
KDialogBase::slotOk();
if ( !mTabs[i]->accept() )
++mDelayedSavingTabs;
if ( mDelayedSavingTabs )
enableButtonOK( false );
else
KDialogBase::slotOk();
}
void KMFolderDialog::slotReadyForAccept()
{
--mDelayedSavingTabs;
if ( mDelayedSavingTabs == 0 )
KDialogBase::slotOk();
}
void KMFolderDialog::slotCancelAccept()
{
mDelayedSavingTabs = -1;
enableButtonOK( true );
// Other tabs might call slotReadyForAccept. -1 ensures that it won't close the dialog,
// but the OK button being enabled means that people might succeed in running
// the same job from save more than once.
// Solution: mAcceptCanceled = true instead of -1.
// Bah for now we only have one tab which can delay saving -> later.
}
void KMFolderDialog::slotChanged( bool )
{
// TODO, support for 'changed', and Apply button.
//if ( b )
// m_changed = true;
// sample code for here: KCMultiDialog calls bool changed() on every KCModuleProxy...
}
void KMFolderDialog::setFolder( KMFolder* folder )
{
Q_ASSERT( mFolder.isNull() );
mFolder = folder;
}
//----------------------------------------------------------------------------
KMail::FolderDiaGeneralTab::FolderDiaGeneralTab( KMFolderDialog* dlg, KMFolderTree* aParent,
const QString& aName,
QWidget* parent, const char* name )
: ConfigModuleTab( parent, name ), mDlg( dlg )
: FolderDiaTab( parent, name ), mDlg( dlg )
{
QVBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
@ -753,7 +812,7 @@ void FolderDiaGeneralTab::slotChangeIcon( QString icon ) // can't use a const-re
//----------------------------------------------------------------------------
FolderDiaMailingListTab::FolderDiaMailingListTab( KMFolderDialog* dlg,
QWidget* parent, const char* name )
: ConfigModuleTab( parent, name ), mDlg( dlg )
: FolderDiaTab( parent, name ), mDlg( dlg )
{
if ( mDlg->folder() && mDlg->folder()->noContent() ) {
return;
@ -1007,9 +1066,3 @@ void FolderDiaMailingListTab::slotInvokeHandler()
}
if ( command ) command->start();
}
void KMFolderDialog::setFolder( KMFolder* folder )
{
Q_ASSERT( mFolder.isNull() );
mFolder = folder;
}

@ -58,11 +58,44 @@ template <typename T> class QGuardedPtr;
namespace KMail {
/**
* This is the base class for tabs in the folder dialog.
* It uses the API from ConfigModuleTab (basically: it's a widget that can load and save)
* but it also adds support for delayed-saving:
* when save() needs to use async jobs (e.g. KIO) for saving,
* we need to delay the closing until after the jobs are finished,
* and to cancel the saving on error.
*
* Feel free to rename and move this base class somewhere else if it
* can be useful for other dialogs.
*/
class FolderDiaTab : public ConfigModuleTab
{
Q_OBJECT
public:
FolderDiaTab( QWidget *parent=0, const char* name=0 )
: ConfigModuleTab( parent, name ) {}
/// Called when clicking OK.
/// If a module returns false, the closing is cancelled for now,
/// and the module can close the dialog later on (i.e. after an async
/// operation like a KIO job).
virtual bool accept() { save(); return true; }
signals:
/// Emit this to tell the dialog that you're done with the async jobs,
/// and that the dialog can be closed.
void readyForAccept();
/// Emit this, i.e. after a job had an error, to tell the dialog to cancel
/// the closing.
void cancelAccept();
};
/**
* "General" tab in the folder dialog
* Internal class, only used by KMFolderDialog
*/
class FolderDiaGeneralTab : public ConfigModuleTab
class FolderDiaGeneralTab : public FolderDiaTab
{
Q_OBJECT
@ -116,7 +149,7 @@ private:
* "Mailing List" tab in the folder dialog
* Internal class, only used by KMFolderDialog
*/
class FolderDiaMailingListTab : public ConfigModuleTab
class FolderDiaMailingListTab : public FolderDiaTab
{
Q_OBJECT
@ -177,14 +210,22 @@ public:
protected slots:
void slotChanged( bool );
virtual void slotOk( void );
virtual void slotOk();
virtual void slotApply();
void slotReadyForAccept();
void slotCancelAccept();
protected:
private:
void addTab( KMail::FolderDiaTab* tab );
private:
QGuardedPtr<KMFolder> mFolder;
QGuardedPtr<KMFolderDir> mFolderDir;
FolderList mFolders;
QValueVector<ConfigModuleTab*> mTabs;
QValueVector<KMail::FolderDiaTab*> mTabs;
int mDelayedSavingTabs; // this should go into a base class one day
};
#endif /*__KMFOLDERDIA*/

Loading…
Cancel
Save