--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/serviceactions/attachmentlistwidget.cpp Wed Aug 25 15:49:42 2010 +0300
@@ -0,0 +1,515 @@
+/****************************************************************************
+**
+** 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 Messaging Framework.
+**
+** $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 "attachmentlistwidget.h"
+#include <QStringListModel>
+#include <QListView>
+#include <QVBoxLayout>
+#include <QLabel>
+#include <QDebug>
+#include <QMessageBox>
+#include <QDialogButtonBox>
+#include <QTreeView>
+#include <QFileInfo>
+#include <QItemDelegate>
+#include <QPainter>
+#include <QPointer>
+#include <QMouseEvent>
+#include <QHeaderView>
+//#include <support/qmailnamespace.h>
+
+class AttachmentListWidget;
+
+static QString sizeString(uint size)
+{
+ if(size < 1024)
+ return QObject::tr("%n byte(s)", "", size);
+ else if(size < (1024 * 1024))
+ return QObject::tr("%1 KB").arg(((float)size)/1024.0, 0, 'f', 1);
+ else if(size < (1024 * 1024 * 1024))
+ return QObject::tr("%1 MB").arg(((float)size)/(1024.0 * 1024.0), 0, 'f', 1);
+ else
+ return QObject::tr("%1 GB").arg(((float)size)/(1024.0 * 1024.0 * 1024.0), 0, 'f', 1);
+}
+
+static QStringList headers(QStringList() << "Attachment" << "Size" << "Type" << "");
+
+class AttachmentListHeader : public QHeaderView
+{
+ Q_OBJECT
+public:
+ AttachmentListHeader(AttachmentListWidget* parent);
+
+signals:
+ void clear();
+
+protected:
+ void paintSection(QPainter * painter, const QRect & rect, int logicalIndex) const;
+#ifndef QT_NO_CURSOR
+ bool viewportEvent(QEvent* e);
+ void mouseMoveEvent(QMouseEvent* e);
+#endif
+ void mousePressEvent(QMouseEvent* e);
+ bool overRemoveLink(QMouseEvent* e);
+
+
+private:
+ AttachmentListWidget* m_parent;
+ mutable QRect m_removeButtonRect;
+
+};
+
+AttachmentListHeader::AttachmentListHeader(AttachmentListWidget* parent)
+:
+QHeaderView(Qt::Horizontal,parent),
+m_parent(parent)
+{
+}
+
+void AttachmentListHeader::paintSection(QPainter * painter, const QRect & rect, int logicalIndex) const
+{
+ if(logicalIndex == 3 && m_parent->attachments().count() > 1)
+ {
+ painter->save();
+ QFont font = painter->font();
+ font.setUnderline(true);
+ painter->setFont(font);
+ painter->drawText(rect,Qt::AlignHCenter | Qt::AlignVCenter,"Remove All",&m_removeButtonRect);
+ painter->restore();
+ }
+ else
+ QHeaderView::paintSection(painter,rect,logicalIndex);
+}
+
+#ifndef QT_NO_CURSOR
+bool AttachmentListHeader::viewportEvent(QEvent* e)
+{
+ if(e->type() == QEvent::Leave)
+ setCursor(QCursor());
+ return QAbstractItemView::viewportEvent(e);
+}
+
+void AttachmentListHeader::mouseMoveEvent(QMouseEvent* e)
+{
+ QHeaderView::mouseMoveEvent(e);
+ if(overRemoveLink(e))
+ {
+ QCursor handCursor(Qt::PointingHandCursor);
+ setCursor(handCursor);
+ }
+ else if(cursor().shape() == Qt::PointingHandCursor)
+ setCursor(QCursor());
+}
+#endif
+
+void AttachmentListHeader::mousePressEvent(QMouseEvent* e)
+{
+ if(overRemoveLink(e))
+ emit clear();
+ QHeaderView::mousePressEvent(e);
+}
+
+bool AttachmentListHeader::overRemoveLink(QMouseEvent* e)
+{
+ return m_removeButtonRect.contains(e->pos());
+}
+
+class AttachmentListDelegate : public QItemDelegate
+{
+ Q_OBJECT
+public:
+ AttachmentListDelegate(AttachmentListWidget* parent = 0);
+ void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
+ bool isOverRemoveLink(const QRect& parentRect, const QPoint& pos) const;
+
+protected slots:
+ bool helpEvent(QHelpEvent * event, QAbstractItemView * view, const QStyleOptionViewItem & option, const QModelIndex & index);
+
+private:
+ QPointer<AttachmentListWidget> m_parent;
+};
+
+AttachmentListDelegate::AttachmentListDelegate(AttachmentListWidget* parent)
+:
+QItemDelegate(parent),
+m_parent(parent)
+{
+}
+
+void AttachmentListDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
+{
+ if(index.isValid() && index.column() == 3)
+ {
+ painter->save();
+ QFont font = painter->font();
+ QColor c = option.palette.brush(QPalette::Link).color();
+ font.setUnderline(true);
+ painter->setPen(c);
+ painter->setFont(font);
+ painter->drawText(option.rect,Qt::AlignHCenter,"Remove");
+ painter->restore();
+ }
+ else
+ QItemDelegate::paint(painter,option,index);
+}
+
+bool AttachmentListDelegate::isOverRemoveLink(const QRect& parentRect, const QPoint& pos) const
+{
+ QFont font;
+ font.setUnderline(true);
+ QFontMetrics fm(font);
+ QRect textRect = fm.boundingRect(parentRect,Qt::AlignHCenter,"Remove");
+ return textRect.contains(pos);
+}
+
+bool AttachmentListDelegate::helpEvent(QHelpEvent *, QAbstractItemView *view, const QStyleOptionViewItem &, const QModelIndex &index)
+{
+ if (!index.isValid()) {
+ view->setToolTip(QString());
+ return false;
+ }
+
+ QString attachment = m_parent->attachmentAt(index.row());
+ view->setToolTip(attachment);
+ return false;
+}
+
+class AttachmentListView : public QTreeView
+{
+ Q_OBJECT
+
+public:
+ AttachmentListView(QWidget* parent = 0);
+
+signals:
+ void removeAttachmentAtIndex(int index);
+
+protected:
+#ifndef QT_NO_CURSOR
+ bool viewportEvent(QEvent* e);
+ void mouseMoveEvent(QMouseEvent* e);
+#endif
+ void mousePressEvent(QMouseEvent* e);
+ bool overRemoveLink(QMouseEvent* e);
+};
+
+AttachmentListView::AttachmentListView(QWidget* parent)
+:
+QTreeView(parent)
+{
+ setMouseTracking(true);
+ installEventFilter(this);
+}
+
+#ifndef QT_NO_CURSOR
+bool AttachmentListView::viewportEvent(QEvent* e)
+{
+ if(e->type() == QEvent::Leave)
+ setCursor(QCursor());
+ return QAbstractItemView::viewportEvent(e);
+}
+
+void AttachmentListView::mouseMoveEvent(QMouseEvent* e)
+{
+ if(overRemoveLink(e))
+ {
+ QCursor handCursor(Qt::PointingHandCursor);
+ setCursor(handCursor);
+ }
+ else if(cursor().shape() == Qt::PointingHandCursor)
+ setCursor(QCursor());
+ QTreeView::mouseMoveEvent(e);
+}
+#endif
+
+void AttachmentListView::mousePressEvent(QMouseEvent* e)
+{
+ if(overRemoveLink(e))
+ {
+ QModelIndex index = indexAt(e->pos());
+ emit removeAttachmentAtIndex(index.row());
+ }
+ QTreeView::mousePressEvent(e);
+}
+
+bool AttachmentListView::overRemoveLink(QMouseEvent* e)
+{
+ QModelIndex index = indexAt(e->pos());
+ if(index.isValid() && index.column() == 3)
+ {
+ AttachmentListDelegate* delegate = static_cast<AttachmentListDelegate*>(itemDelegate());
+ return delegate->isOverRemoveLink(visualRect(index),e->pos());
+ }
+ return false;
+}
+
+class AttachmentListModel : public QAbstractListModel
+{
+public:
+ AttachmentListModel(QWidget* parent );
+ QVariant headerData(int section,Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
+
+ bool isEmpty() const;
+
+ int columnCount(const QModelIndex & parent = QModelIndex()) const;
+ int rowCount(const QModelIndex & parent = QModelIndex()) const;
+
+ QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
+
+ QStringList attachments() const;
+ void setAttachments(const QStringList& attachments);
+
+private:
+ QStringList m_attachments;
+};
+
+AttachmentListModel::AttachmentListModel(QWidget* parent)
+:
+QAbstractListModel(parent)
+{
+}
+
+QVariant AttachmentListModel::headerData(int section, Qt::Orientation o, int role) const
+{
+ if (role == Qt::DisplayRole)
+ {
+ if(section < headers.count())
+ return headers.at(section);
+ }
+
+ return QAbstractListModel::headerData(section,o,role);
+}
+
+bool AttachmentListModel::isEmpty() const
+{
+ return m_attachments.isEmpty();
+}
+
+int AttachmentListModel::columnCount(const QModelIndex & parent ) const
+{
+ Q_UNUSED(parent);
+ return headers.count();
+}
+
+int AttachmentListModel::rowCount(const QModelIndex& parent) const
+{
+ Q_UNUSED(parent);
+ return m_attachments.count();
+}
+
+QVariant AttachmentListModel::data( const QModelIndex & index, int role) const
+{
+ if(index.isValid())
+ {
+ if(role == Qt::DisplayRole && index.isValid())
+ {
+ QString path = m_attachments.at(index.row());
+ QFileInfo fi(path);
+
+ switch(index.column())
+ {
+ case 0:
+ return fi.fileName();
+ break;
+ case 1:
+ return sizeString(fi.size());
+ break;
+ case 2:
+ //QString mimeType = QMail::mimeTypeFromFileName(path);
+ //if(mimeType.isEmpty()) mimeType = "Unknown";
+ //return mimeType;
+ return "Unknown";
+ break;
+ }
+ }
+ else if((role == Qt::DecorationRole || role == Qt::CheckStateRole )&& index.column() > 0)
+ return QVariant();
+ else if(role == Qt::DecorationRole)
+ {
+ static QIcon attachIcon( ":icon/attach" );
+ return attachIcon;
+ }
+ }
+ return QVariant();
+}
+
+QStringList AttachmentListModel::attachments() const
+{
+ return m_attachments;
+}
+
+void AttachmentListModel::setAttachments(const QStringList& attachments)
+{
+ m_attachments.clear();
+
+ foreach (const QString &att, attachments) {
+ if (!att.startsWith("ref:") && !att.startsWith("partRef:")) {
+ m_attachments.append(att);
+ }
+ }
+
+ reset();
+}
+
+AttachmentListWidget::AttachmentListWidget(QWidget* parent)
+:
+QWidget(parent),
+m_listView(new AttachmentListView(this)),
+m_model(new AttachmentListModel(this)),
+m_delegate(new AttachmentListDelegate(this)),
+m_clearLink(new QLabel(this))
+{
+ m_clearLink->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
+ m_clearLink->setTextFormat(Qt::RichText);
+
+ m_listView->setModel(m_model);
+ m_listView->setSelectionMode(QAbstractItemView::NoSelection);
+ AttachmentListHeader* header = new AttachmentListHeader(this);
+ connect(header,SIGNAL(clear()),this,SLOT(clearClicked()));
+ m_listView->setHeader(header);
+ m_listView->header()->setStretchLastSection(true);
+ m_listView->header()->setResizeMode(QHeaderView::ResizeToContents);
+ m_listView->header()->setDefaultSectionSize(180);
+ m_listView->setUniformRowHeights(true);
+ m_listView->setRootIsDecorated(false);
+ m_listView->setItemDelegate(m_delegate);
+
+
+ QVBoxLayout* layout = new QVBoxLayout(this);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0,0,0,0);
+ layout->addWidget(m_listView);
+
+ connect(m_clearLink,SIGNAL(linkActivated(QString)),this,SLOT(clearClicked()));
+ connect(m_listView,SIGNAL(removeAttachmentAtIndex(int)),this,SLOT(removeAttachmentAtIndex(int)));
+}
+
+QStringList AttachmentListWidget::attachments() const
+{
+ return m_attachments;
+}
+
+QString AttachmentListWidget::attachmentAt(int index) const
+{
+ return m_attachments.at(index);
+}
+
+int AttachmentListWidget::count() const
+{
+ return m_attachments.count();
+}
+
+bool AttachmentListWidget::isEmpty() const
+{
+ return m_attachments.isEmpty();
+}
+
+void AttachmentListWidget::addAttachment(const QString& attachment)
+{
+ if(m_attachments.contains(attachment))
+ return;
+
+ m_attachments.append(attachment);
+
+ m_model->setAttachments(m_attachments);
+ setVisible(!m_model->isEmpty());
+
+ emit attachmentsAdded(QStringList() << attachment);
+}
+
+void AttachmentListWidget::addAttachments(const QStringList& attachments)
+{
+ QSet<QString> newAttachments = attachments.toSet() - m_attachments.toSet();
+
+ if (!newAttachments.isEmpty()) {
+ m_attachments += newAttachments.toList();
+
+ m_model->setAttachments(m_attachments);
+ setVisible(!m_model->isEmpty());
+
+ emit attachmentsAdded(newAttachments.toList());
+ }
+}
+
+void AttachmentListWidget::removeAttachment(const QString& attachment)
+{
+ if (!m_attachments.contains(attachment))
+ return;
+
+ m_attachments.removeAll(attachment);
+
+ m_model->setAttachments(m_attachments);
+ setVisible(!m_model->isEmpty());
+
+ emit attachmentsRemoved(attachment);
+}
+
+void AttachmentListWidget::clear()
+{
+ m_attachments.clear();
+ m_model->setAttachments(m_attachments);
+ setVisible(false);
+}
+
+void AttachmentListWidget::clearClicked()
+{
+ if(QMessageBox::question(this,
+ "Remove attachments",
+ QString("Remove %1 attachments?").arg(m_attachments.count()),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
+ clear();
+}
+
+void AttachmentListWidget::removeAttachmentAtIndex(int index)
+{
+ if(index >= m_attachments.count())
+ return;
+
+ QString attachment = m_attachments.at(index);
+ m_attachments.removeAt(index);
+
+ m_model->setAttachments(m_attachments);
+ setVisible(!m_model->isEmpty());
+
+ emit attachmentsRemoved(attachment);
+}
+
+#include <attachmentlistwidget.moc>
+