diff --git a/ChangeLog.txt b/ChangeLog.txt index 6363689a1..f94994a81 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -54,6 +54,7 @@ - [#88] New feature: Variable width seam allowances. - [#280] New tool: 'Hem' in Detail mode. - [#509] Improve feature: Support internal Paths in Detail tool. +- [#619] Non writable directory prevents opening. # Version 0.4.6 - [#594] Broken export on Mac. diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp index d6e4f6e63..58d8c4543 100644 --- a/src/app/tape/tmainwindow.cpp +++ b/src/app/tape/tmainwindow.cpp @@ -95,6 +95,7 @@ TMainWindow::TMainWindow(QWidget *parent) actionDockDiagram(nullptr), dockDiagramVisible(true), isInitialized(false), + mIsReadOnly(false), recentFileActs(), separatorAct(nullptr), hackedWidgets() @@ -128,9 +129,7 @@ TMainWindow::TMainWindow(QWidget *parent) } SetupMenu(); - - setWindowTitle(tr("untitled %1").arg(qApp->MainWindows().size()+1)); - + UpdateWindowTitle(); ReadSettings(); #if defined(Q_OS_MAC) @@ -269,20 +268,14 @@ bool TMainWindow::LoadFile(const QString &path) if (mType == MeasurementsType::Standard) { VVSTConverter converter(path); - converter.Convert(); - - VDomDocument::ValidateXML(VVSTConverter::CurrentSchema, path); + m->setXMLContent(converter.Convert());// Read again after conversion } else { VVITConverter converter(path); - converter.Convert(); - - VDomDocument::ValidateXML(VVITConverter::CurrentSchema, path); + m->setXMLContent(converter.Convert());// Read again after conversion } - m->setXMLContent(path);// Read again after conversion - if (not m->IsDefinedKnownNamesValid()) { VException e(tr("File contains invalid known measurement(s).")); @@ -298,6 +291,9 @@ bool TMainWindow::LoadFile(const QString &path) ui->labelToolTip->setVisible(false); ui->tabWidget->setVisible(true); + mIsReadOnly = m->IsReadOnly(); + UpdatePadlock(mIsReadOnly); + SetCurrentFile(path); InitWindow(); @@ -309,7 +305,7 @@ bool TMainWindow::LoadFile(const QString &path) ui->tableWidget->selectRow(0); } - GUIReadOnly(m->ReadOnly()); // Keep last + MeasurementGUI(); } catch (VException &e) { @@ -367,12 +363,15 @@ void TMainWindow::FileNew() m = new VMeasurements(mUnit, data); } + mIsReadOnly = m->IsReadOnly(); + UpdatePadlock(mIsReadOnly); + SetCurrentFile(""); MeasurementsWasSaved(false); InitWindow(); - GUIReadOnly(m->ReadOnly()); // Keep last + MeasurementGUI(); } else { @@ -608,45 +607,93 @@ bool TMainWindow::eventFilter(QObject *object, QEvent *event) } //--------------------------------------------------------------------------------------------------------------------- -void TMainWindow::FileSave() +bool TMainWindow::FileSave() { - if (curFile.isEmpty()) + if (curFile.isEmpty() || mIsReadOnly) { return FileSaveAs(); } else { +#ifdef Q_OS_WIN32 + 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); + messageBox.setIcon(QMessageBox::Question); + messageBox.setText(tr("The measurements document has no write permissions.")); + messageBox.setInformativeText("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) + { + QMessageBox messageBox(this); + 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.setDefaultButton(QMessageBox::Ok); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + return false; + } + } + else + { + return false; + } + } + QString error; if (not SaveMeasurements(curFile, error)) { QMessageBox messageBox; messageBox.setIcon(QMessageBox::Warning); - messageBox.setInformativeText(tr("Could not save file")); + messageBox.setText(tr("Could not save the file")); messageBox.setDefaultButton(QMessageBox::Ok); messageBox.setDetailedText(error); messageBox.setStandardButtons(QMessageBox::Ok); messageBox.exec(); + return false; } } + return true; } //--------------------------------------------------------------------------------------------------------------------- -void TMainWindow::FileSaveAs() +bool TMainWindow::FileSaveAs() { QString filters; QString fName = tr("measurements"); QString suffix; if (mType == MeasurementsType::Individual) { - filters = tr("Individual measurements (*.vit)"); - suffix = "vit"; - fName += "." + suffix; + filters = tr("Individual measurements") + QLatin1String(" (*.vit)"); + suffix = QLatin1String("vit"); + fName += QLatin1String(".") + suffix; } else { - filters = tr("Standard measurements (*.vst)"); - suffix = "vst"; - fName += "." + suffix; + filters = tr("Standard measurements") + QLatin1String(" (*.vst)"); + suffix = QLatin1String("vst"); + fName += QLatin1String(".") + suffix; } QString dir; @@ -654,30 +701,30 @@ void TMainWindow::FileSaveAs() { if (mType == MeasurementsType::Individual) { - dir = qApp->TapeSettings()->GetPathIndividualMeasurements() + "/" + fName; + dir = qApp->TapeSettings()->GetPathIndividualMeasurements() + QLatin1String("/") + fName; } else { - dir = qApp->TapeSettings()->GetPathStandardMeasurements() + "/" + fName; + dir = qApp->TapeSettings()->GetPathStandardMeasurements() + QLatin1String("/") + fName; } } else { - dir = QFileInfo(curFile).absolutePath() + "/" + fName; + dir = QFileInfo(curFile).absolutePath() + QLatin1String("/") + fName; } QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"), dir, filters); if (fileName.isEmpty()) { - return; + return false; } QFileInfo f( fileName ); if (f.suffix().isEmpty() && f.suffix() != suffix) { - fileName += "." + suffix; + fileName += QLatin1String(".") + suffix; } if (QFileInfo(fileName).exists()) @@ -688,11 +735,16 @@ void TMainWindow::FileSaveAs() { qCCritical(tMainWindow, "%s", qUtf8Printable(tr("Failed to lock. This file already opened in another window."))); - return; + return false; } } - ReadOnly(false); + // Need for restoring previous state in case of failure + const bool readOnly = m->IsReadOnly(); + + m->SetReadOnly(false); + mIsReadOnly = false; + QString error; bool result = SaveMeasurements(fileName, error); if (result == false) @@ -705,16 +757,23 @@ void TMainWindow::FileSaveAs() messageBox.setStandardButtons(QMessageBox::Ok); messageBox.exec(); - return; + // Restore previous state + m->SetReadOnly(readOnly); + mIsReadOnly = readOnly; + return false; } + UpdatePadlock(false); + UpdateWindowTitle(); + VlpCreateLock(lock, fileName); if (not lock->IsLocked()) { qCCritical(tMainWindow, "%s", qUtf8Printable(tr("Failed to lock. This file already opened in another window. " "Expect collissions when run 2 copies of the program."))); - return; + return false; } + return true; } //--------------------------------------------------------------------------------------------------------------------- @@ -925,15 +984,6 @@ void TMainWindow::SavePMSystem(int index) } } -//--------------------------------------------------------------------------------------------------------------------- -void TMainWindow::ReadOnly(bool ro) -{ - m->SetReadOnly(ro); - MeasurementsWasSaved(false); - - GUIReadOnly(ro); -} - //--------------------------------------------------------------------------------------------------------------------- void TMainWindow::Remove() { @@ -1247,19 +1297,12 @@ void TMainWindow::ImportFromPattern() return; } -#ifdef Q_OS_WIN32 - qt_ntfs_permission_lookup++; // turn checking on -#endif /*Q_OS_WIN32*/ - QStringList measurements; try { VPatternConverter converter(mPath); - converter.Convert(); - - VDomDocument::ValidateXML(VPatternConverter::CurrentSchema, mPath); QScopedPointer doc(new VLitePattern()); - doc->setXMLContent(mPath); + doc->setXMLContent(converter.Convert()); measurements = doc->ListMeasurements(); } catch (VException &e) @@ -1269,10 +1312,6 @@ void TMainWindow::ImportFromPattern() return; } -#ifdef Q_OS_WIN32 - qt_ntfs_permission_lookup--; // turn it off again -#endif /*Q_OS_WIN32*/ - measurements = FilterMeasurements(measurements, m->ListAll()); qint32 currentRow; @@ -1410,7 +1449,7 @@ void TMainWindow::ShowMData() ui->plainTextEditFormula->blockSignals(false); } - MeasurementReadOnly(m->ReadOnly()); + MeasurementGUI(); } else { @@ -1779,7 +1818,23 @@ void TMainWindow::SetupMenu() ui->actionSaveAs->setShortcuts(QKeySequence::SaveAs); connect(ui->actionExportToCSV, &QAction::triggered, this, &TMainWindow::ExportToCSV); - connect(ui->actionReadOnly, &QAction::triggered, this, &TMainWindow::ReadOnly); + connect(ui->actionReadOnly, &QAction::triggered, RECEIVER(this)[this](bool ro) + { + if (not mIsReadOnly) + { + m->SetReadOnly(ro); + MeasurementsWasSaved(false); + UpdatePadlock(ro); + UpdateWindowTitle(); + } + else + { + if (QAction *action = qobject_cast< QAction * >(this->sender())) + { + action->setChecked(true); + } + } + }); connect(ui->actionPreferences, &QAction::triggered, this, &TMainWindow::Preferences); for (int i = 0; i < MaxRecentFiles; ++i) @@ -1975,11 +2030,11 @@ void TMainWindow::InitWindow() connect(ui->toolButtonFindPrevious, &QToolButton::clicked, [this] (){search->FindPrevious();}); connect(ui->toolButtonFindNext, &QToolButton::clicked, [this] (){search->FindNext();}); - connect(search.data(), &VTableSearch::HasResult, [this] (bool state) + connect(search.data(), &VTableSearch::HasResult, RECEIVER(this)[this] (bool state) { ui->toolButtonFindPrevious->setEnabled(state); }); - connect(search.data(), &VTableSearch::HasResult, [this] (bool state) + connect(search.data(), &VTableSearch::HasResult, RECEIVER(this)[this] (bool state) { ui->toolButtonFindNext->setEnabled(state); }); @@ -1990,7 +2045,6 @@ void TMainWindow::InitWindow() ui->actionAddCustom->setEnabled(true); ui->actionAddKnown->setEnabled(true); ui->actionImportFromPattern->setEnabled(true); - ui->actionReadOnly->setEnabled(true); ui->actionSaveAs->setEnabled(true); #if QT_VERSION > QT_VERSION_CHECK(5, 1, 0) @@ -2073,18 +2127,15 @@ void TMainWindow::ShowHeaderUnits(QTableWidget *table, int column, const QString void TMainWindow::MeasurementsWasSaved(bool saved) { setWindowModified(!saved); - ui->actionSave->setEnabled(!saved); + not mIsReadOnly ? ui->actionSave->setEnabled(!saved): ui->actionSave->setEnabled(false); } //--------------------------------------------------------------------------------------------------------------------- void TMainWindow::SetCurrentFile(const QString &fileName) { curFile = fileName; - QString shownName = QFileInfo(curFile).fileName(); if (curFile.isEmpty()) { - shownName = tr("untitled"); - mType == MeasurementsType::Standard ? shownName += QLatin1String(".vst") : shownName += QLatin1String(".vit"); ui->lineEditPathToFile->setText(tr("")); ui->lineEditPathToFile->setToolTip(tr("File was not saved yet.")); ui->lineEditPathToFile->setCursorPosition(0); @@ -2107,33 +2158,8 @@ void TMainWindow::SetCurrentFile(const QString &fileName) settings->SetRecentFileList(files); UpdateRecentFileActions(); } - shownName += "[*]"; - setWindowTitle(shownName); - setWindowFilePath(curFile); -#if defined(Q_OS_MAC) - static QIcon fileIcon = QIcon(QApplication::applicationDirPath() + - QLatin1String("/../Resources/measurements.icns")); - QIcon icon; - if (not curFile.isEmpty()) - { - if (not isWindowModified()) - { - icon = fileIcon; - } - else - { - static QIcon darkIcon; - - if (darkIcon.isNull()) - { - darkIcon = QIcon(darkenPixmap(fileIcon.pixmap(16, 16))); - } - icon = darkIcon; - } - } - setWindowIcon(icon); -#endif //defined(Q_OS_MAC) + UpdateWindowTitle(); } //--------------------------------------------------------------------------------------------------------------------- @@ -2167,7 +2193,7 @@ bool TMainWindow::MaybeSave() messageBox->setDefaultButton(QMessageBox::Yes); messageBox->setEscapeButton(QMessageBox::Cancel); - messageBox->setButtonText(QMessageBox::Yes, curFile.isEmpty() ? tr("Save...") : tr("Save")); + messageBox->setButtonText(QMessageBox::Yes, curFile.isEmpty() || mIsReadOnly ? tr("Save...") : tr("Save")); messageBox->setButtonText(QMessageBox::No, tr("Don't Save")); messageBox->setWindowModality(Qt::ApplicationModal); @@ -2176,8 +2202,14 @@ bool TMainWindow::MaybeSave() switch (ret) { case QMessageBox::Yes: - FileSave(); - return true; + if (mIsReadOnly) + { + return FileSaveAs(); + } + else + { + return FileSave(); + } case QMessageBox::No: return true; case QMessageBox::Cancel: @@ -2364,16 +2396,6 @@ void TMainWindow::RefreshTable() //--------------------------------------------------------------------------------------------------------------------- void TMainWindow::Controls() { - if (m->ReadOnly()) - { - ui->toolButtonRemove->setEnabled(false); - ui->toolButtonTop->setEnabled(false); - ui->toolButtonUp->setEnabled(false); - ui->toolButtonDown->setEnabled(false); - ui->toolButtonBottom->setEnabled(false); - return; - } - if (ui->tableWidget->rowCount() > 0) { ui->toolButtonRemove->setEnabled(true); @@ -2449,6 +2471,63 @@ void TMainWindow::MFields(bool enabled) } } +//--------------------------------------------------------------------------------------------------------------------- +void TMainWindow::UpdateWindowTitle() +{ + QString showName; + bool isFileWritable = true; + if (not curFile.isEmpty()) + { +#ifdef Q_OS_WIN32 + qt_ntfs_permission_lookup++; // turn checking on +#endif /*Q_OS_WIN32*/ + isFileWritable = QFileInfo(curFile).isWritable(); +#ifdef Q_OS_WIN32 + qt_ntfs_permission_lookup--; // turn it off again +#endif /*Q_OS_WIN32*/ + showName = StrippedName(curFile); + } + else + { + showName = tr("untitled %1").arg(qApp->MainWindows().size()+1); + mType == MeasurementsType::Standard ? showName += QLatin1String(".vst") : showName += QLatin1String(".vit"); + } + + showName += QLatin1String("[*]"); + + if (mIsReadOnly || not isFileWritable) + { + showName += QLatin1String(" (") + tr("read only") + QLatin1String(")"); + } + + setWindowTitle(showName); + setWindowFilePath(curFile); + +#if defined(Q_OS_MAC) + static QIcon fileIcon = QIcon(QApplication::applicationDirPath() + + QLatin1String("/../Resources/measurements.icns")); + QIcon icon; + if (not curFile.isEmpty()) + { + if (not isWindowModified()) + { + icon = fileIcon; + } + else + { + static QIcon darkIcon; + + if (darkIcon.isNull()) + { + darkIcon = QIcon(darkenPixmap(fileIcon.pixmap(16, 16))); + } + icon = darkIcon; + } + } + setWindowIcon(icon); +#endif //defined(Q_OS_MAC) +} + //--------------------------------------------------------------------------------------------------------------------- QString TMainWindow::ClearCustomName(const QString &name) const { @@ -2530,7 +2609,7 @@ void TMainWindow::Open(const QString &pathTo, const QString &filter) } //--------------------------------------------------------------------------------------------------------------------- -void TMainWindow::GUIReadOnly(bool ro) +void TMainWindow::UpdatePadlock(bool ro) { ui->actionReadOnly->setChecked(ro); if (ro) @@ -2542,90 +2621,26 @@ void TMainWindow::GUIReadOnly(bool ro) ui->actionReadOnly->setIcon(QIcon("://tapeicon/24x24/padlock_opened.png")); } - ui->actionAddCustom->setDisabled(ro); - ui->actionAddKnown->setDisabled(ro); - - ui->plainTextEditNotes->setReadOnly(ro); - - if (mType == MeasurementsType::Individual) - { - ui->lineEditGivenName->setReadOnly(ro); - ui->lineEditFamilyName->setReadOnly(ro); - ui->dateEditBirthDate->setReadOnly(ro); - ui->comboBoxGender->setDisabled(ro); - ui->lineEditEmail->setReadOnly(ro); - } - - ui->comboBoxPMSystem->setDisabled(ro); - - MeasurementReadOnly(ro); + ui->actionReadOnly->setDisabled(mIsReadOnly); } //--------------------------------------------------------------------------------------------------------------------- -void TMainWindow::MeasurementReadOnly(bool ro) +void TMainWindow::MeasurementGUI() { - if (ro == false) + if (const QTableWidgetItem *nameField = ui->tableWidget->item(ui->tableWidget->currentRow(), ColumnName)) { - if (const QTableWidgetItem *nameField = ui->tableWidget->item(ui->tableWidget->currentRow(), ColumnName)) - { - if (nameField->text().indexOf(CustomMSign) == 0) // Check if custom - { - ui->lineEditName->setReadOnly(ro); - ui->plainTextEditDescription->setReadOnly(ro); - ui->lineEditFullName->setReadOnly(ro); - - // Need to block signals for QLineEdit in readonly mode because it still emits - // QLineEdit::editingFinished signal. - ui->lineEditName->blockSignals(ro); - ui->lineEditFullName->blockSignals(ro); - } - else - { // known measurement - ui->lineEditName->setReadOnly(not ro); - ui->plainTextEditDescription->setReadOnly(not ro); - ui->lineEditFullName->setReadOnly(not ro); - - // Need to block signals for QLineEdit in readonly mode because it still emits - // QLineEdit::editingFinished signal. - ui->lineEditName->blockSignals(not ro); - ui->lineEditFullName->blockSignals(not ro); - } - } - else - { - return; - } - } - else - { - ui->lineEditName->setReadOnly(ro); - ui->plainTextEditDescription->setReadOnly(ro); - ui->lineEditFullName->setReadOnly(ro); + const bool isCustom = not (nameField->text().indexOf(CustomMSign) == 0); + ui->lineEditName->setReadOnly(isCustom); + ui->plainTextEditDescription->setReadOnly(isCustom); + ui->lineEditFullName->setReadOnly(isCustom); // Need to block signals for QLineEdit in readonly mode because it still emits // QLineEdit::editingFinished signal. - ui->lineEditName->blockSignals(ro); - ui->lineEditFullName->blockSignals(ro); - } + ui->lineEditName->blockSignals(isCustom); + ui->lineEditFullName->blockSignals(isCustom); - if (mType == MeasurementsType::Individual) - { - ui->plainTextEditFormula->setReadOnly(ro); - - // Need to block signals for QLineEdit in readonly mode because it still emits QLineEdit::editingFinished - // signal. - ui->lineEditGivenName->blockSignals(ro); - ui->lineEditFamilyName->blockSignals(ro); - ui->lineEditEmail->blockSignals(ro); + Controls(); // Buttons remove, up, down } - else - { - ui->doubleSpinBoxBaseValue->setReadOnly(ro); - ui->doubleSpinBoxInSizes->setReadOnly(ro); - ui->doubleSpinBoxInHeights->setReadOnly(ro); - } - - Controls(); // Buttons remove, up, down } //--------------------------------------------------------------------------------------------------------------------- @@ -2733,13 +2748,9 @@ bool TMainWindow::LoadFromExistingFile(const QString &path) else { VVITConverter converter(path); - converter.Convert(); - - VDomDocument::ValidateXML(VVITConverter::CurrentSchema, path); + m->setXMLContent(converter.Convert());// Read again after conversion } - m->setXMLContent(path);// Read again after conversion - if (not m->IsDefinedKnownNamesValid()) { VException e(tr("File contains invalid known measurement(s).")); @@ -2767,7 +2778,9 @@ bool TMainWindow::LoadFromExistingFile(const QString &path) lock.reset();// Now we can unlock the file - GUIReadOnly(m->ReadOnly()); // Keep last + mIsReadOnly = m->IsReadOnly(); + UpdatePadlock(mIsReadOnly); + MeasurementGUI(); } catch (VException &e) { diff --git a/src/app/tape/tmainwindow.h b/src/app/tape/tmainwindow.h index 0642f7758..f83ac270e 100644 --- a/src/app/tape/tmainwindow.h +++ b/src/app/tape/tmainwindow.h @@ -78,8 +78,8 @@ private slots: void CreateFromExisting(); void Preferences(); - void FileSave(); - void FileSaveAs(); + bool FileSave(); + bool FileSaveAs(); void ExportToCSV(); void AboutToShowWindowMenu(); void ShowWindow() const; @@ -96,7 +96,6 @@ private slots: void SaveBirthDate(const QDate & date); void SaveNotes(); void SavePMSystem(int index); - void ReadOnly(bool ro); void Remove(); void MoveTop(); @@ -147,6 +146,7 @@ private: QAction *actionDockDiagram; bool dockDiagramVisible; bool isInitialized; + bool mIsReadOnly; enum { MaxRecentFiles = 5 }; QAction *recentFileActs[MaxRecentFiles]; QAction *separatorAct; @@ -185,10 +185,11 @@ private: void ShowMDiagram(const QString &name); void Open(const QString &pathTo, const QString &filter); - void GUIReadOnly(bool ro); - void MeasurementReadOnly(bool ro); + void UpdatePadlock(bool ro); + void MeasurementGUI(); void Controls(); void MFields(bool enabled); + void UpdateWindowTitle(); void ReadSettings(); void WriteSettings(); diff --git a/src/app/tape/tmainwindow.ui b/src/app/tape/tmainwindow.ui index f2f768404..48e6ce9e5 100644 --- a/src/app/tape/tmainwindow.ui +++ b/src/app/tape/tmainwindow.ui @@ -924,7 +924,6 @@ - diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index 25f2e1090..70cb64052 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -380,20 +380,14 @@ QSharedPointer MainWindow::OpenMeasurementFile(const QString &pat if (m->Type() == MeasurementsType::Standard) { VVSTConverter converter(path); - converter.Convert(); - - VDomDocument::ValidateXML(VVSTConverter::CurrentSchema, path); + m->setXMLContent(converter.Convert());// Read again after conversion } else { VVITConverter converter(path); - converter.Convert(); - - VDomDocument::ValidateXML(VVITConverter::CurrentSchema, path); + m->setXMLContent(converter.Convert());// Read again after conversion } - m->setXMLContent(path);// Read again after conversion - if (not m->IsDefinedKnownNamesValid()) { VException e(tr("Measurement file contains invalid known measurement(s).")); @@ -2406,7 +2400,7 @@ bool MainWindow::SaveAs() const bool result = SavePattern(fileName, error); if (result == false) { - QMessageBox messageBox; + QMessageBox messageBox(this); messageBox.setIcon(QMessageBox::Warning); messageBox.setInformativeText(tr("Could not save file")); messageBox.setDefaultButton(QMessageBox::Ok); @@ -2449,25 +2443,69 @@ bool MainWindow::SaveAs() */ bool MainWindow::Save() { - if (curFile.isEmpty()) + if (curFile.isEmpty() || patternReadOnly) { return SaveAs(); } else { +#ifdef Q_OS_WIN32 + 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); + messageBox.setIcon(QMessageBox::Question); + messageBox.setText(tr("The document has no write permissions.")); + messageBox.setInformativeText("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) + { + QMessageBox messageBox(this); + 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.setDefaultButton(QMessageBox::Ok); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + return false; + } + } + else + { + return false; + } + } + QString error; bool result = SavePattern(curFile, error); if (result) { - QString autofile = curFile + autosavePrefix; - QFile file(autofile); - file.remove(); + QFile::remove(curFile + autosavePrefix); } else { - QMessageBox messageBox; + QMessageBox messageBox(this); messageBox.setIcon(QMessageBox::Warning); - messageBox.setInformativeText(tr("Could not save file")); + messageBox.setText(tr("Could not save the file")); messageBox.setDefaultButton(QMessageBox::Ok); messageBox.setDetailedText(error); messageBox.setStandardButtons(QMessageBox::Ok); @@ -2559,10 +2597,6 @@ void MainWindow::Clear() #endif CleanLayout(); listDetails.clear(); // don't move to CleanLayout() - -#ifdef Q_OS_WIN32 - qt_ntfs_permission_lookup--; // turn it off again -#endif /*Q_OS_WIN32*/ qApp->getUndoStack()->clear(); toolOptions->ClearPropertyBrowser(); toolOptions->itemClicked(nullptr); @@ -2698,8 +2732,6 @@ void MainWindow::FullParseFile() GlobalChangePP(patternPiece); SetEnableTool(comboBoxDraws->count() > 0); - patternReadOnly = doc->IsReadOnly(); - SetEnableWidgets(true); detailsWidget->UpdateList(); VMainGraphicsView::NewSceneRect(sceneDraw, qApp->getSceneView()); @@ -3272,7 +3304,7 @@ bool MainWindow::MaybeSave() messageBox->setEscapeButton(QMessageBox::Cancel); messageBox->setButtonText(QMessageBox::Yes, - curFile.isEmpty() || doc->IsReadOnly() ? tr("Save...") : tr("Save")); + curFile.isEmpty() || patternReadOnly ? tr("Save...") : tr("Save")); messageBox->setButtonText(QMessageBox::No, tr("Don't Save")); messageBox->setWindowModality(Qt::ApplicationModal); @@ -3281,7 +3313,7 @@ bool MainWindow::MaybeSave() switch (ret) { case QMessageBox::Yes: - if (doc->IsReadOnly()) + if (patternReadOnly) { return SaveAs(); } @@ -3910,18 +3942,11 @@ bool MainWindow::LoadPattern(const QString &fileName, const QString& customMeasu VMainGraphicsView::NewSceneRect(sceneDraw, ui->view); VMainGraphicsView::NewSceneRect(sceneDetails, ui->view); -#ifdef Q_OS_WIN32 - qt_ntfs_permission_lookup++; // turn checking on -#endif /*Q_OS_WIN32*/ - qApp->setOpeningPattern();//Begin opening file try { VPatternConverter converter(fileName); - converter.Convert(); - - VDomDocument::ValidateXML(VPatternConverter::CurrentSchema, fileName); - doc->setXMLContent(fileName); + doc->setXMLContent(converter.Convert()); if (!customMeasureFile.isEmpty()) { doc->SetPath(RelativeMPath(fileName, customMeasureFile)); @@ -3984,14 +4009,12 @@ bool MainWindow::LoadPattern(const QString &fileName, const QString& customMeasu return false; } -#ifdef Q_OS_WIN32 - qt_ntfs_permission_lookup--; // turn it off again -#endif /*Q_OS_WIN32*/ - FullParseFile(); if (guiEnabled) { // No errors occurred + patternReadOnly = doc->IsReadOnly(); + SetEnableWidgets(true); setCurrentFile(fileName); helpLabel->setText(tr("File loaded")); qCDebug(vMainWindow, "File loaded."); @@ -4297,20 +4320,14 @@ QString MainWindow::CheckPathToMeasurements(const QString &patternPath, const QS if (patternType == MeasurementsType::Standard) { VVSTConverter converter(mPath); - converter.Convert(); - - VDomDocument::ValidateXML(VVSTConverter::CurrentSchema, mPath); + m->setXMLContent(converter.Convert());// Read again after conversion } else { VVITConverter converter(mPath); - converter.Convert(); - - VDomDocument::ValidateXML(VVITConverter::CurrentSchema, mPath); + m->setXMLContent(converter.Convert());// Read again after conversion } - m->setXMLContent(mPath);// Read again after conversion - if (not m->IsDefinedKnownNamesValid()) { VException e(tr("Measurement file contains invalid known measurement(s).")); @@ -4630,13 +4647,26 @@ QString MainWindow::GetMeasurementFileName() //--------------------------------------------------------------------------------------------------------------------- void MainWindow::UpdateWindowTitle() { - if (not patternReadOnly) + bool isFileWritable = true; + if (not curFile.isEmpty()) + { +#ifdef Q_OS_WIN32 + qt_ntfs_permission_lookup++; // turn checking on +#endif /*Q_OS_WIN32*/ + isFileWritable = QFileInfo(curFile).isWritable(); +#ifdef Q_OS_WIN32 + qt_ntfs_permission_lookup--; // turn it off again +#endif /*Q_OS_WIN32*/ + } + + if (not patternReadOnly && isFileWritable) { setWindowTitle(GetPatternFileName()+GetMeasurementFileName()); } else { - setWindowTitle(GetPatternFileName()+GetMeasurementFileName() + " " + tr("(read only)")); + setWindowTitle(GetPatternFileName()+GetMeasurementFileName() + QLatin1String(" (") + tr("read only") + + QLatin1String(")")); } setWindowFilePath(curFile); diff --git a/src/libs/ifc/xml/vabstractconverter.cpp b/src/libs/ifc/xml/vabstractconverter.cpp index aa1a2be00..ab21c1743 100644 --- a/src/libs/ifc/xml/vabstractconverter.cpp +++ b/src/libs/ifc/xml/vabstractconverter.cpp @@ -49,17 +49,13 @@ //--------------------------------------------------------------------------------------------------------------------- VAbstractConverter::VAbstractConverter(const QString &fileName) - :VDomDocument(), ver(0x0), fileName(fileName) + : VDomDocument(), + m_ver(0x0), + m_convertedFileName(fileName), + m_tmpFile() { - QFileInfo info(fileName); - if (info.isSymLink() && not info.isWritable()) - { - ReplaceSymLink(); - } - - this->setXMLContent(fileName); - const QString version = GetVersionStr(); - ver = GetVersion(version); + setXMLContent(m_convertedFileName);// Throw an exception on error + m_ver = GetVersion(GetVersionStr()); } //--------------------------------------------------------------------------------------------------------------------- @@ -67,34 +63,29 @@ VAbstractConverter::~VAbstractConverter() {} //--------------------------------------------------------------------------------------------------------------------- -void VAbstractConverter::Convert() +QString VAbstractConverter::Convert() { - if (ver == MaxVer()) + if (m_ver == MaxVer()) { - return; - } - - QString error; - const QString backupFileName = fileName + QLatin1String(".backup"); - if (SafeCopy(fileName, backupFileName, error) == false) - { - const QString errorMsg(tr("Error creating a backup file: %1.").arg(error)); - throw VException(errorMsg); + return m_convertedFileName; } ReserveFile(); - if (ver <= MaxVer()) + if (m_tmpFile.open()) { - ApplyPatches(); + m_convertedFileName = m_tmpFile.fileName(); } else { - DowngradeToCurrentMaxVersion(); + const QString errorMsg(tr("Error openning a temp file file: %1.").arg(m_tmpFile.errorString())); + throw VException(errorMsg); } + m_tmpFile.close(); - QFile file(backupFileName); - file.remove(); + m_ver < MaxVer() ? ApplyPatches() : DowngradeToCurrentMaxVersion(); + + return m_convertedFileName; } //--------------------------------------------------------------------------------------------------------------------- @@ -180,31 +171,25 @@ void VAbstractConverter::ReserveFile() const //It's not possible in all cases make conversion without lose data. //For such cases we will store old version in a reserve file. QString error; - QFileInfo info(fileName); - const QString reserveFileName = QString("%1/%2(v%3).%4") + QFileInfo info(m_convertedFileName); + const QString reserveFileName = QString("%1/%2(v%3).%4.bak") .arg(info.absoluteDir().absolutePath()) .arg(info.baseName()) .arg(GetVersionStr()) .arg(info.completeSuffix()); - if (not SafeCopy(fileName, reserveFileName, error)) + if (not SafeCopy(m_convertedFileName, reserveFileName, error)) { - const QString errorMsg(tr("Error creating a reserv copy: %1.").arg(error)); - throw VException(errorMsg); - } -} +#ifdef Q_OS_WIN32 + qt_ntfs_permission_lookup++; // turn checking on +#endif /*Q_OS_WIN32*/ + const bool isFileWritable = info.isWritable(); +#ifdef Q_OS_WIN32 + qt_ntfs_permission_lookup--; // turn it off again +#endif /*Q_OS_WIN32*/ -//--------------------------------------------------------------------------------------------------------------------- -void VAbstractConverter::ReplaceSymLink() const -{ - // See issue #582. Issue with standard path to shared data on Linux - // https://bitbucket.org/dismine/valentina/issues/582/issue-with-standard-path-to-shared-data-on - QFileInfo info(fileName); - if (info.isSymLink() && not info.isWritable()) - { - QString error; - if (not SafeCopy(info.symLinkTarget(), fileName, error)) + if (not IsReadOnly() && isFileWritable) { - const QString errorMsg(tr("Error replacing a symlink by real file: %1.").arg(error)); + const QString errorMsg(tr("Error creating a reserv copy: %1.").arg(error)); throw VException(errorMsg); } } @@ -291,19 +276,19 @@ void VAbstractConverter::ValidateInputFile(const QString ¤tSchema) const QString schema; try { - schema = XSDSchema(ver); + schema = XSDSchema(m_ver); } catch(const VException &e) { - if (ver < MinVer()) + if (m_ver < MinVer()) { // Version less than minimally supported version. Can't do anything. throw; } - else if (ver > MaxVer()) + else if (m_ver > MaxVer()) { // Version bigger than maximum supported version. We still have a chance to open the file. try { // Try to open like the current version. - ValidateXML(currentSchema, fileName); + ValidateXML(currentSchema, m_convertedFileName); } catch(const VException &exp) { // Nope, we can't. @@ -319,14 +304,14 @@ void VAbstractConverter::ValidateInputFile(const QString ¤tSchema) const return; // All is fine and we can try to convert to current max version. } - ValidateXML(schema, fileName); + ValidateXML(schema, m_convertedFileName); } //--------------------------------------------------------------------------------------------------------------------- void VAbstractConverter::Save() const { QString error; - if (SaveDocument(fileName, error) == false) + if (SaveDocument(m_convertedFileName, error) == false) { VException e(error); throw e; diff --git a/src/libs/ifc/xml/vabstractconverter.h b/src/libs/ifc/xml/vabstractconverter.h index 9e5b82821..1943c3638 100644 --- a/src/libs/ifc/xml/vabstractconverter.h +++ b/src/libs/ifc/xml/vabstractconverter.h @@ -37,6 +37,7 @@ #include #include +#include #include #include "vdomdocument.h" @@ -52,14 +53,15 @@ public: explicit VAbstractConverter(const QString &fileName); virtual ~VAbstractConverter() Q_DECL_OVERRIDE; - void Convert(); + QString Convert(); virtual bool SaveDocument(const QString &fileName, QString &error) const Q_DECL_OVERRIDE; static int GetVersion(const QString &version); protected: - int ver; - QString fileName; + int m_ver; + QString m_convertedFileName; + void ValidateInputFile(const QString ¤tSchema) const; Q_NORETURN void InvalidVersion(int ver) const; @@ -76,6 +78,8 @@ protected: virtual void ApplyPatches() =0; virtual void DowngradeToCurrentMaxVersion() =0; + virtual bool IsReadOnly() const =0; + void Replace(QString &formula, const QString &newName, int position, const QString &token, int &bias) const; void CorrectionsPositions(int position, int bias, QMap &tokens) const; static void BiasTokens(int position, int bias, QMap &tokens); @@ -83,12 +87,13 @@ protected: private: Q_DISABLE_COPY(VAbstractConverter) + QTemporaryFile m_tmpFile; + QString GetVersionStr() const; static void ValidateVersion(const QString &version); void ReserveFile() const; - void ReplaceSymLink() const; }; #endif // VABSTRACTCONVERTER_H diff --git a/src/libs/ifc/xml/vdomdocument.cpp b/src/libs/ifc/xml/vdomdocument.cpp index e5a590f11..ebea2dc6e 100644 --- a/src/libs/ifc/xml/vdomdocument.cpp +++ b/src/libs/ifc/xml/vdomdocument.cpp @@ -124,7 +124,8 @@ const QString VDomDocument::TagVersion = QStringLiteral("version"); //--------------------------------------------------------------------------------------------------------------------- VDomDocument::VDomDocument() - : QDomDocument(), map(QHash()) + : QDomDocument(), + map() {} //--------------------------------------------------------------------------------------------------------------------- @@ -804,12 +805,11 @@ bool VDomDocument::SafeCopy(const QString &source, const QString &destination, Q #endif /*Q_OS_WIN32*/ QTemporaryFile destFile(destination + QLatin1String(".XXXXXX")); - destFile.setAutoRemove(false); + destFile.setAutoRemove(false);// Will be renamed to be destination file // cppcheck-suppress ConfigurationNotChecked if (not destFile.open()) { error = destFile.errorString(); - result = false; } else { @@ -850,6 +850,10 @@ bool VDomDocument::SafeCopy(const QString &source, const QString &destination, Q } } } + else + { + error = sourceFile.errorString(); + } } #ifdef Q_OS_WIN32 diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp index f3a4af8c7..7bcc178ed 100644 --- a/src/libs/ifc/xml/vpatternconverter.cpp +++ b/src/libs/ifc/xml/vpatternconverter.cpp @@ -133,10 +133,11 @@ static const QString strSeamAllowance = QStringLiteral("seamAllowanc static const QString strNodeType = QStringLiteral("nodeType"); static const QString strDet = QStringLiteral("det"); static const QString strTypeObject = QStringLiteral("typeObject"); +static const QString strReadOnly = QStringLiteral("readOnly"); //--------------------------------------------------------------------------------------------------------------------- VPatternConverter::VPatternConverter(const QString &fileName) - :VAbstractConverter(fileName) + : VAbstractConverter(fileName) { ValidateInputFile(CurrentSchema); } @@ -207,124 +208,105 @@ QString VPatternConverter::XSDSchema(int ver) const //--------------------------------------------------------------------------------------------------------------------- void VPatternConverter::ApplyPatches() { - try + switch (m_ver) { - switch (ver) - { - case (0x000100): - ToV0_1_1(); - ValidateXML(XSDSchema(0x000101), fileName); - V_FALLTHROUGH - case (0x000101): - ToV0_1_2(); - ValidateXML(XSDSchema(0x000102), fileName); - V_FALLTHROUGH - case (0x000102): - ToV0_1_3(); - ValidateXML(XSDSchema(0x000103), fileName); - V_FALLTHROUGH - case (0x000103): - ToV0_1_4(); - ValidateXML(XSDSchema(0x000104), fileName); - V_FALLTHROUGH - case (0x000104): - ToV0_2_0(); - ValidateXML(XSDSchema(0x000200), fileName); - V_FALLTHROUGH - case (0x000200): - ToV0_2_1(); - ValidateXML(XSDSchema(0x000201), fileName); - V_FALLTHROUGH - case (0x000201): - ToV0_2_2(); - ValidateXML(XSDSchema(0x000202), fileName); - V_FALLTHROUGH - case (0x000202): - ToV0_2_3(); - ValidateXML(XSDSchema(0x000203), fileName); - V_FALLTHROUGH - case (0x000203): - ToV0_2_4(); - ValidateXML(XSDSchema(0x000204), fileName); - V_FALLTHROUGH - case (0x000204): - ToV0_2_5(); - ValidateXML(XSDSchema(0x000205), fileName); - V_FALLTHROUGH - case (0x000205): - ToV0_2_6(); - ValidateXML(XSDSchema(0x000206), fileName); - V_FALLTHROUGH - case (0x000206): - ToV0_2_7(); - ValidateXML(XSDSchema(0x000207), fileName); - V_FALLTHROUGH - case (0x000207): - ToV0_3_0(); - ValidateXML(XSDSchema(0x000300), fileName); - V_FALLTHROUGH - case (0x000300): - ToV0_3_1(); - ValidateXML(XSDSchema(0x000301), fileName); - V_FALLTHROUGH - case (0x000301): - ToV0_3_2(); - ValidateXML(XSDSchema(0x000302), fileName); - V_FALLTHROUGH - case (0x000302): - ToV0_3_3(); - ValidateXML(XSDSchema(0x000303), fileName); - V_FALLTHROUGH - case (0x000303): - ToV0_3_4(); - ValidateXML(XSDSchema(0x000304), fileName); - V_FALLTHROUGH - case (0x000304): - ToV0_3_5(); - ValidateXML(XSDSchema(0x000305), fileName); - V_FALLTHROUGH - case (0x000305): - ToV0_3_6(); - ValidateXML(XSDSchema(0x000306), fileName); - V_FALLTHROUGH - case (0x000306): - ToV0_3_7(); - ValidateXML(XSDSchema(0x000307), fileName); - V_FALLTHROUGH - case (0x000307): - ToV0_3_8(); - ValidateXML(XSDSchema(0x000308), fileName); - V_FALLTHROUGH - case (0x000308): - ToV0_3_9(); - ValidateXML(XSDSchema(0x000309), fileName); - V_FALLTHROUGH - case (0x000309): - ToV0_4_0(); - ValidateXML(XSDSchema(0x000400), fileName); - V_FALLTHROUGH - case (0x000400): - break; - default: - break; - } - } - catch (VException &e) - { - QString error; - const QString backupFileName = fileName + QLatin1String(".backup"); - if (SafeCopy(backupFileName, fileName, error) == false) - { - const QString errorMsg(tr("Error restoring backup file: %1.").arg(error)); - VException excep(errorMsg); - excep.AddMoreInformation(e.ErrorMessage()); - throw excep; - } - - QFile file(backupFileName); - file.remove(); - - throw; + case (0x000100): + ToV0_1_1(); + ValidateXML(XSDSchema(0x000101), m_convertedFileName); + V_FALLTHROUGH + case (0x000101): + ToV0_1_2(); + ValidateXML(XSDSchema(0x000102), m_convertedFileName); + V_FALLTHROUGH + case (0x000102): + ToV0_1_3(); + ValidateXML(XSDSchema(0x000103), m_convertedFileName); + V_FALLTHROUGH + case (0x000103): + ToV0_1_4(); + ValidateXML(XSDSchema(0x000104), m_convertedFileName); + V_FALLTHROUGH + case (0x000104): + ToV0_2_0(); + ValidateXML(XSDSchema(0x000200), m_convertedFileName); + V_FALLTHROUGH + case (0x000200): + ToV0_2_1(); + ValidateXML(XSDSchema(0x000201), m_convertedFileName); + V_FALLTHROUGH + case (0x000201): + ToV0_2_2(); + ValidateXML(XSDSchema(0x000202), m_convertedFileName); + V_FALLTHROUGH + case (0x000202): + ToV0_2_3(); + ValidateXML(XSDSchema(0x000203), m_convertedFileName); + V_FALLTHROUGH + case (0x000203): + ToV0_2_4(); + ValidateXML(XSDSchema(0x000204), m_convertedFileName); + V_FALLTHROUGH + case (0x000204): + ToV0_2_5(); + ValidateXML(XSDSchema(0x000205), m_convertedFileName); + V_FALLTHROUGH + case (0x000205): + ToV0_2_6(); + ValidateXML(XSDSchema(0x000206), m_convertedFileName); + V_FALLTHROUGH + case (0x000206): + ToV0_2_7(); + ValidateXML(XSDSchema(0x000207), m_convertedFileName); + V_FALLTHROUGH + case (0x000207): + ToV0_3_0(); + ValidateXML(XSDSchema(0x000300), m_convertedFileName); + V_FALLTHROUGH + case (0x000300): + ToV0_3_1(); + ValidateXML(XSDSchema(0x000301), m_convertedFileName); + V_FALLTHROUGH + case (0x000301): + ToV0_3_2(); + ValidateXML(XSDSchema(0x000302), m_convertedFileName); + V_FALLTHROUGH + case (0x000302): + ToV0_3_3(); + ValidateXML(XSDSchema(0x000303), m_convertedFileName); + V_FALLTHROUGH + case (0x000303): + ToV0_3_4(); + ValidateXML(XSDSchema(0x000304), m_convertedFileName); + V_FALLTHROUGH + case (0x000304): + ToV0_3_5(); + ValidateXML(XSDSchema(0x000305), m_convertedFileName); + V_FALLTHROUGH + case (0x000305): + ToV0_3_6(); + ValidateXML(XSDSchema(0x000306), m_convertedFileName); + V_FALLTHROUGH + case (0x000306): + ToV0_3_7(); + ValidateXML(XSDSchema(0x000307), m_convertedFileName); + V_FALLTHROUGH + case (0x000307): + ToV0_3_8(); + ValidateXML(XSDSchema(0x000308), m_convertedFileName); + V_FALLTHROUGH + case (0x000308): + ToV0_3_9(); + ValidateXML(XSDSchema(0x000309), m_convertedFileName); + V_FALLTHROUGH + case (0x000309): + ToV0_4_0(); + ValidateXML(XSDSchema(0x000400), m_convertedFileName); + V_FALLTHROUGH + case (0x000400): + break; + default: + InvalidVersion(m_ver); + break; } } @@ -335,6 +317,27 @@ void VPatternConverter::DowngradeToCurrentMaxVersion() Save(); } +//--------------------------------------------------------------------------------------------------------------------- +bool VPatternConverter::IsReadOnly() const +{ + // Check if attribute readOnly was not changed in file format + Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == CONVERTER_VERSION_CHECK(0, 4, 0), + "Check attribute readOnly."); + + // Possibly in future attribute readOnly will change position etc. + // For now position is the same for all supported format versions. + // But don't forget to keep all versions of attribute until we support that format versions + + const QDomElement pattern = documentElement(); + + if (pattern.isNull()) + { + return false; + } + + return GetParametrBool(pattern, strReadOnly, falseStr); +} + //--------------------------------------------------------------------------------------------------------------------- void VPatternConverter::ToV0_1_1() { @@ -1095,7 +1098,7 @@ void VPatternConverter::TagMeasurementsToV0_2_0() ms.removeAttribute(strType); ms.removeAttribute(strPath); - QDomText newNodeText = createTextNode(QFileInfo(fileName).absoluteDir().relativeFilePath(path)); + QDomText newNodeText = createTextNode(QFileInfo(m_convertedFileName).absoluteDir().relativeFilePath(path)); ms.appendChild(newNodeText); } diff --git a/src/libs/ifc/xml/vpatternconverter.h b/src/libs/ifc/xml/vpatternconverter.h index 3341fecaf..ccf873331 100644 --- a/src/libs/ifc/xml/vpatternconverter.h +++ b/src/libs/ifc/xml/vpatternconverter.h @@ -72,6 +72,8 @@ protected: virtual void ApplyPatches() Q_DECL_OVERRIDE; virtual void DowngradeToCurrentMaxVersion() Q_DECL_OVERRIDE; + virtual bool IsReadOnly() const Q_DECL_OVERRIDE; + private: Q_DISABLE_COPY(VPatternConverter) static const QString PatternMinVerStr; diff --git a/src/libs/ifc/xml/vvitconverter.cpp b/src/libs/ifc/xml/vvitconverter.cpp index 49c7a397d..abf2f66ab 100644 --- a/src/libs/ifc/xml/vvitconverter.cpp +++ b/src/libs/ifc/xml/vvitconverter.cpp @@ -60,6 +60,8 @@ const QString VVITConverter::CurrentSchema = QStringLiteral("://schema/in //VVITConverter::MeasurementMinVer; // <== DON'T FORGET TO UPDATE TOO!!!! //VVITConverter::MeasurementMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!! +static const QString strTagRead_Only = QStringLiteral("read-only"); + //--------------------------------------------------------------------------------------------------------------------- VVITConverter::VVITConverter(const QString &fileName) :VAbstractMConverter(fileName) @@ -95,48 +97,29 @@ QString VVITConverter::XSDSchema(int ver) const //--------------------------------------------------------------------------------------------------------------------- void VVITConverter::ApplyPatches() { - try + switch (m_ver) { - switch (ver) - { - case (0x000200): - ToV0_3_0(); - ValidateXML(XSDSchema(0x000300), fileName); - V_FALLTHROUGH - case (0x000300): - ToV0_3_1(); - ValidateXML(XSDSchema(0x000301), fileName); - V_FALLTHROUGH - case (0x000301): - ToV0_3_2(); - ValidateXML(XSDSchema(0x000302), fileName); - V_FALLTHROUGH - case (0x000302): - ToV0_3_3(); - ValidateXML(XSDSchema(0x000303), fileName); - V_FALLTHROUGH - case (0x000303): - break; - default: - break; - } - } - catch (VException &e) - { - QString error; - const QString backupFileName = fileName + QLatin1String(".backup"); - if (SafeCopy(backupFileName, fileName, error) == false) - { - const QString errorMsg(tr("Error restoring backup file: %1.").arg(error)); - VException excep(errorMsg); - excep.AddMoreInformation(e.ErrorMessage()); - throw excep; - } - - QFile file(backupFileName); - file.remove(); - - throw; + case (0x000200): + ToV0_3_0(); + ValidateXML(XSDSchema(0x000300), m_convertedFileName); + V_FALLTHROUGH + case (0x000300): + ToV0_3_1(); + ValidateXML(XSDSchema(0x000301), m_convertedFileName); + V_FALLTHROUGH + case (0x000301): + ToV0_3_2(); + ValidateXML(XSDSchema(0x000302), m_convertedFileName); + V_FALLTHROUGH + case (0x000302): + ToV0_3_3(); + ValidateXML(XSDSchema(0x000303), m_convertedFileName); + V_FALLTHROUGH + case (0x000303): + break; + default: + InvalidVersion(m_ver); + break; } } @@ -147,6 +130,20 @@ void VVITConverter::DowngradeToCurrentMaxVersion() Save(); } +//--------------------------------------------------------------------------------------------------------------------- +bool VVITConverter::IsReadOnly() const +{ + // Check if attribute read-only was not changed in file format + Q_STATIC_ASSERT_X(VVITConverter::MeasurementMaxVer == CONVERTER_VERSION_CHECK(0, 3, 3), + "Check attribute read-only."); + + // Possibly in future attribute read-only will change position etc. + // For now position is the same for all supported format versions. + // But don't forget to keep all versions of attribute until we support that format versions + + return UniqueTagText(strTagRead_Only, falseStr) == trueStr; +} + //--------------------------------------------------------------------------------------------------------------------- void VVITConverter::AddNewTagsForV0_3_0() { diff --git a/src/libs/ifc/xml/vvitconverter.h b/src/libs/ifc/xml/vvitconverter.h index 45b220183..8516f2eeb 100644 --- a/src/libs/ifc/xml/vvitconverter.h +++ b/src/libs/ifc/xml/vvitconverter.h @@ -67,6 +67,7 @@ protected: virtual QString XSDSchema(int ver) const Q_DECL_OVERRIDE; virtual void ApplyPatches() Q_DECL_OVERRIDE; virtual void DowngradeToCurrentMaxVersion() Q_DECL_OVERRIDE; + virtual bool IsReadOnly() const Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(VVITConverter) diff --git a/src/libs/ifc/xml/vvstconverter.cpp b/src/libs/ifc/xml/vvstconverter.cpp index 5f7518dbf..7d66e5492 100644 --- a/src/libs/ifc/xml/vvstconverter.cpp +++ b/src/libs/ifc/xml/vvstconverter.cpp @@ -60,6 +60,8 @@ const QString VVSTConverter::CurrentSchema = QStringLiteral("://schema/st //VVSTConverter::MeasurementMinVer; // <== DON'T FORGET TO UPDATE TOO!!!! //VVSTConverter::MeasurementMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!! +static const QString strTagRead_Only = QStringLiteral("read-only"); + //--------------------------------------------------------------------------------------------------------------------- VVSTConverter::VVSTConverter(const QString &fileName) :VAbstractMConverter(fileName) @@ -95,48 +97,29 @@ QString VVSTConverter::XSDSchema(int ver) const //--------------------------------------------------------------------------------------------------------------------- void VVSTConverter::ApplyPatches() { - try + switch (m_ver) { - switch (ver) - { - case (0x000300): - ToV0_4_0(); - ValidateXML(XSDSchema(0x000400), fileName); - V_FALLTHROUGH - case (0x000400): - ToV0_4_1(); - ValidateXML(XSDSchema(0x000401), fileName); - V_FALLTHROUGH - case (0x000401): - ToV0_4_2(); - ValidateXML(XSDSchema(0x000402), fileName); - V_FALLTHROUGH - case (0x000402): - ToV0_4_3(); - ValidateXML(XSDSchema(0x000403), fileName); - V_FALLTHROUGH - case (0x000403): - break; - default: - break; - } - } - catch (VException &e) - { - QString error; - const QString backupFileName = fileName + QLatin1String(".backup"); - if (SafeCopy(backupFileName, fileName, error) == false) - { - const QString errorMsg(tr("Error restoring backup file: %1.").arg(error)); - VException excep(errorMsg); - excep.AddMoreInformation(e.ErrorMessage()); - throw excep; - } - - QFile file(backupFileName); - file.remove(); - - throw; + case (0x000300): + ToV0_4_0(); + ValidateXML(XSDSchema(0x000400), m_convertedFileName); + V_FALLTHROUGH + case (0x000400): + ToV0_4_1(); + ValidateXML(XSDSchema(0x000401), m_convertedFileName); + V_FALLTHROUGH + case (0x000401): + ToV0_4_2(); + ValidateXML(XSDSchema(0x000402), m_convertedFileName); + V_FALLTHROUGH + case (0x000402): + ToV0_4_3(); + ValidateXML(XSDSchema(0x000403), m_convertedFileName); + V_FALLTHROUGH + case (0x000403): + break; + default: + InvalidVersion(m_ver); + break; } } @@ -147,6 +130,20 @@ void VVSTConverter::DowngradeToCurrentMaxVersion() Save(); } +//--------------------------------------------------------------------------------------------------------------------- +bool VVSTConverter::IsReadOnly() const +{ + // Check if attribute read-only was not changed in file format + Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMaxVer == CONVERTER_VERSION_CHECK(0, 4, 3), + "Check attribute read-only."); + + // Possibly in future attribute read-only will change position etc. + // For now position is the same for all supported format versions. + // But don't forget to keep all versions of attribute until we support that format versions + + return UniqueTagText(strTagRead_Only, falseStr) == trueStr; +} + //--------------------------------------------------------------------------------------------------------------------- void VVSTConverter::AddNewTagsForV0_4_0() { diff --git a/src/libs/ifc/xml/vvstconverter.h b/src/libs/ifc/xml/vvstconverter.h index d76ccc3b9..15872915f 100644 --- a/src/libs/ifc/xml/vvstconverter.h +++ b/src/libs/ifc/xml/vvstconverter.h @@ -67,6 +67,7 @@ protected: virtual QString XSDSchema(int ver) const Q_DECL_OVERRIDE; virtual void ApplyPatches() Q_DECL_OVERRIDE; virtual void DowngradeToCurrentMaxVersion() Q_DECL_OVERRIDE; + virtual bool IsReadOnly() const Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(VVSTConverter) diff --git a/src/libs/vformat/vmeasurements.cpp b/src/libs/vformat/vmeasurements.cpp index 62ead1f98..288fef775 100644 --- a/src/libs/vformat/vmeasurements.cpp +++ b/src/libs/vformat/vmeasurements.cpp @@ -373,7 +373,7 @@ QString VMeasurements::Notes() const //--------------------------------------------------------------------------------------------------------------------- void VMeasurements::SetNotes(const QString &text) { - if (not ReadOnly()) + if (not IsReadOnly()) { setTagText(TagNotes, text); } @@ -388,7 +388,7 @@ QString VMeasurements::FamilyName() const //--------------------------------------------------------------------------------------------------------------------- void VMeasurements::SetFamilyName(const QString &text) { - if (not ReadOnly()) + if (not IsReadOnly()) { setTagText(TagFamilyName, text); } @@ -403,7 +403,7 @@ QString VMeasurements::GivenName() const //--------------------------------------------------------------------------------------------------------------------- void VMeasurements::SetGivenName(const QString &text) { - if (not ReadOnly()) + if (not IsReadOnly()) { setTagText(TagGivenName, text); } @@ -418,7 +418,7 @@ QDate VMeasurements::BirthDate() const //--------------------------------------------------------------------------------------------------------------------- void VMeasurements::SetBirthDate(const QDate &date) { - if (not ReadOnly()) + if (not IsReadOnly()) { setTagText(TagBirthDate, date.toString("yyyy-MM-dd")); } @@ -433,7 +433,7 @@ GenderType VMeasurements::Gender() const //--------------------------------------------------------------------------------------------------------------------- void VMeasurements::SetGender(const GenderType &gender) { - if (not ReadOnly()) + if (not IsReadOnly()) { setTagText(TagGender, GenderToStr(gender)); } @@ -448,7 +448,7 @@ QString VMeasurements::PMSystem() const //--------------------------------------------------------------------------------------------------------------------- void VMeasurements::SetPMSystem(const QString &system) { - if (not ReadOnly()) + if (not IsReadOnly()) { setTagText(TagPMSystem, ClearPMCode(system)); } @@ -463,23 +463,16 @@ QString VMeasurements::Email() const //--------------------------------------------------------------------------------------------------------------------- void VMeasurements::SetEmail(const QString &text) { - if (not ReadOnly()) + if (not IsReadOnly()) { setTagText(TagEmail, text); } } //--------------------------------------------------------------------------------------------------------------------- -bool VMeasurements::ReadOnly() const +bool VMeasurements::IsReadOnly() const { - if (UniqueTagText(TagReadOnly, "false") == "true") - { - return true; - } - else - { - return false; - } + return UniqueTagText(TagReadOnly, falseStr) == trueStr; } //--------------------------------------------------------------------------------------------------------------------- @@ -487,11 +480,11 @@ void VMeasurements::SetReadOnly(bool ro) { if (ro) { - setTagText(TagReadOnly, "true"); + setTagText(TagReadOnly, trueStr); } else { - setTagText(TagReadOnly, "false"); + setTagText(TagReadOnly, falseStr); } } diff --git a/src/libs/vformat/vmeasurements.h b/src/libs/vformat/vmeasurements.h index 48c9bbf5a..0ecb8b86c 100644 --- a/src/libs/vformat/vmeasurements.h +++ b/src/libs/vformat/vmeasurements.h @@ -94,7 +94,7 @@ public: QString Email() const; void SetEmail(const QString &text); - bool ReadOnly() const; + bool IsReadOnly() const; void SetReadOnly(bool ro); void SetMName(const QString &name, const QString &text); diff --git a/src/libs/vmisc/vabstractapplication.cpp b/src/libs/vmisc/vabstractapplication.cpp index d7d97cbae..cd7d1c394 100644 --- a/src/libs/vmisc/vabstractapplication.cpp +++ b/src/libs/vmisc/vabstractapplication.cpp @@ -125,18 +125,6 @@ VAbstractApplication::VAbstractApplication(int &argc, char **argv) // Connect this slot with VApplication::aboutToQuit. Settings()->sync(); }); - -#if !defined(Q_OS_WIN) - QDir standardPath(VCommonSettings::unixStandardSharePath); - const QDir localdata (QDir::homePath() + QDir::separator() + VCommonSettings::valentinaUnixHomeFolder); - if (standardPath.exists() && not localdata.exists()) - { - if (localdata.mkdir(localdata.absolutePath())) - { - SymlinkCopyDirRecursive(standardPath.absolutePath(), localdata.absolutePath(), true); - } - } -#endif // !defined(Q_OS_WIN) } //--------------------------------------------------------------------------------------------------------------------- @@ -406,54 +394,3 @@ void VAbstractApplication::ClearTranslation() delete pmsTranslator; } } - -//--------------------------------------------------------------------------------------------------------------------- -bool VAbstractApplication::SymlinkCopyDirRecursive(const QString &fromDir, const QString &toDir, bool replaceOnConflit) -{ - QDir dir; - dir.setPath(fromDir); - - foreach (QString copyFile, dir.entryList(QDir::Files)) - { - const QString from = fromDir + QDir::separator() + copyFile; - const QString to = toDir + QDir::separator() + copyFile; - - if (QFile::exists(to)) - { - if (replaceOnConflit) - { - if (QFile::remove(to) == false) - { - return false; - } - } - else - { - continue; - } - } - - if (QFile::link(from, to) == false) - { - return false; - } - } - - foreach (QString copyDir, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) - { - const QString from = fromDir + QDir::separator() + copyDir; - const QString to = toDir + QDir::separator() + copyDir; - - if (dir.mkpath(to) == false) - { - return false; - } - - if (SymlinkCopyDirRecursive(from, to, replaceOnConflit) == false) - { - return false; - } - } - - return true; -} diff --git a/src/libs/vmisc/vabstractapplication.h b/src/libs/vmisc/vabstractapplication.h index a00a980b4..6e006c45e 100644 --- a/src/libs/vmisc/vabstractapplication.h +++ b/src/libs/vmisc/vabstractapplication.h @@ -149,8 +149,6 @@ private: bool openingPattern; void ClearTranslation(); - - static bool SymlinkCopyDirRecursive(const QString &fromDir, const QString &toDir, bool replaceOnConflit); }; diff --git a/src/libs/vmisc/vcommonsettings.cpp b/src/libs/vmisc/vcommonsettings.cpp index e09caac44..e230e3b5a 100644 --- a/src/libs/vmisc/vcommonsettings.cpp +++ b/src/libs/vmisc/vcommonsettings.cpp @@ -76,8 +76,7 @@ const QString VCommonSettings::SettingUserDefinedMaterials = QStringLitera static const QString commonIniFilename = QStringLiteral("common"); #if !defined(Q_OS_WIN) -const QString VCommonSettings::unixStandardSharePath = QStringLiteral("/usr/share/valentina"); -const QString VCommonSettings::valentinaUnixHomeFolder = QStringLiteral(".valentina"); +const QString VCommonSettings::unixStandardSharePath = QStringLiteral("/usr/share/valentina"); #endif //--------------------------------------------------------------------------------------------------------------------- @@ -110,15 +109,7 @@ QString VCommonSettings::SharePath(const QString &shareItem) } else { - QDir dir(QDir::homePath() + QDir::separator() + VCommonSettings::valentinaUnixHomeFolder + shareItem); - if (dir.exists()) - { - return dir.absolutePath(); - } - else - { - return VCommonSettings::unixStandardSharePath + shareItem; - } + return VCommonSettings::unixStandardSharePath + shareItem; } } #else // Unix @@ -132,15 +123,7 @@ QString VCommonSettings::SharePath(const QString &shareItem) } else { - QDir dir(QDir::homePath() + QDir::separator() + VCommonSettings::valentinaUnixHomeFolder + shareItem); - if (dir.exists()) - { - return dir.absolutePath(); - } - else - { - return VCommonSettings::unixStandardSharePath + shareItem; - } + return VCommonSettings::unixStandardSharePath + shareItem; } #endif #endif diff --git a/src/libs/vmisc/vcommonsettings.h b/src/libs/vmisc/vcommonsettings.h index 2959ab838..6ba755bec 100644 --- a/src/libs/vmisc/vcommonsettings.h +++ b/src/libs/vmisc/vcommonsettings.h @@ -128,7 +128,6 @@ public: #if !defined(Q_OS_WIN) static const QString unixStandardSharePath; - static const QString valentinaUnixHomeFolder; #endif private: