--HG--
branch : develop
This commit is contained in:
Valentina Zhuravska 2015-09-18 16:41:09 +03:00
commit 2bfd22c02c
34 changed files with 1387 additions and 264 deletions

View file

@ -26,4 +26,9 @@ Patch contributors:
* Mac OS package. * Mac OS package.
Peter Gsellmann Peter Gsellmann
* Testing * Testing
Alex Zaharov <alexzkhr@gmail.com>
* Developing.
Valentina Zhuravska <zhuravska19@gmail.com>
* Developing.
* Testing.
* Translation.

View file

@ -38,6 +38,8 @@
#include <QTranslator> #include <QTranslator>
#include <QPointer> #include <QPointer>
#include <QLocalServer> #include <QLocalServer>
#include <QMessageBox>
#include <iostream>
#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
# include "../../libs/vmisc/backport/qcommandlineparser.h" # include "../../libs/vmisc/backport/qcommandlineparser.h"
@ -45,6 +47,91 @@
# include <QCommandLineParser> # include <QCommandLineParser>
#endif #endif
//---------------------------------------------------------------------------------------------------------------------
inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
Q_UNUSED(context)
// Why on earth didn't Qt want to make failed signal/slot connections qWarning?
if ((type == QtDebugMsg) && msg.contains("::connect"))
{
type = QtWarningMsg;
}
// this is another one that doesn't make sense as just a debug message. pretty serious
// sign of a problem
// http://www.developer.nokia.com/Community/Wiki/QPainter::begin:Paint_device_returned_engine_%3D%3D_0_(Known_Issue)
if ((type == QtDebugMsg) && msg.contains("QPainter::begin") && msg.contains("Paint device returned engine"))
{
type = QtWarningMsg;
}
// This qWarning about "Cowardly refusing to send clipboard message to hung application..."
// is something that can easily happen if you are debugging and the application is paused.
// As it is so common, not worth popping up a dialog.
if ((type == QtWarningMsg) && QString(msg).contains("QClipboard::event")
&& QString(msg).contains("Cowardly refusing"))
{
type = QtDebugMsg;
}
// only the GUI thread should display message boxes. If you are
// writing a multithreaded application and the error happens on
// a non-GUI thread, you'll have to queue the message to the GUI
QCoreApplication *instance = QCoreApplication::instance();
const bool isGuiThread = instance && (QThread::currentThread() == instance->thread());
if (isGuiThread)
{
//fixme: trying to make sure there are no save/load dialogs are opened, because error message during them will
//lead to crash
const bool topWinAllowsPop = (qApp->activeModalWidget() == nullptr) ||
!qApp->activeModalWidget()->inherits("QFileDialog");
QMessageBox messageBox;
switch (type)
{
case QtDebugMsg:
std::cerr << msg.toUtf8().constData() << std::endl;
return;
case QtWarningMsg:
messageBox.setIcon(QMessageBox::Warning);
break;
case QtCriticalMsg:
messageBox.setIcon(QMessageBox::Critical);
break;
case QtFatalMsg:
messageBox.setIcon(QMessageBox::Critical);
break;
default:
break;
}
if (type == QtWarningMsg || type == QtCriticalMsg || type == QtFatalMsg)
{
if (topWinAllowsPop)
{
messageBox.setInformativeText(msg);
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.setWindowModality(Qt::ApplicationModal);
messageBox.setModal(true);
messageBox.exec();
}
}
if (QtFatalMsg == type)
{
abort();
}
}
else
{
if (type != QtDebugMsg)
{
abort(); // be NOISY unless overridden!
}
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
MApplication::MApplication(int &argc, char **argv) MApplication::MApplication(int &argc, char **argv)
:VAbstractApplication(argc, argv), :VAbstractApplication(argc, argv),
@ -138,6 +225,8 @@ QList<TMainWindow *> MApplication::MainWindows()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void MApplication::InitOptions() void MApplication::InitOptions()
{ {
qInstallMessageHandler(noisyFailureMsgHandler);
OpenSettings(); OpenSettings();
qDebug()<<"Version:"<<APP_VERSION_STR; qDebug()<<"Version:"<<APP_VERSION_STR;

View file

@ -12,7 +12,8 @@ SOURCES += \
$$PWD/dialogs/tapeconfigdialog.cpp \ $$PWD/dialogs/tapeconfigdialog.cpp \
$$PWD/dialogs/configpages/tapeconfigurationpage.cpp \ $$PWD/dialogs/configpages/tapeconfigurationpage.cpp \
$$PWD/dialogs/configpages/tapepathpage.cpp \ $$PWD/dialogs/configpages/tapepathpage.cpp \
$$PWD/vlitepattern.cpp $$PWD/vlitepattern.cpp \
$$PWD/vtablesearch.cpp
HEADERS += \ HEADERS += \
$$PWD/tmainwindow.h \ $$PWD/tmainwindow.h \
@ -25,7 +26,8 @@ HEADERS += \
$$PWD/dialogs/tapeconfigdialog.h \ $$PWD/dialogs/tapeconfigdialog.h \
$$PWD/dialogs/configpages/tapeconfigurationpage.h \ $$PWD/dialogs/configpages/tapeconfigurationpage.h \
$$PWD/dialogs/configpages/tapepathpage.h \ $$PWD/dialogs/configpages/tapepathpage.h \
$$PWD/vlitepattern.h $$PWD/vlitepattern.h \
$$PWD/vtablesearch.h
FORMS += \ FORMS += \
$$PWD/tmainwindow.ui \ $$PWD/tmainwindow.ui \

View file

@ -37,6 +37,7 @@
#include "../ifc/xml/vvitconverter.h" #include "../ifc/xml/vvitconverter.h"
#include "../ifc/xml/vvstconverter.h" #include "../ifc/xml/vvstconverter.h"
#include "../ifc/xml/vpatternconverter.h" #include "../ifc/xml/vpatternconverter.h"
#include "../vmisc/vlockguard.h"
#include "vlitepattern.h" #include "vlitepattern.h"
#include "../qmuparser/qmudef.h" #include "../qmuparser/qmudef.h"
#include "../vtools/dialogs/support/dialogeditwrongformula.h" #include "../vtools/dialogs/support/dialogeditwrongformula.h"
@ -48,9 +49,6 @@
#include <QMessageBox> #include <QMessageBox>
#include <QComboBox> #include <QComboBox>
#include <QProcess> #include <QProcess>
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
# include <QLockFile>
#endif
#define DIALOG_MAX_FORMULA_HEIGHT 64 #define DIALOG_MAX_FORMULA_HEIGHT 64
@ -70,9 +68,11 @@ TMainWindow::TMainWindow(QWidget *parent)
gradationSizes(nullptr), gradationSizes(nullptr),
comboBoxUnits(nullptr), comboBoxUnits(nullptr),
formulaBaseHeight(0), formulaBaseHeight(0),
lock(nullptr) lock(nullptr),
search()
{ {
ui->setupUi(this); ui->setupUi(this);
search = QSharedPointer<VTableSearch>(new VTableSearch(ui->tableWidget));
ui->tabWidget->setVisible(false); ui->tabWidget->setVisible(false);
ui->mainToolBar->setContextMenuPolicy(Qt::PreventContextMenu); ui->mainToolBar->setContextMenuPolicy(Qt::PreventContextMenu);
@ -98,10 +98,6 @@ TMainWindow::~TMainWindow()
delete m; delete m;
} }
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
delete lock; // Unlock pattern file
#endif
delete ui; delete ui;
} }
@ -182,18 +178,14 @@ void TMainWindow::LoadFile(const QString &path)
} }
} }
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) VlpCreateLock(lock, QFileInfo(path).fileName()+".lock");
lock = new QLockFile(QFileInfo(path).fileName()+".lock");
lock->setStaleLockTime(0); if (lock->GetLockError() == QLockFile::LockFailedError)
if (not MApplication::TryLock(lock))
{ {
if (lock->error() == QLockFile::LockFailedError) qCCritical(tMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData());
{ lock.reset();
qCCritical(tMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData()); return;
return;
}
} }
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
try try
{ {
@ -257,6 +249,7 @@ void TMainWindow::LoadFile(const QString &path)
m = nullptr; m = nullptr;
delete data; delete data;
data = nullptr; data = nullptr;
lock.reset();
return; return;
} }
} }
@ -361,6 +354,24 @@ void TMainWindow::OpenTemplate()
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void TMainWindow::Find(const QString &term)
{
search->Find(term);
}
//---------------------------------------------------------------------------------------------------------------------
void TMainWindow::FindPrevious()
{
search->FindPrevious();
}
//---------------------------------------------------------------------------------------------------------------------
void TMainWindow::FindNext()
{
search->FindNext();
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void TMainWindow::closeEvent(QCloseEvent *event) void TMainWindow::closeEvent(QCloseEvent *event)
{ {
@ -462,6 +473,22 @@ void TMainWindow::FileSaveAs()
{ {
fileName += "." + suffix; fileName += "." + suffix;
} }
if (QFileInfo(fileName).exists())
{
VLockGuard<char> tmp(fileName + ".lock");
if (not tmp.IsLocked())
{
if (lock->GetLockError() == QLockFile::LockFailedError)
{
qCCritical(tMainWindow, "%s", tr("Failed to lock. This file already opened in another window.")
.toUtf8().constData());
return;
}
}
}
QString error; QString error;
bool result = SaveMeasurements(fileName, error); bool result = SaveMeasurements(fileName, error);
if (result == false) if (result == false)
@ -473,6 +500,20 @@ void TMainWindow::FileSaveAs()
messageBox.setDetailedText(error); messageBox.setDetailedText(error);
messageBox.setStandardButtons(QMessageBox::Ok); messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.exec(); messageBox.exec();
return;
}
lock.reset();
VlpCreateLock(lock, fileName + ".lock");
if (lock->GetLockError() == QLockFile::LockFailedError)
{
qCCritical(tMainWindow, "%s", tr("Failed to lock. This file already opened in another window. "
"Expect collissions when run 2 copies of the program.").toUtf8().constData());
lock.reset();
return;
} }
} }
@ -613,7 +654,9 @@ void TMainWindow::Remove()
MeasurementsWasSaved(false); MeasurementsWasSaved(false);
search->RemoveRow(row);
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
if (ui->tableWidget->rowCount() > 0) if (ui->tableWidget->rowCount() > 0)
{ {
@ -679,6 +722,7 @@ void TMainWindow::MoveUp()
m->MoveUp(nameField->text()); m->MoveUp(nameField->text());
MeasurementsWasSaved(false); MeasurementsWasSaved(false);
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(row-1); ui->tableWidget->selectRow(row-1);
} }
@ -696,6 +740,7 @@ void TMainWindow::MoveDown()
m->MoveDown(nameField->text()); m->MoveDown(nameField->text());
MeasurementsWasSaved(false); MeasurementsWasSaved(false);
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(row+1); ui->tableWidget->selectRow(row+1);
} }
@ -730,6 +775,8 @@ void TMainWindow::Fx()
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(row); ui->tableWidget->selectRow(row);
} }
delete dialog; delete dialog;
@ -760,7 +807,9 @@ void TMainWindow::AddCustom()
m->AddEmptyAfter(nameField->text(), name); m->AddEmptyAfter(nameField->text(), name);
} }
search->AddRow(currentRow);
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(currentRow); ui->tableWidget->selectRow(currentRow);
@ -789,6 +838,8 @@ void TMainWindow::AddKnown()
{ {
m->AddEmpty(list.at(i)); m->AddEmpty(list.at(i));
} }
search->AddRow(currentRow);
} }
} }
else else
@ -806,11 +857,13 @@ void TMainWindow::AddKnown()
{ {
m->AddEmptyAfter(after, list.at(i)); m->AddEmptyAfter(after, list.at(i));
} }
search->AddRow(currentRow);
after = list.at(i); after = list.at(i);
} }
} }
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(currentRow); ui->tableWidget->selectRow(currentRow);
@ -839,18 +892,13 @@ void TMainWindow::ImportFromPattern()
return; return;
} }
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) VLockGuard<char> tmp(QFileInfo(mPath).fileName()+".lock");
QLockFile *lock = new QLockFile(QFileInfo(mPath).fileName()+".lock");
lock->setStaleLockTime(0); if (tmp.GetLockError() == QLockFile::LockFailedError)
if (not MApplication::TryLock(lock))
{ {
if (lock->error() == QLockFile::LockFailedError) qCCritical(tMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData());
{ return;
qCCritical(tMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData());
return;
}
} }
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on qt_ntfs_permission_lookup++; // turn checking on
@ -878,8 +926,6 @@ void TMainWindow::ImportFromPattern()
qt_ntfs_permission_lookup--; // turn it off again qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/ #endif /*Q_OS_WIN32*/
delete lock; // release a pattern file
measurements = FilterMeasurements(measurements, m->ListAll()); measurements = FilterMeasurements(measurements, m->ListAll());
qint32 currentRow; qint32 currentRow;
@ -906,6 +952,8 @@ void TMainWindow::ImportFromPattern()
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(currentRow); ui->tableWidget->selectRow(currentRow);
MeasurementsWasSaved(false); MeasurementsWasSaved(false);
@ -917,6 +965,7 @@ void TMainWindow::ChangedSize(const QString &text)
const int row = ui->tableWidget->currentRow(); const int row = ui->tableWidget->currentRow();
data->SetSize(text.toInt()); data->SetSize(text.toInt());
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(row); ui->tableWidget->selectRow(row);
} }
@ -926,6 +975,7 @@ void TMainWindow::ChangedHeight(const QString &text)
const int row = ui->tableWidget->currentRow(); const int row = ui->tableWidget->currentRow();
data->SetHeight(text.toInt()); data->SetHeight(text.toInt());
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(row); ui->tableWidget->selectRow(row);
} }
@ -1070,6 +1120,7 @@ void TMainWindow::SaveMName()
m->SetMName(nameField->text(), newName); m->SetMName(nameField->text(), newName);
MeasurementsWasSaved(false); MeasurementsWasSaved(false);
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->blockSignals(true); ui->tableWidget->blockSignals(true);
ui->tableWidget->selectRow(row); ui->tableWidget->selectRow(row);
@ -1139,6 +1190,7 @@ void TMainWindow::SaveMValue()
const QTextCursor cursor = ui->plainTextEditFormula->textCursor(); const QTextCursor cursor = ui->plainTextEditFormula->textCursor();
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->blockSignals(true); ui->tableWidget->blockSignals(true);
ui->tableWidget->selectRow(row); ui->tableWidget->selectRow(row);
@ -1163,6 +1215,7 @@ void TMainWindow::SaveMBaseValue(double value)
MeasurementsWasSaved(false); MeasurementsWasSaved(false);
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->blockSignals(true); ui->tableWidget->blockSignals(true);
ui->tableWidget->selectRow(row); ui->tableWidget->selectRow(row);
@ -1185,6 +1238,7 @@ void TMainWindow::SaveMSizeIncrease(double value)
MeasurementsWasSaved(false); MeasurementsWasSaved(false);
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->blockSignals(true); ui->tableWidget->blockSignals(true);
ui->tableWidget->selectRow(row); ui->tableWidget->selectRow(row);
@ -1207,6 +1261,7 @@ void TMainWindow::SaveMHeightIncrease(double value)
MeasurementsWasSaved(false); MeasurementsWasSaved(false);
RefreshData(); RefreshData();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(row); ui->tableWidget->selectRow(row);
} }
@ -1464,6 +1519,10 @@ void TMainWindow::InitWindow()
connect(ui->toolButtonExpr, &QToolButton::clicked, this, &TMainWindow::Fx); connect(ui->toolButtonExpr, &QToolButton::clicked, this, &TMainWindow::Fx);
} }
connect(ui->lineEditFind, &QLineEdit::textEdited, this, &TMainWindow::Find);
connect(ui->toolButtonFindPrevious, &QToolButton::clicked, this, &TMainWindow::FindPrevious);
connect(ui->toolButtonFindNext, &QToolButton::clicked, this, &TMainWindow::FindNext);
ui->plainTextEditNotes->setPlainText(m->Notes()); ui->plainTextEditNotes->setPlainText(m->Notes());
connect(ui->plainTextEditNotes, &QPlainTextEdit::textChanged, this, &TMainWindow::SaveNotes); connect(ui->plainTextEditNotes, &QPlainTextEdit::textChanged, this, &TMainWindow::SaveNotes);
@ -1678,6 +1737,7 @@ void TMainWindow::SetDefaultSize(int value)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void TMainWindow::RefreshData() void TMainWindow::RefreshData()
{ {
data->ClearUniqueNames();
data->ClearVariables(VarType::Measurement); data->ClearVariables(VarType::Measurement);
m->ReadMeasurements(); m->ReadMeasurements();
@ -1817,6 +1877,10 @@ void TMainWindow::MFields(bool enabled)
ui->pushButtonGrow->setEnabled(enabled); ui->pushButtonGrow->setEnabled(enabled);
ui->toolButtonExpr->setEnabled(enabled); ui->toolButtonExpr->setEnabled(enabled);
} }
ui->lineEditFind->setEnabled(enabled);
ui->toolButtonFindPrevious->setEnabled(enabled);
ui->toolButtonFindNext->setEnabled(enabled);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -2003,6 +2067,8 @@ void TMainWindow::UpdatePatternUnit()
ShowUnits(); ShowUnits();
RefreshTable(); RefreshTable();
search->RefreshList(ui->lineEditFind->text());
ui->tableWidget->selectRow(row); ui->tableWidget->selectRow(row);
} }

