+#include
#define DIM_DIVIDER 6
@@ -82,7 +83,7 @@ BiomeColorDialog::BiomeColorDialog(MainWindow *parent, QString initrc, int mc, i
ui->gridLayout->addWidget(separator, 256, 0, 1, 3);
QString dir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
- QDirIterator it(dir, QDirIterator::NoIteratorFlags);
+ QDirIterator it(dir);
while (it.hasNext())
{
QString rc = it.next();
@@ -203,6 +204,8 @@ int BiomeColorDialog::saveColormap(QString rc, QString desc)
continue;
stream << bname << " " << colors[i][0] << " " << colors[i][1] << " " << colors[i][2] << "\n";
}
+ stream.flush();
+ file.close();
modified = false;
if (index > 0)
@@ -217,15 +220,14 @@ int BiomeColorDialog::saveColormap(QString rc, QString desc)
return index;
}
-int BiomeColorDialog::loadColormap(QString path, bool reset)
+int BiomeColorDialog::loadColormap(QIODevice *iodevice, bool reset)
{
- QFile file(path);
int n = 0;
- if (!path.isEmpty() && file.open(QIODevice::ReadOnly))
+ if (iodevice && iodevice->open(QIODevice::ReadOnly))
{
char buf[32*1024];
- qint64 siz = file.read(buf, sizeof(buf)-1);
- file.close();
+ qint64 siz = iodevice->read(buf, sizeof(buf)-1);
+ iodevice->close();
if (siz >= 0)
{
buf[siz] = 0;
@@ -247,12 +249,18 @@ int BiomeColorDialog::loadColormap(QString path, bool reset)
buttons[i][0]->setIcon(getColorIcon(col));
}
}
- return n;
-}
-QString BiomeColorDialog::getRc()
-{
- return activerc;
+ if (!reset)
+ {
+ if (n == 0)
+ {
+ warn(this, tr("No biome colors found."));
+ return n;
+ }
+ info(this, tr("Replaced %n biome color(s).", "", n));
+ modified = true;
+ }
+ return n;
}
void BiomeColorDialog::setBiomeColor(int id, const QColor &col)
@@ -269,10 +277,10 @@ void BiomeColorDialog::editBiomeColor(int id)
QColor col = QColor(colors[id][0], colors[id][1], colors[id][2]);
QColorDialog *dialog = new QColorDialog(col, this);
//dialog->setOption(QColorDialog::DontUseNativeDialog, true);
- if (dialog->exec())
- {
+ connect(dialog, &QDialog::accepted, [=] {
setBiomeColor(id, dialog->selectedColor());
- }
+ });
+ dialog->show();
}
void BiomeColorDialog::on_comboColormaps_currentIndexChanged(int index)
@@ -287,7 +295,15 @@ void BiomeColorDialog::on_comboColormaps_currentIndexChanged(int index)
}
activerc = qvariant_cast(ui->comboColormaps->currentData());
- loadColormap(activerc, true);
+ if (!activerc.isEmpty())
+ {
+ QFile file(activerc);
+ loadColormap(&file, true);
+ }
+ else
+ {
+ loadColormap(nullptr, true);
+ }
}
void BiomeColorDialog::onSaveAs()
@@ -301,40 +317,63 @@ void BiomeColorDialog::onSaveAs()
if (!QFile::exists(rc))
break;
}
- bool ok;
- QString desc = QInputDialog::getText(
- this, tr("Save biome colors as..."),
- tr("Biome colors:"), QLineEdit::Normal,
- QString("Colormap#%1").arg(n), &ok);
- if (!ok || desc.isEmpty())
- return;
+ QInputDialog *dialog = new QInputDialog(this);
+ dialog->setInputMode(QInputDialog::TextInput);
+ dialog->setWindowTitle(tr("Save biome colors as..."));
+ dialog->setLabelText(tr("Biome colors:"));
+ dialog->setTextValue(QString("Colormap#%1").arg(n));
+ connect(dialog, &QInputDialog::textValueSelected, [=](const QString &text) {
+ this->onSaveSelect(rc, text);
+ });
+ dialog->show();
+}
- int idx = saveColormap(rc, desc);
+void BiomeColorDialog::onSaveSelect(const QString& rc, const QString &text)
+{
+ int idx = saveColormap(rc, text);
ui->comboColormaps->setCurrentIndex(idx);
- activerc = rc;
+ emit yieldBiomeColorRc(rc);
+ accept();
+}
+
+void BiomeColorDialog::exportColors(QTextStream& stream)
+{
+ for (int i = 0; i < 256; i++)
+ {
+ const char *bname = biome2str(MC_NEWEST, i);
+ if (!bname)
+ continue;
+ stream << bname << " " << colors[i][0] << " " << colors[i][1] << " " << colors[i][2] << "\n";
+ }
+ stream.flush();
}
void BiomeColorDialog::onExport()
{
- QFileInfo finfo(mainwindow->prevdir);
+#if WASM
+ QByteArray content;
+ QTextStream stream(&content);
+ exportColors(stream);
+ QFileDialog::saveFileContent(content, "biomecolors.txt");
+#else
QString fnam = QFileDialog::getSaveFileName(
- this, tr("Export biome color map"), finfo.absolutePath(), tr("Color map files (*.colormap *.txt);;Any files (*)"));
+ this, tr("Export biome color map"), mainwindow->prevdir, tr("Color map files (*.colormap *.txt);;Any files (*)"));
if (fnam.isEmpty())
return;
+
+ QFileInfo finfo(fnam);
QFile file(fnam);
+ mainwindow->prevdir = finfo.absolutePath();
+
if (!file.open(QIODevice::WriteOnly))
{
- warn(this, tr("Failed open file for writing."));
+ warn(this, tr("Failed to open file for export:\n\"%1\"").arg(fnam));
return;
}
+
QTextStream stream(&file);
- for (int i = 0; i < 256; i++)
- {
- const char *bname = biome2str(MC_NEWEST, i);
- if (!bname)
- continue;
- stream << bname << " " << colors[i][0] << " " << colors[i][1] << " " << colors[i][2] << "\n";
- }
+ exportColors(stream);
+#endif
}
void BiomeColorDialog::onRemove()
@@ -351,47 +390,64 @@ void BiomeColorDialog::onRemove()
void BiomeColorDialog::onAccept()
{
- on_comboColormaps_currentIndexChanged(ui->comboColormaps->currentIndex());
+ if (modified)
+ {
+ if (activerc.isEmpty())
+ {
+ onSaveAs();
+ return; // accept only after save-as dialog
+ }
+ saveColormap(activerc, "");
+ }
emit yieldBiomeColorRc(activerc);
accept();
}
void BiomeColorDialog::onImport()
{
- QFileInfo finfo(mainwindow->prevdir);
- QString fnam = QFileDialog::getOpenFileName(
- this, tr("Load biome color map"), finfo.absolutePath(), tr("Color map files (*.colormap *.txt);;Any files (*)"));
- if (!fnam.isNull())
- {
- int n = loadColormap(fnam, false);
- if (n == 0)
- {
- warn(this, tr("No biome colors found."));
- return;
+ QString filter = tr("Color map files (*.colormap *.txt);;Any files (*)");
+#if WASM
+ auto fileOpenCompleted = [=](const QString &fnam, const QByteArray &content) {
+ if (!fnam.isEmpty()) {
+ QBuffer buffer;
+ buffer.setData(content);
+ loadColormap(&buffer, false);
}
- info(this, tr("Replaced %n biome color(s).", "", n));
- modified = true;
- }
+ };
+ QFileDialog::getOpenFileContent(filter, fileOpenCompleted);
+#else
+ QString fnam = QFileDialog::getOpenFileName(
+ this, tr("Load biome color map"), mainwindow->prevdir, filter);
+ if (fnam.isEmpty())
+ return;
+ QFileInfo finfo(fnam);
+ QFile file(fnam);
+ mainwindow->prevdir = finfo.absolutePath();
+ loadColormap(&file, false);
+#endif
}
void BiomeColorDialog::onColorHelp()
{
- QString msg = tr(
- ""
- "Custom biome colors should be defined in an ASCII text file, "
- "with one biome-color mapping per line. Each mapping should consist "
- "of a biome ID or biome resource name followed by a color that can be "
- "written as a hex code (prefixed with # or 0x) or as an RGB triplet. "
- "Special characters are ignored."
- "
"
- "Examples:"
- "
"
- "sunflower_plains: #FFFF00"
- "
"
- "128 [255 255 0]"
- "
"
- );
- QMessageBox::information(this, tr("Help: custom biome colors"), msg, QMessageBox::Ok);
+ QMessageBox *mb = new QMessageBox(this);
+ mb->setIcon(QMessageBox::Information);
+ mb->setWindowTitle(tr("Help: custom biome colors"));
+ mb->setText(tr(
+ ""
+ "Custom biome colors should be defined in an ASCII text file, "
+ "with one biome-color mapping per line. Each mapping should consist "
+ "of a biome ID or biome resource name followed by a color that can be "
+ "written as a hex code (prefixed with # or 0x) or as an RGB triplet. "
+ "Special characters are ignored."
+ "
"
+ "Examples:"
+ "
"
+ "sunflower_plains: #FFFF00"
+ "
"
+ "128 [255 255 0]"
+ "
"
+ ));
+ mb->show();
}
void BiomeColorDialog::onAllToDefault()
diff --git a/src/biomecolordialog.h b/src/biomecolordialog.h
index a476dfa..4b1953d 100644
--- a/src/biomecolordialog.h
+++ b/src/biomecolordialog.h
@@ -3,6 +3,7 @@
#include
#include
+#include
namespace Ui {
class BiomeColorDialog;
@@ -18,8 +19,7 @@ class BiomeColorDialog : public QDialog
~BiomeColorDialog();
int saveColormap(QString rc, QString desc);
- int loadColormap(QString path, bool reset);
- QString getRc();
+ int loadColormap(QIODevice *iodevice, bool reset);
void arrange(int sort);
@@ -34,6 +34,7 @@ private slots:
void on_comboColormaps_currentIndexChanged(int index);
void onSaveAs();
+ void onSaveSelect(const QString &rc, const QString &text);
void onExport();
void onRemove();
void onAccept();
@@ -42,6 +43,9 @@ private slots:
void onAllToDefault();
void onAllToDimmed();
+private:
+ void exportColors(QTextStream& stream);
+ void importColors(QTextStream& stream);
private:
Ui::BiomeColorDialog *ui;
diff --git a/src/conditiondialog.cpp b/src/conditiondialog.cpp
index 39dba70..ad5e7d1 100644
--- a/src/conditiondialog.cpp
+++ b/src/conditiondialog.cpp
@@ -1,24 +1,24 @@
#include "conditiondialog.h"
#include "ui_conditiondialog.h"
-#include "mainwindow.h"
-#include "scripts.h"
+#include "config.h"
#include "layerdialog.h"
+#include "mapview.h"
#include "message.h"
-#include "config.h"
+#include "scripts.h"
#include "util.h"
#include
-#include
-#include
-#include
-#include
-#include
#include
#include
#include
-#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
#define WARNING_CHAR QChar(0x26A0)
@@ -63,7 +63,7 @@ ConditionDialog::ConditionDialog(FormConditions *parent, MapView *mapview, Confi
// w->setFont(dfont);
int initindex = -1;
- const QVector existing = parent->getConditions();
+ const std::vector existing = parent->getConditions();
for (Condition c : existing)
{
if (initcond)
@@ -868,7 +868,7 @@ void ConditionDialog::updateBiomeSelection()
}
}
-int ConditionDialog::warnIfBad(Condition cond)
+bool ConditionDialog::warnIfBad(Condition cond)
{
const FilterInfo &ft = g_filterinfo.list[cond.type];
if ((cond.varflags & Condition::VAR_WITH_START) && (cond.varstart == 0))
@@ -877,7 +877,7 @@ int ConditionDialog::warnIfBad(Condition cond)
{
QString text = tr("No allowed start pieces specified. Condition can never be true.");
warn(this, tr("Missing Start Piece"), text);
- return QMessageBox::Cancel;
+ return false;
}
}
if (cond.type == F_CLIMATE_NOISE)
@@ -891,7 +891,7 @@ int ConditionDialog::warnIfBad(Condition cond)
"with the full range required, which can never be satisfied."
);
warn(this, tr("Bad Climate Range"), text);
- return QMessageBox::Cancel;
+ return false;
}
}
}
@@ -910,7 +910,7 @@ int ConditionDialog::warnIfBad(Condition cond)
.arg(w).arg(QChar(0xD7)).arg(h).arg(w*h)
.arg(cond.count * cond.biomeSize).arg(1< 246)
{
- return warn(this, tr("Bad Surface Height"),
- tr("Cave biomes do not generate above Y = 246. "
- "You should consider lowering the sampling height."
- "\n\n"
- "Continue anyway?"),
- QMessageBox::Ok | QMessageBox::Cancel);
+ int button = warn(this, tr("Bad Surface Height"),
+ tr("Cave biomes do not generate above Y = 246.\nThe sampling height should be lowered."),
+ tr("Continue anyway?"), QMessageBox::Ok | QMessageBox::Cancel);
+ return button != QMessageBox::Cancel;
}
}
if (cond.type == F_BIOME_SAMPLE)
{
if (cond.biomeToFind == 0 && cond.biomeToFindM == 0)
{
- return warn(this, tr("No Allowed Biomes"),
- tr("The set of allowed biomes is empty, which can never "
- "be satisfied. Please include some biomes for the required "
- "proportion."),
- QMessageBox::Cancel);
+ QString text = tr(
+ "The set of allowed biomes is empty, which can never be satisfied. "
+ "Please include some biomes for the required proportion.");
+ warn(this, tr("No Allowed Biomes"), text);
+ return false;
}
}
}
@@ -958,16 +956,14 @@ int ConditionDialog::warnIfBad(Condition cond)
ok &= (cond.z1 & 511) < AFKMAX && (cond.z1 & 511) > AFKMIN - (cond.z2 - cond.z1);
if (!ok)
{
- return warn(this, tr("Bad Area for Quad-Structure"),
- tr("The selected area does not contain a range where a "
- "quad-structure can generate."
- "\n\n"
- "Continue anyway?"),
- QMessageBox::Ok | QMessageBox::Cancel);
+ int button = warn(this, tr("Bad Area for Quad-Structure"),
+ tr("The selected area does not contain a range where a quad-structure can generate."),
+ tr("Continue anyway?"), QMessageBox::Ok | QMessageBox::Cancel);
+ return button != QMessageBox::Cancel;
}
}
}
- return QMessageBox::Ok;
+ return true;
}
static uint16_t tristateFlags(QCheckBox *cb, uint16_t flg)
@@ -1139,7 +1135,7 @@ void ConditionDialog::onAccept()
getClimateLimits(c.limok, c.limex);
- if (warnIfBad(c) != QMessageBox::Ok)
+ if (!warnIfBad(c))
return;
cond = c;
emit setCond(item, cond, 1);
@@ -1230,10 +1226,10 @@ void ConditionDialog::on_buttonExclude_clicked()
void ConditionDialog::on_buttonAreaInfo_clicked()
{
- QMessageBox mb(this);
- mb.setIcon(QMessageBox::Information);
- mb.setWindowTitle(tr("Help: area entry"));
- mb.setText(tr(
+ QMessageBox *mb = new QMessageBox(this);
+ mb->setIcon(QMessageBox::Information);
+ mb->setWindowTitle(tr("Help: area entry"));
+ mb->setText(tr(
""
"The area can be entered via custom rectangle, that is defined "
"by its two opposing corners, relative to a center point. These bounds "
@@ -1251,7 +1247,7 @@ void ConditionDialog::on_buttonAreaInfo_clicked()
"-32 to 31, and get sampled at -32, -16, 0 and 16."
"
"
));
- mb.exec();
+ mb->show();
}
void ConditionDialog::on_buttonFromVisible_clicked()
@@ -1489,12 +1485,11 @@ void ConditionDialog::on_pushLuaSave_clicked()
ui->textEditLua->document()->setModified(false);
}
-void ConditionDialog::on_pushLuaSaveAs_clicked()
+void ConditionDialog::onLuaSaveAs(const QString& fileName)
{
- QString fnam = QFileDialog::getSaveFileName(
- this, tr("Save lua script"), getLuaDir(), tr("Lua script (*.lua)"));
- if (fnam.isEmpty())
+ if (fileName.isEmpty())
return;
+ QString fnam = fileName;
if (!fnam.endsWith(".lua"))
fnam += ".lua";
QFile file(fnam);
@@ -1510,6 +1505,15 @@ void ConditionDialog::on_pushLuaSaveAs_clicked()
ui->comboLua->setCurrentIndex(ui->comboLua->count() - 1);
}
+void ConditionDialog::on_pushLuaSaveAs_clicked()
+{
+ QFileDialog *dialog = new QFileDialog(this, tr("Save lua script"), getLuaDir(), tr("Lua script (*.lua)"));
+ dialog->setAcceptMode(QFileDialog::AcceptSave);
+ dialog->setSupportedSchemes(QStringList("file"));
+ connect(dialog, &QFileDialog::fileSelected, this, &ConditionDialog::onLuaSaveAs);
+ dialog->show();
+}
+
void ConditionDialog::on_pushLuaOpen_clicked()
{
QDesktopServices::openUrl(getLuaDir());
@@ -1559,16 +1563,17 @@ void ConditionDialog::on_pushLuaExample_clicked()
},
};
- bool ok = false;
- QString choice = QInputDialog::getItem(this,
- tr("Lua examples"),
- tr("Replace editor content with example:"),
- examples, 0, false, &ok
- );
- if (ok && !choice.isEmpty())
- {
- ui->textEditLua->document()->setPlainText(code[choice]);
- }
+ QInputDialog *dialog = new QInputDialog(this);
+ dialog->setWindowTitle(tr("Lua examples"));
+ dialog->setLabelText(tr("Replace editor content with example:"));
+ dialog->setComboBoxItems(examples);
+ dialog->setTextValue(examples.first());
+ dialog->setComboBoxEditable(false);
+ connect(dialog, &QInputDialog::textValueSelected, [=](const QString &text) {
+ if (code.contains(text))
+ ui->textEditLua->document()->setPlainText(code[text]);
+ });
+ dialog->show();
}
void ConditionDialog::on_comboHeightRange_currentIndexChanged(int index)
@@ -1584,10 +1589,10 @@ void ConditionDialog::on_comboHeightRange_currentIndexChanged(int index)
void ConditionDialog::on_pushInfoLua_clicked()
{
- QMessageBox mb(this);
- mb.setIcon(QMessageBox::Information);
- mb.setWindowTitle(tr("Help: Lua script"));
- mb.setText( tr(
+ QMessageBox *mb = new QMessageBox(this);
+ mb->setIcon(QMessageBox::Information);
+ mb->setWindowTitle(tr("Help: Lua script"));
+ mb->setText( tr(
""
"Lua scripts allow the user to write custom filters. "
"A valid Lua filtering script has to define a"
@@ -1625,7 +1630,7 @@ void ConditionDialog::on_pushInfoLua_clicked()
"positions x1, z1 to x2, z2, or nil upon failure"
"
"
));
- mb.exec();
+ mb->show();
}
void ConditionDialog::on_comboClimatePara_currentIndexChanged(int)
diff --git a/src/conditiondialog.h b/src/conditiondialog.h
index 76f3cab..470c88b 100644
--- a/src/conditiondialog.h
+++ b/src/conditiondialog.h
@@ -1,16 +1,17 @@
#ifndef CONDITIONDIALOG_H
#define CONDITIONDIALOG_H
-#include "search.h"
+#include "config.h"
#include "formconditions.h"
+#include "search.h"
#include "util.h"
#include "widgets.h"
-#include
#include
+#include
#include
-#include
#include
+#include
class MainWindow;
class MapView;
@@ -57,7 +58,7 @@ class ConditionDialog : public QDialog
void addTempCat(int temp, QString name);
void updateMode();
void updateBiomeSelection();
- int warnIfBad(Condition cond);
+ bool warnIfBad(Condition cond);
void onReject();
void onAccept();
@@ -97,6 +98,7 @@ private slots:
void on_lineBiomeSize_textChanged(const QString &text);
+ void onLuaSaveAs(const QString& fileName);
void on_comboLua_currentIndexChanged(int index);
void on_pushLuaSaveAs_clicked();
void on_pushLuaSave_clicked();
diff --git a/src/config.cpp b/src/config.cpp
index 07ae833..66e6065 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -1,12 +1,13 @@
#include "config.h"
-#include "util.h"
+
#include "seedtables.h"
+#include "util.h"
#include
#include
+#include
#include
-
/// globals
unsigned char g_biomeColors[256][3];
@@ -106,6 +107,7 @@ void WorldInfo::write(QTextStream& stream)
{
stream << "#MC: " << mc2str(mc) << "\n";
stream << "#Large: " << large << "\n";
+ stream.flush();
}
void LayerOpt::reset()
@@ -361,6 +363,7 @@ void Config::reset()
//fontNorm.setFamily(QString::fromUtf8("DejaVu Sans"));
//fontMono.setFamily(QString::fromUtf8("DejaVu Sans Mono"));
fontMono.setStyleHint(QFont::Monospace);
+ fontMono.setFixedPitch(true);
fontNorm.setStyleHint(QFont::AnyStyle);
fontMono.setPointSize(10);
fontNorm.setPointSize(10);
@@ -460,6 +463,7 @@ void Gen48Config::write(QTextStream& stream)
stream << "#Gen48X2: " << x2 << "\n";
stream << "#Gen48Z2: " << z2 << "\n";
}
+ stream.flush();
}
uint64_t Gen48Config::estimateSeedCnt(uint64_t slist48len)
@@ -480,8 +484,8 @@ uint64_t Gen48Config::estimateSeedCnt(uint64_t slist48len)
else if (mode == GEN48_QM)
{
cnt = 0;
- for (int i = 0, n = sizeof(g_qm_90) / sizeof(int64_t); i < n; i++)
- if (qmonumentQual(g_qm_90[i]) >= qmarea)
+ for (const uint64_t *s = g_qm_90; *s; s++)
+ if (qmonumentQual(*s) >= qmarea)
cnt++;
}
else if (mode == GEN48_LIST)
@@ -544,5 +548,6 @@ void SearchConfig::write(QTextStream& stream)
stream << "#SMin: " << smin << "\n";
if (smax != ~(uint64_t)0)
stream << "#SMax: " << smax << "\n";
+ stream.flush();
}
diff --git a/src/configdialog.cpp b/src/configdialog.cpp
index dfb1869..0e1e12a 100644
--- a/src/configdialog.cpp
+++ b/src/configdialog.cpp
@@ -1,15 +1,10 @@
#include "configdialog.h"
#include "ui_configdialog.h"
-#include "biomecolordialog.h"
-#include "maptoolsdialog.h"
-#include "world.h"
-#include "util.h"
-
-#include
-#include
#include
+#include
#include
+#include
ConfigDialog::ConfigDialog(QWidget *parent, Config *config)
@@ -32,7 +27,7 @@ ConfigDialog::ConfigDialog(QWidget *parent, Config *config)
ui->lineIconScale->setValidator(new QDoubleValidator(1.0/8, 16.0, 3, ui->lineIconScale));
QString rclang = ":/lang";
- QDirIterator it(rclang, QDirIterator::Subdirectories);
+ QDirIterator it(rclang);
while (it.hasNext())
{
QString fnam = it.next();
diff --git a/src/exportdialog.cpp b/src/exportdialog.cpp
index c279397..640b104 100644
--- a/src/exportdialog.cpp
+++ b/src/exportdialog.cpp
@@ -3,15 +3,19 @@
#include "mainwindow.h"
#include "mapview.h"
-#include "util.h"
#include "message.h"
+#include "util.h"
-#include
#include
-#include
-#include
+#include
#include
+#include
+#include
+#if WASM
+#include "qzipwriter.h"
+#include
+#endif
void ExportWorker::runWorkItem(const ExportWorkItem& work)
{
@@ -154,6 +158,12 @@ ExportDialog::ExportDialog(MainWindow *parent)
ui->lineEditX2->setText(settings.value("export/x1").toString());
ui->lineEditZ2->setText(settings.value("export/z1").toString());
+#if WASM
+ ui->labelDir->setVisible(false);
+ ui->lineDir->setVisible(false);
+ ui->buttonDirSelect->setVisible(false);
+#endif
+
update();
}
@@ -177,8 +187,12 @@ bool ExportDialog::initWork(ExportWorkItem *work, uint64_t seed, int tx, int tz)
work->fnam.replace("%S", QString::number((int64_t)seed));
work->fnam.replace("%x", QString::number(tx));
work->fnam.replace("%z", QString::number(tz));
+#if WASM
+ return false;
+#else
work->fnam = dir.filePath(work->fnam);
return QFileInfo::exists(work->fnam);
+#endif
}
bool ExportDialog::requestWork(ExportWorkItem *work)
@@ -205,6 +219,29 @@ void ExportDialog::onWorkerFinished()
for (ExportWorker *worker : qAsConst(workers))
if (worker->isRunning())
return;
+
+#if WASM
+ QByteArray content;
+ QBuffer buffer(&content);
+ buffer.open(QIODevice::WriteOnly);
+ QZipWriter zipwriter(&buffer);
+ zipwriter.setCompressionPolicy(QZipWriter::AutoCompress);
+
+ for (const QString& fnam : qAsConst(paths))
+ {
+ QFile file(fnam);
+ if (file.open(QFile::ReadOnly))
+ {
+ zipwriter.addFile(fnam, &file);
+ file.close();
+ QFile::remove(fnam);
+ }
+ }
+ zipwriter.close();
+
+ QFileDialog::saveFileContent(content, "images.zip");
+#endif
+
emit exportFinished();
}
@@ -364,6 +401,7 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
this->tilesize = -1;
this->heightvis = ui->comboHeightVis->currentIndex() - 1;
this->bgmode = 0;
+ this->paths.clear();
bool existwarn = false;
if (tiled)
@@ -387,6 +425,7 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
ExportWorkItem work;
existwarn |= initWork(&work, seed, x, z);
workitems.push_back(work);
+ paths.push_back(work.fnam);
}
}
}
@@ -396,9 +435,10 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
int maxsiz = 0x8000;
if (x1 - x0 >= maxsiz || z1 - z0 >= maxsiz)
{
- int button = warn(this, tr("Consider tiling very large images into smaller sections.\nContinue?"),
- QMessageBox::Cancel | QMessageBox::Yes);
- if (button == QMessageBox::Cancel)
+ int button = warn(this, tr("Warning"),
+ tr("Consider tiling very large images into smaller sections."),
+ tr("Continue?"), QMessageBox::Cancel | QMessageBox::Yes);
+ if (button != QMessageBox::Yes)
{
return;
}
@@ -409,14 +449,16 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
ExportWorkItem work;
existwarn |= initWork(&work, seed, 0, 0);
workitems.push_back(work);
+ paths.push_back(work.fnam);
}
}
if (existwarn)
{
- int button = warn(this, tr("One or more of files already exist.\nContinue and overwrite?"),
- QMessageBox::Cancel | QMessageBox::Yes);
- if (button == QMessageBox::Cancel)
+ int button = warn(this, tr("Warning"),
+ tr("One or more of files already exist."),
+ tr("Continue and overwrite?"), QMessageBox::Cancel | QMessageBox::Yes);
+ if (button != QMessageBox::Yes)
{
return;
}
diff --git a/src/exportdialog.h b/src/exportdialog.h
index 0304065..805c014 100644
--- a/src/exportdialog.h
+++ b/src/exportdialog.h
@@ -89,6 +89,7 @@ private slots:
QMutex mutex;
QList workitems;
QVector workers;
+ QVector paths;
std::atomic_bool stop;
};
diff --git a/src/exportdialog.ui b/src/exportdialog.ui
index 2dc81ca..89e239f 100644
--- a/src/exportdialog.ui
+++ b/src/exportdialog.ui
@@ -35,7 +35,7 @@
-
-
+
Export directory:
@@ -212,7 +212,7 @@
-
-
+
@@ -450,16 +450,16 @@
-
- CoordEdit
- QLineEdit
-
-
StyledComboBox
QComboBox
+
+ CoordEdit
+ QLineEdit
+
+
diff --git a/src/formconditions.cpp b/src/formconditions.cpp
index 0391c6e..84bfd0a 100644
--- a/src/formconditions.cpp
+++ b/src/formconditions.cpp
@@ -4,9 +4,9 @@
#include "conditiondialog.h"
#include "mainwindow.h"
-#include
-#include
#include
+#include
+#include
QDataStream& operator<<(QDataStream& out, const Condition& v)
@@ -74,6 +74,10 @@ FormConditions::FormConditions(QWidget *parent)
}
}
+#if WASM
+ ui->listConditions->setDragDropMode(QAbstractItemView::NoDragDrop);
+#endif
+
qRegisterMetaType< Condition >("Condition");
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
qRegisterMetaTypeStreamOperators< Condition >("Condition");
@@ -85,9 +89,9 @@ FormConditions::~FormConditions()
delete ui;
}
-QVector FormConditions::getConditions() const
+std::vector FormConditions::getConditions() const
{
- QVector conds;
+ std::vector conds;
for (int i = 0, ie = ui->listConditions->count(); i < ie; i++)
{
@@ -119,12 +123,12 @@ void FormConditions::updateSensitivity()
ui->buttonEdit->setEnabled(false);
}
- QVector selcond;
+ std::vector selcond;
int disabled = 0;
for (int i = 0; i < selected.size(); i++)
{
Condition c = qvariant_cast(selected[i]->data(Qt::UserRole));
- selcond.append(c);
+ selcond.push_back(c);
if (c.meta & Condition::DISABLED)
disabled++;
}
@@ -142,7 +146,7 @@ void FormConditions::updateSensitivity()
int FormConditions::getIndex(int idx) const
{
- const QVector condvec = getConditions();
+ const std::vector condvec = getConditions();
int cnt[100] = {};
for (const Condition& c : condvec)
if (c.save >= 0 && c.save < 100)
@@ -283,7 +287,7 @@ void FormConditions::on_buttonAddFilter_clicked()
void FormConditions::on_listConditions_customContextMenuRequested(const QPoint &pos)
{
- QMenu menu(this);
+ QMenu *menu = new QMenu(this);
// this is a contextual temporary menu so shortcuts are only indicated here,
// but will not function - see keyReleaseEvent() for shortcut implementation
@@ -291,46 +295,46 @@ void FormConditions::on_listConditions_customContextMenuRequested(const QPoint &
if (parent)
{
- QAction *actadd = menu.addAction(QIcon::fromTheme("list-add"),
+ QAction *actadd = menu->addAction(QIcon::fromTheme("list-add"),
tr("Add new condition"), this,
&FormConditions::conditionsAdd, QKeySequence::New);
actadd->setEnabled(true);
- QAction *actedit = menu.addAction(QIcon(),
+ QAction *actedit = menu->addAction(QIcon(),
tr("Edit condition"), this,
&FormConditions::conditionsEdit, QKeySequence::Open);
actedit->setEnabled(n == 1);
- QAction *actcut = menu.addAction(QIcon::fromTheme("edit-cut"),
+ QAction *actcut = menu->addAction(QIcon::fromTheme("edit-cut"),
tr("Cut %n condition(s)", "", n), this,
&FormConditions::conditionsCut, QKeySequence::Cut);
actcut->setEnabled(n > 0);
- QAction *actcopy = menu.addAction(QIcon::fromTheme("edit-copy"),
+ QAction *actcopy = menu->addAction(QIcon::fromTheme("edit-copy"),
tr("Copy %n condition(s)", "", n), this,
&FormConditions::conditionsCopy, QKeySequence::Copy);
actcopy->setEnabled(n > 0);
int pn = conditionsPaste(true);
- QAction *actpaste = menu.addAction(QIcon::fromTheme("edit-paste"),
+ QAction *actpaste = menu->addAction(QIcon::fromTheme("edit-paste"),
tr("Paste %n condition(s)", "", pn), this,
&FormConditions::conditionsPaste, QKeySequence::Paste);
actpaste->setEnabled(pn > 0);
- QAction *actdel = menu.addAction(QIcon::fromTheme("edit-delete"),
+ QAction *actdel = menu->addAction(QIcon::fromTheme("edit-delete"),
tr("Remove %n condition(s)", "", n), this,
&FormConditions::conditionsDelete, QKeySequence::Delete);
actdel->setEnabled(n > 0);
}
else
{
- QAction *actcopy = menu.addAction(QIcon::fromTheme("edit-copy"),
+ QAction *actcopy = menu->addAction(QIcon::fromTheme("edit-copy"),
tr("Copy %n condition(s)", "", n), this,
&FormConditions::conditionsCopy, QKeySequence::Copy);
actcopy->setEnabled(n > 0);
}
- menu.exec(ui->listConditions->mapToGlobal(pos));
+ menu->popup(ui->listConditions->mapToGlobal(pos));
}
void FormConditions::on_listConditions_itemDoubleClicked(QListWidgetItem *item)
diff --git a/src/formconditions.h b/src/formconditions.h
index 8db3b69..baa3678 100644
--- a/src/formconditions.h
+++ b/src/formconditions.h
@@ -5,7 +5,7 @@
#include
#include
-#include "searchthread.h"
+#include "search.h"
namespace Ui {
class FormConditions;
@@ -34,7 +34,7 @@ class FormConditions : public QWidget
explicit FormConditions(QWidget *parent = nullptr);
~FormConditions();
- QVector getConditions() const;
+ std::vector getConditions() const;
void updateSensitivity();
int getIndex(int idx) const;
@@ -46,7 +46,7 @@ class FormConditions : public QWidget
signals:
void changed();
- void selectionUpdate(const QVector& selected);
+ void selectionUpdate(const std::vector& selected);
public slots:
void on_buttonRemoveAll_clicked();
diff --git a/src/formgen48.cpp b/src/formgen48.cpp
index 9e248ad..a1f27f3 100644
--- a/src/formgen48.cpp
+++ b/src/formgen48.cpp
@@ -2,11 +2,10 @@
#include "ui_formgen48.h"
#include "mainwindow.h"
+#include "message.h"
#include "search.h"
#include "seedtables.h"
-#include "message.h"
-
-#include "cubiomes/util.h"
+#include "util.h"
#include
#include
@@ -22,8 +21,8 @@ class SetSpinBox : public QSpinBox
: QSpinBox(parent)
{
std::set vset;
- for (int i = 0, n = sizeof(g_qm_90) / sizeof(int64_t); i < n; i++)
- vset.insert(qmonumentQual(g_qm_90[i]));
+ for (const uint64_t *s = g_qm_90; *s; s++)
+ vset.insert(qmonumentQual(*s));
for (int v : vset)
vlist.push_back(v);
@@ -112,9 +111,10 @@ bool FormGen48::setList48(QString path, bool quiet)
}
else if (!quiet)
{
- int button = warn(this, tr("Failed to load 48-bit seed list from file:\n\"%1\"").arg(path),
- QMessageBox::Reset|QMessageBox::Ignore);
- if (button == QMessageBox::Reset)
+ int button = warn(this, tr("Warning"),
+ tr("Failed to load 48-bit seed list from file:\n\"%1\"").arg(path),
+ tr("Reset list path?"), QMessageBox::Reset | QMessageBox::Ignore);
+ if (button != QMessageBox::Ignore)
{
slist48path.clear();
slist48.clear();
@@ -144,6 +144,26 @@ bool FormGen48::setList48(QString path, bool quiet)
return ok;
}
+bool FormGen48::setList48(QTextStream& stream)
+{
+ slist48path.clear();
+ slist48.clear();
+ while (!stream.atEnd())
+ {
+ QByteArray line = stream.readLine().toLocal8Bit();
+ uint64_t s = 0;
+ if (sscanf(line.data(), "%" PRId64, (int64_t*)&s) == 1)
+ slist48.push_back(s);
+ }
+
+ if (slist48.empty())
+ ui->lineList48->setText(tr("[no seeds!]"));
+ else
+ ui->lineList48->setText(tr("[%n seed(s)]", "", slist48.size()));
+
+ emit changed();
+ return true;
+}
void FormGen48::setConfig(const Gen48Config& gen48, bool quiet)
@@ -158,7 +178,11 @@ void FormGen48::setConfig(const Gen48Config& gen48, bool quiet)
ui->lineEditX2->setText(QString::number(gen48.x2));
ui->lineEditZ2->setText(QString::number(gen48.z2));
+#if WASM
+ (void) quiet;
+#else
setList48(gen48.slist48path, quiet);
+#endif
if (gen48.manualarea)
ui->radioManual->setChecked(true);
@@ -220,7 +244,7 @@ void FormGen48::updateCount()
}
-void FormGen48::updateAutoConditions(const QVector& condlist)
+void FormGen48::updateAutoConditions(const std::vector& condlist)
{
cond.type = 0;
for (const Condition& c : condlist)
@@ -350,10 +374,20 @@ void FormGen48::on_comboLow20_currentIndexChanged(int)
void FormGen48::on_buttonBrowse_clicked()
{
- QString fnam = QFileDialog::getOpenFileName(
- this, tr("Load seed list"), parent->prevdir, tr("Text files (*.txt);;Any files (*)"));
+ QString filter = tr("Text files (*.txt);;Any files (*)");
+#if WASM
+ auto fileOpenCompleted = [=](const QString &fnam, const QByteArray &content) {
+ if (!fnam.isEmpty()) {
+ QTextStream stream(content);
+ setList48(stream);
+ }
+ };
+ QFileDialog::getOpenFileContent(filter, fileOpenCompleted);
+#else
+ QString fnam = QFileDialog::getOpenFileName(this, tr("Load seed list"), parent->prevdir, filter);
if (!fnam.isEmpty())
setList48(fnam, false);
+#endif
}
void FormGen48::on_radioAuto_toggled()
diff --git a/src/formgen48.h b/src/formgen48.h
index 9de44db..1919916 100644
--- a/src/formgen48.h
+++ b/src/formgen48.h
@@ -1,8 +1,8 @@
#ifndef FORMGEN48_H
#define FORMGEN48_H
-#include
#include
+#include
#include "config.h"
#include "search.h"
@@ -26,12 +26,13 @@ class FormGen48 : public QWidget
Gen48Config getConfig(bool resolveauto = false);
bool setList48(QString path, bool quiet);
+ bool setList48(QTextStream& stream);
const std::vector& getList48() { return slist48; }
uint64_t estimateSeedCnt();
void updateCount();
- void updateAutoConditions(const QVector& condlist);
+ void updateAutoConditions(const std::vector& condlist);
void updateAutoUi();
signals:
diff --git a/src/formsearchcontrol.cpp b/src/formsearchcontrol.cpp
index aecfd48..bcd1ebd 100644
--- a/src/formsearchcontrol.cpp
+++ b/src/formsearchcontrol.cpp
@@ -2,18 +2,16 @@
#include "ui_formsearchcontrol.h"
#include "mainwindow.h"
-#include "search.h"
-#include "rangedialog.h"
#include "message.h"
+#include "rangedialog.h"
+#include "search.h"
#include "util.h"
-#include "cubiomes/util.h"
-
-#include
#include
#include
#include
#include
+#include
QVariant SeedTableModel::data(const QModelIndex& index, int role) const
@@ -93,6 +91,8 @@ void SeedTableModel::removeRow(int row)
void SeedTableModel::reset()
{
+ if (seeds.empty())
+ return;
beginRemoveRows(QModelIndex(), 0, seeds.size());
seeds.clear();
endRemoveRows();
@@ -104,7 +104,6 @@ FormSearchControl::FormSearchControl(MainWindow *parent)
, ui(new Ui::FormSearchControl)
, model()
, proxy()
- , protodialog()
, sthread(this)
, elapsed()
, stimer()
@@ -119,7 +118,6 @@ FormSearchControl::FormSearchControl(MainWindow *parent)
, updt(20)
{
ui->setupUi(this);
- protodialog = new ProtoBaseDialog(this);
ui->comboSearchType->addItem(tr("incremental"), SEARCH_INC);
ui->comboSearchType->addItem(tr("48-bit only"), SEARCH_48ONLY);
@@ -158,8 +156,6 @@ FormSearchControl::~FormSearchControl()
{
stimer.stop();
sthread.stop(); // tell search to stop at next convenience
- sthread.quit(); // tell the event loop to exit
- sthread.wait(); // wait for search to finish
delete ui;
}
@@ -217,8 +213,12 @@ bool FormSearchControl::setSearchConfig(SearchConfig s, bool quiet)
smin = s.smin;
smax = s.smax;
+#if WASM
+ (void) quiet;
+#else
if (ok)
ok &= setList64(s.slist64path, quiet);
+#endif
ui->lineStart->setText(QString::asprintf("%" PRId64, (int64_t)s.startseed));
@@ -254,9 +254,10 @@ bool FormSearchControl::setList64(QString path, bool quiet)
}
else if (!quiet)
{
- int button = warn(this, tr("Failed to load 64-bit seed list from file:\n\"%1\"").arg(path),
- QMessageBox::Reset|QMessageBox::Ignore);
- if (button == QMessageBox::Reset)
+ int button = warn(this, tr("Warning"),
+ tr("Failed to load 64-bit seed list from file:\n\"%1\"").arg(path),
+ tr("Reset list path?"), QMessageBox::Reset | QMessageBox::Ignore);
+ if (button != QMessageBox::Ignore)
{
slist64fnam.clear();
slist64path.clear();
@@ -267,6 +268,26 @@ bool FormSearchControl::setList64(QString path, bool quiet)
return false;
}
+bool FormSearchControl::setList64(QTextStream& stream)
+{
+ slist64fnam.clear();
+ slist64path.clear();
+ slist64.clear();
+
+ while (!stream.atEnd())
+ {
+ QByteArray line = stream.readLine().toLocal8Bit();
+ uint64_t s = 0;
+ if (sscanf(line.data(), "%" PRId64, (int64_t*)&s) == 1)
+ slist64.push_back(s);
+ }
+
+ if (!slist64.empty())
+ updateSearchProgress(0, slist64.size(), slist64[0]);
+
+ return true;
+}
+
void FormSearchControl::setResultsPath(QString path)
{
resultfile.close();
@@ -310,22 +331,11 @@ void FormSearchControl::setSearchMode(int mode)
}
}
-
-int FormSearchControl::warning(QString text, QMessageBox::StandardButtons buttons)
-{
- return warn(this, text, buttons);
-}
-
-void FormSearchControl::openProtobaseMsg(QString path)
-{
- protodialog->setPath(path);
- protodialog->show();
-}
-
-void FormSearchControl::closeProtobaseMsg()
+void FormSearchControl::setSearchRange(uint64_t smin, uint64_t smax)
{
- if (protodialog->closeOnDone())
- protodialog->close();
+ this->smin = smin;
+ this->smax = smax;
+ searchProgressReset();
}
void FormSearchControl::on_buttonClear_clicked()
@@ -355,12 +365,6 @@ void FormSearchControl::on_buttonStart_clicked()
warn(this, tr("No seed list file selected."));
ok = false;
}
- if (sthread.isRunning())
- {
- warn(this, tr("Search is still running."));
- ok = false;
- }
-
if (ok)
{
session.gen48 = parent->formGen48->getConfig(true);
@@ -418,19 +422,25 @@ void FormSearchControl::on_buttonMore_clicked()
int type = ui->comboSearchType->currentData().toInt();
if (type == SEARCH_LIST)
{
- QString fnam = QFileDialog::getOpenFileName(
- this, tr("Load seed list"), parent->prevdir, tr("Text files (*.txt);;Any files (*)"));
+ QString filter = tr("Text files (*.txt);;Any files (*)");
+#if WASM
+ auto fileOpenCompleted = [=](const QString &fnam, const QByteArray &content) {
+ if (!fnam.isEmpty()) {
+ QTextStream stream(content);
+ setList64(stream);
+ }
+ };
+ QFileDialog::getOpenFileContent(filter, fileOpenCompleted);
+#else
+ QString fnam = QFileDialog::getOpenFileName(this, tr("Load seed list"), parent->prevdir, filter);
setList64(fnam, false);
+#endif
}
else if (type == SEARCH_INC)
{
RangeDialog *dialog = new RangeDialog(this, smin, smax);
- int status = dialog->exec();
- if (status == QDialog::Accepted)
- {
- dialog->getBounds(&smin, &smax);
- searchProgressReset();
- }
+ connect(dialog, &RangeDialog::applyBounds, this, &FormSearchControl::setSearchRange);
+ dialog->show();
}
}
@@ -452,40 +462,40 @@ void FormSearchControl::on_results_clicked(const QModelIndex &)
void FormSearchControl::on_results_customContextMenuRequested(const QPoint &pos)
{
- QMenu menu(this);
+ QMenu *menu = new QMenu(this);
// this is a contextual temporary menu so shortcuts are only indicated here,
// but will not function - see keyReleaseEvent() for shortcut implementation
- QAction *actremove = menu.addAction(QIcon::fromTheme("list-remove"),
+ QAction *actremove = menu->addAction(QIcon::fromTheme("list-remove"),
tr("Remove selected seed"), this,
&FormSearchControl::removeCurrent, QKeySequence::Delete);
actremove->setEnabled(ui->results->selectionModel()->hasSelection());
- QAction *actcopyseed = menu.addAction(QIcon::fromTheme("edit-copy"),
+ QAction *actcopyseed = menu->addAction(QIcon::fromTheme("edit-copy"),
tr("Copy selected seed"), this,
&FormSearchControl::copySeed, QKeySequence::Copy);
actcopyseed->setEnabled(ui->results->selectionModel()->hasSelection());
- QAction *actcopylist = menu.addAction(QIcon::fromTheme("edit-copy"),
+ QAction *actcopylist = menu->addAction(QIcon::fromTheme("edit-copy"),
tr("Copy seed list"), this,
&FormSearchControl::copyResults, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_C));
actcopylist->setEnabled(ui->results->model()->rowCount() > 0);
int n = pasteList(true);
- QAction *actpaste = menu.addAction(QIcon::fromTheme("edit-paste"),
+ QAction *actpaste = menu->addAction(QIcon::fromTheme("edit-paste"),
tr("Paste %n seed(s) from clipboard", "", n), this,
&FormSearchControl::pasteResults, QKeySequence::Paste);
actpaste->setEnabled(n > 0);
- menu.exec(ui->results->mapToGlobal(pos));
+ menu->popup(ui->results->mapToGlobal(pos));
}
void FormSearchControl::on_buttonSearchHelp_clicked()
{
- QMessageBox mb(this);
- mb.setIcon(QMessageBox::Information);
- mb.setWindowTitle(tr("Help: search types"));
- mb.setText(tr(
+ QMessageBox *mb = new QMessageBox(this);
+ mb->setIcon(QMessageBox::Information);
+ mb->setWindowTitle(tr("Help: search types"));
+ mb->setText(tr(
""
"The incremental search checks seeds in numerical order, "
"except for grouping seeds into work items for parallelization. "
@@ -511,7 +521,7 @@ void FormSearchControl::on_buttonSearchHelp_clicked()
"this option.)"
"
"
));
- mb.exec();
+ mb->show();
}
void FormSearchControl::on_comboSearchType_currentIndexChanged(int)
diff --git a/src/formsearchcontrol.h b/src/formsearchcontrol.h
index 8bc2f83..13a3691 100644
--- a/src/formsearchcontrol.h
+++ b/src/formsearchcontrol.h
@@ -1,20 +1,19 @@
#ifndef FORMSEARCHCONTROL_H
#define FORMSEARCHCONTROL_H
-#include
-#include
+#include
+#include
+#include
#include
#include
-#include
-#include
#include
-#include
-
-#include
+#include
+#include
-#include "searchthread.h"
-#include "protobasedialog.h"
#include "config.h"
+#include "searchthread.h"
+
+#include
namespace Ui {
class FormSearchControl;
@@ -107,6 +106,7 @@ class FormSearchControl : public QWidget
void stopSearch();
bool setList64(QString path, bool quiet);
+ bool setList64(QTextStream& stream);
void setResultsPath(QString path);
@@ -120,9 +120,7 @@ class FormSearchControl : public QWidget
void resultsAdded(int cnt);
public slots:
- int warning(QString text, QMessageBox::StandardButtons buttons = QMessageBox::Ok);
- void openProtobaseMsg(QString path);
- void closeProtobaseMsg();
+ void setSearchRange(uint64_t smin, uint64_t smax);
void on_buttonClear_clicked();
void on_buttonStart_clicked();
@@ -158,7 +156,6 @@ public slots:
Ui::FormSearchControl *ui;
SeedTableModel *model;
SeedSortProxy *proxy;
- ProtoBaseDialog *protodialog;
SearchMaster sthread;
QElapsedTimer elapsed;
QTimer stimer;
diff --git a/src/gotodialog.cpp b/src/gotodialog.cpp
index 46d5d43..a128229 100644
--- a/src/gotodialog.cpp
+++ b/src/gotodialog.cpp
@@ -2,11 +2,10 @@
#include "ui_gotodialog.h"
#include "mapview.h"
-#include "message.h"
+#include
#include
#include
-#include
static bool g_animate;
@@ -44,13 +43,6 @@ void GotoDialog::on_buttonBox_clicked(QAbstractButton *button)
qreal x = ui->lineX->text().toDouble();
qreal z = ui->lineZ->text().toDouble();
qreal scale = ui->lineScale->text().toDouble();
- if (scale > 4096)
- {
- int button = warn(this, tr("Setting a very large scale may be unsafe.\n"
- "Continue anyway?"), QMessageBox::Abort|QMessageBox::Yes);
- if (button == QMessageBox::Abort)
- return;
- }
if (scale < scalemin) scale = scalemin;
if (scale > scalemax) scale = scalemax;
ui->lineScale->setText(QString::asprintf("%.4f", scale));
@@ -68,13 +60,21 @@ void GotoDialog::on_buttonBox_clicked(QAbstractButton *button)
}
}
+void GotoDialog::on_lineScale_textChanged(const QString &text)
+{
+ qreal value = text.toDouble();
+ ui->lineScale->setStyleSheet(value > 4096 ? "color: red" : "");
+}
+
void GotoDialog::keyPressEvent(QKeyEvent *event)
{
+ static QRegularExpression coord_delim = QRegularExpression("[, ]+");
+
if (event->matches(QKeySequence::Paste))
{
QClipboard *clipboard = QGuiApplication::clipboard();
QString s = clipboard->text().trimmed();
- QStringList xz = s.split(QRegularExpression("[, ]+"));
+ QStringList xz = s.split(coord_delim);
if (xz.count() == 2)
{
ui->lineX->setText(xz[0]);
@@ -91,3 +91,4 @@ void GotoDialog::keyPressEvent(QKeyEvent *event)
QWidget::keyReleaseEvent(event);
}
+
diff --git a/src/gotodialog.h b/src/gotodialog.h
index 04f370e..7a40d5f 100644
--- a/src/gotodialog.h
+++ b/src/gotodialog.h
@@ -20,6 +20,7 @@ class GotoDialog : public QDialog
void keyPressEvent(QKeyEvent *event) override;
private slots:
+ void on_lineScale_textChanged(const QString &text);
void on_buttonBox_clicked(QAbstractButton *button);
private:
diff --git a/src/gotodialog.ui b/src/gotodialog.ui
index 89c722b..a4f3275 100644
--- a/src/gotodialog.ui
+++ b/src/gotodialog.ui
@@ -80,6 +80,9 @@
Qt::StrongFocus
+
+ A very large scale may be unsafe
+
-
diff --git a/src/headless.cpp b/src/headless.cpp
index 8186aca..0f251a7 100644
--- a/src/headless.cpp
+++ b/src/headless.cpp
@@ -1,13 +1,11 @@
#include "headless.h"
+
#include "message.h"
-#include "aboutdialog.h"
+#include "util.h"
-#include
#include
#include
-
-#include "cubiomes/util.h"
-
+#include
#if defined(_WIN32)
#include
@@ -89,7 +87,15 @@ bool Headless::loadSession(QString sessionpath)
qOut() << "Loading session: \"" << sessionpath << "\"\n";
qOut().flush();
- if (!session.load(nullptr, sessionpath, false))
+ QFile file(sessionpath);
+ if (!file.open(QFile::ReadOnly))
+ {
+ warn(nullptr, "Path could not be opened.");
+ return false;
+ }
+
+ QTextStream stream(&file);
+ if (!session.load(nullptr, stream, false))
{
return false;
}
diff --git a/src/main.cpp b/src/main.cpp
index 8c68fed..31e6b54 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,17 +1,14 @@
-#include "mainwindow.h"
+#include "aboutdialog.h"
#include "headless.h"
+#include "mainwindow.h"
-#include "aboutdialog.h"
-#include "world.h"
+#include "cubiomes/util.h"
#include
-#include
+#include
#include
+#include
#include
-#include
-
-#include "cubiomes/generator.h"
-#include "cubiomes/util.h"
extern "C"
int getStructureConfig_override(int stype, int mc, StructureConfig *sconf)
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index a5618e1..e517cd5 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1,42 +1,42 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
-#include "presetdialog.h"
#include "aboutdialog.h"
-#include "conditiondialog.h"
-#include "extgendialog.h"
#include "biomecolordialog.h"
-#include "maptoolsdialog.h"
+#include "configdialog.h"
#include "exportdialog.h"
+#include "extgendialog.h"
#include "layerdialog.h"
-#include "tablocations.h"
+#include "maptoolsdialog.h"
+#include "message.h"
+#include "presetdialog.h"
#include "tabbiomes.h"
+#include "tablocations.h"
#include "tabstructures.h"
-#include "message.h"
-#include "world.h"
#include "util.h"
+#include "world.h"
#if WITH_UPDATER
#include "updater.h"
#endif
-#include
-#include
-#include
+#include
+#include
#include
-#include
-#include
-#include
-#include
-#include
#include
-#include
#include
#include
-#include
-#include
+#include
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#if WITH_DBUS
#include
@@ -284,6 +284,12 @@ MainWindow::MainWindow(QString sessionpath, QString resultspath, QWidget *parent
onConditionsChanged();
update();
+#if WASM
+ ui->menuFile->removeAction(ui->actionPresetLoad);
+ ui->menuFile->removeAction(ui->actionPresetSave);
+ ui->menuFile->removeAction(ui->actionQuit);
+#endif
+
#if WITH_UPDATER
QAction *updateaction = new QAction("Check for updates", this);
connect(updateaction, &QAction::triggered, [=]() { searchForUpdates(false); });
@@ -507,12 +513,16 @@ void MainWindow::loadSettings()
onUpdateConfig();
+#if WASM
+ showFullScreen();
+#else
if (settings.value("mainwindow/maximized", isMaximized()).toBool()) {
showMaximized();
} else if (config.restoreWindow) {
resize(settings.value("mainwindow/size", size()).toSize());
move(settings.value("mainwindow/pos", pos()).toPoint());
}
+#endif
prevdir = settings.value("mainwindow/prevdir", prevdir).toString();
int toolarea = toolBarArea(ui->toolBar);
@@ -556,12 +566,38 @@ void MainWindow::loadSettings()
if (config.restoreSession && QFile::exists(sessionpath))
{
- loadSession(sessionpath, false, false);
+ loadSession(sessionpath, false);
}
}
+bool MainWindow::saveSession(QString path, bool quiet)
+{
+ QFile file(path);
+ if (!file.open(QIODevice::WriteOnly))
+ {
+ if (!quiet)
+ warn(this, tr("Failed to open file:\n\"%1\"").arg(path));
+ return false;
+ }
+
+ QTextStream stream(&file);
+ return saveSession(stream);
+}
+
+bool MainWindow::loadSession(QString fnam, bool keepresults)
+{
+ QFile file(fnam);
+ if (!file.open(QIODevice::ReadOnly))
+ {
+ warn(this, QApplication::tr("Failed to open session file:\n\"%1\"").arg(fnam));
+ return false;
+ }
+
+ QTextStream stream(&file);
+ return loadSession(stream, keepresults, false);
+}
-bool MainWindow::saveSession(QString fnam, bool quiet)
+bool MainWindow::saveSession(QTextStream& stream)
{
Session session;
session.sc = formControl->getSearchConfig();
@@ -569,11 +605,10 @@ bool MainWindow::saveSession(QString fnam, bool quiet)
session.cv = formCond->getConditions();
session.slist = formControl->getResults();
getSeed(&session.wi);
-
- return session.save(this, fnam, quiet);
+ return session.save(this, stream);
}
-bool MainWindow::loadSession(QString fnam, bool keepresults, bool quiet)
+bool MainWindow::loadSession(QTextStream& stream, bool keepresults, bool quiet)
{
Session session;
// build current session before loading to keep unspecified values the same
@@ -581,7 +616,7 @@ bool MainWindow::loadSession(QString fnam, bool keepresults, bool quiet)
session.sc = formControl->getSearchConfig();
session.gen48 = formGen48->getConfig(false);
- if (!session.load(this, fnam, quiet))
+ if (!session.load(this, stream, quiet))
return false;
setSeed(session.wi);
@@ -792,26 +827,43 @@ void MainWindow::on_seedEdit_textChanged(const QString &a)
void MainWindow::on_actionSave_triggered()
{
- QString fnam = QFileDialog::getSaveFileName(
- this, tr("Save progress"), prevdir, tr("Session files (*.session *.txt);;Any files (*)"));
+#if WASM
+ QByteArray content;
+ QTextStream stream(&content);
+ saveSession(stream);
+ QFileDialog::saveFileContent(content, "session.txt");
+#else
+ QString filter = tr("Session files (*.session *.txt);;Any files (*)");
+ QString fnam = QFileDialog::getSaveFileName(this, tr("Save progress"), prevdir, filter);
if (!fnam.isEmpty())
{
QFileInfo finfo(fnam);
prevdir = finfo.absolutePath();
- saveSession(fnam);
+ saveSession(fnam, false);
}
+#endif
}
void MainWindow::on_actionLoad_triggered()
{
- QString fnam = QFileDialog::getOpenFileName(
- this, tr("Load progress"), prevdir, tr("Session files (*.session *.txt);;Any files (*)"));
+ QString filter = tr("Session files (*.session *.txt);;Any files (*)");
+#if WASM
+ auto fileOpenCompleted = [=](const QString &fnam, const QByteArray &content) {
+ if (!fnam.isEmpty()) {
+ QTextStream stream(content);
+ loadSession(stream, false, false);
+ }
+ };
+ QFileDialog::getOpenFileContent(filter, fileOpenCompleted);
+#else
+ QString fnam = QFileDialog::getOpenFileName(this, tr("Load progress"), prevdir, filter);
if (!fnam.isEmpty())
{
QFileInfo finfo(fnam);
prevdir = finfo.absolutePath();
- loadSession(fnam, false, false);
+ loadSession(fnam, false);
}
+#endif
}
void MainWindow::on_actionQuit_triggered()
@@ -844,7 +896,7 @@ void MainWindow::on_actionOpenShadow_triggered()
void MainWindow::on_actionRedistribute_triggered()
{
- QVector conds = formCond->getConditions();
+ std::vector conds = formCond->getConditions();
if (!conds.empty())
{
QMap ids;
@@ -885,8 +937,8 @@ void MainWindow::on_actionPresetLoad_triggered()
getSeed(&wi);
PresetDialog *dialog = new PresetDialog(this, wi, false);
dialog->setActiveFilter(formCond->getConditions());
- if (dialog->exec() && !dialog->rc.isEmpty())
- loadSession(dialog->rc, true, false);
+ connect(dialog, &QDialog::accepted, [=] { loadSession(dialog->rc, true); });
+ dialog->show();
}
void MainWindow::on_actionExamples_triggered()
@@ -895,8 +947,8 @@ void MainWindow::on_actionExamples_triggered()
getSeed(&wi);
PresetDialog *dialog = new PresetDialog(this, wi, true);
dialog->setActiveFilter(formCond->getConditions());
- if (dialog->exec() && !dialog->rc.isEmpty())
- loadSession(dialog->rc, true, false);
+ connect(dialog, &QDialog::accepted, [=] { loadSession(dialog->rc, true); });
+ dialog->show();
}
void MainWindow::on_actionAbout_triggered()
@@ -928,15 +980,14 @@ void MainWindow::on_actionAddShadow_triggered()
void MainWindow::on_actionExtGen_triggered()
{
ExtGenDialog *dialog = new ExtGenDialog(this, &g_extgen);
- int status = dialog->exec();
- if (status == QDialog::Accepted)
- {
+ connect(dialog, &QDialog::accepted, [=] {
g_extgen = dialog->getSettings();
// invalidate the map world, forcing an update
getMapView()->deleteWorld();
setMCList(g_extgen.experimentalVers);
updateMapSeed();
- }
+ });
+ dialog->show();
}
void MainWindow::on_actionExportImg_triggered()
@@ -947,14 +998,24 @@ void MainWindow::on_actionExportImg_triggered()
void MainWindow::on_actionScreenshot_triggered()
{
- QString fnam = QFileDialog::getSaveFileName(
- this, tr("Save screenshot"), prevdir, tr("Images (*.png *.jpg *.ppm)"));
+#if WASM
+ QPixmap pixmap = getMapView()->screenshot();
+ QImage img = pixmap.toImage();
+ QByteArray content;
+ QBuffer buffer(&content);
+ buffer.open(QIODevice::WriteOnly);
+ img.save(&buffer, "PNG");
+ QFileDialog::saveFileContent(content, "screenshot.png");
+#else
+ QString filter = tr("Images (*.png *.jpg *.ppm)");
+ QString fnam = QFileDialog::getSaveFileName(this, tr("Save screenshot"), prevdir, filter);
if (!fnam.isEmpty())
{
QPixmap pixmap = getMapView()->screenshot();
QImage img = pixmap.toImage();
img.save(fnam);
}
+#endif
}
void MainWindow::on_actionDock_triggered()
@@ -1022,11 +1083,6 @@ void MainWindow::onAutosaveTimeout()
{
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
saveSession(path + "/session.save", true);
- //int dispms = 10000;
- //if (saveProgress(path + "/session.save", true))
- // ui->statusBar->showMessage(tr("Session autosaved"), dispms);
- //else
- // ui->statusBar->showMessage(tr("Autosave failed"), dispms);
}
}
@@ -1061,11 +1117,11 @@ void MainWindow::onActionBiomeLayerSelect(int mode, int disp)
void MainWindow::onConditionsChanged()
{
- QVector conds = formCond->getConditions();
+ std::vector conds = formCond->getConditions();
formGen48->updateAutoConditions(conds);
}
-void MainWindow::onConditionsSelect(const QVector& selection)
+void MainWindow::onConditionsSelect(const std::vector& selection)
{
std::vector shapes;
for (const Condition& c : selection)
@@ -1125,17 +1181,27 @@ void MainWindow::onUpdateConfig()
info(this, tr("The application will need to be restarted before all changes can take effect."));
}
+ QFont fnorm_old = ui->labelMC->font();
+ QFont fmono_old = ui->labelMono->font();
+ QFont fnorm = config.fontNorm;
+ QFont fmono = config.fontMono;
+ if (fnorm.family() == "Monospace") // avoid identification conflict
+ fnorm = QApplication::font();
+ fnorm.setStyleHint(QFont::AnyStyle);
+ fmono.setStyleHint(QFont::Monospace);
+ fmono.setFixedPitch(true);
+
+ bool font_changed = fnorm_old != fnorm || fmono_old != fmono;
+
QFontMetrics fm_ref(QFontDatabase::systemFont(QFontDatabase::GeneralFont));
- QFontMetrics fm_new(config.fontNorm);
+ QFontMetrics fm_new(fnorm);
g_fontscale = fm_new.height() / (qreal) fm_ref.height();
g_iconscale = config.iconScale;
getMapView()->setConfig(config);
- if ((old.uistyle != config.uistyle) ||
- (old.fontNorm != config.fontNorm) ||
- (old.iconScale != config.iconScale))
+ if ((old.uistyle != config.uistyle) || (old.iconScale != config.iconScale) || font_changed)
{
onStyleChanged(config.uistyle);
int s = (int) round(g_iconscale * 20);
@@ -1145,16 +1211,9 @@ void MainWindow::onUpdateConfig()
{
onBiomeColorChange();
}
- if (old.fontNorm != config.fontNorm || old.fontMono != config.fontMono)
- {
- QFont fnorm = config.fontNorm;
- QFont fmono = config.fontMono;
- if (fnorm.family() == "Monospace") // avoid identification conflict
- fnorm = QApplication::font();
- fnorm.setStyleHint(QFont::AnyStyle);
- fmono.setStyleHint(QFont::Monospace);
- fmono.setFixedPitch(true);
+ if (font_changed)
+ {
QFont fnormb = fnorm;
QFont fmonob = fmono;
fnormb.setBold(true);
diff --git a/src/mainwindow.h b/src/mainwindow.h
index fdb4d5f..cf935b3 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -1,27 +1,25 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
-#include
-#include
-#include
-#include
-#include
#include
#include
+#include
+#include
#include
-
-#include
-#include
-#include
#include
-#include
+#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include "mapview.h"
-#include "searchthread.h"
-#include "configdialog.h"
#include "formconditions.h"
#include "formgen48.h"
#include "formsearchcontrol.h"
@@ -61,8 +59,10 @@ class MainWindow : public QMainWindow
protected:
void saveSettings();
void loadSettings();
- bool saveSession(QString fnam, bool quiet = false);
- bool loadSession(QString fnam, bool keepresults, bool quiet);
+ bool saveSession(QString path, bool quiet);
+ bool loadSession(QString path, bool keepresults);
+ bool saveSession(QTextStream& stream);
+ bool loadSession(QTextStream& stream, bool keepresults, bool quiet);
void updateMapSeed();
void setDockable(bool dockable);
void setMCList(bool experimental);
@@ -117,7 +117,7 @@ private slots:
void onActionHistory(QAction *act);
void onActionBiomeLayerSelect(int lopt, int disp = -1);
void onConditionsChanged();
- void onConditionsSelect(const QVector& selection);
+ void onConditionsSelect(const std::vector& selection);
void onGen48Changed();
void onSelectedSeedChanged(uint64_t seed);
void onSearchStatusChanged(bool running);
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index 000277c..9278ced 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -50,32 +50,6 @@
9
-
-
-
-
- Seed can be an integer or text. Leave empty for a random seed
-
-
- seed:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- Show map for this y-level
-
-
- Y:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
@@ -99,17 +73,7 @@
- -
-
-
- Minecraft version
-
-
- MC
-
-
-
- -
+
-
@@ -180,7 +144,17 @@
- -
+
-
+
+
+ Minecraft version
+
+
+ MC
+
+
+
+ -
0
@@ -204,6 +178,44 @@
+ -
+
+
+ Show map for this y-level
+
+
+ Y:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ Monospace
+
+
+
+
+
+
+
+ -
+
+
+ Seed can be an integer or text. Leave empty for a random seed
+
+
+ seed:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
-
diff --git a/src/maptoolsdialog.cpp b/src/maptoolsdialog.cpp
index 13eb2ee..81400a2 100644
--- a/src/maptoolsdialog.cpp
+++ b/src/maptoolsdialog.cpp
@@ -1,15 +1,12 @@
#include "maptoolsdialog.h"
#include "ui_maptoolsdialog.h"
-#include
#include
-#include
#include
+#include
+#include
#include
-#include "world.h"
-#include "util.h"
-
MapToolsDialog::MapToolsDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::MapToolsDialog)
diff --git a/src/mapview.cpp b/src/mapview.cpp
index 98ff83f..a26a39b 100644
--- a/src/mapview.cpp
+++ b/src/mapview.cpp
@@ -1,18 +1,19 @@
#include "mapview.h"
+
#include "gotodialog.h"
#include "util.h"
-#include
-#include
+#include
#include
+#include
#include
-#include
+#include
+#include
+#include
+#include
#include
#include
-#include
-#include
-#include
-#include
+#include
#include
@@ -199,7 +200,10 @@ void MapView::setShapes(const std::vector& s)
void MapView::refreshBiomeColors()
{
if (world)
+ {
world->refreshBiomeColors();
+ update(1);
+ }
}
void MapView::settingsToWorld()
@@ -361,8 +365,8 @@ void MapView::mapUpdate()
void MapView::showContextMenu(const QPoint &pos)
{
- QMenu menu(this);
- menu.setFont(font());
+ QMenu *menu = new QMenu(this);
+ menu->setFont(font());
// this is a contextual temporary menu so shortcuts are only indicated here,
// but will not function - see keyReleaseEvent() for shortcut implementation
@@ -410,33 +414,33 @@ void MapView::showContextMenu(const QPoint &pos)
int wmax = 0;
for (auto& it : cpy_dat)
{
- int w = txtWidth(menu.fontMetrics(), it.txt + " ");
+ int w = txtWidth(menu->fontMetrics(), it.txt + " ");
if (w > wmax)
wmax = w;
}
- menu.addAction(tr("Go to coordinates..."), this, &MapView::onGoto, QKeySequence(Qt::CTRL + Qt::Key_G));
+ menu->addAction(tr("Go to coordinates..."), this, &MapView::onGoto, QKeySequence(Qt::CTRL + Qt::Key_G));
if (world)
{
QString txt = tr("Copy seed:");
- while (txtWidth(menu.fontMetrics(), txt + " ") < wmax)
+ while (txtWidth(menu->fontMetrics(), txt + " ") < wmax)
txt += " ";
txt += QString::asprintf("%" PRId64, (int64_t)world->wi.seed);
- menu.addAction(txt, this, &MapView::copySeed, QKeySequence::Copy);
+ menu->addAction(txt, this, &MapView::copySeed, QKeySequence::Copy);
}
for (auto& it : cpy_dat)
{
QString txt = it.txt;
- while (txtWidth(menu.fontMetrics(), txt + " ") < wmax)
+ while (txtWidth(menu->fontMetrics(), txt + " ") < wmax)
txt += " ";
txt += it.cpy;
- menu.addAction(txt, [=](){ this->copyText(it.cpy); });
+ menu->addAction(txt, [=](){ this->copyText(it.cpy); });
}
- //menu.addAction(tr("Animation"), this, &MapView::runAni);
+ //menu->addAction(tr("Animation"), this, &MapView::runAni);
- for (QAction *act : menu.actions())
+ for (QAction *act : menu->actions())
act->setFont(font());
- menu.exec(mapToGlobal(pos));
+ menu->popup(mapToGlobal(pos));
}
void MapView::runAni()
diff --git a/src/message.cpp b/src/message.cpp
index 24e9538..409ac96 100644
--- a/src/message.cpp
+++ b/src/message.cpp
@@ -61,37 +61,54 @@ int term_prompt(const QString& title, const QString& text, QMessageBox::Standard
}
static
-int message(QWidget *parent, QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons)
+int message(
+ QWidget *parent, QMessageBox::Icon icon, const QString& title, const QString& text,
+ const QString& prompt, QMessageBox::StandardButtons buttons)
{
+ QString s = text;
+ if (!prompt.isEmpty())
+ s += "\n\n" + prompt;
if (!parent)
- return term_prompt(title, text, buttons);
+ return term_prompt(title, s, buttons);
// emulate the behaviour of QMessageBox::warning(...), but raise as active window
- QMessageBox w(parent);
- w.setWindowTitle(title);
- w.setText(text);
- w.setIconPixmap(QMessageBox::standardIcon(icon)); // setIcon() plays a sound on windows
- for (uint mask = QMessageBox::FirstButton; mask <= QMessageBox::LastButton; mask <<= 1)
- if (mask & buttons)
- w.addButton((QMessageBox::StandardButton)mask);
+ QMessageBox *w = new QMessageBox(parent);
+ w->setWindowTitle(title);
+ w->setIconPixmap(QMessageBox::standardIcon(icon)); // setIcon() plays a sound on windows
parent->setWindowState(Qt::WindowActive);
//w.setWindowState(Qt::WindowActive);
- if (w.exec() == -1)
+#if WASM || 1
+ w->setText(text);
+ w->addButton(QMessageBox::Ok);
+ w->show();
+ return QMessageBox::Cancel;
+#else
+ w->setText(s);
+ for (uint mask = QMessageBox::FirstButton; mask <= QMessageBox::LastButton; mask <<= 1)
+ if (mask & buttons)
+ w->addButton((QMessageBox::StandardButton)mask);
+ if (w->exec() == -1)
return QMessageBox::Cancel;
- return w.standardButton(w.clickedButton());
+ return w->standardButton(w->clickedButton());
+#endif
+}
+
+int warn(QWidget *parent, const QString& title, const QString& text, const QString& prompt, QMessageBox::StandardButtons buttons)
+{
+ return message(parent, QMessageBox::Warning, title, text, prompt, buttons);
}
-int warn(QWidget *parent, const QString& title, const QString& text, QMessageBox::StandardButtons buttons)
+void warn(QWidget *parent, const QString& title, const QString& text)
{
- return message(parent, QMessageBox::Warning, title, text, buttons);
+ message(parent, QMessageBox::Warning, title, text, "", QMessageBox::Ok);
}
-int warn(QWidget *parent, const QString& text, QMessageBox::StandardButtons buttons)
+void warn(QWidget *parent, const QString& text)
{
- return message(parent, QMessageBox::Warning, QApplication::tr("Warning"), text, buttons);
+ message(parent, QMessageBox::Warning, QApplication::tr("Warning"), text, "", QMessageBox::Ok);
}
-int info(QWidget *parent, const QString& text, QMessageBox::StandardButtons buttons)
+void info(QWidget *parent, const QString& text)
{
- return message(parent, QMessageBox::Information, QApplication::tr("Information"), text, buttons);
+ message(parent, QMessageBox::Information, QApplication::tr("Information"), text, "", QMessageBox::Ok);
}
diff --git a/src/message.h b/src/message.h
index 498f303..d3a1177 100644
--- a/src/message.h
+++ b/src/message.h
@@ -3,8 +3,9 @@
#include
-int warn(QWidget *parent, const QString& title, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok);
-int warn(QWidget *parent, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok);
-int info(QWidget *parent, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok);
+int warn(QWidget *parent, const QString& title, const QString& text, const QString& prompt, QMessageBox::StandardButtons buttons);
+void warn(QWidget *parent, const QString& title, const QString& text);
+void warn(QWidget *parent, const QString& text);
+void info(QWidget *parent, const QString& text);
#endif // MESSAGE_H
diff --git a/src/presetdialog.cpp b/src/presetdialog.cpp
index d2ef8f0..17643e1 100644
--- a/src/presetdialog.cpp
+++ b/src/presetdialog.cpp
@@ -2,16 +2,15 @@
#include "ui_presetdialog.h"
#include "aboutdialog.h"
-#include "mainwindow.h"
#include "util.h"
-#include
-#include
-#include
-#include
-#include
#include
+#include
#include
+#include
+#include
+#include
+#include
bool loadConditions(Preset& preset, QString rc)
@@ -68,6 +67,10 @@ PresetDialog::PresetDialog(QWidget *parent, WorldInfo wi, bool showEamples)
else
ui->tabWidget->setCurrentWidget(ui->tabFilters);
+#if WASM
+ ui->tabWidget->removeTab(0); // no filesystem for filters
+#endif
+
ui->splitterH->setSizes(QList({7500, 10000}));
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
@@ -146,7 +149,7 @@ PresetDialog::~PresetDialog()
delete ui;
}
-void PresetDialog::setActiveFilter(const QVector& condvec)
+void PresetDialog::setActiveFilter(const std::vector& condvec)
{
activeFilter = condvec;
}
diff --git a/src/presetdialog.h b/src/presetdialog.h
index 36d4e24..b48d96b 100644
--- a/src/presetdialog.h
+++ b/src/presetdialog.h
@@ -2,9 +2,10 @@
#define EXAMPLESDIALOG_H
#include "config.h"
-#include "formconditions.h"
+#include "search.h"
#include
+#include
namespace Ui {
class PresetDialog;
@@ -12,7 +13,7 @@ class PresetDialog;
struct Preset
{
- QVector condvec;
+ std::vector condvec;
QString title;
QString desc;
};
@@ -30,7 +31,7 @@ class PresetDialog : public QDialog
explicit PresetDialog(QWidget *parent, WorldInfo wi, bool showExamples);
~PresetDialog();
- void setActiveFilter(const QVector& condvec);
+ void setActiveFilter(const std::vector& condvec);
QListWidgetItem *addPreset(QString rc, QString title, QString desc, bool enabled);
@@ -49,7 +50,7 @@ private slots:
Ui::PresetDialog *ui;
std::map presets;
public:
- QVector activeFilter;
+ std::vector activeFilter;
QString rc;
};
diff --git a/src/protobasedialog.cpp b/src/protobasedialog.cpp
deleted file mode 100644
index bbeb6c4..0000000
--- a/src/protobasedialog.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "protobasedialog.h"
-#include "ui_protobasedialog.h"
-
-ProtoBaseDialog::ProtoBaseDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::ProtoBaseDialog)
-{
- ui->setupUi(this);
-}
-
-ProtoBaseDialog::~ProtoBaseDialog()
-{
- delete ui;
-}
-
-bool ProtoBaseDialog::closeOnDone()
-{
- return ui->checkBox->isChecked();
-}
-
-void ProtoBaseDialog::setPath(QString path)
-{
- QString msg = tr(
- "This may take a moment. Results will be saved to:"
- "\n\n\"%1\"\n\n"
- "so subsequent searches will start faster.").arg(path);
- ui->label->setText(msg);
-}
diff --git a/src/protobasedialog.h b/src/protobasedialog.h
deleted file mode 100644
index 237594f..0000000
--- a/src/protobasedialog.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef PROTOBASEDIALOG_H
-#define PROTOBASEDIALOG_H
-
-#include
-
-namespace Ui {
-class ProtoBaseDialog;
-}
-
-class ProtoBaseDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit ProtoBaseDialog(QWidget *parent = nullptr);
- ~ProtoBaseDialog();
-
- bool closeOnDone();
- void setPath(QString path);
-
-private:
- Ui::ProtoBaseDialog *ui;
-};
-
-#endif // PROTOBASEDIALOG_H
diff --git a/src/protobasedialog.ui b/src/protobasedialog.ui
deleted file mode 100644
index 2c7074a..0000000
--- a/src/protobasedialog.ui
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
- ProtoBaseDialog
-
-
- Generating Protobases
-
-
-
- :/icons/logo.png:/icons/logo.png
-
-
-
-
-
-
- <html><head/><body><p><span style=" font-size:12pt; font-weight:600;">Please wait: generating protobases.</span></p></body></html>
-
-
-
- -
-
-
- This may take a moment. Results will be saved to _PATH_ so subsequent searches will start faster.
-
-
-
- -
-
-
- Automatically close dialog when processing is done.
-
-
- true
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Close
-
-
-
-
-
-
-
-
-
-
- buttonBox
- accepted()
- ProtoBaseDialog
- accept()
-
-
- 248
- 254
-
-
- 157
- 274
-
-
-
-
- buttonBox
- rejected()
- ProtoBaseDialog
- reject()
-
-
- 316
- 260
-
-
- 286
- 274
-
-
-
-
-
diff --git a/src/qzipwriter.h b/src/qzipwriter.h
new file mode 100644
index 0000000..8f4e233
--- /dev/null
+++ b/src/qzipwriter.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/// NOTE this is forwarded from the private Qt header for QZipWriter.
+/// It is not part of the Qt API and may change between versions.
+/// However, as of writing this, it's available on Qt5 and Qt6.
+
+#ifndef QZIPWRITER_H
+#define QZIPWRITER_H
+
+#include
+#include
+#include
+
+// QT_BEGIN_NAMESPACE
+
+class QZipWriterPrivate;
+
+class Q_CORE_EXPORT QZipWriter
+{
+public:
+ explicit QZipWriter(const QString &fileName, QIODevice::OpenMode mode = (QIODevice::WriteOnly | QIODevice::Truncate) );
+
+ explicit QZipWriter(QIODevice *device);
+ ~QZipWriter();
+
+ QIODevice* device() const;
+
+ bool isWritable() const;
+ bool exists() const;
+
+ enum Status {
+ NoError,
+ FileWriteError,
+ FileOpenError,
+ FilePermissionsError,
+ FileError
+ };
+
+ Status status() const;
+
+ enum CompressionPolicy {
+ AlwaysCompress,
+ NeverCompress,
+ AutoCompress
+ };
+
+ void setCompressionPolicy(CompressionPolicy policy);
+ CompressionPolicy compressionPolicy() const;
+
+ void setCreationPermissions(QFile::Permissions permissions);
+ QFile::Permissions creationPermissions() const;
+
+ void addFile(const QString &fileName, const QByteArray &data);
+
+ void addFile(const QString &fileName, QIODevice *device);
+
+ void addDirectory(const QString &dirName);
+
+ void addSymLink(const QString &fileName, const QString &destination);
+
+ void close();
+private:
+ QZipWriterPrivate *d;
+ Q_DISABLE_COPY_MOVE(QZipWriter)
+};
+
+// QT_END_NAMESPACE
+
+#endif // QZIPWRITER_H
diff --git a/src/rangedialog.cpp b/src/rangedialog.cpp
index c4e406a..ac08467 100644
--- a/src/rangedialog.cpp
+++ b/src/rangedialog.cpp
@@ -18,23 +18,6 @@ RangeDialog::~RangeDialog()
delete ui;
}
-bool RangeDialog::getBounds(uint64_t *smin, uint64_t *smax)
-{
- bool ok, allok = true;
- int base = 10;
- if (ui->checkHex->isChecked())
- base = 16;
- *smin = ui->lineMin->text().toULongLong(&ok, base);
- allok &= ok;
- if (!ok)
- *smin = 0;
- *smax = ui->lineMax->text().toULongLong(&ok, base);
- allok &= ok;
- if (!ok)
- *smax = ~(uint64_t)0;
- return allok;
-}
-
void RangeDialog::on_buttonBox_clicked(QAbstractButton *button)
{
QDialogButtonBox::StandardButton b = ui->buttonBox->standardButton(button);
@@ -48,4 +31,16 @@ void RangeDialog::on_buttonBox_clicked(QAbstractButton *button)
ui->lineMin->setText(QString::asprintf(fmt, 0));
ui->lineMax->setText(QString::asprintf(fmt, ~(uint64_t)0));
}
+ if (b == QDialogButtonBox::Ok)
+ {
+ bool ok;
+ int base = 10;
+ if (ui->checkHex->isChecked())
+ base = 16;
+ uint64_t smin = ui->lineMin->text().toULongLong(&ok, base);
+ if (!ok) smin = 0;
+ uint64_t smax = ui->lineMax->text().toULongLong(&ok, base);
+ if (!ok) smax = ~(uint64_t)0;
+ emit applyBounds(smin, smax);
+ }
}
diff --git a/src/rangedialog.h b/src/rangedialog.h
index a5bbf17..94d99df 100644
--- a/src/rangedialog.h
+++ b/src/rangedialog.h
@@ -16,7 +16,8 @@ class RangeDialog : public QDialog
explicit RangeDialog(QWidget *parent, uint64_t smin, uint64_t smax);
~RangeDialog();
- bool getBounds(uint64_t *smin, uint64_t *smax);
+signals:
+ void applyBounds(uint64_t smin, uint64_t smax);
private slots:
void on_buttonBox_clicked(QAbstractButton *button);
diff --git a/src/scripts.cpp b/src/scripts.cpp
index ae15bf4..1f17d60 100644
--- a/src/scripts.cpp
+++ b/src/scripts.cpp
@@ -4,13 +4,13 @@
#include "util.h"
#include
-#include
-#include
+#include
#include
+#include
#include
+#include
#include
#include
-#include
LuaOutput g_lua_output[100];
@@ -307,7 +307,7 @@ int runCheckScript(
SearchThreadEnv * env,
int pass,
Pos * path,
- Condition * cond
+ const Condition * cond
)
{
int top = lua_gettop(L);
@@ -326,7 +326,7 @@ int runCheckScript(
}
std::vector nodes;
- gather_nodes(nodes, env->condtree, path, cond->save);
+ gather_nodes(nodes, &env->condtree, path, cond->save);
lua_pushlightuserdata(L, env);
lua_setglobal(L, "_cb_env");
diff --git a/src/scripts.h b/src/scripts.h
index 46b5e38..b5fefab 100644
--- a/src/scripts.h
+++ b/src/scripts.h
@@ -56,7 +56,7 @@ int runCheckScript(
SearchThreadEnv * env,
int pass,
Pos * path,
- Condition * cond
+ const Condition * cond
);
struct Rule
diff --git a/src/search.cpp b/src/search.cpp
index cc72172..c3c5acb 100644
--- a/src/search.cpp
+++ b/src/search.cpp
@@ -1,18 +1,19 @@
#include "search.h"
+
+#include "config.h"
+#include "scripts.h"
#include "seedtables.h"
-#include "mainwindow.h"
#include "util.h"
-#include "scripts.h"
-#include "cubiomes/quadbase.h"
#include "cubiomes/finders.h"
+#include "cubiomes/quadbase.h"
-#include
-#include
#include
-#include
-#include
+#include
#include
+#include
+#include
+#include
#include
@@ -223,7 +224,7 @@ ConditionTree::~ConditionTree()
{
}
-QString ConditionTree::set(const QVector& cv, int mc)
+QString ConditionTree::set(const std::vector& cv, int mc)
{
int cmax = 0;
for (const Condition& c : cv)
@@ -260,7 +261,7 @@ SearchThreadEnv::~SearchThreadEnv()
lua_close(it.second);
}
-QString SearchThreadEnv::init(int mc, bool large, ConditionTree *condtree)
+QString SearchThreadEnv::init(int mc, bool large, const ConditionTree& condtree)
{
this->condtree = condtree;
this->mc = mc;
@@ -279,7 +280,7 @@ QString SearchThreadEnv::init(int mc, bool large, ConditionTree *condtree)
lua_close(it.second);
l_states.clear();
- for (const Condition& c: qAsConst(condtree->condvec))
+ for (const Condition& c: condtree.condvec)
{
if (c.type != F_LUA)
continue;
@@ -349,13 +350,14 @@ int testTreeAt(
int node
)
{
- ConditionTree *tree = env->condtree;
- Condition& c = tree->condvec[node];
+ const ConditionTree *tree = &env->condtree;
+ const Condition& c = tree->condvec[node];
const std::vector& branches = tree->references[c.save];
int st, br;
int rx1, rz1, rx2, rz2;
Pos pos;
- Pos inst[MAX_INSTANCES];
+
+ std::vector inst(MAX_INSTANCES);
switch (c.type)
{
@@ -539,7 +541,7 @@ int testTreeAt(
st = COND_OK;
if (lua_State *L = env->l_states[c.hash])
{
- Pos *buf = path ? path : inst;
+ Pos *buf = path ? path : &inst[0];
for (int b : branches)
{
int sta = testTreeAt(at, env, pass, abort, buf, b);
@@ -566,13 +568,13 @@ int testTreeAt(
if (branches.empty())
{ // this is a leaf node => check only for presence of instances
int icnt = c.count;
- st = testCondAt(at, env, pass, abort, inst, &icnt, &c);
+ st = testCondAt(at, env, pass, abort, &inst[0], &icnt, &c);
if (path && st >= COND_MAYBE_POS_VALID)
{
if (icnt == 1)
- path[c.save] = *inst;
+ path[c.save] = inst[0];
else if (icnt > 1 && st == COND_OK)
- path[c.save] = *inst;
+ path[c.save] = inst[0];
else
path[c.save].x = path[c.save].z = -1;
}
@@ -591,7 +593,7 @@ int testTreeAt(
}
else
{
- st = testCondAt(at, env, pass, abort, inst, NULL, &c);
+ st = testCondAt(at, env, pass, abort, &inst[0], NULL, &c);
if (st == COND_FAILED || st == COND_MAYBE_POS_INVAL)
return st;
pos = inst[0]; // center point of instances
@@ -614,7 +616,7 @@ int testTreeAt(
{ // check each instance individually, splitting the instances into
// independent subbranches that are combined via OR
int icnt = MAX_INSTANCES;
- st = testCondAt(at, env, pass, abort, inst, &icnt, &c);
+ st = testCondAt(at, env, pass, abort, &inst[0], &icnt, &c);
if (st == COND_FAILED || st == COND_MAYBE_POS_INVAL)
return st;
int sta = COND_FAILED;
@@ -683,22 +685,21 @@ static const QuadInfo *getQHInfo(uint64_t cst)
getStructureConfig(Swamp_Hut, MC_NEWEST, &sc);
sc.salt = 0; // ignore version dependent salt offsets
- for (size_t i = 0, n = sizeof(low20QuadHutBarely) / sizeof(uint64_t); i < n; i++)
+ for (const uint64_t *cst = low20QuadHutBarely; *cst; cst++)
{
- uint64_t c = low20QuadHutBarely[i];
- for (uint64_t s = c;; s += 0x100000)
+ for (uint64_t s = *cst;; s += 0x100000)
{
// find a quad-hut for this constellation
Pos pc;
- if (scanForQuads(sc, 128, s, low20QuadHutBarely, n, 20, 0, 0, 0, 1, 1, &pc, 1) < 1)
+ if (scanForQuads(sc, 128, s, low20QuadHutBarely, 20, 0, 0, 0, 1, 1, &pc, 1) < 1)
continue;
qreal rad = isQuadBase(sc, s, 160);
if (rad == 0)
continue;
- QuadInfo *qi = &qh_info[c];
+ QuadInfo *qi = &qh_info[*cst];
qi->rad = rad;
- qi->c = c;
+ qi->c = *cst;
qi->p[0] = getFeaturePos(sc, s, 0, 0);
qi->p[1] = getFeaturePos(sc, s, 0, 1);
qi->p[2] = getFeaturePos(sc, s, 1, 0);
@@ -706,28 +707,12 @@ static const QuadInfo *getQHInfo(uint64_t cst)
qi->afk = getOptimalAfk(qi->p, 7,7,9, &qi->spcnt);
qi->typ = Swamp_Hut;
- qi->flt = F_QH_BARELY;
- int j, m;
- m = sizeof(low20QuadHutNormal) / sizeof(uint64_t);
- for (j = 0; j < m; j++) {
- if (low20QuadHutNormal[j] == c) {
- qi->flt = F_QH_NORMAL;
- break;
- }
- }
- m = sizeof(low20QuadClassic) / sizeof(uint64_t);
- for (j = 0; j < m; j++) {
- if (low20QuadClassic[j] == c) {
- qi->flt = F_QH_CLASSIC;
- break;
- }
- }
- m = sizeof(low20QuadIdeal) / sizeof(uint64_t);
- for (j = 0; j < m; j++) {
- if (low20QuadIdeal[j] == c) {
- qi->flt = F_QH_IDEAL;
- break;
- }
+ switch (getQuadHutCst(*cst))
+ {
+ case CST_IDEAL: qi->flt = F_QH_IDEAL; break;
+ case CST_CLASSIC: qi->flt = F_QH_CLASSIC; break;
+ case CST_NORMAL: qi->flt = F_QH_NORMAL; break;
+ default: qi->flt = F_QH_BARELY;
}
break;
}
@@ -754,16 +739,15 @@ static const QuadInfo *getQMInfo(uint64_t s48)
getStructureConfig(Monument, MC_NEWEST, &sc);
sc.salt = 0;
- for (size_t i = 0, n = sizeof(g_qm_90) / sizeof(uint64_t); i < n; i++)
+ for (const uint64_t *s = g_qm_90; *s; s++)
{
- uint64_t s = g_qm_90[i];
- QuadInfo *qi = &qm_info[s];
- qi->rad = isQuadBase(sc, s, 160);
- qi->c = s;
- qi->p[0] = getLargeStructurePos(sc, s, 0, 0);
- qi->p[1] = getLargeStructurePos(sc, s, 0, 1);
- qi->p[2] = getLargeStructurePos(sc, s, 1, 0);
- qi->p[3] = getLargeStructurePos(sc, s, 1, 1);
+ QuadInfo *qi = &qm_info[*s];
+ qi->rad = isQuadBase(sc, *s, 160);
+ qi->c = *s;
+ qi->p[0] = getLargeStructurePos(sc, *s, 0, 0);
+ qi->p[1] = getLargeStructurePos(sc, *s, 0, 1);
+ qi->p[2] = getLargeStructurePos(sc, *s, 1, 0);
+ qi->p[3] = getLargeStructurePos(sc, *s, 1, 1);
qi->afk = getOptimalAfk(qi->p, 58,0/*23*/,58, &qi->spcnt);
qi->afk.x -= 29;
qi->afk.z -= 29;
@@ -971,7 +955,7 @@ static int f_track_minmax(void *data, int x, int z, double p)
struct sample_boime_t
{
- Condition *cond;
+ const Condition *cond;
Pos at;
int rmaxsq;
int n;
@@ -1038,7 +1022,7 @@ testCondAt(
std::atomic_bool * abort, // abort signal
Pos * cent, // output center position(s)
int * imax, // max instances (NULL for avg)
- Condition * cond // condition to check
+ const Condition * cond // condition to check
)
{
int x1, x2, z1, z2;
@@ -1051,7 +1035,7 @@ testCondAt(
int i, n, icnt;
int64_t s, r, rmin, rmax;
const uint64_t *seeds;
- Pos p[MAX_INSTANCES];
+ std::vector p(MAX_INSTANCES);
const FilterInfo& finfo = g_filterinfo.list[cond->type];
@@ -1100,19 +1084,15 @@ testCondAt(
case F_QH_IDEAL:
seeds = low20QuadIdeal;
- n = sizeof(low20QuadIdeal) / sizeof(uint64_t);
goto L_qh_any;
case F_QH_CLASSIC:
seeds = low20QuadClassic;
- n = sizeof(low20QuadClassic) / sizeof(uint64_t);
goto L_qh_any;
case F_QH_NORMAL:
seeds = low20QuadHutNormal;
- n = sizeof(low20QuadHutNormal) / sizeof(uint64_t);
goto L_qh_any;
case F_QH_BARELY:
seeds = low20QuadHutBarely;
- n = sizeof(low20QuadHutBarely) / sizeof(uint64_t);
L_qh_any:
rx1 = x1 >> 9;
@@ -1121,8 +1101,8 @@ testCondAt(
rz2 = z2 >> 9;
n = scanForQuads(
- sconf, 128, (env->seed) & MASK48, seeds, n, 20, sconf.salt,
- rx1, rz1, rx2 - rx1 + 1, rz2 - rz1 + 1, p, MAX_INSTANCES);
+ sconf, 128, (env->seed) & MASK48, seeds, 20, sconf.salt,
+ rx1, rz1, rx2 - rx1 + 1, rz2 - rz1 + 1, &p[0], MAX_INSTANCES);
if (n < 1)
return COND_FAILED;
icnt = 0;
@@ -1178,9 +1158,8 @@ testCondAt(
rz2 = z2 >> 9;
// we don't really need to check for more than one instance here
n = scanForQuads(
- sconf, 160, (env->seed) & MASK48, g_qm_90,
- sizeof(g_qm_90) / sizeof(uint64_t), 48, sconf.salt,
- rx1, rz1, rx2 - rx1 + 1, rz2 - rz1 + 1, p, 1);
+ sconf, 160, (env->seed) & MASK48, g_qm_90, 48, sconf.salt,
+ rx1, rz1, rx2 - rx1 + 1, rz2 - rz1 + 1, &p[0], 1);
if (n < 1)
return COND_FAILED;
icnt = 0;
@@ -1438,7 +1417,7 @@ testCondAt(
}
else
{ // we need the average position of all instances
- icnt = getMineshafts(env->mc, env->seed, rx1, rz1, rx2, rz2, p, MAX_INSTANCES);
+ icnt = getMineshafts(env->mc, env->seed, rx1, rz1, rx2, rz2, &p[0], MAX_INSTANCES);
if (icnt < cond->count)
return COND_FAILED;
xt = zt = 0;
@@ -1948,7 +1927,7 @@ testCondAt(
else
{ // we need the average position of all instances
icnt = getBiomeCenters(
- p, NULL, MAX_INSTANCES, &env->g, r, cond->biomeId, cond->biomeSize, cond->tol,
+ &p[0], NULL, MAX_INSTANCES, &env->g, r, cond->biomeId, cond->biomeSize, cond->tol,
(volatile char*)abort
);
xt = zt = 0;
@@ -2129,8 +2108,7 @@ void findQuadStructs(int styp, Generator *g, QVector *out)
{
qcnt = scanForQuads(
sconf, 128, g->seed & MASK48,
- low20QuadHutBarely, sizeof(low20QuadHutBarely) / sizeof(uint64_t),
- 20, sconf.salt,
+ low20QuadHutBarely, 20, sconf.salt,
-r, -r, 2*r, 2*r, qlist, qmax
);
@@ -2163,8 +2141,7 @@ void findQuadStructs(int styp, Generator *g, QVector *out)
{
qcnt = scanForQuads(
sconf, 160, g->seed & MASK48,
- g_qm_90, sizeof(g_qm_90) / sizeof(uint64_t),
- 48, sconf.salt,
+ g_qm_90, 48, sconf.salt,
-r, -r, 2*r, 2*r, qlist, qmax
);
diff --git a/src/search.h b/src/search.h
index 83f916f..d73a0de 100644
--- a/src/search.h
+++ b/src/search.h
@@ -1,7 +1,7 @@
#ifndef SEARCH_H
#define SEARCH_H
-#include "config.h"
+#include "cubiomes/finders.h"
#include "lua/src/lua.hpp"
@@ -639,16 +639,16 @@ static_assert(
struct ConditionTree
{
- QVector condvec;
+ std::vector condvec;
std::vector> references;
~ConditionTree();
- QString set(const QVector& cv, int mc);
+ QString set(const std::vector& cv, int mc);
};
struct SearchThreadEnv
{
- ConditionTree *condtree;
+ ConditionTree condtree;
Generator g;
SurfaceNoise sn;
@@ -663,7 +663,7 @@ struct SearchThreadEnv
SearchThreadEnv();
~SearchThreadEnv();
- QString init(int mc, bool large, ConditionTree *condtree);
+ QString init(int mc, bool large, const ConditionTree& condtree);
void setSeed(uint64_t seed);
void init4Dim(int dim);
@@ -707,7 +707,7 @@ int testCondAt(
std::atomic_bool * abort, // abort signal
Pos * cent, // output center position(s)
int * imax, // max instances (NULL for avg)
- Condition * cond // condition to check
+ const Condition * cond // condition to check
);
struct QuadInfo
diff --git a/src/searchthread.cpp b/src/searchthread.cpp
index 9f98308..2cf1379 100644
--- a/src/searchthread.cpp
+++ b/src/searchthread.cpp
@@ -1,17 +1,20 @@
#include "searchthread.h"
+
+#include "aboutdialog.h"
#include "formsearchcontrol.h"
-#include "util.h"
-#include "seedtables.h"
#include "message.h"
-#include "aboutdialog.h"
+#include "seedtables.h"
+
+#include "cubiomes/quadbase.h"
+#include "cubiomes/util.h"
-#include
#include
-#include
+#include
#include
+#include
#include
+#include
#include
-#include
void Session::writeHeader(QTextStream& stream)
@@ -26,41 +29,22 @@ void Session::writeHeader(QTextStream& stream)
for (Condition &c : cv)
stream << "#Cond: " << c.toHex() << "\n";
+ stream.flush();
}
-bool Session::save(QWidget *widget, QString fnam, bool quiet)
+bool Session::save(QWidget *widget, QTextStream& stream)
{
- QFile file(fnam);
-
- if (!file.open(QIODevice::WriteOnly))
- {
- if (!quiet)
- warn(widget, QApplication::tr("Failed to open file:\n\"%1\"").arg(fnam));
- return false;
- }
-
- QTextStream stream(&file);
+ (void) widget;
writeHeader(stream);
-
for (uint64_t s : slist)
stream << QString::asprintf("%" PRId64 "\n", (int64_t)s);
-
+ stream.flush();
return true;
}
-bool Session::load(QWidget *widget, QString fnam, bool quiet)
+bool Session::load(QWidget *widget, QTextStream& stream, bool quiet)
{
- QFile file(fnam);
-
- if (!file.open(QIODevice::ReadOnly))
- {
- if (!quiet)
- warn(widget, QApplication::tr("Failed to open session file:\n\"%1\"").arg(fnam));
- return false;
- }
-
int major = 0, minor = 0, patch = 0;
- QTextStream stream(&file);
QString line;
line = stream.readLine();
int lno = 1;
@@ -69,22 +53,20 @@ bool Session::load(QWidget *widget, QString fnam, bool quiet)
{
if (quiet)
return false;
- QString msg = QApplication::tr("File does not look like a session file.\n"
- "Progress may be incomplete or broken.\n\n"
- "Continue anyway?");
- int button = warn(widget, msg, QMessageBox::Abort|QMessageBox::Yes);
- if (button == QMessageBox::Abort)
+ int button = warn(widget, QApplication::tr("Warning"),
+ QApplication::tr("File does not look like a session file.\nProgress may be incomplete or broken."),
+ QApplication::tr("Continue anyway?"), QMessageBox::Abort | QMessageBox::Yes);
+ if (button != QMessageBox::Yes)
return false;
}
else if (cmpVers(major, minor, patch) > 0)
{
if (quiet)
return false;
- QString msg = QApplication::tr("Session file was created with a newer version.\n"
- "Progress may be incomplete or broken.\n\n"
- "Continue loading progress anyway?");
- int button = warn(widget, msg, QMessageBox::Abort|QMessageBox::Yes);
- if (button == QMessageBox::Abort)
+ int button = warn(widget, QApplication::tr("Warning"),
+ QApplication::tr("Session file was created with a newer version.\nProgress may be incomplete or broken."),
+ QApplication::tr("Continue loading progress anyway?"), QMessageBox::Abort | QMessageBox::Yes);
+ if (button != QMessageBox::Yes)
return false;
}
@@ -112,10 +94,10 @@ bool Session::load(QWidget *widget, QString fnam, bool quiet)
{
if (quiet)
return false;
- QString msg = QApplication::tr("Condition [%1] at line %2 is not supported.\n\n"
- "Continue anyway?");
- int button = warn(widget, msg.arg(c.save).arg(lno), QMessageBox::Abort|QMessageBox::Yes);
- if (button == QMessageBox::Abort)
+ int button = warn(widget, QApplication::tr("Warning"),
+ QApplication::tr("Condition [%1] at line %2 is not supported.").arg(c.save).arg(lno),
+ QApplication::tr("Continue anyway?"), QMessageBox::Abort | QMessageBox::Yes);
+ if (button != QMessageBox::Yes)
return false;
}
}
@@ -132,10 +114,10 @@ bool Session::load(QWidget *widget, QString fnam, bool quiet)
{
if (quiet)
return false;
- QString msg = QApplication::tr("Failed to parse line %1 of file:\n%2\n\n"
- "Continue anyway?");
- int button = warn(widget, msg.arg(lno).arg(line), QMessageBox::Abort|QMessageBox::Yes);
- if (button == QMessageBox::Abort)
+ int button = warn(widget, QApplication::tr("Warning"),
+ QApplication::tr("Failed to parse line %1 of file:\n%2").arg(lno).arg(line),
+ QApplication::tr("Continue anyway?"), QMessageBox::Abort | QMessageBox::Yes);
+ if (button != QMessageBox::Yes)
return false;
}
}
@@ -145,7 +127,7 @@ bool Session::load(QWidget *widget, QString fnam, bool quiet)
SearchMaster::SearchMaster(QWidget *parent)
- : QThread(parent)
+ : QObject(parent)
, mutex()
, abort()
, proghist()
@@ -204,7 +186,7 @@ bool SearchMaster::set(QWidget *widget, const Session& s)
const FilterInfo& finfo = g_filterinfo.list[c.type];
- if (c.relative && refbuf[c.relative] == 0)
+ if (c.relative && (refbuf[c.relative] == 0 || disabled[c.relative]))
{
warn(widget, tr("Condition with ID %1 has a broken reference position:\n"
"condition missing or out of order.").arg(cid));
@@ -215,13 +197,6 @@ bool SearchMaster::set(QWidget *widget, const Session& s)
warn(widget, tr("More than one condition with ID %1.").arg(cid));
return false;
}
- if (c.relative && disabled[c.relative])
- {
- int button = info(widget, tr("Condition %1 has been indirectly disabled by reference.").arg(cid),
- QMessageBox::Abort|QMessageBox::Ignore);
- if (button == QMessageBox::Abort)
- return false;
- }
if (s.wi.mc < finfo.mcmin)
{
const char *mcs = mc2str(finfo.mcmin);
@@ -248,10 +223,8 @@ bool SearchMaster::set(QWidget *widget, const Session& s)
}
if ((b | m | c.biomeToExcl | c.biomeToExclM) == 0)
{
- int button = info(widget, tr("Biome condition with ID %1 specifies no biomes.").arg(cid),
- QMessageBox::Abort|QMessageBox::Ignore);
- if (button == QMessageBox::Abort)
- return false;
+ warn(widget, tr("Biome condition with ID %1 specifies no biomes.").arg(cid));
+ return false;
}
int layerId = 0;
@@ -318,7 +291,7 @@ bool SearchMaster::set(QWidget *widget, const Session& s)
QString err = condtree.set(s.cv, s.wi.mc);
if (err.isEmpty())
{
- err = env.init(s.wi.mc, s.wi.large, &condtree);
+ err = env.init(s.wi.mc, s.wi.large, condtree);
}
if (!err.isEmpty())
{
@@ -344,92 +317,43 @@ bool SearchMaster::set(QWidget *widget, const Session& s)
return true;
}
-
-static int check(uint64_t s48, void *data)
+static void genQHBases(int qual, uint64_t salt, std::vector& list48)
{
- (void) data;
- static const StructureConfig sconf = {0,0,0,0,0,0};
- return isQuadBaseFeature24(sconf, s48, 7+1, 7+1, 9+1) != 0;
-}
-
-static void genQHBases(QObject *qtobj, int qual, uint64_t salt, std::vector& list48, std::atomic_bool *stop)
-{
- const char *lbstr = NULL;
- const uint64_t *lbset = NULL;
- uint64_t lbcnt = 0;
- QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
- if (path.isEmpty())
- path = "protobases";
-
+ int cst_type = 0;
switch (qual)
{
case IDEAL_SALTED:
- case IDEAL:
- lbstr = "ideal";
- lbset = low20QuadIdeal;
- lbcnt = sizeof(low20QuadIdeal) / sizeof(uint64_t);
- break;
- case CLASSIC:
- lbstr = "cassic";
- lbset = low20QuadClassic;
- lbcnt = sizeof(low20QuadClassic) / sizeof(uint64_t);
- break;
- case NORMAL:
- lbstr = "normal";
- lbset = low20QuadHutNormal;
- lbcnt = sizeof(low20QuadHutNormal) / sizeof(uint64_t);
- break;
- case BARELY:
- lbstr = "barely";
- lbset = low20QuadHutBarely;
- lbcnt = sizeof(low20QuadHutBarely) / sizeof(uint64_t);
- break;
- default:
- return;
+ case IDEAL: cst_type = CST_IDEAL; break;
+ case CLASSIC: cst_type = CST_CLASSIC; break;
+ case NORMAL: cst_type = CST_NORMAL; break;
+ case BARELY: cst_type = CST_BARELY; break;
}
- path += QString("/quad_") + lbstr + ".txt";
- QByteArray fnam = path.toLocal8Bit();
- uint64_t *qb = NULL;
- uint64_t qn = 0;
-
- if ((qb = loadSavedSeeds(fnam.data(), &qn)) == NULL)
+ QDirIterator it(":/qh");
+ while (it.hasNext())
{
- printf("[INFO]: Writing quad-protobases to: %s\n", fnam.data());
- fflush(stdout);
-
- if (qtobj)
- QMetaObject::invokeMethod(qtobj, "openProtobaseMsg", Qt::QueuedConnection, Q_ARG(QString, path));
+ QString fnam = it.next();
+ printf("> %s\n", fnam.toLocal8Bit().data());
+ QFile file(fnam);
+ uint64_t low = it.fileInfo().baseName().toUInt(nullptr, 16);
+ uint64_t mid = 0;
+ if (getQuadHutCst(low) > cst_type)
+ continue;
- int threads = QThread::idealThreadCount();
- int err = searchAll48(&qb, &qn, fnam.data(), threads, lbset, lbcnt, 20, check, NULL, (volatile char*) stop);
+ file.open(QIODevice::ReadOnly);
+ QTextStream stream(&file);
- if (err)
+ while (!stream.atEnd())
{
- printf("[WARN]: Failed to generate protobases.\n");
- if (qtobj && !*stop)
- {
- QMetaObject::invokeMethod(
- qtobj, "warning", Qt::BlockingQueuedConnection,
- Q_ARG(QString, SearchMaster::tr("Failed to generate protobases.")));
- }
- return;
+ QString line = stream.readLine();
+ uint64_t diff = line.toULongLong(nullptr, 16);
+ if (diff == 0)
+ break;
+ mid += diff;
+ uint64_t s48 = (mid << 20) + low;
+ list48.push_back(s48 - salt);
}
}
- else
- {
- //printf("Loaded quad-protobases from: %s\n", fnam.data());
- //fflush(stdout);
- }
-
- if (qb)
- {
- // convert protobases to proper bases by subtracting the salt
- list48.resize(qn);
- for (uint64_t i = 0; i < qn; i++)
- list48[i] = qb[i] - salt;
- free(qb);
- }
}
static bool applyTranspose(std::vector& slist,
@@ -469,13 +393,13 @@ static bool applyTranspose(std::vector& slist,
return !slist.empty();
}
-void SearchMaster::presearch(QObject *qtobj)
+void SearchMaster::presearch()
{
uint64_t sstart = seed;
if (gen48.mode == GEN48_AUTO)
{ // resolve automatic mode
- for (const Condition& c : qAsConst(condtree.condvec))
+ for (const Condition& c : condtree.condvec)
{
if (c.type >= F_QH_IDEAL && c.type <= F_QH_BARELY)
{
@@ -504,19 +428,16 @@ void SearchMaster::presearch(QObject *qtobj)
salt = sconf.salt;
}
slist.clear();
- genQHBases(qtobj, gen48.qual, salt, slist, &abort);
+ genQHBases(gen48.qual, salt, slist);
}
else if (gen48.mode == GEN48_QM)
{
StructureConfig sconf;
getStructureConfig_override(Monument, mc, &sconf);
- const uint64_t *qb = g_qm_90;
- uint64_t qn = sizeof(g_qm_90) / sizeof(uint64_t);
slist.clear();
- slist.reserve(qn);
- for (uint64_t i = 0; i < qn; i++)
- if (qmonumentQual(qb[i]) >= gen48.qmarea)
- slist.push_back((qb[i] - sconf.salt) & MASK48);
+ for (const uint64_t *s = g_qm_90; *s; s++)
+ if (qmonumentQual(*s) >= gen48.qmarea)
+ slist.push_back((*s - sconf.salt) & MASK48);
}
else if (gen48.mode == GEN48_LIST)
{
@@ -646,14 +567,12 @@ void SearchMaster::presearch(QObject *qtobj)
}
}
-void SearchMaster::run()
+void SearchMaster::start()
{
stop();
abort = false;
- QObject *qtobj = parent();
- presearch(qtobj);
- if (qtobj)
- QMetaObject::invokeMethod(qtobj, "closeProtobaseMsg", Qt::BlockingQueuedConnection);
+ presearch();
+
if (abort)
{
emit searchFinish(false);
@@ -682,7 +601,7 @@ void SearchMaster::run()
itemtimer.start();
count = 0;
- for (SearchWorker *worker: workers)
+ for (SearchWorker *worker : workers)
{
worker->start();
}
@@ -694,52 +613,27 @@ void SearchMaster::stop()
if (workers.empty())
return;
- // clear event loop of currently running signals (such as results triggers)
- QApplication::processEvents();
+ long stop_ms = 1000;
+ QElapsedTimer timer;
+ timer.start();
- for (long stop_ms = 300; ; stop_ms *= 5)
+ while (timer.elapsed() < stop_ms)
{
- QElapsedTimer timer;
- timer.start();
-
- int running = 0;
- for (SearchWorker *worker: workers)
- {
- long ms = stop_ms - timer.elapsed();
- if (ms < 1) ms = 1;
- running += !worker->wait(ms);
- }
- if (!running)
- break;
- if (parent() == nullptr)
- continue;
- int button = 0;
- Qt::ConnectionType connectiontype = Qt::BlockingQueuedConnection;
- if (QThread::currentThread() == QApplication::instance()->thread())
- { // main thread would deadlock with a blocking connection
- connectiontype = Qt::DirectConnection;
- }
- QMetaObject::invokeMethod(
- parent(), "warning", connectiontype,
- Q_RETURN_ARG(int, button),
- Q_ARG(QString, tr("Failed to stop %n worker thread(s).\n"
- "Keep waiting for threads to stop?", "", running)),
- Q_ARG(QMessageBox::StandardButtons, QMessageBox::No|QMessageBox::Yes));
- if (button != QMessageBox::Yes)
+ bool busy = false;
+ for (SearchWorker *worker : workers)
+ busy |= worker->isRunning();
+ if (!busy)
break;
+ QThread::msleep(10);
}
- for (SearchWorker *worker: workers)
+ for (SearchWorker *worker : workers)
{
+ worker->disconnect(this);
if (worker->isRunning())
- {
- worker->disconnect(this);
connect(worker, &SearchWorker::finished, worker, &QObject::deleteLater);
- }
else
- {
delete worker;
- }
}
workers.clear();
@@ -875,7 +769,7 @@ bool SearchMaster::requestItem(SearchWorker *item)
if (isdone)
return false;
- QMutexLocker locker(&mutex);
+ // QMutexLocker locker(&mutex);
// check if we should adjust the item size
uint64_t nsec = itemtimer.nsecsElapsed();
@@ -1032,26 +926,41 @@ SearchWorker::SearchWorker(SearchMaster *master)
this->sstart = master->seed;
this->scnt = 0;
this->seed = master->seed;
+
+ this->env = new SearchThreadEnv();
}
+SearchWorker::~SearchWorker()
+{
+ delete env;
+}
+
+bool SearchWorker::getNextItem()
+{
+ QMutexLocker locker(&master->mutex);
+ return master->requestItem(this);
+}
void SearchWorker::run()
{
Pos origin = {0,0};
- SearchThreadEnv env;
- env.init(master->mc, master->large, &master->condtree);
+ env->init(master->mc, master->large, master->condtree);
+
+ volatile char b[1024*1024];
+ for (size_t i = 0; i < sizeof(b); i++)
+ b[i] = (char)i + b[i % 256];
switch (master->searchtype)
{
case SEARCH_LIST:
- while (!*abort && master->requestItem(this))
+ while (!*abort && getNextItem())
{ // seed = slist[..]
uint64_t ie = idx+scnt < len ? idx+scnt : len;
for (uint64_t i = idx; i < ie; i++)
{
seed = slist[i];
- env.setSeed(seed);
- if (testTreeAt(origin, &env, PASS_FULL_64, abort) == COND_OK)
+ env->setSeed(seed);
+ if (testTreeAt(origin, env, PASS_FULL_64, abort) == COND_OK)
{
if (!*abort)
emit result(seed);
@@ -1063,7 +972,7 @@ void SearchWorker::run()
break;
case SEARCH_48ONLY:
- while (!*abort && master->requestItem(this))
+ while (!*abort && getNextItem())
{
if (slist)
{
@@ -1071,8 +980,8 @@ void SearchWorker::run()
for (uint64_t i = idx; i < ie; i++)
{
seed = slist[i];
- env.setSeed(seed);
- if (testTreeAt(origin, &env, PASS_FULL_48, abort) != COND_FAILED)
+ env->setSeed(seed);
+ if (testTreeAt(origin, env, PASS_FULL_48, abort) != COND_FAILED)
{
if (!*abort)
emit result(seed);
@@ -1084,8 +993,8 @@ void SearchWorker::run()
seed = sstart;
for (int i = 0; i < scnt; i++)
{
- env.setSeed(seed);
- if (testTreeAt(origin, &env, PASS_FULL_48, abort) != COND_FAILED)
+ env->setSeed(seed);
+ if (testTreeAt(origin, env, PASS_FULL_48, abort) != COND_FAILED)
{
if (!*abort)
emit result(seed);
@@ -1102,7 +1011,7 @@ void SearchWorker::run()
break;
case SEARCH_INC:
- while (!*abort && master->requestItem(this))
+ while (!*abort && getNextItem())
{
if (slist)
{ // seed = (high << 48) | slist[..]
@@ -1113,8 +1022,8 @@ void SearchWorker::run()
{
seed = (high << 48) | slist[lowidx];
- env.setSeed(seed);
- if (testTreeAt(origin, &env, PASS_FULL_64, abort) == COND_OK)
+ env->setSeed(seed);
+ if (testTreeAt(origin, env, PASS_FULL_64, abort) == COND_OK)
{
if (!*abort)
emit result(seed);
@@ -1135,8 +1044,8 @@ void SearchWorker::run()
seed = sstart;
for (int i = 0; i < scnt; i++)
{
- env.setSeed(seed);
- if (testTreeAt(origin, &env, PASS_FULL_64, abort) == COND_OK)
+ env->setSeed(seed);
+ if (testTreeAt(origin, env, PASS_FULL_64, abort) == COND_OK)
{
if (!*abort)
emit result(seed);
@@ -1153,7 +1062,7 @@ void SearchWorker::run()
break;
case SEARCH_BLOCKS:
- while (!*abort && master->requestItem(this))
+ while (!*abort && getNextItem())
{ // seed = ([..] << 48) | low
if (slist && idx >= len)
{
@@ -1167,8 +1076,8 @@ void SearchWorker::run()
else
low = sstart & MASK48;
- env.setSeed(low);
- if (testTreeAt(origin, &env, PASS_FULL_48, abort) == COND_FAILED)
+ env->setSeed(low);
+ if (testTreeAt(origin, env, PASS_FULL_48, abort) == COND_FAILED)
{
continue;
}
@@ -1177,8 +1086,8 @@ void SearchWorker::run()
{
seed = (high << 48) | low;
- env.setSeed(seed);
- if (testTreeAt(origin, &env, PASS_FULL_64, abort) == COND_OK)
+ env->setSeed(seed);
+ if (testTreeAt(origin, env, PASS_FULL_64, abort) == COND_OK)
{
if (!*abort)
emit result(seed);
diff --git a/src/searchthread.h b/src/searchthread.h
index 0863723..436ca77 100644
--- a/src/searchthread.h
+++ b/src/searchthread.h
@@ -16,19 +16,19 @@
struct Session
{
void writeHeader(QTextStream& stream);
- bool save(QWidget *widget, QString fnam, bool quiet);
- bool load(QWidget *widget, QString fnam, bool quiet);
+ bool save(QWidget *widget, QTextStream& stream);
+ bool load(QWidget *widget, QTextStream& stream, bool quiet);
WorldInfo wi;
SearchConfig sc;
Gen48Config gen48;
- QVector cv;
+ std::vector cv;
std::vector slist;
};
struct SearchWorker;
-struct SearchMaster : QThread
+struct SearchMaster : QObject
{
Q_OBJECT
public:
@@ -37,9 +37,9 @@ struct SearchMaster : QThread
bool set(QWidget *widget, const Session& s);
- void presearch(QObject *qtobj);
+ void presearch();
- virtual void run() override;
+ void start();
void stop();
// Get search progress:
@@ -101,7 +101,9 @@ struct SearchWorker : QThread
Q_OBJECT
public:
SearchWorker(SearchMaster *master);
+ ~SearchWorker();
+ bool getNextItem();
virtual void run() override;
signals:
@@ -120,8 +122,11 @@ struct SearchWorker : QThread
uint64_t sstart; // starting seed
int scnt; // number of seeds to process in this item
uint64_t seed; // (out) current seed while processing
- // the end seed is highest unsigned seed value in the search space
+ // the end seed is the highest unsigned seed value in the search space
// (or the last entry in the seed list)
+
+private:
+ SearchThreadEnv * env;
};
diff --git a/src/seedtables.h b/src/seedtables.h
index a193dae..3e58b3f 100644
--- a/src/seedtables.h
+++ b/src/seedtables.h
@@ -113,6 +113,7 @@ static const uint64_t g_qm_90[] = {
261039958084216ULL,
264768543640500ULL,
265956699301296ULL,
+ 0
};
static const uint64_t g_qm_95[] = {
@@ -130,6 +131,7 @@ static const uint64_t g_qm_95[] = {
206145729365528ULL,
226043537443714ULL,
143737608964985ULL,
+ 0
};
diff --git a/src/tabbiomes.cpp b/src/tabbiomes.cpp
index 3df7bec..1535f49 100644
--- a/src/tabbiomes.cpp
+++ b/src/tabbiomes.cpp
@@ -1,15 +1,15 @@
#include "tabbiomes.h"
#include "ui_tabbiomes.h"
-#include "util.h"
-#include "world.h"
+
#include "message.h"
+#include "util.h"
+#include
#include
#include
-#include
#include
#include
-#include
+#include
#include
@@ -164,7 +164,7 @@ QVariant BiomeTableModel::data(const QModelIndex& index, int role) const
uint64_t seed = seeds[index.row()];
return cnt[id][seed];
}
- return QVariant::Invalid;
+ return QVariant();
}
QVariant BiomeTableModel::headerData(int section, Qt::Orientation orientation, int role) const
@@ -197,7 +197,7 @@ QVariant BiomeTableModel::headerData(int section, Qt::Orientation orientation, i
if (role == Qt::ToolTipRole && bname)
return QVariant::fromValue(QString("%1:%2").arg(id).arg(bname));
}
- return QVariant::Invalid;
+ return QVariant();
}
void BiomeTableModel::insertIds(QSet& nids)
@@ -738,8 +738,8 @@ void TabBiomes::on_pushStart_clicked()
thread.start();
}
-static
-void csvline(QTextStream& stream, const QString& qte, const QString& sep, QStringList& cols)
+
+static void csvline(QTextStream& stream, const QString& qte, const QString& sep, QStringList& cols)
{
if (qte.isEmpty())
{
@@ -750,27 +750,11 @@ void csvline(QTextStream& stream, const QString& qte, const QString& sep, QStrin
stream << qte << cols.join(sep) << qte << "\n";
}
-void TabBiomes::on_pushExport_clicked()
+void TabBiomes::exportResults(QTextStream& stream)
{
- QString fnam = QFileDialog::getSaveFileName(
- this, tr("Export biome analysis"), parent->prevdir, tr("Text files (*.txt *csv);;Any files (*)"));
- if (fnam.isEmpty())
- return;
-
- QFileInfo finfo(fnam);
- QFile file(fnam);
- parent->prevdir = finfo.absolutePath();
-
- if (!file.open(QIODevice::WriteOnly))
- {
- warn(parent, tr("Failed to open file for export:\n\"%1\"").arg(fnam));
- return;
- }
-
QString qte = parent->config.quote;
QString sep = parent->config.separator;
- QTextStream stream(&file);
stream << "Sep=" + sep + "\n";
sep = qte + sep + qte;
@@ -831,6 +815,35 @@ void TabBiomes::on_pushExport_clicked()
csvline(stream, qte, sep, cols);
}
}
+ stream.flush();
+}
+
+void TabBiomes::on_pushExport_clicked()
+{
+#if WASM
+ QByteArray content;
+ QTextStream stream(&content);
+ exportResults(stream);
+ QFileDialog::saveFileContent(content, "biomes.csv");
+#else
+ QString fnam = QFileDialog::getSaveFileName(
+ this, tr("Export biome analysis"), parent->prevdir, tr("Text files (*.txt *csv);;Any files (*)"));
+ if (fnam.isEmpty())
+ return;
+
+ QFileInfo finfo(fnam);
+ QFile file(fnam);
+ parent->prevdir = finfo.absolutePath();
+
+ if (!file.open(QIODevice::WriteOnly))
+ {
+ warn(parent, tr("Failed to open file for export:\n\"%1\"").arg(fnam));
+ return;
+ }
+
+ QTextStream stream(&file);
+ exportResults(stream);
+#endif
}
void TabBiomes::on_buttonFromVisible_clicked()
diff --git a/src/tabbiomes.h b/src/tabbiomes.h
index 9bbd02e..0b5c562 100644
--- a/src/tabbiomes.h
+++ b/src/tabbiomes.h
@@ -8,8 +8,6 @@
#include
#include "mainwindow.h"
-#include "search.h"
-#include "world.h"
#include "util.h"
namespace Ui {
@@ -150,6 +148,9 @@ private slots:
void on_treeLocate_itemClicked(QTreeWidgetItem *item, int column);
void on_tabWidget_currentChanged(int index);
+private:
+ void exportResults(QTextStream& stream);
+
private:
Ui::TabBiomes *ui;
MainWindow *parent;
diff --git a/src/tablocations.cpp b/src/tablocations.cpp
index 2ea946a..9e3fc74 100644
--- a/src/tablocations.cpp
+++ b/src/tablocations.cpp
@@ -1,20 +1,20 @@
#include "tablocations.h"
#include "ui_tablocations.h"
+#include "config.h"
#include "message.h"
#include "util.h"
-#include "config.h"
+#include
#include
#include
-#include
#include
#include
-#include
+#include
-#include
#include
#include
+#include
#define SAMPLES_MAX 99999999
@@ -61,12 +61,12 @@ QTreeWidgetItem *setConditionTreeItems(ConditionTree& ctree, int node, int64_t s
return item;
}
-QString AnalysisLocations::set(WorldInfo wi, const QVector& conds)
+QString AnalysisLocations::set(WorldInfo wi, const std::vector& conds)
{
this->wi = wi;
QString err = condtree.set(conds, wi.mc);
if (err.isEmpty())
- err = env.init(wi.mc, wi.large, &condtree);
+ err = env.init(wi.mc, wi.large, condtree);
return err;
}
@@ -134,7 +134,6 @@ TabLocations::TabLocations(MainWindow *parent)
ui->lineX->setValidator(new QIntValidator((int)-3e7, (int)3e7, this));
ui->lineZ->setValidator(new QIntValidator((int)-3e7, (int)3e7, this));
- connect(&thread, &AnalysisLocations::warning, this, &TabLocations::warning, Qt::BlockingQueuedConnection);
connect(&thread, &AnalysisLocations::itemDone, this, &TabLocations::onAnalysisItemDone, Qt::BlockingQueuedConnection);
connect(&thread, &AnalysisLocations::finished, this, &TabLocations::onAnalysisFinished);
@@ -192,11 +191,6 @@ void TabLocations::load(QSettings& settings)
maxresults = settings.value("config/maxMatching", maxresults).toInt();
}
-int TabLocations::warning(QString text, QMessageBox::StandardButtons buttons)
-{
- return warn(parent, text, buttons);
-}
-
void TabLocations::onAnalysisItemDone(QTreeWidgetItem *item)
{
if (qbuf.size() + ui->treeWidget->topLevelItemCount() >= maxresults)
@@ -281,12 +275,12 @@ void TabLocations::on_pushStart_clicked()
WorldInfo wi;
parent->getSeed(&wi);
- QVector conds = parent->formCond->getConditions();
+ std::vector conds = parent->formCond->getConditions();
QString err = thread.set(wi, conds);
if (!err.isEmpty())
{
- warning(err, QMessageBox::Ok);
+ warn(this, err);
return;
}
@@ -420,10 +414,10 @@ void TabLocations::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
QVariant at = item->data(0, Qt::UserRole+2);
std::vector shapes;
- const QVector& conds = thread.condtree.condvec;
+ const std::vector& conds = thread.condtree.condvec;
int node = item->data(0, Qt::UserRole+3).toInt();
- if (node >= 0 || node < conds.size())
+ if (node >= 0 || node < (int)conds.size())
{
const Condition& c = conds[node];
const FilterInfo& ft = g_filterinfo.list[c.type];
@@ -482,8 +476,7 @@ void TabLocations::on_pushExpand_clicked()
ui->treeWidget->collapseAll();
}
-static
-void csvline(QTextStream& stream, const QString& qte, const QString& sep, QStringList& cols)
+static void csvline(QTextStream& stream, const QString& qte, const QString& sep, QStringList& cols)
{
if (qte.isEmpty())
{
@@ -494,27 +487,11 @@ void csvline(QTextStream& stream, const QString& qte, const QString& sep, QStrin
stream << qte << cols.join(sep) << qte << "\n";
}
-void TabLocations::on_pushExport_clicked()
+void TabLocations::exportResults(QTextStream& stream)
{
- QString fnam = QFileDialog::getSaveFileName(
- this, tr("Export locations"), parent->prevdir, tr("Text files (*.txt *csv);;Any files (*)"));
- if (fnam.isEmpty())
- return;
-
- QFileInfo finfo(fnam);
- QFile file(fnam);
- parent->prevdir = finfo.absolutePath();
-
- if (!file.open(QIODevice::WriteOnly))
- {
- warn(parent, tr("Failed to open file for export:\n\"%1\"").arg(fnam));
- return;
- }
-
QString qte = parent->config.quote;
QString sep = parent->config.separator;
- QTextStream stream(&file);
stream << "Sep=" + sep + "\n";
sep = qte + sep + qte;
@@ -534,5 +511,34 @@ void TabLocations::on_pushExport_clicked()
}
csvline(stream, qte, sep, cols);
}
+ stream.flush();
+}
+
+void TabLocations::on_pushExport_clicked()
+{
+#if WASM
+ QByteArray content;
+ QTextStream stream(&content);
+ exportResults(stream);
+ QFileDialog::saveFileContent(content, "locations.csv");
+#else
+ QString fnam = QFileDialog::getSaveFileName(
+ this, tr("Export locations"), parent->prevdir, tr("Text files (*.txt *csv);;Any files (*)"));
+ if (fnam.isEmpty())
+ return;
+
+ QFileInfo finfo(fnam);
+ QFile file(fnam);
+ parent->prevdir = finfo.absolutePath();
+
+ if (!file.open(QIODevice::WriteOnly))
+ {
+ warn(parent, tr("Failed to open file for export:\n\"%1\"").arg(fnam));
+ return;
+ }
+
+ QTextStream stream(&file);
+ exportResults(stream);
+#endif
}
diff --git a/src/tablocations.h b/src/tablocations.h
index 2a6d770..02a54e8 100644
--- a/src/tablocations.h
+++ b/src/tablocations.h
@@ -7,7 +7,6 @@
#include "mainwindow.h"
#include "search.h"
-#include "world.h"
namespace Ui {
class TabLocations;
@@ -20,13 +19,12 @@ class AnalysisLocations : public QThread
explicit AnalysisLocations(QObject *parent = nullptr)
: QThread(parent), wi(),stop(),sidx(),pidx() {}
- QString set(WorldInfo wi, const QVector& conds);
+ QString set(WorldInfo wi, const std::vector& conds);
virtual void run() override;
signals:
void itemDone(QTreeWidgetItem *item);
- int warning(QString text, QMessageBox::StandardButtons buttons);
public:
WorldInfo wi;
@@ -53,7 +51,6 @@ class TabLocations : public QWidget, public ISaveTab
virtual void load(QSettings& settings) override;
private slots:
- int warning(QString text, QMessageBox::StandardButtons buttons);
void onAnalysisItemDone(QTreeWidgetItem *item);
void onAnalysisFinished();
void onBufferTimeout();
@@ -64,6 +61,9 @@ private slots:
void on_pushExport_clicked();
void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column);
+private:
+ void exportResults(QTextStream& stream);
+
private:
Ui::TabLocations *ui;
MainWindow *parent;
diff --git a/src/tabstructures.cpp b/src/tabstructures.cpp
index 87bb116..2f8d4cf 100644
--- a/src/tabstructures.cpp
+++ b/src/tabstructures.cpp
@@ -1,13 +1,13 @@
#include "tabstructures.h"
#include "ui_tabstructures.h"
-#include "util.h"
#include "message.h"
+#include "util.h"
-#include
#include
-#include
#include
+#include
+#include
#include