File indexing completed on 2024-12-08 04:34:50

0001 /*
0002     This is the shares view of Smb4K.
0003 
0004     SPDX-FileCopyrightText: 2006-2022 Alexander Reinholdt <alexander.reinholdt@kdemail.net>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 // application specific includes
0009 #include "smb4ksharesview.h"
0010 #include "core/smb4ksettings.h"
0011 #include "core/smb4kshare.h"
0012 #include "smb4ksharesviewitem.h"
0013 #include "smb4ktooltip.h"
0014 
0015 // Qt includes
0016 #include <QDrag>
0017 #include <QMouseEvent>
0018 #include <QWheelEvent>
0019 
0020 // KDE includes
0021 #include <KIconLoader>
0022 
0023 Smb4KSharesView::Smb4KSharesView(QWidget *parent)
0024     : QListWidget(parent)
0025 {
0026     setMouseTracking(true);
0027     setSelectionMode(ExtendedSelection);
0028     setResizeMode(Adjust);
0029     setSortingEnabled(true);
0030     setWordWrap(true);
0031     setAcceptDrops(true);
0032     setDragEnabled(true);
0033     setDropIndicatorShown(true);
0034     setUniformItemSizes(true);
0035     setWrapping(true);
0036     setTextElideMode(Qt::ElideNone);
0037 
0038     m_toolTip = new Smb4KToolTip(this);
0039 
0040     setContextMenuPolicy(Qt::CustomContextMenu);
0041 }
0042 
0043 Smb4KSharesView::~Smb4KSharesView()
0044 {
0045 }
0046 
0047 void Smb4KSharesView::setViewMode(QListView::ViewMode mode, int iconSize)
0048 {
0049     //
0050     // Set the view mode
0051     //
0052     QListWidget::setViewMode(mode);
0053 
0054     //
0055     // Make adjustments
0056     //
0057     switch (mode) {
0058     case IconMode: {
0059         setUniformItemSizes(true);
0060         setIconSize(QSize(iconSize, iconSize));
0061         setSpacing(5);
0062         break;
0063     }
0064     case ListMode: {
0065         setUniformItemSizes(false);
0066         setIconSize(QSize(iconSize, iconSize));
0067         setSpacing(0);
0068         break;
0069     }
0070     default: {
0071         break;
0072     }
0073     }
0074 
0075     //
0076     // Align the items
0077     //
0078     for (int i = 0; i < count(); ++i) {
0079         Smb4KSharesViewItem *viewItem = static_cast<Smb4KSharesViewItem *>(item(i));
0080         viewItem->setItemAlignment(mode);
0081     }
0082 }
0083 
0084 Smb4KToolTip *Smb4KSharesView::toolTip()
0085 {
0086     return m_toolTip;
0087 }
0088 
0089 bool Smb4KSharesView::event(QEvent *e)
0090 {
0091     switch (e->type()) {
0092     case QEvent::ToolTip: {
0093         // Intercept the tool tip event and show our own tool tip.
0094         QPoint pos = viewport()->mapFromGlobal(cursor().pos());
0095         Smb4KSharesViewItem *item = static_cast<Smb4KSharesViewItem *>(itemAt(pos));
0096 
0097         if (item) {
0098             if (Smb4KSettings::showShareToolTip()) {
0099                 //
0100                 // Set up the tooltip
0101                 //
0102                 m_toolTip->setupToolTip(Smb4KToolTip::MountedShare, item->shareItem());
0103 
0104                 //
0105                 // Show the tooltip
0106                 //
0107                 m_toolTip->show(cursor().pos(), nativeParentWidget()->windowHandle());
0108             }
0109         }
0110 
0111         break;
0112     }
0113     default: {
0114         break;
0115     }
0116     }
0117 
0118     return QListWidget::event(e);
0119 }
0120 
0121 void Smb4KSharesView::mousePressEvent(QMouseEvent *e)
0122 {
0123     //
0124     // Hide the tooltip
0125     //
0126     if (m_toolTip->isVisible()) {
0127         m_toolTip->hide();
0128     }
0129 
0130     //
0131     // Get the item that is under the mouse. If there is no
0132     // item, unselect the current item.
0133     //
0134 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0135     QListWidgetItem *item = itemAt(e->position().toPoint());
0136 #else
0137     QListWidgetItem *item = itemAt(e->pos());
0138 #endif
0139 
0140     if (!item && !selectedItems().isEmpty()) {
0141         clearSelection();
0142         setCurrentItem(nullptr);
0143         Q_EMIT itemPressed(currentItem());
0144     }
0145 
0146     QListWidget::mousePressEvent(e);
0147 }
0148 
0149 void Smb4KSharesView::mouseMoveEvent(QMouseEvent *e)
0150 {
0151     //
0152     // Hide the tooltip
0153     //
0154     if (m_toolTip->isVisible()) {
0155         m_toolTip->hide();
0156     }
0157 
0158     QListWidget::mouseMoveEvent(e);
0159 }
0160 
0161 void Smb4KSharesView::dragEnterEvent(QDragEnterEvent *e)
0162 {
0163     if (e->mimeData()->hasUrls()) {
0164         e->accept();
0165     } else {
0166         e->ignore();
0167     }
0168 }
0169 
0170 void Smb4KSharesView::dragMoveEvent(QDragMoveEvent *e)
0171 {
0172     // Let the QAbstractItemView do the highlighting of the item, etc.
0173     QAbstractItemView::dragMoveEvent(e);
0174 
0175     // Now we do our thing.
0176 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0177     Smb4KSharesViewItem *item = static_cast<Smb4KSharesViewItem *>(itemAt(e->position().toPoint()));
0178 #else
0179     Smb4KSharesViewItem *item = static_cast<Smb4KSharesViewItem *>(itemAt(e->pos()));
0180 #endif
0181 
0182     if (item && !item->shareItem()->isInaccessible() && (item->flags() & Qt::ItemIsDropEnabled) && (e->proposedAction() & (Qt::CopyAction | Qt::MoveAction))) {
0183         QUrl url = QUrl::fromLocalFile(item->shareItem()->path());
0184 
0185         if (e->source() == this && e->mimeData()->urls().first() == url) {
0186             e->ignore();
0187         } else {
0188             e->accept();
0189         }
0190     } else {
0191         e->ignore();
0192     }
0193 }
0194 
0195 void Smb4KSharesView::dropEvent(QDropEvent *e)
0196 {
0197     // Get the item and process the drop event
0198 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0199     Smb4KSharesViewItem *item = static_cast<Smb4KSharesViewItem *>(itemAt(e->position().toPoint()));
0200 #else
0201     Smb4KSharesViewItem *item = static_cast<Smb4KSharesViewItem *>(itemAt(e->pos()));
0202 #endif
0203 
0204     if (item && !item->shareItem()->isInaccessible() && (e->proposedAction() & (Qt::CopyAction | Qt::MoveAction))) {
0205         QUrl url = QUrl::fromLocalFile(item->shareItem()->path());
0206 
0207         if (e->source() == this && e->mimeData()->urls().first() == url) {
0208             e->ignore();
0209         } else {
0210             e->acceptProposedAction();
0211             Q_EMIT acceptedDropEvent(item, e);
0212             e->accept();
0213         }
0214     } else {
0215         e->ignore();
0216     }
0217 }
0218 
0219 Qt::DropActions Smb4KSharesView::supportedDropActions() const
0220 {
0221     // Only allow copying and linking.
0222     return (Qt::CopyAction | Qt::LinkAction);
0223 }
0224 
0225 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0226 QMimeData *Smb4KSharesView::mimeData(const QList<QListWidgetItem *> &list) const
0227 #else
0228 QMimeData *Smb4KSharesView::mimeData(const QList<QListWidgetItem *> list) const
0229 #endif
0230 {
0231     QMimeData *mimeData = new QMimeData();
0232     QList<QUrl> urls;
0233 
0234     for (int i = 0; i < list.count(); ++i) {
0235         Smb4KSharesViewItem *item = static_cast<Smb4KSharesViewItem *>(list.at(i));
0236         urls << QUrl::fromLocalFile(item->shareItem()->path());
0237     }
0238 
0239     mimeData->setUrls(urls);
0240 
0241     return mimeData;
0242 }
0243 
0244 void Smb4KSharesView::startDrag(Qt::DropActions supported)
0245 {
0246     QList<QListWidgetItem *> list = selectedItems();
0247 
0248     if (!list.isEmpty()) {
0249         QMimeData *data = mimeData(list);
0250 
0251         if (!data) {
0252             return;
0253         }
0254 
0255         QDrag *drag = new QDrag(this);
0256 
0257         QPixmap pixmap;
0258 
0259         if (list.count() == 1) {
0260             Smb4KSharesViewItem *item = static_cast<Smb4KSharesViewItem *>(list.first());
0261             pixmap = item->icon().pixmap(KIconLoader::SizeMedium);
0262         } else {
0263             pixmap = KDE::icon(QStringLiteral("document-multiple")).pixmap(KIconLoader::SizeMedium);
0264         }
0265 
0266         drag->setPixmap(pixmap);
0267         drag->setMimeData(data);
0268 
0269         drag->exec(supported, Qt::IgnoreAction);
0270     }
0271 }