Accept file drops across the channel footer
This commit is contained in:
1 parent
b631c4ed72
commit
49ee66d49c
3 files changed
+63
No files matched your search
@@ -13,6 +13,9 @@
|
||||
#include <QMouseEvent>
|
||||
#include <QMenu>
|
||||
#include <QStyle>
|
||||
#include <QDropEvent>
|
||||
#include <QMimeData>
|
||||
#include <QUrl>
|
||||
|
||||
extern "C" {
|
||||
#include "../../lib/debug_config.h"
|
||||
@@ -175,6 +178,7 @@ ChannelList::ChannelList(DbManager* db, QWidget *parent)
|
||||
layout->addWidget(m_listView);
|
||||
|
||||
auto *footer = new QWidget(this);
|
||||
m_footer = footer; m_footer->setObjectName("channelFooter");
|
||||
auto *fl = new QHBoxLayout(footer);
|
||||
fl->setContentsMargins(6, 4, 6, 4);
|
||||
fl->setSpacing(6);
|
||||
@@ -240,6 +244,12 @@ ChannelList::ChannelList(DbManager* db, QWidget *parent)
|
||||
fl->addWidget(plusBtn);
|
||||
|
||||
layout->addWidget(footer);
|
||||
auto targets = footer->findChildren<QWidget*>(); targets.append(footer);
|
||||
for (auto* target : targets) { target->setAcceptDrops(true); target->installEventFilter(this); }
|
||||
m_dropHint = new QLabel(footer); m_dropHint->setObjectName("ownFilesDropHint");
|
||||
m_dropHint->setAttribute(Qt::WA_TransparentForMouseEvents); m_dropHint->setAlignment(Qt::AlignCenter);
|
||||
m_dropHint->setStyleSheet("QLabel { border: 2px dashed palette(highlight); background: palette(window); color: palette(text); }");
|
||||
m_dropHint->hide();
|
||||
|
||||
connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged,
|
||||
this, [this](const QModelIndex ¤t, const QModelIndex &) {
|
||||
@@ -266,6 +276,46 @@ ChannelList::ChannelList(DbManager* db, QWidget *parent)
|
||||
});
|
||||
}
|
||||
|
||||
bool ChannelList::eventFilter(QObject* target, QEvent* event) {
|
||||
if (event->type() == QEvent::DragLeave) { m_dropHint->hide(); return true; }
|
||||
if (event->type() != QEvent::DragEnter && event->type() != QEvent::DragMove && event->type() != QEvent::Drop)
|
||||
return QWidget::eventFilter(target, event);
|
||||
auto* drop = static_cast<QDropEvent*>(event);
|
||||
QString channel = m_listView->currentIndex().data(ChannelChannelIdRole).toString();
|
||||
QString reason;
|
||||
if (!channel.toULongLong()) reason = QCoreApplication::translate("ChatGui", "Select a group to upload files");
|
||||
else if (!m_db || !m_db->myNodeId() || !gui_bridge_is_uasync_ready())
|
||||
reason = QCoreApplication::translate("ChatGui", "Upload unavailable");
|
||||
else if (!drop->mimeData()->hasUrls() || drop->mimeData()->urls().isEmpty() || !(drop->possibleActions() & Qt::CopyAction))
|
||||
reason = QCoreApplication::translate("ChatGui", "Drop local files to copy");
|
||||
QStringList paths;
|
||||
if (reason.isEmpty()) for (const auto& url : drop->mimeData()->urls()) {
|
||||
if (!url.isLocalFile() || url.toLocalFile().isEmpty()) {
|
||||
reason = QCoreApplication::translate("ChatGui", "Only local files can be uploaded"); break;
|
||||
}
|
||||
paths.append(url.toLocalFile());
|
||||
}
|
||||
if (event->type() == QEvent::Drop) m_dropHint->hide();
|
||||
else {
|
||||
m_dropHint->setGeometry(m_footer->rect());
|
||||
m_dropHint->setText(reason.isEmpty() ? QCoreApplication::translate("ChatGui", "Copy to my files") : reason);
|
||||
m_dropHint->show(); m_dropHint->raise();
|
||||
}
|
||||
if (!reason.isEmpty()) {
|
||||
if (event->type() != QEvent::DragMove)
|
||||
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "file drop: rejected channel=%s reason=%s", qPrintable(channel), qPrintable(reason));
|
||||
drop->ignore();
|
||||
// После отклонённого DragEnter Qt не гарантирует DragLeave.
|
||||
m_dropHint->hide(); return true;
|
||||
}
|
||||
drop->setDropAction(Qt::CopyAction); drop->accept();
|
||||
if (event->type() == QEvent::Drop) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "file drop: accepted channel=%s files=%d", qPrintable(channel), int(paths.size()));
|
||||
QTimer::singleShot(0, this, [this, channel, paths] { emit ownFilesDropped(channel, paths); });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChannelList::refreshDmPresence() {
|
||||
if (!m_dmPresenceTimer->isActive()) m_dmPresenceTimer->start();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user