File indexing completed on 2024-05-26 05:28:11

0001 /* Copyright (C) 2012 Thomas Lübking <thomas.luebking@gmail.com>
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 
0023 #include <QAction>
0024 #include <QDragEnterEvent>
0025 #include <QDebug>
0026 #include <QInputDialog>
0027 #include <QMenu>
0028 #include <QMimeData>
0029 #include "Composer/MessageComposer.h"
0030 #include "Gui/ComposerAttachmentsList.h"
0031 #include "Gui/Util.h"
0032 #include "Imap/Model/ItemRoles.h"
0033 #include "Imap/Model/DragAndDrop.h"
0034 #include "UiUtils/IconLoader.h"
0035 
0036 ComposerAttachmentsList::ComposerAttachmentsList(QWidget *parent):
0037     QListView(parent), m_dragging(false), m_dragInside(false), m_composer(0)
0038 {
0039     setMouseTracking( true );
0040     setAcceptDrops(true);
0041     setDragDropMode( DragDrop );
0042     setDragDropOverwriteMode( false );
0043     setDragEnabled(true);
0044     setDropIndicatorShown(false);
0045     setContextMenuPolicy(Qt::CustomContextMenu);
0046     connect(this, &QWidget::customContextMenuRequested, this, &ComposerAttachmentsList::showContextMenu);
0047 
0048     m_actionSendInline = new QAction(UiUtils::loadIcon(QStringLiteral("insert-image")), tr("Send Inline"), this);
0049     m_actionSendInline->setCheckable(true);
0050     connect(m_actionSendInline, &QAction::triggered, this, &ComposerAttachmentsList::slotToggledContentDispositionInline);
0051     addAction(m_actionSendInline);
0052 
0053     m_actionRename = new QAction(UiUtils::loadIcon(QStringLiteral("edit-rename")), tr("Rename..."), this);
0054     connect(m_actionRename, &QAction::triggered, this, &ComposerAttachmentsList::slotRenameAttachment);
0055     addAction(m_actionRename);
0056 
0057     m_actionRemoveAttachment = new QAction(UiUtils::loadIcon(QStringLiteral("list-remove")), tr("Remove"), this);
0058     connect(m_actionRemoveAttachment, &QAction::triggered, this, &ComposerAttachmentsList::slotRemoveAttachment);
0059     addAction(m_actionRemoveAttachment);
0060 
0061     connect(this, &ComposerAttachmentsList::itemDroppedOut, this, &ComposerAttachmentsList::slotRemoveAttachment);
0062     connect(this, &QAbstractItemView::clicked, this, &ComposerAttachmentsList::onCurrentChanged);
0063     connect(this, &QAbstractItemView::activated, this, &ComposerAttachmentsList::onCurrentChanged);
0064 }
0065 
0066 void ComposerAttachmentsList::setComposer(std::shared_ptr<Composer::MessageComposer> composer)
0067 {
0068     // prevent double connections etc
0069     Q_ASSERT(!m_composer);
0070 
0071     m_composer = composer;
0072     setModel(m_composer.get());
0073     connect(model(), &QAbstractItemModel::rowsRemoved, this, &ComposerAttachmentsList::onAttachmentNumberChanged);
0074     connect(model(), &QAbstractItemModel::rowsInserted, this, &ComposerAttachmentsList::onAttachmentNumberChanged);
0075     connect(model(), &QAbstractItemModel::layoutChanged, this, &ComposerAttachmentsList::onAttachmentNumberChanged);
0076     connect(model(), &QAbstractItemModel::modelReset, this, &ComposerAttachmentsList::onAttachmentNumberChanged);
0077 
0078     onAttachmentNumberChanged();
0079 }
0080 
0081 void ComposerAttachmentsList::startDrag(Qt::DropActions da)
0082 {
0083     m_dragging = true;
0084     m_dragInside = true;
0085     const QModelIndex idx = indexAt(mapFromGlobal(QCursor::pos()));
0086     if (!idx.isValid())
0087         setCurrentIndex(idx);
0088     QListView::startDrag(da);
0089     m_dragging = false;
0090     if (!m_dragInside) {
0091         emit itemDroppedOut();
0092     }
0093 }
0094 
0095 
0096 void ComposerAttachmentsList::dragEnterEvent(QDragEnterEvent *de)
0097 {
0098     if (Gui::Util::isFromDistinctImapAccount(de)) {
0099         de->ignore();
0100         return;
0101     }
0102     if (m_dragging)
0103         m_dragInside = true;
0104     QListView::dragEnterEvent(de);
0105 }
0106 
0107 void ComposerAttachmentsList::dragLeaveEvent(QDragLeaveEvent *de)
0108 {
0109     if (m_dragging)
0110         m_dragInside = false;
0111     QListView::dragLeaveEvent(de);
0112 }
0113 
0114 void ComposerAttachmentsList::dropEvent(QDropEvent* de)
0115 {
0116     if (Gui::Util::isFromDistinctImapAccount(de)) {
0117         de->ignore();
0118         return;
0119     }
0120     QListView::dropEvent(de);
0121 }
0122 
0123 void ComposerAttachmentsList::slotRemoveAttachment()
0124 {
0125     m_composer->removeAttachment(currentIndex());
0126 }
0127 
0128 void ComposerAttachmentsList::slotToggledContentDispositionInline(bool checked)
0129 {
0130     m_composer->setAttachmentContentDisposition(currentIndex(), checked ? Composer::CDN_INLINE : Composer::CDN_ATTACHMENT);
0131 }
0132 
0133 void ComposerAttachmentsList::slotRenameAttachment()
0134 {
0135     bool ok;
0136     QString newName = QInputDialog::getText(this, tr("Rename Attachment"), tr("New Name"), QLineEdit::Normal,
0137                                             currentIndex().data().toString(), &ok);
0138     if (ok) {
0139         m_composer->setAttachmentName(currentIndex(), newName);
0140     }
0141 }
0142 
0143 void ComposerAttachmentsList::onAttachmentNumberChanged()
0144 {
0145     Q_ASSERT(model());
0146     bool current = currentIndex().isValid();
0147     m_actionRemoveAttachment->setEnabled(current);
0148     m_actionSendInline->setEnabled(current);
0149     m_actionRename->setEnabled(current);
0150     onCurrentChanged();
0151 }
0152 
0153 void ComposerAttachmentsList::onCurrentChanged()
0154 {
0155     m_actionSendInline->setChecked(false);
0156 
0157     // This is needed because the QVariant::toInt returns zero when faced with null QVariant
0158     bool ok;
0159     int res = currentIndex().data(Imap::Mailbox::RoleAttachmentContentDispositionMode).toInt(&ok);
0160     if (!ok)
0161         return;
0162 
0163     switch (static_cast<Composer::ContentDisposition>(res)) {
0164     case Composer::CDN_INLINE:
0165         m_actionSendInline->setChecked(true);
0166         break;
0167     case Composer::CDN_ATTACHMENT:
0168         // nothing is needed here
0169         break;
0170     }
0171 }
0172 
0173 void ComposerAttachmentsList::showContextMenu(const QPoint &pos)
0174 {
0175     // Sometimes currentChanged() is not enough -- we really want to have these actions to reflect the current selection, if any
0176     onAttachmentNumberChanged();
0177     QMenu::exec(actions(), mapToGlobal(pos), 0, this);
0178 }
0179