diff --git a/MinetestMapperGui.pro b/MinetestMapperGui.pro index 6bc7a51..2a9f229 100644 --- a/MinetestMapperGui.pro +++ b/MinetestMapperGui.pro @@ -15,12 +15,15 @@ TEMPLATE = app SOURCES += main.cpp\ mainwindow.cpp \ - colorlineedit.cpp + colorlineedit.cpp \ + configdialog.cpp HEADERS += mainwindow.h \ - colorlineedit.h + colorlineedit.h \ + configdialog.h -FORMS += mainwindow.ui +FORMS += mainwindow.ui \ + configdialog.ui RESOURCES += \ minetestmappergui.qrc diff --git a/configdialog.cpp b/configdialog.cpp new file mode 100644 index 0000000..7c53bdd --- /dev/null +++ b/configdialog.cpp @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include +#include + +#include "configdialog.h" +#include "ui_configdialog.h" +#include "mainwindow.h" + +const QString ConfigSettings::defaultMapperExecutableName("minetestmapper"); +QStringList ConfigSettings::predefinedMapperLocations; + +ConfigSettings::InitStatics::InitStatics() +{ + #ifndef Q_OS_WIN + ConfigSettings::predefinedMapperLocations << "/bin/" + defaultMapperExecutableName; + ConfigSettings::predefinedMapperLocations << "/usr/bin/" + defaultMapperExecutableName; + ConfigSettings::predefinedMapperLocations << "/usr/local/bin/" + defaultMapperExecutableName; + #endif +} + + +ConfigDialog::ConfigDialog(const ConfigSettings &settings, MainWindow *app, QWidget *parent) : + QDialog(parent), + ui(new Ui::ConfigDialog), + settings(settings), + application(app) +{ + ui->setupUi(this); + executableList = ConfigSettings::getMapperExecutables(); + QString standardExecutable; + if (!executableList.empty()) + standardExecutable = executableList.at(0); + if (standardExecutable != "") + executableList.push_front(tr("---Automatic--- (Currently: %1)").arg(standardExecutable)); + else + executableList.push_front(tr("---Automatic--- (Currently: NONE - Minetestmapper Not Found)")); + ui->path_Minetestmapper->addItems(executableList); + ui->path_Minetestmapper->setCurrentIndex(0); + if (settings.mapperPath != "") { + ui->path_Minetestmapper->setCurrentText(settings.mapperPath); + if (ui->path_Minetestmapper->currentText() != settings.mapperPath) { + // Unfortunately, adding it means that the saved path can be chosen again, even if it + // does not exist. Can't avoid that, as we still want it to be the *current* value... + executableList.push_back(settings.mapperPath); + ui->path_Minetestmapper->addItem(settings.mapperPath); + ui->path_Minetestmapper->setCurrentText(settings.mapperPath); + // TODO: make the combobox editable (also solves the problem above) + } + } +} + +ConfigDialog::~ConfigDialog() +{ + delete ui; +} + +void ConfigDialog::on_browseMapper_clicked() +{ + #ifdef Q_OS_WIN + QString fileType = tr("Executable (*.exe)"); + #else + QString fileType; + #endif + + bool selectionSeemsOK; + QString fileName; + if (ui->path_Minetestmapper->currentIndex() != 0) { + fileName = ui->path_Minetestmapper->currentText(); + } + else if (ui->path_Minetestmapper->count() > 0) { + fileName = ui->path_Minetestmapper->itemText(1); + } + else { + #ifdef Q_OS_WIN + fileName = QCoreApplication::applicationDirPath(); + #else + fileName = QDir::currentPath(); + #endif + } + do { + fileName = QFileDialog::getOpenFileName(this, tr("Select Mapper Location"), + fileName, + fileType); + if (fileName != "" && !(QFile(fileName).permissions() & QFileDevice::ExeUser)) { + selectionSeemsOK = false; + QMessageBox::critical(this, tr("Invalid minetestmapper executable"), + tr("ERROR: The selected file is not executable")); + } + else { + // TODO: verify if it is minetestmapper (?) -> invoke with --help ? + selectionSeemsOK = true; + } + } while (!selectionSeemsOK); + + if(fileName != "") { + settings.mapperPath = fileName; + ui->path_Minetestmapper->setCurrentText(fileName); + if (ui->path_Minetestmapper->currentText() != fileName) { + executableList.push_back(fileName); + ui->path_Minetestmapper->addItem(fileName); + ui->path_Minetestmapper->setCurrentText(fileName); + } + } +} + +QString ConfigSettings::getDefaultMapperExecutable(void) +{ + QStringList locations = getMapperExecutables(); + if (locations.empty()) return ""; + else return locations.at(0); +} + +void ConfigSettings::addMapperExecutablesToList(QStringList &existingList, QStringList &pathList) +{ + QString prevLocation; + for (; ! pathList.empty(); pathList.pop_front()) { + QString location = QStandardPaths::findExecutable(ConfigSettings::defaultMapperExecutableName, pathList); + if (location != "" && prevLocation != location) { + prevLocation = location; + int count = existingList.count(); + int i; + for (i = 0; i < count; i++) { + if (existingList[i] == location) + break; + } + if (i >= count) + existingList << location; + } + } +} + +QStringList ConfigSettings::getMapperExecutables(void) +{ + QStringList mapperLocations; + QStringList moreLocations = ConfigSettings::predefinedMapperLocations; + + // On windows, check installation directory of minetestmappergui, & give precedence over anything else + #ifdef Q_OS_WIN + QString appDir = QCoreApplication::applicationDirPath(); + QString mapperFileName; + + mapperFileName = QStandardPaths::findExecutable(ConfigSettings::defaultMapperExecutableName, QStringList(appDir)); + if (mapperFileName != "") + mapperLocations << mapperFileName; + + mapperFileName = QStandardPaths::findExecutable(ConfigSettings::defaultMapperExecutableName, QStringList(appDir + '/' + ConfigSettings::defaultMapperExecutableName)); + if (mapperFileName != "") + mapperLocations << mapperFileName; + + mapperFileName = QStandardPaths::findExecutable(ConfigSettings::defaultMapperExecutableName, QStringList(appDir + "/mapper")); + if (mapperFileName != "") + mapperLocations << mapperFileName; + #endif + + // Find all minetestmappers in PATH. Unfortunately, it seems that QT can't do this directly... + QStringList path = QProcessEnvironment::systemEnvironment().value("PATH").split(":"); + addMapperExecutablesToList(mapperLocations, path); + + // Find all minetestmappers in QStandardPaths::ApplicationsLocation, add if not already added + QStringList appLocations = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation); + addMapperExecutablesToList(mapperLocations, appLocations); + + // Add locations from moreLocations that were not already added + addMapperExecutablesToList(mapperLocations, moreLocations); + + return mapperLocations; +} + + +void ConfigDialog::on_path_Minetestmapper_currentIndexChanged(int index) +{ + if (index == 0) + settings.mapperPath = ""; + else + settings.mapperPath = ui->path_Minetestmapper->currentText(); +} + + + +void ConfigDialog::on_CancelButton_clicked() +{ + application->closeConfigDialog(); +} + +void ConfigDialog::on_ApplyButton_clicked() +{ + application->updateConfigSettings(settings); +} + +void ConfigDialog::on_OKButton_clicked() +{ + on_ApplyButton_clicked(); + on_CancelButton_clicked(); +} diff --git a/configdialog.h b/configdialog.h new file mode 100644 index 0000000..fa8d60a --- /dev/null +++ b/configdialog.h @@ -0,0 +1,56 @@ +#ifndef CONFIGDIALOG_H +#define CONFIGDIALOG_H + +#include + + +namespace Ui { +class ConfigDialog; +} +class MainWindow; + +struct ConfigSettings +{ + QString mapperPath; + + static QStringList getMapperExecutables(void); + static QString getDefaultMapperExecutable(void); + static const QString defaultMapperExecutableName; + static QStringList predefinedMapperLocations; + +private: + struct InitStatics { InitStatics(void); }; + static const InitStatics initStatics; + friend struct InitStatics; + + static void addMapperExecutablesToList(QStringList &existingList, QStringList &pathList); +}; + +class ConfigDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ConfigDialog(const ConfigSettings &settings, MainWindow *app, QWidget *parent = 0); + ~ConfigDialog(); + +private: + Ui::ConfigDialog *ui; + QStringList executableList; + ConfigSettings settings; + MainWindow *application; + +protected slots: + +private slots: + + void on_browseMapper_clicked(); + + void on_path_Minetestmapper_currentIndexChanged(int index); + + void on_CancelButton_clicked(); + void on_ApplyButton_clicked(); + void on_OKButton_clicked(); +}; + +#endif // CONFIGDIALOG_H diff --git a/configdialog.ui b/configdialog.ui new file mode 100644 index 0000000..c2cf779 --- /dev/null +++ b/configdialog.ui @@ -0,0 +1,101 @@ + + + ConfigDialog + + + + 0 + 0 + 483 + 66 + + + + Dialog + + + + + + + 0 + 0 + + + + Browse + + + + :/open:/open + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + Apply + + + + + + + OK + + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Mapper Location: + + + + + + + + + + diff --git a/mainwindow.cpp b/mainwindow.cpp index ca74f61..773e6d0 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -9,6 +9,8 @@ #include #include +#include "configdialog.h" + #if defined(Q_OS_WIN) static const QString qSettingsOrganisation("addi"); static const QString qSettingsApplicationPrefix("Minetestmapper_"); @@ -45,7 +47,8 @@ InitStatics::InitStatics(void) MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), - ui(new Ui::MainWindow) + ui(new Ui::MainWindow), + configDialog(NULL) { #ifndef Q_OS_WIN if (!migrateSettingsProfiles()) @@ -191,11 +194,39 @@ void MainWindow::changeEvent(QEvent* event) MainWindow::~MainWindow() { + if (configDialog) { + delete configDialog; + configDialog = NULL; + } delete ui; } void MainWindow::on_button_generate_clicked() { + + QFile mapperBinary; + if (currentSettings.mapperPath == "") + mapperBinary.setFileName(ConfigSettings::getDefaultMapperExecutable()); + else + mapperBinary.setFileName(currentSettings.mapperPath); + if (!mapperBinary.exists()) { + if (currentSettings.mapperPath == "") + QMessageBox::critical(this, tr("Minetestmapper not found"), + tr("ERROR: No minetestmapper executable could not be found

