summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksW <qt-info@nokia.com>2009-05-07 18:06:28 +1000
committerAleksW <qt-info@nokia.com>2009-05-07 18:06:28 +1000
commit871d75f382edf04840fc805f9ba26896642cbc29 (patch)
treee76e0b6b57caf4f9309d6e4582f293dab9e25551
parent9887907dd98df020c12dc64f8d58ae1ff18bb8df (diff)
Improve attachment handling widget in email composer.2009W19
-rw-r--r--src/plugins/composers/email/attachmentlistwidget.cpp422
-rw-r--r--src/plugins/composers/email/attachmentlistwidget.h46
-rw-r--r--src/plugins/composers/email/email.pro6
-rw-r--r--src/plugins/composers/email/emailcomposer.cpp13
-rw-r--r--src/plugins/composers/email/emailcomposer.h8
5 files changed, 489 insertions, 6 deletions
diff --git a/src/plugins/composers/email/attachmentlistwidget.cpp b/src/plugins/composers/email/attachmentlistwidget.cpp
new file mode 100644
index 00000000..ab519686
--- /dev/null
+++ b/src/plugins/composers/email/attachmentlistwidget.cpp
@@ -0,0 +1,422 @@
+#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>
+
+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" << "");
+class AttachmentListWidget;
+
+class AttachmentListHeader : public QHeaderView
+{
+ Q_OBJECT
+public:
+ AttachmentListHeader(AttachmentListWidget* parent);
+
+signals:
+ void clear();
+
+protected:
+ void paintSection(QPainter * painter, const QRect & rect, int logicalIndex) const;
+ bool viewportEvent(QEvent* e);
+ void mouseMoveEvent(QMouseEvent* e);
+ 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 == 2 && 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);
+}
+
+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());
+}
+
+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
+{
+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;
+
+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
+{
+// QStyleOptionViewItem myStyle(option);
+// myStyle.state &= ~QStyle::State_HasFocus;
+ if(index.isValid() && index.column() == 2)
+ {
+ painter->save();
+ QFont font = painter->font();
+ QColor c = m_parent->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);
+}
+
+class AttachmentListView : public QTreeView
+{
+ Q_OBJECT
+
+public:
+ AttachmentListView(QWidget* parent = 0);
+
+signals:
+ void removeAttachmentAtIndex(int index);
+
+protected:
+ bool viewportEvent(QEvent* e);
+ void mouseMoveEvent(QMouseEvent* e);
+ void mousePressEvent(QMouseEvent* e);
+ bool overRemoveLink(QMouseEvent* e);
+};
+
+AttachmentListView::AttachmentListView(QWidget* parent)
+:
+QTreeView(parent)
+{
+ setMouseTracking(true);
+ installEventFilter(this);
+}
+
+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);
+}
+
+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() == 2)
+ {
+ 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;
+ 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);
+}
+
+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;
+ }
+ }
+ else if((role == Qt::DecorationRole || role == Qt::CheckStateRole )&& index.column() > 0)
+ return QVariant();
+ else if(role == Qt::CheckStateRole)
+ {
+ /*
+ Qt::CheckState state = static_cast<Qt::CheckState>(QMailAttachmentListModel::data(index,role).toInt());
+ if(state == Qt::Unchecked)
+ */
+ 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 = attachments;
+ 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);
+
+// m_clearLink->setAlignment(Qt::AlignHCenter);
+// layout->addWidget(m_clearLink);
+// connect(this,SIGNAL(attachmentsAdded(QStringList)),this,SLOT(updateClearLabel()));
+// connect(this,SIGNAL(attachmentsRemoved(QString)),this,SLOT(updateClearLabel()));
+ connect(m_clearLink,SIGNAL(linkActivated(QString)),this,SLOT(clearClicked()));
+ connect(m_listView,SIGNAL(removeAttachmentAtIndex(int)),this,SLOT(removeAttachmentAtIndex(int)));
+
+
+ // updateClearLabel();
+}
+
+QStringList AttachmentListWidget::attachments() const
+{
+ return m_attachments;
+}
+
+void AttachmentListWidget::addAttachment(const QString& attachment)
+{
+ if(m_attachments.contains(attachment))
+ return;
+ m_attachments.append(attachment);
+ m_model->setAttachments(m_attachments);
+ setVisible(!m_attachments.isEmpty());
+ emit attachmentsAdded(QStringList() << attachment);
+}
+
+void AttachmentListWidget::addAttachments(const QStringList& attachments)
+{
+ QSet<QString> result = attachments.toSet() - m_attachments.toSet();
+ m_attachments += result.toList();
+ m_model->setAttachments(m_attachments);
+ setVisible(!m_attachments.isEmpty());
+ emit attachmentsAdded(result.toList());
+}
+
+void AttachmentListWidget::removeAttachment(const QString& attachment)
+{
+ if(!m_attachments.contains(attachment))
+ return;
+
+ m_attachments.removeAll(attachment);
+ m_model->setAttachments(m_attachments);
+ setVisible(!m_attachments.isEmpty());
+ emit attachmentsRemoved(attachment);
+}
+
+void AttachmentListWidget::clear()
+{
+ m_attachments.clear();
+ m_model->setAttachments(m_attachments);
+ setVisible(false);
+}
+
+void AttachmentListWidget::updateClearLabel()
+{
+ int attachmentCount = m_attachments.count();
+ if(attachmentCount)
+ m_clearLink->setText("<b><a href=\"http://foo\">Clear " + QString::number(attachmentCount) + " attachment(s)</a></b>");
+}
+
+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_attachments.isEmpty());
+ emit attachmentsRemoved(attachment);
+}
+
+#include <attachmentlistwidget.moc>
+
diff --git a/src/plugins/composers/email/attachmentlistwidget.h b/src/plugins/composers/email/attachmentlistwidget.h
new file mode 100644
index 00000000..0aa30e36
--- /dev/null
+++ b/src/plugins/composers/email/attachmentlistwidget.h
@@ -0,0 +1,46 @@
+#ifndef ATTACHMENTLISTWIDGET_H
+#define ATTACHMENTLISTWIDGET_H
+
+#include <QWidget>
+
+class QListView;
+class QStringListModel;
+class QLabel;
+class QTreeView;
+class AttachmentListView;
+class AttachmentListModel;
+class AttachmentListDelegate;
+class QModelIndex;
+
+class AttachmentListWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ AttachmentListWidget(QWidget* parent = 0);
+ QStringList attachments() const;
+
+public slots:
+ void clear();
+ void addAttachment(const QString& attachment);
+ void addAttachments(const QStringList& attachments);
+ void removeAttachment(const QString& attachment);
+
+signals:
+ void attachmentsAdded(const QStringList& attachments);
+ void attachmentsRemoved(const QString& attachment);
+
+private slots:
+ void updateClearLabel();
+ void clearClicked();
+ void removeAttachmentAtIndex(int);
+
+private:
+ AttachmentListView* m_listView;
+ AttachmentListModel* m_model;
+ AttachmentListDelegate* m_delegate;
+ QStringList m_attachments;
+ QLabel* m_clearLink;
+};
+
+#endif
diff --git a/src/plugins/composers/email/email.pro b/src/plugins/composers/email/email.pro
index 74a6776a..f65a515e 100644
--- a/src/plugins/composers/email/email.pro
+++ b/src/plugins/composers/email/email.pro
@@ -13,9 +13,11 @@ INCLUDEPATH += . ../../../libraries/qmfutil \
LIBS += -L../../../libraries/qtopiamail -lqtopiamail \
-L../../../libraries/qmfutil -lqmfutil
-HEADERS += emailcomposer.h
+HEADERS += emailcomposer.h \
+ attachmentlistwidget.h
-SOURCES += emailcomposer.cpp
+SOURCES += emailcomposer.cpp \
+ attachmentlistwidget.cpp
TRANSLATIONS += libemailcomposer-ar.ts \
libemailcomposer-de.ts \
diff --git a/src/plugins/composers/email/emailcomposer.cpp b/src/plugins/composers/email/emailcomposer.cpp
index 9cb875c7..205c95c3 100644
--- a/src/plugins/composers/email/emailcomposer.cpp
+++ b/src/plugins/composers/email/emailcomposer.cpp
@@ -33,6 +33,11 @@
#include <QToolButton>
#include <qmailaccountkey.h>
#include <qmailstore.h>
+#include <QListWidget>
+#include <QPushButton>
+#include <QStringListModel>
+#include <QFileDialog>
+#include "attachmentlistwidget.h"
static int minimumLeftWidth = 65;
static const QString placeholder("(no subject)");
@@ -474,6 +479,9 @@ void EmailComposerInterface::updateAttachmentsLabel()
void EmailComposerInterface::selectAttachment()
{
+ QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select attachments"));
+ m_attachmentListWidget->addAttachments(fileNames);
+
/*
if (m_attachments.isEmpty() && m_addAttDialog->documentSelector()->documents().isEmpty()) {
QMessageBox::warning(this,
@@ -504,7 +512,8 @@ EmailComposerInterface::EmailComposerInterface( QWidget *parent )
m_recipientListWidget(0),
m_subjectEdit(0),
m_attachmentAction(0),
- m_title(QString())
+ m_title(QString()),
+ m_attachmentListWidget(0)
{
init();
}
@@ -558,6 +567,7 @@ void EmailComposerInterface::init()
m_attachmentsLabel = new QLabel(this);
layout->addWidget(m_attachmentsLabel);
m_attachmentsLabel->hide();
+ layout->addWidget(m_attachmentListWidget = new AttachmentListWidget(this));
// m_addAttDialog = new AddAttDialog(this, "attachmentDialog");
// connect(m_addAttDialog,SIGNAL(attachmentsChanged()),this,SLOT(updateAttachmentsLabel()));
@@ -724,6 +734,7 @@ void EmailComposerInterface::clear()
m_recipientListWidget->clear();
m_bodyEdit->clear();
+ m_attachmentListWidget->clear();
//m_addAttDialog->clear();
// Delete any temporary files we don't need
diff --git a/src/plugins/composers/email/emailcomposer.h b/src/plugins/composers/email/emailcomposer.h
index b3d79848..41d807a0 100644
--- a/src/plugins/composers/email/emailcomposer.h
+++ b/src/plugins/composers/email/emailcomposer.h
@@ -21,6 +21,7 @@ class QStackedWidget;
class DetailsPage;
class RecipientListWidget;
class QLineEdit;
+class AttachmentListWidget;
class EmailComposerInterface : public QMailComposerInterface
{
@@ -49,10 +50,8 @@ public:
public slots:
void clear();
-// void attach( const QContent &lnk, QMailMessage::AttachmentsAction = QMailMessage::LinkToAttachments );
+ //void attach( const QContent &lnk, QMailMessage::AttachmentsAction = QMailMessage::LinkToAttachments );
void setSignature( const QString &sig );
- void create(const QMailMessage& source);
- void reply(const QMailMessage& source, int action);
protected slots:
void selectAttachment();
@@ -61,6 +60,8 @@ protected slots:
void updateAttachmentsLabel();
private:
+ void create(const QMailMessage& source);
+ void reply(const QMailMessage& source, int action);
void init();
void setPlainText( const QString& text, const QString& signature );
void getDetails(QMailMessage& message) const;
@@ -75,6 +76,7 @@ private:
QStackedWidget* m_widgetStack;
QAction* m_attachmentAction;
RecipientListWidget* m_recipientListWidget;
+ AttachmentListWidget* m_attachmentListWidget;
QLineEdit* m_subjectEdit;
// typedef QPair<QContent, QMailMessage::AttachmentsAction> AttachmentDetail;