Issue #43: Save question

This commit is contained in:
Jakub Melka
2023-02-26 18:37:27 +01:00
parent edf7642151
commit 9a064508ab
7 changed files with 104 additions and 19 deletions

View File

@ -506,6 +506,7 @@ public:
FormField = 0x0008, ///< Form field content changed FormField = 0x0008, ///< Form field content changed
Authorization = 0x0010, ///< Authorization has changed (for example, old document is granted user access, but for new, owner access) Authorization = 0x0010, ///< Authorization has changed (for example, old document is granted user access, but for new, owner access)
XFA_Pagination = 0x0020, ///< XFA pagination has been performed (this flag can be set only when Reset flag has been set and not any other flag) XFA_Pagination = 0x0020, ///< XFA pagination has been performed (this flag can be set only when Reset flag has been set and not any other flag)
PreserveUndoRedo = 0x0040, ///< Preserve undo/red even when Reset flag is being set
}; };
Q_DECLARE_FLAGS(ModificationFlags, ModificationFlag) Q_DECLARE_FLAGS(ModificationFlags, ModificationFlag)

View File

@ -1057,6 +1057,11 @@ void PDFProgramController::saveDocument(const QString& fileName)
pdf::PDFOperationResult result = writer.write(fileName, m_pdfDocument.data(), true); pdf::PDFOperationResult result = writer.write(fileName, m_pdfDocument.data(), true);
if (result) if (result)
{ {
if (m_undoRedoManager)
{
m_undoRedoManager->setIsCurrentSaved(true);
}
updateFileInfo(fileName); updateFileInfo(fileName);
updateTitle(); updateTitle();
@ -1091,6 +1096,41 @@ bool PDFProgramController::canClose() const
return !(m_futureWatcher && m_futureWatcher->isRunning()) || !m_isBusy; return !(m_futureWatcher && m_futureWatcher->isRunning()) || !m_isBusy;
} }
bool PDFProgramController::askForSaveDocumentBeforeClose()
{
if (!m_pdfDocument)
{
// Nothing to be done
return true;
}
if (m_undoRedoManager && !m_undoRedoManager->isCurrentSaved())
{
QString title = tr("Save Document");
QString message = tr("Do you wish to save modified document before it is closed?");
switch (QMessageBox::question(m_mainWindow, title, message, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel))
{
case QMessageBox::Yes:
{
performSave();
return m_undoRedoManager->isCurrentSaved();
}
case QMessageBox::No:
return true;
case QMessageBox::Cancel:
return false;
default:
Q_ASSERT(false);
return true;
}
}
return true;
}
QString PDFProgramController::getOriginalFileName() const QString PDFProgramController::getOriginalFileName() const
{ {
return m_fileInfo.originalFileName; return m_fileInfo.originalFileName;
@ -1174,7 +1214,7 @@ void PDFProgramController::onActionOptimizeTriggered()
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
pdf::PDFDocumentPointer pointer(new pdf::PDFDocument(dialog.takeOptimizedDocument())); pdf::PDFDocumentPointer pointer(new pdf::PDFDocument(dialog.takeOptimizedDocument()));
pdf::PDFModifiedDocument document(qMove(pointer), m_optionalContentActivity, pdf::PDFModifiedDocument::Reset); pdf::PDFModifiedDocument document(qMove(pointer), m_optionalContentActivity, pdf::PDFModifiedDocument::ModificationFlags(pdf::PDFModifiedDocument::Reset | pdf::PDFModifiedDocument::PreserveUndoRedo));
onDocumentModified(qMove(document)); onDocumentModified(qMove(document));
} }
} }
@ -1186,7 +1226,7 @@ void PDFProgramController::onActionSanitizeTriggered()
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
pdf::PDFDocumentPointer pointer(new pdf::PDFDocument(dialog.takeSanitizedDocument())); pdf::PDFDocumentPointer pointer(new pdf::PDFDocument(dialog.takeSanitizedDocument()));
pdf::PDFModifiedDocument document(qMove(pointer), m_optionalContentActivity, pdf::PDFModifiedDocument::Reset); pdf::PDFModifiedDocument document(qMove(pointer), m_optionalContentActivity, pdf::PDFModifiedDocument::ModificationFlags(pdf::PDFModifiedDocument::Reset | pdf::PDFModifiedDocument::PreserveUndoRedo));
onDocumentModified(qMove(document)); onDocumentModified(qMove(document));
} }
} }
@ -1626,7 +1666,7 @@ void PDFProgramController::onDocumentReadingFinished()
m_pdfDocument = qMove(result.document); m_pdfDocument = qMove(result.document);
m_signatures = qMove(result.signatures); m_signatures = qMove(result.signatures);
pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity); pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity);
setDocument(document); setDocument(document, true);
if (m_formManager) if (m_formManager)
{ {
@ -1687,17 +1727,17 @@ void PDFProgramController::onDocumentModified(pdf::PDFModifiedDocument document)
m_pdfDocument = document; m_pdfDocument = document;
document.setOptionalContentActivity(m_optionalContentActivity); document.setOptionalContentActivity(m_optionalContentActivity);
setDocument(document); setDocument(document, false);
} }
void PDFProgramController::onDocumentUndoRedo(pdf::PDFModifiedDocument document) void PDFProgramController::onDocumentUndoRedo(pdf::PDFModifiedDocument document)
{ {
m_pdfDocument = document; m_pdfDocument = document;
document.setOptionalContentActivity(m_optionalContentActivity); document.setOptionalContentActivity(m_optionalContentActivity);
setDocument(document); setDocument(document, false);
} }
void PDFProgramController::setDocument(pdf::PDFModifiedDocument document) void PDFProgramController::setDocument(pdf::PDFModifiedDocument document, bool isCurrentSaved)
{ {
if (document.hasReset()) if (document.hasReset())
{ {
@ -1714,7 +1754,7 @@ void PDFProgramController::setDocument(pdf::PDFModifiedDocument document)
m_optionalContentActivity = new pdf::PDFOptionalContentActivity(document, pdf::OCUsage::View, this); m_optionalContentActivity = new pdf::PDFOptionalContentActivity(document, pdf::OCUsage::View, this);
} }
if (m_undoRedoManager) if (m_undoRedoManager && !document.hasFlag(pdf::PDFModifiedDocument::PreserveUndoRedo))
{ {
m_undoRedoManager->clear(); m_undoRedoManager->clear();
} }
@ -1747,6 +1787,11 @@ void PDFProgramController::setDocument(pdf::PDFModifiedDocument document)
m_textToSpeech->setDocument(document); m_textToSpeech->setDocument(document);
} }
if (m_undoRedoManager)
{
m_undoRedoManager->setIsCurrentSaved(isCurrentSaved);
}
m_pdfWidget->setDocument(document); m_pdfWidget->setDocument(document);
m_mainWindowInterface->setDocument(document); m_mainWindowInterface->setDocument(document);
m_CMSManager->setDocument(document); m_CMSManager->setDocument(document);
@ -1777,7 +1822,7 @@ void PDFProgramController::setDocument(pdf::PDFModifiedDocument document)
void PDFProgramController::closeDocument() void PDFProgramController::closeDocument()
{ {
m_signatures.clear(); m_signatures.clear();
setDocument(pdf::PDFModifiedDocument()); setDocument(pdf::PDFModifiedDocument(), true);
m_pdfDocument.reset(); m_pdfDocument.reset();
updateActionsAvailability(); updateActionsAvailability();
updateTitle(); updateTitle();
@ -1797,10 +1842,17 @@ void PDFProgramController::updateTitle()
if (m_pdfDocument) if (m_pdfDocument)
{ {
QString title = m_pdfDocument->getInfo()->title; QString title = m_pdfDocument->getInfo()->title;
if (title.isEmpty()) if (title.isEmpty())
{ {
title = m_fileInfo.fileName; title = m_fileInfo.fileName;
} }
if (m_undoRedoManager && !m_undoRedoManager->isCurrentSaved())
{
title += "*";
}
m_mainWindow->setWindowTitle(tr("%1 - %2").arg(title, QApplication::applicationDisplayName())); m_mainWindow->setWindowTitle(tr("%1 - %2").arg(title, QApplication::applicationDisplayName()));
} }
else else
@ -2045,9 +2097,12 @@ void PDFProgramController::onActionOpenTriggered()
} }
void PDFProgramController::onActionCloseTriggered() void PDFProgramController::onActionCloseTriggered()
{
if (askForSaveDocumentBeforeClose())
{ {
closeDocument(); closeDocument();
} }
}
void PDFProgramController::onActionDeveloperCreateInstaller() void PDFProgramController::onActionDeveloperCreateInstaller()
{ {

View File

@ -255,7 +255,7 @@ public:
Q_DECLARE_FLAGS(Features, Feature) Q_DECLARE_FLAGS(Features, Feature)
void openDocument(const QString& fileName); void openDocument(const QString& fileName);
void setDocument(pdf::PDFModifiedDocument document); void setDocument(pdf::PDFModifiedDocument document, bool isCurrentSaved);
void closeDocument(); void closeDocument();
pdf::PDFWidget* getPdfWidget() const { return m_pdfWidget; } pdf::PDFWidget* getPdfWidget() const { return m_pdfWidget; }
@ -287,6 +287,7 @@ public:
void setIsBusy(bool isBusy); void setIsBusy(bool isBusy);
bool canClose() const; bool canClose() const;
bool askForSaveDocumentBeforeClose();
virtual QString getOriginalFileName() const override; virtual QString getOriginalFileName() const override;
virtual pdf::PDFTextSelection getSelectedText() const override; virtual pdf::PDFTextSelection getSelectedText() const override;

View File

@ -1,4 +1,4 @@
// Copyright (C) 2020-2022 Jakub Melka // Copyright (C) 2020-2023 Jakub Melka
// //
// This file is part of PDF4QT. // This file is part of PDF4QT.
// //
@ -42,6 +42,7 @@ void PDFUndoRedoManager::doUndo()
UndoRedoItem item = m_undoSteps.back(); UndoRedoItem item = m_undoSteps.back();
m_undoSteps.pop_back(); m_undoSteps.pop_back();
m_isCurrentSaved = false;
m_redoSteps.insert(m_redoSteps.begin(), item); m_redoSteps.insert(m_redoSteps.begin(), item);
clampUndoRedoSteps(); clampUndoRedoSteps();
@ -59,6 +60,7 @@ void PDFUndoRedoManager::doRedo()
UndoRedoItem item = m_redoSteps.front(); UndoRedoItem item = m_redoSteps.front();
m_redoSteps.erase(m_redoSteps.begin()); m_redoSteps.erase(m_redoSteps.begin());
m_isCurrentSaved = false;
m_undoSteps.push_back(item); m_undoSteps.push_back(item);
clampUndoRedoSteps(); clampUndoRedoSteps();
@ -80,6 +82,7 @@ void PDFUndoRedoManager::createUndo(pdf::PDFModifiedDocument document, pdf::PDFD
{ {
m_undoSteps.emplace_back(oldDocument, document, document.getFlags()); m_undoSteps.emplace_back(oldDocument, document, document.getFlags());
m_redoSteps.clear(); m_redoSteps.clear();
m_isCurrentSaved = false;
clampUndoRedoSteps(); clampUndoRedoSteps();
Q_EMIT undoRedoStateChanged(); Q_EMIT undoRedoStateChanged();
} }
@ -109,4 +112,14 @@ void PDFUndoRedoManager::clampUndoRedoSteps()
} }
} }
bool PDFUndoRedoManager::isCurrentSaved() const
{
return m_isCurrentSaved;
}
void PDFUndoRedoManager::setIsCurrentSaved(bool newIsCurrentSaved)
{
m_isCurrentSaved = newIsCurrentSaved;
}
} // namespace pdfviewer } // namespace pdfviewer

