File indexing completed on 2024-10-27 04:50:58
0001 /* 0002 * This file is part of KMail. 0003 * SPDX-FileCopyrightText: 2011-2024 Laurent Montel <montel@kde.org> 0004 * 0005 * SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com> 0006 * 0007 * Parts based on KMail code by: 0008 * SPDX-FileCopyrightText: 2003 Ingo Kloecker <kloecker@kde.org> 0009 * SPDX-FileCopyrightText: 2007 Thomas McGuire <Thomas.McGuire@gmx.net> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 */ 0013 0014 #include "attachmentview.h" 0015 0016 #include "kmkernel.h" 0017 0018 #include <MessageComposer/AttachmentModel> 0019 0020 #include <QContextMenuEvent> 0021 #include <QDrag> 0022 #include <QHBoxLayout> 0023 #include <QHeaderView> 0024 #include <QKeyEvent> 0025 #include <QLabel> 0026 #include <QSortFilterProxyModel> 0027 #include <QToolButton> 0028 0029 #include <KLocalizedString> 0030 #include <QIcon> 0031 0032 #include <KIO/Global> 0033 #include <MessageCore/AttachmentPart> 0034 using MessageCore::AttachmentPart; 0035 0036 using namespace KMail; 0037 0038 AttachmentView::AttachmentView(MessageComposer::AttachmentModel *model, QWidget *parent) 0039 : QTreeView(parent) 0040 , mModel(model) 0041 , mToolButton(new QToolButton(this)) 0042 , mInfoAttachment(new QLabel(this)) 0043 , mWidget(new QWidget()) 0044 , grp(KMKernel::self()->config()->group(QStringLiteral("AttachmentView"))) 0045 { 0046 auto lay = new QHBoxLayout(mWidget); 0047 lay->setContentsMargins({}); 0048 connect(mToolButton, &QAbstractButton::toggled, this, &AttachmentView::slotShowHideAttchementList); 0049 mToolButton->setIcon(QIcon::fromTheme(QStringLiteral("mail-attachment"))); 0050 mToolButton->setAutoRaise(true); 0051 mToolButton->setCheckable(true); 0052 lay->addWidget(mToolButton); 0053 mInfoAttachment->setContentsMargins({}); 0054 mInfoAttachment->setTextFormat(Qt::PlainText); 0055 lay->addWidget(mInfoAttachment); 0056 0057 connect(model, &MessageComposer::AttachmentModel::encryptEnabled, this, &AttachmentView::setEncryptEnabled); 0058 connect(model, &MessageComposer::AttachmentModel::signEnabled, this, &AttachmentView::setSignEnabled); 0059 0060 auto sortModel = new QSortFilterProxyModel(this); 0061 sortModel->setSortCaseSensitivity(Qt::CaseInsensitive); 0062 sortModel->setSourceModel(model); 0063 setModel(sortModel); 0064 connect(model, &MessageComposer::AttachmentModel::rowsInserted, this, &AttachmentView::hideIfEmpty); 0065 connect(model, &MessageComposer::AttachmentModel::rowsRemoved, this, &AttachmentView::hideIfEmpty); 0066 connect(model, &MessageComposer::AttachmentModel::rowsRemoved, this, &AttachmentView::selectNewAttachment); 0067 connect(model, &MessageComposer::AttachmentModel::dataChanged, this, &AttachmentView::updateAttachmentLabel); 0068 0069 setRootIsDecorated(false); 0070 setUniformRowHeights(true); 0071 setSelectionMode(QAbstractItemView::ExtendedSelection); 0072 setDragDropMode(QAbstractItemView::DragDrop); 0073 setEditTriggers(QAbstractItemView::EditKeyPressed); 0074 setDropIndicatorShown(false); 0075 setSortingEnabled(true); 0076 0077 header()->setSectionResizeMode(QHeaderView::Interactive); 0078 header()->setStretchLastSection(false); 0079 restoreHeaderState(); 0080 setColumnWidth(0, 200); 0081 } 0082 0083 AttachmentView::~AttachmentView() 0084 { 0085 saveHeaderState(); 0086 } 0087 0088 void AttachmentView::restoreHeaderState() 0089 { 0090 header()->restoreState(grp.readEntry("State", QByteArray())); 0091 } 0092 0093 void AttachmentView::saveHeaderState() 0094 { 0095 grp.writeEntry("State", header()->saveState()); 0096 grp.sync(); 0097 } 0098 0099 void AttachmentView::contextMenuEvent(QContextMenuEvent *event) 0100 { 0101 Q_UNUSED(event) 0102 Q_EMIT contextMenuRequested(); 0103 } 0104 0105 void AttachmentView::keyPressEvent(QKeyEvent *event) 0106 { 0107 if (event->key() == Qt::Key_Delete) { 0108 // Indexes are based on row numbers, and row numbers change when items are deleted. 0109 // Therefore, first we need to make a list of AttachmentParts to delete. 0110 AttachmentPart::List toRemove; 0111 const QModelIndexList selectedIndexes = selectionModel()->selectedRows(); 0112 toRemove.reserve(selectedIndexes.count()); 0113 for (const QModelIndex &index : selectedIndexes) { 0114 auto part = model()->data(index, MessageComposer::AttachmentModel::AttachmentPartRole).value<AttachmentPart::Ptr>(); 0115 toRemove.append(part); 0116 } 0117 for (const AttachmentPart::Ptr &part : std::as_const(toRemove)) { 0118 mModel->removeAttachment(part); 0119 } 0120 } else { 0121 QTreeView::keyPressEvent(event); 0122 } 0123 } 0124 0125 void AttachmentView::dragEnterEvent(QDragEnterEvent *event) 0126 { 0127 if (event->source() == this) { 0128 // Ignore drags from ourselves. 0129 event->ignore(); 0130 } else { 0131 QTreeView::dragEnterEvent(event); 0132 } 0133 } 0134 0135 void AttachmentView::setEncryptEnabled(bool enabled) 0136 { 0137 setColumnHidden(MessageComposer::AttachmentModel::EncryptColumn, !enabled); 0138 } 0139 0140 void AttachmentView::setSignEnabled(bool enabled) 0141 { 0142 setColumnHidden(MessageComposer::AttachmentModel::SignColumn, !enabled); 0143 } 0144 0145 void AttachmentView::hideIfEmpty() 0146 { 0147 const bool needToShowIt = (model()->rowCount() > 0); 0148 setVisible(needToShowIt); 0149 mToolButton->setChecked(needToShowIt); 0150 widget()->setVisible(needToShowIt); 0151 if (needToShowIt) { 0152 updateAttachmentLabel(); 0153 } else { 0154 mInfoAttachment->clear(); 0155 } 0156 Q_EMIT modified(true); 0157 } 0158 0159 void AttachmentView::updateAttachmentLabel() 0160 { 0161 const MessageCore::AttachmentPart::List list = mModel->attachments(); 0162 qint64 size = 0; 0163 for (const MessageCore::AttachmentPart::Ptr &part : list) { 0164 size += part->size(); 0165 } 0166 mInfoAttachment->setText(i18np("1 attachment (%2)", "%1 attachments (%2)", model()->rowCount(), KIO::convertSize(qMax(0LL, size)))); 0167 } 0168 0169 void AttachmentView::selectNewAttachment() 0170 { 0171 if (selectionModel()->selectedRows().isEmpty()) { 0172 selectionModel()->select(selectionModel()->currentIndex(), QItemSelectionModel::Select | QItemSelectionModel::Rows); 0173 } 0174 } 0175 0176 void AttachmentView::startDrag(Qt::DropActions supportedActions) 0177 { 0178 Q_UNUSED(supportedActions) 0179 0180 const QModelIndexList selection = selectionModel()->selectedRows(); 0181 if (!selection.isEmpty()) { 0182 QMimeData *mimeData = model()->mimeData(selection); 0183 auto drag = new QDrag(this); 0184 drag->setMimeData(mimeData); 0185 drag->exec(Qt::CopyAction); 0186 } 0187 } 0188 0189 QWidget *AttachmentView::widget() const 0190 { 0191 return mWidget; 0192 } 0193 0194 void AttachmentView::slotShowHideAttchementList(bool show) 0195 { 0196 setVisible(show); 0197 if (show) { 0198 mToolButton->setToolTip(i18n("Hide attachment list")); 0199 } else { 0200 mToolButton->setToolTip(i18n("Show attachment list")); 0201 } 0202 } 0203 0204 #include "moc_attachmentview.cpp"