" + "Please configure one (Edit->Preferences)")); + else + QMessageBox::critical(this, tr("Minetestmapper not found"), + tr("ERROR: Configured minetestmapper executable (%1) could not be found

" + "Please configure one (Edit->Preferences)").arg(currentSettings.mapperPath)); + return; + } else if (!(mapperBinary.permissions() & QFileDevice::ExeUser)) { + QMessageBox::critical(this, tr("Minetestmapper not executable"), + tr("ERROR: The configured minetestmapper (%1) is not executable" + "Please configure a valid minetestmapper executable (Edit->Preferences)") + .arg(mapperBinary.fileName())); + return; + } + QDir worldPath = QDir(ui->path_World->text()); if(!worldPath.exists()||worldPath.path()=="."||worldPath.path()=="/"){ QMessageBox::critical(this, tr("no input world selected"), @@ -372,9 +403,10 @@ void MainWindow::on_button_generate_clicked() } myProcess = new QProcess(this); + #ifdef Q_OS_WIN myProcess->setWorkingDirectory(appDir); - QString program = appDir+"/mapper/minetestmapper"; - myProcess->setProgram(program); + #endif + myProcess->setProgram(mapperBinary.fileName()); qDebug()<setArguments(arguments); @@ -672,6 +704,10 @@ void MainWindow::writeProfile(QString profile) //todo: check the current profile settings.beginGroup("Mapper"); + //'currentSettings' + settings.setValue("path_minetestmapper", currentSettings.mapperPath); + + //tab1 General settings.setValue("path_OutputImage", ui->path_OutputImage->text()); settings.setValue("path_World", ui->path_World->text()); settings.setValue("backend",ui->backend->currentIndex()); @@ -743,6 +779,9 @@ void MainWindow::readProfile(QString profile) { QSettings settings(QSettings::IniFormat,QSettings::UserScope,qSettingsOrganisation, qSettingsApplicationPrefix+"profile_"+profile); settings.beginGroup("Mapper"); + //'currentSettings' + currentSettings.mapperPath = settings.value("path_minetestmapper").toString(); + //tab1 Genral ui->path_World->setText(settings.value("path_World",QDir::homePath()).toString()); ui->path_OutputImage->setText(settings.value("path_OutputImage",QDir::homePath().append("/map.png")).toString()); @@ -963,3 +1002,35 @@ void MainWindow::on_tileorigin_clicked() { ui->tiles_map->setText(tr("map origin (top left)")); } + +void MainWindow::on_actionPreferences_triggered() +{ + if (!configDialog) { + configDialog = new ConfigDialog(currentSettings, this, this); + configDialog->show(); + } else { + configDialog->show(); + configDialog->activateWindow(); + } +} + +void MainWindow::closeConfigDialog(void) +{ + if (configDialog) { + delete configDialog; + configDialog = NULL; + } +} + +void MainWindow::updateConfigSettings(const ConfigSettings &newSettings) +{ + if (newSettings.mapperPath != currentSettings.mapperPath) { + // Update all 'auto' paths (colors files, ...) ??? + // (currently there are none, but in the future, + // colors files could be searched for relative to the minetestmapper path. + // If the mapper path changes, the paths of the possible colors files + // may change as well + } + currentSettings = newSettings; +} + diff --git a/mainwindow.h b/mainwindow.h index c151b92..52a9bdd 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -17,6 +17,7 @@ #include #endif +#include "configdialog.h" namespace Ui { class MainWindow; @@ -30,6 +31,10 @@ public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); + // Interaction with config dialog + void closeConfigDialog(void); + void updateConfigSettings(const ConfigSettings &newSettings); + protected: void closeEvent(QCloseEvent* event); // this event is called, when a new translator is loaded or the system language is changed @@ -93,6 +98,8 @@ private slots: void on_tileorigin_clicked(); + void on_actionPreferences_triggered(); + private: Ui::MainWindow *ui; QProgressBar *progressBar; @@ -103,6 +110,9 @@ private: QWinTaskbarButton *taskbarButton; QWinTaskbarProgress *taskbarProgress; #endif + ConfigSettings currentSettings; + ConfigDialog *configDialog; + void finishUiInitialisation(void); // loads a language by the given language shortcur (e.g. de, en) diff --git a/mainwindow.ui b/mainwindow.ui index b396756..21485d3 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -2283,6 +2283,7 @@ + @@ -2568,6 +2569,11 @@ p, li { white-space: pre-wrap; } Open map after creation with the default png viewer + + + &Preferences + +