View file

@ -33,7 +33,9 @@
#include <QTableWidget> #include <QTableWidget>
#include "../vmisc/def.h" #include "../vmisc/def.h"
#include "../vmisc/vlockguard.h"
#include "../vformat/vmeasurements.h" #include "../vformat/vmeasurements.h"
#include "vtablesearch.h"
namespace Ui namespace Ui
{ {
@ -43,9 +45,6 @@ namespace Ui
class QComboBox; class QComboBox;
class QTableWidgetItem; class QTableWidgetItem;
class QLabel; class QLabel;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
class QLockFile;
#endif
class TMainWindow : public QMainWindow class TMainWindow : public QMainWindow
{ {
@ -115,10 +114,11 @@ private slots:
void SaveMFullName(); void SaveMFullName();
void NewWindow(); void NewWindow();
void Preferences(); void Preferences();
void PatternUnitChanged(int index); void PatternUnitChanged(int index);
void Find(const QString &term);
void FindPrevious();
void FindNext();
private: private:
Q_DISABLE_COPY(TMainWindow) Q_DISABLE_COPY(TMainWindow)
@ -133,10 +133,8 @@ private:
QComboBox *gradationSizes; QComboBox *gradationSizes;
QComboBox *comboBoxUnits; QComboBox *comboBoxUnits;
int formulaBaseHeight; int formulaBaseHeight;
VLockGuardPtr<char> lock;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) QSharedPointer<VTableSearch> search;
QLockFile *lock;
#endif
void SetupMenu(); void SetupMenu();
void InitWindow(); void InitWindow();

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>536</width> <width>536</width>
<height>694</height> <height>726</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -43,6 +43,69 @@
<string>Measurements</string> <string>Measurements</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="labelFind">
<property name="text">
<string>Find:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditFind">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonFindPrevious">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Find Previous</string>
</property>
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset theme="go-previous">
<normaloff/>
</iconset>
</property>
<property name="shortcut">
<string>Ctrl+Shift+G</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonFindNext">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Find Next</string>
</property>
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset theme="go-next">
<normaloff/>
</iconset>
</property>
<property name="shortcut">
<string>Ctrl+G</string>
</property>
<property name="autoExclusive">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QTableWidget" name="tableWidget"> <widget class="QTableWidget" name="tableWidget">
<property name="sizePolicy"> <property name="sizePolicy">

View file

@ -0,0 +1,208 @@
/************************************************************************
**
** @file vtablesearch.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 15 9, 2015
**
** @brief
** @copyright
** This source code is part of the Valentine project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2015 Valentina project
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vtablesearch.h"
#include "../vmisc/def.h"
//---------------------------------------------------------------------------------------------------------------------
VTableSearch::VTableSearch(QTableWidget *table)
:table(table),
searchIndex(-1),
searchList()
{
}
//---------------------------------------------------------------------------------------------------------------------
void VTableSearch::Clear()
{
SCASSERT(table != nullptr);
foreach(QTableWidgetItem *item, searchList)
{
if (item->row() % 2 != 0 && table->alternatingRowColors())
{
item->setBackground(QPalette().alternateBase());
}
else
{
item->setBackground(QPalette().base());
}
}
searchIndex = -1;
}
//---------------------------------------------------------------------------------------------------------------------
void VTableSearch::ShowNext(int newIndex)
{
if (not searchList.isEmpty())
{
QTableWidgetItem *item = searchList.at(searchIndex);
item->setBackground(Qt::yellow);
item = searchList.at(newIndex);
item->setBackground(Qt::red);
table->scrollToItem(item);
searchIndex = newIndex;
}
else
{
Clear();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VTableSearch::Find(const QString &term)
{
SCASSERT(table != nullptr);
const QList<QTableWidgetItem *> list = table->findItems(term, Qt::MatchContains);
if (list.isEmpty() || term.isEmpty())
{
Clear();
}
else
{
Clear();
searchList = list;
foreach(QTableWidgetItem *item, searchList)
{
item->setBackground(Qt::yellow);
}
searchIndex = 0;
QTableWidgetItem *item = searchList.at(searchIndex);
item->setBackground(Qt::red);
table->scrollToItem(item);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VTableSearch::FindPrevious()
{
int newIndex = searchIndex - 1;
if (newIndex < 0)
{
newIndex = searchList.size() - 1;
}
ShowNext(newIndex);
}
//---------------------------------------------------------------------------------------------------------------------
void VTableSearch::FindNext()
{
int newIndex = searchIndex + 1;
if (newIndex >= searchList.size())
{
newIndex = 0;
}
ShowNext(newIndex);
}
//---------------------------------------------------------------------------------------------------------------------
void VTableSearch::RemoveRow(int row)
{
if (searchIndex < 0 || searchIndex >= searchList.size())
{
return;
}
const int indexRow = searchList.at(searchIndex)->row();
if (row <= indexRow)
{
foreach(QTableWidgetItem *item, searchList)
{
if (item->row() == row)
{
--searchIndex;
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VTableSearch::AddRow(int row)
{
if (searchIndex < 0 || searchIndex >= searchList.size())
{
return;
}
const int indexRow = searchList.at(searchIndex)->row();
if (row <= indexRow)
{
foreach(QTableWidgetItem *item, searchList)
{
if (item->row() == row)
{
++searchIndex;
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VTableSearch::RefreshList(const QString &term)
{
SCASSERT(table != nullptr);
if (term.isEmpty())
{
return;
}
searchList = table->findItems(term, Qt::MatchContains);
foreach(QTableWidgetItem *item, searchList)
{
item->setBackground(Qt::yellow);
}
if (not searchList.isEmpty())
{
if (searchIndex < 0)
{
searchIndex = searchList.size() - 1;
}
else if (searchIndex >= searchList.size())
{
searchIndex = 0;
}
QTableWidgetItem *item = searchList.at(searchIndex);
item->setBackground(Qt::red);
table->scrollToItem(item);
}
}

View file

@ -0,0 +1,58 @@
/************************************************************************
**
** @file vtablesearch.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 15 9, 2015
**
** @brief
** @copyright
** This source code is part of the Valentine project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2015 Valentina project
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VTABLESEARCH_H
#define VTABLESEARCH_H
#include <QList>
#include <QTableWidget>
class VTableSearch
{
public:
VTableSearch(QTableWidget *table);
void Find(const QString &term);
void FindPrevious();
void FindNext();
void RemoveRow(int row);
void AddRow(int row);
void RefreshList(const QString &term);
private:
Q_DISABLE_COPY(VTableSearch)
QTableWidget *table;
int searchIndex;
QList<QTableWidgetItem *> searchList;
void Clear();
void ShowNext(int newIndex);
};
#endif // VTABLESEARCH_H

View file

@ -53,6 +53,8 @@
Q_LOGGING_CATEGORY(vApp, "v.application") Q_LOGGING_CATEGORY(vApp, "v.application")
constexpr auto DAYS_TO_KEEP_LOGS = 3;
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{ {
@ -170,12 +172,8 @@ const QString VApplication::GistFileName = QStringLiteral("gist.json");
VApplication::VApplication(int &argc, char **argv) VApplication::VApplication(int &argc, char **argv)
: VAbstractApplication(argc, argv), : VAbstractApplication(argc, argv),
trVars(nullptr), autoSaveTimer(nullptr), trVars(nullptr), autoSaveTimer(nullptr),
log(nullptr), lockLog(),
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
out(nullptr), logLock(nullptr)
#else
out(nullptr) out(nullptr)
#endif
{ {
VCommandLine::Reset(); // making sure will create new instance...just in case we will ever do 2 objects of VApplication VCommandLine::Reset(); // making sure will create new instance...just in case we will ever do 2 objects of VApplication
VCommandLine::Get(*this); VCommandLine::Get(*this);
@ -187,16 +185,6 @@ VApplication::~VApplication()
{ {
qCDebug(vApp, "Application closing."); qCDebug(vApp, "Application closing.");
qInstallMessageHandler(0); // Resore the message handler qInstallMessageHandler(0); // Resore the message handler
delete out;
if (log != nullptr)
{
log->close();
delete log;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
delete logLock;
#endif
}
delete trVars; delete trVars;
VCommandLine::Reset(); VCommandLine::Reset();
} }
@ -418,32 +406,25 @@ void VApplication::CreateLogDir() const
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VApplication::BeginLogging() void VApplication::BeginLogging()
{ {
log = new QFile(LogPath()); VlpCreateLock(lockLog, LogPath()+".lock", [this](){return new QFile(LogPath());});
if (log->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
{
out = new QTextStream(log);
qInstallMessageHandler(noisyFailureMsgHandler);
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) if (lockLog->IsLocked())
logLock = new QLockFile(LogPath()+".lock"); {
logLock->setStaleLockTime(0); if (lockLog->GetProtected()->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
if (TryLock(logLock))
{ {
out.reset(new QTextStream(lockLog->GetProtected().get()));
qInstallMessageHandler(noisyFailureMsgHandler);
qCDebug(vApp, "Log file %s was locked.", LogPath().toUtf8().constData()); qCDebug(vApp, "Log file %s was locked.", LogPath().toUtf8().constData());
} }
else else
{ {
qCDebug(vApp, "Failed to lock %s", LogPath().toUtf8().constData()); qCDebug(vApp, "Error opening log file \'%s\'. All debug output redirected to console.",
qCDebug(vApp, "Error type: %d", logLock->error()); LogPath().toUtf8().constData());
} }
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
} }
else else
{ {
delete log; qCDebug(vApp, "Failed to lock %s", LogPath().toUtf8().constData());
log = nullptr;
qCDebug(vApp, "Error opening log file \'%s\'. All debug output redirected to console.",
LogPath().toUtf8().constData());
} }
} }
@ -459,45 +440,29 @@ void VApplication::ClearOldLogs() const
if (allFiles.isEmpty() == false) if (allFiles.isEmpty() == false)
{ {
qCDebug(vApp, "Clearing old logs"); qCDebug(vApp, "Clearing old logs");
for (int i = 0; i < allFiles.size(); ++i) for (int i = 0, sz = allFiles.size(); i < sz; ++i)
{ {
QFileInfo info(allFiles.at(i)); auto fn = allFiles.at(i);
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) QFileInfo info(fn);
QLockFile *lock = new QLockFile(info.absoluteFilePath() + ".lock"); if (info.created().daysTo(QDateTime::currentDateTime()) >= DAYS_TO_KEEP_LOGS)
if (TryLock(lock))
{ {
qCDebug(vApp, "Locked file %s", info.absoluteFilePath().toUtf8().constData()); VLockGuard<QFile> tmp(info.absoluteFilePath() + ".lock", [&fn](){return new QFile(fn);});
QFile oldLog(allFiles.at(i)); if (tmp.GetProtected() != nullptr)
if (oldLog.remove())
{ {
qCDebug(vApp, "Deleted %s", info.absoluteFilePath().toUtf8().constData()); if (tmp.GetProtected()->remove())
{
qCDebug(vApp, "Deleted %s", info.absoluteFilePath().toUtf8().constData());
}
else
{
qCDebug(vApp, "Could not delete %s", info.absoluteFilePath().toUtf8().constData());
}
} }
else else
{ {
qCDebug(vApp, "Could not delete %s", info.absoluteFilePath().toUtf8().constData()); qCDebug(vApp, "Failed to lock %s", info.absoluteFilePath().toUtf8().constData());
} }
} }
else
{
qCDebug(vApp, "Failed to lock %s", info.absoluteFilePath().toUtf8().constData());
}
delete lock;
lock = nullptr;
#else
if (info.created().daysTo(QDateTime::currentDateTime()) >= 3)
{
QFile oldLog(allFiles.at(i));
if (oldLog.remove())
{
qCDebug(vApp, "Deleted %s", info.absoluteFilePath().toUtf8().constData());
}
else
{
qCDebug(vApp, "Could not delete %s", info.absoluteFilePath().toUtf8().constData());
}
}
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
} }
} }
else else
@ -614,7 +579,7 @@ void VApplication::StartLogging()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QTextStream *VApplication::LogFile() QTextStream *VApplication::LogFile()
{ {
return out; return out.get();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -707,27 +672,28 @@ void VApplication::GatherLogs() const
const QStringList allFiles = logsDir.entryList(QDir::NoDotAndDotDot | QDir::Files); const QStringList allFiles = logsDir.entryList(QDir::NoDotAndDotDot | QDir::Files);
if (allFiles.isEmpty() == false) if (allFiles.isEmpty() == false)
{ {
for (int i = 0; i < allFiles.size(); ++i) for (int i = 0, sz = allFiles.size(); i < sz; ++i)
{ {
QFileInfo info(allFiles.at(i)); auto fn = allFiles.at(i);
QFileInfo info(fn);
if (info.fileName() == "valentina.log") if (info.fileName() == "valentina.log")
{ {
continue; continue;
} }
QLockFile *logLock = new QLockFile(info.absoluteFilePath()+".lock");
logLock->setStaleLockTime(0); VLockGuard<QFile> tmp(info.absoluteFilePath() + ".lock", [&fn](){return new QFile(fn);});
if (TryLock(logLock))
if (tmp.IsLocked())
{ {
*out <<"--------------------------" << endl; *out <<"--------------------------" << endl;
QFile logFile(info.absoluteFilePath()); if (tmp.GetProtected()->open(QIODevice::ReadOnly | QIODevice::Text))
if (logFile.open(QIODevice::ReadOnly | QIODevice::Text))
{ {
QTextStream in(&logFile); QTextStream in(&tmp.GetProtected());
while (!in.atEnd()) while (!in.atEnd())
{ {
*out << in.readLine() << endl; *out << in.readLine() << endl;
} }
logFile.close(); tmp.GetProtected()->close();
} }
else else
{ {
@ -736,9 +702,8 @@ void VApplication::GatherLogs() const
} }
else else
{ {
*out << "Could not lock" << info.absoluteFilePath() << "."; qCDebug(vApp, "Failed to lock %s", info.absoluteFilePath().toUtf8().constData());
} }
delete logLock;
} }
} }
else else
@ -924,7 +889,9 @@ void VApplication::SendReport(const QString &reportName) const
const QString arg = QString("curl.exe -k -H \"Authorization: bearer ")+token.join("")+ const QString arg = QString("curl.exe -k -H \"Authorization: bearer ")+token.join("")+
QString("\" -H \"Accept: application/json\" -H \"Content-type: application/json\" -X POST " QString("\" -H \"Accept: application/json\" -H \"Content-type: application/json\" -X POST "
"--data @gist.json https://api.github.com/gists"); "--data @gist.json https://api.github.com/gists");
QProcess::startDetached(arg); QProcess proc;
proc.start(arg);
proc.waitForFinished(10000); // 10 sec
reportFile.remove();// Clear after yourself reportFile.remove();// Clear after yourself
} }
else else

View file

@ -36,7 +36,6 @@
#include "vsettings.h" #include "vsettings.h"
#include "vcmdexport.h" #include "vcmdexport.h"
class VApplication;// use in define class VApplication;// use in define
class VMainGraphicsView; class VMainGraphicsView;
class VPattern; class VPattern;
@ -95,11 +94,9 @@ private:
VTranslateVars *trVars; VTranslateVars *trVars;
QTimer *autoSaveTimer; QTimer *autoSaveTimer;
QFile *log; VLockGuardPtr<QFile> lockLog;
QTextStream *out; std::shared_ptr<QTextStream> out;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
QLockFile *logLock;
#endif
void InitLineWidth(); void InitLineWidth();
#if defined(Q_OS_WIN) && defined(Q_CC_GNU) #if defined(Q_OS_WIN) && defined(Q_CC_GNU)

View file

@ -214,7 +214,9 @@ Robert Martin
Michaela Orth Michaela Orth
Rina Rivera Rina Rivera
Fritz Rometsch Fritz Rometsch
Felix Ulber </string> Felix Ulber
Alex Zaharov
Valentina Zhuravska </string>
</property> </property>
</widget> </widget>
</item> </item>

View file

@ -46,6 +46,7 @@
#include "../vformat/vmeasurements.h" #include "../vformat/vmeasurements.h"
#include "../ifc/xml/vvstconverter.h" #include "../ifc/xml/vvstconverter.h"
#include "../ifc/xml/vvitconverter.h" #include "../ifc/xml/vvitconverter.h"
#include "../vwidgets/vwidgetpopup.h"
#include <QInputDialog> #include <QInputDialog>
#include <QDebug> #include <QDebug>
@ -62,9 +63,6 @@
#include <QtGlobal> #include <QtGlobal>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QDesktopServices> #include <QDesktopServices>
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
# include <QLockFile>
#endif
#include <chrono> #include <chrono>
#include <thread> #include <thread>
@ -1162,13 +1160,16 @@ void MainWindow::SyncMeasurements()
{ {
if (mChanges) if (mChanges)
{ {
if(LoadMeasurements(doc->MPath())) const QString path = AbsoluteMPath(curFile, doc->MPath());
if(LoadMeasurements(path))
{ {
if (not watcher->files().contains(doc->MPath())) if (not watcher->files().contains(path))
{ {
watcher->addPath(doc->MPath()); watcher->addPath(path);
} }
helpLabel->setText(tr("Measurements updated")); const QString msg = tr("Measurements was updated");
helpLabel->setText(msg);
VWidgetPopup::PopupMessage(this, msg);
doc->LiteParseTree(Document::LiteParse); doc->LiteParseTree(Document::LiteParse);
mChanges = false; mChanges = false;
} }
@ -1395,9 +1396,10 @@ void MainWindow::currentPPChanged(int index)
*/ */
void MainWindow::mouseMove(const QPointF &scenePos) void MainWindow::mouseMove(const QPointF &scenePos)
{ {
QString string = QString("%1, %2 (%3)").arg(static_cast<qint32>(qApp->fromPixel(scenePos.x()))) //: Coords in status line: "X, Y (units)"
QString string = QString(tr("%1, %2 (%3)")).arg(static_cast<qint32>(qApp->fromPixel(scenePos.x())))
.arg(static_cast<qint32>(qApp->fromPixel(scenePos.y()))) .arg(static_cast<qint32>(qApp->fromPixel(scenePos.y())))
.arg(doc->UnitsToStr(qApp->patternUnit())); .arg(doc->UnitsToStr(qApp->patternUnit(), true));
if (mouseCoordinate != nullptr) if (mouseCoordinate != nullptr)
{ {
mouseCoordinate->setText(string); mouseCoordinate->setText(string);
@ -1859,9 +1861,24 @@ bool MainWindow::SaveAs()
{ {
fileName += ".val"; fileName += ".val";
} }
const QString oldFileName = curFile;
if (QFileInfo(fileName).exists())
{
VLockGuard<char> tmp(fileName + ".lock");
if (not tmp.IsLocked())
{
if (lock->GetLockError() == QLockFile::LockFailedError)
{
qCCritical(vMainWindow, "%s", tr("Failed to lock. This file already opened in another window.")
.toUtf8().constData());
return false;
}
}
}
QString error; QString error;
bool result = SavePattern(fileName, error); const bool result = SavePattern(fileName, error);
if (result == false) if (result == false)
{ {
QMessageBox messageBox; QMessageBox messageBox;
@ -1871,14 +1888,33 @@ bool MainWindow::SaveAs()
messageBox.setDetailedText(error); messageBox.setDetailedText(error);
messageBox.setStandardButtons(QMessageBox::Ok); messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.exec(); messageBox.exec();
return result;
} }
if (oldFileName != curFile)
{// Now we have new file name after save as. qCDebug(vMainWindow, "Unlock old file");
// But still have previous name in restore list. We should delete them. lock.reset();
QStringList restoreFiles = qApp->ValentinaSettings()->GetRestoreFileList();
restoreFiles.removeAll(oldFileName); qCDebug(vMainWindow, "Locking file");
qApp->ValentinaSettings()->SetRestoreFileList(restoreFiles); VlpCreateLock(lock, fileName+".lock");
if (lock->IsLocked())
{
qCDebug(vMainWindow, "Pattern file %s was locked.", fileName.toUtf8().constData());
} }
else
{
qCDebug(vMainWindow, "Failed to lock %s", fileName.toUtf8().constData());
qCDebug(vMainWindow, "Error type: %d", lock->GetLockError());
if (lock->GetLockError() == QLockFile::LockFailedError)
{
qCCritical(vMainWindow, "%s", tr("Failed to lock. This file already opened in another window. "
"Expect collissions when run 2 copies of the program.")
.toUtf8().constData());
lock.reset();
}
}
return result; return result;
} }
@ -1983,13 +2019,8 @@ void MainWindow::OnlineHelp()
void MainWindow::Clear() void MainWindow::Clear()
{ {
qCDebug(vMainWindow, "Reseting main window."); qCDebug(vMainWindow, "Reseting main window.");
lock.reset();
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
delete lock; // Unlock pattern file
lock = nullptr;
qCDebug(vMainWindow, "Unlocked pattern file."); qCDebug(vMainWindow, "Unlocked pattern file.");
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
ui->actionDetails->setChecked(true); ui->actionDetails->setChecked(true);
ui->actionDraw->setChecked(true); ui->actionDraw->setChecked(true);
ui->actionLayout->setEnabled(true); ui->actionLayout->setEnabled(true);
@ -3060,9 +3091,6 @@ MainWindow::~MainWindow()
CancelTool(); CancelTool();
CleanLayout(); CleanLayout();
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
delete lock; // Unlock pattern file
#endif
delete doc; delete doc;
delete sceneDetails; delete sceneDetails;
delete sceneDraw; delete sceneDraw;
@ -3091,26 +3119,24 @@ bool MainWindow::LoadPattern(const QString &fileName, const QString& customMeasu
return false; return false;
} }
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
qCDebug(vMainWindow, "Loking file"); qCDebug(vMainWindow, "Loking file");
lock = new QLockFile(fileName+".lock"); VlpCreateLock(lock, fileName+".lock");
lock->setStaleLockTime(0);
if (VApplication::TryLock(lock)) if (lock->IsLocked())
{ {
qCDebug(vMainWindow, "Pattern file %s was locked.", fileName.toUtf8().constData()); qCDebug(vMainWindow, "Pattern file %s was locked.", fileName.toUtf8().constData());
} }
else else
{ {
qCDebug(vMainWindow, "Failed to lock %s", fileName.toUtf8().constData()); qCDebug(vMainWindow, "Failed to lock %s", fileName.toUtf8().constData());
qCDebug(vMainWindow, "Error type: %d", lock->error()); qCDebug(vMainWindow, "Error type: %d", lock->GetLockError());
if (lock->error() == QLockFile::LockFailedError) if (lock->GetLockError() == QLockFile::LockFailedError)
{ {
qCCritical(vMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData()); qCCritical(vMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData());
Clear(); Clear();
return false; return false;
} }
} }
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
// On this stage scene empty. Fit scene size to view size // On this stage scene empty. Fit scene size to view size
VMainGraphicsView::NewSceneRect(sceneDraw, ui->view); VMainGraphicsView::NewSceneRect(sceneDraw, ui->view);
@ -3213,14 +3239,11 @@ QStringList MainWindow::GetUnlokedRestoreFileList() const
for (int i = 0; i < files.size(); ++i) for (int i = 0; i < files.size(); ++i)
{ {
// Seeking file that realy need reopen // Seeking file that realy need reopen
QLockFile *lock = new QLockFile(files.at(i)+".lock"); VLockGuard<char> tmp(files.at(i)+".lock");
lock->setStaleLockTime(0); if (tmp.IsLocked())
if (VApplication::TryLock(lock))
{ {
restoreFiles.append(files.at(i)); restoreFiles.append(files.at(i));
} }
delete lock;
lock = nullptr;
} }
// Clearing list after filtering // Clearing list after filtering
@ -3230,7 +3253,6 @@ QStringList MainWindow::GetUnlokedRestoreFileList() const
} }
qApp->ValentinaSettings()->SetRestoreFileList(files); qApp->ValentinaSettings()->SetRestoreFileList(files);
} }
return restoreFiles; return restoreFiles;
#else #else

View file

@ -37,7 +37,7 @@
#include "tools/vtooluniondetails.h" #include "tools/vtooluniondetails.h"
#include "tools/drawTools/drawtools.h" #include "tools/drawTools/drawtools.h"
#include "core/vcmdexport.h" #include "core/vcmdexport.h"
#include <QLockFile> #include "../vmisc/vlockguard.h"
#include <QPointer> #include <QPointer>
#include <QFileSystemWatcher> #include <QFileSystemWatcher>
@ -48,9 +48,6 @@ namespace Ui
} }
class VToolOptionsPropertyBrowser; class VToolOptionsPropertyBrowser;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
class QLockFile;
#endif
/** /**
* @brief The MainWindow class main windows. * @brief The MainWindow class main windows.
@ -233,9 +230,7 @@ private:
QPointer<QLabel> gradationHeightsLabel; QPointer<QLabel> gradationHeightsLabel;
QPointer<QLabel> gradationSizesLabel; QPointer<QLabel> gradationSizesLabel;
VToolOptionsPropertyBrowser *toolOptions; VToolOptionsPropertyBrowser *toolOptions;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) VLockGuardPtr<char> lock;
QLockFile *lock;
#endif
void ToolBarOption(); void ToolBarOption();
void ToolBarStages(); void ToolBarStages();

View file

@ -344,7 +344,7 @@ INSTALL_TRANSLATIONS += \
$${TRANSLATIONS_PATH}/measurements_p9_fi_FI.qm \ $${TRANSLATIONS_PATH}/measurements_p9_fi_FI.qm \
$${TRANSLATIONS_PATH}/measurements_p9_en_US.qm $${TRANSLATIONS_PATH}/measurements_p9_en_US.qm
TRANSLATIONS += \ INSTALL_TRANSLATIONS += \
$${TRANSLATIONS_PATH}/measurements_p10_ru_RU.qm \ $${TRANSLATIONS_PATH}/measurements_p10_ru_RU.qm \
$${TRANSLATIONS_PATH}/measurements_p10_uk_UA.qm \ $${TRANSLATIONS_PATH}/measurements_p10_uk_UA.qm \
$${TRANSLATIONS_PATH}/measurements_p10_de_DE.qm \ $${TRANSLATIONS_PATH}/measurements_p10_de_DE.qm \

View file

@ -34,6 +34,10 @@
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:unique name="measurementName">
<xs:selector xpath="body-measurements/m"/>
<xs:field xpath="@name"/>
</xs:unique>
</xs:element> </xs:element>
<xs:simpleType name="shortName"> <xs:simpleType name="shortName">
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">

View file

@ -74,6 +74,10 @@
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:unique name="incrementName">
<xs:selector xpath="increment"/>
<xs:field xpath="@name"/>
</xs:unique>
</xs:element> </xs:element>
<xs:element name="draw" minOccurs="1" maxOccurs="unbounded"> <xs:element name="draw" minOccurs="1" maxOccurs="unbounded">
<xs:complexType> <xs:complexType>

View file

@ -35,6 +35,10 @@
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:unique name="measurementName">
<xs:selector xpath="body-measurements/m"/>
<xs:field xpath="@name"/>
</xs:unique>
</xs:element> </xs:element>
<xs:simpleType name="shortName"> <xs:simpleType name="shortName">
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">

View file

@ -1018,6 +1018,7 @@ QStringList VAbstractPattern::ListExpressions() const
list << ListPointExpressions(); list << ListPointExpressions();
list << ListArcExpressions(); list << ListArcExpressions();
list << ListSplineExpressions(); list << ListSplineExpressions();
list << ListIncrementExpressions();
return list; return list;
} }
@ -1176,6 +1177,28 @@ QStringList VAbstractPattern::ListPathPointExpressions() const
return expressions; return expressions;
} }
//---------------------------------------------------------------------------------------------------------------------
QStringList VAbstractPattern::ListIncrementExpressions() const
{
QStringList expressions;
const QDomNodeList list = elementsByTagName(TagIncrement);
for (int i=0; i < list.size(); ++i)
{
const QDomElement dom = list.at(i).toElement();
try
{
expressions.append(GetParametrString(dom, IncrementFormula));
}
catch (VExceptionEmptyParameter &e)
{
Q_UNUSED(e)
}
}
return expressions;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VAbstractPattern::IsVariable(const QString &token) const bool VAbstractPattern::IsVariable(const QString &token) const
{ {

View file

@ -248,6 +248,7 @@ private:
QStringList ListArcExpressions() const; QStringList ListArcExpressions() const;
QStringList ListSplineExpressions() const; QStringList ListSplineExpressions() const;
QStringList ListPathPointExpressions() const; QStringList ListPathPointExpressions() const;
QStringList ListIncrementExpressions() const;
bool IsVariable(const QString& token) const; bool IsVariable(const QString& token) const;
bool IsPostfixOperator(const QString& token) const; bool IsPostfixOperator(const QString& token) const;

128
src/libs/vmisc/debugbreak.h Normal file
View file

@ -0,0 +1,128 @@
/* Copyright (c) 2011-2015, Scott Tsai
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DEBUG_BREAK_H
#define DEBUG_BREAK_H
#ifdef _MSC_VER
#define debug_break __debugbreak
#else
#include <signal.h>
#ifdef __cplusplus
extern "C" {
#endif
enum {
/* gcc optimizers consider code after __builtin_trap() dead.
* Making __builtin_trap() unsuitable for breaking into the debugger */
DEBUG_BREAK_PREFER_BUILTIN_TRAP_TO_SIGTRAP = 0,
};
#if defined(__i386__) || defined(__x86_64__)
enum { HAVE_TRAP_INSTRUCTION = 1, };
__attribute__((gnu_inline, always_inline))
static void __inline__ trap_instruction(void)
{
__asm__ volatile("int $0x03");
}
#elif defined(__thumb__)
enum { HAVE_TRAP_INSTRUCTION = 1, };
/* FIXME: handle __THUMB_INTERWORK__ */
__attribute__((gnu_inline, always_inline))
static void __inline__ trap_instruction(void)
{
/* See 'arm-linux-tdep.c' in GDB source.
* Both instruction sequences below work. */
#if 1
/* 'eabi_linux_thumb_le_breakpoint' */
__asm__ volatile(".inst 0xde01");
#else
/* 'eabi_linux_thumb2_le_breakpoint' */
__asm__ volatile(".inst.w 0xf7f0a000");
#endif
/* Known problem:
* After a breakpoint hit, can't stepi, step, or continue in GDB.
* 'step' stuck on the same instruction.
*
* Workaround: a new GDB command,
* 'debugbreak-step' is defined in debugbreak-gdb.py
* that does:
* (gdb) set $instruction_len = 2
* (gdb) tbreak *($pc + $instruction_len)
* (gdb) jump *($pc + $instruction_len)
*/
}
#elif defined(__arm__) && !defined(__thumb__)
enum { HAVE_TRAP_INSTRUCTION = 1, };
__attribute__((gnu_inline, always_inline))
static void __inline__ trap_instruction(void)
{
/* See 'arm-linux-tdep.c' in GDB source,
* 'eabi_linux_arm_le_breakpoint' */
__asm__ volatile(".inst 0xe7f001f0");
/* Has same known problem and workaround
* as Thumb mode */
}
#elif defined(__aarch64__)
enum { HAVE_TRAP_INSTRUCTION = 1, };
__attribute__((gnu_inline, always_inline))
static void __inline__ trap_instruction(void)
{
/* See 'aarch64-tdep.c' in GDB source,
* 'aarch64_default_breakpoint' */
__asm__ volatile(".inst 0xd4200000");
}
#else
enum { HAVE_TRAP_INSTRUCTION = 0, };
#endif
__attribute__((gnu_inline, always_inline))
static void __inline__ debug_break(void)
{
if (HAVE_TRAP_INSTRUCTION) {
trap_instruction();
} else if (DEBUG_BREAK_PREFER_BUILTIN_TRAP_TO_SIGTRAP) {
/* raises SIGILL on Linux x86{,-64}, to continue in gdb:
* (gdb) handle SIGILL stop nopass
* */
__builtin_trap();
} else {
raise(SIGTRAP);
}
}
#ifdef __cplusplus
}
#endif
#endif
#endif

