--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/serviceactions/mainwindow.cpp Wed Aug 25 15:49:42 2010 +0300
@@ -0,0 +1,1371 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "attachmentlistwidget.h"
+#include "qmessageservice.h"
+#include <qmessagemanager.h>
+#include <QComboBox>
+#include <QListWidget>
+#include <QVBoxLayout>
+#include <QLabel>
+#include <QTabWidget>
+#include <QPointer>
+#include <QPushButton>
+#include <QDebug>
+#include <QLineEdit>
+#include <QTextEdit>
+#include <QTextBrowser>
+#include <QFileDialog>
+#include <QTimer>
+#include <QMessageBox>
+#include <QThread>
+#include <QStackedLayout>
+#include <QPair>
+#include <QScrollArea>
+#include <QMenuBar>
+#include <QApplication>
+#include <QStackedWidget>
+#include <QMutex>
+#include <QKeyEvent>
+
+static const QSize WindowGeometry(400,300);
+static const QString WindowTitle("Service-actions Example");
+static unsigned int RecentMessagesCount = 50;
+
+class AccountsWidget : public QWidget
+{
+ Q_OBJECT
+
+private:
+ class Loader : public QThread
+ {
+ public:
+ Loader(AccountsWidget* parent);
+ void run();
+
+ private:
+ AccountsWidget* m_parent;
+ };
+
+public:
+ AccountsWidget(QWidget* parent = 0);
+ QMessageAccountId currentAccount() const;
+ QString currentAccountName() const;
+ bool isEmpty() const;
+
+signals:
+ void accountChanged();
+
+protected:
+ void showEvent(QShowEvent* e);
+ void hideEvent(QHideEvent* e);
+
+private slots:
+ void load();
+ void loadStarted();
+ void loadFinished();
+
+private:
+ void setupUi();
+ void setIds(const QMessageAccountIdList& ids);
+ QMessageAccountIdList ids() const;
+
+private:
+ QStackedLayout* m_stackedLayout;
+ QComboBox* m_accountsCombo;
+ QLabel* m_busyLabel;
+
+ Loader m_loader;
+ mutable QMutex m_loadMutex;
+ QMessageAccountIdList m_ids;
+};
+
+AccountsWidget::Loader::Loader(AccountsWidget* parent)
+:
+QThread(parent),
+m_parent(parent)
+{
+}
+
+void AccountsWidget::Loader::run()
+{
+ QMessageManager manager;
+ m_parent->setIds(manager.queryAccounts());
+}
+
+AccountsWidget::AccountsWidget(QWidget* parent)
+:
+QWidget(parent),
+m_stackedLayout(0),
+m_accountsCombo(0),
+m_busyLabel(0),
+m_loader(this)
+{
+ setupUi();
+
+ connect(&m_loader,SIGNAL(started()),this,SLOT(loadStarted()));
+ connect(&m_loader,SIGNAL(finished()),this,SLOT(loadFinished()));
+}
+
+QMessageAccountId AccountsWidget::currentAccount() const
+{
+ QMessageAccountId result;
+ if(m_loader.isFinished() && m_accountsCombo->count())
+ {
+ int index = m_accountsCombo->currentIndex();
+ return ids().at(index);
+ }
+
+ return result;
+}
+
+QString AccountsWidget::currentAccountName() const
+{
+ if(m_loader.isFinished() && m_accountsCombo->count())
+ return m_accountsCombo->itemData(m_accountsCombo->currentIndex()).toString();
+ return QString();
+}
+
+bool AccountsWidget::isEmpty() const
+{
+ return m_accountsCombo->count() == 0;
+}
+
+void AccountsWidget::showEvent(QShowEvent* e)
+{
+ load();
+ QWidget::showEvent(e);
+}
+
+void AccountsWidget::hideEvent(QHideEvent* e)
+{
+ if(m_loader.isRunning())
+ m_loader.exit();
+ QWidget::hideEvent(e);
+}
+
+void AccountsWidget::load()
+{
+ static bool runonce = false;
+ //#define NOTHREAD
+#ifdef NOTHREAD
+ QMessageManager manager;
+ if(!runonce)
+ setIds(manager.queryAccounts());
+ // m_loader.start();
+
+#else
+ // if(!runonce)
+ m_loader.start();
+#endif
+ runonce = true;
+}
+
+void AccountsWidget::loadStarted()
+{
+#ifndef _WIN32_WCE
+ setCursor(Qt::BusyCursor);
+#endif
+ m_stackedLayout->setCurrentWidget(m_busyLabel);
+}
+
+void AccountsWidget::loadFinished()
+{
+ m_accountsCombo->clear();
+
+ QMessageAccountIdList accountIds = ids();
+
+ if(!accountIds.isEmpty())
+ {
+ for(int i = 0; i < accountIds.count(); ++i)
+ {
+ QMessageAccount account(accountIds[i]);
+ m_accountsCombo->addItem(QString("%1 - %2").arg(i+1).arg(account.name()),account.name());
+ }
+
+ m_stackedLayout->setCurrentWidget(m_accountsCombo);
+ }
+ else
+ m_busyLabel->setText("No accounts!");
+
+#ifndef _WIN32_WCE
+ setCursor(Qt::ArrowCursor);
+#endif
+}
+
+void AccountsWidget::setupUi()
+{
+ m_stackedLayout = new QStackedLayout(this);
+
+ m_accountsCombo = new QComboBox(this);
+ m_stackedLayout->addWidget(m_accountsCombo);
+ connect(m_accountsCombo,SIGNAL(currentIndexChanged(int)),this,SIGNAL(accountChanged()));
+
+ m_busyLabel = new QLabel("Loading...");
+ m_stackedLayout->addWidget(m_busyLabel);
+
+ setSizePolicy(m_accountsCombo->sizePolicy());
+
+}
+
+void AccountsWidget::setIds(const QMessageAccountIdList& ids)
+{
+ QMutexLocker mutex(&m_loadMutex);
+
+ m_ids = ids;
+}
+
+QMessageAccountIdList AccountsWidget::ids() const
+{
+ QMutexLocker mutex(&m_loadMutex);
+ return m_ids;
+}
+
+class RecentMessagesWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ RecentMessagesWidget(QWidget* parent = 0, unsigned int maxRecent = 10);
+ ~RecentMessagesWidget();
+ QMessageId currentMessage() const;
+
+signals:
+ void selected(const QMessageId& messageId);
+
+protected:
+ void showEvent(QShowEvent* e);
+ void hideEvent(QHideEvent* e);
+
+private slots:
+ void currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous);
+ void messagesFound(const QMessageIdList& result);
+ void stateChanged(QMessageService::State s);
+ void messageUpdated(const QMessageId& id, const QMessageManager::NotificationFilterIdSet& filter);
+ void messageRemoved(const QMessageId& id, const QMessageManager::NotificationFilterIdSet& filter);
+ void processResults();
+
+private:
+ void setupUi();
+ void updateState();
+ void load();
+
+private:
+ enum State { Unloaded, Loading, LoadFinished, Processing, LoadFailed, Done };
+ static const int MessageIdRole = Qt::UserRole + 1;
+
+private:
+ QListWidget* m_messageListWidget;
+ QLabel* m_statusLabel;
+ QStackedLayout* m_layout;
+ QMessageIdList m_ids;
+ QMap<QMessageId,QListWidgetItem*> m_indexMap;
+ unsigned int m_maxRecent;
+ QMessageService* m_service;
+ State m_state;
+ QMessageManager::NotificationFilterId m_storeFilterId;
+ QMessageManager m_manager;
+};
+
+RecentMessagesWidget::RecentMessagesWidget(QWidget* parent, unsigned int maxRecent)
+:
+QWidget(parent),
+m_messageListWidget(0),
+m_statusLabel(0),
+m_layout(0),
+m_maxRecent(maxRecent),
+m_service(new QMessageService(this)),
+m_state(Unloaded)
+{
+ setupUi();
+ connect(m_service,SIGNAL(messagesFound(const QMessageIdList&)),this,SLOT(messagesFound(const QMessageIdList&)));
+ connect(m_service,SIGNAL(stateChanged(QMessageService::State)),this,SLOT(stateChanged(QMessageService::State)));
+
+ //register for message update notifications
+
+ connect(&m_manager, SIGNAL(messageUpdated(const QMessageId&, const QMessageManager::NotificationFilterIdSet&)),
+ this, SLOT(messageUpdated(const QMessageId&, const QMessageManager::NotificationFilterIdSet&)));
+ connect(&m_manager, SIGNAL(messageRemoved(const QMessageId&, const QMessageManager::NotificationFilterIdSet&)),
+ this, SLOT(messageRemoved(const QMessageId&, const QMessageManager::NotificationFilterIdSet&)));
+
+ m_storeFilterId = m_manager.registerNotificationFilter(QMessageFilter());
+}
+
+RecentMessagesWidget::~RecentMessagesWidget()
+{
+ m_manager.unregisterNotificationFilter(m_storeFilterId);
+}
+
+QMessageId RecentMessagesWidget::currentMessage() const
+{
+ QMessageId result;
+
+ if(QListWidgetItem* currentItem = m_messageListWidget->currentItem())
+ result = QMessageId(currentItem->data(MessageIdRole).toString());
+
+ return result;
+}
+
+void RecentMessagesWidget::showEvent(QShowEvent* e)
+{
+ if(m_state == Unloaded)
+ load();
+
+ updateState();
+
+ QWidget::showEvent(e);
+}
+
+void RecentMessagesWidget::hideEvent(QHideEvent* e)
+{
+ if(m_state == Loading || m_state == Processing)
+ {
+ m_service->cancel();
+ m_state = Unloaded;
+ m_ids.clear();
+ }
+
+ QWidget::hideEvent(e);
+}
+
+void RecentMessagesWidget::currentItemChanged(QListWidgetItem*, QListWidgetItem*)
+{
+ if(m_state != Processing || m_state != Loading)
+ emit selected(currentMessage());
+}
+
+//! [process-results]
+void RecentMessagesWidget::messagesFound(const QMessageIdList& ids)
+{
+ m_ids.append(ids);
+}
+//! [process-results]
+
+void RecentMessagesWidget::stateChanged(QMessageService::State newState)
+{
+ if (newState == QMessageService::FinishedState) {
+ if ((m_state != LoadFailed) && (m_service->error() == QMessageManager::NoError)) {
+ m_state = LoadFinished;
+ } else {
+ m_state = LoadFailed;
+ }
+ }
+
+ updateState();
+}
+
+
+void RecentMessagesWidget::messageUpdated(const QMessageId& id, const QMessageManager::NotificationFilterIdSet& filter)
+{
+ if(!filter.contains(m_storeFilterId) || m_state == Loading || !id.isValid() || !m_indexMap.contains(id))
+ return;
+
+ //update the pertinent entry to reflect completeness
+
+ QListWidgetItem* item = m_indexMap.value(id);
+ if(item)
+ {
+
+ QMessage message(id);
+ bool partialMessage = !message.find(message.bodyId()).isContentAvailable();
+ QFont itemFont = item->font();
+ itemFont.setItalic(partialMessage);
+ item->setFont(itemFont);
+ }
+}
+
+void RecentMessagesWidget::messageRemoved(const QMessageId& id, const QMessageManager::NotificationFilterIdSet& filter)
+{
+ if(!filter.contains(m_storeFilterId) || m_state == Loading || !id.isValid() || !m_indexMap.contains(id))
+ return;
+
+ QListWidgetItem* item = m_indexMap.value(id);
+ if(item)
+ {
+ int row = m_messageListWidget->row(item);
+ QListWidgetItem* item = m_messageListWidget->takeItem(row);
+ m_indexMap.remove(id);
+ delete item;
+ }
+ m_ids.removeAll(id);
+}
+
+void RecentMessagesWidget::setupUi()
+{
+ m_layout = new QStackedLayout(this);
+
+ m_messageListWidget = new QListWidget(this);
+ m_layout->addWidget(m_messageListWidget);
+ connect(m_messageListWidget,SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
+ this,SLOT(currentItemChanged(QListWidgetItem*,QListWidgetItem*)));
+
+ m_statusLabel = new QLabel(this);
+ m_statusLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ m_statusLabel->setFrameStyle(QFrame::Box);
+ m_layout->addWidget(m_statusLabel);
+
+}
+
+void RecentMessagesWidget::updateState()
+{
+ switch(m_state)
+ {
+ case Unloaded:
+ {
+ m_statusLabel->setText(QString());
+ m_layout->setCurrentWidget(m_statusLabel);
+ }
+ break;
+ case Loading:
+ {
+ m_statusLabel->setText("Loading...");
+ m_layout->setCurrentWidget(m_statusLabel);
+ }
+ break;
+ case LoadFinished:
+ {
+ if(m_ids.isEmpty())
+ {
+ m_statusLabel->setText("Finished. No messages.");
+ m_layout->setCurrentWidget(m_statusLabel);
+ }
+ else
+ {
+ m_state = Processing;
+ updateState();
+ processResults();
+ }
+ }
+ break;
+ case Processing:
+ m_layout->setCurrentWidget(m_messageListWidget);
+ break;
+ case LoadFailed:
+ {
+ m_statusLabel->setText("Load failed!");
+ m_layout->setCurrentWidget(m_statusLabel);
+ }
+ break;
+ }
+
+#ifndef _WIN32_WCE
+ if(m_state == Loading || m_state == Processing)
+ setCursor(Qt::BusyCursor);
+ else
+ setCursor(Qt::ArrowCursor);
+#endif
+
+}
+
+//! [load-message]
+void RecentMessagesWidget::load()
+{
+ m_ids.clear();
+ m_state = Loading;
+ bool b;
+
+ b=m_service->queryMessages(QMessageFilter(),QMessageSortOrder::byReceptionTimeStamp(Qt::DescendingOrder),m_maxRecent);
+//! [load-message]
+};
+
+//! [process-results2]
+void RecentMessagesWidget::processResults()
+{
+ if(!m_ids.isEmpty())
+ {
+ QMessageId id = m_ids.takeFirst();
+ QMessage message(id);
+
+ QListWidgetItem* newItem = new QListWidgetItem(message.from().addressee()+QString(":")+message.subject());
+ newItem->setData(MessageIdRole,id.toString());
+ QFont itemFont = newItem->font();
+ bool isPartialMessage = !message.find(message.bodyId()).isContentAvailable();
+ itemFont.setItalic(isPartialMessage);
+ newItem->setFont(itemFont);
+ m_messageListWidget->addItem(newItem);
+ m_indexMap.insert(id,newItem);
+ m_messageListWidget->update();
+ QTimer::singleShot(100,this,SLOT(processResults()));
+ }
+ else
+ {
+ m_state = Done;
+ updateState();
+ }
+}
+//! [process-results2]
+
+class ComposeSendWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ComposeSendWidget(QMessageService* service, QWidget* parent = 0);
+
+signals:
+ void actionsChanged();
+
+private slots:
+ void composeButtonClicked();
+ void sendButtonClicked();
+ void addAttachmentButtonClicked();
+ void accountChanged();
+
+private:
+ void setupUi();
+ QMessage constructQMessage(bool asHtml = false) const;
+
+private:
+ QStackedLayout* m_layoutStack;
+ QMessageService* m_service;
+ AccountsWidget* m_accountsWidget;
+ QLineEdit* m_toEdit;
+ QLineEdit* m_ccEdit;
+ QLabel* m_ccLabel;
+ QLineEdit* m_bccEdit;
+ QLabel* m_bccLabel;
+ QLineEdit* m_subjectEdit;
+ QLabel* m_subjectLabel;
+ QTextEdit* m_bodyEdit;
+ AttachmentListWidget* m_attachmentList;
+ QAction* m_attachmentsAction;
+ QAction* m_sendAsHTMLAction;
+};
+
+ComposeSendWidget::ComposeSendWidget(QMessageService* service, QWidget* parent)
+:
+QWidget(parent),
+m_layoutStack(0),
+m_service(service),
+m_accountsWidget(0),
+m_toEdit(0),
+m_ccEdit(0),
+m_ccLabel(0),
+m_bccEdit(0),
+m_bccLabel(0),
+m_subjectEdit(0),
+m_subjectLabel(0),
+m_bodyEdit(0),
+m_attachmentList(0),
+m_attachmentsAction(0),
+m_sendAsHTMLAction(0)
+{
+ setupUi();
+}
+
+static void notifyResult(bool result, const QString& description)
+{
+#ifndef _WIN32_WCE
+ if(result) QMessageBox::information(0,description,"Succeeded!");
+ else QMessageBox::critical(0,description,"Failed.");
+#else
+ Q_UNUSED(result);
+ Q_UNUSED(description);
+#endif
+}
+
+//! [send-compose-message]
+void ComposeSendWidget::composeButtonClicked()
+{
+ QMessage message(constructQMessage());
+ m_service->compose(message);
+}
+
+void ComposeSendWidget::sendButtonClicked()
+{
+ bool asHtml = (sender() == m_sendAsHTMLAction);
+ QMessage message(constructQMessage(asHtml));
+ notifyResult(m_service->send(message),"Send message");
+}
+//! [send-compose-message]
+
+void ComposeSendWidget::addAttachmentButtonClicked()
+{
+ QStringList filenames = QFileDialog::getOpenFileNames(this,tr("Select attachments"));
+ m_attachmentList->addAttachments(filenames);
+}
+
+void ComposeSendWidget::accountChanged()
+{
+ QMessageAccount currentAccount(m_accountsWidget->currentAccount());
+
+ bool isSmsAccount = (currentAccount.messageTypes() & QMessage::Sms) > 0;
+
+ foreach(QWidget* emailSpecificWidget , QList<QWidget*>() << m_bccEdit << m_bccLabel <<
+ m_ccEdit << m_ccLabel <<
+ m_subjectEdit << m_subjectLabel) {
+ emailSpecificWidget->setVisible(!isSmsAccount);
+ }
+
+ m_attachmentsAction->setEnabled(!isSmsAccount);
+ m_sendAsHTMLAction->setEnabled(!isSmsAccount);
+}
+
+void ComposeSendWidget::setupUi()
+{
+ QGridLayout* gl = new QGridLayout(this);
+
+ QLabel* accountLabel = new QLabel("Account:",this);
+ gl->addWidget(accountLabel,0,0);
+
+ m_accountsWidget = new AccountsWidget(this);
+ gl->addWidget(m_accountsWidget,0,1);
+
+ connect(m_accountsWidget,SIGNAL(accountChanged()),this,SLOT(accountChanged()));
+
+ QLabel* toLabel = new QLabel("To:",this);
+ gl->addWidget(toLabel,1,0);
+
+ m_toEdit = new QLineEdit(this);
+ gl->addWidget(m_toEdit,1,1);
+
+ m_ccLabel = new QLabel("Cc:",this);
+ gl->addWidget(m_ccLabel,2,0);
+
+ m_ccEdit = new QLineEdit(this);
+ gl->addWidget(m_ccEdit,2,1);
+
+ m_bccLabel = new QLabel("Bcc",this);
+ gl->addWidget(m_bccLabel,3,0);
+
+ m_bccEdit = new QLineEdit(this);
+ gl->addWidget(m_bccEdit,3,1);
+
+ m_subjectLabel = new QLabel("Subject:",this);
+ gl->addWidget(m_subjectLabel,4,0);
+
+ m_subjectEdit = new QLineEdit(this);
+ gl->addWidget(m_subjectEdit,4,1);
+
+ m_bodyEdit = new QTextEdit(this);
+ gl->addWidget(m_bodyEdit,5,0,1,2);
+
+ m_attachmentList = new AttachmentListWidget(this);
+ gl->addWidget(m_attachmentList,6,0,1,2);
+ m_attachmentList->hide();
+
+ QAction* composeAction = new QAction("Compose",this);
+ connect(composeAction,SIGNAL(triggered()),this,SLOT(composeButtonClicked()));
+ addAction(composeAction);
+
+ QAction* sendAction = new QAction("Send",this);
+ connect(sendAction,SIGNAL(triggered()),this,SLOT(sendButtonClicked()));
+ addAction(sendAction);
+
+ m_sendAsHTMLAction = new QAction("Send as HTML",this);
+ connect(m_sendAsHTMLAction,SIGNAL(triggered()),this,SLOT(sendButtonClicked()));
+ addAction(m_sendAsHTMLAction);
+
+ QAction* separator = new QAction(this);
+ separator->setSeparator(true);
+ addAction(separator);
+
+ m_attachmentsAction = new QAction("Add attachment",this);
+ connect(m_attachmentsAction,SIGNAL(triggered()),this,SLOT(addAttachmentButtonClicked()));
+ addAction(m_attachmentsAction);
+}
+
+
+//! [construct-message]
+QMessage ComposeSendWidget::constructQMessage(bool asHtml) const
+{
+ QMessage message;
+
+ if(m_accountsWidget->isEmpty())
+ {
+ QMessageBox::critical(const_cast<ComposeSendWidget*>(this),"No Accounts","Cannot send a message without any available accounts");
+ return message;
+ }
+
+ QMessageAccountId selectedAccountId = m_accountsWidget->currentAccount();
+ QMessageAccount selectedAccount(selectedAccountId);
+
+ bool composingSms = (selectedAccount.messageTypes() & QMessage::Sms) > 0;
+
+ QMessageAddressList toList;
+ QMessageAddressList ccList;
+ QMessageAddressList bccList;
+
+ QMessageAddress::Type addressType = QMessageAddress::Email;
+ if(composingSms)
+ {
+ addressType = QMessageAddress::Phone;
+ message.setType(QMessage::Sms);
+ }
+
+ foreach(QString s, m_toEdit->text().split(QRegExp("\\s"),QString::SkipEmptyParts))
+ toList.append(QMessageAddress(addressType, s));
+ message.setTo(toList);
+
+ if(!composingSms)
+ {
+ foreach(QString s, m_ccEdit->text().split(QRegExp("\\s"),QString::SkipEmptyParts))
+ ccList.append(QMessageAddress(QMessageAddress::Email, s));
+ message.setCc(ccList);
+
+ foreach(QString s, m_bccEdit->text().split(QRegExp("\\s"),QString::SkipEmptyParts))
+ bccList.append(QMessageAddress(QMessageAddress::Email, s));
+ message.setBcc(bccList);
+ message.setSubject(m_subjectEdit->text());
+
+ message.setType(QMessage::Email);
+
+ message.appendAttachments(m_attachmentList->attachments());
+ }
+
+ message.setParentAccountId(selectedAccountId);
+
+ if(!composingSms && asHtml) {
+ //create html body
+ QString htmlBody("<html><head><title></title></head><body><h2 align=center>%1</h2><hr>%2</body></html>");
+ message.setBody(htmlBody.arg(message.subject()).arg(m_bodyEdit->toPlainText()),"text/html");
+ }
+ else
+ message.setBody(m_bodyEdit->toPlainText());
+
+ return message;
+}
+//! [construct-message]
+
+class MessageViewWidget : public QWidget
+{
+ Q_OBJECT
+
+ static const unsigned int LoadTimeLimit = 20; //seconds
+
+ static QString downloadLinkURL()
+ {
+ static const QString url("MessageViewWidget://download");
+ return url;
+ };
+
+public:
+ MessageViewWidget(QWidget* parent = 0);
+ ~MessageViewWidget();
+
+ QMessageId viewing() const;
+
+public slots:
+ void view(const QMessageId& messageId);
+ bool retrieveBody();
+
+protected:
+ void showEvent(QShowEvent* e);
+ void hideEvent(QHideEvent* e);
+
+private slots:
+ void stateChanged(QMessageService::State s);
+ void loadTimeout();
+ void linkClicked(const QUrl&);
+ void messageUpdated(const QMessageId&, const QMessageManager::NotificationFilterIdSet& filterSet);
+ void messageRemoved(const QMessageId&, const QMessageManager::NotificationFilterIdSet& filterSet);
+
+
+private:
+ enum State { Unloaded , Loaded, Loading, LoadFailed };
+ void setupUi();
+ void updateState();
+ void loadMessage();
+ void resetService();
+
+private:
+ QStackedLayout* m_layoutStack;
+ QLabel* m_statusLabel;
+ QMessageService* m_service;
+ QLineEdit* m_fromLabel;
+ QLineEdit* m_subjectLabel;
+ QTextBrowser* m_messageBrowser;
+ QMessageId m_messageId;
+ State m_state;
+ QTimer m_loadTimer;
+ QMessageManager::NotificationFilterId m_storeFilterId;
+ QMessageManager m_manager;
+};
+
+MessageViewWidget::MessageViewWidget(QWidget* parent)
+:
+QWidget(parent),
+m_layoutStack(0),
+m_statusLabel(0),
+m_service(new QMessageService(this)),
+m_messageBrowser(0),
+m_state(Unloaded)
+{
+ setupUi();
+ resetService();
+ connect(&m_loadTimer,SIGNAL(timeout()),this,SLOT(loadTimeout()));
+ connect(&m_manager, SIGNAL(messageUpdated(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)),
+ this,SLOT(messageUpdated(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)));
+ connect(&m_manager, SIGNAL(messageRemoved(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)),
+ this,SLOT(messageRemoved(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)));
+ m_storeFilterId = m_manager.registerNotificationFilter(QMessageFilter());
+}
+
+MessageViewWidget::~MessageViewWidget()
+{
+ m_manager.unregisterNotificationFilter(m_storeFilterId);
+}
+
+void MessageViewWidget::view(const QMessageId& messageId)
+{
+ m_messageId = messageId;
+ m_state = m_messageId.isValid() ? Loaded : Unloaded;
+
+ updateState();
+}
+
+//! [retrieve-message-body]
+bool MessageViewWidget::retrieveBody()
+{
+ if(m_state != Loading && !m_loadTimer.isActive())
+ {
+ m_loadTimer.setSingleShot(true);
+ m_loadTimer.start(LoadTimeLimit * 1000);
+ m_state = Unloaded;
+
+ return m_service->retrieveBody(m_messageId);
+ }
+
+ return false;
+}
+
+//! [retrieve-message-body]
+
+void MessageViewWidget::showEvent(QShowEvent* e)
+{
+ updateState();
+ QWidget::showEvent(e);
+}
+
+void MessageViewWidget::hideEvent(QHideEvent* e)
+{
+ if(m_state == Loading)
+ {
+ m_service->cancel();
+ m_state = Unloaded;
+ }
+
+ QWidget::hideEvent(e);
+}
+
+void MessageViewWidget::stateChanged(QMessageService::State newState)
+{
+ if (m_state == LoadFailed)
+ return;
+
+ if (newState == QMessageService::ActiveState) {
+ m_state = Loading;
+ } else if (newState == QMessageService::FinishedState) {
+ m_state = (m_service->error() == QMessageManager::NoError ? Loaded : LoadFailed);
+ }
+
+ updateState();
+}
+
+void MessageViewWidget::loadTimeout()
+{
+ qWarning() << "Load timeout";
+ m_service->cancel();
+ m_state = LoadFailed;
+ updateState();
+}
+
+void MessageViewWidget::linkClicked(const QUrl& url)
+{
+ bool downloadLinkClicked = url.toString() == downloadLinkURL();
+
+ if(downloadLinkClicked)
+ retrieveBody();
+}
+
+void MessageViewWidget::messageUpdated(const QMessageId& id, const QMessageManager::NotificationFilterIdSet& filterSet)
+{
+ if(!filterSet.contains(m_storeFilterId) || m_state == Loading || !id.isValid() || id != m_messageId)
+ return;
+
+ view(id);
+}
+
+void MessageViewWidget::messageRemoved(const QMessageId& id, const QMessageManager::NotificationFilterIdSet& filterSet)
+{
+ if(id == m_messageId)
+ {
+ m_state = Unloaded;
+ m_loadTimer.stop();
+ m_messageId = QMessageId();
+ view(QMessageId());
+ }
+}
+
+QMessageId MessageViewWidget::viewing() const
+{
+ return m_messageId;
+}
+
+void MessageViewWidget::setupUi()
+{
+ m_layoutStack = new QStackedLayout(this);
+
+ m_statusLabel = new QLabel(this);
+ m_statusLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ m_layoutStack->addWidget(m_statusLabel);
+
+ m_messageBrowser = new QTextBrowser(this);
+ m_messageBrowser->setOpenLinks(false);
+ connect(m_messageBrowser,SIGNAL(anchorClicked(const QUrl&)),this,SLOT(linkClicked(const QUrl&)));
+ m_layoutStack->addWidget(m_messageBrowser);
+}
+
+void MessageViewWidget::updateState()
+{
+ switch(m_state)
+ {
+ case Unloaded:
+ {
+ m_messageBrowser->clear();
+ m_layoutStack->setCurrentWidget(m_messageBrowser);
+ } break;
+ case Loading:
+ {
+ m_statusLabel->setText("Downloading...");
+ m_layoutStack->setCurrentWidget(m_statusLabel);
+ } break;
+ case Loaded:
+ {
+ if(m_loadTimer.isActive())
+ {
+ m_loadTimer.stop();
+ if(m_service->state() == QMessageService::ActiveState)
+ m_service->cancel();
+ }
+
+ loadMessage();
+ m_layoutStack->setCurrentWidget(m_messageBrowser);
+ } break;
+ case LoadFailed:
+ {
+ m_statusLabel->setText("Download failed!");
+ m_layoutStack->setCurrentWidget(m_statusLabel);
+ } break;
+ }
+}
+
+//! [partial-message-check]
+void MessageViewWidget::loadMessage()
+{
+ m_messageBrowser->clear();
+
+ static const QString htmlTemplate("\
+ <html>\
+ <head>\
+ </head>\
+ <body>\
+ <table border=\"0\" cellspacing=\"0\">\
+ <tr><td><b>From: </b></td><td>%1</td></tr>\
+ <tr><td><b>Subject: </b></td><td>%2</td></tr>\
+ <tr><td><b>Date: </b></td><td>%3</td></tr>\
+ </table>\
+ <hr>%4\
+ <\body>\
+ </html>\
+ ");
+
+ if(m_messageId.isValid())
+ {
+ QMessage message(m_messageId);
+
+ QMessageContentContainer bodyPart = message.find(message.bodyId());
+
+ QString bodyText;
+
+ //for partial message display a download link instead
+
+ bool bodyAvailable = bodyPart.isContentAvailable();
+
+ if(bodyAvailable)
+ {
+ if(bodyPart.contentType() == "text")
+ bodyText = bodyPart.textContent();
+ else bodyText = "<Non-text content>";
+ }
+ else
+ bodyText = QString("<p align=\"center\"><a href=\"%1\">Download</a></p>").arg(downloadLinkURL());
+ m_messageBrowser->setHtml(htmlTemplate\
+ .arg(message.from().addressee())\
+ .arg(message.subject())\
+ .arg(message.receivedDate().toString())\
+ .arg(bodyText));
+ }
+}
+//! [partial-message-check]
+
+void MessageViewWidget::resetService()
+{
+ if(m_service)
+ m_service->deleteLater();
+ m_service = new QMessageService(this);
+ connect(m_service,SIGNAL(stateChanged(QMessageService::State)),this,SLOT(stateChanged(QMessageService::State)));
+}
+
+class RetrieveWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ RetrieveWidget(QWidget* parent = 0);
+
+private slots:
+ void messageSelected(const QMessageId& messageId);
+
+private:
+ void setupUi();
+
+private:
+ QMessageService* m_service;
+ RecentMessagesWidget* m_recentMessagesWidget;
+ MessageViewWidget* m_messageViewWidget;
+ QAction* m_retrieveAction;
+};
+
+RetrieveWidget::RetrieveWidget(QWidget* parent)
+:
+QWidget(parent),
+m_recentMessagesWidget(0),
+m_messageViewWidget(0),
+m_retrieveAction(0)
+{
+ setupUi();
+}
+
+void RetrieveWidget::messageSelected(const QMessageId& messageId)
+{
+ QMessage message(messageId);
+ bool partialMessage = !message.find(message.bodyId()).isContentAvailable();
+
+ m_retrieveAction->setEnabled(partialMessage && messageId.isValid());
+}
+
+void RetrieveWidget::setupUi()
+{
+ QVBoxLayout* l = new QVBoxLayout(this);
+ l->addWidget(new QLabel(QString("Last %1 messages:").arg(RecentMessagesCount),this));
+
+ m_recentMessagesWidget = new RecentMessagesWidget(this,RecentMessagesCount);
+ l->addWidget(m_recentMessagesWidget);
+
+ m_messageViewWidget = new MessageViewWidget(this);
+ l->addWidget(m_messageViewWidget);
+
+ m_retrieveAction = new QAction("Retrieve",this);
+ connect(m_retrieveAction,SIGNAL(triggered(bool)),m_messageViewWidget,SLOT(retrieveBody()));
+ addAction(m_retrieveAction);
+
+ connect(m_recentMessagesWidget,SIGNAL(selected(const QMessageId&)),m_messageViewWidget,SLOT(view(const QMessageId&)));
+ connect(m_recentMessagesWidget,SIGNAL(selected(const QMessageId&)),this,SLOT(messageSelected(const QMessageId&)));
+}
+
+class ShowWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ShowWidget(QMessageService* service, QWidget* parent = 0);
+
+private slots:
+ void showButtonClicked();
+
+private:
+ void setupUi();
+
+private:
+ QMessageService* m_service;
+ RecentMessagesWidget* m_recentMessagesWidget;
+};
+
+ShowWidget::ShowWidget(QMessageService* service, QWidget* parent)
+:
+QWidget(parent),
+m_service(service),
+m_recentMessagesWidget(0)
+{
+ setupUi();
+}
+
+//! [show-message]
+void ShowWidget::showButtonClicked()
+{
+
+ QMessageId id = m_recentMessagesWidget->currentMessage();
+
+ if(id.isValid())
+ m_service->show(id);
+}
+//! [show-message]
+
+void ShowWidget::setupUi()
+{
+ QVBoxLayout* vbl = new QVBoxLayout(this);
+
+ QString labelText("Last %1 messages:");
+ vbl->addWidget(new QLabel(labelText.arg(RecentMessagesCount),this));
+
+ m_recentMessagesWidget = new RecentMessagesWidget(this,RecentMessagesCount);
+ vbl->addWidget(m_recentMessagesWidget);
+
+ QAction* showAction = new QAction("Show",this);
+ connect(showAction,SIGNAL(triggered()),this,SLOT(showButtonClicked()));
+ addAction(showAction);
+}
+
+class StoreSignalsWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ StoreSignalsWidget(QWidget* parent = 0);
+
+private slots:
+ void messageAdded(const QMessageId&, const QMessageManager::NotificationFilterIdSet&);
+ void messageUpdated(const QMessageId&, const QMessageManager::NotificationFilterIdSet&);
+ void messageRemoved(const QMessageId&, const QMessageManager::NotificationFilterIdSet&);
+
+private:
+ void setupUi();
+ void appendString(const QString& message);
+
+private:
+ QListWidget* m_activityListWidget;
+ QMessageManager::NotificationFilterId m_notificationFilterId;
+ QMessageManager m_manager;
+};
+
+StoreSignalsWidget::StoreSignalsWidget(QWidget* parent)
+:
+QWidget(parent),
+m_activityListWidget(0)
+{
+ setupUi();
+}
+
+//! [store-signals]
+void StoreSignalsWidget::messageAdded(const QMessageId& id, const QMessageManager::NotificationFilterIdSet& filterSet)
+{
+ if(!filterSet.contains(m_notificationFilterId))
+ return;
+
+ QMessage message(id);
+
+ QString msg = QString("Added: %1").arg(message.subject());
+ m_activityListWidget->addItem(msg);
+}
+
+void StoreSignalsWidget::messageUpdated(const QMessageId& id, const QMessageManager::NotificationFilterIdSet& filterSet)
+{
+ if(!filterSet.contains(m_notificationFilterId))
+ return;
+
+ QMessage message(id);
+
+ QString msg = QString("Updated: %1").arg(message.subject());
+ m_activityListWidget->addItem(msg);
+}
+
+void StoreSignalsWidget::messageRemoved(const QMessageId& id, const QMessageManager::NotificationFilterIdSet& filterSet)
+{
+ if(!filterSet.contains(m_notificationFilterId))
+ return;
+
+ QString idString(id.toString());
+ idString.truncate(10);
+
+ QString msg = QString("Removed ID: %1 ...").arg(idString);
+ m_activityListWidget->addItem(msg);
+}
+//! [store-signals]
+
+void StoreSignalsWidget::setupUi()
+{
+ m_activityListWidget = new QListWidget(this);
+ QVBoxLayout* l = new QVBoxLayout(this);
+ l->setSpacing(0);
+ l->setContentsMargins(0,0,0,0);
+ l->addWidget(m_activityListWidget);
+
+ connect(&m_manager,
+ SIGNAL(messageAdded(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)),
+ this,
+ SLOT(messageAdded(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)));
+
+ connect(&m_manager,
+ SIGNAL(messageRemoved(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)),
+ this,
+ SLOT(messageRemoved(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)));
+
+ connect(&m_manager,
+ SIGNAL(messageUpdated(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)),
+ this,
+ SLOT(messageUpdated(const QMessageId&,const QMessageManager::NotificationFilterIdSet&)));
+
+ m_notificationFilterId = m_manager.registerNotificationFilter(QMessageFilter());
+
+ QAction* clearAction = new QAction("Clear",this);
+ connect(clearAction,SIGNAL(triggered(bool)),m_activityListWidget,SLOT(clear()));
+ addAction(clearAction);
+}
+
+MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f)
+:
+QMainWindow(parent,f),
+m_tabWidget(0)
+{
+
+ m_service = new QMessageService(this);
+
+ connect(m_service,SIGNAL(stateChanged(QMessageService::State)),
+ this,SLOT(serviceStateChanged(QMessageService::State)));
+
+ //example widgets
+
+ m_widgetStack = new QStackedWidget(this);
+ setCentralWidget(m_widgetStack);
+
+ foreach(QWidget* exampleWidget, QWidgetList() << new ComposeSendWidget(m_service,this)
+ << new ShowWidget(m_service,this)
+ << new RetrieveWidget(this)
+ << new StoreSignalsWidget(this)) {
+
+ m_widgetStack->addWidget(exampleWidget);
+#ifdef _WIN32_WCE
+ exampleWidget->installEventFilter(this);
+#endif
+ }
+
+ //main menu
+#ifndef _WIN32_WCE
+ QMenu* fileMenu = new QMenu("File",this);
+#endif
+
+ int index = 0;
+ foreach(QAction* viewAction, QList<QAction*>() << new QAction("Compose\\Send",this)
+ << new QAction("Show",this)
+ << new QAction("Retrieve/Query",this)
+ << new QAction("Store Signals",this))
+ {
+ connect(viewAction,SIGNAL(triggered()),this,SLOT(viewSelected()));
+#ifndef _WIN32_WCE
+ fileMenu->addAction(viewAction);
+#else
+ menuBar()->addAction(viewAction);
+#endif
+ viewAction->setData(index);
+ index++;
+ }
+#ifndef _WIN32_WCE
+ fileMenu->addSeparator();
+#else
+ menuBar()->addSeparator();
+#endif
+
+ QAction* quitAction = new QAction("Quit",this);
+ connect(quitAction,SIGNAL(triggered()),qApp,SLOT(quit()));
+#ifndef _WIN32_WCE
+ fileMenu->addAction(quitAction);
+ menuBar()->addMenu(fileMenu);
+#else
+ menuBar()->addAction(quitAction);
+#endif
+
+ QTimer::singleShot(0,this,SLOT(viewSelected()));
+
+ //window properties
+
+ setWindowTitle(WindowTitle);
+ resize(WindowGeometry);
+
+}
+
+#ifdef _WIN32_WCE
+bool MainWindow::eventFilter(QObject* source, QEvent* e)
+{
+ bool actionChanged = (m_widgetStack->currentWidget() == source) && e->type() == QEvent::ActionChanged;
+ if(actionChanged)
+ viewSelected(); //update the menu items
+ return false;
+}
+#endif
+
+void MainWindow::serviceStateChanged(QMessageService::State newState)
+{
+ if ((newState == QMessageService::FinishedState) && (m_service->error() != QMessageManager::NoError))
+ QMessageBox::critical(this,"Error","One or more service actions failed");
+}
+
+void MainWindow::viewSelected()
+{
+ static QMenu* actionMenu = 0;
+
+ if(!actionMenu)
+ {
+ actionMenu = new QMenu("Action",this);
+#ifndef _WIN32_WCE
+ menuBar()->addMenu(actionMenu);
+#endif
+ }
+ QAction* senderAction = qobject_cast<QAction*>(sender());
+ if(senderAction)
+ m_widgetStack->setCurrentIndex(senderAction->data().toInt());
+
+ bool currentViewHasActions = m_widgetStack->currentWidget() && !m_widgetStack->currentWidget()->actions().isEmpty();
+ actionMenu->clear();
+ if(currentViewHasActions)
+ {
+ foreach(QAction* a, m_widgetStack->currentWidget()->actions())
+ actionMenu->addAction(a);
+ }
+#ifdef _WIN32_WCE
+ static QAction* leftSoftButton = new QAction("Action",this);
+ leftSoftButton->setMenu(actionMenu);
+ menuBar()->setDefaultAction(leftSoftButton);
+#endif
+}
+
+#include <mainwindow.moc>
+