diff --git a/src/api/conversationmodel.h b/src/api/conversationmodel.h index e9bde275b82a4fd96cfb11e9ffbd8e9c4034c02a..6974272b78f9a5849a18a157861a6a8cb67bca3a 100644 --- a/src/api/conversationmodel.h +++ b/src/api/conversationmodel.h @@ -211,6 +211,8 @@ public: void sendFile(const QString& convUid, const QString& path, const QString& filename); + void acceptTransfer(const QString & convUid, uint64_t interactionId); + void acceptTransfer(const QString& convUid, uint64_t interactionId, const QString& path); void cancelTransfer(const QString& convUid, uint64_t interactionId); diff --git a/src/api/datatransfermodel.h b/src/api/datatransfermodel.h index 2d36c2ebc99cb80a6eb0cbecb6123028da84f992..5fc79de7683b732366aefb3923d7482ebf86dc64 100644 --- a/src/api/datatransfermodel.h +++ b/src/api/datatransfermodel.h @@ -58,7 +58,7 @@ public: void bytesProgress(int interactionId, int64_t& total, int64_t& progress); - void accept(int interactionId, const QString& file_path, std::size_t offset); + QString accept(int interactionId, const QString& file_path, std::size_t offset); void cancel(int interactionId); diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp index 3e2b2db3e0c62aea3f960217164ae3e588ce95e9..21ff7f35da45b570f905130eff2a8f926ff006d4 100644 --- a/src/conversationmodel.cpp +++ b/src/conversationmodel.cpp @@ -2025,6 +2025,14 @@ ConversationModel::sendFile(const QString& convUid, } } +void +ConversationModel::acceptTransfer(const QString& convUid, uint64_t interactionId) +{ + lrc::api::datatransfer::Info info = {}; + getTransferInfo(interactionId, info); + acceptTransfer(convUid, interactionId, info.displayName); +} + void ConversationModel::acceptTransfer(const QString& convUid, uint64_t interactionId, const QString& path) { @@ -2175,31 +2183,17 @@ ConversationModelPimpl::slotTransferStatusAwaitingHost(long long dringId, datatr if (emitUpdated) { dirtyConversations = {true, true}; emit linked.interactionStatusUpdated(convId, interactionId, itCopy); - // If it's an accepted file type and less than 20 MB, accept transfer. - - // TODO: Use Qt functions - - auto extensionIdx = info.displayName.toStdString().find_last_of("."); - if (extensionIdx == std::string::npos) - return; - auto extension = QString(info.displayName).remove(0, extensionIdx); + // Only accept if contact is added try { - auto contactInfo = linked.owner.contactModel->getContact(conversations[conversationIdx].participants.front()); - // Only accept if contact is added + auto contactUri = conversations[conversationIdx].participants.front(); + auto contactInfo = linked.owner.contactModel->getContact(contactUri); if (contactInfo.profileInfo.type != profile::Type::RING) return; } catch (...) { return; } - auto destinationDir = lrc.getDataTransferModel().downloadDirectory; - if (info.totalSize < 20 * 1024 * 1024 && !destinationDir.isEmpty()) { - auto wantedFilename = destinationDir + info.displayName; - auto duplicate = 0; - while (std::ifstream(wantedFilename.toStdString()).good()) { - ++duplicate; - wantedFilename = destinationDir + info.displayName.left(extensionIdx) + - " (" + toQString(duplicate) + ")" + extension.toLower(); - } - acceptTransfer(convId, interactionId, wantedFilename); + // If it's an accepted file type and less than 20 MB, accept transfer. + if (info.totalSize < 20 * 1024 * 1024 && info.displayName.contains(".")) { + acceptTransfer(convId, interactionId, info.displayName); } } } @@ -2208,8 +2202,17 @@ ConversationModelPimpl::slotTransferStatusAwaitingHost(long long dringId, datatr void ConversationModelPimpl::acceptTransfer(const QString& convUid, uint64_t interactionId, const QString& path) { - lrc.getDataTransferModel().accept(interactionId, path, 0); - storage::updateInteractionBody(db, interactionId, path); + auto destinationDir = lrc.getDataTransferModel().downloadDirectory; + if (destinationDir.isEmpty()) { + return; + } +#ifdef Q_OS_WIN + if (destinationDir.right(1) != '/') { + destinationDir += "/"; + } +#endif + auto acceptedFilePath = lrc.getDataTransferModel().accept(interactionId, destinationDir + path, 0); + storage::updateInteractionBody(db, interactionId, acceptedFilePath); storage::updateInteractionStatus(db, interactionId, interaction::Status::TRANSFER_ACCEPTED); // prepare interaction Info and emit signal for the client @@ -2221,7 +2224,7 @@ ConversationModelPimpl::acceptTransfer(const QString& convUid, uint64_t interact auto& interactions = conversations[conversationIdx].interactions; auto it = interactions.find(interactionId); if (it != interactions.end()) { - it->second.body = path; + it->second.body = acceptedFilePath; it->second.status = interaction::Status::TRANSFER_ACCEPTED; emitUpdated = true; itCopy = it->second; diff --git a/src/datatransfermodel.cpp b/src/datatransfermodel.cpp index 4c05ac4cbb8ad9a2c49214e669146f30baed3dff..23823d4152377dee14036351a4e4876751bf9416 100644 --- a/src/datatransfermodel.cpp +++ b/src/datatransfermodel.cpp @@ -32,6 +32,7 @@ // Qt #include <QUuid> +#include <QFileInfo> namespace lrc { namespace api { @@ -64,6 +65,8 @@ class DataTransferModel::Impl : public QObject public: Impl(DataTransferModel& up_link); + QString getUniqueFilePath(const QString& filename); + DataTransferModel& upLink; std::map<long long, int> dring2lrcIdMap; std::map<int, long long> lrc2dringIdMap; // stricly the reverse map of dring2lrcIdMap @@ -74,10 +77,30 @@ DataTransferModel::Impl::Impl(DataTransferModel& up_link) , upLink {up_link} {} +QString +DataTransferModel::Impl::getUniqueFilePath(const QString& filename) +{ + if (!QFile::exists(filename)) { + return filename; + } + QString base(filename); + QString ext = QFileInfo(filename).completeSuffix(); + if (!ext.isEmpty()) { + ext = ext.prepend("."); + } + base.chop(ext.size()); + QString ret; + for (int suffix = 1;; suffix++) { + ret = QString("%1 (%2)%3").arg(base).arg(suffix).arg(ext); + if (!QFile::exists(ret)) { + return ret; + } + } +} + void DataTransferModel::registerTransferId(long long dringId, int interactionId) { - pimpl_->dring2lrcIdMap.emplace(dringId, interactionId); pimpl_->lrc2dringIdMap.emplace(interactionId, dringId); } @@ -135,13 +158,15 @@ DataTransferModel::bytesProgress(int interactionId, int64_t& total, int64_t& pro reinterpret_cast<qlonglong&>(progress)); } -void +QString DataTransferModel::accept(int interactionId, const QString& file_path, std::size_t offset) { + auto unique_file_path = pimpl_->getUniqueFilePath(file_path); auto dring_id = pimpl_->lrc2dringIdMap.at(interactionId); - ConfigurationManager::instance().acceptFileTransfer(dring_id, file_path, offset); + ConfigurationManager::instance().acceptFileTransfer(dring_id, unique_file_path, offset); + return unique_file_path; } void