diff --git a/doomsday/tools/shell/shell-gui/res/shell.qrc b/doomsday/tools/shell/shell-gui/res/shell.qrc
index a84df3ff12..1bea5003ce 100644
--- a/doomsday/tools/shell/shell-gui/res/shell.qrc
+++ b/doomsday/tools/shell/shell-gui/res/shell.qrc
@@ -2,5 +2,6 @@
shell.png
shell@2x.png
+ toolbar_placeholder.png
diff --git a/doomsday/tools/shell/shell-gui/res/toolbar_placeholder.png b/doomsday/tools/shell/shell-gui/res/toolbar_placeholder.png
new file mode 100644
index 0000000000..c069b1ee35
Binary files /dev/null and b/doomsday/tools/shell/shell-gui/res/toolbar_placeholder.png differ
diff --git a/doomsday/tools/shell/shell-gui/shell-gui.pro b/doomsday/tools/shell/shell-gui/shell-gui.pro
index 0cf73e10fd..0535cb3148 100644
--- a/doomsday/tools/shell/shell-gui/shell-gui.pro
+++ b/doomsday/tools/shell/shell-gui/shell-gui.pro
@@ -69,3 +69,15 @@ else {
INSTALLS += target
target.path = $$DENG_BIN_DIR
}
+
+HEADERS += \
+ src/folderselection.h
+
+SOURCES += \
+ src/folderselection.cpp
+
+HEADERS += \
+ src/preferences.h
+
+SOURCES += \
+ src/preferences.cpp
diff --git a/doomsday/tools/shell/shell-gui/src/folderselection.cpp b/doomsday/tools/shell/shell-gui/src/folderselection.cpp
new file mode 100644
index 0000000000..0cfaee7180
--- /dev/null
+++ b/doomsday/tools/shell/shell-gui/src/folderselection.cpp
@@ -0,0 +1,87 @@
+/** @file folderselection.cpp Widget for selecting a folder.
+ *
+ * @authors Copyright © 2013 Jaakko Keränen
+ *
+ * @par License
+ * GPL: http://www.gnu.org/licenses/gpl.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. This program is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the GNU
+ * General Public License along with this program; if not, see:
+ * http://www.gnu.org/licenses
+ */
+
+#include "folderselection.h"
+#include
+#include
+#include
+#include
+
+DENG2_PIMPL(FolderSelection)
+{
+ QString prompt;
+ QLineEdit *edit;
+ QPushButton *button;
+
+ Instance(Public &i) : Base(i),
+ edit(0),
+ button(0)
+ {
+ /*
+ // What's up with the extra spacing?
+ QPalette pal = self.palette();
+ pal.setColor(self.backgroundRole(), Qt::red);
+ self.setPalette(pal);
+ self.setAutoFillBackground(true);
+ */
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ self.setLayout(layout);
+
+ edit = new QLineEdit;
+ edit->setMinimumWidth(280);
+ button = new QPushButton(tr("..."));
+
+ layout->addWidget(edit, 1);
+ layout->addWidget(button, 0);
+ }
+};
+
+FolderSelection::FolderSelection(QString const &prompt, QWidget *parent)
+ : QWidget(parent), d(new Instance(*this))
+{
+ d->prompt = prompt;
+
+ connect(d->button, SIGNAL(clicked()), this, SLOT(selectFolder()));
+}
+
+FolderSelection::~FolderSelection()
+{
+ delete d;
+}
+
+void FolderSelection::setPath(de::NativePath const &path)
+{
+ d->edit->setText(path.toString());
+}
+
+de::NativePath FolderSelection::path() const
+{
+ return d->edit->text();
+}
+
+void FolderSelection::selectFolder()
+{
+ QString dir = QFileDialog::getExistingDirectory(0, d->prompt, d->edit->text());
+ if(!dir.isEmpty())
+ {
+ d->edit->setText(dir);
+ emit selected();
+ }
+}
diff --git a/doomsday/tools/shell/shell-gui/src/folderselection.h b/doomsday/tools/shell/shell-gui/src/folderselection.h
new file mode 100644
index 0000000000..f43308e252
--- /dev/null
+++ b/doomsday/tools/shell/shell-gui/src/folderselection.h
@@ -0,0 +1,52 @@
+/** @file folderselection.h Widget for selecting a folder.
+ *
+ * @authors Copyright © 2013 Jaakko Keränen
+ *
+ * @par License
+ * GPL: http://www.gnu.org/licenses/gpl.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. This program is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the GNU
+ * General Public License along with this program; if not, see:
+ * http://www.gnu.org/licenses
+ */
+
+#ifndef FOLDERSELECTION_H
+#define FOLDERSELECTION_H
+
+#include
+#include
+#include
+
+/**
+ * Widget for selecting a folder.
+ */
+class FolderSelection : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FolderSelection(QString const &prompt, QWidget *parent = 0);
+ virtual ~FolderSelection();
+
+ void setPath(de::NativePath const &path);
+
+ de::NativePath path() const;
+
+signals:
+ void selected();
+
+public slots:
+ void selectFolder();
+
+private:
+ struct Instance;
+ Instance *d;
+};
+
+#endif // FOLDERSELECTION_H
diff --git a/doomsday/tools/shell/shell-gui/src/guishellapp.cpp b/doomsday/tools/shell/shell-gui/src/guishellapp.cpp
index dd6655c8c8..9aed3c9a97 100644
--- a/doomsday/tools/shell/shell-gui/src/guishellapp.cpp
+++ b/doomsday/tools/shell/shell-gui/src/guishellapp.cpp
@@ -21,6 +21,7 @@
#include "opendialog.h"
#include "aboutdialog.h"
#include "localserverdialog.h"
+#include "preferences.h"
#include
#include
#include
@@ -42,6 +43,11 @@ struct GuiShellApp::Instance
#endif
QList windows;
+ Preferences *prefs;
+
+ Instance() : prefs(0)
+ {}
+
~Instance()
{
foreach(LinkWindow *win, windows)
@@ -87,7 +93,8 @@ GuiShellApp::GuiShellApp(int &argc, char **argv)
connect(svMenu, SIGNAL(aboutToShow()), this, SLOT(updateMenu()));
- // This will appear in the application menu:
+ // These will appear in the application menu:
+ menu->addAction(tr("Preferences..."), this, SLOT(showPreferences()), QKeySequence(tr("Ctrl+,")));
menu->addAction(tr("About"), this, SLOT(aboutShell()));
#endif
@@ -248,6 +255,26 @@ void GuiShellApp::aboutShell()
AboutDialog().exec();
}
+void GuiShellApp::showPreferences()
+{
+ if(!d->prefs)
+ {
+ d->prefs = new Preferences;
+ connect(d->prefs, SIGNAL(finished(int)), this, SLOT(preferencesDone()));
+ d->prefs->open();
+ }
+ else
+ {
+ d->prefs->activateWindow();
+ }
+}
+
+void GuiShellApp::preferencesDone()
+{
+ d->prefs->deleteLater();
+ d->prefs = 0;
+}
+
void GuiShellApp::updateMenu()
{
#ifdef MACOSX
diff --git a/doomsday/tools/shell/shell-gui/src/guishellapp.h b/doomsday/tools/shell/shell-gui/src/guishellapp.h
index 1dccb3369a..45ac8a975b 100644
--- a/doomsday/tools/shell/shell-gui/src/guishellapp.h
+++ b/doomsday/tools/shell/shell-gui/src/guishellapp.h
@@ -48,6 +48,8 @@ public slots:
void stopServer();
void updateLocalServerMenu();
void aboutShell();
+ void showPreferences();
+ void preferencesDone();
void updateMenu();
protected slots:
diff --git a/doomsday/tools/shell/shell-gui/src/linkwindow.cpp b/doomsday/tools/shell/shell-gui/src/linkwindow.cpp
index 50b09ec688..60cbe75cfd 100644
--- a/doomsday/tools/shell/shell-gui/src/linkwindow.cpp
+++ b/doomsday/tools/shell/shell-gui/src/linkwindow.cpp
@@ -149,6 +149,7 @@ LinkWindow::LinkWindow(QWidget *parent)
#ifndef MACOSX
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ fileMenu->addAction(tr("&Settings..."), app, SLOT(showPreferences()));
fileMenu->addAction(tr("&Quit"), app, SLOT(quit()), QKeySequence(tr("Ctrl+Q")));
// Menus are window-specific on non-Mac platforms.
@@ -201,9 +202,13 @@ LinkWindow::LinkWindow(QWidget *parent)
statusBar()->addPermanentWidget(d->currentHost);
statusBar()->addPermanentWidget(d->timeCounter);
+ QIcon icon(":/images/toolbar_placeholder.png");
+
QToolBar *tools = addToolBar(tr("View"));
d->statusButton = new QToolButton;
+ d->statusButton->setIcon(icon);
+ //d->statusButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
d->statusButton->setFocusPolicy(Qt::NoFocus);
d->statusButton->setText(tr("Status"));
d->statusButton->setCheckable(true);
@@ -212,6 +217,8 @@ LinkWindow::LinkWindow(QWidget *parent)
tools->addWidget(d->statusButton);
d->consoleButton = new QToolButton;
+ d->consoleButton->setIcon(icon);
+ //d->consoleButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
d->consoleButton->setFocusPolicy(Qt::NoFocus);
d->consoleButton->setText(tr("Console"));
d->consoleButton->setCheckable(true);
@@ -264,7 +271,7 @@ void LinkWindow::closeEvent(QCloseEvent *event)
if(QMessageBox::question(
this,
tr("Close Connection?"),
- tr("Connection is still open. Do you want to close it?"),
+ tr("Connection is still open. Do you want to close the window regardless?"),
QMessageBox::Close | QMessageBox::Cancel) == QMessageBox::Cancel)
{
event->ignore();
diff --git a/doomsday/tools/shell/shell-gui/src/localserverdialog.cpp b/doomsday/tools/shell/shell-gui/src/localserverdialog.cpp
index d3ddc2acc1..dab98c3bd8 100644
--- a/doomsday/tools/shell/shell-gui/src/localserverdialog.cpp
+++ b/doomsday/tools/shell/shell-gui/src/localserverdialog.cpp
@@ -17,6 +17,7 @@
*/
#include "localserverdialog.h"
+#include "folderselection.h"
#include
#include
#include
@@ -28,6 +29,7 @@
#include
#include
#include
+#include "preferences.h"
using namespace de;
using namespace de::shell;
@@ -38,8 +40,7 @@ DENG2_PIMPL(LocalServerDialog)
QComboBox *games;
QLineEdit *port;
QLineEdit *options;
- QLineEdit *folder;
- QLineEdit *iwadFolder;
+ FolderSelection *runtime;
Instance(Public &i) : Base(i)
{
@@ -68,33 +69,14 @@ DENG2_PIMPL(LocalServerDialog)
port->setToolTip(tr("Port must be between 0 and 65535."));
form->addRow(tr("TCP port:"), port);
- folder = new QLineEdit;
- folder->setMinimumWidth(300);
- folder->setText(st.value("LocalServer/runtime").toString());
- if(folder->text().isEmpty())
+ runtime = new FolderSelection(tr("Select Runtime Folder"));
+ runtime->setPath(st.value("LocalServer/runtime").toString());
+ if(runtime->path().isEmpty())
{
- folder->setText(DoomsdayInfo::defaultServerRuntimeFolder().toString());
+ runtime->setPath(DoomsdayInfo::defaultServerRuntimeFolder().toString());
}
- form->addRow(tr("Runtime folder:"), folder);
-
- QPushButton *folderButton = new QPushButton(tr("Select Folder"));
- connect(folderButton, SIGNAL(clicked()), &self, SLOT(pickFolder()));
- form->addRow(0, folderButton);
-#ifdef WIN32
- folderButton->setMaximumWidth(100);
-#endif
-
- iwadFolder = new QLineEdit;
- iwadFolder->setMinimumWidth(300);
- iwadFolder->setText(st.value("LocalServer/iwad").toString());
- form->addRow(tr("IWAD folder:"), iwadFolder);
-
- QPushButton *iwadFolderButton = new QPushButton(tr("Select Folder"));
- connect(iwadFolderButton, SIGNAL(clicked()), &self, SLOT(pickIwadFolder()));
- form->addRow(0, iwadFolderButton);
-#ifdef WIN32
- iwadFolderButton->setMaximumWidth(100);
-#endif
+ form->addRow(tr("Runtime folder:"), runtime);
+ QObject::connect(runtime, SIGNAL(selected()), &self, SLOT(validate()));
options = new QLineEdit;
options->setMinimumWidth(300);
@@ -110,7 +92,6 @@ DENG2_PIMPL(LocalServerDialog)
QObject::connect(no, SIGNAL(clicked()), &self, SLOT(reject()));
QObject::connect(opt, SIGNAL(clicked()), &self, SLOT(configureGameOptions()));
yes->setDefault(true);
- yes->setAutoDefault(true);
}
};
@@ -141,33 +122,20 @@ QString LocalServerDialog::gameMode() const
QStringList LocalServerDialog::additionalOptions() const
{
QStringList opts = d->options->text().split(' ', QString::SkipEmptyParts);
- opts << "-iwad" << d->iwadFolder->text();
- return opts;
-}
-NativePath LocalServerDialog::runtimeFolder() const
-{
- return d->folder->text();
-}
-
-void LocalServerDialog::pickFolder()
-{
- QString dir = QFileDialog::getExistingDirectory(this,
- tr("Select Runtime Folder"),
- d->folder->text());
- if(!dir.isEmpty()) d->folder->setText(dir);
+ Preferences prefs;
+ NativePath iwadPath = prefs.iwadFolder();
+ if(!iwadPath.isEmpty())
+ {
+ opts << "-iwad" << iwadPath.toString();
+ }
- validate();
+ return opts;
}
-void LocalServerDialog::pickIwadFolder()
+NativePath LocalServerDialog::runtimeFolder() const
{
- QString dir = QFileDialog::getExistingDirectory(this,
- tr("Select IWAD Folder"),
- d->iwadFolder->text());
- if(!dir.isEmpty()) d->iwadFolder->setText(dir);
-
- validate();
+ return d->runtime->path();
}
void LocalServerDialog::configureGameOptions()
@@ -179,8 +147,8 @@ void LocalServerDialog::saveState()
QSettings st;
st.setValue("LocalServer/gameMode", d->games->itemData(d->games->currentIndex()).toString());
st.setValue("LocalServer/port", d->port->text().toInt());
- st.setValue("LocalServer/runtime", d->folder->text());
- st.setValue("LocalServer/iwad", d->iwadFolder->text());
+ st.setValue("LocalServer/runtime", d->runtime->path().toString());
+ //st.setValue("LocalServer/iwad", d->iwadFolder->text());
st.setValue("LocalServer/options", d->options->text());
}
@@ -196,9 +164,10 @@ void LocalServerDialog::validate()
isValid = false;
}
- if(d->folder->text().isEmpty()) isValid = false;
+ if(d->runtime->path().isEmpty()) isValid = false;
- if(d->iwadFolder->text().isEmpty()) isValid = false;
+ //if(d->iwadFolder->text().isEmpty()) isValid = false;
d->yes->setEnabled(isValid);
+ if(isValid) d->yes->setDefault(true);
}
diff --git a/doomsday/tools/shell/shell-gui/src/localserverdialog.h b/doomsday/tools/shell/shell-gui/src/localserverdialog.h
index 8815f01558..9cc79e5173 100644
--- a/doomsday/tools/shell/shell-gui/src/localserverdialog.h
+++ b/doomsday/tools/shell/shell-gui/src/localserverdialog.h
@@ -36,8 +36,6 @@ class LocalServerDialog : public QDialog
de::NativePath runtimeFolder() const;
protected slots:
- void pickFolder();
- void pickIwadFolder();
void configureGameOptions();
void saveState();
void validate();
diff --git a/doomsday/tools/shell/shell-gui/src/preferences.cpp b/doomsday/tools/shell/shell-gui/src/preferences.cpp
new file mode 100644
index 0000000000..bb8049f68a
--- /dev/null
+++ b/doomsday/tools/shell/shell-gui/src/preferences.cpp
@@ -0,0 +1,90 @@
+#include "preferences.h"
+#include "folderselection.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+DENG2_PIMPL(Preferences)
+{
+ QCheckBox *useDefaultIwad;
+ FolderSelection *iwadFolder;
+
+ Instance(Public &i) : Base(i)
+ {
+ QSettings st;
+
+ self.setWindowTitle(tr("Preferences"));
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ self.setLayout(mainLayout);
+
+ mainLayout->addStretch(1);
+
+ QGroupBox *group = new QGroupBox(tr("IWAD Folder"));
+ mainLayout->addWidget(group);
+
+ useDefaultIwad = new QCheckBox(tr("Use Doomsday's configured IWAD folder"));
+ useDefaultIwad->setChecked(st.value("Preferences/defaultIwad", true).toBool());
+ useDefaultIwad->setToolTip(tr("Doomsday's IWAD folder can be configured using "
+ "configuration files or environment variables."));
+
+ iwadFolder = new FolderSelection(tr("Select IWAD Folder"));
+ iwadFolder->setPath(st.value("Preferences/iwadFolder").toString());
+
+ QVBoxLayout *bl = new QVBoxLayout;
+ bl->addWidget(useDefaultIwad);
+ bl->addWidget(iwadFolder);
+ group->setLayout(bl);
+
+ mainLayout->addStretch(1);
+
+ // Buttons.
+ QDialogButtonBox *bbox = new QDialogButtonBox;
+ mainLayout->addWidget(bbox);
+ QPushButton *yes = bbox->addButton(tr("&OK"), QDialogButtonBox::YesRole);
+ QPushButton *no = bbox->addButton(tr("&Cancel"), QDialogButtonBox::RejectRole);
+ QPushButton *act = bbox->addButton(tr("&Apply"), QDialogButtonBox::ActionRole);
+ QObject::connect(yes, SIGNAL(clicked()), &self, SLOT(accept()));
+ QObject::connect(no, SIGNAL(clicked()), &self, SLOT(reject()));
+ QObject::connect(act, SIGNAL(clicked()), &self, SLOT(saveState()));
+ yes->setDefault(true);
+ }
+};
+
+Preferences::Preferences(QWidget *parent) :
+ QDialog(parent), d(new Instance(*this))
+{
+ connect(d->useDefaultIwad, SIGNAL(toggled(bool)), this, SLOT(validate()));
+ connect(this, SIGNAL(accepted()), this, SLOT(saveState()));
+ validate();
+}
+
+Preferences::~Preferences()
+{
+ delete d;
+}
+
+de::NativePath Preferences::iwadFolder() const
+{
+ if(!d->useDefaultIwad->isChecked())
+ {
+ return d->iwadFolder->path();
+ }
+ return "";
+}
+
+void Preferences::saveState()
+{
+ QSettings st;
+ st.setValue("Preferences/defaultIwad", d->useDefaultIwad->isChecked());
+ st.setValue("Preferences/iwadFolder", iwadFolder().toString());
+}
+
+void Preferences::validate()
+{
+ d->iwadFolder->setDisabled(d->useDefaultIwad->isChecked());
+}
diff --git a/doomsday/tools/shell/shell-gui/src/preferences.h b/doomsday/tools/shell/shell-gui/src/preferences.h
new file mode 100644
index 0000000000..66c80b8e34
--- /dev/null
+++ b/doomsday/tools/shell/shell-gui/src/preferences.h
@@ -0,0 +1,46 @@
+/** @file preferences.h Widget for user preferences.
+ *
+ * @authors Copyright © 2013 Jaakko Keränen
+ *
+ * @par License
+ * GPL: http://www.gnu.org/licenses/gpl.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. This program is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the GNU
+ * General Public License along with this program; if not, see:
+ * http://www.gnu.org/licenses
+ */
+
+#ifndef PREFERENCES_H
+#define PREFERENCES_H
+
+#include
+#include
+
+class Preferences : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit Preferences(QWidget *parent = 0);
+ ~Preferences();
+
+ de::NativePath iwadFolder() const;
+
+signals:
+
+public slots:
+ void saveState();
+ void validate();
+
+private:
+ struct Instance;
+ Instance *d;
+};
+
+#endif // PREFERENCES_H