/* * This file is part of smolbote. It's copyrighted by the contributors recorded * in the version control history of the file, available from its original * location: git://neueland.iserlohn-fortress.net/smolbote.git * * SPDX-License-Identifier: GPL-3.0 */ #include #include "browser.h" #include #include #include #include #include #include "mainwindow.h" // startup time measuring #ifdef QT_DEBUG #include #endif // read config into std::string, supports qrc inline std::string readConfig(QString path) { QFile conf(path); std::string ret; if(conf.open(QIODevice::ReadOnly)) { ret = conf.readAll().toStdString(); conf.close(); } return ret; } bool writeUserConfig(const std::string &path, Configuration &config) { // set firstRun to false so we don't re-init on every run config.setValue("browser.firstRun", false); // The .path's need to be overriden because ~ doesn't translate to home const QString &home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); // profile.path std::string profilePath = config.value("profile.path").value(); config.setValue("profile.path", patchHome(profilePath, home.toStdString())); // bookmarks.path std::string bookmarksPath = config.value("bookmarks.path").value(); config.setValue("bookmarks.path", patchHome(bookmarksPath, home.toStdString())); // downloads.path std::string downloadsPath = config.value("downloads.path").value(); config.setValue("downloads.path", patchHome(downloadsPath, home.toStdString())); return config.writeUserConfiguration(path); } int main(int argc, char *argv[]) { // Create application object Browser instance(argc, argv); #ifdef GIT_VERSION instance.setApplicationVersion(GIT_VERSION); #else instance.setApplicationVersion("1.0.0"); #endif #ifdef QT_DEBUG QElapsedTimer timer; timer.start(); #endif QCommandLineParser parser; parser.setApplicationDescription("yet another Qt browser"); parser.addHelpOption(); parser.addVersionOption(); // user config, ~/.config/smolbote/smolbote.cfg or empty if there is none QCommandLineOption configOption({"c", "config"}, "Set configuration file.", "path"); configOption.setDefaultValue(QStandardPaths::locate(QStandardPaths::AppConfigLocation, "smolbote.cfg")); parser.addOption(configOption); // default config, :/poi.cfg QCommandLineOption defaultConfigOption("default-config", "Set the default configuration file.", "path"); defaultConfigOption.setDefaultValue(":/poi.cfg"); parser.addOption(defaultConfigOption); // print default config, so users can easily create their overrides QCommandLineOption printDefaultConfigOption("print-default-config", "Print default configuration."); parser.addOption(printDefaultConfigOption); // generate user config QCommandLineOption generateUserConfigOption("generate-user-config", "Generate user configuration and exit."); parser.addOption(generateUserConfigOption); QCommandLineOption profileOption({"p", "profile"}, "Use this profile.", "PROFILE"); profileOption.setDefaultValue(""); parser.addOption(profileOption); QCommandLineOption socketOption("socket", "Set socket to use for IPC, leave blank for default, 'none' to disable.", "name"); socketOption.setDefaultValue(""); parser.addOption(socketOption); QCommandLineOption newWindowOption("in-new-window", "Open URL in new window"); parser.addOption(newWindowOption); parser.addPositionalArgument("URL", "URL(s) to open"); parser.process(instance); #ifdef QT_DEBUG qDebug("config=%s", qUtf8Printable(parser.value(configOption))); qDebug("default-config=%s", qUtf8Printable(parser.value(defaultConfigOption))); #endif if(parser.isSet(printDefaultConfigOption)) { std::cout << readConfig(parser.value(defaultConfigOption)); std::cout.flush(); return 0; } // TODO: check for other instances // if we socket hasn't been disabled (socket is not none) if(parser.value(socketOption) != "none") { bool bindOk = instance.bindLocalSocket(parser.value(socketOption)); if(bindOk) { qDebug("Connected to local socket: %s", qUtf8Printable(instance.serverName())); } else { // pass arguments to new instance return instance.sendMessage(parser.value(profileOption), parser.isSet(newWindowOption), parser.positionalArguments()); } } std::shared_ptr config = std::make_shared(); config->readDefaultConfiguration(readConfig(parser.value(defaultConfigOption))); config->readUserConfiguration(parser.value(configOption).toStdString()); // check if first run if(config->value("browser.firstRun").value() || parser.isSet(generateUserConfigOption)) { // create a user config file QString path = parser.value(configOption); // there may be no smolbote.cfg if(path.isEmpty()) { path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/smolbote.cfg"; } QDir configDir = QFileInfo(path).absoluteDir(); if(!configDir.exists()) { bool mkpathSuccess = configDir.mkpath("."); #ifdef QT_DEBUG qDebug("mkpath %s: %s", qUtf8Printable(configDir.absolutePath()), mkpathSuccess ? "ok" : "failed"); #endif } #ifdef QT_DEBUG qDebug("Generating user config on first run to %s", qUtf8Printable(path)); #endif qDebug("Saving config to: %s - %s", qUtf8Printable(path), writeUserConfig(path.toStdString(), *config) ? "ok" : "failed"); if(parser.isSet(generateUserConfigOption)) { return 0; } } instance.setConfiguration(config); instance.loadProfiles(); instance.createSession(parser.value(profileOption), parser.isSet(newWindowOption), parser.positionalArguments()); #ifdef QT_DEBUG qDebug("Startup complete in %lldms", timer.elapsed()); #endif return instance.exec(); }