Bug 260788 - "magic next" button doesn't jump to mail in a subfolder of the inbox.
Summary: "magic next" button doesn't jump to mail in a subfolder of the inbox.
Status: CLOSED FIXED
Alias: None
Product: KMail Mobile
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Windows CE Microsoft Windows CE
: NOR normal
Target Milestone: ---
Assignee: kdepim bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-12-20 13:31 UTC by Ludwig Reiter
Modified: 2011-01-13 15:36 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ludwig Reiter 2010-12-20 13:31:49 UTC
Version:           unspecified (using Devel) 
OS:                Windows CE

version: 20101219-9-56


Reproducible: Always

Steps to Reproduce:
1. mark unread a mail in a subfolder of the inbox.
2. mark unread a mail in the inbox.
3. select the inbox unread mail.
4. click on the magic next button.
=> Nothing happens.
 


Expected Results:  
Should jump to the unread subfolder mail.
Comment 1 Tobias Koenig 2010-12-23 14:15:04 UTC
	A	 mobile/lib/collectionfetchwatcher.h	 [License: UNKNOWN]


	A	 mobile/lib/collectionfetchwatcher.cpp	 [License: UNKNOWN]

commit e82f635eb3ab5bc31dec73c56cf5dd10c9f70b01
Author: Tobias Koenig <tokoe@kde.org>
Date:   Thu Dec 23 14:15:56 2010 +0100

    Fix 'Next Unread Message' button
    
    When the next collection with unread messages has been selected we
    have to wait until the collection is completely loaded into the model,
    otherwise selectNextUnreadMessageInCurrentFolder() does not find the
    unread message.
    
    BUG: 260788

