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.
2190 lines
70 KiB
2190 lines
70 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 "folderviewtooltip.h"
|
|
using KMail::FolderViewToolTip;
|
|
|
|
#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 <tqpainter.h>
|
|
#include <tqcursor.h>
|
|
#include <tqregexp.h>
|
|
#include <tqpopupmenu.h>
|
|
|
|
#include <unistd.h>
|
|
#include <assert.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <fixx11h.h>
|
|
|
|
//=============================================================================
|
|
|
|
KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const TQString & name,
|
|
KFolderTreeItem::Protocol protocol )
|
|
: TQObject( parent, name.latin1() ),
|
|
KFolderTreeItem( parent, name, protocol, Root ),
|
|
mFolder( 0 ), mNeedsRepaint( true )
|
|
{
|
|
init();
|
|
setPixmap( 0, normalIcon( iconSize() ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const TQString & name,
|
|
KMFolder* folder )
|
|
: TQObject( parent, name.latin1() ),
|
|
KFolderTreeItem( parent, name ),
|
|
mFolder( folder ), mNeedsRepaint( true )
|
|
{
|
|
init();
|
|
setPixmap( 0, normalIcon( iconSize() ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
KMFolderTreeItem::KMFolderTreeItem( KFolderTreeItem *parent, const TQString & name,
|
|
KMFolder* folder )
|
|
: TQObject( 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;
|
|
}
|
|
}
|
|
|
|
TQPixmap KMFolderTreeItem::normalIcon(int size) const
|
|
{
|
|
TQString 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:
|
|
{
|
|
//If not a resource folder don't try to use icalIface folder pixmap
|
|
if(kmkernel->iCalIface().isResourceFolder( mFolder ))
|
|
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();
|
|
TQPixmap 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;
|
|
}
|
|
|
|
TQPixmap KMFolderTreeItem::unreadIcon(int size) const
|
|
{
|
|
TQPixmap 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 {
|
|
if( kmkernel->iCalIface().isResourceFolder( mFolder ) )
|
|
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
|
|
KFolderTreeItem::Type newType = type();
|
|
if( kmkernel->iCalIface().isResourceFolder( mFolder ) )
|
|
newType = kmkernel->iCalIface().folderType(mFolder);
|
|
|
|
// reload the folder tree if the type changed, needed because of the
|
|
// various type-dependent folder hiding options
|
|
if ( type() != newType )
|
|
static_cast<KMFolderTree*>( listView() )->delayedReload();
|
|
setType( newType );
|
|
|
|
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();
|
|
}
|
|
|
|
void KMFolderTreeItem::slotNoContentChanged()
|
|
{
|
|
// reload the folder tree if the no content state changed, needed because
|
|
// we hide no-content folders if their child nodes are hidden
|
|
TQTimer::singleShot( 0, static_cast<KMFolderTree*>( listView() ), TQT_SLOT(reload()) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool KMFolderTreeItem::acceptDrag(TQDropEvent* e) const
|
|
{
|
|
// Do not allow drags from the favorite folder view, as they don't really
|
|
// make sense and do not work.
|
|
KMMainWidget *mainWidget = static_cast<KMFolderTree*>( listView() )->mainWidget();
|
|
assert( mainWidget );
|
|
if ( mainWidget->favoriteFolderView() &&
|
|
e->source() == mainWidget->favoriteFolderView()->viewport() )
|
|
return false;
|
|
|
|
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();
|
|
delete shorty;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTreeItem::updateCount()
|
|
{
|
|
if ( !folder() ) {
|
|
setTotalCount( -1 );
|
|
return;
|
|
}
|
|
KMail::FolderTreeBase* tree = dynamic_cast<KMail::FolderTreeBase*>( listView() );
|
|
if ( !tree ) return;
|
|
|
|
tree->slotUpdateCounts( folder(), true /* force update */ );
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
KMFolderTree::KMFolderTree( KMMainWidget *mainWidget, TQWidget *parent,
|
|
const char *name )
|
|
: KMail::FolderTreeBase( mainWidget, parent, name )
|
|
, mUpdateTimer( 0, "mUpdateTimer" )
|
|
, autoopen_timer( 0, "autoopen_timer" )
|
|
{
|
|
oldSelected = 0;
|
|
oldCurrent = 0;
|
|
mLastItem = 0;
|
|
dropItem = 0;
|
|
mMainWidget = mainWidget;
|
|
mReloading = false;
|
|
mCutFolder = false;
|
|
|
|
mUpdateCountTimer= new TQTimer( this, "mUpdateCountTimer" );
|
|
|
|
setDragEnabled( true );
|
|
addAcceptableDropMimetype( "application/x-qlistviewitem", false );
|
|
|
|
setSelectionModeExt( Extended );
|
|
|
|
int namecol = addColumn( i18n("Folder"), 250 );
|
|
header()->setStretchEnabled( true, namecol );
|
|
setResizeMode( TQListView::NoColumn );
|
|
// 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, TQT_SLOT(slotToggleUnreadColumn()));
|
|
mTotalPop = mPopup->insertItem(i18n("Total Column"), this, TQT_SLOT(slotToggleTotalColumn()));
|
|
mSizePop = mPopup->insertItem(i18n("Size Column"), this, TQT_SLOT(slotToggleSizeColumn()));
|
|
|
|
connect( this, TQT_SIGNAL( triggerRefresh() ),
|
|
this, TQT_SLOT( refresh() ) );
|
|
|
|
new FolderViewToolTip( this );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// connects all needed signals to their slots
|
|
void KMFolderTree::connectSignals()
|
|
{
|
|
connect( mUpdateCountTimer, TQT_SIGNAL(timeout()),
|
|
this, TQT_SLOT(slotUpdateCountTimeout()) );
|
|
|
|
connect(&mUpdateTimer, TQT_SIGNAL(timeout()),
|
|
this, TQT_SLOT(delayedUpdate()));
|
|
|
|
connect(kmkernel->folderMgr(), TQT_SIGNAL(changed()),
|
|
this, TQT_SLOT(doFolderListChanged()));
|
|
|
|
connect(kmkernel->folderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)),
|
|
this, TQT_SLOT(slotFolderRemoved(KMFolder*)));
|
|
|
|
connect(kmkernel->folderMgr(), TQT_SIGNAL(folderMoveOrCopyOperationFinished()),
|
|
this, TQT_SLOT(slotFolderMoveOrCopyOperationFinished()));
|
|
|
|
connect(kmkernel->imapFolderMgr(), TQT_SIGNAL(changed()),
|
|
this, TQT_SLOT(doFolderListChanged()));
|
|
|
|
connect(kmkernel->imapFolderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)),
|
|
this, TQT_SLOT(slotFolderRemoved(KMFolder*)));
|
|
|
|
connect(kmkernel->dimapFolderMgr(), TQT_SIGNAL(changed()),
|
|
this, TQT_SLOT(doFolderListChanged()));
|
|
|
|
connect(kmkernel->dimapFolderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)),
|
|
this, TQT_SLOT(slotFolderRemoved(KMFolder*)));
|
|
|
|
connect(kmkernel->searchFolderMgr(), TQT_SIGNAL(changed()),
|
|
this, TQT_SLOT(doFolderListChanged()));
|
|
|
|
connect(kmkernel->acctMgr(), TQT_SIGNAL(accountRemoved(KMAccount*)),
|
|
this, TQT_SLOT(slotAccountRemoved(KMAccount*)));
|
|
|
|
connect(kmkernel->acctMgr(), TQT_SIGNAL(accountAdded(KMAccount*)),
|
|
this, TQT_SLOT(slotUnhideLocalInbox()));
|
|
|
|
connect(kmkernel->searchFolderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)),
|
|
this, TQT_SLOT(slotFolderRemoved(KMFolder*)));
|
|
|
|
connect( &autoopen_timer, TQT_SIGNAL( timeout() ),
|
|
this, TQT_SLOT( openFolder() ) );
|
|
|
|
connect( this, TQT_SIGNAL( contextMenuRequested( TQListViewItem*, const TQPoint &, int ) ),
|
|
this, TQT_SLOT( slotContextMenuRequested( TQListViewItem*, const TQPoint & ) ) );
|
|
|
|
connect( this, TQT_SIGNAL( expanded( TQListViewItem* ) ),
|
|
this, TQT_SLOT( slotFolderExpanded( TQListViewItem* ) ) );
|
|
|
|
connect( this, TQT_SIGNAL( collapsed( TQListViewItem* ) ),
|
|
this, TQT_SLOT( slotFolderCollapsed( TQListViewItem* ) ) );
|
|
|
|
connect( this, TQT_SIGNAL( itemRenamed( TQListViewItem*, int, const TQString &)),
|
|
this, TQT_SLOT( slotRenameFolder( TQListViewItem*, int, const TQString &)));
|
|
|
|
connect( this, TQT_SIGNAL(folderSelected(KMFolder*)), TQT_SLOT(updateCopyActions()) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTree::readConfig (void)
|
|
{
|
|
KConfig* conf = KMKernel::config();
|
|
|
|
readColorConfig();
|
|
|
|
// Custom/Ssystem font support
|
|
{
|
|
KConfigGroupSaver saver(conf, "Fonts");
|
|
if (!conf->readBoolEntry("defaultFonts",true)) {
|
|
TQFont 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 ( TQListViewItemIterator 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 ( TQListViewItemIterator 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 = TQListViewItemIterator (this);
|
|
TQTimer::singleShot( 0, this, TQT_SLOT(slotUpdateOneCount()) );
|
|
}
|
|
|
|
for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) {
|
|
KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current());
|
|
if ( !fti || !fti->folder() )
|
|
continue;
|
|
|
|
disconnect(fti->folder(),TQT_SIGNAL(iconsChanged()),
|
|
fti,TQT_SLOT(slotIconsChanged()));
|
|
connect(fti->folder(),TQT_SIGNAL(iconsChanged()),
|
|
fti,TQT_SLOT(slotIconsChanged()));
|
|
|
|
disconnect(fti->folder(),TQT_SIGNAL(nameChanged()),
|
|
fti,TQT_SLOT(slotNameChanged()));
|
|
connect(fti->folder(),TQT_SIGNAL(nameChanged()),
|
|
fti,TQT_SLOT(slotNameChanged()));
|
|
|
|
disconnect( fti->folder(), TQT_SIGNAL(noContentChanged()),
|
|
fti, TQT_SLOT(slotNoContentChanged()) );
|
|
connect( fti->folder(), TQT_SIGNAL(noContentChanged()),
|
|
fti, TQT_SLOT(slotNoContentChanged()) );
|
|
|
|
disconnect( fti->folder(), TQT_SIGNAL(syncStateChanged()),
|
|
this, TQT_SLOT(slotSyncStateChanged()) );
|
|
connect( fti->folder(), TQT_SIGNAL(syncStateChanged()),
|
|
this, TQT_SLOT(slotSyncStateChanged()) );
|
|
|
|
// we want to be noticed of changes to update the unread/total columns
|
|
disconnect(fti->folder(), TQT_SIGNAL(msgAdded(KMFolder*,Q_UINT32)),
|
|
this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
|
|
connect(fti->folder(), TQT_SIGNAL(msgAdded(KMFolder*,Q_UINT32)),
|
|
this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
|
|
//}
|
|
|
|
disconnect(fti->folder(), TQT_SIGNAL(numUnreadMsgsChanged(KMFolder*)),
|
|
this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
|
|
connect(fti->folder(), TQT_SIGNAL(numUnreadMsgsChanged(KMFolder*)),
|
|
this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
|
|
disconnect(fti->folder(), TQT_SIGNAL(msgRemoved(KMFolder*)),
|
|
this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
|
|
connect(fti->folder(), TQT_SIGNAL(msgRemoved(KMFolder*)),
|
|
this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
|
|
|
|
disconnect(fti->folder(), TQT_SIGNAL(folderSizeChanged( KMFolder* )),
|
|
this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
|
|
connect(fti->folder(), TQT_SIGNAL(folderSizeChanged( KMFolder* )),
|
|
this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
|
|
|
|
|
|
|
|
disconnect(fti->folder(), TQT_SIGNAL(shortcutChanged(KMFolder*)),
|
|
mMainWidget, TQT_SLOT( slotShortcutChanged(KMFolder*)));
|
|
connect(fti->folder(), TQT_SIGNAL(shortcutChanged(KMFolder*)),
|
|
mMainWidget, TQT_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 ( TQListViewItemIterator 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
|
|
TQTimer::singleShot( 0, this, TQT_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");
|
|
|
|
TQTimer::singleShot( 0, this, TQT_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 );
|
|
|
|
// add child-folders
|
|
if (folder && folder->child()) {
|
|
addDirectory( folder->child(), fti );
|
|
}
|
|
} else {
|
|
// hide local inbox if unused
|
|
if ( kmkernel->inboxFolder() == folder && hideLocalInbox() ) {
|
|
connect( kmkernel->inboxFolder(), TQT_SIGNAL(msgAdded(KMFolder*,Q_UINT32)), TQT_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 );
|
|
}
|
|
|
|
// add child-folders
|
|
if (folder && folder->child()) {
|
|
addDirectory( folder->child(), fti );
|
|
}
|
|
|
|
// Check if this is an IMAP resource folder or a no-content parent only
|
|
// containing groupware folders
|
|
if ( (kmkernel->iCalIface().hideResourceFolder( folder ) || folder->noContent())
|
|
&& fti->childCount() == 0 ) {
|
|
// It is
|
|
removeFromFolderToItemMap( folder );
|
|
delete fti;
|
|
// still, it might change in the future, so we better check the change signals
|
|
connect ( folder, TQT_SIGNAL(noContentChanged()), TQT_SLOT(delayedReload()) );
|
|
continue;
|
|
}
|
|
|
|
connect (fti, TQT_SIGNAL(iconChanged(KMFolderTreeItem*)),
|
|
this, TQT_SIGNAL(iconChanged(KMFolderTreeItem*)));
|
|
connect (fti, TQT_SIGNAL(nameChanged(KMFolderTreeItem*)),
|
|
this, TQT_SIGNAL(nameChanged(KMFolderTreeItem*)));
|
|
}
|
|
// restore last open-state
|
|
fti->setOpen( readIsListViewItemOpen(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 ( TQListViewItemIterator 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)
|
|
{
|
|
TQListViewItem *item = indexOfFolder(aFolder);
|
|
if (!item) return;
|
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*> ( item );
|
|
if ( oldCurrent == fti )
|
|
oldCurrent = 0;
|
|
if ( oldSelected == fti )
|
|
oldSelected = 0;
|
|
if (!fti || !fti->folder()) return;
|
|
if (fti == currentItem())
|
|
{
|
|
TQListViewItem *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 ( TQListViewItem * parent = fti->parent() ; parent ; parent = parent->parent() )
|
|
parent->setOpen( true );
|
|
ensureItemVisible( fti );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTree::nextUnreadFolder()
|
|
{
|
|
nextUnreadFolder( false );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTree::nextUnreadFolder(bool confirm)
|
|
{
|
|
TQListViewItemIterator 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()
|
|
{
|
|
TQListViewItemIterator 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()
|
|
{
|
|
TQListViewItemIterator it( currentItem() );
|
|
++it;
|
|
KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
|
|
if (fti) {
|
|
prepareItem( fti );
|
|
setFocus();
|
|
setCurrentItem( fti );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTree::decCurrentFolder()
|
|
{
|
|
TQListViewItemIterator 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;
|
|
}
|
|
|
|
TQValueList<TQGuardedPtr<KMFolder> > KMFolderTree::selectedFolders()
|
|
{
|
|
TQValueList<TQGuardedPtr<KMFolder> > rv;
|
|
for ( TQListViewItemIterator 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( TQListViewItem* 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(TQResizeEvent* e)
|
|
{
|
|
KConfig* conf = KMKernel::config();
|
|
|
|
KConfigGroupSaver saver(conf, "Geometry");
|
|
conf->writeEntry(name(), size().width());
|
|
|
|
KListView::resizeEvent(e);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// show context menu
|
|
void KMFolderTree::slotContextMenuRequested( TQListViewItem *lvi,
|
|
const TQPoint &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())))
|
|
{
|
|
TQString 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,
|
|
TQT_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,
|
|
TQT_SLOT(slotCheckMail()));
|
|
}
|
|
} else { // regular folders
|
|
|
|
folderMenu->insertSeparator();
|
|
if ( !fti->folder()->noChildren() && !multiFolder ) {
|
|
folderMenu->insertItem(SmallIconSet("folder_new"),
|
|
i18n("&New Subfolder..."), this,
|
|
TQT_SLOT(addChildFolder()));
|
|
}
|
|
|
|
// copy folder
|
|
TQPopupMenu *copyMenu = new TQPopupMenu( folderMenu );
|
|
folderToPopupMenu( CopyFolder, this, &mMenuToFolder, copyMenu );
|
|
folderMenu->insertItem( i18n("&Copy Folder To"), copyMenu );
|
|
|
|
if ( fti->folder()->isMoveable() && fti->folder()->canDeleteMessages() )
|
|
{
|
|
TQPopupMenu *moveMenu = new TQPopupMenu( 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( "archive_folder" )->plug( folderMenu );
|
|
|
|
mMainWidget->action("compact")->plug(folderMenu);
|
|
|
|
if ( GlobalSettings::self()->enableFavoriteFolderView() ) {
|
|
folderMenu->insertItem( SmallIconSet("bookmark_add"), i18n("Add to Favorite Folders"),
|
|
this, TQT_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("Serverside Subscription..."), mMainWidget,
|
|
TQT_SLOT(slotSubscriptionDialog()));
|
|
folderMenu->insertItem(SmallIcon("bookmark_folder"),
|
|
i18n("Local Subscription..."), mMainWidget,
|
|
TQT_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,
|
|
TQT_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, TQT_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,
|
|
TQT_SLOT(assignShortcut()));
|
|
|
|
if ( !fti->folder()->noContent() && fti->folder()->canDeleteMessages() ) {
|
|
folderMenu->insertItem( i18n("Expire..."), fti,
|
|
TQT_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(TQMouseEvent * 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(TQMouseEvent* me)
|
|
{
|
|
TQListViewItem *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->userRightsState() != KMail::ACLJobs::Ok || // hack, we should get the acls
|
|
( imapFolder->userRightsState() == KMail::ACLJobs::Ok &&
|
|
( imapFolder->userRights() & KMail::ACLJobs::Create ) );
|
|
} else if ( folder && folder->folderType() == KMFolderTypeCachedImap ) {
|
|
const KMFolderCachedImap *dimapFolder = static_cast<const KMFolderCachedImap*>( folder->storage() );
|
|
createRights = dimapFolder->userRightsState() != KMail::ACLJobs::Ok ||
|
|
( dimapFolder->userRightsState() == KMail::ACLJobs::Ok &&
|
|
( dimapFolder->userRights() & KMail::ACLJobs::Create ) );
|
|
}
|
|
return createRights;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Create a subfolder.
|
|
// Requires creating the appropriate subdirectory and show a dialog
|
|
void KMFolderTree::addChildFolder( KMFolder *folder, TQWidget * 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 ) ) {
|
|
const TQString message = i18n( "<qt>Cannot create folder under <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
|
|
TQListViewItem *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();
|
|
TQString 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();
|
|
TQString 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();
|
|
TQStringList existingFolders;
|
|
TQListViewItemIterator fldIt(this);
|
|
TQMap<TQString,bool> folderMap;
|
|
KMFolderTreeItem *fti;
|
|
for (TQListViewItemIterator fldIt(this); fldIt.current(); fldIt++)
|
|
{
|
|
fti = static_cast<KMFolderTreeItem*>(fldIt.current());
|
|
if (fti && fti->folder())
|
|
folderMap.insert(fti->folder()->idString(), true);
|
|
}
|
|
TQStringList groupList = config->groupList();
|
|
TQString name;
|
|
for (TQStringList::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
|
|
if ( folder->noContent() )
|
|
continue; // we hide nocontent folders if they have no child folders
|
|
if ( folder == kmkernel->inboxFolder() )
|
|
continue; // local inbox can be hidden as well
|
|
}
|
|
|
|
//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( TQDragEnterEvent *e )
|
|
{
|
|
oldCurrent = 0;
|
|
oldSelected = 0;
|
|
|
|
oldCurrent = currentItem();
|
|
for ( TQListViewItemIterator it( this ) ; it.current() ; ++it )
|
|
if ( it.current()->isSelected() )
|
|
oldSelected = it.current();
|
|
|
|
setFocus();
|
|
|
|
TQListViewItem *i = itemAt( contentsToViewport(e->pos()) );
|
|
if ( i ) {
|
|
dropItem = i;
|
|
autoopen_timer.start( autoopenTime );
|
|
}
|
|
else
|
|
dropItem = 0;
|
|
|
|
e->accept( acceptDrag(e) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTree::contentsDragMoveEvent( TQDragMoveEvent *e )
|
|
{
|
|
TQPoint vp = contentsToViewport(e->pos());
|
|
TQListViewItem *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 TQDropEvent::Copy:
|
|
break;
|
|
case TQDropEvent::Move:
|
|
e->acceptAction();
|
|
break;
|
|
case TQDropEvent::Link:
|
|
e->acceptAction();
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
} else {
|
|
e->accept( false );
|
|
}
|
|
} else {
|
|
e->accept( false );
|
|
autoopen_timer.stop();
|
|
dropItem = 0;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTree::contentsDragLeaveEvent( TQDragLeaveEvent * )
|
|
{
|
|
if (!oldCurrent) return;
|
|
|
|
autoopen_timer.stop();
|
|
dropItem = 0;
|
|
|
|
setCurrentItem( oldCurrent );
|
|
if ( oldSelected )
|
|
setSelected( oldSelected, true );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTree::contentsDropEvent( TQDropEvent *e )
|
|
{
|
|
autoopen_timer.stop();
|
|
|
|
TQListViewItem *item = itemAt( contentsToViewport(e->pos()) );
|
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
|
|
// Check that each pointer is not null
|
|
for ( TQValueList<TQGuardedPtr<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() ) )
|
|
{
|
|
if ( e->provides("application/x-qlistviewitem") ) {
|
|
int action = dndMode( true /* always ask */ );
|
|
if ( (action == DRAG_COPY || action == DRAG_MOVE) && !mCopySourceFolders.isEmpty() ) {
|
|
for ( TQValueList<TQGuardedPtr<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() ) {
|
|
int action;
|
|
if ( mMainWidget->headers()->folder() && mMainWidget->headers()->folder()->isReadOnly() )
|
|
action = DRAG_COPY;
|
|
else
|
|
action = dndMode();
|
|
// 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 {
|
|
handleMailListDrop( e, fti->folder() );
|
|
}
|
|
}
|
|
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( TQListViewItem * 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() || ( !folder->account()->listOnlyOpenFolders() &&
|
|
fti->parent() ) )
|
|
return;
|
|
if ( folder->getSubfolderState() == KMFolderImap::imapNoInformation )
|
|
{
|
|
// check if all parents are expanded
|
|
TQListViewItem *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( TQListViewItem * 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(TQListViewItem *item, int col,
|
|
const TQString &text)
|
|
{
|
|
|
|
KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
|
|
|
|
if ((!fti) || (fti && fti->folder() && col != 0 && !currentFolder()->child()))
|
|
return;
|
|
|
|
TQString fldName, oldFldName;
|
|
|
|
oldFldName = fti->name(0);
|
|
|
|
if (!text.isEmpty())
|
|
fldName = text;
|
|
else
|
|
fldName = oldFldName;
|
|
|
|
fldName.replace("/", "");
|
|
fldName.replace(TQRegExp("^\\."), "");
|
|
|
|
if (fldName.isEmpty())
|
|
fldName = i18n("unnamed");
|
|
|
|
fti->setText(0, fldName);
|
|
fti->folder()->rename(fldName, &(kmkernel->folderMgr()->dir()));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
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;
|
|
|
|
TQMap<TQString,KMFolder*>::iterator it;
|
|
for ( it= mFolderToUpdateCount.begin();
|
|
it!=mFolderToUpdateCount.end();
|
|
++it )
|
|
{
|
|
slotUpdateCounts( it.data() );
|
|
}
|
|
mFolderToUpdateCount.clear();
|
|
mUpdateCountTimer->stop();
|
|
|
|
}
|
|
|
|
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( TQObject *o, TQEvent *e )
|
|
{
|
|
if ( e->type() == TQEvent::MouseButtonPress &&
|
|
static_cast<TQMouseEvent*>(e)->button() == RightButton &&
|
|
o->isA("TQHeader") )
|
|
{
|
|
mPopup->popup( static_cast<TQMouseEvent*>(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->storage() ) {
|
|
if ( KMAccount* acct = 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( TQStringList *str,
|
|
TQValueList<TQGuardedPtr<KMFolder> > *folders,
|
|
bool localFolders,
|
|
bool imapFolders,
|
|
bool dimapFolders,
|
|
bool searchFolders,
|
|
bool includeNoContent,
|
|
bool includeNoChildren )
|
|
{
|
|
for ( TQListViewItemIterator 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;
|
|
TQString prefix;
|
|
prefix.fill( ' ', 2 * fti->depth() );
|
|
str->append(prefix + fti->text(0));
|
|
folders->append(fti->folder());
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTree::slotResetFolderList( TQListViewItem* 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;
|
|
TQListViewItem* item = indexOfFolder( folder );
|
|
if ( item )
|
|
{
|
|
doFolderSelected( item );
|
|
ensureItemVisible( item );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMFolderTree::folderToPopupMenu( MenuAction action, TQObject *receiver,
|
|
KMMenuToFolder *aMenuToFolder, TQPopupMenu *menu, TQListViewItem *item )
|
|
{
|
|
while ( menu->count() )
|
|
{
|
|
TQPopupMenu *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, TQT_SIGNAL(activated(int)), receiver,
|
|
TQT_SLOT(moveSelectedToFolder(int)) );
|
|
connect( menu, TQT_SIGNAL(activated(int)), receiver,
|
|
TQT_SLOT(moveSelectedToFolder(int)) );
|
|
} else {
|
|
disconnect( menu, TQT_SIGNAL(activated(int)), receiver,
|
|
TQT_SLOT(copySelectedToFolder(int)) );
|
|
connect( menu, TQT_SIGNAL(activated(int)), receiver,
|
|
TQT_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;
|
|
}
|
|
TQString label = fti->text( 0 );
|
|
label.replace( "&","&&" );
|
|
if ( fti->firstChild() )
|
|
{
|
|
// new level
|
|
TQPopupMenu* popup = new TQPopupMenu( 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;
|
|
|
|
TQString 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( TQValueList<TQGuardedPtr<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();
|
|
|
|
TQStringList sourceFolderNames;
|
|
|
|
// check if move/copy is possible at all
|
|
for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); it != sources.constEnd(); ++it ) {
|
|
KMFolder* source = *it;
|
|
|
|
// check if folder with same name already exits
|
|
TQString 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 ) );
|
|
setDragEnabled( true );
|
|
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 ) );
|
|
setDragEnabled( true );
|
|
return;
|
|
}
|
|
if ( f->parent() )
|
|
f = f->parent()->owner();
|
|
}
|
|
|
|
TQString 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 );
|
|
setDragEnabled( true );
|
|
return;
|
|
}
|
|
folderDir = folderDir->parent();
|
|
}
|
|
}
|
|
|
|
if( source && source->child() && parent &&
|
|
( parent->path().find( source->child()->path() + "/" ) == 0 ) ) {
|
|
KMessageBox::error( this, message );
|
|
setDragEnabled( true );
|
|
return;
|
|
}
|
|
|
|
if( source && source->child()
|
|
&& ( parent == source->child() ) ) {
|
|
KMessageBox::error( this, message );
|
|
setDragEnabled( true );
|
|
return;
|
|
}
|
|
}
|
|
|
|
// check if the source folders are independent of each other
|
|
for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); move && it != sources.constEnd(); ++it ) {
|
|
KMFolderDir *parentDir = (*it)->child();
|
|
if ( !parentDir )
|
|
continue;
|
|
for ( TQValueList<TQGuardedPtr<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") );
|
|
setDragEnabled( true );
|
|
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 ( TQValueList<TQGuardedPtr<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 );
|
|
}
|
|
}
|
|
}
|
|
|
|
TQDragObject * KMFolderTree::dragObject()
|
|
{
|
|
KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>
|
|
(itemAt(viewport()->mapFromGlobal(TQCursor::pos())));
|
|
if ( !item || !item->parent() || !item->folder() ) // top-level items or something invalid
|
|
return 0;
|
|
mCopySourceFolders = selectedFolders();
|
|
|
|
TQDragObject *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::slotSyncStateChanged()
|
|
{
|
|
// Only emit the signal when a selected folder changes, otherwise the folder menu is updated
|
|
// too often
|
|
TQValueList< TQGuardedPtr<KMFolder> > folders = selectedFolders();
|
|
TQValueList< TQGuardedPtr<KMFolder> >::const_iterator it = folders.constBegin();
|
|
TQValueList< TQGuardedPtr<KMFolder> >::const_iterator end = folders.constEnd();
|
|
while ( it != end ) {
|
|
TQGuardedPtr<KMFolder> folder = *it;
|
|
if ( folder == sender() ) {
|
|
emit syncStateChanged();
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
}
|
|
|
|
void KMFolderTree::slotAddToFavorites()
|
|
{
|
|
KMail::FavoriteFolderView *favView = mMainWidget->favoriteFolderView();
|
|
assert( favView );
|
|
for ( TQListViewItemIterator it( this ); it.current(); ++it ) {
|
|
if ( it.current()->isSelected() )
|
|
favView->addFolder( static_cast<KMFolderTreeItem*>( it.current() ) );
|
|
}
|
|
}
|
|
|
|
void KMFolderTree::slotUnhideLocalInbox()
|
|
{
|
|
disconnect( kmkernel->inboxFolder(), TQT_SIGNAL(msgAdded(KMFolder*,Q_UINT32)),
|
|
this, TQT_SLOT(slotUnhideLocalInbox()) );
|
|
reload();
|
|
}
|
|
|
|
void KMFolderTree::delayedReload()
|
|
{
|
|
TQTimer::singleShot( 0, this, TQT_SLOT(reload()) );
|
|
}
|
|
|
|
#include "kmfoldertree.moc"
|