Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Toutes les fonctions  ·  Vues d'ensemble  · 

mainwindow.cpp Example File
serviceactions/mainwindow.cpp

    /****************************************************************************
    **
    ** Copyright (C) 2009 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:LGPL$
    ** No Commercial Usage
    ** This file contains pre-release code and may not be distributed.
    ** You may use this file in accordance with the terms and conditions
    ** contained in the Technology Preview License Agreement accompanying
    ** this package.
    **
    ** GNU Lesser General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU Lesser
    ** General Public License version 2.1 as published by the Free Software
    ** Foundation and appearing in the file LICENSE.LGPL included in the
    ** packaging of this file.  Please review the following information to
    ** ensure the GNU Lesser General Public License version 2.1 requirements
    ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    **
    ** In addition, as a special exception, Nokia gives you certain additional
    ** rights.  These rights are described in the Nokia Qt LGPL Exception
    ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    **
    ** If you have questions regarding the use of this file, please contact
    ** Nokia at qt-info@nokia.com.
    **
    **
    **
    **
    **
    **
    **
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/

    #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)));

        //register for message update notifications

        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;

        //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 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) {
            //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;
    }

    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(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();

                    //if(bodyPart.contentSubType() == "plain")
                    //    qWarning() << "Blah";
                    //else if(bodyPart.contentSubType() == "html" || bodyPart.contentSubType() == "rtf")
                    //     qWarning() << "FOO";
                    //else bodyText = "<Unknown text content>";
                }
                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()
    {
        //get the selected account

        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)));

        //example widgets

        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
        }

        //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(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>

Publicité

Best Of

Actualités les plus lues

Semaine
Mois
Année
  1. Microsoft ouvre aux autres compilateurs C++ AMP, la spécification pour la conception d'applications parallèles C++ utilisant le GPU 22
  2. « Quelque chose ne va vraiment pas avec les développeurs "modernes" », un développeur à "l'ancienne" critique la multiplication des bibliothèques 27
  3. Les développeurs ignorent-ils trop les failles découvertes dans leur code ? Prenez-vous en compte les remarques des autres ? 17
  4. RIM : « 13 % des développeurs ont gagné plus de 100 000 $ sur l'AppWord », Qt et open-source au menu du BlackBerry DevCon Europe 0
  5. BlackBerry 10 : premières images du prochain OS de RIM qui devrait intégrer des widgets et des tuiles inspirées de Windows Phone 0
  6. Adieu qmake, bienvenue qbs : Qt Building Suite, un outil déclaratif et extensible pour la compilation de projets Qt 17
  7. Quelles nouveautés de C++11 Visual C++ doit-il rapidement intégrer ? Donnez-nous votre avis 10
Page suivante

Le blog Digia au hasard

Logo

Déploiement d'applications Qt Commercial sur les tablettes Windows 8

Le blog Digia est l'endroit privilégié pour la communication sur l'édition commerciale de Qt, où des réponses publiques sont apportées aux questions les plus posées au support. Lire l'article.

Communauté

Ressources

Liens utiles

Contact

  • Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).

Qt dans le magazine

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt qtmobility-1.0-tp
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web