Browse Source

Accept file drops across the channel footer

master
evgeny 4 days ago
parent
commit
49ee66d49c
  1. 50
      tools/chatgui/src/channellist.cpp
  2. 8
      tools/chatgui/src/channellist.h
  3. 5
      tools/chatgui/src/mainwindow.cpp

50
tools/chatgui/src/channellist.cpp

@ -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 &current, 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();
}

8
tools/chatgui/src/channellist.h

@ -6,11 +6,13 @@
#include <QListView>
#include <QStandardItemModel>
#include <QString>
#include <QStringList>
#include <QHash>
#include <QTimer>
class DbManager;
class QPushButton;
class QLabel;
class ChannelList : public QWidget {
Q_OBJECT
@ -34,16 +36,22 @@ signals:
void channelSettingsRequested(const QString& channelId);
void filesRequested(const QString& channelId);
void ownFilesRequested(const QString& channelId);
void ownFilesDropped(const QString& channelId, const QStringList& paths);
void joinRequested();
void createGroupRequested();
void settingsRequested();
void connMonitorRequested();
protected:
bool eventFilter(QObject* target, QEvent* event) override;
private:
QListView *m_listView;
QStandardItemModel *m_model;
DbManager *m_db;
QPushButton *m_ownFilesButton;
QWidget *m_footer;
QLabel *m_dropHint;
bool m_autoConnectActive = false;
QHash<QString, bool> m_dmOnline;
QTimer* m_dmPresenceTimer;

5
tools/chatgui/src/mainwindow.cpp

@ -621,6 +621,11 @@ void MainWindow::setupConnects() {
qPrintable(channel), (unsigned long long)owner);
showMemberFiles(channel, owner);
});
connect(m_channelList, &ChannelList::ownFilesDropped, this, [this](const QString& channel, const QStringList& paths) {
if (!m_fileBrowser) m_fileBrowser = new MemberFileBrowser(m_db, this);
m_fileBrowser->show(); m_fileBrowser->raise(); m_fileBrowser->activateWindow();
m_fileBrowser->uploadOwnFiles(channel, paths);
});
connect(m_accountList, &AccountList::callRequested, this, &MainWindow::onCallRequested);
connect(m_messageList, &MessageList::callRequested, this, &MainWindow::onCallRequested);
connect(m_accountList, &AccountList::pmRequested, this, &MainWindow::onPmRequested);

Loading…
Cancel
Save