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