mirror of
https://github.com/mumble-voip/mumble.git
synced 2025-10-26 11:19:16 +00:00
FEAT(client): Allow specifying config file via commandline switch
This adds the switch -c/--config to the mumble client. If -c is followed by a filename, this file will be read instead of the standard config. A new config option database= has been added to the 'General' section of the ini file. This can be used to specify a different database which is necessary to run multiple completely separate Mumble instances at the same time. Additionaly the (undocumented) function to merge another ini file by providing it as a parameter has been removed as it was conflicting with the added functionality. FIXES #3953
This commit is contained in:
parent
3a07016b8f
commit
4edae462fa
@ -40,11 +40,10 @@ static bool execQueryAndLogFailure(QSqlQuery &query, const QString &queryString)
|
||||
}
|
||||
|
||||
|
||||
Database::Database(const QString &dbname) {
|
||||
db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbname);
|
||||
bool Database::findOrCreateDatabase()
|
||||
{
|
||||
QSettings qs;
|
||||
QStringList datapaths;
|
||||
int i;
|
||||
|
||||
datapaths << g.qdBasePath.absolutePath();
|
||||
datapaths << QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
@ -55,42 +54,65 @@ Database::Database(const QString &dbname) {
|
||||
datapaths << QDir::currentPath();
|
||||
datapaths << qApp->applicationDirPath();
|
||||
datapaths << qs.value(QLatin1String("InstPath")).toString();
|
||||
bool found = false;
|
||||
datapaths.removeAll(QLatin1String(""));
|
||||
datapaths.removeDuplicates();
|
||||
|
||||
for (i = 0; (i < datapaths.size()) && ! found; i++) {
|
||||
if (!datapaths[i].isEmpty()) {
|
||||
// Try the legacy path first, and use it if it exists.
|
||||
// If it doesn't, use the new, non-hidden version.
|
||||
QFile legacyDatabaseFile(datapaths[i] + QLatin1String("/.mumble.sqlite"));
|
||||
if (legacyDatabaseFile.exists()) {
|
||||
db.setDatabaseName(legacyDatabaseFile.fileName());
|
||||
found = db.open();
|
||||
// Try to find an existing database
|
||||
foreach(const QString &datapath, datapaths) {
|
||||
// Try the legacy path first, and use it if it exists.
|
||||
// If it doesn't, use the new, non-hidden version.
|
||||
QFile legacyDatabaseFile(datapath + QLatin1String("/.mumble.sqlite"));
|
||||
if (legacyDatabaseFile.exists()) {
|
||||
db.setDatabaseName(legacyDatabaseFile.fileName());
|
||||
if (db.open()) {
|
||||
return true;
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
QFile databaseFile(datapaths[i] + QLatin1String("/mumble.sqlite"));
|
||||
if (databaseFile.exists()) {
|
||||
db.setDatabaseName(databaseFile.fileName());
|
||||
found = db.open();
|
||||
}
|
||||
QFile databaseFile(datapath + QLatin1String("/mumble.sqlite"));
|
||||
if (databaseFile.exists()) {
|
||||
db.setDatabaseName(databaseFile.fileName());
|
||||
if (db.open()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! found) {
|
||||
for (i = 0; (i < datapaths.size()) && ! found; i++) {
|
||||
if (!datapaths[i].isEmpty()) {
|
||||
QDir::root().mkpath(datapaths[i]);
|
||||
QFile f(datapaths[i] + QLatin1String("/mumble.sqlite"));
|
||||
db.setDatabaseName(f.fileName());
|
||||
found = db.open();
|
||||
// There is no existing database, so we create one
|
||||
foreach(const QString &datapath, datapaths) {
|
||||
QDir::root().mkpath(datapath);
|
||||
QFile f(datapath + QLatin1String("/mumble.sqlite"));
|
||||
db.setDatabaseName(f.fileName());
|
||||
if (db.open()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Database::Database(const QString &dbname) {
|
||||
db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbname);
|
||||
if (!g.s.qsDatabaseLocation.isEmpty()) {
|
||||
QFile configuredLocation(g.s.qsDatabaseLocation);
|
||||
if (configuredLocation.exists()) {
|
||||
db.setDatabaseName(g.s.qsDatabaseLocation);
|
||||
db.open();
|
||||
} else {
|
||||
int result = QMessageBox::critical(nullptr, QLatin1String("Mumble"), tr("The database file '%1' set in the configuration file does not exist. Do you want to create a new database file at this location?").arg(g.s.qsDatabaseLocation), QMessageBox::Yes | QMessageBox::No);
|
||||
if (result == QMessageBox::Yes) {
|
||||
db.setDatabaseName(g.s.qsDatabaseLocation);
|
||||
db.open();
|
||||
} else {
|
||||
qFatal("Database: File not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! found) {
|
||||
QMessageBox::critical(nullptr, QLatin1String("Mumble"), tr("Mumble failed to initialize a database in any\nof the possible locations."), QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
|
||||
qFatal("Database: Failed initialization");
|
||||
if (!db.isOpen()) {
|
||||
if (findOrCreateDatabase()) {
|
||||
g.s.qsDatabaseLocation = db.databaseName();
|
||||
} else {
|
||||
QMessageBox::critical(nullptr, QLatin1String("Mumble"), tr("Mumble failed to initialize a database in any of the possible locations."), QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton);
|
||||
qFatal("Database: Failed initialization");
|
||||
}
|
||||
}
|
||||
|
||||
QFileInfo fi(db.databaseName());
|
||||
|
||||
@ -25,6 +25,10 @@ class Database : public QObject {
|
||||
Q_DISABLE_COPY(Database)
|
||||
|
||||
QSqlDatabase db;
|
||||
/// This function is called when no database location is configured
|
||||
/// in the config file. It tries to find an existing database file and
|
||||
/// creates a new one if none was found.
|
||||
bool findOrCreateDatabase();
|
||||
public:
|
||||
Database(const QString &dbname);
|
||||
~Database() Q_DECL_OVERRIDE;
|
||||
|
||||
@ -65,7 +65,7 @@ static void migrateDataDir() {
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
Global::Global() {
|
||||
Global::Global(const QString &qsConfigPath) {
|
||||
mw = 0;
|
||||
db = 0;
|
||||
p = 0;
|
||||
@ -119,29 +119,37 @@ Global::Global() {
|
||||
bDebugDumpInput = false;
|
||||
bDebugPrintQueue = false;
|
||||
|
||||
QStringList qsl;
|
||||
qsl << QCoreApplication::instance()->applicationDirPath();
|
||||
qsl << QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QString appdata;
|
||||
wchar_t appData[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, appData))) {
|
||||
appdata = QDir::fromNativeSeparators(QString::fromWCharArray(appData));
|
||||
|
||||
if (!appdata.isEmpty()) {
|
||||
appdata.append(QLatin1String("/Mumble"));
|
||||
qsl << appdata;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach(const QString &dir, qsl) {
|
||||
QFile inifile(QString::fromLatin1("%1/mumble.ini").arg(dir));
|
||||
if (inifile.exists() && inifile.permissions().testFlag(QFile::WriteUser)) {
|
||||
qdBasePath.setPath(dir);
|
||||
qs = new QSettings(inifile.fileName(), QSettings::IniFormat);
|
||||
break;
|
||||
if (!qsConfigPath.isEmpty()) {
|
||||
QFile inifile(qsConfigPath);
|
||||
qs = new QSettings(inifile.fileName(), QSettings::IniFormat);
|
||||
} else {
|
||||
QStringList qsl;
|
||||
qsl << QCoreApplication::instance()->applicationDirPath();
|
||||
qsl << QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, appData))) {
|
||||
appdata = QDir::fromNativeSeparators(QString::fromWCharArray(appData));
|
||||
|
||||
if (!appdata.isEmpty()) {
|
||||
appdata.append(QLatin1String("/Mumble"));
|
||||
qsl << appdata;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach(const QString &dir, qsl) {
|
||||
QFile inifile(QString::fromLatin1("%1/mumble.ini").arg(dir));
|
||||
if (inifile.exists() && inifile.permissions().testFlag(QFile::WriteUser)) {
|
||||
qdBasePath.setPath(dir);
|
||||
qs = new QSettings(inifile.fileName(), QSettings::IniFormat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -108,7 +108,7 @@ public:
|
||||
bool bHappyEaster;
|
||||
static const char ccHappyEaster[];
|
||||
|
||||
Global();
|
||||
Global(const QString &qsConfigPath = QString());
|
||||
~Global();
|
||||
};
|
||||
|
||||
|
||||
@ -674,6 +674,8 @@ void Settings::load(QSettings* settings_ptr) {
|
||||
// Config updates
|
||||
SAVELOAD(uiUpdateCounter, "lastupdate");
|
||||
|
||||
SAVELOAD(qsDatabaseLocation, "databaselocation");
|
||||
|
||||
SAVELOAD(bMute, "audio/mute");
|
||||
SAVELOAD(bDeaf, "audio/deaf");
|
||||
LOADENUM(atTransmit, "audio/transmit");
|
||||
@ -1031,6 +1033,8 @@ void Settings::save() {
|
||||
// Config updates
|
||||
SAVELOAD(uiUpdateCounter, "lastupdate");
|
||||
|
||||
SAVELOAD(qsDatabaseLocation, "databaselocation");
|
||||
|
||||
SAVELOAD(bMute, "audio/mute");
|
||||
SAVELOAD(bDeaf, "audio/deaf");
|
||||
SAVELOAD(atTransmit, "audio/transmit");
|
||||
|
||||
@ -430,6 +430,9 @@ struct Settings {
|
||||
// Config updates
|
||||
unsigned int uiUpdateCounter;
|
||||
|
||||
/// Path to SQLite-DB
|
||||
QString qsDatabaseLocation;
|
||||
|
||||
// Nonsaved
|
||||
LoopMode lmLoopMode;
|
||||
float dPacketLoss;
|
||||
|
||||
@ -125,7 +125,26 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
Global::g_global_struct = new Global();
|
||||
// This argument has to be parsed first, since it's value is needed to create the global struct,
|
||||
// which other switches are modifying. If it is parsed first, the order of the arguments does not matter.
|
||||
QStringList args = a.arguments();
|
||||
const int index = std::max(args.lastIndexOf(QLatin1String("-c")), args.lastIndexOf(QLatin1String("--config")));
|
||||
if (index >= 0) {
|
||||
if (index + 1 < args.count()) {
|
||||
QFile inifile(args.at(index + 1));
|
||||
if (inifile.exists() && inifile.permissions().testFlag(QFile::WriteUser)) {
|
||||
Global::g_global_struct = new Global(args.at(index + 1));
|
||||
} else {
|
||||
printf("%s", qPrintable(MainWindow::tr("Configuration file %1 does not exist or is not writable.\n").arg(args.at(index + 1))));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
qCritical("Missing argument for --config!");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
Global::g_global_struct = new Global();
|
||||
}
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
|
||||
// For Qt >= 5.10 we use QRandomNumberGenerator that is seeded automatically
|
||||
@ -143,8 +162,8 @@ int main(int argc, char **argv) {
|
||||
bool bRpcMode = false;
|
||||
QString rpcCommand;
|
||||
QUrl url;
|
||||
|
||||
if (a.arguments().count() > 1) {
|
||||
QStringList args = a.arguments();
|
||||
for (int i = 1; i < args.count(); ++i) {
|
||||
if (args.at(i) == QLatin1String("-h") || args.at(i) == QLatin1String("--help")
|
||||
#if defined(Q_OS_WIN)
|
||||
@ -165,6 +184,10 @@ int main(int argc, char **argv) {
|
||||
" -h, --help Show this help text and exit.\n"
|
||||
" -m, --multiple\n"
|
||||
" Allow multiple instances of the client to be started.\n"
|
||||
" -c, --config\n"
|
||||
" Specify an alternative configuration file.\n"
|
||||
" If you use this to run multiple instances of Mumble at once,\n"
|
||||
" make sure to set an alternative 'database' value in the config.\n"
|
||||
" -n, --noidentity\n"
|
||||
" Suppress loading of identity files (i.e., certificates.)\n"
|
||||
" -jn, --jackname <arg>\n"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user