[kde-doc-english] [trojita] src/Gui: GUI: disable automatic preloading of the "other" multipart/alternative message parts
Jan Kundrát
jkt at flaska.net
Wed Jan 9 09:58:10 UTC 2013
Git commit 1e37120823fdfc55c4a8730fa1ad7521876b7601 by Jan Kundrát.
Committed on 09/01/2013 at 10:56.
Pushed by jkt into branch 'master'.
GUI: disable automatic preloading of the "other" multipart/alternative message parts
This has a nice side effect that the tab widget gets resized when the
part-to-be-loaded is bigger than the old part
M +24 -9 src/Gui/LoadablePartWidget.cpp
M +14 -6 src/Gui/LoadablePartWidget.h
M +20 -4 src/Gui/PartWidget.cpp
M +8 -4 src/Gui/PartWidgetFactory.cpp
M +7 -1 src/Gui/PartWidgetFactory.h
http://commits.kde.org/trojita/1e37120823fdfc55c4a8730fa1ad7521876b7601
diff --git a/src/Gui/LoadablePartWidget.cpp b/src/Gui/LoadablePartWidget.cpp
index 0d2b605..98e2b0c 100644
--- a/src/Gui/LoadablePartWidget.cpp
+++ b/src/Gui/LoadablePartWidget.cpp
@@ -29,24 +29,32 @@ namespace Gui
{
LoadablePartWidget::LoadablePartWidget(QWidget *parent, Imap::Network::MsgPartNetAccessManager *manager, const QModelIndex &part,
- QObject *wheelEventFilter, QObject *guiInteractionTarget):
+ QObject *wheelEventFilter, QObject *guiInteractionTarget, const LoadingTriggerMode mode):
QStackedWidget(parent), manager(manager), partIndex(part), realPart(0), wheelEventFilter(wheelEventFilter),
- guiInteractionTarget(guiInteractionTarget)
+ guiInteractionTarget(guiInteractionTarget), loadButton(0), m_loadOnShow(mode == LOAD_ON_SHOW)
{
Q_ASSERT(partIndex.isValid());
- loadButton = new QPushButton(tr("Load %1 (%2)").arg(partIndex.data(Imap::Mailbox::RolePartMimeType).toString(),
- Imap::Mailbox::PrettySize::prettySize(partIndex.data(Imap::Mailbox::RolePartOctets).toUInt())),
- this);
- connect(loadButton, SIGNAL(clicked()), this, SLOT(loadClicked()));
- addWidget(loadButton);
+ if (mode == LOAD_ON_CLICK) {
+ loadButton = new QPushButton(tr("Load %1 (%2)").arg(partIndex.data(Imap::Mailbox::RolePartMimeType).toString(),
+ Imap::Mailbox::PrettySize::prettySize(partIndex.data(Imap::Mailbox::RolePartOctets).toUInt())),
+ this);
+ connect(loadButton, SIGNAL(clicked()), this, SLOT(loadClicked()));
+ addWidget(loadButton);
+ }
}
void LoadablePartWidget::loadClicked()
{
if (!partIndex.isValid()) {
- loadButton->setEnabled(false);
+ if (loadButton) {
+ loadButton->setEnabled(false);
+ }
return;
}
+ if (loadButton) {
+ loadButton->deleteLater();
+ loadButton = 0;
+ }
realPart = new SimplePartWidget(this, manager, partIndex);
realPart->installEventFilter(wheelEventFilter);
realPart->connectGuiInteractionEvents(guiInteractionTarget);
@@ -59,6 +67,13 @@ QString LoadablePartWidget::quoteMe() const
return realPart ? realPart->quoteMe() : QString();
}
+void LoadablePartWidget::showEvent(QShowEvent *event)
+{
+ QStackedWidget::showEvent(event);
+ if (m_loadOnShow) {
+ m_loadOnShow = false;
+ loadClicked();
+ }
}
-
+}
diff --git a/src/Gui/LoadablePartWidget.h b/src/Gui/LoadablePartWidget.h
index a3ee04e..9ba7b13 100644
--- a/src/Gui/LoadablePartWidget.h
+++ b/src/Gui/LoadablePartWidget.h
@@ -33,21 +33,28 @@ class QPushButton;
namespace Gui
{
-/** @short Widget which implements "click-through" for loading message parts on demand
+/** @short Widget which implements delayed loading of message parts
+
+ This class supports two modes of loading, either a "click-through" one for loading message parts
+ on demand after the user clicks a button, or an "automated" mode where the data are loaded after
+ this widget becomes visible.
- When a policy dictates that certain body parts should not be shown unless
- really required, this widget comes to action. It provides a click-wrapped
- meaning of showing huge body parts. No data are transfered unless the user
- clicks a button.
*/
class LoadablePartWidget : public QStackedWidget, public AbstractPartWidget
{
Q_OBJECT
public:
+ /** @short Load when the widget becomes visible, or wait until the user clicks a button? */
+ typedef enum {
+ LOAD_ON_SHOW, /**< @short Load as soon as the widget becomes visible */
+ LOAD_ON_CLICK /**< @short Load onlt after the user has clicked a button */
+ } LoadingTriggerMode;
LoadablePartWidget(QWidget *parent, Imap::Network::MsgPartNetAccessManager *manager, const QModelIndex &part,
- QObject *wheelEventFilter, QObject *guiInteractionTarget);
+ QObject *wheelEventFilter, QObject *guiInteractionTarget, const LoadingTriggerMode mode);
QString quoteMe() const;
virtual void reloadContents() {}
+protected:
+ virtual void showEvent(QShowEvent *event);
private slots:
void loadClicked();
private:
@@ -57,6 +64,7 @@ private:
QObject *wheelEventFilter;
QObject *guiInteractionTarget;
QPushButton *loadButton;
+ bool m_loadOnShow;
LoadablePartWidget(const LoadablePartWidget &); // don't implement
LoadablePartWidget &operator=(const LoadablePartWidget &); // don't implement
diff --git a/src/Gui/PartWidget.cpp b/src/Gui/PartWidget.cpp
index d2fcdbe..640a962 100644
--- a/src/Gui/PartWidget.cpp
+++ b/src/Gui/PartWidget.cpp
@@ -51,17 +51,33 @@ MultipartAlternativeWidget::MultipartAlternativeWidget(QWidget *parent,
{
setContentsMargins(0,0,0,0);
int preferredIndex = -1;
+ // First loop iteration is used to find out what MIME type to show
for (int i = 0; i < partIndex.model()->rowCount(partIndex); ++i) {
- using namespace Imap::Mailbox;
QModelIndex anotherPart = partIndex.child(i, 0);
Q_ASSERT(anotherPart.isValid());
- QWidget *item = factory->create(anotherPart, recursionDepth + 1);
QString mimeType = anotherPart.data(Imap::Mailbox::RolePartMimeType).toString();
- addTab(item, mimeType);
if (preferredIndex == -1 && mimeType == preferredMimeType)
preferredIndex = i;
}
- setCurrentIndex(preferredIndex == -1 ? partIndex.model()->rowCount(partIndex) - 1 : preferredIndex);
+ if (preferredIndex == -1) {
+ // If no preference is obvious, let's assume the last item wins
+ preferredIndex = partIndex.model()->rowCount(partIndex) - 1;
+ }
+ // The second loop actually creates the widgets
+ for (int i = 0; i < partIndex.model()->rowCount(partIndex); ++i) {
+ QModelIndex anotherPart = partIndex.child(i, 0);
+ Q_ASSERT(anotherPart.isValid());
+ // TODO: This is actually not perfect, the preferred part of a multipart/alternative
+ // which is nested as a non-preferred part of another multipart/alternative actually gets loaded here.
+ // I can live with that.
+ QWidget *item = factory->create(anotherPart, recursionDepth + 1,
+ i == preferredIndex ?
+ PartWidgetFactory::LOAD_IMMEDIATELY :
+ PartWidgetFactory::LOAD_ON_SHOW);
+ QString mimeType = anotherPart.data(Imap::Mailbox::RolePartMimeType).toString();
+ addTab(item, mimeType);
+ }
+ setCurrentIndex(preferredIndex);
}
QString MultipartAlternativeWidget::quoteMe() const
diff --git a/src/Gui/PartWidgetFactory.cpp b/src/Gui/PartWidgetFactory.cpp
index e5e903d..01fe437 100644
--- a/src/Gui/PartWidgetFactory.cpp
+++ b/src/Gui/PartWidgetFactory.cpp
@@ -51,7 +51,7 @@ QWidget *PartWidgetFactory::create(const QModelIndex &partIndex)
return create(partIndex, 0);
}
-QWidget *PartWidgetFactory::create(const QModelIndex &partIndex, int recursionDepth)
+QWidget *PartWidgetFactory::create(const QModelIndex &partIndex, int recursionDepth, const PartLoadingMode loadingMode)
{
using namespace Imap::Mailbox;
Q_ASSERT(partIndex.isValid());
@@ -145,9 +145,10 @@ QWidget *PartWidgetFactory::create(const QModelIndex &partIndex, int recursionDe
Q_ASSERT(model);
Q_ASSERT(part);
part->fetchFromCache(model);
- bool showDirectly = true;
+
+ bool showDirectly = loadingMode == LOAD_IMMEDIATELY;
if (!part->fetched())
- showDirectly = model->isNetworkOnline() || part->octets() <= ExpensiveFetchThreshold;
+ showDirectly &= model->isNetworkOnline() || part->octets() <= ExpensiveFetchThreshold;
QWidget *widget = 0;
if (showDirectly) {
@@ -155,7 +156,10 @@ QWidget *PartWidgetFactory::create(const QModelIndex &partIndex, int recursionDe
static_cast<SimplePartWidget*>(widget)->connectGuiInteractionEvents(guiInteractionTarget);
} else if (model->isNetworkAvailable()) {
- widget = new LoadablePartWidget(0, manager, partIndex, wheelEventFilter, guiInteractionTarget);
+ widget = new LoadablePartWidget(0, manager, partIndex, wheelEventFilter, guiInteractionTarget,
+ loadingMode == LOAD_ON_SHOW && part->octets() <= ExpensiveFetchThreshold ?
+ LoadablePartWidget::LOAD_ON_SHOW :
+ LoadablePartWidget::LOAD_ON_CLICK);
} else {
widget = new QLabel(tr("Offline"), 0);
}
diff --git a/src/Gui/PartWidgetFactory.h b/src/Gui/PartWidgetFactory.h
index 0977ce6..85ef633 100644
--- a/src/Gui/PartWidgetFactory.h
+++ b/src/Gui/PartWidgetFactory.h
@@ -36,9 +36,15 @@ class PartWidgetFactory
Q_DECLARE_TR_FUNCTIONS(PartWidgetFactory)
enum { ExpensiveFetchThreshold = 50*1024 };
public:
+ /** @short Are the parts supposed to be visible immediately, or only after their respective widget is shown? */
+ typedef enum {
+ LOAD_IMMEDIATELY, /**< @short Load them immediately */
+ LOAD_ON_SHOW /**< @short Load the parts only after they have been shown to the user */
+ } PartLoadingMode;
+
PartWidgetFactory(Imap::Network::MsgPartNetAccessManager *manager, QObject *wheelEventFilter, QObject *guiInteractionTarget);
QWidget *create(const QModelIndex &partIndex);
- QWidget *create(const QModelIndex &partIndex, int recursionDepth);
+ QWidget *create(const QModelIndex &partIndex, int recursionDepth, const PartLoadingMode loadingMode = LOAD_IMMEDIATELY);
private:
Imap::Network::MsgPartNetAccessManager *manager;
QObject *wheelEventFilter;
More information about the kde-doc-english
mailing list