Silly me, forgot to attach patch file.
And I forgot to mention: composing dialog is centered on the screen containing 
trojita's main window, also tested with dual screen configuration in X11...


On Tuesday 26 July 2011 05:48:18 Thomas Gahr wrote:
> I worked a little on the compositor dialog - added Cancel button and fixed
> tabulator-order.
> I also implemented a rudimentary completion when entering a recipient.
> Known email addresses are rememberd and completed. So far they are not
> saved to a file (need to figure out good place to put these, QSettings
> will probably be a bad choice - maybe a trojitaknownmails.xml next to the
> settingsfile).
> 
> Cheers,
> Thomas
From c33f74bb8f407ebf63c9f8bc15e96c84a398ade6 Mon Sep 17 00:00:00 2001
From: thomas gahr <[email protected]>
Date: Tue, 26 Jul 2011 05:44:59 +0200
Subject: [PATCH] SMTP: some GUI-love, autocompletion for known recipients

---
 src/Gui/ComposeWidget.cpp |   33 +++++++++++++++-
 src/Gui/ComposeWidget.h   |    7 +++
 src/Gui/ComposeWidget.ui  |   97 +++++++++++++++++++++++++++++++++++++--------
 src/Gui/Window.cpp        |   13 ++++++
 4 files changed, 132 insertions(+), 18 deletions(-)

diff --git a/src/Gui/ComposeWidget.cpp b/src/Gui/ComposeWidget.cpp
index 9fca5d0..5b87d8b 100644
--- a/src/Gui/ComposeWidget.cpp
+++ b/src/Gui/ComposeWidget.cpp
@@ -22,6 +22,8 @@
 #include <QMessageBox>
 #include <QProgressDialog>
 #include <QSettings>
+#include <QCompleter>
+#include <QStringListModel>
 
 #include "ComposeWidget.h"
 #include "ui_ComposeWidget.h"
@@ -38,9 +40,21 @@ namespace {
 
 namespace Gui {
 
+//for now the list of known emails will simply be a static member
+//of this class
+//TODO: implement a model that has the ability to save/load the list
+//of known recipients via some backend (xml, plain text, whatever)
+//and use this instead of QStringListModel
+
+//I really hope static initialization will do no harm but for now this
+//should do until the abovementioned TODO is emplemented
+//Thomas Gahr 26 July 2011
+QScopedPointer<QAbstractListModel> ComposeWidget::_recipientCompleterModel(new QStringListModel);
+
 ComposeWidget::ComposeWidget(QWidget *parent) :
     QWidget(parent, Qt::Window),
-    ui(new Ui::ComposeWidget)
+    ui(new Ui::ComposeWidget),
+    _recipientCompleter(new QCompleter(this))
 {
     ui->setupUi(this);
     connect( ui->sendButton, SIGNAL(clicked()), this, SLOT(send()) );
@@ -51,6 +65,8 @@ ComposeWidget::ComposeWidget(QWidget *parent) :
     QFont font(QString::fromAscii("x-trojita-terminus-like-fixed-width"));
     font.setStyleHint(QFont::TypeWriter);
     ui->mailText->setFont(font);
+
+    _recipientCompleter->setModel(_recipientCompleterModel.data());
 }
 
 ComposeWidget::~ComposeWidget()
@@ -184,6 +200,7 @@ void ComposeWidget::addRecipient( int position, const QString& kind, const QStri
     combo->addItems( toCcBcc );
     combo->setCurrentIndex( toCcBcc.indexOf( kind ) );
     QLineEdit* edit = new QLineEdit( address, this );
+    edit->setCompleter( _recipientCompleter );
     _recipientsAddress.insert( position, edit );
     _recipientsKind.insert( position, combo );
     connect( edit, SIGNAL(editingFinished()), this, SLOT(handleRecipientAddressChange()) );
@@ -266,11 +283,25 @@ QList<QPair<QString, QString> > ComposeWidget::_parseRecipients()
             kind = QLatin1String("Cc");
         else if ( _recipientsKind[i]->currentText() == tr("Bcc") )
             kind = QLatin1String("Bcc");
+        //TODO: simplify recipient - i.e. strip stuff like < > or the real name
+        //=> only keep string around @ until either <,> or space is hit...
         res << qMakePair( kind, _recipientsAddress[i]->text() );
+        maybeAddNewKnownRecipient(_recipientsAddress[i]->text());
     }
     return res;
 }
 
+void ComposeWidget::maybeAddNewKnownRecipient(const QString &recipient)
+{
+    //assumption: currentIndex will be the found completion
+    _recipientCompleter->setCompletionPrefix(recipient);
+    if( _recipientCompleter->currentCompletion().isEmpty() ){
+        _recipientCompleterModel->insertRow(0);
+        QModelIndex idx=_recipientCompleterModel->index(0);
+        _recipientCompleterModel->setData(idx,recipient);
+    }
+}
+
 }
 
 
