From 5cbfa5fbaad7b5b35759611a4113d0829e0b90bf Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Mon, 12 Jan 2026 22:50:45 +0200 Subject: [PATCH] Cleanup temp file handling IB-8812 Signed-off-by: Raul Metsma --- client/CryptoDoc.cpp | 44 ++++--------- client/CryptoDoc.h | 2 +- client/DigiDoc.cpp | 54 ++++----------- client/DigiDoc.h | 5 +- client/DocumentModel.cpp | 120 ++++++++++++++++++++++++---------- client/DocumentModel.h | 16 +++-- client/MainWindow.cpp | 4 +- client/dialogs/FileDialog.cpp | 12 ---- client/dialogs/FileDialog.h | 1 - client/translations/en.ts | 4 -- client/translations/et.ts | 4 -- client/widgets/FileItem.cpp | 5 -- client/widgets/FileItem.h | 1 - client/widgets/FileList.cpp | 27 ++++---- 14 files changed, 143 insertions(+), 156 deletions(-) diff --git a/client/CryptoDoc.cpp b/client/CryptoDoc.cpp index d8de3b09c..7dba3bffc 100644 --- a/client/CryptoDoc.cpp +++ b/client/CryptoDoc.cpp @@ -34,9 +34,6 @@ #include #include #include -#include -#include -#include #include #include @@ -74,7 +71,6 @@ struct CryptoDoc::Private QString fileName; int version = -1; CDocumentModel *documents = new CDocumentModel(this); - QStringList tempFiles; // libcdoc handlers DDConfiguration conf; @@ -144,9 +140,9 @@ bool CDocumentModel::addFile(const QString &file, const QString &mime) return true; } -void CDocumentModel::addTempReference(const QString &file) +QString CDocumentModel::containerName() const { - d->tempFiles.append(file); + return d->fileName; } QString CDocumentModel::copy(int row, const QString &dst) const @@ -181,19 +177,8 @@ QString CDocumentModel::mime(int row) const void CDocumentModel::open(int row) { - if(d->isEncrypted()) - return; - QString path = FileDialog::tempPath(FileDialog::safeName(data(row))); - if(!verifyFile(path)) - return; - if(copy(row, path).isEmpty()) - return; - d->tempFiles.append(path); - FileDialog::setReadOnly(path); - if(FileDialog::isSignedPDF(path)) - Application::showClient({ std::move(path) }, false, false, true); - else - QDesktopServices::openUrl(QUrl::fromLocalFile(path)); + if(!d->isEncrypted()) + DocumentModel::open(row); } bool CDocumentModel::removeRow(int row) @@ -210,6 +195,7 @@ bool CDocumentModel::removeRow(int row) return false; } + removeTempFile(data(row)); d->files.erase(d->files.cbegin() + row); return true; } @@ -223,10 +209,10 @@ QString CDocumentModel::save(int row, const QString &path) const { if(d->isEncrypted()) return {}; - + if(QFileInfo::exists(path)) + return path; QString fileName = copy(row, path); - QFileInfo f(fileName); - if(!f.exists()) + if(!QFileInfo::exists(fileName)) return {}; FileDialog::setFileZone(fileName, d->fileName); return fileName; @@ -279,13 +265,7 @@ bool CryptoDoc::canDecrypt(const QSslCertificate &cert) { void CryptoDoc::clear(const QString &file, int version) { - for(const QString &f: qAsConst(d->tempFiles)) - { - // reset read-only attribute to enable delete file - FileDialog::setReadOnly(f, false); - QFile::remove(f); - } - d->tempFiles.clear(); + d->documents->clearTempFolder(); d->reader.reset(); d->files.clear(); d->fileName = file; @@ -394,13 +374,13 @@ bool CryptoDoc::decrypt(const libcdoc::Lock *lock, const QByteArray& secret) str = tr("Cannot read file."); break; case DDCryptoBackend::PIN_CANCELED: - str = tr("PIN entry canceled"); + str = QCryptoBackend::tr("PIN Canceled"); break; case DDCryptoBackend::PIN_INCORRECT: - str = tr("PIN incorrect"); + str = QCryptoBackend::tr("PIN Incorrect"); break; case DDCryptoBackend::PIN_LOCKED: - str = tr("PIN locked"); + str = QCryptoBackend::tr("PIN locked"); break; default: str = tr("Please check your internet connection and network settings."); diff --git a/client/CryptoDoc.h b/client/CryptoDoc.h index 6681a162b..3a0c2da71 100644 --- a/client/CryptoDoc.h +++ b/client/CryptoDoc.h @@ -87,7 +87,6 @@ class CDocumentModel final: public DocumentModel Q_OBJECT public: bool addFile(const QString &file, const QString &mime = QStringLiteral("application/octet-stream")) final; - void addTempReference(const QString &file) final; QString data(int row) const final; quint64 fileSize(int row) const final; QString mime(int row) const final; @@ -100,6 +99,7 @@ class CDocumentModel final: public DocumentModel CDocumentModel(CryptoDoc::Private *doc); Q_DISABLE_COPY(CDocumentModel) + QString containerName() const final; QString copy(int row, const QString &dst) const; CryptoDoc::Private *d; diff --git a/client/DigiDoc.cpp b/client/DigiDoc.cpp index 7a3c16a16..a4602c0cb 100644 --- a/client/DigiDoc.cpp +++ b/client/DigiDoc.cpp @@ -36,8 +36,6 @@ #include #include #include -#include -#include #include #include @@ -313,9 +311,9 @@ bool SDocumentModel::addFile(const QString &file, const QString &mime) return false; } -void SDocumentModel::addTempReference(const QString &file) +QString SDocumentModel::containerName() const { - doc->m_tempFiles.append(file); + return doc->fileName(); } QString SDocumentModel::data(int row) const @@ -342,23 +340,6 @@ QString SDocumentModel::mime(int row) const return from(doc->b->dataFiles().at(size_t(row))->mediaType()); } -void SDocumentModel::open(int row) -{ - if(row >= rowCount()) - return; - QString path = FileDialog::tempPath(FileDialog::safeName(from(doc->b->dataFiles().at(size_t(row))->fileName()))); - if(!verifyFile(path)) - return; - if(!QFileInfo::exists(save(row, path))) - return; - doc->m_tempFiles.append(path); - FileDialog::setReadOnly(path); - if(!doc->fileName().endsWith(QLatin1String(".pdf"), Qt::CaseInsensitive) && FileDialog::isSignedPDF(path)) - qApp->showClient({ std::move(path) }, false, false, true); - else - QDesktopServices::openUrl(QUrl::fromLocalFile(path)); -} - bool SDocumentModel::removeRow(int row) { if(!doc->b) @@ -366,6 +347,7 @@ bool SDocumentModel::removeRow(int row) try { + removeTempFile(data(row)); doc->b->removeDataFile(unsigned(row)); doc->modified = true; return true; @@ -383,9 +365,11 @@ QString SDocumentModel::save(int row, const QString &path) const { if(row >= rowCount()) return {}; - - QFile::remove( path ); + if(QFileInfo::exists(path)) + return path; doc->b->dataFiles().at(size_t(row))->saveAs(path.toStdString()); + if(!QFileInfo::exists(path)) + return {}; FileDialog::setFileZone(path, doc->fileName()); return path; } @@ -420,14 +404,7 @@ void DigiDoc::clear() m_signatures.clear(); m_timestamps.clear(); m_fileName.clear(); - for(const QString &file: m_tempFiles) - { - //reset read-only attribute to enable delete file - FileDialog::setReadOnly(file, false); - QFile::remove(file); - } - - m_tempFiles.clear(); + m_documentModel->clearTempFolder(); modified = false; } @@ -512,19 +489,17 @@ bool DigiDoc::open( const QString &file ) try { WaitDialogHolder waitDialog(parent, tr("Opening"), false); return waitFor([&] { + m_fileName = file; b = Container::openPtr(to(file), &cb); if(b && b->mediaType() == "application/vnd.etsi.asic-s+zip" && b->dataFiles().size() == 1 && b->signatures().size() == 1) { - const DataFile *f = b->dataFiles().at(0); - if(from(f->fileName()).endsWith(QStringLiteral(".ddoc"), Qt::CaseInsensitive)) + if(from(b->dataFiles().at(0)->fileName()).endsWith(QStringLiteral(".ddoc"), Qt::CaseInsensitive)) { - const QString tmppath = FileDialog::tempPath(FileDialog::safeName(from(f->fileName()))); - f->saveAs(to(tmppath)); - if(QFileInfo::exists(tmppath)) + const QString tmppath = m_documentModel->saveTemp(0); + if(!tmppath.isEmpty()) { - m_tempFiles.append(tmppath); try { parentContainer = std::exchange(b, Container::openPtr(to(tmppath), &cb)); } catch(const Exception &) {} @@ -540,7 +515,6 @@ bool DigiDoc::open( const QString &file ) m_timestamps.append(DigiDocSignature(signature, this)); } Application::addRecent(file); - m_fileName = file; containerState = signatures().isEmpty() ? ContainerState::UnsignedSavedContainer : ContainerState::SignedContainer; return true; }); @@ -672,7 +646,7 @@ void DigiDoc::setLastError(const QString &title, const Exception &e) case Exception::PINFailed: dlg->withText(tr("PIN Login failed")); break; case Exception::PINIncorrect: - dlg->withText(tr("PIN Incorrect")); break; + dlg->withText(QCryptoBackend::tr("PIN Incorrect")); break; case Exception::PINLocked: dlg->withText(tr("PIN Locked. Unblock to reuse PIN.")); break; case Exception::NetworkError: @@ -721,7 +695,7 @@ bool DigiDoc::sign(const QString &city, const QString &state, const QString &zip case Exception::PINIncorrect: WarningDialog::create() ->withTitle(tr("Failed to sign container")) - ->withText(tr("PIN Incorrect")) + ->withText(QCryptoBackend::tr("PIN Incorrect")) ->exec(); return sign(city, state, zip, country, role, signer); case Exception::InvalidUrl: diff --git a/client/DigiDoc.h b/client/DigiDoc.h index ae975defb..1433134c1 100644 --- a/client/DigiDoc.h +++ b/client/DigiDoc.h @@ -93,11 +93,9 @@ class SDocumentModel final: public DocumentModel public: bool addFile(const QString &file, const QString &mime = QStringLiteral("application/octet-stream")) final; - void addTempReference(const QString &file) final; QString data(int row) const final; quint64 fileSize(int row) const final; QString mime(int row) const final; - void open(int row) final; bool removeRow(int row) final; int rowCount() const final; QString save(int row, const QString &path) const final; @@ -106,6 +104,8 @@ class SDocumentModel final: public DocumentModel SDocumentModel(DigiDoc *container); Q_DISABLE_COPY(SDocumentModel) + QString containerName() const final; + DigiDoc *doc; friend class DigiDoc; }; @@ -159,7 +159,6 @@ class DigiDoc: public QObject QList m_signatures, m_timestamps; bool modified = false; QString m_fileName; - QStringList m_tempFiles; friend class DigiDocSignature; friend class SDocumentModel; diff --git a/client/DocumentModel.cpp b/client/DocumentModel.cpp index 0e04ea5af..535d4fa03 100644 --- a/client/DocumentModel.cpp +++ b/client/DocumentModel.cpp @@ -23,11 +23,60 @@ #include "dialogs/FileDialog.h" #include "dialogs/WarningDialog.h" -#include +#include #include -#include +#include +#include +#include + +void DocumentModel::clearTempFolder() +{ + if(!m_tempFolder.isEmpty() && m_tempFolder != QDir::tempPath()) + { + for(const auto &info: QDir(m_tempFolder).entryInfoList(QDir::Files)) + FileDialog::setReadOnly(info.absoluteFilePath(), false); + QDir(m_tempFolder).removeRecursively(); + } + m_tempFolder.clear(); +} + +QString DocumentModel::saveTemp(int row) const +{ + if(m_tempFolder.isEmpty()) + { + QString name = containerName(); + if(!name.isEmpty()) + { + QDir tmp = QDir::temp(); + QString dirName = FileDialog::safeName(QFileInfo(name).completeBaseName()); + if(dirName.isEmpty()) + dirName = FileDialog::safeName(QFileInfo(name).fileName()); + if(!dirName.isEmpty()) + { + int i = 0; + QString candidate = dirName; + while(tmp.exists(candidate)) + candidate = QStringLiteral("%1_%2").arg(dirName).arg(i++); + if(tmp.mkdir(candidate)) + m_tempFolder = tmp.filePath(candidate); + } + } + if(m_tempFolder.isEmpty()) + m_tempFolder = QDir::tempPath(); + } + return save(row, QDir(m_tempFolder).filePath(FileDialog::safeName(data(row)))); +} -bool DocumentModel::addFileCheck(const QString &container, QFileInfo file) +void DocumentModel::removeTempFile(const QString &file) +{ + if(m_tempFolder.isEmpty() || m_tempFolder == QDir::tempPath()) + return; + QString path = QDir(m_tempFolder).filePath(FileDialog::safeName(file)); + FileDialog::setReadOnly(path, false); + QFile::remove(path); +} + +bool DocumentModel::addFileCheck(const QString &container, const QFileInfo &file) const { // Check that container is not dropped into itself if(QFileInfo(container) == file) @@ -64,42 +113,47 @@ bool DocumentModel::addFileCheck(const QString &container, QFileInfo file) return true; } -void DocumentModel::addTempFiles(const QStringList &files) +void DocumentModel::open(int row) { - for(const QString &file: files) + if(row >= rowCount()) + return; + static const QJsonArray defaultArray { + QStringLiteral("ddoc"), QStringLiteral("bdoc"), QStringLiteral("edoc"), QStringLiteral("adoc"), QStringLiteral("asice"), QStringLiteral("cdoc"), QStringLiteral("asics"), + QStringLiteral("txt"), QStringLiteral("doc"), QStringLiteral("docx"), QStringLiteral("odt"), QStringLiteral("ods"), QStringLiteral("tex"), QStringLiteral("wks"), QStringLiteral("wps"), + QStringLiteral("wpd"), QStringLiteral("rtf"), QStringLiteral("xlr"), QStringLiteral("xls"), QStringLiteral("xlsx"), QStringLiteral("pdf"), QStringLiteral("key"), QStringLiteral("odp"), + QStringLiteral("pps"), QStringLiteral("ppt"), QStringLiteral("pptx"), QStringLiteral("png"), QStringLiteral("jpg"), QStringLiteral("jpeg"), QStringLiteral("bmp"), QStringLiteral("ai"), + QStringLiteral("gif"), QStringLiteral("ico"), QStringLiteral("ps"), QStringLiteral("psd"), QStringLiteral("tif"), QStringLiteral("tiff"), QStringLiteral("csv")}; + QJsonArray allowedExts = Application::confValue(QLatin1String("ALLOWED-EXTENSIONS")).toArray(defaultArray); + if(!allowedExts.contains(QJsonValue(QFileInfo(data(row)).suffix().toLower()))) { - addFile(file); - addTempReference(file); + WarningDialog::create() + ->withTitle(tr("Failed to open file")) + ->withText(tr("A file with this extension cannot be opened in the DigiDoc4 Client. Download the file to view it.")) + ->setCancelText(WarningDialog::OK) + ->open(); + return; } + QString path = saveTemp(row); + if(path.isEmpty()) + return; + FileDialog::setReadOnly(path); + if(!containerName().endsWith(QLatin1String(".pdf"), Qt::CaseInsensitive) && FileDialog::isSignedPDF(path)) + Application::showClient({ std::move(path) }, false, false, true); + else + QDesktopServices::openUrl(QUrl::fromLocalFile(path)); } -QStringList DocumentModel::tempFiles() const +void DocumentModel::copyModel(DocumentModel *model) { - QStringList copied; - for(int i = 0, rows = rowCount(); i < rows; ++i) + if(!model) + return; + for(int i = 0, rows = model->rowCount(); i < rows; ++i) { - if(QFileInfo f(save(i, FileDialog::tempPath(data(i)))); f.exists()) - copied.append(f.absoluteFilePath()); + QString path = model->saveTemp(i); + if(path.isEmpty()) + continue; + addFile(path); } - return copied; -} - -bool DocumentModel::verifyFile(const QString &f) -{ - static const QJsonArray defaultArray { - QStringLiteral("ddoc"), QStringLiteral("bdoc") ,QStringLiteral("edoc"), QStringLiteral("adoc"), QStringLiteral("asice"), QStringLiteral("cdoc"), QStringLiteral("asics"), - QStringLiteral("txt"), QStringLiteral("doc"), QStringLiteral("docx"), QStringLiteral("odt"), QStringLiteral("ods"), QStringLiteral("tex"), QStringLiteral("wks"), QStringLiteral("wps"), - QStringLiteral("wpd"), QStringLiteral("rtf"), QStringLiteral("xlr"), QStringLiteral("xls"), QStringLiteral("xlsx"), QStringLiteral("pdf"), QStringLiteral("key"), QStringLiteral("odp"), - QStringLiteral("pps"), QStringLiteral("ppt"), QStringLiteral("pptx"), QStringLiteral("png"), QStringLiteral("jpg"), QStringLiteral("jpeg"), QStringLiteral("bmp"), QStringLiteral("ai"), - QStringLiteral("gif"), QStringLiteral("ico"), QStringLiteral("ps"), QStringLiteral("psd"), QStringLiteral("tif"), QStringLiteral("tiff"), QStringLiteral("csv")}; - - QJsonArray allowedExts = Application::confValue(QLatin1String("ALLOWED-EXTENSIONS")).toArray(defaultArray); - if(allowedExts.contains(QJsonValue(QFileInfo(f).suffix().toLower()))) - return true; - WarningDialog::create() - ->withTitle(tr("Failed to open file")) - ->withText(tr("A file with this extension cannot be opened in the DigiDoc4 Client. Download the file to view it.")) - ->setCancelText(WarningDialog::OK) - ->open(); - return false; + if(m_tempFolder.isEmpty()) + m_tempFolder = std::exchange(model->m_tempFolder, {}); } diff --git a/client/DocumentModel.h b/client/DocumentModel.h index 192b9ed21..471e24a8f 100644 --- a/client/DocumentModel.h +++ b/client/DocumentModel.h @@ -29,21 +29,25 @@ class DocumentModel: public QObject using QObject::QObject; virtual bool addFile(const QString &file, const QString &mime = QStringLiteral("application/octet-stream")) = 0; - virtual void addTempFiles(const QStringList &files); - virtual void addTempReference(const QString &file) = 0; + virtual void copyModel(DocumentModel *model); virtual QString data(int row) const = 0; virtual quint64 fileSize(int row) const = 0; virtual QString mime(int row) const = 0; - virtual void open(int row) = 0; + virtual void open(int row); virtual bool removeRow(int row) = 0; virtual int rowCount() const = 0; virtual QString save(int row, const QString &path) const = 0; - virtual QStringList tempFiles() const; + void clearTempFolder(); + QString saveTemp(int row) const; signals: void added(const QString &file); protected: - bool addFileCheck(const QString &container, QFileInfo file); - static bool verifyFile(const QString &f); + bool addFileCheck(const QString &container, const QFileInfo &file) const; + virtual QString containerName() const = 0; + void removeTempFile(const QString &file); + +private: + mutable QString m_tempFolder; }; diff --git a/client/MainWindow.cpp b/client/MainWindow.cpp index 3aced7083..b8a12036f 100644 --- a/client/MainWindow.cpp +++ b/client/MainWindow.cpp @@ -340,7 +340,7 @@ void MainWindow::convertToCDoc() if (digiDoc->state() == SignedContainer) cryptoContainer->documentModel()->addFile(digiDoc->fileName()); else - cryptoContainer->documentModel()->addTempFiles(digiDoc->documentModel()->tempFiles()); + cryptoContainer->documentModel()->copyModel(digiDoc->documentModel()); auto cardData = qApp->signer()->tokenauth(); if (!cardData.cert().isNull()) { @@ -607,7 +607,7 @@ bool MainWindow::wrap(const QString& wrappedFile, bool pdf) if(pdf) signatureContainer->documentModel()->addFile(wrappedFile); else - signatureContainer->documentModel()->addTempFiles(cryptoDoc->documentModel()->tempFiles()); + signatureContainer->documentModel()->copyModel(cryptoDoc->documentModel()); cryptoDoc.reset(); resetDigiDoc(std::move(signatureContainer)); diff --git a/client/dialogs/FileDialog.cpp b/client/dialogs/FileDialog.cpp index ddb891b46..4b15a9335 100644 --- a/client/dialogs/FileDialog.cpp +++ b/client/dialogs/FileDialog.cpp @@ -323,18 +323,6 @@ QStringList FileDialog::result( const QStringList &list ) return l; } -QString FileDialog::tempPath(const QString &file) -{ - QDir tmp = QDir::temp(); - if(!tmp.exists(file)) - return tmp.path() + '/' + file; - QFileInfo info(file); - int i = 0; - while(tmp.exists(QStringLiteral("%1_%2.%3").arg(info.baseName()).arg(i).arg(info.suffix()))) - ++i; - return QStringLiteral("%1/%2_%3.%4").arg(tmp.path()).arg(info.baseName()).arg(i).arg(info.suffix()); -} - QString FileDialog::safeName(const QString &file) { QFileInfo info(file); diff --git a/client/dialogs/FileDialog.h b/client/dialogs/FileDialog.h index 0de2d4d83..cb87355ff 100644 --- a/client/dialogs/FileDialog.h +++ b/client/dialogs/FileDialog.h @@ -41,7 +41,6 @@ class FileDialog : public QFileDialog static void setReadOnly(const QString &path, bool readonly = true); static QString normalized(const QString &file); static QString safeName(const QString &file); - static QString tempPath(const QString &file); static QString getOpenFileName(QWidget *parent = nullptr, const QString &caption = {}, const QString &dir = {}, const QString &filter = {}, diff --git a/client/translations/en.ts b/client/translations/en.ts index 158c6a678..4d311c8eb 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -758,10 +758,6 @@ Missing signature Missing signature - - PIN Incorrect - PIN Incorrect - PIN Login failed PIN Login failed diff --git a/client/translations/et.ts b/client/translations/et.ts index a26b51075..ddf901b35 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -758,10 +758,6 @@ Missing signature Allkiri puudub - - PIN Incorrect - Vale PIN - PIN Login failed PIN-koodi valideerimine ebaõnnestus diff --git a/client/widgets/FileItem.cpp b/client/widgets/FileItem.cpp index aac72b47c..80374c92a 100644 --- a/client/widgets/FileItem.cpp +++ b/client/widgets/FileItem.cpp @@ -61,11 +61,6 @@ bool FileItem::event(QEvent *event) return Item::event(event); } -QString FileItem::getFile() -{ - return fileName; -} - void FileItem::initTabOrder(QWidget *item) { setTabOrder(item, ui->fileName); diff --git a/client/widgets/FileItem.h b/client/widgets/FileItem.h index 5976fdda5..1176ec3c4 100644 --- a/client/widgets/FileItem.h +++ b/client/widgets/FileItem.h @@ -33,7 +33,6 @@ class FileItem final : public Item explicit FileItem(QString file, ria::qdigidoc4::ContainerState state, QWidget *parent = nullptr); ~FileItem() final; - QString getFile(); void initTabOrder(QWidget *item) final; QWidget* lastTabWidget() final; void stateChange(ria::qdigidoc4::ContainerState state) final; diff --git a/client/widgets/FileList.cpp b/client/widgets/FileList.cpp index 6130ba498..eb78a6dd2 100644 --- a/client/widgets/FileList.cpp +++ b/client/widgets/FileList.cpp @@ -62,7 +62,8 @@ void FileList::clear() bool FileList::eventFilter(QObject *obj, QEvent *event) { - if(!qobject_cast(obj)) + auto *fileItem = qobject_cast(obj); + if(!fileItem || !documentModel) return ItemList::eventFilter(obj, event); switch(event->type()) { @@ -81,21 +82,22 @@ bool FileList::eventFilter(QObject *obj, QEvent *event) if((mouse->pos() - obj->property("dragStartPosition").toPoint()).manhattanLength() < QApplication::startDragDistance()) break; - auto *fileItem = qobject_cast(obj); - if(!documentModel || !fileItem) - break; int i = index(fileItem); if(i == -1) break; - QString path = FileDialog::tempPath(fileItem->getFile()); - documentModel->save(i, path); - documentModel->addTempReference(path); + QString path = documentModel->saveTemp(i); + if(path.isEmpty()) + break; + FileDialog::setReadOnly(path, false); auto *mimeData = new QMimeData; mimeData->setText(QFileInfo(path).fileName()); mimeData->setUrls({ QUrl::fromLocalFile(path) }); auto *drag = new QDrag(this); drag->setMimeData(mimeData); - drag->exec(Qt::CopyAction); + if(drag->exec(Qt::MoveAction | Qt::CopyAction) == Qt::MoveAction) + QFile::remove(path); + else + FileDialog::setReadOnly(path); return true; } default: break; @@ -127,10 +129,11 @@ void FileList::save(FileItem *item) { if(int i = index(item); documentModel && i != -1) { - QString extension = QFileInfo(item->getFile()).suffix(); - QString capitalized = extension[0].toUpper() + extension.mid(1); + QString file = FileDialog::safeName(documentModel->data(i)); + QString extension = QFileInfo(file).suffix(); + QString capitalized = extension.isEmpty() ? QString() : extension[0].toUpper() + extension.mid(1); QString dest = FileDialog::getSaveFileName(this, FileDialog::tr("Save file"), - QFileInfo(container).dir().absolutePath() + QDir::separator() + FileDialog::safeName(item->getFile()), + QFileInfo(container).dir().absolutePath() + QDir::separator() + file, QStringLiteral("%1 (*%2)").arg(capitalized, extension)); if(!dest.endsWith(QStringLiteral(".%1").arg(extension)) && !extension.isEmpty()) @@ -217,7 +220,7 @@ void FileList::setModel(DocumentModel *documentModel) void FileList::stateChange(ria::qdigidoc4::ContainerState state) { ItemList::stateChange(state); - updateDownload(); + updateDownload(); } void FileList::updateDownload()