diff --git a/mobile/lib/CMakeLists.txt b/mobile/lib/CMakeLists.txt
index f2a60ea..4dcf5cd 100644
--- a/mobile/lib/CMakeLists.txt
+++ b/mobile/lib/CMakeLists.txt
@@ -12,6 +12,7 @@ set(mobileui_SRCS
     akonadibreadcrumbnavigationfactory.cpp
     breadcrumbnavigation.cpp
     breadcrumbnavigationcontext.cpp
+    collectionfetchwatcher.cpp
     declarativewidgetbase.cpp
     declarativeakonadiitem.cpp
     exporthandlerbase.cpp
diff --git a/mobile/lib/collectionfetchwatcher.cpp b/mobile/lib/collectionfetchwatcher.cpp
new file mode 100644
index 0000000..3725de5
--- /dev/null
+++ b/mobile/lib/collectionfetchwatcher.cpp
@@ -0,0 +1,94 @@
+/*
+    Copyright (C) 2010 Klarälvdalens Datakonsult AB,
+        a KDAB Group company, info@kdab.net,
+        author Tobias Koenig <tokoe@kdab.com>
+
+    This library is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Library General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    This library 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 Library General Public
+    License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to the
+    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+*/
+
+#include "collectionfetchwatcher.h"
+
+#include <akonadi/collectionstatistics.h>
+#include <akonadi/entitytreemodel.h>
+
+#include <QtCore/QAbstractItemModel>
+
+using namespace AkonadiFuture;
+
+class CollectionFetchWatcher::Private
+{
+  public:
+    Private( CollectionFetchWatcher *qq, const QModelIndex &index, const QAbstractItemModel *model )
+      : q( qq ), mIndex( index ), mModel( model )
+    {
+    }
+
+    void dataChanged( const QModelIndex &index, const QModelIndex& )
+    {
+      if ( index != mIndex )
+        return;
+
+      if ( mIndex.data( Akonadi::EntityTreeModel::FetchStateRole ).toInt() == Akonadi::EntityTreeModel::IdleState ) {
+        q->disconnect( mModel, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
+                       q, SLOT( dataChanged( const QModelIndex&, const QModelIndex& ) ) );
+
+        emit q->collectionFetched( mIndex );
+
+        q->deleteLater();
+      }
+    }
+
+    CollectionFetchWatcher *q;
+    QPersistentModelIndex mIndex;
+    const QAbstractItemModel *mModel;
+};
+
+CollectionFetchWatcher::CollectionFetchWatcher( const QModelIndex &index, const QAbstractItemModel *model, QObject *parent )
+  : QObject( parent ), d( new Private( this, index, model ) )
+{
+  Q_ASSERT( d->mIndex.model() == d->mModel ); // make sure we work on the right indexes/model
+}
+
+CollectionFetchWatcher::~CollectionFetchWatcher()
+{
+  delete d;
+}
+
+void CollectionFetchWatcher::start()
+{
+  const Akonadi::Collection collection = d->mIndex.data( Akonadi::EntityTreeModel::CollectionRole ).value<Akonadi::Collection>();
+  Q_ASSERT( collection.isValid() );
+
+  if ( collection.statistics().count() == 0 ) {
+    // no reason to wait, this collection does not contain any items
+    emit collectionFetched( d->mIndex );
+    deleteLater();
+    return;
+  }
+
+  // check if the loading has been finished already
+  if ( d->mIndex.data( Akonadi::EntityTreeModel::FetchStateRole ).toInt() == Akonadi::EntityTreeModel::IdleState ) {
+    emit collectionFetched( d->mIndex );
+    deleteLater();
+    return;
+  }
+
+  // start our work
+  connect( d->mModel, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
+           this, SLOT( dataChanged( const QModelIndex&, const QModelIndex& ) ) );
+}
+
+#include "collectionfetchwatcher.moc"
diff --git a/mobile/lib/collectionfetchwatcher.h b/mobile/lib/collectionfetchwatcher.h
new file mode 100644
index 0000000..27fe38a
--- /dev/null
+++ b/mobile/lib/collectionfetchwatcher.h
@@ -0,0 +1,81 @@
+/*
+    Copyright (C) 2010 Klarälvdalens Datakonsult AB,
+        a KDAB Group company, info@kdab.net,
+        author Tobias Koenig <tokoe@kdab.com>
+
+    This library is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Library General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    This library 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 Library General Public
+    License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to the
+    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+*/
+
+#ifndef AKONADI_COLLECTIONFETCHWATCHER_H
+#define AKONADI_COLLECTIONFETCHWATCHER_H
+
+#include "mobileui_export.h"
+
+#include <QtCore/QObject>
+
+class QAbstractItemModel;
+class QModelIndex;
+
+namespace AkonadiFuture {
+
+/**
+ * @short A class that encapsulates logic to wait for an collection to be completely loaded into a model.
+ *
+ * @author Tobias Koenig <tokoe@kde.org>
+ */
+class MOBILEUI_EXPORT CollectionFetchWatcher : public QObject
+{
+  Q_OBJECT
+
+  public:
+    /**
+     * Creates a new collection fetch watcher.
+     *
+     * @param index The model index of the collection to wait for.
+     * @param model The model to work on.
+     * @param parent The parent object.
+     */
+    CollectionFetchWatcher( const QModelIndex &index, const QAbstractItemModel *model, QObject *parent = 0 );
+
+    /**
+     * Destroys the collection fetch watcher.
+     */
+    ~CollectionFetchWatcher();
+
+    /**
+     * Starts watching the collection.
+     */
+    void start();
+
+  Q_SIGNALS:
+    /**
+     * This signal is emitted when the watched collection at @p index has been loaded completely into
+     * the model.
+     */
+    void collectionFetched( const QModelIndex &index );
+
+  private:
+    //@cond PRIVATE
+    class Private;
+    Private* const d;
+
+    Q_PRIVATE_SLOT( d, void dataChanged( const QModelIndex&, const QModelIndex& ) )
+    //@endcond
+};
+
+}
+
+#endif
diff --git a/mobile/mail/mainview.cpp b/mobile/mail/mainview.cpp
index b6c1881..6fd855a 100644
--- a/mobile/mail/mainview.cpp
+++ b/mobile/mail/mainview.cpp
@@ -26,6 +26,7 @@
 #include "actionhelper.h"
 #include "breadcrumbnavigation.h"
 #include "charsetselectiondialog.h"
+#include "collectionfetchwatcher.h"
 #include "composerview.h"
 #include "configwidget.h"
 #include "declarativewidgetbase.h"
@@ -1634,7 +1635,9 @@ void MainView::selectNextUnreadMessage()
   QModelIndex next = MailCommon::Util::nextUnreadCollection( model, model->index( 0, 0 ), MailCommon::Util::ForwardSearch );
   if ( next.isValid() ) {
     regularSelectionModel()->setCurrentIndex( next, QItemSelectionModel::ClearAndSelect );
-    selectNextUnreadMessageInCurrentFolder();
+    AkonadiFuture::CollectionFetchWatcher *watcher = new AkonadiFuture::CollectionFetchWatcher( next, model, this );
+    connect( watcher, SIGNAL( collectionFetched( const QModelIndex& ) ), SLOT( selectNextUnreadMessageInCurrentFolder() ) );
+    watcher->start();
   }
 }
 
diff --git a/mobile/mail/mainview.h b/mobile/mail/mainview.h
index 697850a..10bbfac 100644
--- a/mobile/mail/mainview.h
+++ b/mobile/mail/mainview.h
@@ -183,6 +183,7 @@ class MainView : public KDeclarativeMainView
     void selectOverrideEncoding();
     void toggleShowExtendedHeaders( bool );
     void messageListSettingsChanged( const MessageListSettings& );
+    bool selectNextUnreadMessageInCurrentFolder();
 
   private:
     void reply( quint64 id, MessageComposer::ReplyStrategy replyStrategy, bool quoteOriginal = true );
@@ -191,7 +192,6 @@ class MainView : public KDeclarativeMainView
     void recoverAutoSavedMessages();
     Akonadi::Item currentItem() const;
     MessageViewer::MessageViewItem *messageViewerItem();
-    bool selectNextUnreadMessageInCurrentFolder();
     uint currentFolderIdentity() const;
 
     bool mAskingToGoOnline;
Comment 2 Ludwig Reiter 2011-01-13 15:36:28 UTC
version 2011-01-12 git-b984b66

Magic button selects also the unread mails from the subfolder.
ok.