File indexing completed on 2024-11-24 04:53:00

0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
0002 
0003    This file is part of the Trojita Qt IMAP e-mail client,
0004    http://trojita.flaska.net/
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU General Public License as
0008    published by the Free Software Foundation; either version 2 of
0009    the License or (at your option) version 3 or any later version
0010    accepted by the membership of KDE e.V. (or its successor approved
0011    by the membership of KDE e.V.), which shall act as a proxy
0012    defined in Section 14 of version 3 of the license.
0013 
0014    This program is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017    GNU General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 #ifndef COMPOSEWIDGET_H
0023 #define COMPOSEWIDGET_H
0024 
0025 #include <memory>
0026 
0027 #include <QList>
0028 #include <QMap>
0029 #include <QPersistentModelIndex>
0030 #include <QUrl>
0031 #include <QPointer>
0032 #include <QWidget>
0033 
0034 #include "Common/Logging.h"
0035 #include "Composer/Recipients.h"
0036 #include "Composer/MessageComposer.h"
0037 #include "Plugins/AddressbookPlugin.h"
0038 
0039 
0040 namespace Ui
0041 {
0042 class ComposeWidget;
0043 }
0044 
0045 class QAbstractListModel;
0046 class QActionGroup;
0047 class QComboBox;
0048 class QLineEdit;
0049 class QMenu;
0050 class QPushButton;
0051 class QSettings;
0052 class QToolButton;
0053 
0054 namespace Composer {
0055 class Submission;
0056 }
0057 
0058 namespace MSA {
0059 class MSAFactory;
0060 }
0061 
0062 namespace Gui
0063 {
0064 
0065 class MainWindow;
0066 
0067 class InhibitComposerDirtying;
0068 
0069 class ComposerSaveState;
0070 
0071 /** @short A "Compose New Mail..." dialog
0072 
0073   Implements a widget which can act as a standalone window for composing e-mail messages.
0074   Uses Imap::Mailbox::MessageComposer as a backend for composing a message. @see Imap::Mailbox::MessageComposer
0075 
0076   */
0077 class ComposeWidget : public QWidget
0078 {
0079     Q_OBJECT
0080 public:
0081     ~ComposeWidget();
0082     static ComposeWidget *warnIfMsaNotConfigured(ComposeWidget *widget, MainWindow *mainWindow);
0083     static ComposeWidget *createDraft(MainWindow *mainWindow, const QString &path);
0084     static ComposeWidget *createBlank(MainWindow *mainWindow);
0085     static ComposeWidget *createFromUrl(MainWindow *mainWindow, const QUrl &url);
0086     static ComposeWidget *createReply(MainWindow *mainWindow, const Composer::ReplyMode &mode, const QModelIndex &replyingToMessage,
0087                                       const QList<QPair<Composer::RecipientKind, QString> > &recipients, const QString &subject,
0088                                       const QString &body, const QList<QByteArray> &inReplyTo, const QList<QByteArray> &references);
0089     static ComposeWidget *createForward(MainWindow *mainWindow, const Composer::ForwardMode mode, const QModelIndex &forwardingMessage,
0090                                         const QString &subject, const QList<QByteArray> &inReplyTo, const QList<QByteArray> &references);
0091     static ComposeWidget *createFromReadOnly(MainWindow *mainWindow, const QModelIndex &messageRoot, const QList<QPair<Composer::RecipientKind, QString>> &recipients);
0092     void placeOnMainWindow();
0093 protected:
0094     void changeEvent(QEvent *e);
0095     void closeEvent(QCloseEvent *ce);
0096     bool eventFilter(QObject *o, QEvent *e);
0097 
0098 private slots:
0099     void calculateMaxVisibleRecipients();
0100     void collapseRecipients();
0101     void completeRecipient(QAction *act);
0102     void completeRecipients(const QString &text);
0103     void send();
0104     void gotError(const QString &error);
0105     void sent();
0106     void updateRecipientList();
0107     void scrollRecipients(int);
0108     void gotoNextInputLineFrom(QWidget *w);
0109     void handleFocusChange();
0110     void scrollToFocus();
0111     void slotFadeFinished();
0112 
0113     void slotCheckAddressOfSender();
0114     void slotCheckAddress(QLineEdit *edit);
0115 
0116     void slotAskForFileAttachment();
0117     void slotAttachFiles(QList<QUrl> urls);
0118 
0119     void slotUpdateSignature();
0120     void updateWindowTitle();
0121 
0122     void autoSaveDraft();
0123     void setMessageUpdated();
0124 
0125     void setUiWidgetsEnabled(const bool enabled);
0126 
0127     void onCompletionAvailable(const Plugins::NameEmailList &completion);
0128     void onCompletionFailed(Plugins::AddressbookJob::Error error);
0129 
0130     void passwordRequested(const QString &user, const QString &host);
0131     void passwordError();
0132     void toggleReplyMarking();
0133     void updateReplyMarkingAction();
0134     void updateReplyMode();
0135     void markReplyModeHandpicked();
0136 
0137 signals:
0138     void logged(const Common::LogKind kind, const QString& source, const QString& message);
0139 
0140 private:
0141     ComposeWidget(MainWindow *mainWindow, std::shared_ptr<Composer::AbstractComposer> messageComposer, MSA::MSAFactory *msaFactory);
0142     void setResponseData(const QList<QPair<Composer::RecipientKind, QString> > &recipients, const QString &subject,
0143                          const QString &body, const QList<QByteArray> &inReplyTo, const QList<QByteArray> &references,
0144                          const QModelIndex &replyingToMessage);
0145     bool setReplyMode(const Composer::ReplyMode mode);
0146 
0147     static QByteArray extractMailAddress(const QString &text, bool &ok);
0148     static Composer::RecipientKind recipientKindForNextRow(const Composer::RecipientKind kind);
0149     void addRecipient(int position, Composer::RecipientKind kind, const QString &address);
0150     bool parseRecipients(QList<QPair<Composer::RecipientKind, Imap::Message::MailAddress> > &results, QString &errorMessage);
0151     void removeRecipient(int position);
0152     void fadeIn(QWidget *w);
0153     void askPassword(const QString &user, const QString &host);
0154 
0155     bool buildMessageData();
0156     bool shouldBuildMessageLocally() const;
0157 
0158     void saveDraft(const QString &path);
0159     void loadDraft(const QString &path);
0160 
0161     std::shared_ptr<Composer::MessageComposer> interactiveComposer();
0162 
0163     Ui::ComposeWidget *ui;
0164     QPushButton *sendButton;
0165     QPushButton *cancelButton;
0166     QToolButton *m_markButton;
0167     QActionGroup *m_markAsReply;
0168     QAction *m_actionStandalone;
0169     QAction *m_actionInReplyTo;
0170     QAction *m_actionToggleMarking;
0171     QToolButton *m_replyModeButton;
0172     QActionGroup *m_replyModeActions;
0173     QAction *m_actionHandPickedRecipients;
0174     QAction *m_actionReplyModePrivate;
0175     QAction *m_actionReplyModeAllButMe;
0176     QAction *m_actionReplyModeAll;
0177     QAction *m_actionReplyModeList;
0178     typedef QPair<QComboBox*, QLineEdit*> Recipient;
0179     QList<Recipient> m_recipients;
0180     QTimer *m_recipientListUpdateTimer;
0181     QPointer<QWidget> m_lastFocusedRecipient;
0182     int m_maxVisibleRecipients;
0183 
0184     bool m_sentMail;
0185     bool m_explicitDraft;
0186     QString m_autoSavePath;
0187 
0188     QList<QByteArray> m_inReplyTo;
0189     QList<QByteArray> m_references;
0190     QPersistentModelIndex m_replyingToMessage;
0191 
0192     std::unique_ptr<ComposerSaveState> m_saveState;
0193 
0194     bool m_appendUidReceived;
0195     uint m_appendUidValidity;
0196     uint m_appendUid;
0197     bool m_genUrlAuthReceived;
0198     QString m_urlauth;
0199 
0200     MainWindow *m_mainWindow;
0201     QSettings *m_settings;
0202 
0203     std::shared_ptr<Composer::AbstractComposer> m_composer;
0204     Composer::Submission *m_submission;
0205 
0206     QMenu *m_completionPopup;
0207     QLineEdit *m_completionReceiver;
0208     int m_completionCount;
0209 
0210     QMap<QLineEdit *, Plugins::AddressbookJob *> m_firstCompletionRequests;
0211     QMap<QLineEdit *, Plugins::AddressbookJob *> m_secondCompletionRequests;
0212 
0213     friend class InhibitComposerDirtying;
0214     friend class ComposerSaveState;
0215 
0216     ComposeWidget(const ComposeWidget &); // don't implement
0217     ComposeWidget &operator=(const ComposeWidget &); // don't implement
0218 };
0219 
0220 }
0221 
0222 #endif // COMPOSEWIDGET_H