Test file manager copy and deferred drag completion
This commit is contained in:
1 parent
4049a3f884
commit
9640a18b03
1 file changed
+82
-2
@@ -19,6 +19,12 @@
|
||||
#include <QDragEnterEvent>
|
||||
#include <QDropEvent>
|
||||
#include <QLineEdit>
|
||||
#include <QAction>
|
||||
#include <QClipboard>
|
||||
#include <QDrag>
|
||||
#include <QMouseEvent>
|
||||
#include <QScopeGuard>
|
||||
#include <functional>
|
||||
extern "C" {
|
||||
#include "member_files/member_files.h"
|
||||
#include "mem.h"
|
||||
@@ -29,6 +35,7 @@ static mf_gui_request quotaCaptured;
|
||||
static QList<mf_transfer_request> transfers;
|
||||
static QList<quint64> cancelled;
|
||||
static bool ready = true;
|
||||
static std::function<void(mf_transfer_request)> transferStarted;
|
||||
extern "C" int gui_bridge_is_uasync_ready(void) { return ready; }
|
||||
extern "C" UTUN_INSTANCE* gui_bridge_get_inst(void) { return nullptr; }
|
||||
extern "C" void gui_bridge_post_uasync_fn(void (*function)(void*), void* arg) {
|
||||
@@ -37,7 +44,10 @@ extern "C" void gui_bridge_post_uasync_fn(void (*function)(void*), void* arg) {
|
||||
if (request->message.command == MF_QUOTA) quotaCaptured = *request;
|
||||
else captured = *request;
|
||||
}
|
||||
if (function == member_files_gui_transfer) transfers.append(*(mf_transfer_request*)arg);
|
||||
if (function == member_files_gui_transfer) {
|
||||
auto request = *(mf_transfer_request*)arg; transfers.append(request);
|
||||
if (transferStarted) transferStarted(request);
|
||||
}
|
||||
if (function == member_files_gui_cancel) cancelled.append(((mf_cancel_request*)arg)->id);
|
||||
u_free(arg);
|
||||
}
|
||||
@@ -75,7 +85,77 @@ private slots:
|
||||
debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_DEBUG);
|
||||
debug_set_category_level(DEBUG_CATEGORY_MEDIA, DEBUG_LEVEL_INFO);
|
||||
}
|
||||
void init() { transfers.clear(); cancelled.clear(); ready = true; }
|
||||
void init() { transfers.clear(); cancelled.clear(); ready = true; transferStarted = {}; }
|
||||
|
||||
void exportToSystemClipboardAndSingleDrag() {
|
||||
QTemporaryDir cache; QVERIFY(cache.isValid()); QByteArray oldCache = qgetenv("XDG_CACHE_HOME");
|
||||
qputenv("XDG_CACHE_HOME", cache.path().toUtf8());
|
||||
auto restoreCache = qScopeGuard([oldCache] { qputenv("XDG_CACHE_HOME", oldCache); QApplication::clipboard()->clear(); });
|
||||
sqlite3* sql = nullptr; QCOMPARE(sqlite3_open(":memory:", &sql), SQLITE_OK);
|
||||
QCOMPARE(sqlite3_exec(sql, "CREATE TABLE accounts(node_id INTEGER,display_name TEXT);"
|
||||
"INSERT INTO accounts VALUES(11,'Other'),(22,'Me'),(33,'Server');"
|
||||
"CREATE TABLE peers_42(node_id INTEGER,adm_tags TEXT,adm_tags_sig BLOB,deleted INTEGER,source INTEGER);"
|
||||
"INSERT INTO peers_42 VALUES(11,'{}',NULL,0,0),(22,'{}',NULL,0,0),"
|
||||
"(33,'{\"storage\":\"yes\"}',zeroblob(64),0,0);", nullptr, nullptr, nullptr), SQLITE_OK);
|
||||
DbManager db; db.setDb(sql); db.setMyNodeId(22); QString exported;
|
||||
{
|
||||
MemberFileBrowser browser(&db); browser.setChannel("42", 11); browser.show();
|
||||
auto* tree = browser.findChild<QTreeWidget*>();
|
||||
auto* item = new QTreeWidgetItem(tree, {"remote.txt"});
|
||||
item->setData(0, Qt::UserRole, "remote.txt"); item->setData(0, Qt::UserRole + 1, MF_FILE);
|
||||
item->setData(0, Qt::UserRole + 2, QByteArray(16, '\7')); tree->setCurrentItem(item);
|
||||
auto* copy = browser.findChild<QAction*>("memberFilesCopy"); QVERIFY(copy); QVERIFY(copy->isEnabled());
|
||||
QApplication::clipboard()->setText("unchanged"); copy->trigger();
|
||||
QTRY_COMPARE(transfers.size(), 1); auto request = transfers.last();
|
||||
QCOMPARE(request.upload, 0); QCOMPARE(request.owner, 11ULL); QCOMPARE(request.group, 42ULL); QCOMPARE(request.server, 33ULL);
|
||||
QCOMPARE(QString::fromUtf8(request.remote), QString("remote.txt"));
|
||||
QCOMPARE(QByteArray((const char*)request.version, 16), QByteArray(16, '\7'));
|
||||
QCOMPARE(QApplication::clipboard()->text(), QString("unchanged"));
|
||||
exported = QString::fromUtf8(request.local);
|
||||
{ QFile file(exported); QVERIFY(file.open(QIODevice::WriteOnly)); QCOMPARE(file.write("downloaded bytes"), 16LL); }
|
||||
complete(browser, request);
|
||||
const auto* mime = QApplication::clipboard()->mimeData(); QVERIFY(mime->hasUrls());
|
||||
QCOMPARE(mime->urls(), QList<QUrl>{QUrl::fromLocalFile(exported)});
|
||||
QVERIFY(mime->data("x-special/gnome-copied-files").startsWith("copy\n"));
|
||||
copy->trigger(); QCOMPARE(transfers.size(), 1); // Готовая версия не скачивается повторно.
|
||||
|
||||
item->setData(0, Qt::UserRole + 2, QByteArray(16, '\10'));
|
||||
QApplication::clipboard()->setText("keep on error"); copy->trigger(); QTRY_COMPARE(transfers.size(), 2);
|
||||
complete(browser, transfers.last(), MF_IO_ERROR); QCOMPARE(QApplication::clipboard()->text(), QString("keep on error"));
|
||||
copy->trigger(); QTRY_COMPARE(transfers.size(), 3); auto cancelledRequest = transfers.last();
|
||||
cancelButton(browser)->click(); complete(browser, cancelledRequest, MF_CANCELLED);
|
||||
QCOMPARE(QApplication::clipboard()->text(), QString("keep on error"));
|
||||
|
||||
bool committed = false, received = false;
|
||||
transferStarted = [&browser, &committed](mf_transfer_request transfer) {
|
||||
QTimer::singleShot(50, &browser, [&browser, &committed, transfer] {
|
||||
QFile file(QString::fromUtf8(transfer.local)); QVERIFY(file.open(QIODevice::WriteOnly));
|
||||
QCOMPARE(file.write("drag bytes"), 10LL); file.close(); committed = true; complete(browser, transfer);
|
||||
});
|
||||
};
|
||||
QTimer receiver; receiver.setInterval(5);
|
||||
connect(&receiver, &QTimer::timeout, &browser, [&] {
|
||||
auto* drag = QCoreApplication::instance()->findChild<QDrag*>();
|
||||
if (!drag || !drag->mimeData()) return;
|
||||
receiver.stop(); auto* data = drag->mimeData();
|
||||
QVERIFY(data->hasUrls()); QVERIFY(!committed);
|
||||
// Запрос системного менеджера приходит до скачивания и возвращается лишь после commit.
|
||||
auto urls = data->urls(); QVERIFY(committed); QCOMPARE(urls.size(), 1);
|
||||
QFile file(urls.first().toLocalFile()); QVERIFY(file.open(QIODevice::ReadOnly)); QCOMPARE(file.readAll(), QByteArray("drag bytes"));
|
||||
received = true; QDrag::cancel();
|
||||
});
|
||||
receiver.start();
|
||||
QTimer::singleShot(3000, &browser, [] { QDrag::cancel(); });
|
||||
tree->setFocus(); QCoreApplication::processEvents(); QPoint point = tree->visualItemRect(item).center();
|
||||
QTest::mousePress(tree->viewport(), Qt::LeftButton, Qt::NoModifier, point);
|
||||
QMouseEvent move(QEvent::MouseMove, QPointF(point + QPoint(40, 0)), Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
|
||||
QApplication::sendEvent(tree->viewport(), &move);
|
||||
QTest::mouseRelease(tree->viewport(), Qt::LeftButton, Qt::NoModifier, point + QPoint(40, 0));
|
||||
QVERIFY(received); QCOMPARE(transfers.size(), 4); transferStarted = {};
|
||||
}
|
||||
QVERIFY(QFile::exists(exported)); // Закрытие Group files не ломает локальный URI.
|
||||
db.setDb(nullptr); QCOMPARE(sqlite3_close(sql), SQLITE_OK);
|
||||
}
|
||||
|
||||
void browserDropsIntoCurrentDirectory() {
|
||||
sqlite3* sql = nullptr; QCOMPARE(sqlite3_open(":memory:", &sql), SQLITE_OK);
|
||||
|
||||
Reference in new issue
Block a user