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.
2168 lines
68 KiB
2168 lines
68 KiB
// kmfoldertree.cpp |
|
#ifdef HAVE_CONFIG_H |
|
#include <config.h> |
|
#endif |
|
|
|
#include "kmfoldertree.h" |
|
|
|
#include "kmfoldermgr.h" |
|
#include "kmfolder.h" |
|
#include "kmfolderimap.h" |
|
#include "kmfoldercachedimap.h" |
|
#include "kmfolderdia.h" |
|
#include "kmheaders.h" |
|
#include "kmmainwidget.h" |
|
#include "kmailicalifaceimpl.h" |
|
#include "accountmanager.h" |
|
using KMail::AccountManager; |
|
#include "globalsettings.h" |
|
#include "kmcommands.h" |
|
#include "foldershortcutdialog.h" |
|
#include "expirypropertiesdialog.h" |
|
#include "newfolderdialog.h" |
|
#include "acljobs.h" |
|
#include "messagecopyhelper.h" |
|
using KMail::MessageCopyHelper; |
|
#include "favoritefolderview.h" |
|
|
|
#include <maillistdrag.h> |
|
using namespace KPIM; |
|
|
|
#include <kapplication.h> |
|
#include <kglobalsettings.h> |
|
#include <kiconloader.h> |
|
#include <kmessagebox.h> |
|
#include <kconfig.h> |
|
#include <kpopupmenu.h> |
|
#include <kdebug.h> |
|
|
|
#include <qpainter.h> |
|
#include <qcursor.h> |
|
#include <qregexp.h> |
|
#include <qpopupmenu.h> |
|
|
|
#include <unistd.h> |
|
#include <assert.h> |
|
|
|
#include <X11/Xlib.h> |
|
#include <fixx11h.h> |
|
|
|
//============================================================================= |
|
|
|
KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const QString & name, |
|
KFolderTreeItem::Protocol protocol ) |
|
: QObject( parent, name.latin1() ), |
|
KFolderTreeItem( parent, name, protocol, Root ), |
|
mFolder( 0 ), mNeedsRepaint( true ) |
|
{ |
|
init(); |
|
setPixmap( 0, normalIcon( iconSize() ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const QString & name, |
|
KMFolder* folder ) |
|
: QObject( parent, name.latin1() ), |
|
KFolderTreeItem( parent, name ), |
|
mFolder( folder ), mNeedsRepaint( true ) |
|
{ |
|
init(); |
|
setPixmap( 0, normalIcon( iconSize() ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
KMFolderTreeItem::KMFolderTreeItem( KFolderTreeItem *parent, const QString & name, |
|
KMFolder* folder ) |
|
: QObject( 0, name.latin1() ), |
|
KFolderTreeItem( parent, name ), |
|
mFolder( folder ), mNeedsRepaint( true ) |
|
{ |
|
init(); |
|
setPixmap( 0, normalIcon( iconSize() ) ); |
|
} |
|
|
|
KMFolderTreeItem::~KMFolderTreeItem() |
|
{ |
|
} |
|
|
|
static KFolderTreeItem::Protocol protocolFor( KMFolderType t ) { |
|
switch ( t ) { |
|
case KMFolderTypeImap: |
|
return KFolderTreeItem::Imap; |
|
case KMFolderTypeCachedImap: |
|
return KFolderTreeItem::CachedImap; |
|
case KMFolderTypeMbox: |
|
case KMFolderTypeMaildir: |
|
return KFolderTreeItem::Local; |
|
case KMFolderTypeSearch: |
|
return KFolderTreeItem::Search; |
|
default: |
|
return KFolderTreeItem::NONE; |
|
} |
|
} |
|
|
|
QPixmap KMFolderTreeItem::normalIcon(int size) const |
|
{ |
|
QString icon; |
|
if ( (!mFolder && type() == Root) || useTopLevelIcon() ) { |
|
switch ( protocol() ) { |
|
case KFolderTreeItem::Imap: |
|
case KFolderTreeItem::CachedImap: |
|
case KFolderTreeItem::News: |
|
icon = "server"; break; |
|
case KFolderTreeItem::Search: |
|
icon = "viewmag";break; |
|
default: |
|
icon = "folder";break; |
|
} |
|
} else { |
|
// special folders |
|
switch ( type() ) { |
|
case Inbox: icon = "folder_inbox"; break; |
|
case Outbox: icon = "folder_outbox"; break; |
|
case SentMail: icon = "folder_sent_mail"; break; |
|
case Trash: icon = "trashcan_empty"; break; |
|
case Drafts: icon = "edit"; break; |
|
case Templates: icon = "filenew"; break; |
|
default: icon = kmkernel->iCalIface().folderPixmap( type() ); break; |
|
} |
|
// non-root search folders |
|
if ( protocol() == KMFolderTreeItem::Search ) { |
|
icon = "mail_find"; |
|
} |
|
if ( mFolder && mFolder->noContent() ) { |
|
icon = "folder_grey"; |
|
} |
|
} |
|
|
|
if ( icon.isEmpty() ) |
|
icon = "folder"; |
|
|
|
if (mFolder && mFolder->useCustomIcons() ) { |
|
icon = mFolder->normalIconPath(); |
|
} |
|
KIconLoader * il = KGlobal::instance()->iconLoader(); |
|
QPixmap pm = il->loadIcon( icon, KIcon::Small, size, |
|
KIcon::DefaultState, 0, true ); |
|
if ( mFolder && pm.isNull() ) { |
|
pm = il->loadIcon( mFolder->normalIconPath(), KIcon::Small, size, |
|
KIcon::DefaultState, 0, true ); |
|
} |
|
|
|
return pm; |
|
} |
|
|
|
QPixmap KMFolderTreeItem::unreadIcon(int size) const |
|
{ |
|
QPixmap pm; |
|
|
|
if ( !mFolder || useTopLevelIcon() || mFolder->isSystemFolder() || |
|
kmkernel->folderIsTrash( mFolder ) || |
|
kmkernel->folderIsTemplates( mFolder ) || |
|
kmkernel->folderIsDraftOrOutbox( mFolder ) ) |
|
pm = normalIcon( size ); |
|
|
|
KIconLoader * il = KGlobal::instance()->iconLoader(); |
|
if ( mFolder && mFolder->useCustomIcons() ) { |
|
pm = il->loadIcon( mFolder->unreadIconPath(), KIcon::Small, size, |
|
KIcon::DefaultState, 0, true ); |
|
if ( pm.isNull() ) |
|
pm = il->loadIcon( mFolder->normalIconPath(), KIcon::Small, size, |
|
KIcon::DefaultState, 0, true ); |
|
} |
|
if ( pm.isNull() ) { |
|
if ( mFolder && mFolder->noContent() ) { |
|
pm = il->loadIcon( "folder_grey_open", KIcon::Small, size, |
|
KIcon::DefaultState, 0, true ); |
|
} else { |
|
pm = il->loadIcon( kmkernel->iCalIface().folderPixmap( type() ), |
|
KIcon::Small, size, KIcon::DefaultState, 0, true ); |
|
if ( pm.isNull() ) |
|
pm = il->loadIcon( "folder_open", KIcon::Small, size, |
|
KIcon::DefaultState, 0, true ); |
|
} |
|
} |
|
|
|
return pm; |
|
} |
|
|
|
void KMFolderTreeItem::init() |
|
{ |
|
if ( !mFolder ) |
|
return; |
|
|
|
setProtocol( protocolFor( mFolder->folderType() ) ); |
|
|
|
if ( useTopLevelIcon() ) |
|
setType(Root); |
|
else { |
|
if ( mFolder == kmkernel->inboxFolder() ) |
|
setType( Inbox ); |
|
else if ( kmkernel->folderIsDraftOrOutbox( mFolder ) ) { |
|
if ( mFolder == kmkernel->outboxFolder() ) |
|
setType( Outbox ); |
|
else |
|
setType( Drafts ); |
|
} |
|
else if ( kmkernel->folderIsSentMailFolder( mFolder ) ) |
|
setType( SentMail ); |
|
else if ( kmkernel->folderIsTrash( mFolder ) ) |
|
setType( Trash ); |
|
else if ( kmkernel->folderIsTemplates( mFolder ) ) |
|
setType( Templates ); |
|
else if( kmkernel->iCalIface().isResourceFolder(mFolder) ) |
|
setType( kmkernel->iCalIface().folderType(mFolder) ); |
|
// System folders on dimap or imap which are not resource folders are |
|
// inboxes. Urgs. |
|
if ( mFolder->isSystemFolder() && |
|
!kmkernel->iCalIface().isResourceFolder( mFolder) && |
|
( mFolder->folderType() == KMFolderTypeImap |
|
|| mFolder->folderType() == KMFolderTypeCachedImap ) ) |
|
setType( Inbox ); |
|
} |
|
if ( !mFolder->isSystemFolder() ) |
|
setRenameEnabled( 0, false ); |
|
|
|
KMFolderTree* tree = dynamic_cast<KMFolderTree*>( listView() ); |
|
if ( tree ) |
|
tree->insertIntoFolderToItemMap( mFolder, this ); |
|
} |
|
|
|
void KMFolderTreeItem::adjustUnreadCount( int newUnreadCount ) { |
|
// adjust the icons if the folder is now newly unread or |
|
// now newly not-unread |
|
if ( newUnreadCount != 0 && unreadCount() == 0 ) |
|
setPixmap( 0, unreadIcon( iconSize() ) ); |
|
if ( unreadCount() != 0 && newUnreadCount == 0 ) |
|
setPixmap( 0, normalIcon( iconSize() ) ); |
|
|
|
setUnreadCount( newUnreadCount ); |
|
} |
|
|
|
void KMFolderTreeItem::slotIconsChanged() |
|
{ |
|
kdDebug(5006) << k_funcinfo << endl; |
|
// this is prone to change, so better check |
|
if( kmkernel->iCalIface().isResourceFolder( mFolder ) ) |
|
setType( kmkernel->iCalIface().folderType(mFolder) ); |
|
|
|
if ( unreadCount() > 0 ) |
|
setPixmap( 0, unreadIcon( iconSize() ) ); |
|
else |
|
setPixmap( 0, normalIcon( iconSize() ) ); |
|
emit iconChanged( this ); |
|
repaint(); |
|
} |
|
|
|
void KMFolderTreeItem::slotNameChanged() |
|
{ |
|
setText( 0, mFolder->label() ); |
|
emit nameChanged( this ); |
|
repaint(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMFolderTreeItem::acceptDrag(QDropEvent* e) const |
|
{ |
|
if ( protocol() == KFolderTreeItem::Search ) |
|
return false; // nothing can be dragged into search folders |
|
|
|
if ( e->provides( KPIM::MailListDrag::format() ) ) { |
|
if ( !mFolder || mFolder->moveInProgress() || mFolder->isReadOnly() || |
|
(mFolder->noContent() && childCount() == 0) || |
|
(mFolder->noContent() && isOpen()) ) { |
|
return false; |
|
} |
|
else { |
|
return true; |
|
} |
|
} else if ( e->provides("application/x-qlistviewitem") ) { |
|
// wtf: protocol() is NONE instead of Local for the local root folder |
|
if ( !mFolder && protocol() == KFolderTreeItem::NONE && type() == KFolderTreeItem::Root ) |
|
return true; // local top-level folder |
|
if ( !mFolder || mFolder->isReadOnly() || mFolder->noContent() ) |
|
return false; |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTreeItem::slotShowExpiryProperties() |
|
{ |
|
if ( !mFolder ) |
|
return; |
|
|
|
KMFolderTree* tree = static_cast<KMFolderTree*>( listView() ); |
|
KMail::ExpiryPropertiesDialog *dlg = |
|
new KMail::ExpiryPropertiesDialog( tree, mFolder ); |
|
dlg->show(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTreeItem::properties() |
|
{ |
|
if ( !mFolder ) |
|
return; |
|
|
|
KMail::FolderTreeBase* tree = static_cast<KMail::FolderTreeBase*>( listView() ); |
|
tree->mainWidget()->modifyFolder( this ); |
|
//Nothing here the above may actually delete this KMFolderTreeItem |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTreeItem::assignShortcut() |
|
{ |
|
if ( !mFolder ) |
|
return; |
|
|
|
KMail::FolderShortcutDialog *shorty = |
|
new KMail::FolderShortcutDialog( mFolder, |
|
kmkernel->getKMMainWidget(), |
|
listView() ); |
|
shorty->exec(); |
|
return; |
|
} |
|
|
|
|
|
//============================================================================= |
|
|
|
|
|
KMFolderTree::KMFolderTree( KMMainWidget *mainWidget, QWidget *parent, |
|
const char *name ) |
|
: KMail::FolderTreeBase( mainWidget, parent, name ) |
|
, mUpdateTimer( 0, "mUpdateTimer" ) |
|
, autoopen_timer( 0, "autoopen_timer" ) |
|
{ |
|
oldSelected = 0; |
|
oldCurrent = 0; |
|
mLastItem = 0; |
|
mMainWidget = mainWidget; |
|
mReloading = false; |
|
mCutFolder = false; |
|
|
|
mUpdateCountTimer= new QTimer( this, "mUpdateCountTimer" ); |
|
|
|
setDragEnabled( true ); |
|
addAcceptableDropMimetype( "application/x-qlistviewitem", false ); |
|
|
|
setSelectionModeExt( Extended ); |
|
|
|
int namecol = addColumn( i18n("Folder"), 250 ); |
|
header()->setStretchEnabled( true, namecol ); |
|
|
|
// connect |
|
connectSignals(); |
|
|
|
// popup to switch columns |
|
header()->setClickEnabled(true); |
|
header()->installEventFilter(this); |
|
mPopup = new KPopupMenu(this); |
|
mPopup->insertTitle(i18n("View Columns")); |
|
mPopup->setCheckable(true); |
|
mUnreadPop = mPopup->insertItem(i18n("Unread Column"), this, SLOT(slotToggleUnreadColumn())); |
|
mTotalPop = mPopup->insertItem(i18n("Total Column"), this, SLOT(slotToggleTotalColumn())); |
|
mSizePop = mPopup->insertItem(i18n("Size Column"), this, SLOT(slotToggleSizeColumn())); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// connects all needed signals to their slots |
|
void KMFolderTree::connectSignals() |
|
{ |
|
connect( mUpdateCountTimer, SIGNAL(timeout()), |
|
this, SLOT(slotUpdateCountTimeout()) ); |
|
|
|
connect(&mUpdateTimer, SIGNAL(timeout()), |
|
this, SLOT(delayedUpdate())); |
|
|
|
connect(kmkernel->folderMgr(), SIGNAL(changed()), |
|
this, SLOT(doFolderListChanged())); |
|
|
|
connect(kmkernel->folderMgr(), SIGNAL(folderRemoved(KMFolder*)), |
|
this, SLOT(slotFolderRemoved(KMFolder*))); |
|
|
|
connect(kmkernel->folderMgr(), SIGNAL(folderMoveOrCopyOperationFinished()), |
|
this, SLOT(slotFolderMoveOrCopyOperationFinished())); |
|
|
|
connect(kmkernel->imapFolderMgr(), SIGNAL(changed()), |
|
this, SLOT(doFolderListChanged())); |
|
|
|
connect(kmkernel->imapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)), |
|
this, SLOT(slotFolderRemoved(KMFolder*))); |
|
|
|
connect(kmkernel->dimapFolderMgr(), SIGNAL(changed()), |
|
this, SLOT(doFolderListChanged())); |
|
|
|
connect(kmkernel->dimapFolderMgr(), SIGNAL(folderRemoved(KMFolder*)), |
|
this, SLOT(slotFolderRemoved(KMFolder*))); |
|
|
|
connect(kmkernel->searchFolderMgr(), SIGNAL(changed()), |
|
this, SLOT(doFolderListChanged())); |
|
|
|
connect(kmkernel->acctMgr(), SIGNAL(accountRemoved(KMAccount*)), |
|
this, SLOT(slotAccountRemoved(KMAccount*))); |
|
|
|
connect(kmkernel->searchFolderMgr(), SIGNAL(folderRemoved(KMFolder*)), |
|
this, SLOT(slotFolderRemoved(KMFolder*))); |
|
|
|
connect( &autoopen_timer, SIGNAL( timeout() ), |
|
this, SLOT( openFolder() ) ); |
|
|
|
connect( this, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint &, int ) ), |
|
this, SLOT( slotContextMenuRequested( QListViewItem*, const QPoint & ) ) ); |
|
|
|
connect( this, SIGNAL( expanded( QListViewItem* ) ), |
|
this, SLOT( slotFolderExpanded( QListViewItem* ) ) ); |
|
|
|
connect( this, SIGNAL( collapsed( QListViewItem* ) ), |
|
this, SLOT( slotFolderCollapsed( QListViewItem* ) ) ); |
|
|
|
connect( this, SIGNAL( itemRenamed( QListViewItem*, int, const QString &)), |
|
this, SLOT( slotRenameFolder( QListViewItem*, int, const QString &))); |
|
|
|
connect( this, SIGNAL(folderSelected(KMFolder*)), SLOT(updateCopyActions()) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::readConfig (void) |
|
{ |
|
KConfig* conf = KMKernel::config(); |
|
|
|
readColorConfig(); |
|
|
|
// Custom/Ssystem font support |
|
{ |
|
KConfigGroupSaver saver(conf, "Fonts"); |
|
if (!conf->readBoolEntry("defaultFonts",true)) { |
|
QFont folderFont( KGlobalSettings::generalFont() ); |
|
setFont(conf->readFontEntry("folder-font", &folderFont)); |
|
} |
|
else |
|
setFont(KGlobalSettings::generalFont()); |
|
} |
|
|
|
// restore the layout |
|
restoreLayout(conf, "Geometry"); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Save the configuration file |
|
void KMFolderTree::writeConfig() |
|
{ |
|
// save the current state of the folders |
|
for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) { |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
if (fti) |
|
writeIsListViewItemOpen(fti); |
|
} |
|
|
|
// save the current layout |
|
saveLayout(KMKernel::config(), "Geometry"); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Updates the count of unread messages (count of unread messages |
|
// is now cached in KMails config file) |
|
void KMFolderTree::updateUnreadAll() |
|
{ |
|
bool upd = isUpdatesEnabled(); |
|
setUpdatesEnabled(false); |
|
|
|
KMFolderDir* fdir; |
|
KMFolderNode* folderNode; |
|
KMFolder* folder; |
|
|
|
fdir = &kmkernel->folderMgr()->dir(); |
|
for (folderNode = fdir->first(); |
|
folderNode != 0; |
|
folderNode =fdir->next()) |
|
{ |
|
if (!folderNode->isDir()) { |
|
folder = static_cast<KMFolder*>(folderNode); |
|
|
|
folder->open("updateunread"); |
|
folder->countUnread(); |
|
folder->close("updateunread"); |
|
} |
|
} |
|
|
|
setUpdatesEnabled(upd); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Reload the tree of items in the list view |
|
void KMFolderTree::reload(bool openFolders) |
|
{ |
|
if ( mReloading ) { |
|
// no parallel reloads are allowed |
|
kdDebug(5006) << "KMFolderTree::reload - already reloading" << endl; |
|
return; |
|
} |
|
mReloading = true; |
|
|
|
int top = contentsY(); |
|
mLastItem = 0; |
|
// invalidate selected drop item |
|
oldSelected = 0; |
|
// remember last |
|
KMFolder* last = currentFolder(); |
|
KMFolder* selected = 0; |
|
KMFolder* oldCurrentFolder = |
|
( oldCurrent ? static_cast<KMFolderTreeItem*>(oldCurrent)->folder(): 0 ); |
|
for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) { |
|
KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
writeIsListViewItemOpen( fti ); |
|
if ( fti->isSelected() ) |
|
selected = fti->folder(); |
|
} |
|
mFolderToItem.clear(); |
|
clear(); |
|
|
|
// construct the root of the local folders |
|
KMFolderTreeItem * root = new KMFolderTreeItem( this, i18n("Local Folders") ); |
|
root->setOpen( readIsListViewItemOpen(root) ); |
|
|
|
KMFolderDir * fdir = &kmkernel->folderMgr()->dir(); |
|
addDirectory(fdir, root); |
|
|
|
fdir = &kmkernel->imapFolderMgr()->dir(); |
|
// each imap-account creates it's own root |
|
addDirectory(fdir, 0); |
|
|
|
fdir = &kmkernel->dimapFolderMgr()->dir(); |
|
// each dimap-account creates it's own root |
|
addDirectory(fdir, 0); |
|
|
|
// construct the root of the search folder hierarchy: |
|
root = new KMFolderTreeItem( this, i18n("Searches"), KFolderTreeItem::Search ); |
|
root->setOpen( readIsListViewItemOpen( root ) ); |
|
|
|
fdir = &kmkernel->searchFolderMgr()->dir(); |
|
addDirectory(fdir, root); |
|
|
|
if (openFolders) |
|
{ |
|
// we open all folders to update the count |
|
mUpdateIterator = QListViewItemIterator (this); |
|
QTimer::singleShot( 0, this, SLOT(slotUpdateOneCount()) ); |
|
} |
|
|
|
for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) { |
|
KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
if ( !fti || !fti->folder() ) |
|
continue; |
|
|
|
disconnect(fti->folder(),SIGNAL(iconsChanged()), |
|
fti,SLOT(slotIconsChanged())); |
|
connect(fti->folder(),SIGNAL(iconsChanged()), |
|
fti,SLOT(slotIconsChanged())); |
|
|
|
disconnect(fti->folder(),SIGNAL(nameChanged()), |
|
fti,SLOT(slotNameChanged())); |
|
connect(fti->folder(),SIGNAL(nameChanged()), |
|
fti,SLOT(slotNameChanged())); |
|
|
|
// With the use of slotUpdateCountsDelayed is not necesary |
|
// a specific processing for Imap |
|
#if 0 |
|
if (fti->folder()->folderType() == KMFolderTypeImap) { |
|
// imap-only |
|
KMFolderImap *imapFolder = |
|
dynamic_cast<KMFolderImap*> ( fti->folder()->storage() ); |
|
disconnect( imapFolder, SIGNAL(folderComplete(KMFolderImap*, bool)), |
|
this,SLOT(slotUpdateCounts(KMFolderImap*, bool))); |
|
connect( imapFolder, SIGNAL(folderComplete(KMFolderImap*, bool)), |
|
this,SLOT(slotUpdateCounts(KMFolderImap*, bool))); |
|
} else {*/ |
|
#endif |
|
|
|
// we want to be noticed of changes to update the unread/total columns |
|
disconnect(fti->folder(), SIGNAL(msgAdded(KMFolder*,Q_UINT32)), |
|
this,SLOT(slotUpdateCountsDelayed(KMFolder*))); |
|
connect(fti->folder(), SIGNAL(msgAdded(KMFolder*,Q_UINT32)), |
|
this,SLOT(slotUpdateCountsDelayed(KMFolder*))); |
|
//} |
|
|
|
disconnect(fti->folder(), SIGNAL(numUnreadMsgsChanged(KMFolder*)), |
|
this,SLOT(slotUpdateCountsDelayed(KMFolder*))); |
|
connect(fti->folder(), SIGNAL(numUnreadMsgsChanged(KMFolder*)), |
|
this,SLOT(slotUpdateCountsDelayed(KMFolder*))); |
|
disconnect(fti->folder(), SIGNAL(msgRemoved(KMFolder*)), |
|
this,SLOT(slotUpdateCountsDelayed(KMFolder*))); |
|
connect(fti->folder(), SIGNAL(msgRemoved(KMFolder*)), |
|
this,SLOT(slotUpdateCountsDelayed(KMFolder*))); |
|
|
|
disconnect(fti->folder(), SIGNAL(folderSizeChanged( KMFolder* )), |
|
this,SLOT(slotUpdateCountsDelayed(KMFolder*))); |
|
connect(fti->folder(), SIGNAL(folderSizeChanged( KMFolder* )), |
|
this,SLOT(slotUpdateCountsDelayed(KMFolder*))); |
|
|
|
|
|
|
|
disconnect(fti->folder(), SIGNAL(shortcutChanged(KMFolder*)), |
|
mMainWidget, SLOT( slotShortcutChanged(KMFolder*))); |
|
connect(fti->folder(), SIGNAL(shortcutChanged(KMFolder*)), |
|
mMainWidget, SLOT( slotShortcutChanged(KMFolder*))); |
|
|
|
|
|
if (!openFolders) |
|
slotUpdateCounts(fti->folder()); |
|
|
|
// populate the size column |
|
fti->setFolderSize( 0 ); |
|
fti->setFolderIsCloseToQuota( fti->folder()->storage()->isCloseToQuota() ); |
|
|
|
} |
|
ensureVisible(0, top + visibleHeight(), 0, 0); |
|
// if current and selected folder did not change set it again |
|
for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) |
|
{ |
|
if ( last && |
|
static_cast<KMFolderTreeItem*>( it.current() )->folder() == last ) |
|
{ |
|
mLastItem = static_cast<KMFolderTreeItem*>( it.current() ); |
|
setCurrentItem( it.current() ); |
|
} |
|
if ( selected && |
|
static_cast<KMFolderTreeItem*>( it.current() )->folder() == selected ) |
|
{ |
|
setSelected( it.current(), true ); |
|
} |
|
if ( oldCurrentFolder && |
|
static_cast<KMFolderTreeItem*>( it.current() )->folder() == oldCurrentFolder ) |
|
{ |
|
oldCurrent = it.current(); |
|
} |
|
} |
|
refresh(); |
|
mReloading = false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotUpdateOneCount() |
|
{ |
|
if ( !mUpdateIterator.current() ) return; |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(mUpdateIterator.current()); |
|
++mUpdateIterator; |
|
if ( !fti->folder() ) { |
|
// next one please |
|
QTimer::singleShot( 0, this, SLOT(slotUpdateOneCount()) ); |
|
return; |
|
} |
|
|
|
// open the folder and update the count |
|
bool open = fti->folder()->isOpened(); |
|
if (!open) fti->folder()->open("updatecount"); |
|
slotUpdateCounts(fti->folder()); |
|
// restore previous state |
|
if (!open) fti->folder()->close("updatecount"); |
|
|
|
QTimer::singleShot( 0, this, SLOT(slotUpdateOneCount()) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Recursively add a directory of folders to the tree of folders |
|
void KMFolderTree::addDirectory( KMFolderDir *fdir, KMFolderTreeItem* parent ) |
|
{ |
|
for ( KMFolderNode * node = fdir->first() ; node ; node = fdir->next() ) { |
|
if ( node->isDir() ) |
|
continue; |
|
|
|
KMFolder * folder = static_cast<KMFolder*>(node); |
|
KMFolderTreeItem * fti = 0; |
|
if (!parent) |
|
{ |
|
// create new root-item, but only if this is not the root of a |
|
// "groupware folders only" account |
|
if ( kmkernel->iCalIface().hideResourceAccountRoot( folder ) ) |
|
continue; |
|
// it needs a folder e.g. to save it's state (open/close) |
|
fti = new KMFolderTreeItem( this, folder->label(), folder ); |
|
fti->setExpandable( true ); |
|
} else { |
|
// Check if this is an IMAP resource folder |
|
if ( kmkernel->iCalIface().hideResourceFolder( folder ) ) |
|
// It is |
|
continue; |
|
|
|
// hide local inbox if unused |
|
if ( kmkernel->inboxFolder() == folder && hideLocalInbox() ) { |
|
connect( kmkernel->inboxFolder(), SIGNAL(msgAdded(KMFolder*,Q_UINT32)), SLOT(slotUnhideLocalInbox()) ); |
|
continue; |
|
} |
|
|
|
// create new child |
|
fti = new KMFolderTreeItem( parent, folder->label(), folder ); |
|
// set folders explicitely to exandable when they have children |
|
// this way we can do a listing for IMAP folders when the user expands them |
|
// even when the child folders are not created yet |
|
if ( folder->storage()->hasChildren() == FolderStorage::HasChildren ) { |
|
fti->setExpandable( true ); |
|
} else { |
|
fti->setExpandable( false ); |
|
} |
|
|
|
connect (fti, SIGNAL(iconChanged(KMFolderTreeItem*)), |
|
this, SIGNAL(iconChanged(KMFolderTreeItem*))); |
|
connect (fti, SIGNAL(nameChanged(KMFolderTreeItem*)), |
|
this, SIGNAL(nameChanged(KMFolderTreeItem*))); |
|
|
|
} |
|
// restore last open-state |
|
fti->setOpen( readIsListViewItemOpen(fti) ); |
|
|
|
// add child-folders |
|
if (folder && folder->child()) { |
|
addDirectory( folder->child(), fti ); |
|
} |
|
} // for-end |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Initiate a delayed refresh of the tree |
|
void KMFolderTree::refresh() |
|
{ |
|
mUpdateTimer.changeInterval(200); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Updates the pixmap and extendedLabel information for items |
|
void KMFolderTree::delayedUpdate() |
|
{ |
|
bool upd = isUpdatesEnabled(); |
|
if ( upd ) { |
|
setUpdatesEnabled(false); |
|
|
|
for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) { |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
if (!fti || !fti->folder()) |
|
continue; |
|
|
|
if ( fti->needsRepaint() ) { |
|
fti->repaint(); |
|
fti->setNeedsRepaint( false ); |
|
} |
|
} |
|
setUpdatesEnabled(upd); |
|
} |
|
mUpdateTimer.stop(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Folders have been added/deleted update the tree of folders |
|
void KMFolderTree::doFolderListChanged() |
|
{ |
|
reload(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotAccountRemoved(KMAccount *) |
|
{ |
|
doFolderSelected( firstChild() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotFolderMoveOrCopyOperationFinished() |
|
{ |
|
setDragEnabled( true ); |
|
} |
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotFolderRemoved(KMFolder *aFolder) |
|
{ |
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*> |
|
(indexOfFolder(aFolder)); |
|
if ( oldCurrent == fti ) |
|
oldCurrent = 0; |
|
if ( oldSelected == fti ) |
|
oldSelected = 0; |
|
if (!fti || !fti->folder()) return; |
|
if (fti == currentItem()) |
|
{ |
|
QListViewItem *qlvi = fti->itemAbove(); |
|
if (!qlvi) qlvi = fti->itemBelow(); |
|
doFolderSelected( qlvi ); |
|
} |
|
removeFromFolderToItemMap( aFolder ); |
|
|
|
if ( dropItem == fti ) { // The removed item is the dropItem |
|
dropItem = 0; // it becomes invalid |
|
} |
|
|
|
delete fti; |
|
updateCopyActions(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Methods for navigating folders with the keyboard |
|
void KMFolderTree::prepareItem( KMFolderTreeItem* fti ) |
|
{ |
|
for ( QListViewItem * parent = fti->parent() ; parent ; parent = parent->parent() ) |
|
parent->setOpen( true ); |
|
ensureItemVisible( fti ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::nextUnreadFolder() |
|
{ |
|
nextUnreadFolder( false ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::nextUnreadFolder(bool confirm) |
|
{ |
|
QListViewItemIterator it( currentItem() ? currentItem() : firstChild() ); |
|
if ( currentItem() ) |
|
++it; // don't find current item |
|
for ( ; it.current() ; ++it ) { |
|
//check if folder is one to stop on |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
if (checkUnreadFolder(fti,confirm)) return; |
|
} |
|
//Now if confirm is true we are doing "ReadOn" |
|
//we have got to the bottom of the folder list |
|
//so we have to start at the top |
|
if (confirm) { |
|
for ( it = firstChild() ; it.current() ; ++it ) { |
|
//check if folder is one to stop on |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
if (checkUnreadFolder(fti,confirm)) return; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMFolderTree::checkUnreadFolder (KMFolderTreeItem* fti, bool confirm) |
|
{ |
|
if ( fti && fti->folder() && !fti->folder()->ignoreNewMail() && |
|
( fti->folder()->countUnread() > 0 ) ) { |
|
|
|
// Don't change into the trash or outbox folders. |
|
if (fti->type() == KFolderTreeItem::Trash || |
|
fti->type() == KFolderTreeItem::Outbox ) |
|
return false; |
|
|
|
if (confirm) { |
|
// Skip drafts, sent mail and templates as well, when reading mail with |
|
// the space bar but not when changing into the next folder with unread |
|
// mail via ctrl+ or ctrl- so we do this only if (confirm == true), |
|
// which means we are doing readOn. |
|
if ( fti->type() == KFolderTreeItem::Drafts || |
|
fti->type() == KFolderTreeItem::Templates || |
|
fti->type() == KFolderTreeItem::SentMail ) |
|
return false; |
|
|
|
// warn user that going to next folder - but keep track of |
|
// whether he wishes to be notified again in "AskNextFolder" |
|
// parameter (kept in the config file for kmail) |
|
if ( KMessageBox::questionYesNo( this, |
|
i18n( "<qt>Go to the next unread message in folder <b>%1</b>?</qt>" ) |
|
.arg( fti->folder()->label() ), |
|
i18n( "Go to Next Unread Message" ), |
|
i18n("Go To"), i18n("Do Not Go To"), // defaults |
|
"AskNextFolder", |
|
false) |
|
== KMessageBox::No ) return true; |
|
} |
|
prepareItem( fti ); |
|
blockSignals( true ); |
|
doFolderSelected( fti ); |
|
blockSignals( false ); |
|
emit folderSelectedUnread( fti->folder() ); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::prevUnreadFolder() |
|
{ |
|
QListViewItemIterator it( currentItem() ? currentItem() : lastItem() ); |
|
if ( currentItem() ) |
|
--it; // don't find current item |
|
for ( ; it.current() ; --it ) { |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
if (checkUnreadFolder(fti,false)) return; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::incCurrentFolder() |
|
{ |
|
QListViewItemIterator it( currentItem() ); |
|
++it; |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
if (fti) { |
|
prepareItem( fti ); |
|
setFocus(); |
|
setCurrentItem( fti ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::decCurrentFolder() |
|
{ |
|
QListViewItemIterator it( currentItem() ); |
|
--it; |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
if (fti) { |
|
prepareItem( fti ); |
|
setFocus(); |
|
setCurrentItem( fti ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::selectCurrentFolder() |
|
{ |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( currentItem() ); |
|
if (fti) { |
|
prepareItem( fti ); |
|
doFolderSelected( fti ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
KMFolder *KMFolderTree::currentFolder() const |
|
{ |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( currentItem() ); |
|
if (fti ) |
|
return fti->folder(); |
|
else |
|
return 0; |
|
} |
|
|
|
QValueList<QGuardedPtr<KMFolder> > KMFolderTree::selectedFolders() |
|
{ |
|
QValueList<QGuardedPtr<KMFolder> > rv; |
|
for ( QListViewItemIterator it( this ); it.current(); ++it ) { |
|
if ( it.current()->isSelected() ) { |
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() ); |
|
rv.append( fti->folder() ); |
|
} |
|
} |
|
return rv; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// When not dragging and dropping a change in the selected item |
|
// indicates the user has changed the active folder emit a signal |
|
// so that the header list and reader window can be udpated. |
|
void KMFolderTree::doFolderSelected( QListViewItem* qlvi, bool keepSelection ) |
|
{ |
|
if (!qlvi) return; |
|
if ( mLastItem && mLastItem == qlvi && (keepSelection || selectedFolders().count() == 1) ) |
|
return; |
|
|
|
KMFolderTreeItem* fti = static_cast< KMFolderTreeItem* >(qlvi); |
|
KMFolder* folder = 0; |
|
if (fti) folder = fti->folder(); |
|
|
|
|
|
if (mLastItem && mLastItem != fti && mLastItem->folder() |
|
&& (mLastItem->folder()->folderType() == KMFolderTypeImap)) |
|
{ |
|
KMFolderImap *imapFolder = static_cast<KMFolderImap*>(mLastItem->folder()->storage()); |
|
imapFolder->setSelected(false); |
|
} |
|
mLastItem = fti; |
|
|
|
if ( !keepSelection ) |
|
clearSelection(); |
|
setCurrentItem( qlvi ); |
|
if ( !keepSelection ) |
|
setSelected( qlvi, true ); |
|
ensureItemVisible( qlvi ); |
|
if (!folder) { |
|
emit folderSelected(0); // Root has been selected |
|
} |
|
else { |
|
emit folderSelected(folder); |
|
slotUpdateCounts(folder); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::resizeEvent(QResizeEvent* e) |
|
{ |
|
KConfig* conf = KMKernel::config(); |
|
|
|
KConfigGroupSaver saver(conf, "Geometry"); |
|
conf->writeEntry(name(), size().width()); |
|
|
|
KListView::resizeEvent(e); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// show context menu |
|
void KMFolderTree::slotContextMenuRequested( QListViewItem *lvi, |
|
const QPoint &p ) |
|
{ |
|
if (!lvi) |
|
return; |
|
setCurrentItem( lvi ); |
|
|
|
if (!mMainWidget) return; // safe bet |
|
|
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(lvi); |
|
if ( !isSelected( fti ) ) |
|
doFolderSelected( fti ); |
|
else if ( fti != mLastItem ) |
|
doFolderSelected( fti, true ); |
|
|
|
if (!fti ) |
|
return; |
|
|
|
KPopupMenu *folderMenu = new KPopupMenu; |
|
bool multiFolder = selectedFolders().count() > 1; |
|
if (fti->folder()) folderMenu->insertTitle(fti->folder()->label()); |
|
|
|
// outbox specific, but there it's the most used action |
|
if ( (fti->folder() == kmkernel->outboxFolder()) && fti->folder()->count() ) |
|
mMainWidget->action("send_queued")->plug( folderMenu ); |
|
// Mark all as read is supposedly used often, therefor it is first |
|
if ( fti->folder() && !fti->folder()->noContent() ) |
|
mMainWidget->action("mark_all_as_read")->plug( folderMenu ); |
|
|
|
/* Treat the special case of the root and account folders */ |
|
if ((!fti->folder() || (fti->folder()->noContent() |
|
&& !fti->parent()))) |
|
{ |
|
QString createChild = i18n("&New Subfolder..."); |
|
if (!fti->folder()) createChild = i18n("&New Folder..."); |
|
|
|
if (fti->folder() || (fti->text(0) != i18n("Searches")) && !multiFolder) |
|
folderMenu->insertItem(SmallIconSet("folder_new"), |
|
createChild, this, |
|
SLOT(addChildFolder())); |
|
|
|
if (!fti->folder()) { |
|
mMainWidget->action("compact_all_folders")->plug(folderMenu); |
|
mMainWidget->action("expire_all_folders")->plug(folderMenu); |
|
} else if (fti->folder()->folderType() == KMFolderTypeImap) { |
|
folderMenu->insertItem(SmallIconSet("mail_get"), i18n("Check &Mail"), |
|
this, |
|
SLOT(slotCheckMail())); |
|
} |
|
} else { // regular folders |
|
|
|
folderMenu->insertSeparator(); |
|
if ( !fti->folder()->noChildren() && !multiFolder ) { |
|
folderMenu->insertItem(SmallIconSet("folder_new"), |
|
i18n("&New Subfolder..."), this, |
|
SLOT(addChildFolder())); |
|
} |
|
|
|
// copy folder |
|
QPopupMenu *copyMenu = new QPopupMenu( folderMenu ); |
|
folderToPopupMenu( CopyFolder, this, &mMenuToFolder, copyMenu ); |
|
folderMenu->insertItem( i18n("&Copy Folder To"), copyMenu ); |
|
|
|
if ( fti->folder()->isMoveable() ) |
|
{ |
|
QPopupMenu *moveMenu = new QPopupMenu( folderMenu ); |
|
folderToPopupMenu( MoveFolder, this, &mMenuToFolder, moveMenu ); |
|
folderMenu->insertItem( i18n("&Move Folder To"), moveMenu ); |
|
} |
|
|
|
// Want to be able to display properties for ALL folders, |
|
// so we can edit expiry properties. |
|
// -- smp. |
|
if (!fti->folder()->noContent()) |
|
{ |
|
if ( !multiFolder ) |
|
mMainWidget->action("search_messages")->plug(folderMenu); |
|
|
|
mMainWidget->action("compact")->plug(folderMenu); |
|
|
|
if ( GlobalSettings::self()->enableFavoriteFolderView() ) { |
|
folderMenu->insertItem( SmallIconSet("bookmark_add"), i18n("Add to Favorite Folders"), |
|
this, SLOT(slotAddToFavorites()) ); |
|
} |
|
|
|
folderMenu->insertSeparator(); |
|
mMainWidget->action("empty")->plug(folderMenu); |
|
if ( !fti->folder()->isSystemFolder() ) { |
|
mMainWidget->action("delete_folder")->plug(folderMenu); |
|
} |
|
folderMenu->insertSeparator(); |
|
} |
|
} |
|
|
|
/* plug in IMAP and DIMAP specific things */ |
|
if (fti->folder() && |
|
(fti->folder()->folderType() == KMFolderTypeImap || |
|
fti->folder()->folderType() == KMFolderTypeCachedImap )) |
|
{ |
|
folderMenu->insertItem(SmallIconSet("bookmark_folder"), |
|
i18n("Subscription..."), mMainWidget, |
|
SLOT(slotSubscriptionDialog())); |
|
folderMenu->insertItem(SmallIcon("bookmark_folder"), |
|
i18n("Local Subscription..."), mMainWidget, |
|
SLOT(slotLocalSubscriptionDialog())); |
|
|
|
if (!fti->folder()->noContent()) |
|
{ |
|
mMainWidget->action("refresh_folder")->plug(folderMenu); |
|
if ( fti->folder()->folderType() == KMFolderTypeImap && !multiFolder ) { |
|
folderMenu->insertItem(SmallIconSet("reload"), i18n("Refresh Folder List"), this, |
|
SLOT(slotResetFolderList())); |
|
} |
|
} |
|
if ( fti->folder()->folderType() == KMFolderTypeCachedImap && !multiFolder ) { |
|
KMFolderCachedImap * folder = static_cast<KMFolderCachedImap*>( fti->folder()->storage() ); |
|
folderMenu->insertItem( SmallIconSet("wizard"), |
|
i18n("&Troubleshoot IMAP Cache..."), |
|
folder, SLOT(slotTroubleshoot()) ); |
|
} |
|
folderMenu->insertSeparator(); |
|
} |
|
|
|
if ( fti->folder() && fti->folder()->isMailingListEnabled() && !multiFolder ) { |
|
mMainWidget->action("post_message")->plug(folderMenu); |
|
} |
|
|
|
if (fti->folder() && fti->parent() && !multiFolder) |
|
{ |
|
folderMenu->insertItem(SmallIconSet("configure_shortcuts"), |
|
i18n("&Assign Shortcut..."), |
|
fti, |
|
SLOT(assignShortcut())); |
|
|
|
if ( !fti->folder()->noContent() ) { |
|
folderMenu->insertItem( i18n("Expire..."), fti, |
|
SLOT( slotShowExpiryProperties() ) ); |
|
} |
|
mMainWidget->action("modify")->plug(folderMenu); |
|
} |
|
|
|
|
|
kmkernel->setContextMenuShown( true ); |
|
folderMenu->exec (p, 0); |
|
kmkernel->setContextMenuShown( false ); |
|
triggerUpdate(); |
|
delete folderMenu; |
|
folderMenu = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::contentsMousePressEvent(QMouseEvent * e) |
|
{ |
|
// KFolderTree messes around with the selection mode |
|
KListView::contentsMousePressEvent( e ); |
|
} |
|
|
|
// If middle button and folder holds mailing-list, create a message to that list |
|
void KMFolderTree::contentsMouseReleaseEvent(QMouseEvent* me) |
|
{ |
|
QListViewItem *lvi = currentItem(); // Needed for when branches are clicked on |
|
ButtonState btn = me->button(); |
|
doFolderSelected(lvi, true); |
|
|
|
// get underlying folder |
|
KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>(lvi); |
|
|
|
if (!fti || !fti->folder()) { |
|
KFolderTree::contentsMouseReleaseEvent(me); |
|
return; |
|
} |
|
|
|
// react on middle-button only |
|
if (btn != Qt::MidButton) { |
|
KFolderTree::contentsMouseReleaseEvent(me); |
|
return; |
|
} |
|
|
|
if ( fti->folder()->isMailingListEnabled() ) { |
|
KMCommand *command = new KMMailingListPostCommand( this, fti->folder() ); |
|
command->start(); |
|
} |
|
|
|
KFolderTree::contentsMouseReleaseEvent(me); |
|
} |
|
|
|
// little static helper |
|
static bool folderHasCreateRights( const KMFolder *folder ) |
|
{ |
|
bool createRights = true; // we don't have acls for local folders yet |
|
if ( folder && folder->folderType() == KMFolderTypeImap ) { |
|
const KMFolderImap *imapFolder = static_cast<const KMFolderImap*>( folder->storage() ); |
|
createRights = imapFolder->userRights() == 0 || // hack, we should get the acls |
|
( imapFolder->userRights() > 0 && ( imapFolder->userRights() & KMail::ACLJobs::Create ) ); |
|
} else if ( folder && folder->folderType() == KMFolderTypeCachedImap ) { |
|
const KMFolderCachedImap *dimapFolder = static_cast<const KMFolderCachedImap*>( folder->storage() ); |
|
createRights = dimapFolder->userRights() == 0 || |
|
( dimapFolder->userRights() > 0 && ( dimapFolder->userRights() & KMail::ACLJobs::Create ) ); |
|
} |
|
return createRights; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Create a subfolder. |
|
// Requires creating the appropriate subdirectory and show a dialog |
|
void KMFolderTree::addChildFolder( KMFolder *folder, QWidget * parent ) |
|
{ |
|
KMFolder *aFolder = folder; |
|
if ( !aFolder ) { |
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(currentItem()); |
|
if (!fti) |
|
return; |
|
aFolder = fti->folder(); |
|
} |
|
if (aFolder) { |
|
if (!aFolder->createChildFolder()) |
|
return; |
|
if ( !folderHasCreateRights( aFolder ) ) { |
|
// FIXME: change this message to "Cannot create folder under ..." or similar |
|
const QString message = i18n( "<qt>Cannot create folder <b>%1</b> because of insufficient " |
|
"permissions on the server. If you think you should be able to create " |
|
"subfolders here, ask your administrator to grant you rights to do so." |
|
"</qt> " ).arg(aFolder->label()); |
|
KMessageBox::error( this, message ); |
|
return; |
|
} |
|
} |
|
|
|
if ( parent ) |
|
( new KMail::NewFolderDialog( parent, aFolder ) )->exec(); |
|
else |
|
( new KMail::NewFolderDialog( this, aFolder ) )->show(); |
|
return; |
|
/* |
|
KMFolderDir *dir = &(kmkernel->folderMgr()->dir()); |
|
if (aFolder) |
|
dir = aFolder->child(); |
|
|
|
KMFolderDialog *d = |
|
new KMFolderDialog(0, dir, this, i18n("Create Subfolder") ); |
|
|
|
if (d->exec()) { // fti may be deleted here |
|
QListViewItem *qlvi = indexOfFolder( aFolder ); |
|
if (qlvi) { |
|
qlvi->setOpen(true); |
|
blockSignals( true ); |
|
setCurrentItem( qlvi ); |
|
blockSignals( false ); |
|
} |
|
} |
|
delete d; |
|
// update if added to root Folder |
|
if (!aFolder || aFolder->noContent()) { |
|
doFolderListChanged(); |
|
} |
|
*/ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Returns whether a folder directory should be open as specified in the |
|
// config file. |
|
bool KMFolderTree::readIsListViewItemOpen(KMFolderTreeItem *fti) |
|
{ |
|
KConfig* config = KMKernel::config(); |
|
KMFolder *folder = fti->folder(); |
|
QString name; |
|
if (folder) |
|
{ |
|
name = "Folder-" + folder->idString(); |
|
} else if (fti->type() == KFolderTreeItem::Root) |
|
{ |
|
if (fti->protocol() == KFolderTreeItem::NONE) // local root |
|
name = "Folder_local_root"; |
|
else if (fti->protocol() == KFolderTreeItem::Search) |
|
name = "Folder_search"; |
|
else |
|
return false; |
|
} else { |
|
return false; |
|
} |
|
KConfigGroupSaver saver(config, name); |
|
|
|
return config->readBoolEntry("isOpen", false); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Saves open/closed state of a folder directory into the config file |
|
void KMFolderTree::writeIsListViewItemOpen(KMFolderTreeItem *fti) |
|
{ |
|
KConfig* config = KMKernel::config(); |
|
KMFolder *folder = fti->folder(); |
|
QString name; |
|
if (folder && !folder->idString().isEmpty()) |
|
{ |
|
name = "Folder-" + folder->idString(); |
|
} else if (fti->type() == KFolderTreeItem::Root) |
|
{ |
|
if (fti->protocol() == KFolderTreeItem::NONE) // local root |
|
name = "Folder_local_root"; |
|
else if (fti->protocol() == KFolderTreeItem::Search) |
|
name = "Folder_search"; |
|
else |
|
return; |
|
} else { |
|
return; |
|
} |
|
KConfigGroupSaver saver(config, name); |
|
config->writeEntry("isOpen", fti->isOpen() ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::cleanupConfigFile() |
|
{ |
|
if ( childCount() == 0 ) |
|
return; // just in case reload wasn't called before |
|
KConfig* config = KMKernel::config(); |
|
QStringList existingFolders; |
|
QListViewItemIterator fldIt(this); |
|
QMap<QString,bool> folderMap; |
|
KMFolderTreeItem *fti; |
|
for (QListViewItemIterator fldIt(this); fldIt.current(); fldIt++) |
|
{ |
|
fti = static_cast<KMFolderTreeItem*>(fldIt.current()); |
|
if (fti && fti->folder()) |
|
folderMap.insert(fti->folder()->idString(), true); |
|
} |
|
QStringList groupList = config->groupList(); |
|
QString name; |
|
for (QStringList::Iterator grpIt = groupList.begin(); |
|
grpIt != groupList.end(); grpIt++) |
|
{ |
|
if ((*grpIt).left(7) != "Folder-") continue; |
|
name = (*grpIt).mid(7); |
|
if (folderMap.find(name) == folderMap.end()) |
|
{ |
|
KMFolder* folder = kmkernel->findFolderById( name ); |
|
if ( folder ) { |
|
if ( kmkernel->iCalIface().hideResourceFolder( folder ) |
|
|| kmkernel->iCalIface().hideResourceAccountRoot( folder ) ) |
|
continue; // hidden IMAP resource folder, don't delete info |
|
} |
|
|
|
//KMessageBox::error( 0, "cleanupConfigFile: Deleting group " + *grpIt ); |
|
config->deleteGroup(*grpIt, true); |
|
kdDebug(5006) << "Deleting information about folder " << name << endl; |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::openFolder() |
|
{ |
|
autoopen_timer.stop(); |
|
if ( dropItem && !dropItem->isOpen() ) { |
|
dropItem->setOpen( true ); |
|
dropItem->repaint(); |
|
} |
|
} |
|
|
|
static const int autoopenTime = 750; |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::contentsDragEnterEvent( QDragEnterEvent *e ) |
|
{ |
|
oldCurrent = 0; |
|
oldSelected = 0; |
|
|
|
oldCurrent = currentItem(); |
|
for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) |
|
if ( it.current()->isSelected() ) |
|
oldSelected = it.current(); |
|
|
|
setFocus(); |
|
|
|
QListViewItem *i = itemAt( contentsToViewport(e->pos()) ); |
|
if ( i ) { |
|
dropItem = i; |
|
autoopen_timer.start( autoopenTime ); |
|
} |
|
else |
|
dropItem = 0; |
|
|
|
e->accept( acceptDrag(e) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::contentsDragMoveEvent( QDragMoveEvent *e ) |
|
{ |
|
QPoint vp = contentsToViewport(e->pos()); |
|
QListViewItem *i = itemAt( vp ); |
|
if ( i ) { |
|
bool dragAccepted = acceptDrag( e ); |
|
if ( dragAccepted ) { |
|
setCurrentItem( i ); |
|
} |
|
|
|
if ( i != dropItem ) { |
|
autoopen_timer.stop(); |
|
dropItem = i; |
|
autoopen_timer.start( autoopenTime ); |
|
} |
|
|
|
if ( dragAccepted ) { |
|
e->accept( itemRect(i) ); |
|
|
|
switch ( e->action() ) { |
|
case QDropEvent::Copy: |
|
break; |
|
case QDropEvent::Move: |
|
e->acceptAction(); |
|
break; |
|
case QDropEvent::Link: |
|
e->acceptAction(); |
|
break; |
|
default: |
|
; |
|
} |
|
} else { |
|
e->accept( false ); |
|
} |
|
} else { |
|
e->accept( false ); |
|
autoopen_timer.stop(); |
|
dropItem = 0; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::contentsDragLeaveEvent( QDragLeaveEvent * ) |
|
{ |
|
if (!oldCurrent) return; |
|
|
|
autoopen_timer.stop(); |
|
dropItem = 0; |
|
|
|
setCurrentItem( oldCurrent ); |
|
if ( oldSelected ) |
|
setSelected( oldSelected, true ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::contentsDropEvent( QDropEvent *e ) |
|
{ |
|
autoopen_timer.stop(); |
|
|
|
QListViewItem *item = itemAt( contentsToViewport(e->pos()) ); |
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item); |
|
// Check that each pointer is not null |
|
for ( QValueList<QGuardedPtr<KMFolder> >::ConstIterator it = mCopySourceFolders.constBegin(); |
|
it != mCopySourceFolders.constEnd(); ++it ) { |
|
if ( ! (*it) ) { |
|
fti = 0; |
|
break; |
|
} |
|
} |
|
if (fti && mCopySourceFolders.count() == 1) |
|
{ |
|
KMFolder *source = mCopySourceFolders.first(); |
|
// if we are dragging to ourselves or to our parent, set fti to 0 so nothing is done |
|
if (source == fti->folder() || source->parent()->owner() == fti->folder()) fti = 0; |
|
} |
|
if (fti && acceptDrag(e) && ( fti != oldSelected || e->source() != mMainWidget->headers()->viewport() ) ) |
|
{ |
|
int action = dndMode( e->provides("application/x-qlistviewitem") /* always ask */ ); |
|
if ( e->provides("application/x-qlistviewitem") ) { |
|
if ( (action == DRAG_COPY || action == DRAG_MOVE) && !mCopySourceFolders.isEmpty() ) { |
|
for ( QValueList<QGuardedPtr<KMFolder> >::ConstIterator it = mCopySourceFolders.constBegin(); |
|
it != mCopySourceFolders.constEnd(); ++it ) { |
|
if ( ! (*it)->isMoveable() ) |
|
action = DRAG_COPY; |
|
} |
|
moveOrCopyFolder( mCopySourceFolders, fti->folder(), (action == DRAG_MOVE) ); |
|
} |
|
} else { |
|
if ( e->source() == mMainWidget->headers()->viewport() ) { |
|
// KMHeaders does copy/move itself |
|
if ( action == DRAG_MOVE && fti->folder() ) |
|
emit folderDrop( fti->folder() ); |
|
else if ( action == DRAG_COPY && fti->folder() ) |
|
emit folderDropCopy( fti->folder() ); |
|
} else if ( action == DRAG_COPY || action == DRAG_MOVE ) { |
|
MailList list; |
|
if ( !MailListDrag::decode( e, list ) ) { |
|
kdWarning() << k_funcinfo << "Could not decode drag data!" << endl; |
|
} else { |
|
QValueList<Q_UINT32> serNums = MessageCopyHelper::serNumListFromMailList( list ); |
|
new MessageCopyHelper( serNums, fti->folder(), action == DRAG_MOVE, this ); |
|
} |
|
} |
|
} |
|
e->accept( true ); |
|
} else |
|
e->accept( false ); |
|
|
|
dropItem = 0; |
|
|
|
setCurrentItem( oldCurrent ); |
|
if ( oldCurrent) mLastItem = static_cast<KMFolderTreeItem*>(oldCurrent); |
|
if ( oldSelected ) |
|
{ |
|
clearSelection(); |
|
setSelected( oldSelected, true ); |
|
} |
|
|
|
mCopySourceFolders.clear(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotFolderExpanded( QListViewItem * item ) |
|
{ |
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item); |
|
if ( !fti || !fti->folder() || !fti->folder()->storage() ) return; |
|
|
|
fti->setFolderSize( fti->folder()->storage()->folderSize() ); |
|
|
|
if( fti->folder()->folderType() == KMFolderTypeImap ) |
|
{ |
|
KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() ); |
|
// if we should list all folders we limit this to the root folder |
|
if ( !folder->account()->listOnlyOpenFolders() && |
|
fti->parent() ) |
|
return; |
|
if ( folder->getSubfolderState() == KMFolderImap::imapNoInformation ) |
|
{ |
|
// check if all parents are expanded |
|
QListViewItem *parent = item->parent(); |
|
while ( parent ) |
|
{ |
|
if ( !parent->isOpen() ) |
|
return; |
|
parent = parent->parent(); |
|
} |
|
// the tree will be reloaded after that |
|
bool success = folder->listDirectory(); |
|
if (!success) fti->setOpen( false ); |
|
if ( fti->childCount() == 0 && fti->parent() ) |
|
fti->setExpandable( false ); |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotFolderCollapsed( QListViewItem * item ) |
|
{ |
|
slotResetFolderList( item, false ); |
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item); |
|
if ( !fti || !fti->folder() || !fti->folder()->storage() ) return; |
|
|
|
fti->setFolderSize( fti->folder()->storage()->folderSize() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotRenameFolder(QListViewItem *item, int col, |
|
const QString &text) |
|
{ |
|
|
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item); |
|
|
|
if ((!fti) || (fti && fti->folder() && col != 0 && !currentFolder()->child())) |
|
return; |
|
|
|
QString fldName, oldFldName; |
|
|
|
oldFldName = fti->name(0); |
|
|
|
if (!text.isEmpty()) |
|
fldName = text; |
|
else |
|
fldName = oldFldName; |
|
|
|
fldName.replace("/", ""); |
|
fldName.replace(QRegExp("^\\."), ""); |
|
|
|
if (fldName.isEmpty()) |
|
fldName = i18n("unnamed"); |
|
|
|
fti->setText(0, fldName); |
|
fti->folder()->rename(fldName, &(kmkernel->folderMgr()->dir())); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotUpdateCounts(KMFolderImap * folder, bool success) |
|
{ |
|
if (success) slotUpdateCounts(folder->folder()); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotUpdateCountsDelayed(KMFolder * folder) |
|
{ |
|
// kdDebug(5006) << "KMFolderTree::slotUpdateCountsDelayed()" << endl; |
|
if ( !mFolderToUpdateCount.contains( folder->idString() ) ) |
|
{ |
|
// kdDebug( 5006 )<< "adding " << folder->idString() << " to updateCountList " << endl; |
|
mFolderToUpdateCount.insert( folder->idString(),folder ); |
|
} |
|
if ( !mUpdateCountTimer->isActive() ) |
|
mUpdateCountTimer->start( 500 ); |
|
} |
|
|
|
|
|
void KMFolderTree::slotUpdateCountTimeout() |
|
{ |
|
// kdDebug(5006) << "KMFolderTree::slotUpdateCountTimeout()" << endl; |
|
|
|
QMap<QString,KMFolder*>::iterator it; |
|
for ( it= mFolderToUpdateCount.begin(); |
|
it!=mFolderToUpdateCount.end(); |
|
++it ) |
|
{ |
|
slotUpdateCounts( it.data() ); |
|
} |
|
mFolderToUpdateCount.clear(); |
|
mUpdateCountTimer->stop(); |
|
|
|
} |
|
|
|
void KMFolderTree::slotUpdateCounts(KMFolder * folder) |
|
{ |
|
// kdDebug(5006) << "KMFolderTree::slotUpdateCounts()" << endl; |
|
QListViewItem * current; |
|
if (folder) |
|
current = indexOfFolder(folder); |
|
else |
|
current = currentItem(); |
|
|
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(current); |
|
// sanity check |
|
if (!fti) return; |
|
if (!fti->folder()) fti->setTotalCount(-1); |
|
|
|
// get the unread count |
|
int count = 0; |
|
if (folder && folder->noContent()) // always empty |
|
count = -1; |
|
else { |
|
if ( fti->folder() ) |
|
count = fti->folder()->countUnread(); |
|
} |
|
|
|
// set it |
|
bool repaint = false; |
|
if (fti->unreadCount() != count) { |
|
fti->adjustUnreadCount( count ); |
|
repaint = true; |
|
} |
|
if (isTotalActive()) |
|
{ |
|
// get the total-count |
|
if (fti->folder()->noContent()) |
|
count = -1; |
|
else { |
|
// get the cached count if the folder is not open |
|
count = fti->folder()->count( !fti->folder()->isOpened() ); |
|
} |
|
// set it |
|
if ( count != fti->totalCount() ) { |
|
fti->setTotalCount(count); |
|
repaint = true; |
|
} |
|
} |
|
if ( isSizeActive() ) { |
|
if ( !fti->folder()->noContent()) { |
|
int size = folder->storage()->folderSize(); |
|
if ( size != fti->folderSize() ) { |
|
fti->setFolderSize( size ); |
|
repaint = true; |
|
} |
|
} |
|
} |
|
if ( fti->folderIsCloseToQuota() != folder->storage()->isCloseToQuota() ) { |
|
fti->setFolderIsCloseToQuota( folder->storage()->isCloseToQuota() ); |
|
} |
|
|
|
if (fti->parent() && !fti->parent()->isOpen()) |
|
repaint = false; // we're not visible |
|
if (repaint) { |
|
fti->setNeedsRepaint( true ); |
|
refresh(); |
|
} |
|
// tell the kernel that one of the counts has changed |
|
kmkernel->messageCountChanged(); |
|
} |
|
|
|
void KMFolderTree::updatePopup() const |
|
{ |
|
mPopup->setItemChecked( mUnreadPop, isUnreadActive() ); |
|
mPopup->setItemChecked( mTotalPop, isTotalActive() ); |
|
mPopup->setItemChecked( mSizePop, isSizeActive() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::toggleColumn(int column, bool openFolders) |
|
{ |
|
if (column == unread) |
|
{ |
|
// switch unread |
|
if ( isUnreadActive() ) |
|
{ |
|
removeUnreadColumn(); |
|
reload(); |
|
} else { |
|
addUnreadColumn( i18n("Unread"), 70 ); |
|
reload(); |
|
} |
|
// toggle KPopupMenu |
|
mPopup->setItemChecked( mUnreadPop, isUnreadActive() ); |
|
|
|
} else if (column == total) { |
|
// switch total |
|
if ( isTotalActive() ) |
|
{ |
|
removeTotalColumn(); |
|
reload(); |
|
} else { |
|
addTotalColumn( i18n("Total"), 70 ); |
|
reload(openFolders); |
|
} |
|
mPopup->setItemChecked( mTotalPop, isTotalActive() ); |
|
} else if (column == foldersize) { |
|
// switch total |
|
if ( isSizeActive() ) |
|
{ |
|
removeSizeColumn(); |
|
reload(); |
|
} else { |
|
addSizeColumn( i18n("Size"), 70 ); |
|
reload( openFolders ); |
|
} |
|
// toggle KPopupMenu |
|
mPopup->setItemChecked( mSizePop, isSizeActive() ); |
|
|
|
} else kdDebug(5006) << "unknown column:" << column << endl; |
|
|
|
// toggles the switches of the mainwin |
|
emit columnsChanged(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotToggleUnreadColumn() |
|
{ |
|
toggleColumn(unread); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotToggleTotalColumn() |
|
{ |
|
// activate the total-column and force the folders to be opened |
|
toggleColumn(total, true); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotToggleSizeColumn() |
|
{ |
|
// activate the size-column and force the folders to be opened |
|
toggleColumn(foldersize, true); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMFolderTree::eventFilter( QObject *o, QEvent *e ) |
|
{ |
|
if ( e->type() == QEvent::MouseButtonPress && |
|
static_cast<QMouseEvent*>(e)->button() == RightButton && |
|
o->isA("QHeader") ) |
|
{ |
|
mPopup->popup( static_cast<QMouseEvent*>(e)->globalPos() ); |
|
return true; |
|
} |
|
return KFolderTree::eventFilter(o, e); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotCheckMail() |
|
{ |
|
if (!currentItem()) |
|
return; |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(currentItem()); |
|
KMFolder* folder = fti->folder(); |
|
if (folder && folder->folderType() == KMFolderTypeImap) |
|
{ |
|
KMAccount* acct = static_cast<KMFolderImap*>(folder->storage())->account(); |
|
kmkernel->acctMgr()->singleCheckMail(acct, true); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotNewMessageToMailingList() |
|
{ |
|
KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( currentItem() ); |
|
if ( !fti || !fti->folder() ) |
|
return; |
|
KMCommand *command = new KMMailingListPostCommand( this, fti->folder() ); |
|
command->start(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::createFolderList( QStringList *str, |
|
QValueList<QGuardedPtr<KMFolder> > *folders, |
|
bool localFolders, |
|
bool imapFolders, |
|
bool dimapFolders, |
|
bool searchFolders, |
|
bool includeNoContent, |
|
bool includeNoChildren ) |
|
{ |
|
for ( QListViewItemIterator it( this ) ; it.current() ; ++it ) |
|
{ |
|
KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current()); |
|
if (!fti || !fti->folder()) continue; |
|
// type checks |
|
KMFolder* folder = fti->folder(); |
|
if (!imapFolders && folder->folderType() == KMFolderTypeImap) continue; |
|
if (!dimapFolders && folder->folderType() == KMFolderTypeCachedImap) continue; |
|
if (!localFolders && (folder->folderType() == KMFolderTypeMbox || |
|
folder->folderType() == KMFolderTypeMaildir)) continue; |
|
if (!searchFolders && folder->folderType() == KMFolderTypeSearch) continue; |
|
if (!includeNoContent && folder->noContent()) continue; |
|
if (!includeNoChildren && folder->noChildren()) continue; |
|
QString prefix; |
|
prefix.fill( ' ', 2 * fti->depth() ); |
|
str->append(prefix + fti->text(0)); |
|
folders->append(fti->folder()); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::slotResetFolderList( QListViewItem* item, bool startList ) |
|
{ |
|
if ( !item ) |
|
item = currentItem(); |
|
|
|
KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( item ); |
|
if ( fti && fti->folder() && |
|
fti->folder()->folderType() == KMFolderTypeImap ) |
|
{ |
|
KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() ); |
|
folder->setSubfolderState( KMFolderImap::imapNoInformation ); |
|
if ( startList ) |
|
folder->listDirectory(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::showFolder( KMFolder* folder ) |
|
{ |
|
if ( !folder ) return; |
|
QListViewItem* item = indexOfFolder( folder ); |
|
if ( item ) |
|
{ |
|
doFolderSelected( item ); |
|
ensureItemVisible( item ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::folderToPopupMenu( MenuAction action, QObject *receiver, |
|
KMMenuToFolder *aMenuToFolder, QPopupMenu *menu, QListViewItem *item ) |
|
{ |
|
while ( menu->count() ) |
|
{ |
|
QPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup(); |
|
if ( popup ) |
|
delete popup; |
|
else |
|
menu->removeItemAt( 0 ); |
|
} |
|
// connect the signals |
|
if ( action == MoveMessage || action == MoveFolder ) |
|
{ |
|
disconnect( menu, SIGNAL(activated(int)), receiver, |
|
SLOT(moveSelectedToFolder(int)) ); |
|
connect( menu, SIGNAL(activated(int)), receiver, |
|
SLOT(moveSelectedToFolder(int)) ); |
|
} else { |
|
disconnect( menu, SIGNAL(activated(int)), receiver, |
|
SLOT(copySelectedToFolder(int)) ); |
|
connect( menu, SIGNAL(activated(int)), receiver, |
|
SLOT(copySelectedToFolder(int)) ); |
|
} |
|
if ( !item ) { |
|
item = firstChild(); |
|
|
|
// avoid a popup menu with the single entry 'Local Folders' if there |
|
// are no IMAP accounts |
|
if ( childCount() == 2 && action != MoveFolder ) { // only 'Local Folders' and 'Searches' |
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( item ); |
|
if ( fti->protocol() == KFolderTreeItem::Search ) { |
|
// skip 'Searches' |
|
item = item->nextSibling(); |
|
fti = static_cast<KMFolderTreeItem*>( item ); |
|
} |
|
folderToPopupMenu( action, receiver, aMenuToFolder, menu, fti->firstChild() ); |
|
return; |
|
} |
|
} |
|
|
|
while ( item ) |
|
{ |
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( item ); |
|
if ( fti->protocol() == KFolderTreeItem::Search ) |
|
{ |
|
// skip search folders |
|
item = item->nextSibling(); |
|
continue; |
|
} |
|
QString label = fti->text( 0 ); |
|
label.replace( "&","&&" ); |
|
if ( fti->firstChild() ) |
|
{ |
|
// new level |
|
QPopupMenu* popup = new QPopupMenu( menu, "subMenu" ); |
|
folderToPopupMenu( action, receiver, aMenuToFolder, popup, fti->firstChild() ); |
|
bool subMenu = false; |
|
if ( ( action == MoveMessage || action == CopyMessage ) && |
|
fti->folder() && !fti->folder()->noContent() ) |
|
subMenu = true; |
|
if ( ( action == MoveFolder || action == CopyFolder ) |
|
&& ( !fti->folder() || ( fti->folder() && !fti->folder()->noChildren() ) ) ) |
|
subMenu = true; |
|
|
|
QString sourceFolderName; |
|
KMFolderTreeItem* srcItem = dynamic_cast<KMFolderTreeItem*>( currentItem() ); |
|
if ( srcItem ) |
|
sourceFolderName = srcItem->text( 0 ); |
|
|
|
if ( (action == MoveFolder || action == CopyFolder) |
|
&& fti->folder() && fti->folder()->child() |
|
&& fti->folder()->child()->hasNamedFolder( sourceFolderName ) ) { |
|
subMenu = false; |
|
} |
|
|
|
if ( subMenu ) |
|
{ |
|
int menuId; |
|
if ( action == MoveMessage || action == MoveFolder ) |
|
menuId = popup->insertItem( i18n("Move to This Folder"), -1, 0 ); |
|
else |
|
menuId = popup->insertItem( i18n("Copy to This Folder"), -1, 0 ); |
|
popup->insertSeparator( 1 ); |
|
aMenuToFolder->insert( menuId, fti->folder() ); |
|
} |
|
menu->insertItem( label, popup ); |
|
} else |
|
{ |
|
// insert an item |
|
int menuId = menu->insertItem( label ); |
|
if ( fti->folder() ) |
|
aMenuToFolder->insert( menuId, fti->folder() ); |
|
bool enabled = (fti->folder() ? true : false); |
|
if ( fti->folder() && |
|
( fti->folder()->isReadOnly() || fti->folder()->noContent() ) ) |
|
enabled = false; |
|
menu->setItemEnabled( menuId, enabled ); |
|
} |
|
|
|
item = item->nextSibling(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::moveSelectedToFolder( int menuId ) |
|
{ |
|
moveOrCopyFolder( selectedFolders(), mMenuToFolder[ menuId ], true /*move*/ ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::copySelectedToFolder( int menuId ) |
|
{ |
|
moveOrCopyFolder( selectedFolders(), mMenuToFolder[ menuId ], false /*copy, don't move*/ ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolderTree::moveOrCopyFolder( QValueList<QGuardedPtr<KMFolder> > sources, KMFolder* destination, bool move ) |
|
{ |
|
kdDebug(5006) << k_funcinfo << "source: " << sources << " destination: " << destination << " move: " << move << endl; |
|
|
|
// Disable drag during copy operation since it prevents from many crashes |
|
setDragEnabled( false ); |
|
|
|
KMFolderDir* parent = &(kmkernel->folderMgr()->dir()); |
|
if ( destination ) |
|
parent = destination->createChildFolder(); |
|
|
|
QStringList sourceFolderNames; |
|
|
|
// check if move/copy is possible at all |
|
for ( QValueList<QGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); it != sources.constEnd(); ++it ) { |
|
KMFolder* source = *it; |
|
|
|
// check if folder with same name already exits |
|
QString sourceFolderName; |
|
if ( source ) |
|
sourceFolderName = source->label(); |
|
|
|
if ( parent->hasNamedFolder( sourceFolderName ) || sourceFolderNames.contains( sourceFolderName ) ) { |
|
KMessageBox::error( this, i18n("<qt>Cannot move or copy folder <b>%1</b> here because a folder with the same name already exists.</qt>") |
|
.arg( sourceFolderName ) ); |
|
return; |
|
} |
|
sourceFolderNames.append( sourceFolderName ); |
|
|
|
// don't move/copy a folder that's still not completely moved/copied |
|
KMFolder *f = source; |
|
while ( f ) { |
|
if ( f->moveInProgress() ) { |
|
KMessageBox::error( this, i18n("<qt>Cannot move or copy folder <b>%1</b> because it is not completely copied itself.</qt>") |
|
.arg( sourceFolderName ) ); |
|
return; |
|
} |
|
if ( f->parent() ) |
|
f = f->parent()->owner(); |
|
} |
|
|
|
QString message = |
|
i18n( "<qt>Cannot move or copy folder <b>%1</b> into a subfolder below itself.</qt>" ). |
|
arg( sourceFolderName ); |
|
KMFolderDir* folderDir = parent; |
|
// check that the folder can be moved |
|
if ( source && source->child() ) |
|
{ |
|
while ( folderDir && ( folderDir != &kmkernel->folderMgr()->dir() ) && |
|
( folderDir != source->parent() ) ) |
|
{ |
|
if ( folderDir->findRef( source ) != -1 ) |
|
{ |
|
KMessageBox::error( this, message ); |
|
return; |
|
} |
|
folderDir = folderDir->parent(); |
|
} |
|
} |
|
|
|
if( source && source->child() && parent && |
|
( parent->path().find( source->child()->path() + "/" ) == 0 ) ) { |
|
KMessageBox::error( this, message ); |
|
return; |
|
} |
|
|
|
if( source && source->child() |
|
&& ( parent == source->child() ) ) { |
|
KMessageBox::error( this, message ); |
|
return; |
|
} |
|
} |
|
|
|
// check if the source folders are independent of each other |
|
for ( QValueList<QGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); move && it != sources.constEnd(); ++it ) { |
|
KMFolderDir *parentDir = (*it)->child(); |
|
if ( !parentDir ) |
|
continue; |
|
for ( QValueList<QGuardedPtr<KMFolder> >::ConstIterator it2 = sources.constBegin(); it2 != sources.constEnd(); ++it2 ) { |
|
if ( *it == *it2 ) |
|
continue; |
|
KMFolderDir *childDir = (*it2)->parent(); |
|
do { |
|
if ( parentDir == childDir || parentDir->findRef( childDir->owner() ) != -1 ) { |
|
KMessageBox::error( this, i18n("Moving the selected folders is not possible") ); |
|
return; |
|
} |
|
childDir = childDir->parent(); |
|
} |
|
while ( childDir && childDir != &kmkernel->folderMgr()->dir() ); |
|
} |
|
} |
|
|
|
// de-select moved source folders (can cause crash due to unGetMsg() in KMHeaders) |
|
if ( move ) { |
|
doFolderSelected( indexOfFolder( destination ), false ); |
|
oldCurrent = currentItem(); |
|
} |
|
|
|
// do the actual move/copy |
|
for ( QValueList<QGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); it != sources.constEnd(); ++it ) { |
|
KMFolder* source = *it; |
|
if ( move ) { |
|
kdDebug(5006) << "move folder " << (source ? source->label(): "Unknown") << " to " |
|
<< ( destination ? destination->label() : "Local Folders" ) << endl; |
|
kmkernel->folderMgr()->moveFolder( source, parent ); |
|
} else { |
|
kmkernel->folderMgr()->copyFolder( source, parent ); |
|
} |
|
} |
|
} |
|
|
|
QDragObject * KMFolderTree::dragObject() |
|
{ |
|
KMFolderTreeItem *item = static_cast<KMFolderTreeItem*> |
|
(itemAt(viewport()->mapFromGlobal(QCursor::pos()))); |
|
if ( !item || !item->parent() || !item->folder() ) // top-level items or something invalid |
|
return 0; |
|
mCopySourceFolders = selectedFolders(); |
|
|
|
QDragObject *drag = KFolderTree::dragObject(); |
|
if ( drag ) |
|
drag->setPixmap( SmallIcon("folder") ); |
|
return drag; |
|
} |
|
|
|
void KMFolderTree::copyFolder() |
|
{ |
|
KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() ); |
|
if ( item ) { |
|
mCopySourceFolders = selectedFolders(); |
|
mCutFolder = false; |
|
} |
|
updateCopyActions(); |
|
} |
|
|
|
void KMFolderTree::cutFolder() |
|
{ |
|
KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() ); |
|
if ( item ) { |
|
mCopySourceFolders = selectedFolders(); |
|
mCutFolder = true; |
|
} |
|
updateCopyActions(); |
|
} |
|
|
|
void KMFolderTree::pasteFolder() |
|
{ |
|
KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() ); |
|
if ( !mCopySourceFolders.isEmpty() && item && !mCopySourceFolders.contains( item->folder() ) ) { |
|
moveOrCopyFolder( mCopySourceFolders, item->folder(), mCutFolder ); |
|
if ( mCutFolder ) |
|
mCopySourceFolders.clear(); |
|
} |
|
updateCopyActions(); |
|
} |
|
|
|
void KMFolderTree::updateCopyActions() |
|
{ |
|
KAction *copy = mMainWidget->action("copy_folder"); |
|
KAction *cut = mMainWidget->action("cut_folder"); |
|
KAction *paste = mMainWidget->action("paste_folder"); |
|
KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() ); |
|
|
|
if ( !item || !item->folder() ) { |
|
copy->setEnabled( false ); |
|
cut->setEnabled( false ); |
|
} else { |
|
copy->setEnabled( true ); |
|
cut->setEnabled( item->folder()->isMoveable() ); |
|
} |
|
|
|
if ( mCopySourceFolders.isEmpty() ) |
|
paste->setEnabled( false ); |
|
else |
|
paste->setEnabled( true ); |
|
} |
|
|
|
void KMFolderTree::slotAddToFavorites() |
|
{ |
|
QValueList<QGuardedPtr<KMFolder> > folders = selectedFolders(); |
|
KMail::FavoriteFolderView *favView = mMainWidget->favoriteFolderView(); |
|
assert( favView ); |
|
for ( QValueList<QGuardedPtr<KMFolder> >::ConstIterator it = folders.constBegin(); it != folders.constEnd(); ++it ) |
|
favView->addFolder( *it ); |
|
} |
|
|
|
void KMFolderTree::slotUnhideLocalInbox() |
|
{ |
|
disconnect( kmkernel->inboxFolder(), SIGNAL(msgAdded(KMFolder*,Q_UINT32)), |
|
this, SLOT(slotUnhideLocalInbox()) ); |
|
reload(); |
|
} |
|
|
|
#include "kmfoldertree.moc"
|
|
|