mirror of
https://github.com/leozide/leocad.git
synced 2026-10-26 22:10:32 +00:00
Validate localized numeric input and unify image limits
Parse dialog numbers using their validator locale so localized decimals and grouped input round trip correctly, while displaying values without digit grouping. Keep invalid input open with a validation message instead of silently saving or clamping it, and serialize Blender settings in their canonical format. Use a 1–32768 pixel range for image dimensions across Save Image, HTML export, command-line output, POV-Ray, and Blender. Bound export step edits by the model step count, grid spacing to 10000 studs, and area-light grids to 64 samples per axis. Preserve existing show/hide step bounds and avoid a total-pixel cap. Validation: macOS Qt debug build and numeric dialog checks across ten locales, including localized input, validation messages, image dimension boundaries, and settings round trips.
This commit is contained in:
1 parent
513e556ce9
commit
2125868dc6
12 files changed
+198
-78
No files matched your search
@@ -12,6 +12,7 @@
|
||||
#include "camera.h"
|
||||
#include "lc_previewwidget.h"
|
||||
#include "lc_colors.h"
|
||||
#include "lc_qutils.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
@@ -579,9 +580,9 @@ lcCommandLineOptions lcApplication::ParseCommandLineOptions()
|
||||
ParseString(Options.ImageName, false);
|
||||
}
|
||||
else if (Option == QLatin1String("-w") || Option == QLatin1String("--width"))
|
||||
ParseInteger(Options.ImageWidth, 1, INT_MAX);
|
||||
ParseInteger(Options.ImageWidth, 1, LC_MAX_IMAGE_DIMENSION);
|
||||
else if (Option == QLatin1String("-h") || Option == QLatin1String("--height"))
|
||||
ParseInteger(Options.ImageHeight, 1, INT_MAX);
|
||||
ParseInteger(Options.ImageHeight, 1, LC_MAX_IMAGE_DIMENSION);
|
||||
else if (Option == QLatin1String("-f") || Option == QLatin1String("--from"))
|
||||
ParseUnsigned(Options.ImageStart, 1, LC_STEP_MAX);
|
||||
else if (Option == QLatin1String("-t") || Option == QLatin1String("--to"))
|
||||
|
||||
@@ -320,6 +320,16 @@ void lcBlenderPreferencesDialog::ResetSettings()
|
||||
|
||||
void lcBlenderPreferencesDialog::accept()
|
||||
{
|
||||
for (QLineEdit* Edit : findChildren<QLineEdit*>())
|
||||
{
|
||||
if (Edit->isEnabled() && !Edit->isReadOnly() && Edit->validator() && !Edit->hasAcceptableInput())
|
||||
{
|
||||
QMessageBox::information(this, windowTitle(), tr("Please enter a valid value for '%1'.").arg(Edit->accessibleName()));
|
||||
Edit->setFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mApplyButton->setEnabled(false);
|
||||
mPreferences->Apply(QDialog::Accepted);
|
||||
QDialog::accept();
|
||||
@@ -649,7 +659,7 @@ void lcBlenderPreferences::InitPathsAndSettings()
|
||||
mSettingsBox = new QGroupBox(mContent);
|
||||
mSettingsSubform = new QFormLayout(mSettingsBox);
|
||||
mSettingsBox->setLayout(mSettingsSubform);
|
||||
mSettingsBox->setWhatsThis(tr("<p><b>Import and Render Settings</b></p><p>Adjust the selected importer's geometry, materials, camera, and image options. Hover over a control or press F1 for its description. Image width and height are in pixels; render percentage scales the output dimensions.</p>"));
|
||||
mSettingsBox->setWhatsThis(tr("<p><b>Import and Render Settings</b></p><p>Adjust the selected importer's geometry, materials, camera, and image options. Hover over a control or press F1 for its description. Image width and height are in pixels, from 1 to 32768; render percentage scales the output dimensions.</p>"));
|
||||
mForm->addRow(mSettingsBox);
|
||||
|
||||
mSettingsBox->setTitle(tr("LDraw Import TN Add-on Settings"));
|
||||
@@ -688,7 +698,7 @@ void lcBlenderPreferences::InitPathsAndSettings()
|
||||
if (LblIdx == LBL_IMAGE_WIDTH || LblIdx == LBL_IMAGE_HEIGHT)
|
||||
{
|
||||
connect(LineEdit, &QLineEdit::textChanged, this, &lcBlenderPreferences::SizeChanged);
|
||||
LineEdit->setValidator(new QIntValidator(16, LC_RENDER_IMAGE_MAX_SIZE));
|
||||
LineEdit->setValidator(new QIntValidator(1, LC_MAX_IMAGE_DIMENSION));
|
||||
}
|
||||
else if(LblIdx == LBL_DEFAULT_COLOUR)
|
||||
{
|
||||
@@ -699,13 +709,13 @@ void lcBlenderPreferences::InitPathsAndSettings()
|
||||
}
|
||||
else
|
||||
{
|
||||
LineEdit->setText(mBlenderSettings[LblIdx].value);
|
||||
if (LblIdx == LBL_IMAGE_SCALE)
|
||||
LineEdit->setValidator(new QDoubleValidator(0.01,10.0,2));
|
||||
else if (LblIdx == LBL_RENDER_PERCENTAGE || LblIdx == LBL_CAMERA_BORDER_PERCENT)
|
||||
LineEdit->setValidator(new QIntValidator(1,1000));
|
||||
else
|
||||
LineEdit->setValidator(new QDoubleValidator(0.01,100.0,2));
|
||||
SetNumericText(LineEdit, mBlenderSettings[LblIdx].value);
|
||||
connect(LineEdit, &QLineEdit::textEdited, this, &lcBlenderPreferences::SettingTextChanged);
|
||||
}
|
||||
LineEdit->setToolTip(mBlenderSettings[LblIdx].tooltip);
|
||||
@@ -806,7 +816,7 @@ void lcBlenderPreferences::InitPathsAndSettingsMM()
|
||||
mSettingsBox = new QGroupBox(mContent);
|
||||
mSettingsSubform = new QFormLayout(mSettingsBox);
|
||||
mSettingsBox->setLayout(mSettingsSubform);
|
||||
mSettingsBox->setWhatsThis(tr("<p><b>Import and Render Settings</b></p><p>Adjust the selected importer's geometry, materials, camera, and image options. Hover over a control or press F1 for its description. Image width and height are in pixels; render percentage scales the output dimensions.</p>"));
|
||||
mSettingsBox->setWhatsThis(tr("<p><b>Import and Render Settings</b></p><p>Adjust the selected importer's geometry, materials, camera, and image options. Hover over a control or press F1 for its description. Image width and height are in pixels, from 1 to 32768; render percentage scales the output dimensions.</p>"));
|
||||
mForm->addRow(mSettingsBox);
|
||||
|
||||
mSettingsBox->setTitle(tr("LDraw Import MM Add-on Settings"));
|
||||
@@ -845,11 +855,10 @@ void lcBlenderPreferences::InitPathsAndSettingsMM()
|
||||
if (LblIdx == LBL_RESOLUTION_WIDTH || LblIdx == LBL_RESOLUTION_HEIGHT)
|
||||
{
|
||||
connect(LineEdit, &QLineEdit::textChanged, this, &lcBlenderPreferences::SizeChanged);
|
||||
LineEdit->setValidator(new QIntValidator(16, LC_RENDER_IMAGE_MAX_SIZE));
|
||||
LineEdit->setValidator(new QIntValidator(1, LC_MAX_IMAGE_DIMENSION));
|
||||
}
|
||||
else
|
||||
{
|
||||
LineEdit->setText(mBlenderSettingsMM[LblIdx].value);
|
||||
if (LblIdx == LBL_IMPORT_SCALE)
|
||||
LineEdit->setValidator(new QDoubleValidator(0.01,10.0,2));
|
||||
else if (LblIdx == LBL_RENDER_PERCENTAGE_MM || LblIdx == LBL_CAMERA_BORDER_PERCENT_MM)
|
||||
@@ -860,6 +869,7 @@ void lcBlenderPreferences::InitPathsAndSettingsMM()
|
||||
LineEdit->setValidator(new QDoubleValidator(0.0,10.0,1));
|
||||
else
|
||||
LineEdit->setValidator(new QIntValidator(1, LC_RENDER_IMAGE_MAX_SIZE));
|
||||
SetNumericText(LineEdit, mBlenderSettingsMM[LblIdx].value);
|
||||
connect(LineEdit, &QLineEdit::textEdited, this, &lcBlenderPreferences::SettingTextChanged);
|
||||
}
|
||||
LineEdit->setToolTip(mBlenderSettingsMM[LblIdx].tooltip);
|
||||
@@ -1742,6 +1752,43 @@ void lcBlenderPreferences::ShowResult()
|
||||
mProcess = nullptr;
|
||||
}
|
||||
|
||||
void lcBlenderPreferences::SetNumericText(QLineEdit* Edit, const QString& Value)
|
||||
{
|
||||
const QValidator* Validator = Edit->validator();
|
||||
QLocale Locale = Validator->locale();
|
||||
Locale.setNumberOptions(Locale.numberOptions() | QLocale::OmitGroupSeparator);
|
||||
bool Ok;
|
||||
QString Text;
|
||||
|
||||
if (qobject_cast<const QIntValidator*>(Validator))
|
||||
{
|
||||
const int Number = Value.toInt(&Ok);
|
||||
Text = Locale.toString(Number);
|
||||
}
|
||||
else
|
||||
{
|
||||
const double Number = Value.toDouble(&Ok);
|
||||
Text = Locale.toString(Number, 'g', QLocale::FloatingPointShortest);
|
||||
}
|
||||
|
||||
Edit->setText(Ok ? Text : Value);
|
||||
}
|
||||
|
||||
double lcBlenderPreferences::GetNumericValue(const QLineEdit* Edit, bool& Ok)
|
||||
{
|
||||
Ok = false;
|
||||
|
||||
if (!Edit->hasAcceptableInput())
|
||||
return 0.0;
|
||||
|
||||
const QValidator* Validator = Edit->validator();
|
||||
|
||||
if (qobject_cast<const QIntValidator*>(Validator))
|
||||
return Validator->locale().toInt(Edit->text(), &Ok);
|
||||
|
||||
return Validator->locale().toDouble(Edit->text(), &Ok);
|
||||
}
|
||||
|
||||
void lcBlenderPreferences::SettingTextChanged(const QString& Value)
|
||||
{
|
||||
bool Change = false;
|
||||
@@ -2135,7 +2182,7 @@ bool lcBlenderPreferences::SettingsModified(bool Update, const QString& Module)
|
||||
if (CtlIdx == CTL_RESOLUTION_WIDTH_EDIT)
|
||||
{
|
||||
_OldValue = Width;
|
||||
_Width = gAddonPreferences->mLineEditList[CtlIdx]->text().toDouble(&Ok);
|
||||
_Width = GetNumericValue(gAddonPreferences->mLineEditList[CtlIdx], Ok);
|
||||
if (Ok)
|
||||
{
|
||||
if (Update)
|
||||
@@ -2149,7 +2196,7 @@ bool lcBlenderPreferences::SettingsModified(bool Update, const QString& Module)
|
||||
else if (CtlIdx == CTL_RESOLUTION_HEIGHT_EDIT)
|
||||
{
|
||||
_OldValue = Height;
|
||||
_Height = gAddonPreferences->mLineEditList[CtlIdx]->text().toDouble(&Ok);
|
||||
_Height = GetNumericValue(gAddonPreferences->mLineEditList[CtlIdx], Ok);
|
||||
if (Ok)
|
||||
{
|
||||
if (Update)
|
||||
@@ -2163,7 +2210,7 @@ bool lcBlenderPreferences::SettingsModified(bool Update, const QString& Module)
|
||||
else if (CtlIdx == CTL_RENDER_PERCENTAGE_EDIT_MM)
|
||||
{
|
||||
_OldValue = Scale;
|
||||
_Scale = gAddonPreferences->mLineEditList[CtlIdx]->text().toInt(&Ok);
|
||||
_Scale = GetNumericValue(gAddonPreferences->mLineEditList[CtlIdx], Ok);
|
||||
if (Ok)
|
||||
{
|
||||
if (Update)
|
||||
@@ -2177,7 +2224,7 @@ bool lcBlenderPreferences::SettingsModified(bool Update, const QString& Module)
|
||||
else
|
||||
{
|
||||
_OldValue = mBlenderSettingsMM[LblIdx].value.toDouble();
|
||||
_Value = gAddonPreferences->mLineEditList[CtlIdx]->text().toDouble(&Ok);
|
||||
_Value = GetNumericValue(gAddonPreferences->mLineEditList[CtlIdx], Ok);
|
||||
if (Ok)
|
||||
{
|
||||
if (Update)
|
||||
@@ -2230,7 +2277,7 @@ bool lcBlenderPreferences::SettingsModified(bool Update, const QString& Module)
|
||||
if (CtlIdx == CTL_IMAGE_WIDTH_EDIT)
|
||||
{
|
||||
_OldValue = Width;
|
||||
_Width = gAddonPreferences->mLineEditList[CtlIdx]->text().toDouble(&Ok);
|
||||
_Width = GetNumericValue(gAddonPreferences->mLineEditList[CtlIdx], Ok);
|
||||
if (Ok)
|
||||
{
|
||||
if (Update)
|
||||
@@ -2244,7 +2291,7 @@ bool lcBlenderPreferences::SettingsModified(bool Update, const QString& Module)
|
||||
else if (CtlIdx == CTL_IMAGE_HEIGHT_EDIT)
|
||||
{
|
||||
_OldValue = Height;
|
||||
_Height = gAddonPreferences->mLineEditList[CtlIdx]->text().toDouble(&Ok);
|
||||
_Height = GetNumericValue(gAddonPreferences->mLineEditList[CtlIdx], Ok);
|
||||
if (Ok)
|
||||
{
|
||||
if (Update)
|
||||
@@ -2258,7 +2305,7 @@ bool lcBlenderPreferences::SettingsModified(bool Update, const QString& Module)
|
||||
else if (CtlIdx == CTL_RENDER_PERCENTAGE_EDIT)
|
||||
{
|
||||
_OldValue = Scale;
|
||||
_Scale = gAddonPreferences->mLineEditList[CtlIdx]->text().toInt(&Ok);
|
||||
_Scale = GetNumericValue(gAddonPreferences->mLineEditList[CtlIdx], Ok);
|
||||
if (Ok)
|
||||
{
|
||||
if (Update)
|
||||
@@ -2279,7 +2326,7 @@ bool lcBlenderPreferences::SettingsModified(bool Update, const QString& Module)
|
||||
else
|
||||
{
|
||||
_OldValue = mBlenderSettings[LblIdx].value.toDouble();
|
||||
_Value = gAddonPreferences->mLineEditList[CtlIdx]->text().toDouble(&Ok);
|
||||
_Value = GetNumericValue(gAddonPreferences->mLineEditList[CtlIdx], Ok);
|
||||
}
|
||||
if (Ok)
|
||||
{
|
||||
@@ -2401,15 +2448,15 @@ void lcBlenderPreferences::ResetSettings()
|
||||
for (int CtlIdx = 0; CtlIdx < mLineEditList.size(); CtlIdx++)
|
||||
{
|
||||
if (CtlIdx == CTL_IMAGE_WIDTH_EDIT)
|
||||
mLineEditList[CtlIdx]->setText(QString::number(mImageWidth));
|
||||
SetNumericText(mLineEditList[CtlIdx], QString::number(mImageWidth));
|
||||
else if (CtlIdx == CTL_IMAGE_HEIGHT_EDIT)
|
||||
mLineEditList[CtlIdx]->setText(QString::number(mImageHeight));
|
||||
SetNumericText(mLineEditList[CtlIdx], QString::number(mImageHeight));
|
||||
else if (CtlIdx == CTL_RENDER_PERCENTAGE_EDIT)
|
||||
mLineEditList[CtlIdx]->setText(QString::number(mScale * 100));
|
||||
SetNumericText(mLineEditList[CtlIdx], QString::number(mScale * 100));
|
||||
else if (CtlIdx == CTL_DEFAULT_COLOUR_EDIT)
|
||||
SetDefaultColor(lcGetColorIndex(Settings[LBL_DEFAULT_COLOUR].value.toInt()));
|
||||
else
|
||||
mLineEditList[CtlIdx]->setText(Settings[LblIdx].value);
|
||||
SetNumericText(mLineEditList[CtlIdx], Settings[LblIdx].value);
|
||||
if (LblIdx < LBL_RENDER_PERCENTAGE)
|
||||
LblIdx++;
|
||||
}
|
||||
@@ -2453,13 +2500,13 @@ void lcBlenderPreferences::ResetSettings()
|
||||
for (int CtlIdx = 0; CtlIdx < mLineEditList.size(); CtlIdx++)
|
||||
{
|
||||
if (CtlIdx == CTL_RESOLUTION_WIDTH_EDIT)
|
||||
mLineEditList[CtlIdx]->setText(QString::number(mImageWidth));
|
||||
SetNumericText(mLineEditList[CtlIdx], QString::number(mImageWidth));
|
||||
else if (CtlIdx == CTL_RESOLUTION_HEIGHT_EDIT)
|
||||
mLineEditList[CtlIdx]->setText(QString::number(mImageHeight));
|
||||
SetNumericText(mLineEditList[CtlIdx], QString::number(mImageHeight));
|
||||
else if (CtlIdx == CTL_RENDER_PERCENTAGE_EDIT_MM)
|
||||
mLineEditList[CtlIdx]->setText(QString::number(mScale * 100));
|
||||
SetNumericText(mLineEditList[CtlIdx], QString::number(mScale * 100));
|
||||
else
|
||||
mLineEditList[CtlIdx]->setText(SettingsMM[LblIdx].value);
|
||||
SetNumericText(mLineEditList[CtlIdx], SettingsMM[LblIdx].value);
|
||||
if (LblIdx < LBL_STARTING_STEP_FRAME)
|
||||
LblIdx++;
|
||||
}
|
||||
@@ -3000,7 +3047,7 @@ void lcBlenderPreferences::BrowseBlender(bool)
|
||||
}
|
||||
}
|
||||
|
||||
void lcBlenderPreferences::SizeChanged(const QString& Value)
|
||||
void lcBlenderPreferences::SizeChanged(const QString&)
|
||||
{
|
||||
const bool ImportMM = mImportMMActBox->isChecked();
|
||||
const int Keep_Aspect_Ratio = ImportMM ? int(CTL_KEEP_ASPECT_RATIO_BOX_MM) : int(CTL_KEEP_ASPECT_RATIO_BOX);
|
||||
@@ -3009,15 +3056,20 @@ void lcBlenderPreferences::SizeChanged(const QString& Value)
|
||||
BlenderSettings const* Settings = ImportMM ? mBlenderSettingsMM : mBlenderSettings;
|
||||
|
||||
bool Change = false;
|
||||
int NewValue = Value.toInt();
|
||||
const QLineEdit* Edit = qobject_cast<const QLineEdit*>(sender());
|
||||
bool Ok = false;
|
||||
const int NewValue = Edit ? static_cast<int>(GetNumericValue(Edit, Ok)) : 0;
|
||||
|
||||
if (!Edit || !Ok)
|
||||
return;
|
||||
if (mCheckBoxList[Keep_Aspect_Ratio]->isChecked())
|
||||
{
|
||||
if (sender() == mLineEditList[Width_Edit])
|
||||
{
|
||||
disconnect(mLineEditList[Height_Edit], &QLineEdit::textChanged, this, &lcBlenderPreferences::SizeChanged);
|
||||
|
||||
const QString Height = QString::number(qRound(double(mImageHeight * NewValue / mImageWidth)));
|
||||
mLineEditList[Height_Edit]->setText(Height);
|
||||
const QString Height = QString::number(qRound(double(mImageHeight) * NewValue / mImageWidth));
|
||||
SetNumericText(mLineEditList[Height_Edit], Height);
|
||||
|
||||
Change = Settings[Height_Edit].value != Height;
|
||||
|
||||
@@ -3027,8 +3079,8 @@ void lcBlenderPreferences::SizeChanged(const QString& Value)
|
||||
{
|
||||
disconnect(mLineEditList[Width_Edit], &QLineEdit::textChanged, this, &lcBlenderPreferences::SizeChanged);
|
||||
|
||||
const QString Width = QString::number(qRound(double(NewValue * mImageWidth / mImageHeight)));
|
||||
mLineEditList[Width_Edit]->setText(Width);
|
||||
const QString Width = QString::number(qRound(double(NewValue) * mImageWidth / mImageHeight));
|
||||
SetNumericText(mLineEditList[Width_Edit], Width);
|
||||
|
||||
Change = Settings[Height_Edit].value != Width;
|
||||
|
||||
@@ -3139,8 +3191,8 @@ void lcBlenderPreferences::SetModelSize(bool Update)
|
||||
const QString Width = QString::number(CropImage ? ImageWidth : mImageWidth);
|
||||
const QString Height = QString::number(CropImage ? ImageHeight : mImageHeight);
|
||||
|
||||
mLineEditList[Width_Edit]->setText(Width);
|
||||
mLineEditList[Height_Edit]->setText(Height);
|
||||
SetNumericText(mLineEditList[Width_Edit], Width);
|
||||
SetNumericText(mLineEditList[Height_Edit], Height);
|
||||
|
||||
if (Update)
|
||||
SettingsModified(true);
|
||||
|
||||
@@ -104,6 +104,9 @@ private slots:
|
||||
void DownloadFinished(lcHttpReply*);
|
||||
|
||||
private:
|
||||
static void SetNumericText(QLineEdit* Edit, const QString& Value);
|
||||
static double GetNumericValue(const QLineEdit* Edit, bool& Ok);
|
||||
|
||||
enum BlenderPathType
|
||||
{
|
||||
PATH_BLENDER, // 0 QLineEdit/QPushButton
|
||||
|
||||
@@ -12,8 +12,8 @@ lcHTMLDialog::lcHTMLDialog(QWidget* Parent, lcHTMLExportOptions* Options)
|
||||
|
||||
connect(ui->outputFolderBrowse, &QPushButton::clicked, this, &lcHTMLDialog::OutputFolderBrowseClicked);
|
||||
|
||||
ui->stepWidth->setValidator(new QIntValidator(0, 2048, ui->stepWidth));
|
||||
ui->stepHeight->setValidator(new QIntValidator(0, 2048, ui->stepHeight));
|
||||
ui->stepWidth->setValidator(new QIntValidator(1, LC_MAX_IMAGE_DIMENSION, ui->stepWidth));
|
||||
ui->stepHeight->setValidator(new QIntValidator(1, LC_MAX_IMAGE_DIMENSION, ui->stepHeight));
|
||||
|
||||
mOptions = Options;
|
||||
|
||||
@@ -30,8 +30,8 @@ lcHTMLDialog::lcHTMLDialog(QWidget* Parent, lcHTMLExportOptions* Options)
|
||||
ui->singlePage->setChecked(mOptions->SinglePage);
|
||||
ui->oneStepPerPage->setChecked(!mOptions->SinglePage);
|
||||
ui->indexPage->setChecked(mOptions->SinglePage);
|
||||
ui->stepWidth->setText(QString::number(mOptions->StepImagesWidth));
|
||||
ui->stepHeight->setText(QString::number(mOptions->StepImagesHeight));
|
||||
ui->stepWidth->setText(lcFormatIntegerLocalized(mOptions->StepImagesWidth, ui->stepWidth->validator()->locale()));
|
||||
ui->stepHeight->setText(lcFormatIntegerLocalized(mOptions->StepImagesHeight, ui->stepHeight->validator()->locale()));
|
||||
ui->partsAfterEachStep->setChecked(mOptions->PartsListStep);
|
||||
ui->partsAtTheEnd->setChecked(mOptions->PartsListEnd);
|
||||
}
|
||||
@@ -51,14 +51,32 @@ void lcHTMLDialog::accept()
|
||||
return;
|
||||
}
|
||||
|
||||
bool WidthOk, HeightOk;
|
||||
const int Width = ui->stepWidth->validator()->locale().toInt(ui->stepWidth->text(), &WidthOk);
|
||||
const int Height = ui->stepHeight->validator()->locale().toInt(ui->stepHeight->text(), &HeightOk);
|
||||
|
||||
if (!WidthOk || !ui->stepWidth->hasAcceptableInput())
|
||||
{
|
||||
QMessageBox::information(this, windowTitle(), tr("Please enter a width between 1 and 32768 pixels."));
|
||||
ui->stepWidth->setFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HeightOk || !ui->stepHeight->hasAcceptableInput())
|
||||
{
|
||||
QMessageBox::information(this, windowTitle(), tr("Please enter a height between 1 and 32768 pixels."));
|
||||
ui->stepHeight->setFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
mOptions->PathName = pathName;
|
||||
mOptions->SubModels = ui->currentModelSubmodels->isChecked();
|
||||
mOptions->CurrentOnly = ui->currentModelOnly->isChecked();
|
||||
mOptions->TransparentImages = ui->transparentImages->isChecked();
|
||||
mOptions->SinglePage = ui->singlePage->isChecked();
|
||||
mOptions->IndexPage = ui->indexPage->isChecked();
|
||||
mOptions->StepImagesWidth = ui->stepWidth->text().toInt();
|
||||
mOptions->StepImagesHeight = ui->stepHeight->text().toInt();
|
||||
mOptions->StepImagesWidth = Width;
|
||||
mOptions->StepImagesHeight = Height;
|
||||
mOptions->PartsListStep = ui->partsAfterEachStep->isChecked();
|
||||
mOptions->PartsListEnd = ui->partsAtTheEnd->isChecked();
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="whatsThis">
|
||||
<string><p><b>Steps</b></p><p>Single Page places all steps for each model on one HTML page. One Step per Page creates separate pages with navigation links. In that mode, Index page adds a page linking to the steps.</p><p>Width and Height set the step image size in pixels. Use positive dimensions up to 2048 pixels.</p></string>
|
||||
<string><p><b>Steps</b></p><p>Single Page places all steps for each model on one HTML page. One Step per Page creates separate pages with navigation links. In that mode, Index page adds a page linking to the steps.</p><p>Width and Height set the step image size in pixels. Use dimensions from 1 to 32768 pixels.</p></string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Steps</string>
|
||||
|
||||
+17
-16
@@ -12,16 +12,16 @@ lcImageDialog::lcImageDialog(QWidget* Parent, lcImageDialogOptions* Options)
|
||||
|
||||
connect(ui->fileNameBrowse, &QPushButton::clicked, this, &lcImageDialog::FileNameBrowseClicked);
|
||||
|
||||
ui->width->setValidator(new QIntValidator(1, 32768, this));
|
||||
ui->height->setValidator(new QIntValidator(1, 32768, this));
|
||||
ui->firstStep->setValidator(new QIntValidator(this));
|
||||
ui->lastStep->setValidator(new QIntValidator(this));
|
||||
ui->width->setValidator(new QIntValidator(1, LC_MAX_IMAGE_DIMENSION, this));
|
||||
ui->height->setValidator(new QIntValidator(1, LC_MAX_IMAGE_DIMENSION, this));
|
||||
ui->firstStep->setValidator(new QIntValidator(1, mOptions->End, this));
|
||||
ui->lastStep->setValidator(new QIntValidator(1, mOptions->End, this));
|
||||
|
||||
ui->fileName->setText(mOptions->FilePath);
|
||||
ui->width->setText(QString::number(mOptions->Width));
|
||||
ui->height->setText(QString::number(mOptions->Height));
|
||||
ui->firstStep->setText(QString::number(mOptions->Start));
|
||||
ui->lastStep->setText(QString::number(mOptions->End));
|
||||
ui->width->setText(lcFormatIntegerLocalized(mOptions->Width, ui->width->validator()->locale()));
|
||||
ui->height->setText(lcFormatIntegerLocalized(mOptions->Height, ui->height->validator()->locale()));
|
||||
ui->firstStep->setText(lcFormatIntegerLocalized(mOptions->Start, ui->firstStep->validator()->locale()));
|
||||
ui->lastStep->setText(lcFormatIntegerLocalized(mOptions->End, ui->lastStep->validator()->locale()));
|
||||
ui->rangeCurrent->setChecked(true);
|
||||
}
|
||||
|
||||
@@ -40,17 +40,18 @@ void lcImageDialog::accept()
|
||||
return;
|
||||
}
|
||||
|
||||
int Width = ui->width->text().toInt();
|
||||
bool Ok;
|
||||
int Width = ui->width->validator()->locale().toInt(ui->width->text(), &Ok);
|
||||
|
||||
if (Width < 1 || Width > 32768)
|
||||
if (!Ok || Width < 1 || Width > LC_MAX_IMAGE_DIMENSION)
|
||||
{
|
||||
QMessageBox::information(this, windowTitle(), tr("Please enter a width between 1 and 32768."));
|
||||
return;
|
||||
}
|
||||
|
||||
int Height = ui->height->text().toInt();
|
||||
int Height = ui->height->validator()->locale().toInt(ui->height->text(), &Ok);
|
||||
|
||||
if (Height < 1 || Height > 32768)
|
||||
if (!Ok || Height < 1 || Height > LC_MAX_IMAGE_DIMENSION)
|
||||
{
|
||||
QMessageBox::information(this, windowTitle(), tr("Please enter a height between 1 and 32768."));
|
||||
return;
|
||||
@@ -70,17 +71,17 @@ void lcImageDialog::accept()
|
||||
}
|
||||
else if (ui->rangeCustom->isChecked())
|
||||
{
|
||||
Start = ui->firstStep->text().toInt();
|
||||
Start = ui->firstStep->validator()->locale().toInt(ui->firstStep->text(), &Ok);
|
||||
|
||||
if (Start < 1 || Start > mOptions->End)
|
||||
if (!Ok || Start < 1 || Start > mOptions->End)
|
||||
{
|
||||
QMessageBox::information(this, windowTitle(), tr("First step must be between 1 and %1.").arg(QString::number(mOptions->End)));
|
||||
return;
|
||||
}
|
||||
|
||||
End = ui->lastStep->text().toInt();
|
||||
End = ui->lastStep->validator()->locale().toInt(ui->lastStep->text(), &Ok);
|
||||
|
||||
if (End < 1 || End > mOptions->End)
|
||||
if (!Ok || End < 1 || End > mOptions->End)
|
||||
{
|
||||
QMessageBox::information(this, windowTitle(), tr("Last step must be between 1 and %1.").arg(QString::number(mOptions->End)));
|
||||
return;
|
||||
|
||||
@@ -634,7 +634,12 @@ void lcPropertiesWidget::IntegerChanged()
|
||||
if (!Model)
|
||||
return;
|
||||
|
||||
const int Value = LineEdit->text().toInt();
|
||||
bool Ok;
|
||||
const int Value = LineEdit->validator()->locale().toInt(LineEdit->text(), &Ok);
|
||||
|
||||
if (!Ok || !LineEdit->hasAcceptableInput())
|
||||
return;
|
||||
|
||||
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value);
|
||||
}
|
||||
|
||||
@@ -658,7 +663,7 @@ void lcPropertiesWidget::UpdateInteger(lcObjectPropertyId PropertyId)
|
||||
}
|
||||
else
|
||||
{
|
||||
LineEdit->setText(QString::number(Value.toInt()));
|
||||
LineEdit->setText(lcFormatIntegerLocalized(Value.toInt(), LineEdit->validator()->locale()));
|
||||
LineEdit->setPlaceholderText(QString());
|
||||
}
|
||||
|
||||
@@ -703,9 +708,9 @@ void lcPropertiesWidget::StepNumberChanged()
|
||||
|
||||
bool Ok = true;
|
||||
QString Text = Widget->text();
|
||||
lcStep Step = Text.isEmpty() && PropertyId == lcObjectPropertyId::PieceStepHide ? LC_STEP_MAX : Text.toUInt(&Ok);
|
||||
lcStep Step = Text.isEmpty() && PropertyId == lcObjectPropertyId::PieceStepHide ? LC_STEP_MAX : Widget->validator()->locale().toUInt(Text, &Ok);
|
||||
|
||||
if (!Ok)
|
||||
if (!Ok || !Widget->hasAcceptableInput())
|
||||
return;
|
||||
|
||||
if (PropertyId == lcObjectPropertyId::PieceStepShow)
|
||||
@@ -727,7 +732,7 @@ void lcPropertiesWidget::UpdateStepNumber(lcObjectPropertyId PropertyId, lcStep
|
||||
QSignalBlocker Blocker(Widget);
|
||||
|
||||
Widget->setValidator(new lcStepValidator(Min, Max, PropertyId == lcObjectPropertyId::PieceStepHide, Widget));
|
||||
Widget->setText(Step == LC_STEP_MAX ? QString() : QString::number(Step));
|
||||
Widget->setText(Step == LC_STEP_MAX ? QString() : lcFormatIntegerLocalized(Step, Widget->validator()->locale()));
|
||||
}
|
||||
|
||||
UpdateKeyFrameWidget(PropertyId);
|
||||
@@ -1246,8 +1251,8 @@ void lcPropertiesWidget::CreateWidgets()
|
||||
AddFloatProperty(lcObjectPropertyId::LightPOVRayFadeDistance, tr("Fade Distance"), tr("The distance at which the full light intensity arrives"), true, 0.0f, FLT_MAX);
|
||||
AddFloatProperty(lcObjectPropertyId::LightPOVRayFadePower, tr("Fade Power"), tr("Light falloff rate"), true, 0.0f, FLT_MAX);
|
||||
AddFloatProperty(lcObjectPropertyId::LightPOVRaySpotTightness, tr("Tightness"), tr("Additional exponential spotlight edge softening"), true, 0.0f, FLT_MAX);
|
||||
AddIntegerProperty(lcObjectPropertyId::LightPOVRayAreaGridX, tr("Grid X"), tr("Number of point sources along the X axis"), true, 1, INT_MAX);
|
||||
AddIntegerProperty(lcObjectPropertyId::LightPOVRayAreaGridY, tr("Y"), tr("Number of point sources along the Y axis"), true, 1, INT_MAX);
|
||||
AddIntegerProperty(lcObjectPropertyId::LightPOVRayAreaGridX, tr("Grid X"), tr("Number of point sources along the X axis (1 to 64)."), true, 1, LC_MAX_AREA_LIGHT_GRID);
|
||||
AddIntegerProperty(lcObjectPropertyId::LightPOVRayAreaGridY, tr("Y"), tr("Number of point sources along the Y axis (1 to 64)."), true, 1, LC_MAX_AREA_LIGHT_GRID);
|
||||
|
||||
AddSpacing();
|
||||
|
||||
|
||||
@@ -178,7 +178,8 @@ lcPreferencesDialog::lcPreferencesDialog(QWidget* Parent, lcPreferencesDialogOpt
|
||||
ui->HighlightNewParts->setChecked(mOptions->Preferences.mHighlightNewParts);
|
||||
ui->gridStuds->setChecked(mOptions->Preferences.mDrawGridStuds);
|
||||
ui->gridLines->setChecked(mOptions->Preferences.mDrawGridLines);
|
||||
ui->gridLineSpacing->setText(QString::number(mOptions->Preferences.mGridLineSpacing));
|
||||
ui->gridLineSpacing->setValidator(new QIntValidator(1, LC_MAX_GRID_LINE_SPACING, ui->gridLineSpacing));
|
||||
ui->gridLineSpacing->setText(lcFormatIntegerLocalized(mOptions->Preferences.mGridLineSpacing, ui->gridLineSpacing->validator()->locale()));
|
||||
ui->GridOriginCheckBox->setChecked(mOptions->Preferences.mDrawGridOrigin);
|
||||
ui->AxisIconCheckBox->setChecked(mOptions->Preferences.mDrawAxes);
|
||||
|
||||
@@ -359,10 +360,11 @@ lcPreferencesDialog::~lcPreferencesDialog()
|
||||
|
||||
void lcPreferencesDialog::accept()
|
||||
{
|
||||
int GridLineSpacing = ui->gridLineSpacing->text().toInt();
|
||||
if (GridLineSpacing < 1)
|
||||
bool Ok;
|
||||
int GridLineSpacing = ui->gridLineSpacing->validator()->locale().toInt(ui->gridLineSpacing->text(), &Ok);
|
||||
if (!Ok || !ui->gridLineSpacing->hasAcceptableInput())
|
||||
{
|
||||
QMessageBox::information(this, windowTitle(), tr("Grid spacing must be greater than 0."));
|
||||
QMessageBox::information(this, windowTitle(), tr("Grid spacing must be between 1 and %1 studs.").arg(QString::number(LC_MAX_GRID_LINE_SPACING)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1074,7 +1074,7 @@
|
||||
<string>Grid Line Spacing</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set base-grid line spacing in studs (minimum 1).</string>
|
||||
<string>Set base-grid line spacing in studs (1 to 10000).</string>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
|
||||
@@ -84,6 +84,12 @@ QString lcFormatValueLocalized(float Value)
|
||||
return String;
|
||||
}
|
||||
|
||||
QString lcFormatIntegerLocalized(qlonglong Value, QLocale Locale)
|
||||
{
|
||||
Locale.setNumberOptions(Locale.numberOptions() | QLocale::OmitGroupSeparator);
|
||||
return Locale.toString(Value);
|
||||
}
|
||||
|
||||
float lcParseValueLocalized(const QString& Value)
|
||||
{
|
||||
return QLocale::system().toFloat(Value);
|
||||
|
||||
+7
-1
@@ -2,12 +2,18 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QLocale;
|
||||
class lcPartSelectionWidget;
|
||||
class lcPartSelectionListView;
|
||||
struct lcTrainTrackConnectionType;
|
||||
|
||||
constexpr int LC_MAX_IMAGE_DIMENSION = 32768;
|
||||
constexpr int LC_MAX_GRID_LINE_SPACING = 10000;
|
||||
constexpr int LC_MAX_AREA_LIGHT_GRID = 64;
|
||||
|
||||
QString lcFormatValue(float Value, int Precision);
|
||||
QString lcFormatValueLocalized(float Value);
|
||||
QString lcFormatIntegerLocalized(qlonglong Value, QLocale Locale);
|
||||
float lcParseValueLocalized(const QString& Value);
|
||||
|
||||
void lcSetupDialogHelp(QDialog* Dialog, QDialogButtonBox* ButtonBox);
|
||||
@@ -112,7 +118,7 @@ public:
|
||||
return Acceptable;
|
||||
|
||||
bool Ok;
|
||||
lcStep Step = Input.toUInt(&Ok);
|
||||
lcStep Step = locale().toUInt(Input, &Ok);
|
||||
|
||||
if (Ok)
|
||||
return (Step >= mMin && Step <= mMax) ? Acceptable : Invalid;
|
||||
|
||||
+36
-10
@@ -837,23 +837,23 @@ void lcRenderDialog::SettingsButtonClicked()
|
||||
QDialog Dialog(this);
|
||||
|
||||
Dialog.setWindowTitle(tr("POV-Ray Settings"));
|
||||
Dialog.setWhatsThis(tr("<p><b>POV-Ray Settings</b></p><p>Set the output image dimensions and rendering quality. Width and height are in pixels, with a minimum of 16. Larger images and higher quality can take longer to render.</p><p>Choose OK to save these settings for subsequent renders, or Cancel to keep the previous settings. This dialog does not start rendering.</p>"));
|
||||
Dialog.setWhatsThis(tr("<p><b>POV-Ray Settings</b></p><p>Set the output image dimensions and rendering quality. Width and height are in pixels, from 1 to 32768. Larger images and higher quality can take longer to render.</p><p>Choose OK to save these settings for subsequent renders, or Cancel to keep the previous settings. This dialog does not start rendering.</p>"));
|
||||
|
||||
QFormLayout* Layout = new QFormLayout(&Dialog);
|
||||
|
||||
QLineEdit* WidthEdit = new QLineEdit(&Dialog);
|
||||
Layout->addRow(tr("Width:"), WidthEdit);
|
||||
|
||||
WidthEdit->setText(QString::number(mWidth));
|
||||
WidthEdit->setValidator(new QIntValidator(16, INT_MAX, this));
|
||||
WidthEdit->setToolTip(tr("Set the rendered image width in pixels (minimum 16)."));
|
||||
WidthEdit->setValidator(new QIntValidator(1, LC_MAX_IMAGE_DIMENSION, WidthEdit));
|
||||
WidthEdit->setText(lcFormatIntegerLocalized(mWidth, WidthEdit->validator()->locale()));
|
||||
WidthEdit->setToolTip(tr("Set the rendered image width in pixels (1 to 32768)."));
|
||||
|
||||
QLineEdit* HeightEdit = new QLineEdit(&Dialog);
|
||||
Layout->addRow(tr("Height:"), HeightEdit);
|
||||
|
||||
HeightEdit->setText(QString::number(mHeight));
|
||||
HeightEdit->setValidator(new QIntValidator(16, INT_MAX, this));
|
||||
HeightEdit->setToolTip(tr("Set the rendered image height in pixels (minimum 16)."));
|
||||
HeightEdit->setValidator(new QIntValidator(1, LC_MAX_IMAGE_DIMENSION, HeightEdit));
|
||||
HeightEdit->setText(lcFormatIntegerLocalized(mHeight, HeightEdit->validator()->locale()));
|
||||
HeightEdit->setToolTip(tr("Set the rendered image height in pixels (1 to 32768)."));
|
||||
|
||||
QComboBox* QualityComboBox = new QComboBox(&Dialog);
|
||||
Layout->addRow(tr("Quality:"), QualityComboBox);
|
||||
@@ -878,13 +878,39 @@ void lcRenderDialog::SettingsButtonClicked()
|
||||
lcSetupDialogHelp(&Dialog, ButtonBox);
|
||||
|
||||
QObject::connect(ButtonBox, &QDialogButtonBox::rejected, &Dialog, &QDialog::reject);
|
||||
QObject::connect(ButtonBox, &QDialogButtonBox::accepted, &Dialog, &QDialog::accept);
|
||||
int Width = mWidth;
|
||||
int Height = mHeight;
|
||||
|
||||
QObject::connect(ButtonBox, &QDialogButtonBox::accepted, &Dialog, [&Dialog, WidthEdit, HeightEdit, &Width, &Height]()
|
||||
{
|
||||
bool WidthOk, HeightOk;
|
||||
const int NewWidth = WidthEdit->validator()->locale().toInt(WidthEdit->text(), &WidthOk);
|
||||
const int NewHeight = HeightEdit->validator()->locale().toInt(HeightEdit->text(), &HeightOk);
|
||||
|
||||
if (!WidthOk || !WidthEdit->hasAcceptableInput())
|
||||
{
|
||||
QMessageBox::information(&Dialog, Dialog.windowTitle(), tr("Please enter a width between 1 and %1 pixels.").arg(QString::number(LC_MAX_IMAGE_DIMENSION)));
|
||||
WidthEdit->setFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HeightOk || !HeightEdit->hasAcceptableInput())
|
||||
{
|
||||
QMessageBox::information(&Dialog, Dialog.windowTitle(), tr("Please enter a height between 1 and %1 pixels.").arg(QString::number(LC_MAX_IMAGE_DIMENSION)));
|
||||
HeightEdit->setFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
Width = NewWidth;
|
||||
Height = NewHeight;
|
||||
Dialog.accept();
|
||||
});
|
||||
|
||||
if (Dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
mWidth = std::clamp(WidthEdit->text().toInt(), 16, INT_MAX);
|
||||
mHeight = std::clamp(HeightEdit->text().toInt(), 16, INT_MAX);
|
||||
mWidth = Width;
|
||||
mHeight = Height;
|
||||
mQuality = static_cast<lcPOVRayRenderQuality>(QualityComboBox->currentIndex());
|
||||
|
||||
lcSetProfileInt(LC_PROFILE_RENDER_WIDTH, mWidth);
|
||||
|
||||
Reference in new issue
Block a user