/**************************************************************** * This file is distributed under the following license: * * Copyright (c) 2006-2007, crypton * Copyright (c) 2006, Matt Edman, Justin Hipple * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. ****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __APPLE__ #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "rshare.h" /* Available command-line arguments. */ #define ARG_LANGUAGE "lang" /**< Argument specifying language. */ #define ARG_GUISTYLE "style" /**< Argument specfying GUI style. */ #define ARG_GUISTYLESHEET "stylesheet" /**< Argument specfying GUI style. */ #define ARG_RESET "reset" /**< Reset Rshare's saved settings. */ #define ARG_DATADIR "datadir" /**< Directory to use for data files. */ #define ARG_LOGFILE "logfile" /**< Location of our logfile. */ #define ARG_LOGLEVEL "loglevel" /**< Log verbosity. */ #define ARG_RSLINK_S "r" /**< Open RsLink with protocol retroshare:// */ #define ARG_RSLINK_L "link" /**< Open RsLink with protocol retroshare:// */ #define ARG_RSFILE_S "f" /**< Open RsFile with or without arg */ #define ARG_RSFILE_L "rsfile" /**< Open RsFile with or without arg */ //Other defined for server in /libretroshare/src/rsserver/rsinit.cc:351 // The arguments here can be send to a running instance. // If the command line contains arguments not listed here, we have to start a new instance. // For exmample, the user wants to start a second instance using --base-dir arg of libretroshare. static const char* const forwardableArgs[] = { ARG_RSLINK_S, ARG_RSLINK_L, ARG_RSFILE_S, ARG_RSFILE_L, NULL, }; /* Static member variables */ QMap Rshare::_args; /**< List of command-line arguments. */ QString Rshare::_style; /**< The current GUI style. */ QString Rshare::_stylesheet; /**< The current GUI stylesheet. */ QString Rshare::_language; /**< The current language. */ QString Rshare::_dateformat; /**< The format of dates in feed items etc. */ Log Rshare::_log; /**< Logs debugging messages to file or stdout. */ QStringList Rshare::_links; /**< List of links passed by arguments. */ QStringList Rshare::_files; /**< List of files passed by arguments. */ QDateTime Rshare::mStartupTime; bool Rshare::useConfigDir; QString Rshare::configDir; QLocalServer* Rshare::localServer; /** Catches debugging messages from Qt and sends them to RetroShare's logs. If Qt * emits a QtFatalMsg, we will write the message to the log and then abort(). */ #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) void qt_msg_handler(QtMsgType type, const QMessageLogContext &, const QString &msg) #else void qt_msg_handler(QtMsgType type, const char *msg) #endif { switch (type) { case QtDebugMsg: rDebug(QString("QtDebugMsg: %1").arg(msg)); break; case QtWarningMsg: rNotice(QString("QtWarningMsg: %1").arg(msg)); break; case QtCriticalMsg: rWarn(QString("QtCriticalMsg: %1").arg(msg)); break; case QtFatalMsg: rError(QString("QtFatalMsg: %1").arg(msg)); break; #if QT_VERSION >= QT_VERSION_CHECK (5, 5, 0) case QtInfoMsg: break; #endif } if (type == QtFatalMsg) { rError("Fatal Qt error. Aborting."); abort(); } } static bool notifyRunningInstance() { // Connect to the Local Server of the main process to notify it // that a new process had been started QLocalSocket localSocket; localSocket.connectToServer(QString(TARGET)); std::cerr << "Rshare::Rshare waitForConnected to other instance." << std::endl; if( localSocket.waitForConnected(100) ) { std::cerr << "Rshare::Rshare Connection etablished. Waiting for disconnection." << std::endl; localSocket.waitForDisconnected(1000); return true; } else { std::cerr << "Rshare::Rshare failed to connect to other instance." << std::endl; return false; } } /** Constructor. Parses the command-line arguments, resets Rshare's * configuration (if requested), and sets up the GUI style and language * translation. */ Rshare::Rshare(QStringList args, int &argc, char **argv, const QString &dir) : QApplication(argc, argv) { mStartupTime = QDateTime::currentDateTime(); localServer = NULL; //Initialize connection to LocalServer to know if other process runs. { QString serverName = QString(TARGET); // check if another instance is running bool haveRunningInstance = notifyRunningInstance(); bool sendArgsToRunningInstance = haveRunningInstance; if(args.empty()) sendArgsToRunningInstance = false; // if we find non-forwardable args, start a new instance for(int i = 0; i < args.size(); ++i) { const char* const* argit = forwardableArgs; bool found = false; while(*argit && i < args.size()) { if(args.value(i) == "-"+QString(*argit) || args.value(i) == "--"+QString(*argit)) { found = true; if(argNeedsValue(*argit)) i++; } argit++; } if(!found) sendArgsToRunningInstance = false; } if (sendArgsToRunningInstance) { // load into shared memory QBuffer buffer; buffer.open(QBuffer::ReadWrite); QDataStream out(&buffer); out << args; int size = buffer.size(); QSharedMemory newArgs; newArgs.setKey(serverName + "_newArgs"); if (newArgs.isAttached()) newArgs.detach(); if (!newArgs.create(size)) { std::cerr << "(EE) Rshare::Rshare Unable to create shared memory segment of size:" << size << " error:" << newArgs.errorString().toStdString() << "." << std::endl; #ifdef Q_OS_UNIX std::cerr << "Look with `ipcs -m` for nattch==0 segment. And remove it with `ipcrm -m 'shmid'`." << std::endl; //No need for windows, as it removes shared segment directly even when crash. #endif newArgs.detach(); ::exit(EXIT_FAILURE); } newArgs.lock(); char *to = (char*)newArgs.data(); const char *from = buffer.data().data(); memcpy(to, from, qMin(newArgs.size(), size)); newArgs.unlock(); std::cerr << "Rshare::Rshare waitForConnected to other instance." << std::endl; if(notifyRunningInstance()) { newArgs.detach(); std::cerr << "Rshare::Rshare Arguments was sended." << std::endl << " To disable it, in Options - General - Misc," << std::endl << " uncheck \"Use Local Server to get new Arguments\"." << std::endl; ::exit(EXIT_SUCCESS); // Terminate the program using STDLib's exit function } else std::cerr << "Rshare::Rshare failed to connect to other instance." << std::endl; newArgs.detach(); } if(!haveRunningInstance) { // No main process exists // Or started without arguments // So we start a Local Server to listen for connections from new process localServer= new QLocalServer(); QObject::connect(localServer, SIGNAL(newConnection()), this, SLOT(slotConnectionEstablished())); updateLocalServer(); } } #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) qInstallMessageHandler(qt_msg_handler); #else qInstallMsgHandler(qt_msg_handler); #endif #ifndef __APPLE__ /* set default window icon */ setWindowIcon(QIcon(":/icons/logo_128.png")); #endif mBlink = true; QTimer *timer = new QTimer(this); timer->setInterval(500); connect(timer, SIGNAL(timeout()), this, SLOT(blinkTimer())); timer->start(); timer = new QTimer(this); timer->setInterval(60000); connect(timer, SIGNAL(timeout()), this, SIGNAL(minuteTick())); timer->start(); /* Read in all our command-line arguments. */ parseArguments(args); /* Check if we're supposed to reset our config before proceeding. */ if (_args.contains(ARG_RESET)) { Settings->reset(); } /* Handle the -loglevel and -logfile options. */ if (_args.contains(ARG_LOGFILE)) _log.open(_args.value(ARG_LOGFILE)); if (_args.contains(ARG_LOGLEVEL)) { _log.setLogLevel(Log::stringToLogLevel( _args.value(ARG_LOGLEVEL))); if (!_args.contains(ARG_LOGFILE)) _log.open(stdout); } if (!_args.contains(ARG_LOGLEVEL) && !_args.contains(ARG_LOGFILE)) _log.setLogLevel(Log::Off); /* config directory */ useConfigDir = false; if (dir != "") { setConfigDirectory(dir); } /** Initialize support for language translations. */ //LanguageSupport::initialize(); resetLanguageAndStyle(); /* Switch off auto shutdown */ setQuitOnLastWindowClosed ( false ); /* Initialize GxsIdDetails */ GxsIdDetails::initialize(); } /** Destructor */ Rshare::~Rshare() { /* Cleanup GxsIdDetails */ GxsIdDetails::cleanup(); if (localServer) { localServer->close(); delete localServer; } } /** * @brief Executed when new instance connect command is sent to LocalServer */ void Rshare::slotConnectionEstablished() { QLocalSocket *socket = localServer->nextPendingConnection(); socket->close(); delete socket; QSharedMemory newArgs; newArgs.setKey(QString(TARGET) + "_newArgs"); if (!newArgs.attach()) { std::cerr << "(EE) Rshare::slotConnectionEstablished() Unable to attach to shared memory segment." << newArgs.errorString().toStdString() << std::endl; return; } QBuffer buffer; QDataStream in(&buffer); QStringList args; newArgs.lock(); buffer.setData((char*)newArgs.constData(), newArgs.size()); buffer.open(QBuffer::ReadOnly); in >> args; newArgs.unlock(); newArgs.detach(); emit newArgsReceived(args); while (!args.empty()) { std::cerr << "Rshare::slotConnectionEstablished args:" << QString(args.takeFirst()).toStdString() << std::endl; } } QString Rshare::retroshareVersion(bool withRevision) { QString version = QString("%1.%2.%3%4").arg(RS_MAJOR_VERSION).arg(RS_MINOR_VERSION).arg(RS_BUILD_NUMBER).arg(RS_BUILD_NUMBER_ADD); if (withRevision) { version += QString(" %1 %2").arg(tr("Revision")).arg(QString::number(RS_REVISION_NUMBER,16)); } return version; } /** Enters the main event loop and waits until exit() is called. The signal * running() will be emitted when the event loop has started. */ int Rshare::run() { QTimer::singleShot(0, rApp, SLOT(onEventLoopStarted())); return rApp->exec(); } QDateTime Rshare::startupTime() { return mStartupTime; } /** Called when the application's main event loop has started. This method * will emit the running() signal to indicate that the application's event * loop is running. */ void Rshare::onEventLoopStarted() { emit running(); } /** Display usage information regarding command-line arguments. */ /*void Rshare::printUsage(QString errmsg) { QTextStream out(stdout);*/ /* If there was an error message, print it out. */ /*if (!errmsg.isEmpty()) { out << "** " << errmsg << " **" << endl << endl; }*/ /* Now print the application usage */ //out << "Usage: " << endl; //out << "\t" << qApp->arguments().at(0) << " [options]" << endl; /* And available options */ //out << endl << "Available Options:" << endl; //out << "\t-"ARG_RESET"\t\tResets ALL stored Rshare settings." << endl; //out << "\t-"ARG_DATADIR"\tSets the directory Rshare uses for data files"<< endl; //out << "\t-"ARG_GUISTYLE"\t\tSets Rshare's interface style." << endl; //out << "\t-"ARG_GUISTYLESHEET"\t\tSets Rshare's stylesheet." << endl; //out << "\t\t\t[" << QStyleFactory::keys().join("|") << "]" << endl; //out << "\t-"ARG_LANGUAGE"\t\tSets Rshare's language." << endl; //out << "\t\t\t[" << LanguageSupport::languageCodes().join("|") << "]" << endl; //} /** Displays usage information for command-line args. */ void Rshare::showUsageMessageBox() { QString usage; QTextStream out(&usage); out << "Available Options:" << endl; out << ""; //out << trow(tcol("-"ARG_HELP) + // tcol(tr("Displays this usage message and exits."))); out << trow(tcol("-" ARG_RESET) + tcol(tr("Resets ALL stored RetroShare settings."))); out << trow(tcol("-" ARG_DATADIR" <dir>") + tcol(tr("Sets the directory RetroShare uses for data files."))); out << trow(tcol("-" ARG_LOGFILE" <file>") + tcol(tr("Sets the name and location of RetroShare's logfile."))); out << trow(tcol("-" ARG_LOGLEVEL" <level>") + tcol(tr("Sets the verbosity of RetroShare's logging.") + "
[" + Log::logLevels().join("|") +"]")); out << trow(tcol("-" ARG_GUISTYLE" <style>") + tcol(tr("Sets RetroShare's interface style.") + "
[" + QStyleFactory::keys().join("|") + "]")); out << trow(tcol("-" ARG_GUISTYLESHEET" <stylesheet>") + tcol(tr("Sets RetroShare's interface stylesheets."))); out << trow(tcol("-" ARG_LANGUAGE" <language>") + tcol(tr("Sets RetroShare's language.") + "
[" + LanguageSupport::languageCodes().join("|") + "]")); out << "
"; VMessageBox::information(0, tr("RetroShare Usage Information"), usage, VMessageBox::Ok); } /** Returns true if the specified argument expects a value. */ bool Rshare::argNeedsValue(QString argName) { return (argName == ARG_GUISTYLE || argName == ARG_GUISTYLESHEET || argName == ARG_LANGUAGE || argName == ARG_DATADIR || argName == ARG_LOGFILE || argName == ARG_LOGLEVEL || argName == ARG_RSLINK_S || argName == ARG_RSLINK_L || argName == ARG_RSFILE_S || argName == ARG_RSFILE_L ); } /** Parses the list of command-line arguments for their argument names and * values. */ void Rshare::parseArguments(QStringList args, bool firstRun) { QString arg, value; /* Loop through all command-line args/values and put them in a map */ for (int i = 0; i < args.size(); ++i) { /* Get the argument name and set a blank value */ arg = args.at(i);//.toLower(); Need Upper case for file name. if (arg.toLower() == "empty") continue; value = ""; /* Check if it starts with a - or -- */ if (arg.startsWith("-")) { arg = arg.mid((arg.startsWith("--") ? 2 : 1)); /* Check if it takes a value and there is one on the command-line */ if (i < args.size()-1 && argNeedsValue(arg.toLower())) { value = args.at(++i); } } else { /* Check if links or files without arg */ if (arg.toLower().startsWith("retroshare://")) { value = arg; arg = ARG_RSLINK_L; } else { if (QFile(arg).exists()) { value = arg; arg = ARG_RSFILE_L; } } } /* Don't send theses argument to _args map to allow multiple. */ if (arg == ARG_RSLINK_S || arg == ARG_RSLINK_L) { _links.append(value); } else if (arg == ARG_RSFILE_S || arg == ARG_RSFILE_L) { _files.append(value); } else if (firstRun) { /* Place this arg/value in the map only first time*/ _args.insert(arg, value); } } } /** Verifies that all specified arguments were valid. */ bool Rshare::validateArguments(QString &errmsg) { /* Check for a language that Retroshare recognizes. */ if (_args.contains(ARG_LANGUAGE) && !LanguageSupport::isValidLanguageCode(_args.value(ARG_LANGUAGE))) { errmsg = tr("Invalid language code specified:")+" " + _args.value(ARG_LANGUAGE); return false; } /* Check for a valid GUI style */ if (_args.contains(ARG_GUISTYLE) && !QStyleFactory::keys().contains(_args.value(ARG_GUISTYLE), Qt::CaseInsensitive)) { errmsg = tr("Invalid GUI style specified:")+" " + _args.value(ARG_GUISTYLE); return false; } /* Check for a valid log level */ if (_args.contains(ARG_LOGLEVEL) && !Log::logLevels().contains(_args.value(ARG_LOGLEVEL))) { errmsg = tr("Invalid log level specified:")+" " + _args.value(ARG_LOGLEVEL); return false; } /* Check for a writable log file */ if (_args.contains(ARG_LOGFILE) && !_log.isOpen()) { errmsg = tr("Unable to open log file '%1': %2") .arg(_args.value(ARG_LOGFILE)) .arg(_log.errorString()); return false; } return true; } /** Sets the translation RetroShare will use. If one was specified on the * command-line, we will use that. Otherwise, we'll check to see if one was * saved previously. If not, we'll default to one appropriate for the system * locale. */ bool Rshare::setLanguage(QString languageCode) { /* If the language code is empty, use the previously-saved setting */ if (languageCode.isEmpty()) { languageCode = Settings->getLanguageCode(); } /* Translate into the desired language */ if (LanguageSupport::translate(languageCode)) { _language = languageCode; return true; } return false; } /** Sets the locale RetroShare will use. If a language was specified on the * command-line, we will use one according to that. Otherwise, we'll check to see if a language was * saved previously. If not, we'll default to the system * locale. */ bool Rshare::setLocale(QString languageCode) { bool retVal = false; /* If the language code is empty, use the previously-saved setting */ if (languageCode.isEmpty()) { languageCode = Settings->getLanguageCode(); } /* Set desired locale as default locale */ if (LanguageSupport::localize(languageCode)) { retVal=true; } customizeDateFormat(); return retVal; } /** customize date format for feeds etc. */ void Rshare::customizeDateFormat() { QLocale locale = QLocale(); // set to default locale /* get long date format without weekday */ _dateformat = locale.dateFormat(QLocale::LongFormat); _dateformat.replace(QRegExp("^dddd,*[^ ]* *('[^']+' )*"), ""); _dateformat.replace(QRegExp(",* *dddd"), ""); _dateformat = _dateformat.trimmed(); } /** Get custom date format (defaultlongformat) */ QString Rshare::customDateFormat() { return _dateformat; } /** Sets the GUI style RetroShare will use. If one was specified on the * command-line, we will use that. Otherwise, we'll check to see if one was * saved previously. If not, we'll default to one appropriate for the * operating system. */ bool Rshare::setStyle(QString styleKey) { /* If no style was specified, use the previously-saved setting */ if (styleKey.isEmpty()) { styleKey = Settings->getInterfaceStyle(); } /* Apply the specified GUI style */ if (QApplication::setStyle(styleKey)) { _style = styleKey; return true; } return false; } bool Rshare::setSheet(QString sheet) { /* If no stylesheet was specified, use the previously-saved setting */ if (sheet.isEmpty()) { sheet = Settings->getSheetName(); } /* Apply the specified GUI stylesheet */ _stylesheet = sheet; /* load the StyleSheet*/ loadStyleSheet(_stylesheet); return true; } void Rshare::resetLanguageAndStyle() { /** Translate the GUI to the appropriate language. */ setLanguage(_args.value(ARG_LANGUAGE)); /** Set the locale appropriately. */ setLocale(_args.value(ARG_LANGUAGE)); /** Set the GUI style appropriately. */ setStyle(_args.value(ARG_GUISTYLE)); /** Set the GUI stylesheet appropriately. */ setSheet(_args.value(ARG_GUISTYLESHEET)); } // RetroShare: // Default: // :/qss/stylesheet/qss.default // :/qss/stylesheet/qss. // Internal: // :/qss/stylesheet/.qss // External: // /qss/.qss // Language depended stylesheet // _.lqss // // Plugin: // Default: // :/qss/stylesheet//_qss.default // :/qss/stylesheet//_qss. // Internal: // :/qss/stylesheet//_.qss // External: // /qss//_.qss // Language depended stylesheet // _.lqss void Rshare::loadStyleSheet(const QString &sheetName) { QString locale = QLocale().name(); QString styleSheet; QStringList names; names.push_back(""); // RetroShare /* Get stylesheet from plugins */ if (rsPlugins) { int count = rsPlugins->nbPlugins(); for (int i = 0; i < count; ++i) { RsPlugin* plugin = rsPlugins->plugin(i); if (plugin) { QString pluginStyleSheetName = QString::fromUtf8(plugin->qt_stylesheet().c_str()); if (!pluginStyleSheetName.isEmpty()) { names.push_back(QString("%1/%1_").arg(pluginStyleSheetName)); } } } } foreach (QString name, names) { /* load the default stylesheet */ QFile file(QString(":/qss/stylesheet/%1qss.default").arg(name)); if (file.open(QFile::ReadOnly)) { styleSheet += QLatin1String(file.readAll()) + "\n"; file.close(); } /* load locale depended default stylesheet */ file.setFileName(QString(":/qss/stylesheet/%1qss.%2").arg(name, locale)); if (file.open(QFile::ReadOnly)) { styleSheet += QLatin1String(file.readAll()) + "\n"; file.close(); } if (!sheetName.isEmpty()) { /* load stylesheet */ if (sheetName.left(1) == ":") { /* internal stylesheet */ file.setFileName(QString(":/qss/stylesheet/%1%2.qss").arg(name, sheetName.mid(1))); } else { /* external stylesheet */ file.setFileName(QString("%1/qss/%2%3.qss").arg(QString::fromUtf8(RsAccounts::ConfigDirectory().c_str()), name, sheetName)); if (!file.exists()) { file.setFileName(QString("%1/qss/%2%3.qss").arg(QString::fromUtf8(RsAccounts::DataDirectory().c_str()), name, sheetName)); } } if (file.open(QFile::ReadOnly)) { styleSheet += QLatin1String(file.readAll()) + "\n"; file.close(); /* load language depended stylesheet */ QFileInfo fileInfo(file.fileName()); file.setFileName(fileInfo.path() + "/" + fileInfo.baseName() + "_" + locale + ".lqss"); if (file.open(QFile::ReadOnly)) { styleSheet += QLatin1String(file.readAll()) + "\n"; file.close(); } } } } qApp->setStyleSheet(styleSheet); } /** get list of available stylesheets **/ void Rshare::getAvailableStyleSheets(QMap &styleSheets) { QFileInfoList fileInfoList = QDir(":/qss/stylesheet/").entryInfoList(QStringList("*.qss")); QFileInfo fileInfo; foreach (fileInfo, fileInfoList) { if (fileInfo.isFile()) { QString name = fileInfo.baseName(); styleSheets.insert(QString("%1 (%2)").arg(name, tr("built-in")), ":" + name); } } fileInfoList = QDir(QString::fromUtf8(RsAccounts::ConfigDirectory().c_str()) + "/qss/").entryInfoList(QStringList("*.qss")); foreach (fileInfo, fileInfoList) { if (fileInfo.isFile()) { QString name = fileInfo.baseName(); styleSheets.insert(name, name); } } fileInfoList = QDir(QString::fromUtf8(RsAccounts::DataDirectory().c_str()) + "/qss/").entryInfoList(QStringList("*.qss")); foreach (fileInfo, fileInfoList) { if (fileInfo.isFile()) { QString name = fileInfo.baseName(); if (!styleSheets.contains(name)) { styleSheets.insert(name, name); } } } } void Rshare::refreshStyleSheet(QWidget *widget, bool processChildren) { if (widget != NULL) { // force widget to recalculate valid style widget->style()->unpolish(widget); widget->style()->polish(widget); // widget might need to recalculate properties (like margins) depending on style QEvent event(QEvent::StyleChange); QApplication::sendEvent(widget, &event); // repaint widget widget->update(); if (processChildren == true) { // process children recursively QObjectList childList = widget->children (); for (QObjectList::Iterator it = childList.begin(); it != childList.end(); ++it) { QWidget *child = qobject_cast(*it); if (child != NULL) { refreshStyleSheet(child, processChildren); } } } } } /** Initialize plugins. */ void Rshare::initPlugins() { loadStyleSheet(_stylesheet); LanguageSupport::translatePlugins(_language); } /** Returns the directory RetroShare uses for its data files. */ QString Rshare::dataDirectory() { if (useConfigDir) { return configDir; } else if (_args.contains(ARG_DATADIR)) { return _args.value(ARG_DATADIR); } return defaultDataDirectory(); } /** Returns the default location of RetroShare's data directory. */ QString Rshare::defaultDataDirectory() { #if defined(Q_OS_WIN) return (win32_app_data_folder() + "\\RetroShare"); #else return (QDir::homePath() + "/.RetroShare"); #endif } /** Creates Rshare's data directory, if it doesn't already exist. */ bool Rshare::createDataDirectory(QString *errmsg) { QDir datadir(dataDirectory()); if (!datadir.exists()) { QString path = datadir.absolutePath(); if (!datadir.mkpath(path)) { return err(errmsg, tr("Could not create data directory: %1").arg(path)); } } return true; } /** Set Rshare's data directory - externally */ bool Rshare::setConfigDirectory(QString dir) { useConfigDir = true; configDir = dir; return true; } /** Writes msg with severity level to RetroShare's log. */ Log::LogMessage Rshare::log(Log::LogLevel level, QString msg) { return _log.log(level, msg); } /** Creates and binds a shortcut such that when key is pressed in * sender's context, receiver's slot will be called. */ void Rshare::createShortcut(const QKeySequence &key, QWidget *sender, QWidget *receiver, const char *slot) { QShortcut *s = new QShortcut(key, sender); connect(s, SIGNAL(activated()), receiver, slot); } #ifdef __APPLE__ bool Rshare::event(QEvent *event) { switch (event->type()) { case QEvent::FileOpen:{ QFileOpenEvent* fileOE = static_cast(event); QStringList args; if (! fileOE->file().isEmpty()) { _files.append(fileOE->file()); emit newArgsReceived(QStringList()); return true; } else if (! fileOE->url().isEmpty()) { _links.append(fileOE->url().toString()); emit newArgsReceived(QStringList()); return true; } } default: return QApplication::event(event); } } #endif void Rshare::blinkTimer() { mBlink = !mBlink; emit blink(mBlink); if (mBlink) { /* Tick every second (create an own timer when needed) */ emit secondTick(); } } bool Rshare::loadCertificate(const RsPeerId &accountId, bool autoLogin) { if (!RsAccounts::SelectAccount(accountId)) { return false; } std::string lockFile; int retVal = RsInit::LockAndLoadCertificates(autoLogin, lockFile); switch (retVal) { case 0: break; case 1: QMessageBox::warning( 0, QObject::tr("Multiple instances"), QObject::tr("Another RetroShare using the same profile is " "already running on your system. Please close " "that instance first\n Lock file:\n") + QString::fromUtf8(lockFile.c_str())); return false; case 2: QMessageBox::critical( 0, QObject::tr("Multiple instances"), QObject::tr("An unexpected error occurred when Retroshare " "tried to acquire the single instance lock\n Lock file:\n") + QString::fromUtf8(lockFile.c_str())); return false; case 3: // case 3: QMessageBox::critical( 0, // QObject::tr("Login Failure"), // QObject::tr("Maybe password is wrong") ); return false; default: std::cerr << "Rshare::loadCertificate() unexpected switch value " << retVal << std::endl; return false; } return true; } bool Rshare::updateLocalServer() { if (localServer) { QString serverName = QString(TARGET); if (Settings->getUseLocalServer()) { localServer->removeServer(serverName); localServer->listen(serverName); return true; } localServer->close(); } return false; }