View file

@ -193,7 +193,7 @@ const QString neckSideToBustSideB_M = QStringLiteral("neck_side_to_bus
const QString shoulderTipToWaistB_1inOffset_M = QStringLiteral("shoulder_tip_to_waist_b_1in_offset"); // H13 const QString shoulderTipToWaistB_1inOffset_M = QStringLiteral("shoulder_tip_to_waist_b_1in_offset"); // H13
// I // I
const QString armShoulderTipToWristBent_M = QStringLiteral("arm_shoulder_tip_to_wrist_bent"); // I01 const QString armShoulderTipToWristBent_M = QStringLiteral("arm_shoulder_tip_to_wrist_bent"); // I01
const QString armShoulderTipToElbowBent_M = QStringLiteral(" arm_shoulder_tip_to_elbow_bent"); // I02 const QString armShoulderTipToElbowBent_M = QStringLiteral("arm_shoulder_tip_to_elbow_bent"); // I02
const QString armElbowToWristBent_M = QStringLiteral("arm_elbow_to_wrist_bent"); // I03 const QString armElbowToWristBent_M = QStringLiteral("arm_elbow_to_wrist_bent"); // I03
const QString armElbowCircBent_M = QStringLiteral("arm_elbow_circ_bent"); // I04 const QString armElbowCircBent_M = QStringLiteral("arm_elbow_circ_bent"); // I04
const QString armShoulderTipToWrist_M = QStringLiteral("arm_shoulder_tip_to_wrist"); // I05 const QString armShoulderTipToWrist_M = QStringLiteral("arm_shoulder_tip_to_wrist"); // I05

View file

@ -36,6 +36,8 @@
#include <windows.h> #include <windows.h>
#endif /* Q_OS_WIN */ #endif /* Q_OS_WIN */
#include "debugbreak.h"
#define SceneSize 50000 #define SceneSize 50000
#define DefPointRadius 1.5//mm #define DefPointRadius 1.5//mm
@ -160,43 +162,23 @@ enum class GSizes : unsigned char { ALL,
* https://stackoverflow.com/questions/1721543/continue-to-debug-after-failed-assertion-on-linux-c-c * https://stackoverflow.com/questions/1721543/continue-to-debug-after-failed-assertion-on-linux-c-c
*/ */
#ifndef V_NO_ASSERT #ifndef V_NO_ASSERT
#ifdef Q_OS_WIN32
#ifdef Q_CC_MSVC #ifdef Q_CC_MSVC
#define SCASSERT(cond) \ #define V_PRETTY_FUNCTION __FUNCSIG__
{ \ #else // GCC/Clang
if (!(cond)) \ #define V_PRETTY_FUNCTION __PRETTY_FUNCTION__
{ \
qDebug("ASSERT: %s in %s (%s:%u)", \
#cond, __FUNCSIG__, __FILE__, __LINE__); \
DebugBreak(); \
} \
} \
#else // GCC (Windows)
#define SCASSERT(cond) \
{ \
if (!(cond)) \
{ \
qDebug("ASSERT: %s in %s (%s:%u)", \
#cond, __PRETTY_FUNCTION__, __FILE__, __LINE__);\
DebugBreak(); \
} \
} \
#endif /*Q_CC_MSVC*/ #endif /*Q_CC_MSVC*/
#else // UNIX
#define SCASSERT(cond) \ #define SCASSERT(cond) \
{ \ { \
if (!(cond)) \ if (!(cond)) \
{ \ { \
qDebug("ASSERT: %s in %s (%s:%u)", \ qDebug("ASSERT: %s in %s (%s:%u)", \
#cond, __PRETTY_FUNCTION__, __FILE__, __LINE__);\ #cond, V_PRETTY_FUNCTION, __FILE__, __LINE__); \
std::raise(SIGTRAP); \ debug_break(); \
} \ } \
} \ } \
#endif /* Q_OS_WIN32 */
#else // define but disable this function if debugging is not set #else // define but disable this function if debugging is not set
#define SCASSERT(cond) qt_noop(); #define SCASSERT(cond) qt_noop();
#endif /* V_NO_ASSERT */ #endif /* V_NO_ASSERT */

View file

@ -29,10 +29,6 @@
#include "vabstractapplication.h" #include "vabstractapplication.h"
#include "../vmisc/def.h" #include "../vmisc/def.h"
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
# include <QLockFile>
#endif
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VAbstractApplication::VAbstractApplication(int &argc, char **argv) VAbstractApplication::VAbstractApplication(int &argc, char **argv)
:QApplication(argc, argv), :QApplication(argc, argv),
@ -116,43 +112,3 @@ double VAbstractApplication::fromPixel(double pix) const
{ {
return FromPixel(pix, _patternUnit); return FromPixel(pix, _patternUnit);
} }
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
//---------------------------------------------------------------------------------------------------------------------
bool VAbstractApplication::TryLock(QLockFile *lock)
{
if (lock == nullptr)
{
return false;
}
if (lock->tryLock())
{
return true;
}
else
{
if (lock->error() == QLockFile::LockFailedError)
{
// This happens if a stale lock file exists and another process uses that PID.
// Try removing the stale file, which will fail if a real process is holding a
// file-level lock. A false error is more problematic than not locking properly
// on corner-case systems.
if (lock->removeStaleLockFile() == false || lock->tryLock() == false)
{
return false;
}
else
{
return true;
}
}
else
{
return false;
}
return false;
}
}
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)

View file

@ -33,15 +33,13 @@
#include <QGraphicsScene> #include <QGraphicsScene>
#include "def.h" #include "def.h"
#include "vsettings.h" #include "vsettings.h"
#include "vlockguard.h"
class VAbstractApplication;// use in define class VAbstractApplication;// use in define
class VTranslateVars; class VTranslateVars;
class VAbstractPattern; class VAbstractPattern;
class VMainGraphicsView; class VMainGraphicsView;
class QUndoStack; class QUndoStack;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
class QLockFile;
#endif
#if defined(qApp) #if defined(qApp)
#undef qApp #undef qApp
@ -89,10 +87,6 @@ public:
QUndoStack *getUndoStack() const; QUndoStack *getUndoStack() const;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
static bool TryLock(QLockFile *lock);
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
protected: protected:
QUndoStack *undoStack; QUndoStack *undoStack;

200
src/libs/vmisc/vlockguard.h Normal file
View file

@ -0,0 +1,200 @@
/************************************************************************
**
** @file VLockGuard.h
** @author Alex Zaharov <alexzkhr@gmail.com>
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 14 9, 2015
**
** @brief
** @copyright
** This source code is part of the Valentine project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2015 Valentina project
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VLOCKGUARD_H
#define VLOCKGUARD_H
#include <QString>
#include <stdint.h>
#include <memory>
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
#include <QLockFile>
#define PEDANT_COMPILER ,lock(nullptr)
#else
#define PEDANT_COMPILER
#warning To have lock-file support you must use Qt 5.1+. Expect collissions when run 2 copies of the program.
#endif
/*@brief
* This class creates Guarded object if and only if lock file taken. It keeps shared_ptr to object and lock-file.
* Can use optional object allocator and deleter.
*
* On older Qt lock assumed always taken and compile-time warning is shown.
*
*/
template <typename Guarded>
class VLockGuard
{
public:
VLockGuard(const QString& lockName, int stale = 0, int timeout = 0);
template <typename Alloc>
VLockGuard(const QString& lockName, Alloc a, int stale = 0, int timeout=0);
template <typename Alloc, typename Delete>
VLockGuard(const QString& lockName, Alloc a, Delete d, int stale = 0, int timeout=0);
const std::shared_ptr<Guarded> &GetProtected() const;
int GetLockError() const;
bool IsLocked() const;
private:
Q_DISABLE_COPY(VLockGuard<Guarded>)
std::shared_ptr<Guarded> holder;
int lockError;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
std::shared_ptr<QLockFile> lock;
#endif
bool TryLock(const QString &lockName, int stale, int timeout);
};
//---------------------------------------------------------------------------------------------------------------------
template <typename Guarded>
VLockGuard<Guarded>::VLockGuard(const QString &lockName, int stale, int timeout)
: holder(nullptr), lockError(0) PEDANT_COMPILER
{
if (TryLock(lockName, stale, timeout))
{
holder.reset(new Guarded());
}
}
//---------------------------------------------------------------------------------------------------------------------
//using allocator lambdas seems logically better than supplying pointer, because we will take ownership of allocated
//object
template <typename Guarded> template <typename Alloc>
VLockGuard<Guarded>::VLockGuard(const QString& lockName, Alloc a, int stale, int timeout)
: holder(nullptr), lockError(0) PEDANT_COMPILER
{
if (TryLock(lockName, stale, timeout))
{
holder.reset(a());
}
}
//---------------------------------------------------------------------------------------------------------------------
template <typename Guarded> template <typename Alloc, typename Delete>
VLockGuard<Guarded>::VLockGuard(const QString& lockName, Alloc a, Delete d, int stale, int timeout)
: holder(nullptr), lockError(0) PEDANT_COMPILER
{
if (TryLock(lockName, stale, timeout))
{
holder.reset(a(), d);
}
}
//---------------------------------------------------------------------------------------------------------------------
template <typename Guarded>
const std::shared_ptr<Guarded> &VLockGuard<Guarded>::GetProtected() const
{
return holder;
}
//---------------------------------------------------------------------------------------------------------------------
template <typename Guarded>
int VLockGuard<Guarded>::GetLockError() const
{
return lockError;
}
//---------------------------------------------------------------------------------------------------------------------
template <typename Guarded>
bool VLockGuard<Guarded>::IsLocked() const
{
return holder != nullptr;
}
//---------------------------------------------------------------------------------------------------------------------
template <typename Guarded>
bool VLockGuard<Guarded>::TryLock(const QString &lockName, int stale, int timeout)
{
bool res = true;
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
lock.reset(new QLockFile(lockName));
lock->setStaleLockTime(stale);
for (int i = 0; i < 2 && !lock->tryLock(timeout); i++)
{
if (QLockFile::LockFailedError != lock->error())
{
break;
}
else
{
// This happens if a stale lock file exists and another process uses that PID.
// Try removing the stale file, which will fail if a real process is holding a
// file-level lock. A false error is more problematic than not locking properly
// on corner-case systems.
lock->removeStaleLockFile();
lock->tryLock(timeout);
}
}
res = QLockFile::NoError == (lockError = lock->error());
if (!res)
{
lock.reset();
}
#endif
return res;
}
#undef PEDANT_COMPILER
//use pointer and function below to persistent things like class-member, because lock is taken by constructor
//helper functions allow to write shorter creating and setting new lock-pointer
//new C++11 - "template typedef" http://stackoverflow.com/questions/2795023/c-template-typedef
template <typename Guarded>
using VLockGuardPtr = std::shared_ptr<VLockGuard<Guarded>>;
template <typename Guarded>
void VlpCreateLock(VLockGuardPtr<Guarded>& r, const QString& lockName, int stale = 0, int timeout = 0)
{
r.reset(new VLockGuard<Guarded>(lockName, stale, timeout));
}
template <typename Guarded, typename Alloc>
void VlpCreateLock(VLockGuardPtr<Guarded>& r, const QString& lockName, Alloc a, int stale = 0, int timeout = 0)
{
r.reset(new VLockGuard<Guarded>(lockName, a, stale, timeout));
}
template <typename Guarded, typename Alloc, typename Del>
void VlpCreateLock(VLockGuardPtr<Guarded>& r, const QString& lockName, Alloc a, Del d, int stale = 0, int timeout = 0)
{
r.reset(new VLockGuard<Guarded>(lockName, a, d, stale, timeout));
}
#endif // VLOCKGUARD_H

View file

@ -25,4 +25,6 @@ HEADERS += \
$$PWD/vabstractapplication.h \ $$PWD/vabstractapplication.h \
$$PWD/projectversion.h \ $$PWD/projectversion.h \
$$PWD/vcommonsettings.h \ $$PWD/vcommonsettings.h \
$$PWD/vtapesettings.h $$PWD/vtapesettings.h \
$$PWD/debugbreak.h \
$$PWD/vlockguard.h

View file

@ -31,14 +31,13 @@
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
DeletePatternPiece::DeletePatternPiece(VAbstractPattern *doc, const QString &namePP, QUndoCommand *parent) DeletePatternPiece::DeletePatternPiece(VAbstractPattern *doc, const QString &namePP, QUndoCommand *parent)
: VUndoCommand(QDomElement(), doc, parent), namePP(namePP), patternPiece(QDomElement()), mPath(QString()), : VUndoCommand(QDomElement(), doc, parent), namePP(namePP), patternPiece(QDomElement()),
previousPPName(QString()) previousPPName(QString())
{ {
setText(tr("delete pattern piece %1").arg(namePP)); setText(tr("delete pattern piece %1").arg(namePP));
QDomElement patternP = doc->GetPPElement(namePP); QDomElement patternP = doc->GetPPElement(namePP);
patternPiece = patternP.cloneNode().toElement(); patternPiece = patternP.cloneNode().toElement();
mPath = doc->MPath();
QDomNode previousPP = patternP.previousSibling();//find previous pattern piece QDomNode previousPP = patternP.previousSibling();//find previous pattern piece
previousPPName = doc->GetParametrString(previousPP.toElement(), VAbstractPattern::AttrName, ""); previousPPName = doc->GetParametrString(previousPP.toElement(), VAbstractPattern::AttrName, "");
} }

View file

@ -43,7 +43,6 @@ private:
Q_DISABLE_COPY(DeletePatternPiece) Q_DISABLE_COPY(DeletePatternPiece)
QString namePP; QString namePP;
QDomElement patternPiece; QDomElement patternPiece;
QString mPath;
QString previousPPName; QString previousPPName;
}; };

View file

@ -31,6 +31,9 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QTimer> #include <QTimer>
#include <QLabel>
#include "../vmisc/def.h"
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VWidgetPopup::VWidgetPopup(QWidget *parent) VWidgetPopup::VWidgetPopup(QWidget *parent)
@ -77,6 +80,22 @@ void VWidgetPopup::SetWidget(QWidget *widget, bool own)
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void VWidgetPopup::PopupMessage(QWidget *w, const QString &msg)
{
SCASSERT(w != nullptr);
VWidgetPopup *popup = new VWidgetPopup();
QLabel *label = new QLabel(msg);
QFont f = label->font();
f.setBold(true);
f.setPixelSize(16);
label->setFont(f);
popup->SetWidget(label);
popup->SetLifeTime(2000);
popup->Show(w->frameGeometry().center());
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VWidgetPopup::Show(QPoint coord) void VWidgetPopup::Show(QPoint coord)
{ {

View file

@ -67,6 +67,8 @@ public:
int GetLifeTime() const; int GetLifeTime() const;
void SetLifeTime(int value); void SetLifeTime(int value);
static void PopupMessage(QWidget *w, const QString &msg);
public slots: public slots:
/** Pops up the widget at global coordinates \a coord. */ /** Pops up the widget at global coordinates \a coord. */
void Show(QPoint coord); void Show(QPoint coord);

View file

@ -42,7 +42,8 @@ SOURCES += \
tst_nameregexp.cpp \ tst_nameregexp.cpp \
tst_vlayoutdetail.cpp \ tst_vlayoutdetail.cpp \
tst_varc.cpp \ tst_varc.cpp \
stable.cpp stable.cpp \
tst_measurementregexp.cpp
HEADERS += \ HEADERS += \
tst_vposter.h \ tst_vposter.h \
@ -52,7 +53,8 @@ HEADERS += \
tst_nameregexp.h \ tst_nameregexp.h \
tst_vlayoutdetail.h \ tst_vlayoutdetail.h \
tst_varc.h \ tst_varc.h \
stable.h stable.h \
tst_measurementregexp.h
# Set using ccache. Function enable_ccache() defined in common.pri. # Set using ccache. Function enable_ccache() defined in common.pri.
$$enable_ccache() $$enable_ccache()
@ -115,6 +117,42 @@ CONFIG(debug, debug|release){
} }
} }
#VPatternDB static library (depend on vgeometry, vmisc, VLayout)
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vpatterndb/$${DESTDIR} -lvpatterndb
INCLUDEPATH += $$PWD/../../libs/vpatterndb
DEPENDPATH += $$PWD/../../libs/vpatterndb
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vpatterndb/$${DESTDIR}/vpatterndb.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vpatterndb/$${DESTDIR}/libvpatterndb.a
#VMisc static library
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vmisc/$${DESTDIR}/ -lvmisc
INCLUDEPATH += $$PWD/../../libs/vmisc
DEPENDPATH += $$PWD/../../libs/vmisc
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vmisc/$${DESTDIR}/vmisc.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vmisc/$${DESTDIR}/libvmisc.a
# VGeometry static library (depend on ifc)
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vgeometry/$${DESTDIR} -lvgeometry
INCLUDEPATH += $$PWD/../../libs/vgeometry
DEPENDPATH += $$PWD/../../libs/vgeometry
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/vgeometry.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/libvgeometry.a
# IFC static library (depend on QMuParser)
unix|win32: LIBS += -L$$OUT_PWD/../../libs/ifc/$${DESTDIR}/ -lifc
INCLUDEPATH += $$PWD/../../libs/ifc
DEPENDPATH += $$PWD/../../libs/ifc
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/ifc/$${DESTDIR}/ifc.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/ifc/$${DESTDIR}/libifc.a
# VLayout static library # VLayout static library
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vlayout/$${DESTDIR} -lvlayout unix|win32: LIBS += -L$$OUT_PWD/../../libs/vlayout/$${DESTDIR} -lvlayout
@ -124,11 +162,10 @@ DEPENDPATH += $$PWD/../../libs/vlayout
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/vlayout.lib win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/vlayout.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/libvlayout.a else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/libvlayout.a
# VGeometry static library # QMuParser library
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vgeometry/$${DESTDIR} -lvgeometry win32:CONFIG(release, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
else:win32:CONFIG(debug, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
else:unix: LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser
INCLUDEPATH += $$PWD/../../libs/vgeometry INCLUDEPATH += $${PWD}/../../libs/qmuparser
DEPENDPATH += $$PWD/../../libs/vgeometry DEPENDPATH += $${PWD}/../../libs/qmuparser
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/vgeometry.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/libvgeometry.a

View file

@ -34,6 +34,7 @@
#include "tst_nameregexp.h" #include "tst_nameregexp.h"
#include "tst_vlayoutdetail.h" #include "tst_vlayoutdetail.h"
#include "tst_varc.h" #include "tst_varc.h"
#include "tst_measurementregexp.h"
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@ -52,6 +53,7 @@ int main(int argc, char** argv)
ASSERT_TEST(new TST_NameRegExp()); ASSERT_TEST(new TST_NameRegExp());
ASSERT_TEST(new TST_VLayoutDetail()); ASSERT_TEST(new TST_VLayoutDetail());
ASSERT_TEST(new TST_VArc()); ASSERT_TEST(new TST_VArc());
ASSERT_TEST(new TST_MeasurementRegExp());
return status; return status;
} }

View file

@ -0,0 +1,234 @@
/************************************************************************
**
** @file tst_measurementregexp.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 16 9, 2015
**
** @brief
** @copyright
** This source code is part of the Valentine project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2015 Valentina project
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "tst_measurementregexp.h"
#include "../qmuparser/qmudef.h"
#include "../vmisc/def.h"
#include "../vpatterndb/vtranslatemeasurements.h"
#include <QtTest>
#include <QTranslator>
enum ErrorState {ErrorLoad = 0, ErrorInstall, ErrorSize, NoError};
//---------------------------------------------------------------------------------------------------------------------
TST_MeasurementRegExp::TST_MeasurementRegExp(QObject *parent)
:QObject(parent),
pmsTranslator(nullptr),
trMs(nullptr)
{
}
//---------------------------------------------------------------------------------------------------------------------
TST_MeasurementRegExp::~TST_MeasurementRegExp()
{
delete pmsTranslator;
delete trMs;
}
//---------------------------------------------------------------------------------------------------------------------
// cppcheck-suppress unusedFunction
void TST_MeasurementRegExp::TestOriginalMeasurementNamesRegExp()
{
const QStringList originalNames = OriginalNames();
const QRegularExpression re(NameRegExp());
foreach(const QString &str, originalNames)
{
QCOMPARE(re.match(str).hasMatch(), true);
}
}
//---------------------------------------------------------------------------------------------------------------------
// cppcheck-suppress unusedFunction
void TST_MeasurementRegExp::TestMeasurementRegExp()
{
const int systemCounts = 55;
const QStringList locales {"ru_RU", "uk_UA", "de_DE", "cs_CZ", "he_IL", "fr_FR", "it_IT", "nl_NL", "id_ID",
"es_ES", "fi_FI", "en_US"};
{
const int combinations = systemCounts * locales.size(); // 55*12=660
QDir dir(TranslationsPath());
const QStringList fileNames = dir.entryList(QStringList("measurements_p*_*.qm"));
QVERIFY2(combinations == fileNames.size(), "Unexpected count of files.");
}
for(int s = 0; s < systemCounts; ++s)
{
for(int l = 0, sz = locales.size(); l < sz; ++l)
{
const int res = LoadTranslation(QString("p%1").arg(s), locales.at(l));
switch(res)
{
case ErrorInstall:
case ErrorSize:
case ErrorLoad:
{
const QString message = QString("Failed to check translation for system = p%1 and locale = %2")
.arg(s)
.arg(locales.at(l));
QFAIL(message.toUtf8().constData());
break;
}
case NoError:
{
CheckNames();
if (not pmsTranslator.isNull())
{
const bool result = QCoreApplication::removeTranslator(pmsTranslator);
if (result == false)
{
const QString message = QString("Can't remove translation for system = p%1 and locale = %2")
.arg(s)
.arg(locales.at(l));
QWARN(message.toUtf8().constData());
}
delete pmsTranslator;
}
}
default:
QWARN("Unexpected state");
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
QString TST_MeasurementRegExp::TranslationsPath() const
{
return QApplication::applicationDirPath() + QStringLiteral("/../../../app/valentina/bin/translations");
}
//---------------------------------------------------------------------------------------------------------------------
int TST_MeasurementRegExp::LoadTranslation(const QString &checkedSystem, const QString &checkedLocale)
{
const QString path = TranslationsPath();
const QString file = QString("measurements_%1_%2.qm").arg(checkedSystem).arg(checkedLocale);
if (QFileInfo(path+"/"+file).size() <= 34)
{
const QString message = QString("Translation for system = %1 and locale = %2 is empty. \nFull path: %3/%4")
.arg(checkedSystem)
.arg(checkedLocale)
.arg(path)
.arg(file);
QWARN(message.toUtf8().constData());
return ErrorSize;
}
pmsTranslator = new QTranslator(this);
if (not pmsTranslator->load(file, path))
{
const QString message = QString("Can't load translation for system = %1 and locale = %2. \nFull path: %3/%4")
.arg(checkedSystem)
.arg(checkedLocale)
.arg(path)
.arg(file);
QWARN(message.toUtf8().constData());
delete pmsTranslator;
return ErrorLoad;
}
if (not QCoreApplication::installTranslator(pmsTranslator))
{
const QString message = QString("Can't install translation for system = %1 and locale = %2. \nFull path: %3/%4")
.arg(checkedSystem)
.arg(checkedLocale)
.arg(path)
.arg(file);
QWARN(message.toUtf8().constData());
delete pmsTranslator;
return ErrorInstall;
}
InitTrMs();//Very important do it after load QM file.
return NoError;
}
//---------------------------------------------------------------------------------------------------------------------
void TST_MeasurementRegExp::InitTrMs()
{
if (trMs != nullptr)
{
trMs->Retranslate();
}
else
{
trMs = new VTranslateMeasurements();
}
}
//---------------------------------------------------------------------------------------------------------------------
void TST_MeasurementRegExp::CheckNames() const
{
const QStringList originalNames = OriginalNames();
const QRegularExpression re(NameRegExp());
foreach(const QString &str, originalNames)
{
const QString translated = trMs->MToUser(str);
QCOMPARE(re.match(translated).hasMatch(), true);
}
}
//---------------------------------------------------------------------------------------------------------------------
QStringList TST_MeasurementRegExp::OriginalNames() const
{
const QStringList originalNames = QStringList() << ListGroupA()
<< ListGroupB()
<< ListGroupC()
<< ListGroupD()
<< ListGroupE()
<< ListGroupF()
<< ListGroupG()
<< ListGroupH()
<< ListGroupI()
<< ListGroupJ()
<< ListGroupK()
<< ListGroupL()
<< ListGroupM()
<< ListGroupN()
<< ListGroupO()
<< ListGroupP()
<< ListGroupQ();
return originalNames;
}

View file

@ -0,0 +1,61 @@
/************************************************************************
**
** @file tst_measurementregexp.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 16 9, 2015
**
** @brief
** @copyright
** This source code is part of the Valentine project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2015 Valentina project
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef TST_MEASUREMENTREGEXP_H
#define TST_MEASUREMENTREGEXP_H
#include <QObject>
class QTranslator;
class VTranslateMeasurements;
class TST_MeasurementRegExp : public QObject
{
Q_OBJECT
public:
explicit TST_MeasurementRegExp(QObject *parent = 0);
virtual ~TST_MeasurementRegExp() Q_DECL_OVERRIDE;
private slots:
void TestOriginalMeasurementNamesRegExp();
void TestMeasurementRegExp();
private:
Q_DISABLE_COPY(TST_MeasurementRegExp)
QPointer<QTranslator> pmsTranslator;
VTranslateMeasurements *trMs;
QString TranslationsPath() const;
int LoadTranslation(const QString &checkedSystem, const QString &checkedLocale);
void InitTrMs();
void CheckNames() const;
QStringList OriginalNames() const;
};
#endif // TST_MEASUREMENTREGEXP_H