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

@ -499,13 +499,14 @@ public:
enum ModificationFlag
{
None = 0x0000, ///< No flag
Reset = 0x0001, ///< Whole document content is changed (for example, new document is being set)
PageContents = 0x0002, ///< Page contents changed (page graphics, not annotations)
Annotation = 0x0004, ///< Annotations 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)
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)
None = 0x0000, ///< No flag
Reset = 0x0001, ///< Whole document content is changed (for example, new document is being set)
PageContents = 0x0002, ///< Page contents changed (page graphics, not annotations)
Annotation = 0x0004, ///< Annotations 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)
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)

View File

@ -1057,6 +1057,11 @@ void PDFProgramController::saveDocument(const QString& fileName)
pdf::PDFOperationResult result = writer.write(fileName, m_pdfDocument.data(), true);
if (result)
{
if (m_undoRedoManager)
{
m_undoRedoManager->setIsCurrentSaved(true);
}
updateFileInfo(fileName);
updateTitle();
@ -1091,6 +1096,41 @@ bool PDFProgramController::canClose() const
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
{
return m_fileInfo.originalFileName;
@ -1174,7 +1214,7 @@ void PDFProgramController::onActionOptimizeTriggered()
if (dialog.exec() == QDialog::Accepted)
{
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));
}
}
@ -1186,7 +1226,7 @@ void PDFProgramController::onActionSanitizeTriggered()
if (dialog.exec() == QDialog::Accepted)
{
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));
}
}
@ -1626,7 +1666,7 @@ void PDFProgramController::onDocumentReadingFinished()
m_pdfDocument = qMove(result.document);
m_signatures = qMove(result.signatures);
pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity);
setDocument(document);
setDocument(document, true);
if (m_formManager)
{
@ -1687,17 +1727,17 @@ void PDFProgramController::onDocumentModified(pdf::PDFModifiedDocument document)
m_pdfDocument = document;
document.setOptionalContentActivity(m_optionalContentActivity);
setDocument(document);
setDocument(document, false);
}
void PDFProgramController::onDocumentUndoRedo(pdf::PDFModifiedDocument document)
{
m_pdfDocument = document;
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())
{
@ -1714,7 +1754,7 @@ void PDFProgramController::setDocument(pdf::PDFModifiedDocument document)
m_optionalContentActivity = new pdf::PDFOptionalContentActivity(document, pdf::OCUsage::View, this);
}
if (m_undoRedoManager)
if (m_undoRedoManager && !document.hasFlag(pdf::PDFModifiedDocument::PreserveUndoRedo))
{
m_undoRedoManager->clear();
}
@ -1747,6 +1787,11 @@ void PDFProgramController::setDocument(pdf::PDFModifiedDocument document)
m_textToSpeech->setDocument(document);
}
if (m_undoRedoManager)
{
m_undoRedoManager->setIsCurrentSaved(isCurrentSaved);
}
m_pdfWidget->setDocument(document);
m_mainWindowInterface->setDocument(document);
m_CMSManager->setDocument(document);
@ -1777,7 +1822,7 @@ void PDFProgramController::setDocument(pdf::PDFModifiedDocument document)
void PDFProgramController::closeDocument()
{
m_signatures.clear();
setDocument(pdf::PDFModifiedDocument());
setDocument(pdf::PDFModifiedDocument(), true);
m_pdfDocument.reset();
updateActionsAvailability();
updateTitle();
@ -1797,10 +1842,17 @@ void PDFProgramController::updateTitle()
if (m_pdfDocument)
{
QString title = m_pdfDocument->getInfo()->title;
if (title.isEmpty())
{
title = m_fileInfo.fileName;
}
if (m_undoRedoManager && !m_undoRedoManager->isCurrentSaved())
{
title += "*";
}
m_mainWindow->setWindowTitle(tr("%1 - %2").arg(title, QApplication::applicationDisplayName()));
}
else
@ -2046,7 +2098,10 @@ void PDFProgramController::onActionOpenTriggered()
void PDFProgramController::onActionCloseTriggered()
{
closeDocument();
if (askForSaveDocumentBeforeClose())
{
closeDocument();
}
}
void PDFProgramController::onActionDeveloperCreateInstaller()

View File

@ -255,7 +255,7 @@ public:
Q_DECLARE_FLAGS(Features, Feature)
void openDocument(const QString& fileName);
void setDocument(pdf::PDFModifiedDocument document);
void setDocument(pdf::PDFModifiedDocument document, bool isCurrentSaved);
void closeDocument();
pdf::PDFWidget* getPdfWidget() const { return m_pdfWidget; }
@ -287,6 +287,7 @@ public:
void setIsBusy(bool isBusy);
bool canClose() const;
bool askForSaveDocumentBeforeClose();
virtual QString getOriginalFileName() 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.
//
@ -42,6 +42,7 @@ void PDFUndoRedoManager::doUndo()
UndoRedoItem item = m_undoSteps.back();
m_undoSteps.pop_back();
m_isCurrentSaved = false;
m_redoSteps.insert(m_redoSteps.begin(), item);
clampUndoRedoSteps();
@ -59,6 +60,7 @@ void PDFUndoRedoManager::doRedo()
UndoRedoItem item = m_redoSteps.front();
m_redoSteps.erase(m_redoSteps.begin());
m_isCurrentSaved = false;
m_undoSteps.push_back(item);
clampUndoRedoSteps();
@ -80,6 +82,7 @@ void PDFUndoRedoManager::createUndo(pdf::PDFModifiedDocument document, pdf::PDFD
{
m_undoSteps.emplace_back(oldDocument, document, document.getFlags());
m_redoSteps.clear();
m_isCurrentSaved = false;
clampUndoRedoSteps();
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

View File

@ -1,4 +1,4 @@
// Copyright (C) 2020-2021 Jakub Melka
// Copyright (C) 2020-2023 Jakub Melka
//
// This file is part of PDF4QT.
//
@ -62,6 +62,12 @@ public:
/// \param redoLimit Maximum redo steps
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:
/// This signals are emitted, when undo/redo action availability has
/// been changed (for example, user pressed undo/redo action)
@ -97,6 +103,7 @@ private:
size_t m_redoLimit = 0;
std::vector<UndoRedoItem> m_undoSteps;
std::vector<UndoRedoItem> m_redoSteps;
bool m_isCurrentSaved = true;
};
} // namespace pdfviewer

View File

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

View File

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