mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 20:53:50 +00:00
Added support for the profiles and made creation/editing them more user friendly
This commit is contained in:
parent
a4855186c5
commit
fe9120bcb3
10 changed files with 289 additions and 80 deletions
|
@ -12,6 +12,8 @@ set(LAUNCHER
|
|||
utils/filedialog.cpp
|
||||
utils/naturalsort.cpp
|
||||
utils/lineedit.cpp
|
||||
utils/profilescombobox.cpp
|
||||
utils/textinputdialog.cpp
|
||||
|
||||
launcher.rc
|
||||
)
|
||||
|
@ -26,10 +28,12 @@ set(LAUNCHER_HEADER
|
|||
model/modelitem.hpp
|
||||
model/esm/esmfile.hpp
|
||||
|
||||
utils/combobox.hpp
|
||||
utils/lineedit.hpp
|
||||
utils/filedialog.hpp
|
||||
utils/naturalsort.hpp
|
||||
utils/profilescombobox.hpp
|
||||
utils/textinputdialog.hpp
|
||||
|
||||
)
|
||||
|
||||
# Headers that must be pre-processed
|
||||
|
@ -43,9 +47,10 @@ set(LAUNCHER_HEADER_MOC
|
|||
model/modelitem.hpp
|
||||
model/esm/esmfile.hpp
|
||||
|
||||
utils/combobox.hpp
|
||||
utils/lineedit.hpp
|
||||
utils/filedialog.hpp
|
||||
utils/profilescombobox.hpp
|
||||
utils/textinputdialog.hpp
|
||||
)
|
||||
|
||||
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC})
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
#include "model/datafilesmodel.hpp"
|
||||
#include "model/esm/esmfile.hpp"
|
||||
|
||||
#include "utils/combobox.hpp"
|
||||
#include "utils/profilescombobox.hpp"
|
||||
#include "utils/filedialog.hpp"
|
||||
#include "utils/lineedit.hpp"
|
||||
#include "utils/naturalsort.hpp"
|
||||
#include "utils/textinputdialog.hpp"
|
||||
|
||||
#include "datafilespage.hpp"
|
||||
|
||||
|
@ -139,9 +140,11 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent)
|
|||
// Bottom part with profile options
|
||||
QLabel *profileLabel = new QLabel(tr("Current Profile: "), this);
|
||||
|
||||
mProfilesComboBox = new ComboBox(this);
|
||||
mProfilesComboBox = new ProfilesComboBox(this);
|
||||
mProfilesComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
|
||||
mProfilesComboBox->setInsertPolicy(QComboBox::InsertAtBottom);
|
||||
mProfilesComboBox->setInsertPolicy(QComboBox::NoInsert);
|
||||
mProfilesComboBox->setDuplicatesEnabled(false);
|
||||
mProfilesComboBox->setEditEnabled(false);
|
||||
|
||||
mProfileToolBar = new QToolBar(this);
|
||||
mProfileToolBar->setMovable(false);
|
||||
|
@ -156,16 +159,22 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent)
|
|||
pageLayout->addWidget(splitter);
|
||||
pageLayout->addWidget(mProfileToolBar);
|
||||
|
||||
// Create a dialog for the new profile name input
|
||||
mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this);
|
||||
|
||||
connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString)));
|
||||
|
||||
connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
||||
connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
||||
|
||||
connect(mMastersModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mPluginsModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList)));
|
||||
|
||||
connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(const QString)));
|
||||
connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
|
||||
|
||||
connect(mPluginsTable, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&)));
|
||||
connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
||||
|
||||
connect(mProfilesComboBox, SIGNAL(textChanged(const QString&, const QString&)), this, SLOT(profileChanged(const QString&, const QString&)));
|
||||
connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString)));
|
||||
connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString)));
|
||||
|
||||
createActions();
|
||||
setupConfig();
|
||||
|
@ -230,12 +239,21 @@ void DataFilesPage::setupConfig()
|
|||
mLauncherConfig->beginGroup("Profiles");
|
||||
QStringList profiles = mLauncherConfig->childGroups();
|
||||
|
||||
if (profiles.isEmpty()) {
|
||||
// Add a default profile
|
||||
profiles.append("Default");
|
||||
// Add the profiles to the combobox
|
||||
foreach (const QString &profile, profiles) {
|
||||
|
||||
if (profile.contains(QRegExp("[^a-zA-Z0-9_]")))
|
||||
continue; // Profile name contains garbage
|
||||
|
||||
|
||||
qDebug() << "adding " << profile;
|
||||
mProfilesComboBox->addItem(profile);
|
||||
}
|
||||
|
||||
mProfilesComboBox->addItems(profiles);
|
||||
// Add a default profile
|
||||
if (mProfilesComboBox->count() == 0) {
|
||||
mProfilesComboBox->addItem(QString("Default"));
|
||||
}
|
||||
|
||||
QString currentProfile = mLauncherConfig->value("CurrentProfile").toString();
|
||||
|
||||
|
@ -572,33 +590,37 @@ void DataFilesPage::writeConfig(QString profile)
|
|||
|
||||
void DataFilesPage::newProfile()
|
||||
{
|
||||
bool ok;
|
||||
QString text = QInputDialog::getText(this, tr("New Profile"),
|
||||
tr("Profile Name:"), QLineEdit::Normal,
|
||||
tr("New Profile"), &ok);
|
||||
if (ok && !text.isEmpty()) {
|
||||
if (mProfilesComboBox->findText(text) != -1) {
|
||||
QMessageBox::warning(this, tr("Profile already exists"),
|
||||
tr("the profile <b>%0</b> already exists.").arg(text),
|
||||
QMessageBox::Ok);
|
||||
} else {
|
||||
// Add the new profile to the combobox
|
||||
if (mNewProfileDialog->exec() == QDialog::Accepted) {
|
||||
|
||||
const QString text = mNewProfileDialog->lineEdit()->text();
|
||||
mProfilesComboBox->addItem(text);
|
||||
|
||||
// Copy the currently checked items to cfg
|
||||
writeConfig(text);
|
||||
mLauncherConfig->sync();
|
||||
|
||||
mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(text));
|
||||
}
|
||||
}
|
||||
|
||||
void DataFilesPage::updateOkButton(const QString &text)
|
||||
{
|
||||
if (text.isEmpty()) {
|
||||
mNewProfileDialog->setOkButtonEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
(mProfilesComboBox->findText(text) == -1)
|
||||
? mNewProfileDialog->setOkButtonEnabled(true)
|
||||
: mNewProfileDialog->setOkButtonEnabled(false);
|
||||
}
|
||||
|
||||
void DataFilesPage::deleteProfile()
|
||||
{
|
||||
QString profile = mProfilesComboBox->currentText();
|
||||
|
||||
|
||||
if (profile.isEmpty()) {
|
||||
if (profile.isEmpty())
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setWindowTitle(tr("Delete Profile"));
|
||||
|
@ -694,19 +716,17 @@ void DataFilesPage::setCheckState(QModelIndex index)
|
|||
return;
|
||||
|
||||
if (object->objectName() == QLatin1String("PluginsTable")) {
|
||||
if (mPluginsModel->checkState(index) == Qt::Checked) {
|
||||
mPluginsModel->setCheckState(index, Qt::Unchecked);
|
||||
} else {
|
||||
mPluginsModel->setCheckState(index, Qt::Checked);
|
||||
}
|
||||
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(index);
|
||||
|
||||
(mPluginsModel->checkState(sourceIndex) == Qt::Checked)
|
||||
? mPluginsModel->setCheckState(index, Qt::Unchecked)
|
||||
: mPluginsModel->setCheckState(index, Qt::Checked);
|
||||
}
|
||||
|
||||
if (object->objectName() == QLatin1String("MastersTable")) {
|
||||
if (mMastersModel->checkState(index) == Qt::Checked) {
|
||||
mMastersModel->setCheckState(index, Qt::Unchecked);
|
||||
} else {
|
||||
mMastersModel->setCheckState(index, Qt::Checked);
|
||||
}
|
||||
(mMastersModel->checkState(index) == Qt::Checked)
|
||||
? mMastersModel->setCheckState(index, Qt::Unchecked)
|
||||
: mMastersModel->setCheckState(index, Qt::Checked);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -721,13 +741,23 @@ void DataFilesPage::filterChanged(const QString filter)
|
|||
|
||||
void DataFilesPage::profileChanged(const QString &previous, const QString ¤t)
|
||||
{
|
||||
qDebug() << "Profile is changed from: " << previous << " to " << current;
|
||||
// Prevent the deletion of the default profile
|
||||
(current == QLatin1String("Default")) ? mDeleteProfileAction->setEnabled(false)
|
||||
: mDeleteProfileAction->setEnabled(true);
|
||||
if (current == QLatin1String("Default")) {
|
||||
mDeleteProfileAction->setEnabled(false);
|
||||
mProfilesComboBox->setEditEnabled(false);
|
||||
} else {
|
||||
mDeleteProfileAction->setEnabled(true);
|
||||
mProfilesComboBox->setEditEnabled(true);
|
||||
}
|
||||
|
||||
if (!previous.isEmpty()) {
|
||||
writeConfig(previous);
|
||||
mLauncherConfig->sync();
|
||||
|
||||
if (mProfilesComboBox->currentIndex() == -1)
|
||||
return;
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -737,6 +767,36 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre
|
|||
readConfig();
|
||||
}
|
||||
|
||||
void DataFilesPage::profileRenamed(const QString &previous, const QString ¤t)
|
||||
{
|
||||
if (previous.isEmpty())
|
||||
return;
|
||||
|
||||
// Save the new profile name
|
||||
writeConfig(current);
|
||||
|
||||
// Make sure we have no groups open
|
||||
while (!mLauncherConfig->group().isEmpty()) {
|
||||
mLauncherConfig->endGroup();
|
||||
}
|
||||
|
||||
mLauncherConfig->beginGroup("Profiles");
|
||||
|
||||
// Open the profile-name subgroup
|
||||
mLauncherConfig->beginGroup(previous);
|
||||
mLauncherConfig->remove(""); // Clear the subgroup
|
||||
mLauncherConfig->endGroup();
|
||||
mLauncherConfig->endGroup();
|
||||
mLauncherConfig->sync();
|
||||
|
||||
// Remove the profile from the combobox
|
||||
mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous));
|
||||
|
||||
mMastersModel->uncheckAll();
|
||||
mPluginsModel->uncheckAll();
|
||||
readConfig();
|
||||
}
|
||||
|
||||
void DataFilesPage::showContextMenu(const QPoint &point)
|
||||
{
|
||||
// Make sure there are plugins in the view
|
||||
|
@ -756,11 +816,9 @@ void DataFilesPage::showContextMenu(const QPoint &point)
|
|||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (mPluginsModel->checkState(index) == Qt::Checked) {
|
||||
mUncheckAction->setEnabled(true);
|
||||
} else {
|
||||
mCheckAction->setEnabled(true);
|
||||
}
|
||||
(mPluginsModel->checkState(index) == Qt::Checked)
|
||||
? mUncheckAction->setEnabled(true)
|
||||
: mCheckAction->setEnabled(true);
|
||||
}
|
||||
|
||||
// Show menu
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <QWidget>
|
||||
#include <QModelIndex>
|
||||
|
||||
#include "utils/profilescombobox.hpp"
|
||||
#include <components/files/collections.hpp>
|
||||
|
||||
|
||||
|
@ -13,9 +13,10 @@ class QSettings;
|
|||
class QAction;
|
||||
class QToolBar;
|
||||
class QMenu;
|
||||
class ComboBox;
|
||||
class ProfilesComboBox;
|
||||
class DataFilesModel;
|
||||
|
||||
class TextInputDialog;
|
||||
|
||||
namespace Files { struct ConfigurationManager; }
|
||||
|
||||
|
@ -26,7 +27,7 @@ class DataFilesPage : public QWidget
|
|||
public:
|
||||
DataFilesPage(Files::ConfigurationManager& cfg, QWidget *parent = 0);
|
||||
|
||||
ComboBox *mProfilesComboBox;
|
||||
ProfilesComboBox *mProfilesComboBox;
|
||||
|
||||
void writeConfig(QString profile = QString());
|
||||
bool setupDataFiles();
|
||||
|
@ -37,6 +38,8 @@ public slots:
|
|||
void filterChanged(const QString filter);
|
||||
void showContextMenu(const QPoint &point);
|
||||
void profileChanged(const QString &previous, const QString ¤t);
|
||||
void profileRenamed(const QString &previous, const QString ¤t);
|
||||
void updateOkButton(const QString &text);
|
||||
|
||||
// Action slots
|
||||
void newProfile();
|
||||
|
@ -77,6 +80,8 @@ private:
|
|||
|
||||
QSettings *mLauncherConfig;
|
||||
|
||||
TextInputDialog *mNewProfileDialog;
|
||||
|
||||
// const QStringList checkedPlugins();
|
||||
// const QStringList selectedMasters();
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ int main(int argc, char *argv[])
|
|||
// Now we make sure the current dir is set to application path
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
#ifdef Q_OS_MAC
|
||||
if (dir.dirName() == "MacOS") {
|
||||
dir.cdUp();
|
||||
dir.cdUp();
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include <QtGui>
|
||||
|
||||
#include "utils/combobox.hpp"
|
||||
|
||||
#include "maindialog.hpp"
|
||||
#include "playpage.hpp"
|
||||
#include "graphicspage.hpp"
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef COMBOBOX_H
|
||||
#define COMBOBOX_H
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
class ComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QString oldText;
|
||||
public:
|
||||
ComboBox(QWidget *parent=0) : QComboBox(parent), oldText()
|
||||
{
|
||||
connect(this,SIGNAL(editTextChanged(const QString&)), this,
|
||||
SLOT(textChangedSlot(const QString&)));
|
||||
connect(this,SIGNAL(currentIndexChanged(const QString&)), this,
|
||||
SLOT(textChangedSlot(const QString&)));
|
||||
}
|
||||
private slots:
|
||||
void textChangedSlot(const QString &newText)
|
||||
{
|
||||
emit textChanged(oldText, newText);
|
||||
oldText = newText;
|
||||
}
|
||||
signals:
|
||||
void textChanged(const QString &oldText, const QString &newText);
|
||||
};
|
||||
#endif
|
52
apps/launcher/utils/profilescombobox.cpp
Normal file
52
apps/launcher/utils/profilescombobox.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include <QRegExpValidator>
|
||||
#include <QLineEdit>
|
||||
#include <QString>
|
||||
|
||||
#include "profilescombobox.hpp"
|
||||
|
||||
ProfilesComboBox::ProfilesComboBox(QWidget *parent) :
|
||||
QComboBox(parent)
|
||||
{
|
||||
mValidator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
|
||||
|
||||
setEditable(true);
|
||||
setValidator(mValidator);
|
||||
setCompleter(0);
|
||||
|
||||
connect(this, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(slotIndexChanged(int)));
|
||||
connect(lineEdit(), SIGNAL(returnPressed()), this,
|
||||
SLOT(slotReturnPressed()));
|
||||
}
|
||||
|
||||
void ProfilesComboBox::setEditEnabled(bool editable)
|
||||
{
|
||||
if (!editable)
|
||||
return setEditable(false);
|
||||
|
||||
// Reset the completer and validator
|
||||
setEditable(true);
|
||||
setValidator(mValidator);
|
||||
setCompleter(0);
|
||||
}
|
||||
|
||||
void ProfilesComboBox::slotReturnPressed()
|
||||
{
|
||||
QString current = currentText();
|
||||
QString previous = itemText(currentIndex());
|
||||
|
||||
if (findText(current) != -1)
|
||||
return;
|
||||
|
||||
setItemText(currentIndex(), current);
|
||||
emit(profileRenamed(previous, current));
|
||||
}
|
||||
|
||||
void ProfilesComboBox::slotIndexChanged(int index)
|
||||
{
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
emit(profileChanged(mOldProfile, currentText()));
|
||||
mOldProfile = itemText(index);
|
||||
}
|
30
apps/launcher/utils/profilescombobox.hpp
Normal file
30
apps/launcher/utils/profilescombobox.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef PROFILESCOMBOBOX_HPP
|
||||
#define PROFILESCOMBOBOX_HPP
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
class QString;
|
||||
|
||||
class QRegExpValidator;
|
||||
|
||||
class ProfilesComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ProfilesComboBox(QWidget *parent = 0);
|
||||
void setEditEnabled(bool editable);
|
||||
|
||||
signals:
|
||||
void profileChanged(const QString &previous, const QString ¤t);
|
||||
void profileRenamed(const QString &oldName, const QString &newName);
|
||||
|
||||
private slots:
|
||||
void slotReturnPressed();
|
||||
void slotIndexChanged(int index);
|
||||
|
||||
private:
|
||||
QString mOldProfile;
|
||||
QRegExpValidator *mValidator;
|
||||
};
|
||||
|
||||
#endif // PROFILESCOMBOBOX_HPP
|
61
apps/launcher/utils/textinputdialog.cpp
Normal file
61
apps/launcher/utils/textinputdialog.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QValidator>
|
||||
|
||||
#include "lineedit.hpp"
|
||||
|
||||
#include "textinputdialog.hpp"
|
||||
|
||||
TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
mButtonBox = new QDialogButtonBox(this);
|
||||
mButtonBox->addButton(QDialogButtonBox::Ok);
|
||||
mButtonBox->addButton(QDialogButtonBox::Cancel);
|
||||
|
||||
setMaximumHeight(height());
|
||||
setOkButtonEnabled(false);
|
||||
setModal(true);
|
||||
|
||||
// Messageboxes on mac have no title
|
||||
#ifndef Q_OS_MAC
|
||||
setWindowTitle(title);
|
||||
#else
|
||||
Q_UNUSED(title);
|
||||
#endif
|
||||
|
||||
QLabel *label = new QLabel(this);
|
||||
label->setText(text);
|
||||
|
||||
// Line edit
|
||||
QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
|
||||
mLineEdit = new LineEdit(this);
|
||||
mLineEdit->setValidator(validator);
|
||||
mLineEdit->setCompleter(0);
|
||||
|
||||
QVBoxLayout *dialogLayout = new QVBoxLayout(this);
|
||||
dialogLayout->addWidget(label);
|
||||
dialogLayout->addWidget(mLineEdit);
|
||||
dialogLayout->addWidget(mButtonBox);
|
||||
|
||||
connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
int TextInputDialog::exec()
|
||||
{
|
||||
mLineEdit->clear();
|
||||
mLineEdit->setFocus();
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void TextInputDialog::setOkButtonEnabled(bool enabled)
|
||||
{
|
||||
|
||||
QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok);
|
||||
okButton->setEnabled(enabled);
|
||||
}
|
28
apps/launcher/utils/textinputdialog.hpp
Normal file
28
apps/launcher/utils/textinputdialog.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef TEXTINPUTDIALOG_HPP
|
||||
#define TEXTINPUTDIALOG_HPP
|
||||
|
||||
#include <QDialog>
|
||||
//#include "lineedit.hpp"
|
||||
|
||||
class QDialogButtonBox;
|
||||
class LineEdit;
|
||||
|
||||
class TextInputDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TextInputDialog(const QString& title, const QString &text, QWidget *parent = 0);
|
||||
inline LineEdit *lineEdit() { return mLineEdit; }
|
||||
void setOkButtonEnabled(bool enabled);
|
||||
|
||||
LineEdit *mLineEdit;
|
||||
|
||||
int exec();
|
||||
|
||||
private:
|
||||
QDialogButtonBox *mButtonBox;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // TEXTINPUTDIALOG_HPP
|
Loading…
Reference in a new issue