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.
tdepim/knode/kncollectionview.cpp

458 lines
12 KiB

/*
KNode, the KDE newsreader
Copyright (c) 2004-2005 Volker Krause <volker.krause@rwth-aachen.de>
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"