/* 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 <tqcursor.h> #include <tqheader.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(TQWidget *tqparent, const char* name) : KFolderTree(tqparent, 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, TQT_SLOT(toggleUnreadColumn()) ); mTotalPop = mPopup->insertItem( i18n("Total Column"), this, TQT_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, TQT_SIGNAL(accountAdded(KNNntpAccount*)), TQT_SLOT(addAccount(KNNntpAccount*))); connect(am, TQT_SIGNAL(accountRemoved(KNNntpAccount*)), TQT_SLOT(removeAccount(KNNntpAccount*))); connect(am, TQT_SIGNAL(accountModified(KNNntpAccount*)), TQT_SLOT(updateAccount(KNNntpAccount*))); // connect to the group manager KNGroupManager* gm = knGlobals.groupManager(); connect(gm, TQT_SIGNAL(groupAdded(KNGroup*)), TQT_SLOT(addGroup(KNGroup*))); connect(gm, TQT_SIGNAL(groupRemoved(KNGroup*)), TQT_SLOT(removeGroup(KNGroup*))); connect(gm, TQT_SIGNAL(groupUpdated(KNGroup*)), TQT_SLOT(updateGroup(KNGroup*))); // connect to the folder manager KNFolderManager* fm = knGlobals.folderManager(); connect(fm, TQT_SIGNAL(folderAdded(KNFolder*)), TQT_SLOT(addPendingFolders())); connect(fm, TQT_SIGNAL(folderRemoved(KNFolder*)), TQT_SLOT(removeFolder(KNFolder*))); connect(fm, TQT_SIGNAL(folderActivated(KNFolder*)), TQT_SLOT(activateFolder(KNFolder*))); installEventFilter(this); } KNCollectionView::~KNCollectionView() { writeConfig(); } void KNCollectionView::readConfig() { KConfig *conf = knGlobals.config(); conf->setGroup( "GroupView" ); // execute the listview tqlayout 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() ); TQPalette p = palette(); p.setColor( TQColorGroup::Base, app->backgroundColor() ); p.setColor( TQColorGroup::Text, app->textColor() ); setPalette( p ); setAlternateBackground( app->backgroundColor() ); // FIXME: make this configurable mPaintInfo.colUnread = TQColor( "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 TQValueList<KNGroup*> groups = knGlobals.groupManager()->groupsOfAccount( a ); for ( TQValueList<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(); TQValueList<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->tqparent()) { // root folder it = new KNCollectionViewItem(this, KFolderTreeItem::Local); } else { // make sure the tqparent folder has already been added if (!f->tqparent()->listItem()) addFolder( static_cast<KNFolder*>(f->tqparent()) ); // 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->tqparent()->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() { TQValueList<KNFolder*> folders = knGlobals.folderManager()->folders(); for ( TQValueList<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 ( TQValueList<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( TQListViewItem *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() { TQListViewItemIterator it( currentItem() ); --it; KFolderTreeItem* fti = static_cast<KFolderTreeItem*>(it.current()); if (fti) { ensureItemVisible( fti ); setFocus(); setCurrentItem( fti ); } } void KNCollectionView::incCurrentFolder() { TQListViewItemIterator 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 ); } } TQDragObject* KNCollectionView::dragObject() { KFolderTreeItem *item = static_cast<KFolderTreeItem*> (itemAt(viewport()->mapFromGlobal(TQCursor::pos()))); if ( item && item->protocol() == KFolderTreeItem::Local && item->type() == KFolderTreeItem::Other ) { TQDragObject *d = new TQStoredDrag( "x-knode-drag/folder", viewport() ); d->setPixmap( SmallIcon("folder") ); return d; } return 0; } void KNCollectionView::contentsDropEvent( TQDropEvent *e ) { cleanItemHighlighter(); // necessary since we overwrite KListView::contentsDropEvent() TQListViewItem *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(TQObject *o, TQEvent *e) { if ((e->type() == TQEvent::KeyPress) && (static_cast<TQKeyEvent*>(e)->key() == Key_Tab)) { emit(focusChangeRequest(this)); if (!hasFocus()) // focusChangeRequest was successful return true; } // header popup menu if ( e->type() == TQEvent::MouseButtonPress && static_cast<TQMouseEvent*>(e)->button() == RightButton && o->isA(TQHEADER_OBJECT_NAME_STRING) ) { mPopup->popup( static_cast<TQMouseEvent*>(e)->globalPos() ); return true; } return KFolderTree::eventFilter(o, e); } void KNCollectionView::focusInEvent(TQFocusEvent *e) { TQListView::focusInEvent(e); emit focusChanged(e); } void KNCollectionView::focusOutEvent(TQFocusEvent *e) { TQListView::focusOutEvent(e); emit focusChanged(e); } #include "kncollectionview.moc"