cliParser->addOption("configdir <path>", 'c', "Specify the directory holding configuration files, the SQlite database and the SSL Cert");
cliParser->addOption("datadir <path>", 0, "DEPRECATED - Use --configdir instead");
cliParser->addOption("migrate-backend <backendidentifier>", 0, "Starts an interactive session and attempts to migrate your current storage backend to the new one");
- cliParser->addOption("switch-backend <backendidentifier>", 0, "Starts an interactive session and switches your current storage backend to the new one. No migration will be done!");
+ cliParser->addOption("select-backend <backendidentifier>", 0, "Starts an interactive session and switches your current storage backend to the new one. No migration will be done!");
#endif
#ifdef HAVE_KDE
}
void Core::init() {
- if(Quassel::isOptionSet("switch-backend")) {
- switchBackend(Quassel::optionValue("switch-backend"));
+ if(Quassel::isOptionSet("select-backend")) {
+ switchBackend(Quassel::optionValue("select-backend"));
exit(0);
}
if(!_configured) {
if(!_storageBackends.count()) {
qWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting..."));
- qWarning() << qPrintable(tr("Currently, Quassel only supports SQLite3. You need to build your\n"
- "Qt library with the sqlite plugin enabled in order for quasselcore\n"
+ qWarning() << qPrintable(tr("Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n"
+ "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n"
"to work."));
exit(1); // TODO make this less brutal (especially for mono client -> popup)
}
QVariantMap v;
v["DisplayName"] = backend->displayName();
v["Description"] = backend->description();
- v["ConnectionProperties"] = backend->setupKeys();
- qDebug() << backend->setupKeys();
+ v["SetupKeys"] = backend->setupKeys();
+ v["SetupDefaults"] = backend->setupDefaults();
backends.append(v);
}
reply["StorageBackends"] = backends;
}
Storage *storage = _storageBackends[backend];
- QVariantMap settings = promptForSettings(storage->setupKeys());
+ QVariantMap settings = promptForSettings(storage);
Storage::State storageState = storage->init(settings);
switch(storageState) {
}
Storage *storage = _storageBackends[backend];
- QVariantMap settings = promptForSettings(storage->setupKeys());
+ QVariantMap settings = promptForSettings(storage);
bool ok = initStorage(backend, settings, true /* initial setup is allowed */);
if(ok) {
CoreSettings().setStorageSettings(dbsettings);
}
-QVariantMap Core::promptForSettings(const QVariantMap &map) {
+QVariantMap Core::promptForSettings(const Storage *storage) {
QVariantMap settings;
- if(map.isEmpty())
+
+ QStringList keys = storage->setupKeys();
+ if(keys.isEmpty())
return settings;
QTextStream out(stdout);
QTextStream in(stdin);
out << "!!!Warning: echo mode is always on even if asked for a password!!!" << endl;
+ out << "Default values are in brackets" << endl;
- QVariantMap::const_iterator iter;
+ QVariantMap defaults = storage->setupDefaults();
QString value;
- for(iter = map.constBegin(); iter != map.constEnd(); iter++) {
- out << iter.key() << " (" << iter.value().toString() << "): ";
+ foreach(QString key, keys) {
+ QVariant val;
+ if(defaults.contains(key)) {
+ val = defaults[key];
+ }
+ out << key;
+ if(!val.toString().isEmpty()) {
+ out << " (" << val.toString() << ")";
+ }
+ out << ": ";
out.flush();
- value = in.readLine();
+ value = in.readLine().trimmed();
- if(value.isEmpty()) {
- settings[iter.key()] = iter.value();
- } else {
- value = value.trimmed();
- QVariant val;
- switch(iter.value().type()) {
+ if(!value.isEmpty()) {
+ switch(defaults[key].type()) {
case QVariant::Int:
val = QVariant(value.toInt());
break;
default:
val = QVariant(value);
}
- settings[iter.key()] = val;
}
+ settings[key] = val;
}
return settings;
}
bool migrateBackend(const QString &backend);
bool switchBackend(const QString &backend);
void saveBackendSettings(const QString &backend, const QVariantMap &settings);
- QVariantMap promptForSettings(const QVariantMap &map);
+ QVariantMap promptForSettings(const Storage *storage);
QHash<UserId, SessionThread *> sessions;
Storage *_storage;
return tr("PostgreSQL Turbo Bomber HD!");
}
-QVariantMap PostgreSqlStorage::setupKeys() const {
+QStringList PostgreSqlStorage::setupKeys() const {
+ QStringList keys;
+ keys << "Username"
+ << "Password"
+ << "Hostname"
+ << "Port"
+ << "Database";
+ return keys;
+}
+QVariantMap PostgreSqlStorage::setupDefaults() const {
QVariantMap map;
map["Username"] = QVariant(QString("quassel"));
- map["Password"] = QVariant(QString());
map["Hostname"] = QVariant(QString("localhost"));
map["Port"] = QVariant(5432);
map["Database"] = QVariant(QString("quassel"));
virtual bool isAvailable() const;
virtual QString displayName() const;
virtual QString description() const;
- virtual QVariantMap setupKeys() const;
+ virtual QStringList setupKeys() const;
+ virtual QVariantMap setupDefaults() const;
virtual bool setup(const QVariantMap &settings = QVariantMap());
// TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc
bool isAvailable() const;
QString displayName() const;
- inline QVariantMap setupKeys() const { return QVariantMap(); }
+ virtual inline QStringList setupKeys() const { return QStringList(); }
+ virtual inline QVariantMap setupDefaults() const { return QVariantMap(); }
QString description() const;
// TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc
/** \return A string that can be displayed by the client to describe the storage backend */
virtual QString description() const = 0;
- //! Returns a map where the keys are required properties to use the storage backend
+ //! Returns a list of properties required to use the storage backend
+ virtual QStringList setupKeys() const = 0;
+
+ //! Returns a map where the keys are are properties to use the storage backend
/* the values are QVariants with default values */
- virtual QVariantMap setupKeys() const = 0;
+ virtual QVariantMap setupDefaults() const = 0;
+
//! Setup the storage provider.
/** This prepares the storage provider (e.g. create tables, etc.) for use within Quassel.
virtual bool setup(const QVariantMap &settings = QVariantMap()) = 0;
//! Initialize the storage provider
- /** \param settings Hostname, port, username, password, ...
+ /** \param settings Hostname, port, username, password, ...
* \return the State the storage backend is now in (see Storage::State)
*/
virtual State init(const QVariantMap &settings = QVariantMap()) = 0;
* \param data The Value
*/
virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data) = 0;
-
+
//! Retrieve a persistent user setting
/**
* \param userId The users Id
virtual bool updateIdentity(UserId user, const CoreIdentity &identity) = 0;
virtual void removeIdentity(UserId user, IdentityId identityId) = 0;
virtual QList<CoreIdentity> identities(UserId user) = 0;
-
+
/* Network handling */
//! Create a new Network in the storage backend and return it unique Id
* \return QList<NetworkInfo>.
*/
virtual QList<NetworkInfo> networks(UserId user) = 0;
-
+
//! Get a list of Networks to restore
/** Return a list of networks the user was connected at the time of core shutdown
* \note This method is threadsafe.
*/
virtual QHash<BufferId, MsgId> bufferLastSeenMsgIds(UserId user) = 0;
-
+
/* Message handling */
//! Store a Message in the storage backend and set its unique Id.
/*** Storage Selection Page ***/
-StorageSelectionPage::StorageSelectionPage(const QHash<QString, QVariant> &backends, QWidget *parent) : QWizardPage(parent) {
+StorageSelectionPage::StorageSelectionPage(const QHash<QString, QVariant> &backends, QWidget *parent)
+ : QWizardPage(parent),
+ _connectionBox(0),
+ _backends(backends)
+{
ui.setupUi(this);
- _backends = backends;
setTitle(tr("Select Storage Backend"));
setSubTitle(tr("Please select a database backend for the Quassel Core storage to store the backlog and other data in."));
QVariantMap StorageSelectionPage::connectionProperties() const {
QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
- QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap();
- if(!properties.isEmpty() && _connectionBox) {
- QVariantMap::iterator propertyIter = properties.begin();
- while(propertyIter != properties.constEnd()) {
- QWidget *widget = _connectionBox->findChild<QWidget *>(propertyIter.key());
- switch(propertyIter.value().type()) {
+
+ QVariantMap properties;
+ QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList();
+ if(!setupKeys.isEmpty()) {
+ QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap();
+ foreach(QString key, setupKeys) {
+ QWidget *widget = _connectionBox->findChild<QWidget *>(key);
+ QVariant def;
+ if(defaults.contains(key)) {
+ def = defaults[key];
+ }
+ switch(def.type()) {
case QVariant::Int:
{
QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget);
Q_ASSERT(spinbox);
- propertyIter.value() = QVariant(spinbox->value());
+ def = QVariant(spinbox->value());
}
break;
default:
{
QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
Q_ASSERT(lineEdit);
- propertyIter.value() = QVariant(lineEdit->text());
+ def = QVariant(lineEdit->text());
}
}
- propertyIter++;
+ properties[key] = def;
}
}
+ qDebug() << properties;
+
+
+// QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap();
+// if(!properties.isEmpty() && _connectionBox) {
+// QVariantMap::iterator propertyIter = properties.begin();
+// while(propertyIter != properties.constEnd()) {
+// QWidget *widget = _connectionBox->findChild<QWidget *>(propertyIter.key());
+// switch(propertyIter.value().type()) {
+// case QVariant::Int:
+// {
+// QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget);
+// Q_ASSERT(spinbox);
+// propertyIter.value() = QVariant(spinbox->value());
+// }
+// break;
+// default:
+// {
+// QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
+// Q_ASSERT(lineEdit);
+// propertyIter.value() = QVariant(lineEdit->text());
+// }
+// }
+// propertyIter++;
+// }
+// }
return properties;
}
_connectionBox = 0;
}
- QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap();
- if(!properties.isEmpty()) {
+ QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList();
+ if(!setupKeys.isEmpty()) {
+ QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap();
QGroupBox *propertyBox = new QGroupBox(this);
propertyBox->setTitle(tr("Connection Properties"));
QFormLayout *formlayout = new QFormLayout;
- QVariantMap::const_iterator propertyIter = properties.constBegin();
- while(propertyIter != properties.constEnd()) {
+ foreach(QString key, setupKeys) {
QWidget *widget = 0;
- switch(propertyIter.value().type()) {
+ QVariant def;
+ if(defaults.contains(key)) {
+ def = defaults[key];
+ }
+ switch(def.type()) {
case QVariant::Int:
{
QSpinBox *spinbox = new QSpinBox(propertyBox);
spinbox->setMaximum(64000);
- spinbox->setValue(propertyIter.value().toInt());
+ spinbox->setValue(def.toInt());
widget = spinbox;
}
break;
default:
- widget = new QLineEdit(propertyIter.value().toString(), propertyBox);
+ {
+ QLineEdit *lineEdit = new QLineEdit(def.toString(), propertyBox);
+ if(key.toLower().contains("password")) {
+ lineEdit->setEchoMode(QLineEdit::Password);
+ }
+ widget = lineEdit;
+ }
}
- widget->setObjectName(propertyIter.key());
- formlayout->addRow(propertyIter.key() + ":", widget);
- propertyIter++;
+ widget->setObjectName(key);
+ formlayout->addRow(key + ":", widget);
}
propertyBox->setLayout(formlayout);
static_cast<QVBoxLayout *>(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, propertyBox);