summaryrefslogtreecommitdiffstats
path: root/kmail/kmfolderseldlg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmail/kmfolderseldlg.cpp')
-rw-r--r--kmail/kmfolderseldlg.cpp574
1 files changed, 574 insertions, 0 deletions
diff --git a/kmail/kmfolderseldlg.cpp b/kmail/kmfolderseldlg.cpp
new file mode 100644
index 000000000..21fc53231
--- /dev/null
+++ b/kmail/kmfolderseldlg.cpp
@@ -0,0 +1,574 @@
+// kmfolderseldlg.cpp
+
+#include <config.h>
+#include "kmfolderseldlg.h"
+#include "kmfoldertree.h"
+#include "kmfolder.h"
+#include "kmmainwidget.h"
+#include "globalsettings.h"
+
+#include <kdebug.h>
+#include <klineedit.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+
+#include <qlayout.h>
+#include <qtoolbutton.h>
+
+namespace KMail {
+
+class FolderItem : public KFolderTreeItem
+{
+ public:
+ FolderItem( KFolderTree * listView );
+ FolderItem( KFolderTreeItem * listViewItem );
+
+ void setFolder( KMFolder * folder ) { mFolder = folder; };
+ const KMFolder * folder() { return mFolder; };
+
+ // Redefine isAlternate() for proper row coloring behavior.
+ // KListViewItem::isAlternate() is not virtual! Therefore,
+ // it is necessary to overload paintCell() below. If it were
+ // made virtual, paintCell() would no longer be necessary.
+ bool isAlternate () {
+ return mAlternate;
+ }
+
+ // Set the flag which determines if this is an alternate row
+ void setAlternate ( bool alternate ) {
+ mAlternate = alternate;
+ }
+
+ // Must overload paintCell because neither KListViewItem::isAlternate()
+ // or KListViewItem::backgroundColor() are virtual!
+ virtual void paintCell( QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment )
+ {
+ KListView* view = static_cast< KListView* >( listView() );
+
+ // Set alternate background to invalid
+ QColor nocolor;
+ QColor alt = view->alternateBackground();
+ view->setAlternateBackground( nocolor );
+
+ // Set the base and text to the appropriate colors
+ QColorGroup *cgroup = (QColorGroup *)&view->viewport()->colorGroup();
+ QColor base = cgroup->base();
+ QColor text = cgroup->text();
+ cgroup->setColor( QColorGroup::Base, isAlternate() ? alt : base );
+ cgroup->setColor( QColorGroup::Text, isEnabled() ? text : Qt::lightGray );
+
+ // Call the parent paint routine
+ KListViewItem::paintCell( p, cg, column, width, alignment );
+
+ // Restore the base and alternate background
+ cgroup->setColor( QColorGroup::Base, base );
+ cgroup->setColor( QColorGroup::Text, text );
+ view->setAlternateBackground( alt );
+ }
+
+ private:
+ KMFolder * mFolder;
+ bool mAlternate;
+};
+
+//-----------------------------------------------------------------------------
+FolderItem::FolderItem( KFolderTree * listView )
+ : KFolderTreeItem( listView ),
+ mFolder( 0 )
+{}
+
+//-----------------------------------------------------------------------------
+FolderItem::FolderItem( KFolderTreeItem * listViewItem )
+ : KFolderTreeItem( listViewItem ),
+ mFolder( 0 )
+{}
+
+//-----------------------------------------------------------------------------
+SimpleFolderTree::SimpleFolderTree( QWidget * parent,
+ KMFolderTree * folderTree,
+ const QString & preSelection,
+ bool mustBeReadWrite )
+ : KFolderTree( parent ), mFolderTree( folderTree )
+{
+ setSelectionModeExt( Single );
+ mFolderColumn = addColumn( i18n( "Folder" ), 0 );
+ mPathColumn = addColumn( i18n( "Path" ), 0 );
+ setAllColumnsShowFocus( true );
+ setAlternateBackground( QColor( 0xf0, 0xf0, 0xf0 ) );
+
+ reload( mustBeReadWrite, true, true, preSelection );
+ readColorConfig();
+
+ applyFilter( "" );
+
+ connect(this, SIGNAL(collapsed(QListViewItem*)), SLOT(recolorRows()));
+ connect(this, SIGNAL(expanded(QListViewItem*)), SLOT(recolorRows()));
+
+ connect( this, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint &, int ) ),
+ this, SLOT( slotContextMenuRequested( QListViewItem*, const QPoint & ) ) );
+}
+
+//-----------------------------------------------------------------------------
+void SimpleFolderTree::reload( bool mustBeReadWrite, bool showOutbox,
+ bool showImapFolders, const QString& preSelection )
+{
+ mLastMustBeReadWrite = mustBeReadWrite;
+ mLastShowOutbox = showOutbox;
+ mLastShowImapFolders = showImapFolders;
+
+ clear();
+ FolderItem * lastItem = 0;
+ FolderItem * lastTopItem = 0;
+ FolderItem * selectedItem = 0;
+ int lastDepth = 0;
+
+ QString selected = preSelection;
+ if ( selected.isEmpty() && folder() )
+ selected = folder()->idString();
+
+ mFilter = "";
+ QString path;
+
+ for ( QListViewItemIterator it( mFolderTree ) ; it.current() ; ++it )
+ {
+ KMFolderTreeItem * fti = static_cast<KMFolderTreeItem *>( it.current() );
+
+ // search folders are never shown
+ if ( !fti || fti->protocol() == KFolderTreeItem::Search )
+ continue;
+
+ // imap folders?
+ if ( fti->protocol() == KFolderTreeItem::Imap && !showImapFolders )
+ continue;
+
+ // the outbox?
+ if ( fti->type() == KFolderTreeItem::Outbox && !showOutbox )
+ continue;
+
+ int depth = fti->depth();// - 1;
+ FolderItem * item = 0;
+ if ( depth <= 0 ) {
+ // top level - first top level item or after last existing top level item
+ item = new FolderItem( this );
+ if ( lastTopItem )
+ item->moveItem( lastTopItem );
+ lastTopItem = item;
+ depth = 0;
+ path = "";
+ }
+ else {
+ if ( depth > lastDepth ) {
+ // next lower level - parent node will get opened
+ item = new FolderItem( lastItem );
+ lastItem->setOpen(true);
+ }
+ else {
+ path = path.section( '/', 0, -2 - (lastDepth-depth) );
+
+ if ( depth == lastDepth ) {
+ // same level - behind previous item
+ item = new FolderItem( static_cast<FolderItem*>(lastItem->parent()) );
+ item->moveItem( lastItem );
+ } else if ( depth < lastDepth ) {
+ // above previous level - might be more than one level difference
+ // but highest possibility is top level
+ while ( ( depth <= --lastDepth ) && lastItem->parent() ) {
+ lastItem = static_cast<FolderItem *>( lastItem->parent() );
+ }
+ if ( lastItem->parent() ) {
+ item = new FolderItem( static_cast<FolderItem*>(lastItem->parent()) );
+ item->moveItem( lastItem );
+ } else {
+ // chain somehow broken - what does cause this ???
+ kdDebug( 5006 ) << "You shouldn't get here: depth=" << depth
+ << "folder name=" << fti->text( 0 ) << endl;
+ item = new FolderItem( this );
+ lastTopItem = item;
+ }
+ }
+ }
+ }
+
+ if ( depth > 0 )
+ path += "/";
+ path += fti->text( 0 );
+
+ item->setText( mFolderColumn, fti->text( 0 ) );
+ item->setText( mPathColumn, path );
+
+ item->setProtocol( fti->protocol() );
+ item->setType( fti->type() );
+
+ // Make items without folders and readonly items unselectable
+ // if we're told so
+ if ( mustBeReadWrite && ( !fti->folder() || fti->folder()->isReadOnly() ) ) {
+ item->setSelectable( false );
+ } else {
+ if ( fti->folder() ) {
+ item->setFolder( fti->folder() );
+ if ( selected == item->folder()->idString() )
+ selectedItem = item;
+ }
+ }
+ lastItem = item;
+ lastDepth = depth;
+ }
+
+ if ( selectedItem ) {
+ setSelected( selectedItem, true );
+ ensureItemVisible( selectedItem );
+ }
+}
+
+//-----------------------------------------------------------------------------
+const KMFolder * SimpleFolderTree::folder() const
+{
+ QListViewItem * item = currentItem();
+ if ( item ) {
+ const KMFolder * folder = static_cast<FolderItem *>( item )->folder();
+ if( folder ) return folder;
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+void SimpleFolderTree::setFolder( KMFolder *folder )
+{
+ for ( QListViewItemIterator it( this ) ; it.current() ; ++it )
+ {
+ const KMFolder *fld = static_cast<FolderItem *>( it.current() )->folder();
+ if ( fld == folder )
+ {
+ setSelected( it.current(), true );
+ ensureItemVisible( it.current() );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+void SimpleFolderTree::setFolder( const QString& idString )
+{
+ setFolder( kmkernel->findFolderById( idString ) );
+}
+
+//-----------------------------------------------------------------------------
+void SimpleFolderTree::addChildFolder()
+{
+ const KMFolder *fld = folder();
+ if ( fld ) {
+ mFolderTree->addChildFolder( (KMFolder *) fld, parentWidget() );
+ reload( mLastMustBeReadWrite, mLastShowOutbox, mLastShowImapFolders );
+ setFolder( (KMFolder *) fld );
+ }
+}
+
+//-----------------------------------------------------------------------------
+void SimpleFolderTree::slotContextMenuRequested( QListViewItem *lvi,
+ const QPoint &p )
+{
+ if (!lvi)
+ return;
+ setCurrentItem( lvi );
+ setSelected( lvi, TRUE );
+
+ const KMFolder * folder = static_cast<FolderItem *>( lvi )->folder();
+ if ( !folder || folder->noContent() || folder->noChildren() )
+ return;
+
+ KPopupMenu *folderMenu = new KPopupMenu;
+ folderMenu->insertTitle( folder->label() );
+ folderMenu->insertSeparator();
+ folderMenu->insertItem(SmallIconSet("folder_new"),
+ i18n("&New Subfolder..."), this,
+ SLOT(addChildFolder()));
+ kmkernel->setContextMenuShown( true );
+ folderMenu->exec (p, 0);
+ kmkernel->setContextMenuShown( false );
+ delete folderMenu;
+ folderMenu = 0;
+}
+
+//-----------------------------------------------------------------------------
+void SimpleFolderTree::readColorConfig (void)
+{
+ QColor c1=QColor(kapp->palette().active().text());
+ QColor c2=QColor(kapp->palette().active().base());
+
+ mPaintInfo.colFore = c1;
+ mPaintInfo.colBack = c2;
+
+ QPalette newPal = kapp->palette();
+ newPal.setColor( QColorGroup::Base, mPaintInfo.colBack );
+ newPal.setColor( QColorGroup::Text, mPaintInfo.colFore );
+ setPalette( newPal );
+}
+
+
+//-----------------------------------------------------------------------------
+static int recurseFilter( QListViewItem * item, const QString& filter, int column )
+{
+ if ( item == 0 )
+ return 0;
+
+ QListViewItem * child;
+ child = item->firstChild();
+
+ int enabled = 0;
+ while ( child ) {
+ enabled += recurseFilter( child, filter, column );
+ child = child->nextSibling();
+ }
+
+ if ( filter.length() == 0 ||
+ item->text( column ).find( filter, 0, false ) >= 0 ) {
+ item->setVisible( true );
+ ++enabled;
+ }
+ else {
+ item->setVisible( !!enabled );
+ item->setEnabled( false );
+ }
+
+ return enabled;
+}
+
+void SimpleFolderTree::recolorRows()
+{
+ // Iterate through the list to set the alternate row flags.
+ int alt = 0;
+ QListViewItemIterator it ( this );
+ while ( it.current() ) {
+ FolderItem * item = static_cast< FolderItem* >( it.current() );
+
+ if ( item->isVisible() ) {
+ bool visible = true;
+ QListViewItem * parent = item->parent();
+ while ( parent ) {
+ if (!parent->isOpen()) {
+ visible = false;
+ break;
+ }
+ parent = parent->parent();
+ }
+
+ if ( visible ) {
+ item->setAlternate( alt );
+ alt = !alt;
+ }
+ }
+
+ ++it;
+ }
+}
+
+void SimpleFolderTree::applyFilter( const QString& filter )
+{
+ // Reset all items to visible, enabled, and open
+ QListViewItemIterator clean( this );
+ while ( clean.current() ) {
+ QListViewItem * item = clean.current();
+ item->setEnabled( true );
+ item->setVisible( true );
+ item->setOpen( true );
+ ++clean;
+ }
+
+ mFilter = filter;
+
+ if ( filter.isEmpty() ) {
+ setColumnText( mPathColumn, i18n("Path") );
+ return;
+ }
+
+ // Set the visibility and enabled status of each list item.
+ // The recursive algorithm is necessary because visiblity
+ // changes are automatically applied to child nodes by Qt.
+ QListViewItemIterator it( this );
+ while ( it.current() ) {
+ QListViewItem * item = it.current();
+ if ( item->depth() <= 0 )
+ recurseFilter( item, filter, mPathColumn );
+ ++it;
+ }
+
+ // Recolor the rows appropriately
+ recolorRows();
+
+ // Iterate through the list to find the first selectable item
+ QListViewItemIterator first ( this );
+ while ( first.current() ) {
+ FolderItem * item = static_cast< FolderItem* >( first.current() );
+
+ if ( item->isVisible() && item->isSelectable() ) {
+ setSelected( item, true );
+ ensureItemVisible( item );
+ break;
+ }
+
+ ++first;
+ }
+
+ // Display and save the current filter
+ if ( filter.length() > 0 )
+ setColumnText( mPathColumn, i18n("Path") + " ( " + filter + " )" );
+ else
+ setColumnText( mPathColumn, i18n("Path") );
+
+ mFilter = filter;
+}
+
+//-----------------------------------------------------------------------------
+void SimpleFolderTree::keyPressEvent( QKeyEvent *e ) {
+ int ch = e->ascii();
+
+ if ( ch >= 32 && ch <= 126 )
+ applyFilter( mFilter + ch );
+
+ else if ( ch == 8 || ch == 127 ) {
+ if ( mFilter.length() > 0 ) {
+ mFilter.truncate( mFilter.length()-1 );
+ applyFilter( mFilter );
+ }
+ }
+
+ else
+ KListView::keyPressEvent( e );
+}
+
+
+//-----------------------------------------------------------------------------
+KMFolderSelDlg::KMFolderSelDlg( KMMainWidget * parent, const QString& caption,
+ bool mustBeReadWrite, bool useGlobalSettings )
+ : KDialogBase( parent, "folder dialog", true, caption,
+ Ok|Cancel|User1, Ok, true,
+ KGuiItem(i18n("&New Subfolder..."), "folder_new",
+ i18n("Create a new subfolder under the currently selected folder"))
+ ), // mainwin as parent, modal
+ mUseGlobalSettings( useGlobalSettings )
+{
+ KMFolderTree * ft = parent->folderTree();
+ assert( ft );
+
+ QString preSelection = mUseGlobalSettings ?
+ GlobalSettings::self()->lastSelectedFolder() : QString::null;
+ mTreeView = new KMail::SimpleFolderTree( makeVBoxMainWidget(), ft,
+ preSelection, mustBeReadWrite );
+ init();
+}
+
+//----------------------------------------------------------------------------
+KMFolderSelDlg::KMFolderSelDlg( QWidget * parent, KMFolderTree * tree,
+ const QString& caption, bool mustBeReadWrite, bool useGlobalSettings )
+ : KDialogBase( parent, "folder dialog", true, caption,
+ Ok|Cancel|User1, Ok, true,
+ KGuiItem(i18n("&New Subfolder..."), "folder_new",
+ i18n("Create a new subfolder under the currently selected folder"))
+ ), // mainwin as parent, modal
+ mUseGlobalSettings( useGlobalSettings )
+{
+ QString preSelection = mUseGlobalSettings ?
+ GlobalSettings::self()->lastSelectedFolder() : QString::null;
+ mTreeView = new KMail::SimpleFolderTree( makeVBoxMainWidget(), tree,
+ preSelection, mustBeReadWrite );
+ init();
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderSelDlg::init()
+{
+ mTreeView->setFocus();
+ connect( mTreeView, SIGNAL( doubleClicked( QListViewItem*, const QPoint&, int ) ),
+ this, SLOT( slotSelect() ) );
+ connect( mTreeView, SIGNAL( selectionChanged() ),
+ this, SLOT( slotUpdateBtnStatus() ) );
+
+ readConfig();
+}
+
+//-----------------------------------------------------------------------------
+KMFolderSelDlg::~KMFolderSelDlg()
+{
+ const KMFolder * cur = folder();
+ if ( cur && mUseGlobalSettings ) {
+ GlobalSettings::self()->setLastSelectedFolder( cur->idString() );
+ }
+
+ writeConfig();
+}
+
+
+//-----------------------------------------------------------------------------
+KMFolder * KMFolderSelDlg::folder( void )
+{
+ return ( KMFolder * ) mTreeView->folder();
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderSelDlg::setFolder( KMFolder* folder )
+{
+ mTreeView->setFolder( folder );
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderSelDlg::slotSelect()
+{
+ accept();
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderSelDlg::slotUser1()
+{
+ mTreeView->addChildFolder();
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderSelDlg::slotUpdateBtnStatus()
+{
+ enableButton( User1, folder() &&
+ ( !folder()->noContent() && !folder()->noChildren() ) );
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderSelDlg::setFlags( bool mustBeReadWrite, bool showOutbox,
+ bool showImapFolders )
+{
+ mTreeView->reload( mustBeReadWrite, showOutbox, showImapFolders );
+}
+
+void KMFolderSelDlg::readConfig()
+{
+ KConfig *config = KGlobal::config();
+ config->setGroup( "FolderSelectionDialog" );
+
+ QSize size = config->readSizeEntry( "Size" );
+ if ( !size.isEmpty() ) resize( size );
+ else resize( 500, 300 );
+
+ QValueList<int> widths = config->readIntListEntry( "ColumnWidths" );
+ if ( !widths.isEmpty() ) {
+ mTreeView->setColumnWidth(mTreeView->mFolderColumn, widths[0]);
+ mTreeView->setColumnWidth(mTreeView->mPathColumn, widths[1]);
+ }
+ else {
+ int colWidth = width() / 2;
+ mTreeView->setColumnWidth(mTreeView->mFolderColumn, colWidth);
+ mTreeView->setColumnWidth(mTreeView->mPathColumn, colWidth);
+ }
+}
+
+void KMFolderSelDlg::writeConfig()
+{
+ KConfig *config = KGlobal::config();
+ config->setGroup( "FolderSelectionDialog" );
+ config->writeEntry( "Size", size() );
+
+ QValueList<int> widths;
+ widths.push_back(mTreeView->columnWidth(mTreeView->mFolderColumn));
+ widths.push_back(mTreeView->columnWidth(mTreeView->mPathColumn));
+ config->writeEntry( "ColumnWidths", widths );
+}
+
+} // namespace KMail
+
+#include "kmfolderseldlg.moc"