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