View File

@ -1,4 +1,4 @@
// Copyright (C) 2020-2021 Jakub Melka // Copyright (C) 2020-2023 Jakub Melka
// //
// This file is part of PDF4QT. // This file is part of PDF4QT.
// //
@ -62,6 +62,12 @@ public:
/// \param redoLimit Maximum redo steps /// \param redoLimit Maximum redo steps
void setMaximumSteps(size_t undoLimit, size_t redoLimit); void setMaximumSteps(size_t undoLimit, size_t redoLimit);
/// Returns true, if document was saved
bool isCurrentSaved() const;
/// Sets flag, if document was saved
void setIsCurrentSaved(bool newIsCurrentSaved = true);
signals: signals:
/// This signals are emitted, when undo/redo action availability has /// This signals are emitted, when undo/redo action availability has
/// been changed (for example, user pressed undo/redo action) /// been changed (for example, user pressed undo/redo action)
@ -97,6 +103,7 @@ private:
size_t m_redoLimit = 0; size_t m_redoLimit = 0;
std::vector<UndoRedoItem> m_undoSteps; std::vector<UndoRedoItem> m_undoSteps;
std::vector<UndoRedoItem> m_redoSteps; std::vector<UndoRedoItem> m_redoSteps;
bool m_isCurrentSaved = true;
}; };
} // namespace pdfviewer } // namespace pdfviewer

View File

@ -502,6 +502,13 @@ void PDFViewerMainWindow::closeEvent(QCloseEvent* event)
} }
else else
{ {
if (!m_programController->askForSaveDocumentBeforeClose())
{
// User cancelled close operation
event->ignore();
return;
}
if (!m_programController->isFactorySettingsBeingRestored()) if (!m_programController->isFactorySettingsBeingRestored())
{ {
m_programController->writeSettings(); m_programController->writeSettings();

View File

@ -1,4 +1,5 @@
CURRENT: CURRENT:
- Issue #43: Save question
- Issue #40: Sanitization of documents - Issue #40: Sanitization of documents
V: 1.3.2 1.2.2023 V: 1.3.2 1.2.2023