View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0017625 | Scribus | General | public | 2025-09-14 07:56 | 2025-10-18 18:49 |
Reporter | ale | Assigned To | |||
Priority | normal | Severity | feature | Reproducibility | N/A |
Status | new | Resolution | open | ||
Summary | 0017625: [PATCH] Persist "Save as"'s format and add "Save a copy" to a different format | ||||
Description | - When you "Save as" the 1.6 format, Scribus should continue to save as 1.6 during the current session (as long as the file is kept open); currently, it saves as 1.6 but the subsequent calls to "Save" will use the current format for the Scribus version (1.7 in the specific case) - "Save a copy" should save a copy (with a different name / different format) and not change the file name / format for the document currently loaded. | ||||
Tags | No tags attached. | ||||
Patch | Yes | ||||
|
At tonight's Hackergarten we managed to write the code for "Save a copy". With a bit of luck I can create a patch during the weekend... |
|
The patch attached adds the new menu entry "File > Save a Copy", which does not save the current document but creates a copy of it in a new file. On top of it, "File > Save As" is modified to store for the current session, and uses it as default in the "Save As" dialog for the same file. The format is then also used when saving the same file (during the session). Implementation "details": - The "Save a Copy" menu entry is added in the "File" menu, just after "Save As" - "Save a Copy" is enabled and disabled in the same way as "Save As" - When a document is "saved as" a different format the current one, the format is added to the filename in the title bar. ## scribus.cpp getFileNameAndFormatForSaveAs(int fileFormat): - A bit simplified and now Scribus warns with the "final" file name and not the one typed by the user (with the .sla added) - Refactered out the input and sanitizing of the file name from the code doing the saving - Renamed fileNameVersion to fileNameAndFormat; but i might want to go for fileNameAndVersion instead - Changed the logic for removing the gz: it should also be triggered if the current file is gz `updateActiveWindowCaption()` now can be called without arguments and uses the current document state to set the window title. Files with a .gz extension are marked as currently Gzipped (on top of using the document settings). ## customfdialog.cpp Removed a selectNameFilter() that was simply trying to select the whole filters list... ## Follow up tasks - Avoid updating the window title on each key press (0017654) - When opening an old (but "supported") format, ask the user if the document should be kept in the old format (and warn on close that some data might get lost) save-copy.diff (32,553 bytes)
From 1a5f96a83b8cbd8a77e67c82d3cd815169a31e7c Mon Sep 17 00:00:00 2001 From: ale rimoldi <ale@graphicslab.org> Date: Sat, 18 Oct 2025 19:50:03 +0200 Subject: add Save a Copy and improve Save As and better persist the document version for the session diff --git a/scribus/actionmanager.cpp b/scribus/actionmanager.cpp index 6051d5c46..2b67d5187 100644 --- a/scribus/actionmanager.cpp +++ b/scribus/actionmanager.cpp @@ -127,6 +127,8 @@ void ActionManager::initFileMenuActions() scrActions->insert(name, new ScrAction("document-save", "document-save", "", defaultKey(name), mainWindow)); name = "fileSaveAs"; scrActions->insert(name, new ScrAction("document-save-as", "document-save-as", "", defaultKey(name), mainWindow)); + name = "fileSaveCopy"; + scrActions->insert(name, new ScrAction("", defaultKey(name), mainWindow)); name = "fileRevert"; scrActions->insert(name, new ScrAction("revert", QString(), "", defaultKey(name), mainWindow)); name = "fileCollect"; @@ -185,6 +187,7 @@ void ActionManager::initFileMenuActions() connect( (*scrActions)["OutputPreviewPS"], SIGNAL(triggered()), mainWindow, SLOT(outputPreviewPS()) ); connect( (*scrActions)["fileSave"], SIGNAL(triggered()), mainWindow, SLOT(slotFileSave()) ); connect( (*scrActions)["fileSaveAs"], SIGNAL(triggered()), mainWindow, SLOT(slotFileSaveAs()) ); + connect( (*scrActions)["fileSaveCopy"], SIGNAL(triggered()), mainWindow, SLOT(slotFileSaveCopy()) ); connect( (*scrActions)["fileDocSetup150"], SIGNAL(triggered()), mainWindow, SLOT(slotDocSetup()) ); connect( (*scrActions)["filePreferences150"], SIGNAL(triggered()), mainWindow, SLOT(slotPrefsOrg()) ); connect( (*scrActions)["fileRevert"], SIGNAL(triggered()), mainWindow, SLOT(slotFileRevert()) ); @@ -1503,6 +1506,7 @@ void ActionManager::languageChange() (*scrActions)["fileClose"]->setTexts( tr("&Close")); (*scrActions)["fileSave"]->setTexts( tr("&Save")); (*scrActions)["fileSaveAs"]->setTexts( tr("Save &As...")); + (*scrActions)["fileSaveCopy"]->setTexts( tr("Save a Co&py...")); (*scrActions)["fileRevert"]->setTexts( tr("Re&vert to Saved")); (*scrActions)["fileCollect"]->setTexts( tr("Collect for O&utput...")); (*scrActions)["fileImportText"]->setTexts( tr("Get Text...")); @@ -2092,6 +2096,7 @@ void ActionManager::createDefaultMenus() << "fileClose" << "fileSave" << "fileSaveAs" + << "fileSaveCopy" << "fileRevert" << "fileCollect" << "fileImportText" diff --git a/scribus/appmodehelper.cpp b/scribus/appmodehelper.cpp index 06016c344..1dc5bd487 100644 --- a/scribus/appmodehelper.cpp +++ b/scribus/appmodehelper.cpp @@ -1197,6 +1197,7 @@ void AppModeHelper::setSymbolEditMode(bool b, const ScribusDoc* doc) (*a_scrActions)["filePrint"]->setEnabled(b2); (*a_scrActions)["fileCollect"]->setEnabled(b2); (*a_scrActions)["fileSaveAs"]->setEnabled(b2); + (*a_scrActions)["fileSaveCopy"]->setEnabled(b2); (*a_scrActions)["fileExportAsEPS"]->setEnabled(b2); (*a_scrActions)["fileExportAsPDF"]->setEnabled(b2); if (ScCore->haveGS() || ScCore->isWinGUI()) @@ -1252,6 +1253,7 @@ void AppModeHelper::setInlineEditMode(bool b, const ScribusDoc *doc) (*a_scrActions)["filePrint"]->setEnabled(b2); (*a_scrActions)["fileCollect"]->setEnabled(b2); (*a_scrActions)["fileSaveAs"]->setEnabled(b2); + (*a_scrActions)["fileSaveCopy"]->setEnabled(b2); (*a_scrActions)["fileExportAsEPS"]->setEnabled(b2); (*a_scrActions)["fileExportAsPDF"]->setEnabled(b2); if (ScCore->haveGS() || ScCore->isWinGUI()) @@ -1471,6 +1473,7 @@ void AppModeHelper::mainWindowHasNewDoc(const ScribusDoc *doc, bool clipScrapHav (*a_scrActions)["fileRevert"]->setEnabled(false); (*a_scrActions)["fileCollect"]->setEnabled(true); (*a_scrActions)["fileSaveAs"]->setEnabled(true); + (*a_scrActions)["fileSaveCopy"]->setEnabled(true); (*a_scrActions)["fileExportAsEPS"]->setEnabled(true); (*a_scrActions)["fileExportAsPDF"]->setEnabled(true); (*a_scrActions)["fileImportVector"]->setEnabled(true); @@ -1580,6 +1583,7 @@ void AppModeHelper::mainWindowSwitchWin(const ScribusDoc *doc) { (*a_scrActions)["fileCollect"]->setEnabled(false); (*a_scrActions)["fileSaveAs"]->setEnabled(false); + (*a_scrActions)["fileSaveCopy"]->setEnabled(false); (*a_scrActions)["fileExportAsEPS"]->setEnabled(false); (*a_scrActions)["fileExportAsPDF"]->setEnabled(false); (*a_scrActions)["fileSave"]->setEnabled(false); @@ -1624,6 +1628,7 @@ void AppModeHelper::mainWindowSwitchWin(const ScribusDoc *doc) (*a_scrActions)["pageManageProperties"]->setEnabled(true); (*a_scrActions)["fileSaveAs"]->setEnabled(true); + (*a_scrActions)["fileSaveCopy"]->setEnabled(true); (*a_scrActions)["fileCollect"]->setEnabled(true); (*a_scrActions)["toolsPDFPushButton"]->setEnabled(true); (*a_scrActions)["toolsPDFRadioButton"]->setEnabled(true); @@ -1691,6 +1696,7 @@ void AppModeHelper::mainWindowCloseLastDoc() (*a_scrActions)["fileRevert"]->setEnabled(false); (*a_scrActions)["fileSave"]->setEnabled(false); (*a_scrActions)["fileSaveAs"]->setEnabled(false); + (*a_scrActions)["fileSaveCopy"]->setEnabled(false); (*a_scrActions)["insertFrame"]->setEnabled(false); (*a_scrActions)["insertSampleText"]->setEnabled(false); (*a_scrActions)["itemAdjustFrameToImage"]->setEnabled(false); @@ -1865,6 +1871,7 @@ void AppModeHelper::setStartupActionsEnabled(bool enabled) (*a_scrActions)["filePrint"]->setEnabled(false); (*a_scrActions)["fileSave"]->setEnabled(false); (*a_scrActions)["fileSaveAs"]->setEnabled(false); + (*a_scrActions)["fileSaveCopy"]->setEnabled(false); (*a_scrActions)["fileRevert"]->setEnabled(false); (*a_scrActions)["fileCollect"]->setEnabled(false); (*a_scrActions)["fileClose"]->setEnabled(false); diff --git a/scribus/loadsaveplugin.cpp b/scribus/loadsaveplugin.cpp index 28a6ae415..ca39d9b12 100644 --- a/scribus/loadsaveplugin.cpp +++ b/scribus/loadsaveplugin.cpp @@ -67,6 +67,17 @@ QStringList LoadSavePlugin::fileDialogSaveFilter() return getDialogFilter(false, true); } +QString LoadSavePlugin::fileDialogSaveFilter(uint filter) +{ + return getDialogFilterById(filter, true); +} + +QString LoadSavePlugin::fileDialogSaveFilterName(uint filter) +{ + return getDialogFilterNameById(filter, true); + +} + QStringList LoadSavePlugin::getExtensionsForColors(const int id) { QList<FileFormat>::const_iterator it(findFormat(id)); @@ -214,6 +225,26 @@ const QStringList LoadSavePlugin::getDialogFilter(bool forLoad, bool scribusOnly return scribusList+filterList; } +const QString LoadSavePlugin::getDialogFilterById(uint id, bool forLoad) +{ + for (const FileFormat& format: formats) + { + if (format.load == forLoad && format.formatId == id) + return format.filter; + } + return ""; +} + +const QString LoadSavePlugin::getDialogFilterNameById(uint id, bool forLoad) +{ + for (const FileFormat& format: formats) + { + if (format.load == forLoad && format.formatId == id) + return format.trName; + } + return ""; +} + bool LoadSavePlugin::saveFile(const QString & /* fileName */, const FileFormat & /* fmt */) { diff --git a/scribus/loadsaveplugin.h b/scribus/loadsaveplugin.h index 90db6b4c9..f034e2b07 100644 --- a/scribus/loadsaveplugin.h +++ b/scribus/loadsaveplugin.h @@ -69,6 +69,16 @@ class SCRIBUS_API LoadSavePlugin : public ScPlugin // Same deal but for save static QStringList fileDialogSaveFilter(); + /** + * @param filter the index in the list of save filters + * @return empty if the filter is not found + */ + static QString fileDialogSaveFilter(uint filter); + /** + * @param filter the index in the list of save filters + * @return empty if the filter is not found + */ + static QString fileDialogSaveFilterName(uint filter); // Get the highest priority format of a given id, or 0 if // not found / not available. @@ -183,6 +193,15 @@ class SCRIBUS_API LoadSavePlugin : public ScPlugin // Base implementation for fileDialogLoadFilter and fileDialogSaveFilter static const QStringList getDialogFilter(bool forLoad, bool scribusOnly); + /** + * @return the filter name by its ID, as used by the Save As dialog (with the list of extensions); + * returns empty string if the filter is not found. + */ + static const QString getDialogFilterById(uint id, bool forLoad); + /** + * @return the filter name by its ID, without the list of extensions; empty string if the filter is not found. + */ + static const QString getDialogFilterNameById(uint id, bool forLoad); }; diff --git a/scribus/scribus.cpp b/scribus/scribus.cpp index c1457a882..8a271925c 100644 --- a/scribus/scribus.cpp +++ b/scribus/scribus.cpp @@ -922,6 +922,7 @@ void ScribusMainWindow::initMenuBar() scrMenuMgr->addMenuItemString("fileClose", "File"); scrMenuMgr->addMenuItemString("fileSave", "File"); scrMenuMgr->addMenuItemString("fileSaveAs", "File"); + scrMenuMgr->addMenuItemString("fileSaveCopy", "File"); scrMenuMgr->addMenuItemString("fileRevert", "File"); scrMenuMgr->addMenuItemString("fileCollect", "File"); scrMenuMgr->addMenuItemString("SEPARATOR", "File"); @@ -2006,7 +2007,7 @@ bool ScribusMainWindow::recoverFile(const QStringList& foundFiles) continue; doc->setDocumentFileName(dia->recoverNames[i]); doc->hasName = true; - updateActiveWindowCaption(doc->documentFileName()); + updateActiveWindowCaption(); outlinePalette->setDoc(doc); if (outlinePalette->isVisible()) outlinePalette->BuildTree(); @@ -2047,7 +2048,7 @@ void ScribusMainWindow::startUpDialog() // Don's disturb user with "save?" dialog just after new doc // doc changing should be rewritten maybe... maybe later... doc->setModified(false); - updateActiveWindowCaption(doc->documentFileName()); + updateActiveWindowCaption(); } else if (dia->tabSelected() == NewDocDialog::NewFromTemplateTab) { @@ -2057,6 +2058,7 @@ void ScribusMainWindow::startUpDialog() doc->hasName = false; UndoManager::instance()->renameStack(dia->nftGui->currentDocumentTemplate->name); doc->setDocumentFileName(dia->nftGui->currentDocumentTemplate->name); + // TODO: we should probaby add a field to doc saying that it's a template and use updateWindowCaptionForDocument() updateActiveWindowCaption(QObject::tr("Document Template: ") + dia->nftGui->currentDocumentTemplate->name); QDir::setCurrent(PrefsManager::instance().documentDir()); removeRecent(fileName); @@ -2127,7 +2129,7 @@ bool ScribusMainWindow::slotFileNew() // Don't disturb user with "save?" dialog just after new doc // doc changing should be rewritten maybe... maybe later... doc->setModified(false); - updateActiveWindowCaption(doc->documentFileName()); + updateActiveWindowCaption(); } if (docSet) @@ -2296,6 +2298,7 @@ void ScribusMainWindow::newFileFromTemplate() doc->hasName = false; UndoManager::instance()->renameStack(currentTemplate->name); doc->setDocumentFileName(currentTemplate->name); + // TODO: we should probaby add a field to doc saying that it's a template and use updateWindowCaptionForDocument() updateActiveWindowCaption(QObject::tr("Document Template: ") + currentTemplate->name); QDir::setCurrent(PrefsManager::instance().documentDir()); removeRecent(QDir::cleanPath(currentTemplate->file)); @@ -2563,7 +2566,7 @@ void ScribusMainWindow::windowsMenuActivated(int id) void ScribusMainWindow::SwitchWin() { - updateActiveWindowCaption(doc->documentFileName()); + updateActiveWindowCaption(); propertiesPalette->setDoc(doc); contentPalette->setDoc(doc); marksManager->setDoc(doc); @@ -2612,7 +2615,7 @@ void ScribusMainWindow::HaveNewDoc() appModeHelper->mainWindowHasNewDoc(doc, (ScMimeData::clipboardHasScribusData()) || (scrapbookPalette->tempHasContents())); //Update palettes - updateActiveWindowCaption(doc->documentFileName()); + updateActiveWindowCaption(); propertiesPalette->setDoc(doc); contentPalette->setDoc(doc); nsEditor->setDoc(doc); @@ -2756,7 +2759,9 @@ void ScribusMainWindow::slotDocCh(bool /*reb*/) { if (!doc->isModified()) doc->setModified(true); - updateActiveWindowCaption(doc->documentFileName() + "*"); + + updateActiveWindowCaption(); + if (!doc->masterPageMode()) { if (!doc->symbolEditMode() && !doc->inlineEditMode()) @@ -4054,23 +4059,24 @@ bool ScribusMainWindow::slotFileSave() { QString fn(doc->documentFileName()); QString savedFileName; - ret = DoFileSave(fn, &savedFileName); + ret = DoFileSave(fn, &savedFileName, doc->getSaveAsFormat()); if (!ret && !savedFileName.isEmpty()) ScMessageBox::warning(this, CommonStrings::trWarning, tr("Your document was saved to a temporary file and could not be moved: \n%1").arg( QDir::toNativeSeparators(savedFileName) )); else if (!ret) ScMessageBox::warning(this, CommonStrings::trWarning, tr("Cannot write the file: \n%1").arg( QDir::toNativeSeparators(fn) )); + updateActiveWindowCaption(); } else ret = slotFileSaveAs(); return ret; } -bool ScribusMainWindow::slotFileSaveAs() +QPair<QString, uint> ScribusMainWindow::getFileNameAndFormatForSaveAs(int fileFormat) { - bool ret = false; QString fileName; PrefsContext* docContext = m_prefsManager.prefsFile->getContext("docdirs", false); QString wdir; + bool currentlyGzipped = false; if (doc->hasName) { QFileInfo fi(doc->documentFileName()); @@ -4078,7 +4084,10 @@ bool ScribusMainWindow::slotFileSaveAs() if (completeBaseName.endsWith(".sla", Qt::CaseInsensitive)) completeBaseName.chop(4); else if (completeBaseName.endsWith(".gz", Qt::CaseInsensitive)) + { + currentlyGzipped = false; completeBaseName.chop(3); + } wdir = QDir::fromNativeSeparators( fi.path() ); fileName = QDir::fromNativeSeparators( fi.path()+"/"+completeBaseName+".sla" ); } @@ -4094,50 +4103,85 @@ bool ScribusMainWindow::slotFileSaveAs() fileName += "/"; fileName += doc->documentFileName() + ".sla"; } - bool saveCompressed = m_prefsManager.appPrefs.docSetupPrefs.saveCompressed; - if (saveCompressed) + bool wantsSaveCompressed = currentlyGzipped || m_prefsManager.appPrefs.docSetupPrefs.saveCompressed; + if (wantsSaveCompressed) fileName.append(".gz"); - //QString formats = tr("Documents (*.sla *.sla.gz);;All Files (*)"); QString formats(FileLoader::getSaveAsFilterString()); int optionFlags = fdCompressFile | fdHidePreviewCheckBox; - QPair<QString, uint> fileNameVersion { fileName, FORMATID_CURRENTEXPORT }; - fileNameVersion = CFileDialog( wdir, tr("Save As"), formats, fileName, optionFlags, &saveCompressed); - QString fn(fileNameVersion.first); - if (!fn.isEmpty()) - { - docContext->set("save_as", fn.left(fn.lastIndexOf("/"))); - fileName = fn; - if (!((fn.endsWith(".sla")) || (fn.endsWith(".sla.gz")))) - fileName = fn+".sla"; - if (overwrite(this, fileName)) - { - QString savedFileName; - ret = DoFileSave(fileName, &savedFileName, fileNameVersion.second); - if (!ret && !savedFileName.isEmpty()) - ScMessageBox::warning(this, CommonStrings::trWarning, tr("Your document was saved to a temporary file and could not be moved: \n%1").arg( QDir::toNativeSeparators(savedFileName) )); - else if (!ret) - ScMessageBox::warning(this, CommonStrings::trWarning, tr("Cannot write the file: \n%1").arg( QDir::toNativeSeparators(fn) )); - else - doc->pdfOptions().fileName.clear(); // #1482 reset the pdf file name + QPair<QString, uint> fileNameAndFormat { fileName, fileFormat }; + fileNameAndFormat = CFileDialog( wdir, tr("Save As"), formats, fileNameAndFormat, optionFlags, &wantsSaveCompressed); + + fileName = fileNameAndFormat.first; + + if (!fileName.isEmpty()) + { + docContext->set("save_as", fileName.left(fileName.lastIndexOf("/"))); + fileNameAndFormat.first = fileName; + if (!((fileName.endsWith(".sla")) || (fileName.endsWith(".sla.gz")))) + fileNameAndFormat.first = fileName+".sla"; + } + + if (!overwrite(this, fileNameAndFormat.first)) + fileNameAndFormat = {"", 0}; + + return fileNameAndFormat; +} + +bool ScribusMainWindow::slotFileSaveAs() +{ + bool ret = false; + int saveAsFormat = doc->getSaveAsFormat(); + QPair<QString, uint> fileNameAndFormat = getFileNameAndFormatForSaveAs(saveAsFormat); + if (!fileNameAndFormat.first.isEmpty()) + { + QString savedFileName; + ret = DoFileSave(fileNameAndFormat.first, &savedFileName, fileNameAndFormat.second); + if (!ret && !savedFileName.isEmpty()) + ScMessageBox::warning(this, CommonStrings::trWarning, tr("Your document was saved to a temporary file and could not be moved: \n%1").arg( QDir::toNativeSeparators(savedFileName) )); + else if (!ret) + ScMessageBox::warning(this, CommonStrings::trWarning, tr("Cannot write the file: \n%1").arg( QDir::toNativeSeparators(fileNameAndFormat.first) )); + else + { + doc->pdfOptions().fileName.clear(); // #1482 reset the pdf file name + doc->setSaveAsFormat(fileNameAndFormat.second); } + updateActiveWindowCaption(); } - m_mainWindowStatusLabel->setText( tr("Ready")); + m_mainWindowStatusLabel->setText(tr("Ready")); return ret; } -bool ScribusMainWindow::DoFileSave(const QString& fileName, QString* savedFileName, uint formatID) +bool ScribusMainWindow::slotFileSaveCopy() +{ + bool success = false; + QPair<QString, uint> fileNameAndFormat = getFileNameAndFormatForSaveAs(); + if (!fileNameAndFormat.first.isEmpty()) + { + QString savedFileName; + success = DoFileSave(fileNameAndFormat.first, &savedFileName, fileNameAndFormat.second, true); + if (!success && !savedFileName.isEmpty()) + ScMessageBox::warning(this, CommonStrings::trWarning, tr("Your document was saved to a temporary file and could not be moved: \n%1").arg( QDir::toNativeSeparators(savedFileName) )); + else if (!success) + ScMessageBox::warning(this, CommonStrings::trWarning, tr("Cannot write the file: \n%1").arg( QDir::toNativeSeparators(fileNameAndFormat.first) )); + else + doc->pdfOptions().fileName.clear(); // #1482 reset the pdf file name + } + m_mainWindowStatusLabel->setText(tr("Ready")); + return success; +} + +bool ScribusMainWindow::DoFileSave(const QString& fileName, QString* savedFileName, uint formatID, bool saveACopy) { ScCore->fileWatcher->forceScan(); ScCore->fileWatcher->stop(); doc->reorganiseFonts(); m_mainWindowStatusLabel->setText( tr("Saving...")); mainWindowProgressBar->reset(); - bool ret = doc->save(fileName, savedFileName, formatID); + bool ret = doc->save(fileName, savedFileName, formatID, saveACopy); QApplication::processEvents(); - if (ret) + if (!saveACopy && ret) { - updateActiveWindowCaption(fileName); m_undoManager->renameStack(fileName); scrActions["fileRevert"]->setEnabled(false); updateRecent(fileName); @@ -7553,7 +7597,7 @@ void ScribusMainWindow::editSymbolEnd() layerPalette->setEnabled(true); if (outlinePalette->isVisible()) outlinePalette->BuildTree(false); - updateActiveWindowCaption(doc->documentFileName()); + updateActiveWindowCaption(); } void ScribusMainWindow::editInlineStart(int id) @@ -7602,7 +7646,7 @@ void ScribusMainWindow::editInlineEnd() layerPalette->setEnabled(true); if (outlinePalette->isVisible()) outlinePalette->BuildTree(false); - updateActiveWindowCaption(doc->documentFileName()); + updateActiveWindowCaption(); } void ScribusMainWindow::editMasterPagesStart(const QString& temp) @@ -7994,20 +8038,19 @@ void ScribusMainWindow::StatusPic() delete dia; } -QPair<QString, uint> ScribusMainWindow::CFileDialog(const QString& workingDirectory, const QString& dialogCaption, const QString& fileFilter, const QString& defaultFilename, int optionFlags, bool *useCompression, bool *useFonts, bool *useProfiles) +QPair<QString, uint> ScribusMainWindow::CFileDialog(const QString& workingDirectory, const QString& dialogCaption, const QString& fileFilter, const QPair<QString, uint>& defaultFilenameVersion, int optionFlags, bool *useCompression, bool *useFonts, bool *useProfiles) { - // changed from "this" to qApp->activeWindow() to be sure it will be opened - // with the current active window as parent. E.g. it won't hide StoryEditor etc. -- PV CustomFDialog *dia = new CustomFDialog(QApplication::activeWindow(), workingDirectory, dialogCaption, fileFilter, optionFlags); - if (!defaultFilename.isEmpty()) + dia->selectNameFilter(defaultFilenameVersion.second); + if (!defaultFilenameVersion.first.isEmpty()) { - QString tmpFileName = defaultFilename; - if (tmpFileName.endsWith(".gz", Qt::CaseInsensitive)) - tmpFileName.chop(3); - QFileInfo f(tmpFileName); + QString tmpFilename = defaultFilenameVersion.first; + if (tmpFilename.endsWith(".gz", Qt::CaseInsensitive)) + tmpFilename.chop(3); + QFileInfo f(tmpFilename); dia->setExtension(f.suffix()); dia->setZipExtension(f.suffix() + ".gz"); - dia->setSelection(defaultFilename); + dia->setSelection(defaultFilenameVersion.first); if (useCompression != nullptr) dia->setSaveZipFile(*useCompression); } @@ -8021,8 +8064,7 @@ QPair<QString, uint> ScribusMainWindow::CFileDialog(const QString& workingDirect dia->setIncludeProfiles(*useProfiles); } - QPair<QString, uint> fileNameVersion; - fileNameVersion.second = FORMATID_CURRENTEXPORT; + QPair<QString, uint> filenameVersion; if (dia->exec() == QDialog::Accepted) { if (!(optionFlags & fdDirectoriesOnly)) @@ -8043,18 +8085,25 @@ QPair<QString, uint> ScribusMainWindow::CFileDialog(const QString& workingDirect *useProfiles = dia->includeProfiles(); } this->repaint(); - fileNameVersion.first = dia->selectedFile(); + filenameVersion.second = FORMATID_CURRENTEXPORT; + filenameVersion.first = dia->selectedFile(); //Qt 6.8 changes what selectedNameFilter returns.. now includes the file extension list. Remove it. QString formatName(dia->selectedNameFilter()); int location = formatName.indexOf("("); if (location > 0) formatName.truncate(location); formatName = formatName.trimmed(); - fileNameVersion.second=FileLoader::findFormatIDFromDescription(formatName); + filenameVersion.second=FileLoader::findFormatIDFromDescription(formatName); QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } delete dia; - return fileNameVersion; + return filenameVersion; +} + +QPair<QString, uint> ScribusMainWindow::CFileDialog(const QString& workingDirectory, const QString& dialogCaption, const QString& fileFilter, const QString& defaultFilename, int optionFlags, bool *useCompression, bool *useFonts, bool *useProfiles) +{ + QPair<QString, uint> filenameVersion{defaultFilename, FORMATID_CURRENTEXPORT}; + return CFileDialog(workingDirectory, dialogCaption, fileFilter, filenameVersion, optionFlags, useCompression, useFonts, useProfiles); } @@ -8602,6 +8651,18 @@ void ScribusMainWindow::updateActiveWindowCaption(const QString &newCaption) ActWin->setWindowTitle(QDir::toNativeSeparators(newCaption)); } +void ScribusMainWindow::updateActiveWindowCaption() +{ + if (!HaveDoc) + return; + QString caption = QDir::toNativeSeparators(doc->documentFileName()); + if (doc->isModified()) + caption += QStringLiteral("*"); + if (!doc->isDefaultSaveAsFormat()) + caption += QStringLiteral("|") + LoadSavePlugin::fileDialogSaveFilterName(doc->getSaveAsFormat()); + ActWin->setWindowTitle(caption); +}; + void ScribusMainWindow::dragEnterEvent ( QDragEnterEvent* e) { bool accepted = false; diff --git a/scribus/scribus.h b/scribus/scribus.h index 7b2a7185b..d5434f0b9 100644 --- a/scribus/scribus.h +++ b/scribus/scribus.h @@ -156,7 +156,7 @@ public: ScribusDoc* doFileNew(double width, double height, double topMargin, double leftMargin, double rightMargin, double bottomMargin, double columnDistance, double columnCount, bool autoTextFrames, int pageArrangement, int unitIndex, int firstPageLocation, int orientation, int firstPageNumber, const QString& defaultPageSize, bool requiresGUI, int pageCount = 1, bool showView = true, int marginPreset = 0); ScribusDoc* newDoc(double width, double height, double topMargin, double leftMargin, double rightMargin, double bottomMargin, double columnDistance, double columnCount, bool autoTextFrames, int pageArrangement, int unitIndex, int firstPageLocation, int orientation, int firstPageNumber, const QString& defaultPageSize, bool requiresGUI, int pageCount = 1, bool showView = true, int marginPreset = 0); - bool DoFileSave(const QString& fileName, QString* savedFileName = nullptr, uint formatID = FORMATID_CURRENTEXPORT); + bool DoFileSave(const QString& fileName, QString* savedFileName = nullptr, uint formatID = FORMATID_CURRENTEXPORT, bool saveACopy = false); void changeEvent(QEvent *e) override; void closeEvent(QCloseEvent *ce) override; @@ -174,7 +174,9 @@ public: bool getPDFDriver(const QString & filename, const std::vector<int> & pageNumbers, const QMap<int, QImage> & thumbs, QString& error, bool* cancelled = nullptr); bool DoSaveAsEps(const QString& fn, QString& error); QPair<QString, uint> CFileDialog(const QString& workingDirectory = ".", const QString& dialogCaption = "", const QString& fileFilter = "", const QString& defNa = "", - int optionFlags = fdExistingFiles, bool *useCompression = 0, bool *useFonts = 0, bool *useProfiles = 0); + int optionFlags = fdExistingFiles, bool *useCompression = nullptr, bool *useFonts = nullptr, bool *useProfiles = nullptr); + QPair<QString, uint> CFileDialog(const QString& workingDirectory, const QString& dialogCaption, const QString& fileFilter, const QPair<QString, uint>& filenameVersion, + int optionFlags = fdExistingFiles, bool *useCompression = nullptr, bool *useFonts = nullptr, bool *useProfiles = nullptr); /*! \brief Recalculate the colors after changing CMS settings. Call the appropriate document function and then update the GUI elements. \param dia optional progress widget */ @@ -321,7 +323,14 @@ public slots: void extrasMenuAboutToShow(); void newActWin(QMdiSubWindow *w); void closeActiveWindowMasterPageEditor(); + /** + * Use newCaption for the the window title + */ void updateActiveWindowCaption(const QString &newCaption); + /** + * Use the information about the current document to create the window title + */ + void updateActiveWindowCaption(); void windowsMenuActivated(int id); void PutScrap(int scID); void PutToInline(const QString& buffer); @@ -377,6 +386,7 @@ public slots: bool slotFileSave(); /** \brief save a document under a different filename*/ bool slotFileSaveAs(); + bool slotFileSaveCopy(); void slotFileRevert(); /** \brief Sichert den Text eines Elements */ void SaveText(); @@ -475,10 +485,10 @@ public slots: /** \brief Switch appMode \param mode TODO learn modes*/ void setAppModeByToggle(bool isOn, int newMode); - /** \brief Neues Dokument erzeugt */ + /** \brief A new document has been created */ void HaveNewDoc(); void HaveNewSel(); - /** Dokument ist geaendert worden */ + /** The document has been changed */ void slotDocCh(bool reb = true); /** Page preview changed */ void slotPreviewCh(); @@ -631,6 +641,16 @@ private: void initPalettes(); void initScrapbook(); void updateColorMenu(QProgressBar* progressBar = nullptr); + /** + * Get the file name and format version for a new Scribus document. + * + * Display the "Save As" dialog and sanitize the file name entered by the user. + * + * The file name is empty if the user cancels the process or the file is invalid. + * + * @return A pair of file name (QString) and Scribus File Format Version (uint) + */ + QPair<QString, uint> getFileNameAndFormatForSaveAs(int fileFormat=FORMATID_CURRENTEXPORT); int m_ScriptRunning {0}; diff --git a/scribus/scribusdoc.cpp b/scribus/scribusdoc.cpp index c77efe316..0411e5b50 100644 --- a/scribus/scribusdoc.cpp +++ b/scribus/scribusdoc.cpp @@ -2349,6 +2349,23 @@ bool ScribusDoc::isModified() const return m_modified; } +void ScribusDoc::setSaveAsFormat(int saveAsFormat) +{ + if (m_saveAsFormat != saveAsFormat) + { + m_saveAsFormat = saveAsFormat; + } +} + +int ScribusDoc::getSaveAsFormat() const +{ + return m_saveAsFormat; +} + +bool ScribusDoc::isDefaultSaveAsFormat() const { + return m_saveAsFormat == FORMATID_CURRENTEXPORT; +} + bool ScribusDoc::isUndoRedoOngoing() const { return (m_undoRedoOngoing != 0); @@ -4778,7 +4795,7 @@ void ScribusDoc::restoreCopyPage(SimpleState* ss, bool isUndo) } -bool ScribusDoc::save(const QString& fileName, QString* savedFile, uint formatID) +bool ScribusDoc::save(const QString& fileName, QString* savedFile, uint formatID, bool saveACopy) { QProgressBar* mainWindowProgressBar = nullptr; if (ScCore->usingGUI()) @@ -4790,6 +4807,8 @@ bool ScribusDoc::save(const QString& fileName, QString* savedFile, uint formatID bool ret = fl.saveFile(fileName, this, savedFile, formatID); if (!ret) return false; + if (saveACopy) + return true; setDocumentFileName(fileName); setModified(false); hasName = true; diff --git a/scribus/scribusdoc.h b/scribus/scribusdoc.h index 389113876..0a5676436 100644 --- a/scribus/scribusdoc.h +++ b/scribus/scribusdoc.h @@ -112,6 +112,19 @@ public: bool isLoading() const; void setModified(bool); bool isModified() const; + /** + * Set the latest format used when saving a document as + * + * @param saveAsFormat one of FORMATID_SLA*EXPORT from plugins/formatidlist.h + */ + void setSaveAsFormat(int saveAsFormat); + /** + * Get the latest format used when saving a document as + * + * @return saveAsFormat one of FORMATID_SLA*EXPORT from plugins/formatidlist.h + */ + int getSaveAsFormat() const; + bool isDefaultSaveAsFormat() const; bool isUndoRedoOngoing() const; /** Setzt die Seitenattribute */ void setPage(double w, double h, double t, double l, double r, double b, double sp, double ab, bool atf, int fp); @@ -818,7 +831,7 @@ public: /** * @brief Save function */ - bool save(const QString& fileName, QString* savedFile = nullptr, uint formatID = FORMATID_CURRENTEXPORT); + bool save(const QString& fileName, QString* savedFile = nullptr, uint formatID = FORMATID_CURRENTEXPORT, bool saveACopy = false); /** * @brief Set the page margins. Current code uses current page only, also provide a (currently, TODO) option for this. */ @@ -1312,6 +1325,7 @@ protected: UndoManager * const m_undoManager; bool m_loading {false}; bool m_modified {false}; + int m_saveAsFormat {FORMATID_CURRENTEXPORT}; int m_undoRedoOngoing {0}; int m_ActiveLayer {0}; double m_docUnitRatio; diff --git a/scribus/ui/customfdialog.cpp b/scribus/ui/customfdialog.cpp index 169d14bc6..6691a49fd 100644 --- a/scribus/ui/customfdialog.cpp +++ b/scribus/ui/customfdialog.cpp @@ -39,6 +39,7 @@ for which a new license (GPL+exception) is in place. #include <QScreen> #include <QTextCodec> #include <QVBoxLayout> #include "customfdialog.h" @@ -296,7 +297,6 @@ CustomFDialog::CustomFDialog(QWidget *parent, const QString &wDir, const QString fileDialog = new ScFileWidget(this, contextFlags); fileDialog->setIconProvider(new ImIconProvider()); fileDialog->setNameFilter(filter); - fileDialog->selectNameFilter(filter); fileDialog->setDirectory(wDir); hboxLayout->addWidget(fileDialog); vboxLayout1 = new QVBoxLayout; @@ -570,6 +570,16 @@ void CustomFDialog::togglePreview() update(); } +void CustomFDialog::selectNameFilter(const int nameFilter) +{ + fileDialog->selectNameFilter(LoadSavePlugin::fileDialogSaveFilter(nameFilter)); +} + +void CustomFDialog::selectNameFilter(const QString& nameFilter) +{ + fileDialog->selectNameFilter(nameFilter); +} + void CustomFDialog::setSelection(const QString& fileName) { fileDialog->selectFile( QFileInfo(fileName).fileName() ); diff --git a/scribus/ui/customfdialog.h b/scribus/ui/customfdialog.h index 4dfde5add..6229469ae 100644 --- a/scribus/ui/customfdialog.h +++ b/scribus/ui/customfdialog.h @@ -102,9 +102,11 @@ public: \param filter a mask/filter. E.g.: *.txt \param flags combination of fdFlags, default to fdExistingFiles */ - CustomFDialog(QWidget *parent, const QString& wDir, const QString& caption = "", const QString& filter = "", int flags = fdExistingFiles, fwContextFlags contextFlags = contextNone); + explicit CustomFDialog(QWidget *parent, const QString& wDir, const QString& caption = "", const QString& filter = "", int flags = fdExistingFiles, fwContextFlags contextFlags = contextNone); ~CustomFDialog() = default; + void selectNameFilter(const int nameFilter); + void selectNameFilter(const QString& nameFilter); void setSelection(const QString& fileName); QString selectedFile() const; QStringList selectedFiles() const; |
Date Modified | Username | Field | Change |
---|---|---|---|
2025-09-14 07:56 | ale | New Issue | |
2025-09-25 20:34 | ale | Note Added: 0053039 | |
2025-10-18 18:49 | ale | Note Added: 0053075 | |
2025-10-18 18:49 | ale | File Added: save-copy.diff | |
2025-10-18 18:49 | ale | Summary | Persist "Save as"'s format and add "Save a copy" to a different format => [PATCH] Persist "Save as"'s format and add "Save a copy" to a different format |
2025-10-18 18:49 | ale | Patch | No => Yes |