Merge branch 'mapper-location'

master
adrido 2015-10-14 17:58:37 +02:00
commit 66d7c55967
8 changed files with 550 additions and 9 deletions

6
.gitignore vendored
View File

@ -22,7 +22,7 @@
Makefile
MinetestMapperGui
*.o
moc_mainwindow.cpp
qrc_minetestmappergui.cpp
ui_mainwindow.h
moc_*.cpp
qrc_*.cpp
ui_*.h

View File

@ -16,14 +16,17 @@ TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
colorlineedit.cpp \
geometrywidget.cpp
geometrywidget.cpp \
configdialog.cpp
HEADERS += mainwindow.h \
colorlineedit.h \
geometrywidget.h
geometrywidget.h \
configdialog.h
FORMS += mainwindow.ui \
geometrywidget.ui
geometrywidget.ui \
configdialog.ui
RESOURCES += \
minetestmappergui.qrc

281
configdialog.cpp Normal file
View File

@ -0,0 +1,281 @@
#include <QFileDialog>
#include <QMessageBox>
#include <QString>
#include <QDebug>
#include <QStandardPaths>
#include <QProcessEnvironment>
#include "configdialog.h"
#include "ui_configdialog.h"
#include "mainwindow.h"
const QString ConfigSettings::defaultMapperExecutableName("minetestmapper");
QStringList ConfigSettings::predefinedMapperLocations;
QString ConfigSettings::versionUnknown("(unknown)");
QString ConfigSettings::versionError("(error)");
QString ConfigSettings::optionsVersionKey("(version)");
QString ConfigSettings::optionsTreeKey("(github-tree)");
QString ConfigSettings::optionsTreeMinetest("minetest");
QString ConfigSettings::optionsTreeRogier5("Rogier5");
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::getMapperVersion(const QString &mapperBinary, QWidget *parent)
{
QProcess mapperProcess(parent);
mapperProcess.setProgram(mapperBinary);
mapperProcess.setArguments(QStringList("--version"));
mapperProcess.start();
if (!mapperProcess.waitForStarted(1000)) {
mapperProcess.terminate();
return ConfigSettings::versionError;
}
if (!mapperProcess.waitForFinished(1000)) {
mapperProcess.terminate();
if (!mapperProcess.waitForFinished(1000)) {
mapperProcess.kill();
}
return ConfigSettings::versionError;
}
QByteArray dataRaw;
QString data;
dataRaw = mapperProcess.readAllStandardError();
data = QString(dataRaw).trimmed();
if (data.contains("unrecognized option")) {
return ConfigSettings::versionUnknown;
}
dataRaw = mapperProcess.readAllStandardOutput();
data = QString(dataRaw).trimmed();
if (!data.contains("Version-ID:")) {
return ConfigSettings::versionUnknown;
}
return data.replace(QRegularExpression(".*Version-ID: *"),"");
}
// Also store the deduced github source tree and the version in the list
QMap<QString, QString> ConfigSettings::getMapperOptions(const QString &mapperBinary, QWidget *parent)
{
QRegularExpression optionRegex("^(|-[a-zA-Z].*)(--[a-zA-Z0-9][a-zA-Z0-9-_]+)( *(.*[^ \t\r\n]))?[ \t\r\n]*$");
QMap<QString, QString> options;
QProcess mapperProcess(parent);
mapperProcess.setProgram(mapperBinary);
mapperProcess.setArguments(QStringList("--help"));
mapperProcess.start();
if (!mapperProcess.waitForStarted(1000)) {
mapperProcess.terminate();
return options;
}
if (!mapperProcess.waitForFinished(1000)) {
mapperProcess.terminate();
if (!mapperProcess.waitForFinished(1000)) {
mapperProcess.kill();
}
return options;
}
QByteArray helpTextRaw = mapperProcess.readAllStandardOutput();
QStringList helpText = QString(helpTextRaw).trimmed().split("\n");
for (int i = 0; i < helpText.count(); i++) {
QString helpLine = helpText[i].trimmed();
if (helpLine.contains("Color format: '#000000'")) {
options[ConfigSettings::optionsTreeKey] = ConfigSettings::optionsTreeMinetest;
}
else if (helpLine.contains("X and Y coordinate formats:")) {
options[ConfigSettings::optionsTreeKey] = ConfigSettings::optionsTreeRogier5;
}
QString option = helpLine;
option.replace(optionRegex, "\\2");
if (option[1] != '-' || option.contains(' ')) continue;
QString arguments = helpLine;
arguments.replace(optionRegex, "\\4");
if (arguments == helpLine) arguments = "";
options[option] = arguments;
}
options[ConfigSettings::optionsVersionKey] = getMapperVersion(mapperBinary, parent);
return options;
}
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();
}

67
configdialog.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef CONFIGDIALOG_H
#define CONFIGDIALOG_H
#include <QDialog>
#include <QMap>
#include <QString>
namespace Ui {
class ConfigDialog;
}
class MainWindow;
struct ConfigSettings
{
QString mapperPath;
static QString versionUnknown;
static QString versionError;
static QString optionsVersionKey;
static QString optionsTreeKey;
static QString optionsTreeMinetest;
static QString optionsTreeRogier5;
static QStringList getMapperExecutables(void);
static QString getDefaultMapperExecutable(void);
static const QString defaultMapperExecutableName;
static QStringList predefinedMapperLocations;
static QString getMapperVersion(const QString &mapperBinary, QWidget *parent = NULL);
static QMap<QString, QString> getMapperOptions(const QString &mapperBinary, QWidget *parent = NULL);
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

101
configdialog.ui Normal file
View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigDialog</class>
<widget class="QDialog" name="ConfigDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>483</width>
<height>66</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="2">
<widget class="QPushButton" name="browseMapper">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Browse</string>
</property>
<property name="icon">
<iconset resource="minetestmappergui.qrc">
<normaloff>:/open</normaloff>:/open</iconset>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="CancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ApplyButton">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="OKButton">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="path_Minetestmapper">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mapper Location: </string>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="minetestmappergui.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -9,6 +9,8 @@
#include <QCompleter>
#include <QDirModel>
#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,41 @@ 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<br><br>"
"Please configure one (Edit->Preferences)"));
else
QMessageBox::critical(this, tr("Minetestmapper not found"),
tr("ERROR: Configured minetestmapper executable (%1) could not be found<br><br>"
"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;
}
qDebug() << QString("Minetestmapper version: ") + ConfigSettings::getMapperVersion(mapperBinary.fileName(), this);
QDir worldPath = QDir(ui->path_World->text());
if(!worldPath.exists()||worldPath.path()=="."||worldPath.path()=="/"){
QMessageBox::critical(this, tr("no input world selected"),
@ -372,9 +405,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()<<imgName;
myProcess->setArguments(arguments);
@ -672,6 +706,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());
@ -744,6 +782,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());
@ -965,3 +1006,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;
}

View File

@ -17,6 +17,7 @@
#include <QWinTaskbarButton>
#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)

View File

@ -2279,6 +2279,7 @@
<addaction name="separator"/>
<addaction name="actionEdit_heightmap_nodes_txt"/>
<addaction name="actionEdit_heightmap_colors_txt"/>
<addaction name="actionPreferences"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
@ -2564,6 +2565,11 @@ p, li { white-space: pre-wrap; }
<string>Open map after creation with the default png viewer</string>
</property>
</action>
<action name="actionPreferences">
<property name="text">
<string>&amp;Preferences</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>