diff --git a/src/Gui/ComposeWidget.h b/src/Gui/ComposeWidget.h
index ded3409..83a65d1 100644
--- a/src/Gui/ComposeWidget.h
+++ b/src/Gui/ComposeWidget.h
@@ -22,6 +22,7 @@
 #define COMPOSEWIDGET_H
 
 #include <QWidget>
+#include <QScopedPointer>
 
 namespace Ui {
     class ComposeWidget;
@@ -29,6 +30,8 @@ namespace Ui {
 
 class QComboBox;
 class QLineEdit;
+class QCompleter;
+class QAbstractListModel;
 
 namespace Gui {
 
@@ -67,6 +70,10 @@ private:
 
     ComposeWidget(const ComposeWidget&); // don't implement
     ComposeWidget& operator=(const ComposeWidget&); // don't implement
+
+    QCompleter* _recipientCompleter;    //< completer for known / recently used recipients
+    static QScopedPointer<QAbstractListModel> _recipientCompleterModel;
+    void maybeAddNewKnownRecipient( const QString& recipient );
 };
 
 }
diff --git a/src/Gui/ComposeWidget.ui b/src/Gui/ComposeWidget.ui
index 4225dbb..ee28082 100644
--- a/src/Gui/ComposeWidget.ui
+++ b/src/Gui/ComposeWidget.ui
@@ -2,6 +2,14 @@
 <ui version="4.0">
  <class>ComposeWidget</class>
  <widget class="QWidget" name="ComposeWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>648</width>
+    <height>295</height>
+   </rect>
+  </property>
   <property name="windowTitle">
    <string>Compose Mail</string>
   </property>
@@ -17,32 +25,23 @@
     </widget>
    </item>
    <item row="1" column="1">
-    <widget class="QComboBox" name="sender"/>
-   </item>
-   <item row="3" column="0" colspan="2">
-    <widget class="QTextEdit" name="mailText">
+    <widget class="QComboBox" name="sender">
      <property name="sizePolicy">
-      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+      <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
        <horstretch>0</horstretch>
-       <verstretch>1</verstretch>
+       <verstretch>0</verstretch>
       </sizepolicy>
      </property>
     </widget>
    </item>
-   <item row="4" column="1">
-    <widget class="QPushButton" name="sendButton">
+   <item row="3" column="0" colspan="2">
+    <widget class="QTextEdit" name="mailText">
      <property name="sizePolicy">
-      <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
        <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
+       <verstretch>1</verstretch>
       </sizepolicy>
      </property>
-     <property name="layoutDirection">
-      <enum>Qt::RightToLeft</enum>
-     </property>
-     <property name="text">
-      <string>Send</string>
-     </property>
     </widget>
    </item>
    <item row="2" column="0">
@@ -105,8 +104,72 @@
      </property>
     </widget>
    </item>
+   <item row="7" column="0" colspan="2">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cancelButton">
+       <property name="text">
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="sendButton">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="layoutDirection">
+        <enum>Qt::RightToLeft</enum>
+       </property>
+       <property name="text">
+        <string>Send</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
   </layout>
  </widget>
+ <tabstops>
+  <tabstop>sender</tabstop>
+  <tabstop>subject</tabstop>
+  <tabstop>mailText</tabstop>
+  <tabstop>sendButton</tabstop>
+  <tabstop>cancelButton</tabstop>
+ </tabstops>
  <resources/>
- <connections/>
+ <connections>
+  <connection>
+   <sender>cancelButton</sender>
+   <signal>clicked()</signal>
+   <receiver>ComposeWidget</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>543</x>
+     <y>275</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>551</x>
+     <y>253</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
 </ui>
diff --git a/src/Gui/Window.cpp b/src/Gui/Window.cpp
index 32e9ae5..4629c3c 100644
--- a/src/Gui/Window.cpp
+++ b/src/Gui/Window.cpp
@@ -36,6 +36,7 @@
 #include <QToolBar>
 #include <QToolButton>
 #include <QUrl>
+#include <QDesktopWidget> //for Util::centerWidgetOnScreen
 
 #include "Window.h"
 #include "ComposeWidget.h"
@@ -69,6 +70,17 @@
 /** @short All user-facing widgets and related classes */
 namespace Gui {
 
+namespace Util {
+void centerWidgetOnScreen(QWidget* widget, QWidget* parent=0) {
+    widget->adjustSize();
+    widget->move( QApplication::desktop()->screenGeometry(
+                        parent? parent:widget->window()
+                      ).center()
+                  - widget->rect().center() );
+}
+
+}//namespace Util
+
 MainWindow::MainWindow(): QMainWindow(), model(0), m_ignoreStoredPassword(false)
 {
     setWindowTitle( trUtf8("Trojitá") );
@@ -880,6 +892,7 @@ void MainWindow::invokeComposeDialog( const QString& subject, const QString& bod
             s.value( Common::SettingsNames::addressKey ).toString() ),
         recipients, subject, body );
     w->setAttribute( Qt::WA_DeleteOnClose, true );
+    Util::centerWidgetOnScreen( w, this );
     w->show();
 }
 
-- 
1.7.6

Reply via email to