mainwindow.cpp Example File
serviceactions/mainwindow.cpp
#include "mainwindow.h"
#include "qmessageserviceaction.h"
#include <QComboBox>
#include <QListWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QTabWidget>
#include <QPointer>
#include <QPushButton>
#include <QDebug>
#include <QLineEdit>
#include <QTextEdit>
#include <QTextBrowser>
#include "attachmentlistwidget.h"
#include <QFileDialog>
#include <QTimer>
#include <QMessageBox>
#include <QThread>
#include <QStackedLayout>
#include <QPair>
#include <QScrollArea>
#include <QMenuBar>
#include <QApplication>
#include <QStackedWidget>
#include <QMutex>
#include <qmessagestore.h>
#include <QKeyEvent>
typedef QPointer<QMessageServiceAction> QMessageServiceActionPtr;
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()
{
QMessageAccountIdList ids = QMessageStore::instance()->queryAccounts();
m_parent->setIds(ids);
}
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;
if(!runonce)
m_loader.start();
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);
}
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(QMessageServiceAction::State s);
void messageUpdated(const QMessageId& id, const QMessageStore::NotificationFilterIdSet& filter);
void messageRemoved(const QMessageId& id, const QMessageStore::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;
QMessageServiceAction* m_service;
State m_state;
QMessageStore::NotificationFilterId m_storeFilterId;
};
RecentMessagesWidget::RecentMessagesWidget(QWidget* parent, unsigned int maxRecent)
:
QWidget(parent),
m_messageListWidget(0),
m_statusLabel(0),
m_layout(0),
m_maxRecent(maxRecent),
m_service(new QMessageServiceAction(this)),
m_state(Unloaded)
{
setupUi();
connect(m_service,SIGNAL(messagesFound(const QMessageIdList&)),this,SLOT(messagesFound(const QMessageIdList&)));
connect(m_service,SIGNAL(stateChanged(QMessageServiceAction::State)),this,SLOT(stateChanged(QMessageServiceAction::State)));
connect(QMessageStore::instance(),SIGNAL(messageUpdated(const QMessageId&, const QMessageStore::NotificationFilterIdSet&)),
this, SLOT(messageUpdated(const QMessageId&, const QMessageStore::NotificationFilterIdSet&)));
connect(QMessageStore::instance(),SIGNAL(messageRemoved(const QMessageId&, const QMessageStore::NotificationFilterIdSet&)),
this, SLOT(messageRemoved(const QMessageId&, const QMessageStore::NotificationFilterIdSet&)));
m_storeFilterId = QMessageStore::instance()->registerNotificationFilter(QMessageFilter());
}
RecentMessagesWidget::~RecentMessagesWidget()
{
QMessageStore::instance()->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->cancelOperation();
m_state = Unloaded;
m_ids.clear();
}
QWidget::hideEvent(e);
}
void RecentMessagesWidget::currentItemChanged(QListWidgetItem*, QListWidgetItem*)
{
if(m_state != Processing || m_state != Loading)
emit selected(currentMessage());
}
void RecentMessagesWidget::messagesFound(const QMessageIdList& ids)
{
m_ids.append(ids);
}
void RecentMessagesWidget::stateChanged(QMessageServiceAction::State s)
{
if(s == QMessageServiceAction::Failed)
m_state = LoadFailed;
else if(s == QMessageServiceAction::Successful && m_state != LoadFailed)
m_state = LoadFinished;
updateState();
}
void RecentMessagesWidget::messageUpdated(const QMessageId& id, const QMessageStore::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)
{
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 QMessageStore::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
}
void RecentMessagesWidget::load()
{
m_ids.clear();
if(!m_service->queryMessages(QMessageFilter(),QMessageOrdering::byReceptionTimeStamp(Qt::DescendingOrder),m_maxRecent))
m_state = LoadFailed;
else
m_state = Loading;
}
void RecentMessagesWidget::processResults()
{
if(!m_ids.isEmpty())
{
QMessageId id = m_ids.takeFirst();
QMessage message(id);
QListWidgetItem* newItem = new QListWidgetItem(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();
}
}
class ComposeSendWidget : public QWidget
{
Q_OBJECT
public:
ComposeSendWidget(QMessageServiceAction* 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;
QMessageServiceAction* 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(QMessageServiceAction* 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();
}
void ComposeSendWidget::composeButtonClicked()
{
QMessage message(constructQMessage());
m_service->compose(message);
}
void ComposeSendWidget::sendButtonClicked()
{
bool asHtml = (sender() == m_sendAsHTMLAction);
QMessage message(constructQMessage(asHtml));
m_service->send(message);
}
void ComposeSendWidget::addAttachmentButtonClicked()
{
QStringList filenames = QFileDialog::getOpenFileNames(this,tr("Select attachments"));
m_attachmentList->addAttachments(filenames);
}
void ComposeSendWidget::accountChanged()
{
#ifdef _WIN32_WCE
bool isSmsAccount = m_accountsWidget->currentAccountName() == "SMS";
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);
#endif
}
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);
}
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();
#ifdef _WIN32_WCE
QMessageAccount selectedAccount(selectedAccountId);
bool composingSms = selectedAccount.name() == "SMS";
#else
bool composingSms = false;
#endif
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(s,addressType));
message.setTo(toList);
if(!composingSms)
{
foreach(QString s, m_ccEdit->text().split(QRegExp("\\s"),QString::SkipEmptyParts))
ccList.append(QMessageAddress(s,QMessageAddress::Email));
message.setCc(ccList);
foreach(QString s, m_bccEdit->text().split(QRegExp("\\s"),QString::SkipEmptyParts))
bccList.append(QMessageAddress(s,QMessageAddress::Email));
message.setBcc(bccList);
message.setSubject(m_subjectEdit->text());
message.setType(QMessage::Email);
message.appendAttachments(m_attachmentList->attachments());
}
message.setParentAccountId(selectedAccountId);
if(!composingSms && asHtml) {
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;
}
class MessageViewWidget : public QWidget
{
Q_OBJECT
static const unsigned int LoadTimeLimit = 20;
static QString downloadLinkURL()
{
static const QString url("MessageViewWidget:
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(QMessageServiceAction::State s);
void loadTimeout();
void linkClicked(const QUrl&);
void messageUpdated(const QMessageId&, const QMessageStore::NotificationFilterIdSet& filterSet);
void messageRemoved(const QMessageId&, const QMessageStore::NotificationFilterIdSet& filterSet);
private:
enum State { Unloaded , Loaded, Loading, LoadFailed };
void setupUi();
void updateState();
void loadMessage();
void resetService();
private:
QStackedLayout* m_layoutStack;
QLabel* m_statusLabel;
QMessageServiceAction* m_service;
QLineEdit* m_fromLabel;
QLineEdit* m_subjectLabel;
QTextBrowser* m_messageBrowser;
QMessageId m_messageId;
State m_state;
QTimer m_loadTimer;
QMessageStore::NotificationFilterId m_storeFilterId;
};
MessageViewWidget::MessageViewWidget(QWidget* parent)
:
QWidget(parent),
m_layoutStack(0),
m_statusLabel(0),
m_service(new QMessageServiceAction(this)),
m_messageBrowser(0),
m_state(Unloaded)
{
setupUi();
resetService();
connect(&m_loadTimer,SIGNAL(timeout()),this,SLOT(loadTimeout()));
connect(QMessageStore::instance(),SIGNAL(messageUpdated(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)),
this,SLOT(messageUpdated(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)));
connect(QMessageStore::instance(),SIGNAL(messageRemoved(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)),
this,SLOT(messageRemoved(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)));
m_storeFilterId = QMessageStore::instance()->registerNotificationFilter(QMessageFilter());
}
MessageViewWidget::~MessageViewWidget()
{
QMessageStore::instance()->unregisterNotificationFilter(m_storeFilterId);
}
void MessageViewWidget::view(const QMessageId& messageId)
{
m_messageId = messageId;
m_state = m_messageId.isValid() ? Loaded : Unloaded;
updateState();
}
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;
}
void MessageViewWidget::showEvent(QShowEvent* e)
{
updateState();
QWidget::showEvent(e);
}
void MessageViewWidget::hideEvent(QHideEvent* e)
{
if(m_state == Loading)
{
m_service->cancelOperation();
m_state = Unloaded;
}
QWidget::hideEvent(e);
}
void MessageViewWidget::stateChanged(QMessageServiceAction::State s)
{
if(m_state == LoadFailed)
return;
if(s == QMessageServiceAction::InProgress)
m_state = Loading;
else if(s == QMessageServiceAction::Failed)
m_state = LoadFailed;
else if(s == QMessageServiceAction::Successful)
m_state = Loaded;
updateState();
}
void MessageViewWidget::loadTimeout()
{
qWarning() << "Load timeout";
m_service->cancelOperation();
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 QMessageStore::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 QMessageStore::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() == QMessageServiceAction::InProgress)
m_service->cancelOperation();
}
loadMessage();
m_layoutStack->setCurrentWidget(m_messageBrowser);
} break;
case LoadFailed:
{
m_statusLabel->setText("Download failed!");
m_layoutStack->setCurrentWidget(m_statusLabel);
} break;
}
}
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;
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().recipient())\
.arg(message.subject())\
.arg(message.receivedDate().toString())\
.arg(bodyText));
}
}
void MessageViewWidget::resetService()
{
if(m_service)
m_service->deleteLater();
m_service = new QMessageServiceAction(this);
connect(m_service,SIGNAL(stateChanged(QMessageServiceAction::State)),this,SLOT(stateChanged(QMessageServiceAction::State)));
}
class RetrieveWidget : public QWidget
{
Q_OBJECT
public:
RetrieveWidget(QWidget* parent = 0);
private slots:
void messageSelected(const QMessageId& messageId);
private:
void setupUi();
private:
QMessageServiceAction* 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(QMessageServiceAction* service, QWidget* parent = 0);
private slots:
void showButtonClicked();
private:
void setupUi();
private:
QMessageServiceAction* m_service;
RecentMessagesWidget* m_recentMessagesWidget;
};
ShowWidget::ShowWidget(QMessageServiceAction* service, QWidget* parent)
:
QWidget(parent),
m_service(service),
m_recentMessagesWidget(0)
{
setupUi();
}
void ShowWidget::showButtonClicked()
{
QMessageId id = m_recentMessagesWidget->currentMessage();
if(id.isValid())
m_service->show(id);
}
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 QMessageStore::NotificationFilterIdSet&);
void messageUpdated(const QMessageId&, const QMessageStore::NotificationFilterIdSet&);
void messageRemoved(const QMessageId&, const QMessageStore::NotificationFilterIdSet&);
private:
void setupUi();
void appendString(const QString& message);
private:
QListWidget* m_activityListWidget;
QMessageStore::NotificationFilterId m_notificationFilterId;
};
StoreSignalsWidget::StoreSignalsWidget(QWidget* parent)
:
QWidget(parent),
m_activityListWidget(0)
{
setupUi();
}
void StoreSignalsWidget::messageAdded(const QMessageId& id, const QMessageStore::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 QMessageStore::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 QMessageStore::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);
}
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(QMessageStore::instance(),
SIGNAL(messageAdded(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)),
this,
SLOT(messageAdded(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)));
connect(QMessageStore::instance(),
SIGNAL(messageRemoved(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)),
this,
SLOT(messageRemoved(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)));
connect(QMessageStore::instance(),
SIGNAL(messageUpdated(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)),
this,
SLOT(messageUpdated(const QMessageId&,const QMessageStore::NotificationFilterIdSet&)));
m_notificationFilterId = QMessageStore::instance()->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_serviceAction = new QMessageServiceAction(this);
connect(m_serviceAction,SIGNAL(stateChanged(QMessageServiceAction::State)),
this,SLOT(serviceStateChanged(QMessageServiceAction::State)));
m_widgetStack = new QStackedWidget(this);
setCentralWidget(m_widgetStack);
foreach(QWidget* exampleWidget, QWidgetList() << new ComposeSendWidget(m_serviceAction,this)
<< new ShowWidget(m_serviceAction,this)
<< new RetrieveWidget(this)
<< new StoreSignalsWidget(this)) {
m_widgetStack->addWidget(exampleWidget);
#ifdef _WIN32_WCE
exampleWidget->installEventFilter(this);
#endif
}
#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()));
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();
return false;
}
#endif
void MainWindow::serviceStateChanged(QMessageServiceAction::State state)
{
if(state == QMessageServiceAction::Failed)
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>