diff options
Diffstat (limited to 'knode/kncollectionview.cpp')
-rw-r--r-- | knode/kncollectionview.cpp | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/knode/kncollectionview.cpp b/knode/kncollectionview.cpp new file mode 100644 index 000000000..2d48a9e5d --- /dev/null +++ b/knode/kncollectionview.cpp @@ -0,0 +1,457 @@ +/* + KNode, the KDE newsreader + Copyright (c) 2004-2005 Volker Krause <[email protected]> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US +*/ + +#include <qcursor.h> +#include <qheader.h> + +#include <kiconloader.h> +#include <klistview.h> +#include <klocale.h> +#include <kpopupmenu.h> + +#include "knglobals.h" +#include "knconfig.h" +#include "knconfigmanager.h" +#include "knnntpaccount.h" +#include "knaccountmanager.h" +#include "kngroup.h" +#include "kngroupmanager.h" +#include "knfolder.h" +#include "knfoldermanager.h" +#include "headerview.h" +#include "kncollectionview.h" +#include "kncollectionviewitem.h" + +KNCollectionView::KNCollectionView(QWidget *parent, const char* name) : + KFolderTree(parent, name), + mActiveItem( 0 ), + mPopup( 0 ) +{ + setDragEnabled(true); + addAcceptableDropMimetype("x-knode-drag/article", false); + addAcceptableDropMimetype("x-knode-drag/folder", true); + addColumn(i18n("Name"),162); + setDropHighlighter(true); + + // popup menu to enable/disable unread and total 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(toggleUnreadColumn()) ); + mTotalPop = mPopup->insertItem( i18n("Total Column"), this, SLOT(toggleTotalColumn()) ); + + // add unread and total columns if necessary + readConfig(); + + // load accounts and folders + reloadAccounts(); + reloadFolders(); + + // connect to the account manager + KNAccountManager* am = knGlobals.accountManager(); + connect(am, SIGNAL(accountAdded(KNNntpAccount*)), SLOT(addAccount(KNNntpAccount*))); + connect(am, SIGNAL(accountRemoved(KNNntpAccount*)), SLOT(removeAccount(KNNntpAccount*))); + connect(am, SIGNAL(accountModified(KNNntpAccount*)), SLOT(updateAccount(KNNntpAccount*))); + + // connect to the group manager + KNGroupManager* gm = knGlobals.groupManager(); + connect(gm, SIGNAL(groupAdded(KNGroup*)), SLOT(addGroup(KNGroup*))); + connect(gm, SIGNAL(groupRemoved(KNGroup*)), SLOT(removeGroup(KNGroup*))); + connect(gm, SIGNAL(groupUpdated(KNGroup*)), SLOT(updateGroup(KNGroup*))); + + // connect to the folder manager + KNFolderManager* fm = knGlobals.folderManager(); + connect(fm, SIGNAL(folderAdded(KNFolder*)), SLOT(addPendingFolders())); + connect(fm, SIGNAL(folderRemoved(KNFolder*)), SLOT(removeFolder(KNFolder*))); + connect(fm, SIGNAL(folderActivated(KNFolder*)), SLOT(activateFolder(KNFolder*))); + + installEventFilter(this); +} + + +KNCollectionView::~KNCollectionView() +{ + writeConfig(); +} + + + +void KNCollectionView::readConfig() +{ + KConfig *conf = knGlobals.config(); + conf->setGroup( "GroupView" ); + + // execute the listview layout stuff only once + static bool initDone = false; + if (!initDone) { + initDone = true; + const int unreadColumn = conf->readNumEntry("UnreadColumn", 1); + const int totalColumn = conf->readNumEntry("TotalColumn", 2); + + // we need to _activate_ them in the correct order + // this is ugly because we can't use header()->moveSection + // but otherwise the restoreLayout doesn't know that to do + if (unreadColumn != -1 && unreadColumn < totalColumn) + addUnreadColumn( i18n("Unread"), 48 ); + if (totalColumn != -1) + addTotalColumn( i18n("Total"), 36 ); + if (unreadColumn != -1 && unreadColumn > totalColumn) + addUnreadColumn( i18n("Unread"), 48 ); + updatePopup(); + + restoreLayout( knGlobals.config(), "GroupView" ); + } + + // font & color settings + KNConfig::Appearance *app = knGlobals.configManager()->appearance(); + setFont( app->groupListFont() ); + + QPalette p = palette(); + p.setColor( QColorGroup::Base, app->backgroundColor() ); + p.setColor( QColorGroup::Text, app->textColor() ); + setPalette( p ); + setAlternateBackground( app->backgroundColor() ); + // FIXME: make this configurable + mPaintInfo.colUnread = QColor( "blue" ); + mPaintInfo.colFore = app->textColor(); + mPaintInfo.colBack = app->backgroundColor(); +} + + +void KNCollectionView::writeConfig() +{ + KConfig *conf = knGlobals.config(); + conf->setGroup( "GroupView" ); + saveLayout( knGlobals.config(), "GroupView" ); + conf->writeEntry( "UnreadColumn", unreadIndex() ); + conf->writeEntry( "TotalColumn", totalIndex() ); +} + + + +void KNCollectionView::addAccount(KNNntpAccount *a) +{ + // add account item + KNCollectionViewItem* item = new KNCollectionViewItem( this, KFolderTreeItem::News ); + a->setListItem( item ); + item->setOpen( a->wasOpen() ); + + // add groups for this account + QValueList<KNGroup*> groups = knGlobals.groupManager()->groupsOfAccount( a ); + for ( QValueList<KNGroup*>::Iterator it = groups.begin(); it != groups.end(); ++it ) { + KNCollectionViewItem *gitem = new KNCollectionViewItem( item, KFolderTreeItem::News ); + (*it)->setListItem( gitem ); + (*it)->updateListItem(); + } +} + + +void KNCollectionView::removeAccount(KNNntpAccount *a) +{ + if(!a->listItem()) + return; + KNCollectionViewItem *child = 0, *aitem = a->listItem(); + while((child = static_cast<KNCollectionViewItem*>(aitem->firstChild()))) + removeGroup(static_cast<KNGroup*>(child->coll)); + delete aitem; + a->setListItem(0); +} + + +void KNCollectionView::updateAccount(KNNntpAccount *a) +{ + a->updateListItem(); +} + + +void KNCollectionView::reloadAccounts() +{ + KNAccountManager* am = knGlobals.accountManager(); + QValueList<KNNntpAccount*>::Iterator it; + for ( it = am->begin(); it != am->end(); ++it ) { + removeAccount( *it ); + addAccount( *it ); + } +} + + + +void KNCollectionView::addGroup(KNGroup *g) +{ + if (!g->account()->listItem()) + return; + + KNCollectionViewItem *gitem = + new KNCollectionViewItem( g->account()->listItem(), KFolderTreeItem::News ); + g->setListItem(gitem); + updateGroup(g); +} + + +void KNCollectionView::removeGroup(KNGroup *g) +{ + if (!g->listItem()) + return; + + delete g->listItem(); + g->setListItem(0); +} + + +void KNCollectionView::updateGroup(KNGroup *g) +{ + g->updateListItem(); +} + + + +void KNCollectionView::addFolder(KNFolder *f) +{ + KNCollectionViewItem *it; + + if (!f->parent()) { + // root folder + it = new KNCollectionViewItem(this, KFolderTreeItem::Local); + } else { + // make sure the parent folder has already been added + if (!f->parent()->listItem()) + addFolder( static_cast<KNFolder*>(f->parent()) ); + // handle special folders + KFolderTreeItem::Type type = KFolderTreeItem::Other; + switch ( f->id() ) { + case 1: + type = KFolderTreeItem::Drafts; break; + case 2: + type = KFolderTreeItem::Outbox; break; + case 3: + type = KFolderTreeItem::SentMail; break; + } + it = new KNCollectionViewItem( f->parent()->listItem(), KFolderTreeItem::Local, type ); + } + f->setListItem( it ); + updateFolder( f ); +} + + +void KNCollectionView::removeFolder(KNFolder* f) +{ + if(!f->listItem()) + return; + KNCollectionViewItem *child = 0, *it = f->listItem(); + while((child = static_cast<KNCollectionViewItem*>(it->firstChild()))) + removeFolder(static_cast<KNFolder*>(child->coll)); + delete f->listItem(); + f->setListItem(0); +} + + +void KNCollectionView::reloadFolders() +{ + // remove existing folder items + removeFolder(knGlobals.folderManager()->root()); + + // add folder items + addPendingFolders(); +} + + +void KNCollectionView::addPendingFolders() +{ + QValueList<KNFolder*> folders = knGlobals.folderManager()->folders(); + for ( QValueList<KNFolder*>::Iterator it = folders.begin(); it != folders.end(); ++it ) + if ( !(*it)->listItem() ) + addFolder( (*it) ); + // now open the folders if they were open in the last session + for ( QValueList<KNFolder*>::Iterator it = folders.begin(); it != folders.end(); ++it ) + if ( (*it)->listItem()) + (*it)->listItem()->setOpen( (*it)->wasOpen() ); +} + + +void KNCollectionView::activateFolder(KNFolder* f) +{ + if(f->listItem()) + setActive( f->listItem() ); +} + + +void KNCollectionView::updateFolder(KNFolder* f) +{ + f->updateListItem(); +} + + +void KNCollectionView::reload() +{ + reloadAccounts(); + reloadFolders(); +} + +void KNCollectionView::setActive( QListViewItem *i ) +{ + if (!i || mActiveItem == i) + return; + + clearSelection(); + setSelected( i, true ); + setCurrentItem( i ); + mActiveItem = i; + emit( selectionChanged( i ) ); +} + + +void KNCollectionView::nextGroup() +{ + incCurrentFolder(); + setActive( currentItem() ); +} + + +void KNCollectionView::prevGroup() +{ + decCurrentFolder(); + setActive( currentItem() ); +} + + +void KNCollectionView::decCurrentFolder() +{ + QListViewItemIterator it( currentItem() ); + --it; + KFolderTreeItem* fti = static_cast<KFolderTreeItem*>(it.current()); + if (fti) { + ensureItemVisible( fti ); + setFocus(); + setCurrentItem( fti ); + } +} + + +void KNCollectionView::incCurrentFolder() +{ + QListViewItemIterator it( currentItem() ); + ++it; + KFolderTreeItem* fti = static_cast<KFolderTreeItem*>(it.current()); + if (fti) { + ensureItemVisible( fti ); + setFocus(); + setCurrentItem( fti ); + } +} + + +void KNCollectionView::selectCurrentFolder() +{ + KFolderTreeItem* fti = static_cast<KFolderTreeItem*>( currentItem() ); + if (fti) { + ensureItemVisible( fti ); + setActive( fti ); + } +} + + +QDragObject* KNCollectionView::dragObject() +{ + KFolderTreeItem *item = static_cast<KFolderTreeItem*> + (itemAt(viewport()->mapFromGlobal(QCursor::pos()))); + if ( item && item->protocol() == KFolderTreeItem::Local && item->type() == KFolderTreeItem::Other ) { + QDragObject *d = new QStoredDrag( "x-knode-drag/folder", viewport() ); + d->setPixmap( SmallIcon("folder") ); + return d; + } + return 0; +} + + +void KNCollectionView::contentsDropEvent( QDropEvent *e ) +{ + cleanItemHighlighter(); // necessary since we overwrite KListView::contentsDropEvent() + QListViewItem *item = itemAt( contentsToViewport(e->pos()) ); + KNCollectionViewItem *fti = static_cast<KNCollectionViewItem*>(item); + if (fti && (fti->coll) && acceptDrag(e)) { + emit folderDrop( e, fti ); + e->accept( true ); + } + else + e->accept( false ); +} + + + +void KNCollectionView::toggleUnreadColumn() +{ + if ( isUnreadActive() ) + removeUnreadColumn(); + else + addUnreadColumn( i18n("Unread"), 48 ); + mPopup->setItemChecked( mUnreadPop, isUnreadActive() ); + reload(); +} + + +void KNCollectionView::toggleTotalColumn() +{ + if ( isTotalActive() ) + removeTotalColumn(); + else + addTotalColumn( i18n("Total"), 36 ); + mPopup->setItemChecked( mTotalPop, isTotalActive() ); + reload(); +} + +void KNCollectionView::updatePopup() const +{ + mPopup->setItemChecked( mUnreadPop, isUnreadActive() ); + mPopup->setItemChecked( mTotalPop, isTotalActive() ); +} + + + +bool KNCollectionView::eventFilter(QObject *o, QEvent *e) +{ + if ((e->type() == QEvent::KeyPress) && (static_cast<QKeyEvent*>(e)->key() == Key_Tab)) { + emit(focusChangeRequest(this)); + if (!hasFocus()) // focusChangeRequest was successful + return true; + } + + // header popup menu + 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 KNCollectionView::focusInEvent(QFocusEvent *e) +{ + QListView::focusInEvent(e); + emit focusChanged(e); +} + + +void KNCollectionView::focusOutEvent(QFocusEvent *e) +{ + QListView::focusOutEvent(e); + emit focusChanged(e); +} + + +#include "kncollectionview.moc" |