Make minetestmapper location configurable. Search for & propose candidates.

master
Rogier 2015-07-04 07:42:23 +02:00
parent 9a06348f99
commit 20b8e53234
7 changed files with 450 additions and 6 deletions

View File

@ -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

197
configdialog.cpp Normal file
View File

@ -0,0 +1,197 @@
#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;
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();
}

56
configdialog.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef CONFIGDIALOG_H
#define CONFIGDIALOG_H
#include <QDialog>
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

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,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<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;
}
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()<<imgName;
myProcess->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;
}

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

@ -2283,6 +2283,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">
@ -2568,6 +2569,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>