mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 10:22:50 +00:00
753 lines
22 KiB
C++
753 lines
22 KiB
C++
/*
|
|
Copyright (c) 2009 Kevin Ottens <ervin@kde.org>
|
|
|
|
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.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
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, USA.
|
|
*/
|
|
|
|
#include "widget.h"
|
|
|
|
#include <akonadi/collection.h>
|
|
#include <akonadi/item.h>
|
|
#include <akonadi/itemcopyjob.h>
|
|
#include <akonadi/itemmovejob.h>
|
|
|
|
#include "storagemodel.h"
|
|
#include "core/messageitem.h"
|
|
#include "core/view.h"
|
|
#include <core/settings.h>
|
|
|
|
#include <QtCore/QTimer>
|
|
#include <QAction>
|
|
#include <QApplication>
|
|
#include <QDrag>
|
|
#include <QDragMoveEvent>
|
|
#include <QDropEvent>
|
|
|
|
#include <KDE/KActionCollection>
|
|
#include <KDE/KComboBox>
|
|
#include <KDE/KDebug>
|
|
#include <KDE/KIcon>
|
|
#include <KDE/KIconLoader>
|
|
#include <KDE/KLocale>
|
|
#include <KDE/KMenu>
|
|
#include <KDE/KToggleAction>
|
|
#include <KDE/KXMLGUIClient>
|
|
#include <KDE/KXMLGUIFactory>
|
|
|
|
#include "core/groupheaderitem.h"
|
|
|
|
#include <Akonadi/Monitor>
|
|
#include <Akonadi/Tag>
|
|
#include <Akonadi/TagFetchJob>
|
|
#include <Akonadi/TagFetchScope>
|
|
#include <Akonadi/TagAttribute>
|
|
|
|
|
|
namespace MessageList
|
|
{
|
|
|
|
class Widget::Private
|
|
{
|
|
public:
|
|
Private( Widget *owner )
|
|
: q( owner ), mLastSelectedMessage(-1), mXmlGuiClient( 0 ), mMonitor( 0 ) { }
|
|
|
|
Akonadi::Item::List selectionAsItems() const;
|
|
Akonadi::Item itemForRow( int row ) const;
|
|
KMime::Message::Ptr messageForRow( int row ) const;
|
|
|
|
Widget * const q;
|
|
|
|
int mLastSelectedMessage;
|
|
KXMLGUIClient *mXmlGuiClient;
|
|
QModelIndex mGroupHeaderItemIndex;
|
|
Akonadi::Monitor *mMonitor;
|
|
};
|
|
|
|
} // namespace MessageList
|
|
|
|
using namespace MessageList;
|
|
using namespace Akonadi;
|
|
|
|
Widget::Widget( QWidget *parent )
|
|
: Core::Widget( parent ), d( new Private( this ) )
|
|
{
|
|
populateStatusFilterCombo();
|
|
|
|
d->mMonitor = new Akonadi::Monitor( this );
|
|
d->mMonitor->setTypeMonitored( Akonadi::Monitor::Tags );
|
|
connect(d->mMonitor, SIGNAL(tagAdded(Akonadi::Tag)), this, SLOT(populateStatusFilterCombo()));
|
|
connect(d->mMonitor, SIGNAL(tagRemoved(Akonadi::Tag)), this, SLOT(populateStatusFilterCombo()));
|
|
connect(d->mMonitor, SIGNAL(tagChanged(Akonadi::Tag)), this, SLOT(populateStatusFilterCombo()));
|
|
}
|
|
|
|
Widget::~Widget()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void Widget::setXmlGuiClient( KXMLGUIClient *xmlGuiClient )
|
|
{
|
|
d->mXmlGuiClient = xmlGuiClient;
|
|
}
|
|
|
|
bool Widget::canAcceptDrag( const QDropEvent * e )
|
|
{
|
|
if ( e->source() == view()->viewport() )
|
|
return false;
|
|
|
|
Collection::List collections = static_cast<const StorageModel*>( storageModel() )->displayedCollections();
|
|
if ( collections.size()!=1 )
|
|
return false; // no folder here or too many (in case we can't decide where the drop will end)
|
|
|
|
const Collection target = collections.first();
|
|
|
|
if ( ( target.rights() & Collection::CanCreateItem ) == 0 )
|
|
return false; // no way to drag into
|
|
|
|
const KUrl::List urls = KUrl::List::fromMimeData( e->mimeData() );
|
|
foreach ( const KUrl &url, urls ) {
|
|
const Collection collection = Collection::fromUrl( url );
|
|
if ( collection.isValid() ) { // You're not supposed to drop collections here
|
|
return false;
|
|
} else { // Yay, this is an item!
|
|
const QString type = url.queryItems()[QLatin1String( "type" )]; // But does it have the right type?
|
|
if ( !target.contentMimeTypes().contains( type ) ) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Widget::selectNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter,
|
|
MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour,
|
|
bool centerItem,
|
|
bool loop )
|
|
{
|
|
return view()->selectNextMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop );
|
|
}
|
|
|
|
bool Widget::selectPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter,
|
|
MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour,
|
|
bool centerItem,
|
|
bool loop )
|
|
{
|
|
return view()->selectPreviousMessageItem( messageTypeFilter, existingSelectionBehaviour, centerItem, loop );
|
|
}
|
|
|
|
bool Widget::focusNextMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop )
|
|
{
|
|
return view()->focusNextMessageItem( messageTypeFilter, centerItem, loop );
|
|
}
|
|
|
|
bool Widget::focusPreviousMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop )
|
|
{
|
|
return view()->focusPreviousMessageItem( messageTypeFilter, centerItem, loop );
|
|
}
|
|
|
|
void Widget::selectFocusedMessageItem( bool centerItem )
|
|
{
|
|
view()->selectFocusedMessageItem( centerItem );
|
|
}
|
|
|
|
bool Widget::selectFirstMessageItem( MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem )
|
|
{
|
|
return view()->selectFirstMessageItem( messageTypeFilter, centerItem );
|
|
}
|
|
|
|
bool Widget::selectLastMessageItem( Core::MessageTypeFilter messageTypeFilter, bool centerItem )
|
|
{
|
|
return view()->selectLastMessageItem( messageTypeFilter, centerItem );
|
|
}
|
|
|
|
void Widget::selectAll()
|
|
{
|
|
view()->setAllGroupsExpanded( true );
|
|
view()->selectAll();
|
|
}
|
|
|
|
void Widget::setCurrentThreadExpanded( bool expand )
|
|
{
|
|
view()->setCurrentThreadExpanded(expand );
|
|
}
|
|
|
|
void Widget::setAllThreadsExpanded( bool expand )
|
|
{
|
|
view()->setAllThreadsExpanded( expand );
|
|
}
|
|
|
|
void Widget::setAllGroupsExpanded( bool expand )
|
|
{
|
|
view()->setAllGroupsExpanded(expand);
|
|
}
|
|
|
|
void Widget::focusQuickSearch(const QString &selectedText)
|
|
{
|
|
view()->focusQuickSearch(selectedText);
|
|
}
|
|
|
|
void Widget::setQuickSearchClickMessage(const QString &msg)
|
|
{
|
|
view()->setQuickSearchClickMessage(msg);
|
|
}
|
|
|
|
void Widget::fillMessageTagCombo()
|
|
{
|
|
Akonadi::TagFetchJob *fetchJob = new Akonadi::TagFetchJob(this);
|
|
fetchJob->fetchScope().fetchAttribute<Akonadi::TagAttribute>();
|
|
connect(fetchJob, SIGNAL(result(KJob*)), this, SLOT(slotTagsFetched(KJob*)));
|
|
}
|
|
|
|
void Widget::slotTagsFetched(KJob *job)
|
|
{
|
|
if (job->error()) {
|
|
kWarning() << "Failed to load tags " << job->errorString();
|
|
return;
|
|
}
|
|
Akonadi::TagFetchJob *fetchJob = static_cast<Akonadi::TagFetchJob*>(job);
|
|
|
|
KConfigGroup conf( MessageList::Core::Settings::self()->config(),"MessageListView");
|
|
const QString tagSelected= conf.readEntry(QLatin1String("TagSelected"));
|
|
if(tagSelected.isEmpty()) {
|
|
setCurrentStatusFilterItem();
|
|
return;
|
|
}
|
|
const QStringList tagSelectedLst = tagSelected.split(QLatin1Char(','));
|
|
|
|
addMessageTagItem( SmallIcon( QLatin1String( "mail-flag" ) ), i18n( "All" ), QString() );
|
|
|
|
QStringList tagFound;
|
|
foreach( const Akonadi::Tag &akonadiTag, fetchJob->tags() ) {
|
|
if(tagSelectedLst.contains(akonadiTag.url().url())) {
|
|
tagFound.append(akonadiTag.url().url());
|
|
QString iconName = QLatin1String( "mail-tagged" );
|
|
const QString label = akonadiTag.name();
|
|
const QString id = akonadiTag.url().url();
|
|
Akonadi::TagAttribute *attr = akonadiTag.attribute<Akonadi::TagAttribute>();
|
|
if (attr) {
|
|
iconName = attr->iconName();
|
|
}
|
|
addMessageTagItem( SmallIcon( iconName ), label, QVariant( id ) );
|
|
}
|
|
}
|
|
conf.writeEntry(QLatin1String("TagSelected"), tagFound);
|
|
conf.sync();
|
|
|
|
setCurrentStatusFilterItem();
|
|
}
|
|
|
|
void Widget::viewMessageSelected( MessageList::Core::MessageItem *msg )
|
|
{
|
|
int row = -1;
|
|
if ( msg ) {
|
|
row = msg->currentModelIndexRow();
|
|
}
|
|
|
|
if ( !msg || !msg->isValid() || !storageModel() ) {
|
|
d->mLastSelectedMessage = -1;
|
|
emit messageSelected( Item() );
|
|
return;
|
|
}
|
|
|
|
Q_ASSERT( row >= 0 );
|
|
|
|
d->mLastSelectedMessage = row;
|
|
|
|
emit messageSelected( d->itemForRow( row ) ); // this MAY be null
|
|
}
|
|
|
|
void Widget::viewMessageActivated( MessageList::Core::MessageItem *msg )
|
|
{
|
|
Q_ASSERT( msg ); // must not be null
|
|
Q_ASSERT( storageModel() );
|
|
|
|
if ( !msg->isValid() ) {
|
|
return;
|
|
}
|
|
|
|
int row = msg->currentModelIndexRow();
|
|
Q_ASSERT( row >= 0 );
|
|
|
|
// The assert below may fail when quickly opening and closing a non-selected thread.
|
|
// This will actually activate the item without selecting it...
|
|
//Q_ASSERT( d->mLastSelectedMessage == row );
|
|
|
|
if ( d->mLastSelectedMessage != row ) {
|
|
// Very ugly. We are activating a non selected message.
|
|
// This is very likely a double click on the plus sign near a thread leader.
|
|
// Dealing with mLastSelectedMessage here would be expensive: it would involve releasing the last selected,
|
|
// emitting signals, handling recursion... ugly.
|
|
// We choose a very simple solution: double clicking on the plus sign near a thread leader does
|
|
// NOT activate the message (i.e open it in a toplevel window) if it isn't previously selected.
|
|
return;
|
|
}
|
|
|
|
emit messageActivated( d->itemForRow( row ) ); // this MAY be null
|
|
}
|
|
|
|
void Widget::viewSelectionChanged()
|
|
{
|
|
emit selectionChanged();
|
|
if ( !currentMessageItem() ) {
|
|
emit messageSelected( Item() );
|
|
}
|
|
}
|
|
|
|
void Widget::viewMessageListContextPopupRequest( const QList< MessageList::Core::MessageItem * > &selectedItems,
|
|
const QPoint &globalPos )
|
|
{
|
|
Q_UNUSED( selectedItems );
|
|
|
|
if ( !d->mXmlGuiClient )
|
|
return;
|
|
|
|
QMenu *popup = static_cast<QMenu*>( d->mXmlGuiClient->factory()->container(
|
|
QLatin1String( "akonadi_messagelist_contextmenu" ),
|
|
d->mXmlGuiClient ) );
|
|
if ( popup ) {
|
|
popup->exec( globalPos );
|
|
}
|
|
}
|
|
|
|
void Widget::viewMessageStatusChangeRequest( MessageList::Core::MessageItem *msg, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear )
|
|
{
|
|
Q_ASSERT( msg ); // must not be null
|
|
Q_ASSERT( storageModel() );
|
|
|
|
if ( !msg->isValid() ) {
|
|
return;
|
|
}
|
|
|
|
int row = msg->currentModelIndexRow();
|
|
Q_ASSERT( row >= 0 );
|
|
|
|
Item item = d->itemForRow( row );
|
|
Q_ASSERT( item.isValid() );
|
|
|
|
emit messageStatusChangeRequest( item, set, clear );
|
|
}
|
|
|
|
void Widget::viewGroupHeaderContextPopupRequest( MessageList::Core::GroupHeaderItem *ghi, const QPoint &globalPos )
|
|
{
|
|
Q_UNUSED( ghi );
|
|
|
|
KMenu menu( this );
|
|
|
|
QAction *act;
|
|
|
|
QModelIndex index = view()->model()->index( ghi, 0 );
|
|
d->mGroupHeaderItemIndex = index;
|
|
|
|
if ( view()->isExpanded( index ) ) {
|
|
act = menu.addAction( i18n ( "Collapse Group" ) );
|
|
connect( act, SIGNAL(triggered(bool)),
|
|
this, SLOT(slotCollapseItem()) );
|
|
} else {
|
|
act = menu.addAction( i18n ( "Expand Group" ) );
|
|
connect( act, SIGNAL(triggered(bool)),
|
|
this, SLOT(slotExpandItem()) );
|
|
}
|
|
|
|
menu.addSeparator();
|
|
|
|
act = menu.addAction( i18n( "Expand All Groups" ) );
|
|
connect( act, SIGNAL(triggered(bool)),
|
|
view(), SLOT(slotExpandAllGroups()) );
|
|
|
|
act = menu.addAction( i18n( "Collapse All Groups" ) );
|
|
connect( act, SIGNAL(triggered(bool)),
|
|
view(), SLOT(slotCollapseAllGroups()) );
|
|
|
|
menu.exec( globalPos );
|
|
}
|
|
|
|
void Widget::viewDragEnterEvent( QDragEnterEvent *e )
|
|
{
|
|
if ( !canAcceptDrag( e ) ) {
|
|
e->ignore();
|
|
return;
|
|
}
|
|
|
|
e->accept();
|
|
}
|
|
|
|
void Widget::viewDragMoveEvent( QDragMoveEvent *e )
|
|
{
|
|
if ( !canAcceptDrag( e ) ) {
|
|
e->ignore();
|
|
return;
|
|
}
|
|
|
|
e->accept();
|
|
}
|
|
|
|
enum DragMode
|
|
{
|
|
DragCopy,
|
|
DragMove,
|
|
DragCancel
|
|
};
|
|
|
|
void Widget::viewDropEvent( QDropEvent *e )
|
|
{
|
|
if ( !canAcceptDrag( e ) ) {
|
|
e->ignore();
|
|
return;
|
|
}
|
|
|
|
KUrl::List urls = KUrl::List::fromMimeData( e->mimeData() );
|
|
if ( urls.isEmpty() ) {
|
|
kWarning() << "Could not decode drag data!";
|
|
e->ignore();
|
|
return;
|
|
}
|
|
|
|
e->accept();
|
|
|
|
int action;
|
|
if ( ( e->possibleActions() & Qt::MoveAction ) == 0 ) { // We can't move anyway
|
|
action = DragCopy;
|
|
} else {
|
|
action = DragCancel;
|
|
int keybstate = QApplication::keyboardModifiers();
|
|
if ( keybstate & Qt::CTRL ) {
|
|
action = DragCopy;
|
|
|
|
} else if ( keybstate & Qt::SHIFT ) {
|
|
action = DragMove;
|
|
|
|
} else {
|
|
KMenu menu;
|
|
QAction *moveAction = menu.addAction( KIcon( QLatin1String( "go-jump" )), i18n( "&Move Here" ) );
|
|
QAction *copyAction = menu.addAction( KIcon( QLatin1String( "edit-copy" ) ), i18n( "&Copy Here" ) );
|
|
menu.addSeparator();
|
|
menu.addAction( KIcon( QLatin1String( "dialog-cancel" ) ), i18n( "C&ancel" ) );
|
|
|
|
QAction *menuChoice = menu.exec( QCursor::pos() );
|
|
if ( menuChoice == moveAction ) {
|
|
action = DragMove;
|
|
} else if ( menuChoice == copyAction ) {
|
|
action = DragCopy;
|
|
} else {
|
|
action = DragCancel;
|
|
}
|
|
}
|
|
}
|
|
if ( action == DragCancel )
|
|
return;
|
|
|
|
Collection::List collections = static_cast<const StorageModel*>( storageModel() )->displayedCollections();
|
|
Collection target = collections.first();
|
|
Item::List items;
|
|
foreach ( const KUrl &url, urls ) {
|
|
items << Item::fromUrl( url );
|
|
}
|
|
|
|
if ( action == DragCopy ) {
|
|
new ItemCopyJob( items, target, this );
|
|
} else if ( action == DragMove ) {
|
|
new ItemMoveJob( items, target, this );
|
|
}
|
|
}
|
|
|
|
|
|
void Widget::viewStartDragRequest()
|
|
{
|
|
Collection::List collections = static_cast<const StorageModel*>( storageModel() )->displayedCollections();
|
|
|
|
if ( collections.isEmpty() )
|
|
return; // no folder here
|
|
|
|
QList<Core::MessageItem *> selection = view()->selectionAsMessageItemList();
|
|
if ( selection.isEmpty() ) {
|
|
return;
|
|
}
|
|
|
|
bool readOnly = false;
|
|
|
|
foreach ( const Collection &c, collections ) {
|
|
// We won't be able to remove items from this collection
|
|
if ( ( c.rights() & Collection::CanDeleteItem ) == 0 ) {
|
|
// So the drag will be read-only
|
|
readOnly = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
KUrl::List urls;
|
|
Q_FOREACH ( Core::MessageItem *mi, selection ) {
|
|
const Item i = d->itemForRow( mi->currentModelIndexRow() );
|
|
KUrl url = i.url( Item::Item::Item::UrlWithMimeType );
|
|
url.addQueryItem(QLatin1String("parent"), QString::number( mi->parentCollectionId() ) );
|
|
urls << url;
|
|
}
|
|
|
|
QMimeData *mimeData = new QMimeData;
|
|
urls.populateMimeData( mimeData );
|
|
|
|
QDrag *drag = new QDrag( view()->viewport() );
|
|
drag->setMimeData( mimeData );
|
|
|
|
// Set pixmap
|
|
QPixmap pixmap;
|
|
if( selection.size() == 1 ) {
|
|
pixmap = QPixmap( DesktopIcon(QLatin1String( "mail-message" ), KIconLoader::SizeSmall) );
|
|
} else {
|
|
pixmap = QPixmap( DesktopIcon(QLatin1String( "document-multiple" ), KIconLoader::SizeSmall) );
|
|
}
|
|
|
|
// Calculate hotspot (as in Konqueror)
|
|
if( !pixmap.isNull() ) {
|
|
drag->setHotSpot( QPoint( pixmap.width() / 2, pixmap.height() / 2 ) );
|
|
drag->setPixmap( pixmap );
|
|
}
|
|
|
|
if ( readOnly )
|
|
drag->exec( Qt::CopyAction );
|
|
else
|
|
drag->exec( Qt::CopyAction | Qt::MoveAction );
|
|
}
|
|
|
|
Item::List Widget::Private::selectionAsItems() const
|
|
{
|
|
Item::List res;
|
|
QList<Core::MessageItem *> selection = q->view()->selectionAsMessageItemList();
|
|
|
|
foreach ( Core::MessageItem *mi, selection ) {
|
|
Item i = itemForRow( mi->currentModelIndexRow() );
|
|
Q_ASSERT( i.isValid() );
|
|
res << i;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
Item Widget::Private::itemForRow( int row ) const
|
|
{
|
|
return static_cast<const StorageModel*>( q->storageModel() )->itemForRow( row );
|
|
}
|
|
|
|
KMime::Message::Ptr Widget::Private::messageForRow( int row ) const
|
|
{
|
|
return static_cast<const StorageModel*>( q->storageModel() )->messageForRow( row );
|
|
}
|
|
|
|
Item Widget::currentItem() const
|
|
{
|
|
Core::MessageItem *mi = view()->currentMessageItem();
|
|
|
|
if ( mi == 0 ) {
|
|
return Item();
|
|
}
|
|
|
|
return d->itemForRow( mi->currentModelIndexRow() );
|
|
}
|
|
|
|
KMime::Message::Ptr Widget::currentMessage() const
|
|
{
|
|
Core::MessageItem *mi = view()->currentMessageItem();
|
|
|
|
if ( mi == 0 ) {
|
|
return KMime::Message::Ptr();
|
|
}
|
|
|
|
return d->messageForRow( mi->currentModelIndexRow() );
|
|
}
|
|
|
|
|
|
QList<KMime::Message::Ptr > Widget::selectionAsMessageList( bool includeCollapsedChildren ) const
|
|
{
|
|
QList<KMime::Message::Ptr> lstMiPtr;
|
|
QList<Core::MessageItem *> lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren );
|
|
if ( lstMi.isEmpty() ) {
|
|
return lstMiPtr;
|
|
}
|
|
foreach( Core::MessageItem *it, lstMi ) {
|
|
lstMiPtr.append( d->messageForRow( it->currentModelIndexRow() ) );
|
|
}
|
|
return lstMiPtr;
|
|
}
|
|
|
|
QList<Akonadi::Item> Widget::selectionAsMessageItemList( bool includeCollapsedChildren ) const
|
|
{
|
|
QList<Item> lstMiPtr;
|
|
QList<Core::MessageItem *> lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren );
|
|
if ( lstMi.isEmpty() ) {
|
|
return lstMiPtr;
|
|
}
|
|
foreach( Core::MessageItem *it, lstMi ) {
|
|
lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ) );
|
|
}
|
|
return lstMiPtr;
|
|
}
|
|
|
|
QVector<qlonglong> Widget::selectionAsMessageItemListId( bool includeCollapsedChildren ) const
|
|
{
|
|
QVector<qlonglong> lstMiPtr;
|
|
QList<Core::MessageItem *> lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren );
|
|
if ( lstMi.isEmpty() ) {
|
|
return lstMiPtr;
|
|
}
|
|
foreach( Core::MessageItem *it, lstMi ) {
|
|
lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ).id() );
|
|
}
|
|
return lstMiPtr;
|
|
}
|
|
|
|
|
|
QList<Akonadi::Item::Id> Widget::selectionAsListMessageId( bool includeCollapsedChildren ) const
|
|
{
|
|
QList<qlonglong> lstMiPtr;
|
|
QList<Core::MessageItem *> lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren );
|
|
if ( lstMi.isEmpty() ) {
|
|
return lstMiPtr;
|
|
}
|
|
foreach( Core::MessageItem *it, lstMi ) {
|
|
lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ).id() );
|
|
}
|
|
return lstMiPtr;
|
|
}
|
|
|
|
QList<Akonadi::Item> Widget::currentThreadAsMessageList() const
|
|
{
|
|
QList<Item> lstMiPtr;
|
|
QList<Core::MessageItem *> lstMi = view()->currentThreadAsMessageItemList();
|
|
if ( lstMi.isEmpty() ) {
|
|
return lstMiPtr;
|
|
}
|
|
foreach( Core::MessageItem *it, lstMi ) {
|
|
lstMiPtr.append( d->itemForRow( it->currentModelIndexRow() ) );
|
|
}
|
|
return lstMiPtr;
|
|
}
|
|
|
|
|
|
QList<Akonadi::MessageStatus> Widget::currentFilterStatus() const
|
|
{
|
|
return view()->currentFilterStatus();
|
|
}
|
|
|
|
QString Widget::currentFilterSearchString() const
|
|
{
|
|
return view()->currentFilterSearchString();
|
|
}
|
|
|
|
|
|
bool Widget::isThreaded() const
|
|
{
|
|
return view()->isThreaded();
|
|
}
|
|
|
|
bool Widget::selectionEmpty() const
|
|
{
|
|
return view()->selectionEmpty();
|
|
}
|
|
|
|
bool Widget::getSelectionStats(
|
|
Akonadi::Item::List &selectedItems,
|
|
Akonadi::Item::List &selectedVisibleItems,
|
|
bool * allSelectedBelongToSameThread,
|
|
bool includeCollapsedChildren ) const
|
|
{
|
|
if ( !storageModel() )
|
|
return false;
|
|
|
|
selectedItems.clear();
|
|
selectedVisibleItems.clear();
|
|
|
|
QList< Core::MessageItem * > selected = view()->selectionAsMessageItemList( includeCollapsedChildren );
|
|
|
|
Core::MessageItem * topmost = 0;
|
|
|
|
*allSelectedBelongToSameThread = true;
|
|
|
|
foreach( Core::MessageItem *it, selected ) {
|
|
const Item item = d->itemForRow( it->currentModelIndexRow() );
|
|
selectedItems.append( item );
|
|
if ( view()->isDisplayedWithParentsExpanded( it ) )
|
|
selectedVisibleItems.append( item );
|
|
if ( topmost == 0 )
|
|
topmost = ( *it ).topmostMessage();
|
|
else {
|
|
if ( topmost != ( *it ).topmostMessage() )
|
|
*allSelectedBelongToSameThread = false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Widget::deletePersistentSet( MessageList::Core::MessageItemSetReference ref )
|
|
{
|
|
view()->deletePersistentSet( ref );
|
|
}
|
|
|
|
void Widget::markMessageItemsAsAboutToBeRemoved( MessageList::Core::MessageItemSetReference ref, bool bMark )
|
|
{
|
|
QList< Core::MessageItem * > lstPersistent = view()->persistentSetCurrentMessageItemList( ref );
|
|
if ( !lstPersistent.isEmpty() )
|
|
view()->markMessageItemsAsAboutToBeRemoved( lstPersistent, bMark );
|
|
}
|
|
|
|
QList<Akonadi::Item> Widget::itemListFromPersistentSet( MessageList::Core::MessageItemSetReference ref )
|
|
{
|
|
QList<Akonadi::Item> lstItem;
|
|
QList< Core::MessageItem * > refList = view()->persistentSetCurrentMessageItemList( ref );
|
|
if ( !refList.isEmpty() ) {
|
|
foreach( Core::MessageItem *it, refList ) {
|
|
lstItem.append( d->itemForRow( it->currentModelIndexRow() ) );
|
|
}
|
|
}
|
|
return lstItem;
|
|
}
|
|
|
|
|
|
MessageList::Core::MessageItemSetReference Widget::selectionAsPersistentSet( bool includeCollapsedChildren ) const
|
|
{
|
|
QList<Core::MessageItem *> lstMi = view()->selectionAsMessageItemList( includeCollapsedChildren );
|
|
if ( lstMi.isEmpty() ) {
|
|
return -1;
|
|
}
|
|
return view()->createPersistentSet( lstMi );
|
|
}
|
|
|
|
MessageList::Core::MessageItemSetReference Widget::currentThreadAsPersistentSet() const
|
|
{
|
|
QList<Core::MessageItem *> lstMi = view()->currentThreadAsMessageItemList();
|
|
if ( lstMi.isEmpty() ) {
|
|
return -1;
|
|
}
|
|
return view()->createPersistentSet( lstMi );
|
|
}
|
|
|
|
Akonadi::Collection Widget::currentCollection() const
|
|
{
|
|
Collection::List collections = static_cast<const StorageModel*>( storageModel() )->displayedCollections();
|
|
if ( collections.size()!=1 )
|
|
return Akonadi::Collection(); // no folder here or too many (in case we can't decide where the drop will end)
|
|
return collections.first();
|
|
}
|
|
|
|
void Widget::slotCollapseItem()
|
|
{
|
|
view()->setCollapseItem(d->mGroupHeaderItemIndex);
|
|
}
|
|
|
|
void Widget::slotExpandItem()
|
|
{
|
|
view()->setExpandItem(d->mGroupHeaderItemIndex);
|
|
}
|
|
|