Fading version, replaces former patch.
From 6eaaa2c88459cde9c36c4598a8d6cd83a4070919 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20L=C3=BCbking?= <thomas.luebk...@gmail.com>
Date: Sat, 14 Sep 2013 01:03:00 +0200
Subject: [PATCH] cc scrolling
---
src/Gui/ComposeWidget.cpp | 127 +++++++++++++++++++++++++++++++++++++++++++++-
src/Gui/ComposeWidget.h | 5 ++
src/Gui/ComposeWidget.ui | 89 ++++++++++++++++++--------------
3 files changed, 181 insertions(+), 40 deletions(-)
diff --git a/src/Gui/ComposeWidget.cpp b/src/Gui/ComposeWidget.cpp
index 7eef98f..c7cbb54 100644
--- a/src/Gui/ComposeWidget.cpp
+++ b/src/Gui/ComposeWidget.cpp
@@ -23,10 +23,12 @@
#include <QAbstractProxyModel>
#include <QBuffer>
#include <QFileDialog>
+#include <QGraphicsOpacityEffect>
#include <QKeyEvent>
#include <QMenu>
#include <QMessageBox>
#include <QProgressDialog>
+#include <QPropertyAnimation>
#include <QPushButton>
#include <QSettings>
#include <QTimer>
@@ -56,15 +58,18 @@
namespace
{
-enum { OFFSET_OF_FIRST_ADDRESSEE = 1 };
+enum { OFFSET_OF_FIRST_ADDRESSEE = 1, MAX_VISIBLE_RECIPIENTS = 4 };
}
namespace Gui
{
+static const QString trojita_opacityAnimation("trojita_opacityAnimation");
+
ComposeWidget::ComposeWidget(MainWindow *mainWindow, QSettings *settings, MSA::MSAFactory *msaFactory) :
QWidget(0, Qt::Window),
ui(new Ui::ComposeWidget),
+ m_lastFocusedRecipient(NULL),
m_sentMail(false),
m_messageUpdated(false),
m_messageEverEdited(false),
@@ -101,6 +106,13 @@ ComposeWidget::ComposeWidget(MainWindow *mainWindow, QSettings *settings, MSA::M
m_recipientListUpdateTimer->setInterval(250);
connect(m_recipientListUpdateTimer, SIGNAL(timeout()), SLOT(updateRecipientList()));
+ connect(ui->recipientSlider, SIGNAL(valueChanged(int)), SLOT(scrollRecipients(int)));
+ connect (qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), SLOT(invalidateLastFocusedRecipient()));
+ ui->recipientSlider->setMinimum(0);
+ ui->recipientSlider->setMaximum(0);
+ ui->recipientSlider->setVisible(false);
+ ui->envelopeWidget->installEventFilter(this);
+
ui->mailText->setFont(Gui::Util::systemMonospaceFont());
connect(ui->mailText, SIGNAL(urlsAdded(QList<QUrl>)), SLOT(slotAttachFiles(QList<QUrl>)));
@@ -439,9 +451,20 @@ void ComposeWidget::addRecipient(int position, Composer::RecipientKind kind, con
connect(edit, SIGNAL(editingFinished()), SLOT(collapseRecipients()));
connect(edit, SIGNAL(textChanged(QString)), m_recipientListUpdateTimer, SLOT(start()));
m_recipients.insert(position, Recipient(combo, edit));
+ ui->envelopeWidget->setUpdatesEnabled(false);
ui->envelopeLayout->insertRow(actualRow(ui->envelopeLayout, position + OFFSET_OF_FIRST_ADDRESSEE), combo, edit);
setTabOrder(formPredecessor(ui->envelopeLayout, combo), combo);
setTabOrder(combo, edit);
+ const int max = qMax(0, m_recipients.count() - MAX_VISIBLE_RECIPIENTS);
+ ui->recipientSlider->setMaximum(max);
+ ui->recipientSlider->setVisible(max > 0);
+ if (ui->recipientSlider->isVisible()) {
+ const int v = ui->recipientSlider->value();
+ ui->recipientSlider->setValue((position+1)*max/m_recipients.count());
+ if (v == ui->recipientSlider->value()) // force scroll update
+ scrollRecipients(v);
+ }
+ ui->envelopeWidget->setUpdatesEnabled(true);
}
void ComposeWidget::slotCheckAddress()
@@ -473,6 +496,9 @@ void ComposeWidget::removeRecipient(int pos)
m_recipients.at(pos).first->deleteLater();
m_recipients.at(pos).second->deleteLater();
m_recipients.removeAt(pos);
+ const int max = qMax(0, m_recipients.count() - MAX_VISIBLE_RECIPIENTS);
+ ui->recipientSlider->setMaximum(max);
+ ui->recipientSlider->setVisible(max > 0);
}
static inline Composer::RecipientKind currentRecipient(const QComboBox *box)
@@ -501,6 +527,91 @@ void ComposeWidget::updateRecipientList()
}
}
+void ComposeWidget::invalidateLastFocusedRecipient()
+{
+ m_lastFocusedRecipient = QApplication::focusWidget(); // got explicit focus on other widget
+}
+
+void ComposeWidget::fadeIn(QWidget *w)
+{
+ QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(w);
+ w->setGraphicsEffect(effect);
+ QPropertyAnimation *animation = new QPropertyAnimation(effect, "opacity", w);
+ connect (animation, SIGNAL(finished()), SLOT(slotFadeFinished()));
+ animation->setObjectName(trojita_opacityAnimation);
+ animation->setDuration(333);
+ animation->setStartValue(0.0);
+ animation->setEndValue(1.0);
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+void ComposeWidget::slotFadeFinished()
+{
+ Q_ASSERT(sender());
+ QWidget *animatedEffectWidget = qobject_cast<QWidget*>(sender()->parent());
+ Q_ASSERT(animatedEffectWidget);
+ animatedEffectWidget->setGraphicsEffect(0); // deletes old one
+}
+
+void ComposeWidget::scrollRecipients(int value)
+{
+ // ignore focus changes caused by "scrolling"
+ disconnect (qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(invalidateLastFocusedRecipient()));
+
+ QList<QWidget*> visibleWidgets;
+ for (int i = 0; i < m_recipients.count(); ++i) {
+ // remove all widgets from the form because of vspacing - causes spurious padding
+
+ QWidget *toCC = m_recipients.at(i).first;
+ QWidget *lineEdit = m_recipients.at(i).second;
+ if (!m_lastFocusedRecipient) { // apply only _once_
+ if (toCC->hasFocus())
+ m_lastFocusedRecipient = toCC;
+ else if (lineEdit->hasFocus())
+ m_lastFocusedRecipient = lineEdit;
+ }
+ if (toCC->isVisible())
+ visibleWidgets << toCC;
+ if (lineEdit->isVisible())
+ visibleWidgets << lineEdit;
+ ui->envelopeLayout->removeWidget(toCC);
+ ui->envelopeLayout->removeWidget(lineEdit);
+ toCC->hide();
+ lineEdit->hide();
+ }
+
+ const int begin = qMin(m_recipients.count(), value);
+ const int end = qMin(m_recipients.count(), value + MAX_VISIBLE_RECIPIENTS);
+ for (int i = begin, j = 0; i < end; ++i, ++j) {
+ const int pos = actualRow(ui->envelopeLayout, j + OFFSET_OF_FIRST_ADDRESSEE);
+ QWidget *toCC = m_recipients.at(i).first;
+ QWidget *lineEdit = m_recipients.at(i).second;
+ ui->envelopeLayout->insertRow(pos, toCC, lineEdit);
+ if (!visibleWidgets.contains(toCC))
+ fadeIn(toCC);
+ visibleWidgets.removeOne(toCC);
+ if (!visibleWidgets.contains(lineEdit))
+ fadeIn(lineEdit);
+ visibleWidgets.removeOne(lineEdit);
+ toCC->show();
+ lineEdit->show();
+ setTabOrder(formPredecessor(ui->envelopeLayout, toCC), toCC);
+ setTabOrder(toCC, lineEdit);
+ if (toCC == m_lastFocusedRecipient)
+ toCC->setFocus();
+ else if (lineEdit == m_lastFocusedRecipient)
+ lineEdit->setFocus();
+ }
+
+ Q_FOREACH (QWidget *w, visibleWidgets) {
+ // was visible, is no longer -> stop animation so it won't conflict later ones
+ w->setGraphicsEffect(0); // deletes old one
+ if (QPropertyAnimation *pa = w->findChild<QPropertyAnimation*>(trojita_opacityAnimation))
+ pa->stop();
+ }
+ connect (qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), SLOT(invalidateLastFocusedRecipient()));
+}
+
void ComposeWidget::collapseRecipients()
{
QLineEdit *edit = qobject_cast<QLineEdit*>(sender());
@@ -614,6 +725,20 @@ bool ComposeWidget::eventFilter(QObject *o, QEvent *e)
}
return false;
}
+
+ if (o == ui->envelopeWidget) {
+ if (e->type() == QEvent::Wheel) {
+ int v = ui->recipientSlider->value();
+ if (static_cast<QWheelEvent*>(e)->delta() > 0)
+ --v;
+ else
+ ++v;
+ ui->recipientSlider->setValue(v);
+ e->accept();
+ return true;
+ }
+ return false;
+ }
return false;
}
diff --git a/src/Gui/ComposeWidget.h b/src/Gui/ComposeWidget.h
index 5185e5c..e5c40ed 100644
--- a/src/Gui/ComposeWidget.h
+++ b/src/Gui/ComposeWidget.h
@@ -89,6 +89,9 @@ private slots:
void gotError(const QString &error);
void sent();
void updateRecipientList();
+ void scrollRecipients(int);
+ void invalidateLastFocusedRecipient();
+ void slotFadeFinished();
void slotCheckAddress();
void slotCheckAddress(QLineEdit *edit);
@@ -111,6 +114,7 @@ private:
void addRecipient(int position, Composer::RecipientKind kind, const QString &address);
bool parseRecipients(QList<QPair<Composer::RecipientKind, Imap::Message::MailAddress> > &results, QString &errorMessage);
void removeRecipient(int position);
+ void fadeIn(QWidget *w);
bool buildMessageData();
bool shouldBuildMessageLocally() const;
@@ -123,6 +127,7 @@ private:
typedef QPair<QComboBox*, QLineEdit*> Recipient;
QList<Recipient> m_recipients;
QTimer *m_recipientListUpdateTimer;
+ QWidget *m_lastFocusedRecipient;
bool m_sentMail;
/** @short Has it been updated since the last time we auto-saved it? */
diff --git a/src/Gui/ComposeWidget.ui b/src/Gui/ComposeWidget.ui
index 11bfca6..1ff1b26 100644
--- a/src/Gui/ComposeWidget.ui
+++ b/src/Gui/ComposeWidget.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>715</width>
- <height>377</height>
+ <width>716</width>
+ <height>362</height>
</rect>
</property>
<property name="windowTitle">
@@ -15,16 +15,16 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
- <widget class="QSplitter" name="splitter">
+ <widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
- <widget class="QSplitter" name="splitter_2">
+ <widget class="QSplitter" name="splitter">
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
@@ -42,43 +42,54 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <layout class="QFormLayout" name="envelopeLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::ExpandingFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="fromLabel">
- <property name="text">
- <string>From</string>
- </property>
- <property name="buddy">
- <cstring>sender</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="sender">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QFormLayout" name="envelopeLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::ExpandingFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="fromLabel">
+ <property name="text">
+ <string>From</string>
+ </property>
+ <property name="buddy">
+ <cstring>sender</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="sender">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="subjectLabel">
+ <property name="text">
+ <string>Subject</string>
+ </property>
+ <property name="buddy">
+ <cstring>subject</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="LineEdit" name="subject"/>
+ </item>
+ </layout>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="subjectLabel">
- <property name="text">
- <string>Subject</string>
- </property>
- <property name="buddy">
- <cstring>subject</cstring>
+ <item>
+ <widget class="QScrollBar" name="recipientSlider">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="LineEdit" name="subject"/>
- </item>
</layout>
</widget>
<widget class="QGroupBox" name="groupBox">
@@ -161,7 +172,7 @@
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
- <verstretch>3</verstretch>
+ <verstretch>100</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
--
1.8.4