// This file Copyright © Mnemosyne LLC. // It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only), // or any future license endorsed by Mnemosyne LLC. // License text can be found in the licenses/ folder. #include #include #include #include #include #include #include #include #include "Application.h" #include "InteropHelper.h" #include "Prefs.h" using namespace std::string_view_literals; namespace { char const* const DisplayName = "transmission-qt"; auto constexpr FileArgsSeparator = "--"sv; auto constexpr QtArgsSeparator = "---"sv; std::array const Opts = { tr_option{ 'g', "config-dir", "Where to look for configuration files", "g", true, "" }, { 'm', "minimized", "Start minimized in system tray", "m", false, nullptr }, { 'p', "port", "Port to use when connecting to an existing session", "p", true, "" }, { 'r', "remote", "Connect to an existing session at the specified hostname", "r", true, "" }, { 'u', "username", "Username to use when connecting to an existing session", "u", true, "" }, { 'v', "version", "Show version number and exit", "v", false, nullptr }, { 'w', "password", "Password to use when connecting to an existing session", "w", true, "" }, { 0, nullptr, nullptr, nullptr, false, nullptr } }; char const* getUsage() { return "Usage:\n" " transmission-qt [options...] [[--] torrent files...] [--- Qt options...]"; } bool tryDelegate(QStringList const& filenames) { InteropHelper const interop_client; if (!interop_client.isConnected()) { return false; } bool delegated = false; for (auto const& filename : filenames) { auto const add_data = AddData(filename); QString metainfo; switch (add_data.type) { case AddData::URL: metainfo = add_data.url.toString(); break; case AddData::MAGNET: metainfo = add_data.magnet; break; case AddData::FILENAME: case AddData::METAINFO: metainfo = QString::fromUtf8(add_data.toBase64()); break; default: break; } if (!metainfo.isEmpty() && interop_client.addMetainfo(metainfo)) { delegated = true; } } return delegated; } } // namespace int tr_main(int argc, char** argv) { auto const init_mgr = tr_lib_init(); tr_locale_set_global(""); // parse the command-line arguments bool minimized = false; QString host; QString port; QString username; QString password; QString config_dir; QStringList filenames; int opt = 0; char const* optarg = nullptr; int file_args_start_idx = -1; int qt_args_start_idx = -1; while (file_args_start_idx < 0 && qt_args_start_idx < 0 && (opt = tr_getopt(getUsage(), argc, static_cast(argv), std::data(Opts), &optarg)) != TR_OPT_DONE) { switch (opt) { case 'g': config_dir = QString::fromUtf8(optarg); break; case 'p': port = QString::fromUtf8(optarg); break; case 'r': host = QString::fromUtf8(optarg); break; case 'u': username = QString::fromUtf8(optarg); break; case 'w': password = QString::fromUtf8(optarg); break; case 'm': minimized = true; break; case 'v': fmt::print("{:s} {:s}\n", DisplayName, LONG_VERSION_STRING); return 0; case TR_OPT_ERR: fmt::print(stderr, "Invalid option\n"); tr_getopt_usage(DisplayName, getUsage(), std::data(Opts)); return 1; default: if (optarg == FileArgsSeparator) { file_args_start_idx = tr_optind; } else if (optarg == QtArgsSeparator) { qt_args_start_idx = tr_optind; } else { filenames.append(QString::fromUtf8(optarg)); } break; } } if (file_args_start_idx >= 0) { for (int i = file_args_start_idx; i < argc; ++i) { if (argv[i] == QtArgsSeparator) { qt_args_start_idx = i + 1; break; } filenames.push_back(QString::fromUtf8(argv[i])); } } InteropHelper::initialize(); // try to delegate the work to an existing copy of Transmission // before starting ourselves... if (tryDelegate(filenames)) { return 0; } // set the fallback config dir if (config_dir.isNull()) { config_dir = QString::fromStdString(tr_getDefaultConfigDir("transmission")); } // initialize the prefs auto prefs = std::make_unique(config_dir); if (!host.isNull()) { prefs->set(Prefs::SESSION_REMOTE_HOST, host); } if (!port.isNull()) { prefs->set(Prefs::SESSION_REMOTE_PORT, port.toUInt()); } if (!username.isNull()) { prefs->set(Prefs::SESSION_REMOTE_USERNAME, username); } if (!password.isNull()) { prefs->set(Prefs::SESSION_REMOTE_PASSWORD, password); } if (!host.isNull() || !port.isNull() || !username.isNull() || !password.isNull()) { prefs->set(Prefs::SESSION_IS_REMOTE, true); } if (prefs->getBool(Prefs::START_MINIMIZED)) { minimized = true; } // start as minimized only if the system tray present if (!prefs->getBool(Prefs::SHOW_TRAY_ICON)) { minimized = false; } auto qt_argv = std::vector{ argv[0] }; if (qt_args_start_idx >= 0) { qt_argv.insert(qt_argv.end(), &argv[qt_args_start_idx], &argv[argc]); } auto qt_argc = static_cast(std::size(qt_argv)); Application const app(std::move(prefs), minimized, config_dir, filenames, qt_argc, std::data(qt_argv)); return QApplication::exec(); }