File > Save functions.

This commit is contained in:
Roman Telezhynskyi 2021-05-21 17:17:22 +03:00
parent 67fc4b7539
commit d10355b400
10 changed files with 260 additions and 136 deletions

View File

@ -45,6 +45,12 @@
#include "../vwidgets/vmaingraphicsscene.h" #include "../vwidgets/vmaingraphicsscene.h"
#include "vpsheet.h" #include "vpsheet.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
#include "../vmisc/backport/qscopeguard.h"
#else
#include <QScopeGuard>
#endif
#include <QLoggingCategory> #include <QLoggingCategory>
QT_WARNING_PUSH QT_WARNING_PUSH
@ -157,16 +163,50 @@ bool VPMainWindow::LoadFile(QString path)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VPMainWindow::SaveFile(const QString &path) void VPMainWindow::LayoutWasSaved(bool saved)
{
setWindowModified(!saved);
not lIsReadOnly ? ui->actionSave->setEnabled(!saved): ui->actionSave->setEnabled(false);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::SetCurrentFile(const QString &fileName)
{
curFile = fileName;
if (not curFile.isEmpty())
{
auto settings = VPApplication::VApp()->PuzzleSettings();
QStringList files = settings->GetRecentFileList();
files.removeAll(fileName);
files.prepend(fileName);
while (files.size() > MaxRecentFiles)
{
files.removeLast();
}
settings->SetRecentFileList(files);
UpdateRecentFileActions();
}
UpdateWindowTitle();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPMainWindow::SaveLayout(const QString &path, QString &error) -> bool
{ {
QFile file(path); QFile file(path);
file.open(QIODevice::WriteOnly); file.open(QIODevice::WriteOnly);
VPLayoutFileWriter *fileWriter = new VPLayoutFileWriter(); VPLayoutFileWriter fileWriter;
fileWriter->WriteFile(m_layout, &file); fileWriter.WriteFile(m_layout, &file);
// TODO / FIXME : better return value and error handling if (fileWriter.hasError())
{
error = tr("Fail to create layout.");
return false;
}
SetCurrentFile(path);
LayoutWasSaved(true);
return true; return true;
} }
@ -1058,47 +1098,143 @@ void VPMainWindow::on_actionOpen_triggered()
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::on_actionSave_triggered() bool VPMainWindow::on_actionSave_triggered()
{ {
// just for test purpuses, to be removed: if (curFile.isEmpty() || lIsReadOnly)
QMessageBox msgBox; {
msgBox.setText("TODO VPMainWindow::Save"); return on_actionSaveAs_triggered();
int ret = msgBox.exec(); }
Q_UNUSED(ret); if (m_curFileFormatVersion < VLayoutConverter::LayoutMaxVer
&& not ContinueFormatRewrite(m_curFileFormatVersionStr, VLayoutConverter::LayoutMaxVerStr))
{
return false;
}
// TODO if (not CheckFilePermissions(curFile, this))
{
return false;
}
QString error;
if (not SaveLayout(curFile, error))
{
QMessageBox messageBox;
messageBox.setIcon(QMessageBox::Warning);
messageBox.setText(tr("Could not save the file"));
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.setDetailedText(error);
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.exec();
return false;
}
m_curFileFormatVersion = VLayoutConverter::LayoutMaxVer;
m_curFileFormatVersionStr = VLayoutConverter::LayoutMaxVerStr;
return true;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::on_actionSaveAs_triggered() bool VPMainWindow::on_actionSaveAs_triggered()
{ {
// TODO / FIXME : See valentina how the save is done over there. we need to add the QString filters = tr("Layout files") + QStringLiteral(" (*.vlt)");
// extension .vlt, check for empty file names etc. QString suffix = QStringLiteral("vlt");
QString fName = tr("layout") + QChar('.') + suffix;
//Get list last open files
QStringList recentFiles = VPApplication::VApp()->PuzzleSettings()->GetRecentFileList();
QString dir; QString dir;
if (recentFiles.isEmpty()) if (curFile.isEmpty())
{ {
dir = QDir::homePath(); dir = VPApplication::VApp()->PuzzleSettings()->GetPathLayouts();
} }
else else
{ {
//Absolute path to last open file dir = QFileInfo(curFile).absolutePath();
dir = QFileInfo(recentFiles.first()).absolutePath();
} }
QString filters(tr("Layout files") + QLatin1String("(*.vlt)")); bool usedNotExistedDir = false;
QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"), QDir directory(dir);
dir + QLatin1String("/") + tr("Layout") + QLatin1String(".vlt"), if (not directory.exists())
filters, nullptr {
#ifdef Q_OS_LINUX usedNotExistedDir = directory.mkpath(QChar('.'));
, QFileDialog::DontUseNativeDialog }
#endif
);
SaveFile(fileName); QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"), dir + QChar('/') + fName, filters, nullptr,
VAbstractApplication::VApp()->NativeFileDialog());
auto RemoveTempDir = qScopeGuard([usedNotExistedDir, dir]()
{
if (usedNotExistedDir)
{
QDir(dir).rmpath(QChar('.'));
}
});
if (fileName.isEmpty())
{
return false;
}
QFileInfo f( fileName );
if (f.suffix().isEmpty() && f.suffix() != suffix)
{
fileName += QChar('.') + suffix;
}
if (QFileInfo::exists(fileName) && curFile != fileName)
{
// Temporary try to lock the file before saving
VLockGuard<char> tmp(fileName);
if (not tmp.IsLocked())
{
qCCritical(pWindow, "%s",
qUtf8Printable(tr("Failed to lock. This file already opened in another window.")));
return false;
}
}
// Need for restoring previous state in case of failure
// const bool readOnly = m_layout->IsReadOnly();
// m_layout->SetReadOnly(false);
lIsReadOnly = false;
QString error;
bool result = SaveLayout(fileName, error);
if (not result)
{
QMessageBox messageBox;
messageBox.setIcon(QMessageBox::Warning);
messageBox.setInformativeText(tr("Could not save file"));
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.setDetailedText(error);
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.exec();
// Restore previous state
// m_layout->SetReadOnly(readOnly);
// lIsReadOnly = readOnly;
return false;
}
m_curFileFormatVersion = VLayoutConverter::LayoutMaxVer;
m_curFileFormatVersionStr = VLayoutConverter::LayoutMaxVerStr;
// UpdatePadlock(false);
UpdateWindowTitle();
if (curFile == fileName && not lock.isNull())
{
lock->Unlock();
}
VlpCreateLock(lock, fileName);
if (not lock->IsLocked())
{
qCCritical(pWindow, "%s", qUtf8Printable(tr("Failed to lock. This file already opened in another window. "
"Expect collissions when run 2 copies of the program.")));
return false;
}
return true;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -43,6 +43,7 @@
#include "vpcommandline.h" #include "vpcommandline.h"
#include "../vlayout/vlayoutdef.h" #include "../vlayout/vlayoutdef.h"
#include "../vwidgets/vabstractmainwindow.h" #include "../vwidgets/vabstractmainwindow.h"
#include "../vmisc/vlockguard.h"
namespace Ui namespace Ui
{ {
@ -65,12 +66,15 @@ public:
*/ */
bool LoadFile(QString path); bool LoadFile(QString path);
void LayoutWasSaved(bool saved);
void SetCurrentFile(const QString &fileName);
/** /**
* @brief SaveFile Saves the current layout to the layout file of given path * @brief SaveLayout Saves the current layout to the layout file of given path
* @param path path to layout file * @param path path to layout file
* @return true if success * @return true if success
*/ */
bool SaveFile(const QString &path); bool SaveLayout(const QString &path, QString &error);
/** /**
* @brief ImportRawLayouts The function imports the raw layouts of given paths * @brief ImportRawLayouts The function imports the raw layouts of given paths
@ -110,14 +114,14 @@ private slots:
* triggered. * triggered.
* The slot is automatically connected through name convention. * The slot is automatically connected through name convention.
*/ */
void on_actionSave_triggered(); bool on_actionSave_triggered();
/** /**
* @brief on_actionSaveAs_triggered When the menu action File > Save As * @brief on_actionSaveAs_triggered When the menu action File > Save As
* is triggered. * is triggered.
* The slot is automatically connected through name convention. * The slot is automatically connected through name convention.
*/ */
void on_actionSaveAs_triggered(); bool on_actionSaveAs_triggered();
/** /**
* @brief on_actionImportRawLayout_triggered When the menu action * @brief on_actionImportRawLayout_triggered When the menu action
@ -424,6 +428,8 @@ private:
bool isInitialized{false}; bool isInitialized{false};
bool lIsReadOnly{false}; bool lIsReadOnly{false};
QSharedPointer<VLockGuard<char>> lock{nullptr};
/** /**
* @brief CreatePiece creates a piece from the given VLayoutPiece data * @brief CreatePiece creates a piece from the given VLayoutPiece data
* @param rawPiece the raw piece data * @param rawPiece the raw piece data

View File

@ -34,18 +34,6 @@
#include "vplayoutliterals.h" #include "vplayoutliterals.h"
#include "../ifc/xml/vlayoutconverter.h" #include "../ifc/xml/vlayoutconverter.h"
//---------------------------------------------------------------------------------------------------------------------
VPLayoutFileWriter::VPLayoutFileWriter()
{
}
//---------------------------------------------------------------------------------------------------------------------
VPLayoutFileWriter::~VPLayoutFileWriter()
{
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileWriter::WriteFile(VPLayout *layout, QFile *file) void VPLayoutFileWriter::WriteFile(VPLayout *layout, QFile *file)
{ {

View File

@ -31,6 +31,7 @@
#include <QLocale> #include <QLocale>
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
#include <QCoreApplication>
#include "../vmisc/literals.h" #include "../vmisc/literals.h"
@ -43,14 +44,14 @@ class QMarginsF;
class VPLayoutFileWriter : public QXmlStreamWriter class VPLayoutFileWriter : public QXmlStreamWriter
{ {
Q_DECLARE_TR_FUNCTIONS(VPLayoutFileWriter)
public: public:
VPLayoutFileWriter(); VPLayoutFileWriter()= default;
~VPLayoutFileWriter(); ~VPLayoutFileWriter()= default;
void WriteFile(VPLayout *layout, QFile *file); void WriteFile(VPLayout *layout, QFile *file);
private: private:
void WriteLayout(VPLayout *layout); void WriteLayout(VPLayout *layout);
void WriteProperties(VPLayout *layout); void WriteProperties(VPLayout *layout);
void WriteUnplacePiecesList(VPLayout *layout); void WriteUnplacePiecesList(VPLayout *layout);
@ -69,7 +70,6 @@ private:
template <size_t N> template <size_t N>
void SetAttribute(const QString &name, const char (&value)[N]); void SetAttribute(const QString &name, const char (&value)[N]);
}; };
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -775,48 +775,9 @@ bool TMainWindow::FileSave()
return false; return false;
} }
#ifdef Q_OS_WIN32 if (not CheckFilePermissions(curFile, this))
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
const bool isFileWritable = QFileInfo(curFile).isWritable();
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not isFileWritable)
{ {
QMessageBox messageBox(this); return false;
messageBox.setIcon(QMessageBox::Question);
messageBox.setText(tr("The measurements document has no write permissions."));
messageBox.setInformativeText(tr("Do you want to change the premissions?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
messageBox.setDefaultButton(QMessageBox::Yes);
if (messageBox.exec() == QMessageBox::Yes)
{
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
bool changed = QFile::setPermissions(curFile,
QFileInfo(curFile).permissions() | QFileDevice::WriteUser);
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not changed)
{
messageBox.setIcon(QMessageBox::Warning);
messageBox.setText(tr("Cannot set permissions for %1 to writable.").arg(curFile));
messageBox.setInformativeText(tr("Could not save the file."));
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.exec();
return false;
}
}
else
{
return false;
}
} }
QString error; QString error;

View File

@ -3253,52 +3253,9 @@ bool MainWindow::on_actionSave_triggered()
return false; return false;
} }
#ifdef Q_OS_WIN32 if (not CheckFilePermissions(VAbstractValApplication::VApp()->GetPatternPath(), this))
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
const bool isFileWritable = QFileInfo(VAbstractValApplication::VApp()->GetPatternPath()).isWritable();
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not isFileWritable)
{ {
QMessageBox messageBox(this); return false;
messageBox.setIcon(QMessageBox::Question);
messageBox.setText(tr("The document has no write permissions."));
messageBox.setInformativeText(tr("Do you want to change the premissions?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
messageBox.setDefaultButton(QMessageBox::Yes);
if (messageBox.exec() == QMessageBox::Yes)
{
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
bool changed =
QFile::setPermissions(VAbstractValApplication::VApp()->GetPatternPath(),
QFileInfo(VAbstractValApplication::VApp()
->GetPatternPath()).permissions() | QFileDevice::WriteUser);
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not changed)
{
QMessageBox messageBox(this);
messageBox.setIcon(QMessageBox::Warning);
messageBox.setText(tr("Cannot set permissions for %1 to writable.")
.arg(VAbstractValApplication::VApp()->GetPatternPath()));
messageBox.setInformativeText(tr("Could not save the file."));
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.exec();
return false;
}
}
else
{
return false;
}
} }
QString error; QString error;

View File

@ -73,6 +73,7 @@ namespace
{ {
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsIndividualMeasurements, (QLatin1String("paths/individual_measurements"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsIndividualMeasurements, (QLatin1String("paths/individual_measurements")))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsMultisizeMeasurements, (QLatin1String("paths/standard_measurements"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsMultisizeMeasurements, (QLatin1String("paths/standard_measurements")))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsLayouts, (QLatin1String("paths/layouts")))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsPattern, (QLatin1String("paths/pattern"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsPattern, (QLatin1String("paths/pattern")))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsTemplates, (QLatin1String("paths/templates"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsTemplates, (QLatin1String("paths/templates")))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsLabelTemplate, (QLatin1String("paths/labels"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPathsLabelTemplate, (QLatin1String("paths/labels")))
@ -406,6 +407,27 @@ void VCommonSettings::SetPathMultisizeMeasurements(const QString &value)
settings.sync(); settings.sync();
} }
//---------------------------------------------------------------------------------------------------------------------
QString VCommonSettings::GetDefPathLayouts()
{
return QDir::homePath() + QLatin1String("/valentina/") + tr("layouts");
}
//---------------------------------------------------------------------------------------------------------------------
QString VCommonSettings::GetPathLayouts() const
{
QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename);
return settings.value(*settingPathsLayouts, GetDefPathLayouts()).toString();
}
//---------------------------------------------------------------------------------------------------------------------
void VCommonSettings::SetPathLayouts(const QString &value)
{
QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename);
settings.setValue(*settingPathsLayouts, value);
settings.sync();
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QString VCommonSettings::GetDefPathPattern() QString VCommonSettings::GetDefPathPattern()
{ {

View File

@ -1,4 +1,4 @@
/************************************************************************ /************************************************************************
** **
** @file vcommonsettings.h ** @file vcommonsettings.h
** @author Roman Telezhynskyi <dismine(at)gmail.com> ** @author Roman Telezhynskyi <dismine(at)gmail.com>
@ -68,6 +68,10 @@ public:
QString GetPathMultisizeMeasurements() const; QString GetPathMultisizeMeasurements() const;
void SetPathMultisizeMeasurements(const QString &value); void SetPathMultisizeMeasurements(const QString &value);
static QString GetDefPathLayouts();
QString GetPathLayouts() const;
void SetPathLayouts(const QString &value);
static QString GetDefPathPattern(); static QString GetDefPathPattern();
QString GetPathPattern() const; QString GetPathPattern() const;
void SetPathPattern(const QString &value); void SetPathPattern(const QString &value);

View File

@ -236,6 +236,54 @@ void VAbstractMainWindow::UpdateRecentFileActions()
m_separatorAct->setVisible(numRecentFiles>0); m_separatorAct->setVisible(numRecentFiles>0);
} }
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractMainWindow::CheckFilePermissions(const QString &path, QWidget *messageBoxParent) -> bool
{
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
const bool isFileWritable = QFileInfo(path).isWritable();
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not isFileWritable)
{
QMessageBox messageBox(messageBoxParent);
messageBox.setIcon(QMessageBox::Question);
messageBox.setText(tr("The measurements document has no write permissions."));
messageBox.setInformativeText(tr("Do you want to change the premissions?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
messageBox.setDefaultButton(QMessageBox::Yes);
if (messageBox.exec() == QMessageBox::Yes)
{
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
bool changed = QFile::setPermissions(path, QFileInfo(path).permissions() | QFileDevice::WriteUser);
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not changed)
{
messageBox.setIcon(QMessageBox::Warning);
messageBox.setText(tr("Cannot set permissions for %1 to writable.").arg(path));
messageBox.setInformativeText(tr("Could not save the file."));
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.exec();
return false;
}
}
else
{
return false;
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VAbstractMainWindow::WindowsLocale() void VAbstractMainWindow::WindowsLocale()
{ {

View File

@ -71,6 +71,8 @@ protected:
virtual QStringList RecentFileList() const =0; virtual QStringList RecentFileList() const =0;
void UpdateRecentFileActions(); void UpdateRecentFileActions();
static bool CheckFilePermissions(const QString &path, QWidget *messageBoxParent=nullptr) ;
private: private:
Q_DISABLE_COPY(VAbstractMainWindow) Q_DISABLE_COPY(VAbstractMainWindow)
}; };