QString GwtCallback::chooseRVersion() { #ifdef Q_OS_WIN32 RVersion rVersion = desktop::detectRVersion(true, pOwner_->asWidget()); if (rVersion.isValid()) return getRVersion(); else return QString(); #else return QString(); #endif }
void ChooseRHome::setValue(const RVersion& value, bool preferR64) { if (value.isEmpty()) { if (preferR64) ui->radioDefault64->setChecked(true); else ui->radioDefault->setChecked(true); } else { ui->radioCustom->setChecked(true); QList<QListWidgetItem*> matches = ui->listHomeDir->findItems(value.description(), Qt::MatchExactly); if (matches.size() > 0) matches.first()->setSelected(true); ui->listHomeDir->setFocus(); } }
bool prepareEnvironment(Options &options) { bool forceUi = ::GetAsyncKeyState(VK_CONTROL) & ~1; RVersion rVersion = detectRVersion(forceUi); if (!rVersion.isValid()) return false; // get the short path version of the home dir std::string homePath = QDir::toNativeSeparators(rVersion.homeDir()).toStdString(); DWORD len = ::GetShortPathName(homePath.c_str(), NULL, 0); std::vector<TCHAR> buffer(len, 0); if (::GetShortPathName(homePath.c_str(), &(buffer[0]), len) != 0) { // copy path to string and assign it we got one std::string shortHomePath(&(buffer[0])); if (!shortHomePath.empty()) homePath = shortHomePath; } else { LOG_ERROR(systemError(::GetLastError(), ERROR_LOCATION)); } // set R_HOME system::setenv("R_HOME", homePath); std::string path = QDir::toNativeSeparators(rVersion.binDir()).toStdString() + ";" + system::getenv("PATH"); system::setenv("PATH", path); return true; }
int main(int argc, char* argv[]) { core::system::initHook(); try { QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); // initialize log FilePath userHomePath = core::system::userHomePath("R_USER|HOME"); FilePath logPath = core::system::userSettingsPath( userHomePath, "RStudio-Desktop").childPath("log"); core::system::initializeLog("rdesktop", core::system::kLogLevelWarning, logPath); boost::scoped_ptr<QApplication> pApp; boost::scoped_ptr<ApplicationLaunch> pAppLaunch; ApplicationLaunch::init(QString::fromAscii("RStudio"), argc, argv, &pApp, &pAppLaunch); // determine the filename that was passed to us QString filename; #ifdef __APPLE__ // get filename from OpenFile apple-event (pump to ensure delivery) pApp->processEvents(); filename = verifyAndNormalizeFilename( pAppLaunch->startupOpenFileRequest()); #endif // allow all platforms (including OSX) to check the command line. // we include OSX because the way Qt handles apple events is to // re-route them to the first instance to register for events. in // this case (for projects) we use this to initiate a launch // of the application with the project filename on the command line if (filename.isEmpty()) { // get filename from command line arguments if (pApp->arguments().size() > 1) filename = verifyAndNormalizeFilename(pApp->arguments().last()); } // if we have a filename and it is NOT a project file then see // if we can open it within an existing instance if (isNonProjectFilename(filename)) { if (pAppLaunch->sendMessage(filename)) return 0; } else { // try to register ourselves as a peer for others pAppLaunch->attemptToRegisterPeer(); } pApp->setAttribute(Qt::AA_MacDontSwapCtrlAndMeta); initializeSharedSecret(); initializeWorkingDirectory(argc, argv, filename); initializeStartupEnvironment(&filename); Options& options = desktop::options(); if (!prepareEnvironment(options)) return 1; // get install path FilePath installPath; Error error = core::system::installPath("..", argc, argv, &installPath); if (error) { LOG_ERROR(error); return EXIT_FAILURE; } #ifdef _WIN32 RVersion version = detectRVersion(false); #endif // calculate paths to config file and rsession FilePath confPath, sessionPath; // check for debug configuration #ifndef NDEBUG FilePath currentPath = FilePath::safeCurrentPath(installPath); if (currentPath.complete("conf/rdesktop-dev.conf").exists()) { confPath = currentPath.complete("conf/rdesktop-dev.conf"); sessionPath = currentPath.complete("session/rsession"); #ifdef _WIN32 if (version.architecture() == ArchX64) sessionPath = installPath.complete("x64/rsession"); #endif } #endif // if there is no conf path then release mode if (confPath.empty()) { // default session path (then tweak) sessionPath = installPath.complete("bin/rsession"); // check for win64 binary on windows #ifdef _WIN32 if (version.architecture() == ArchX64) sessionPath = installPath.complete("bin/x64/rsession"); #endif // check for running in a bundle on OSX #ifdef __APPLE__ if (installPath.complete("Info.plist").exists()) sessionPath = installPath.complete("MacOS/rsession"); #endif } core::system::fixupExecutablePath(&sessionPath); // launch session SessionLauncher sessionLauncher(sessionPath, confPath); error = sessionLauncher.launchFirstSession(filename, pAppLaunch.get()); if (!error) { int result = pApp->exec(); sessionLauncher.cleanupAtExit(); options.cleanUpScratchTempDir(); return result; } else { LOG_ERROR(error); // These calls to processEvents() seem to be necessary to get // readAllStandardError to work. pApp->processEvents(); pApp->processEvents(); pApp->processEvents(); QMessageBox errorMsg(safeMessageBoxIcon(QMessageBox::Critical), QString::fromUtf8("RStudio"), sessionLauncher.launchFailedErrorMessage()); errorMsg.addButton(new QPushButton(QString::fromUtf8("OK")), QMessageBox::AcceptRole); errorMsg.show(); pApp->exec(); return EXIT_FAILURE; } } CATCH_UNEXPECTED_EXCEPTION }
void ChooseRHome::chooseOther() { if (lastDir_.isEmpty()) { lastDir_ = QString::fromLocal8Bit(core::system::getenv("ProgramFiles").c_str()); } QString dir = QFileDialog::getExistingDirectory( this, QString::fromUtf8("Choose R Directory"), lastDir_, QFileDialog::ShowDirsOnly); if (dir.isEmpty()) return; lastDir_ = dir; QList<RVersion> versions = detectVersionsInDir(dir); RVersion rVer; if (versions.size() == 0) { showWarning( this, QString::fromUtf8("Invalid R Directory"), QString::fromUtf8("This directory does not appear to contain a " "valid R installation.\n\nPlease try again.")); return; } else if (versions.size() > 1) { QStringList items; for (int i = 0; i < versions.size(); i++) items << versions.at(i).description(); QInputDialog inputDialog(this); inputDialog.setOptions(QInputDialog::UseListViewForComboBoxItems); inputDialog.setComboBoxItems(items); inputDialog.setComboBoxEditable(false); inputDialog.setWindowTitle(QString::fromUtf8("Choose Version")); inputDialog.setLabelText(QString::fromUtf8("Please choose the version to use:")); if (inputDialog.exec() != QDialog::Accepted) return; int idx = items.indexOf(QRegExp(inputDialog.textValue(), Qt::CaseSensitive, QRegExp::FixedString)); if (idx < 0) return; rVer = versions.at(idx); } else // versions.size() == 1 { rVer = versions.at(0); } switch (rVer.validate()) { case desktop::ValidateSuccess: break; case desktop::ValidateNotFound: showWarning( this, QString::fromUtf8("Invalid R Directory"), QString::fromUtf8("This directory does not appear to contain a " "valid R installation.\n\nPlease try again.")); return; case desktop::ValidateBadArchitecture: showWarning( this, QString::fromUtf8("Incompatible R Build"), QString::fromUtf8("The version of R you've selected was built " "for a different CPU architecture and cannot " "be used with this version of RStudio.")); return; case desktop::ValidateVersionTooOld: default: showWarning( this, QString::fromUtf8("Incompatible R Build"), QString::fromUtf8("The version of R you've selected is not " "compatible with RStudio. Please install a " "newer version of R.")); return; } QList<QListWidgetItem*> items = ui->listHomeDir->findItems( rVer.description(), Qt::MatchExactly); if (!items.isEmpty()) { ui->listHomeDir->setCurrentItem(items[0]); } else { QListWidgetItem* pItem = toItem(rVer); ui->listHomeDir->addItem(pItem); pItem->setSelected(true); } }
int main(int argc, char* argv[]) { core::system::initHook(); try { initializeLang(); // initialize log core::system::initializeLog("rdesktop", core::system::kLogLevelWarning, desktop::userLogPath()); // ignore SIGPIPE Error error = core::system::ignoreSignal(core::system::SigPipe); if (error) LOG_ERROR(error); #ifdef __APPLE__ // font substituion for OSX Mavericks // see: https://bugreports.qt-project.org/browse/QTBUG-32789 QFont::insertSubstitution(QString::fromUtf8(".Lucida Grande UI"), QString::fromUtf8("Lucida Grande")); #endif boost::scoped_ptr<QApplication> pApp; boost::scoped_ptr<ApplicationLaunch> pAppLaunch; ApplicationLaunch::init(QString::fromUtf8("RStudio"), argc, argv, &pApp, &pAppLaunch); // determine the filename that was passed to us QString filename; #ifdef __APPLE__ // get filename from OpenFile apple-event (pump to ensure delivery) pApp->processEvents(); filename = verifyAndNormalizeFilename( pAppLaunch->startupOpenFileRequest()); #endif // allow all platforms (including OSX) to check the command line. // we include OSX because the way Qt handles apple events is to // re-route them to the first instance to register for events. in // this case (for projects) we use this to initiate a launch // of the application with the project filename on the command line if (filename.isEmpty()) { // get filename from command line arguments if (pApp->arguments().size() > 1) { QString arg = pApp->arguments().last(); if (arg != QString::fromUtf8(kRunDiagnosticsOption)) filename = verifyAndNormalizeFilename(arg); } } // if we have a filename and it is NOT a project file then see // if we can open it within an existing instance if (isNonProjectFilename(filename)) { if (pAppLaunch->sendMessage(filename)) return 0; } else { // try to register ourselves as a peer for others pAppLaunch->attemptToRegisterPeer(); } // init options from command line desktop::options().initFromCommandLine(pApp->arguments()); // reset log if we are in run-diagnostics mode if (desktop::options().runDiagnostics()) { desktop::reattachConsoleIfNecessary(); initializeStderrLog("rdesktop", core::system::kLogLevelWarning); } pApp->setAttribute(Qt::AA_MacDontSwapCtrlAndMeta); initializeSharedSecret(); initializeWorkingDirectory(argc, argv, filename); initializeStartupEnvironment(&filename); Options& options = desktop::options(); if (!prepareEnvironment(options)) return 1; // get install path FilePath installPath; error = core::system::installPath("..", argv[0], &installPath); if (error) { LOG_ERROR(error); return EXIT_FAILURE; } #ifdef _WIN32 RVersion version = detectRVersion(false); #endif // calculate paths to config file, rsession, and desktop scripts FilePath confPath, sessionPath, scriptsPath; // check for debug configuration #ifndef NDEBUG FilePath currentPath = FilePath::safeCurrentPath(installPath); if (currentPath.complete("conf/rdesktop-dev.conf").exists()) { confPath = currentPath.complete("conf/rdesktop-dev.conf"); sessionPath = currentPath.complete("session/rsession"); scriptsPath = currentPath.complete("desktop"); #ifdef _WIN32 if (version.architecture() == ArchX64) sessionPath = installPath.complete("x64/rsession"); #endif } #endif // if there is no conf path then release mode if (confPath.empty()) { // default paths (then tweak) sessionPath = installPath.complete("bin/rsession"); scriptsPath = installPath.complete("bin"); // check for win64 binary on windows #ifdef _WIN32 if (version.architecture() == ArchX64) sessionPath = installPath.complete("bin/x64/rsession"); #endif // check for running in a bundle on OSX #ifdef __APPLE__ if (installPath.complete("Info.plist").exists()) { sessionPath = installPath.complete("MacOS/rsession"); scriptsPath = installPath.complete("MacOS"); } #endif } core::system::fixupExecutablePath(&sessionPath); // set the scripts path in options desktop::options().setScriptsPath(scriptsPath); // launch session SessionLauncher sessionLauncher(sessionPath, confPath); error = sessionLauncher.launchFirstSession(filename, pAppLaunch.get()); if (!error) { int result = pApp->exec(); sessionLauncher.cleanupAtExit(); options.cleanUpScratchTempDir(); return result; } else { LOG_ERROR(error); // These calls to processEvents() seem to be necessary to get // readAllStandardError to work. pApp->processEvents(); pApp->processEvents(); pApp->processEvents(); QMessageBox errorMsg(safeMessageBoxIcon(QMessageBox::Critical), QString::fromUtf8("RStudio"), sessionLauncher.launchFailedErrorMessage()); errorMsg.addButton(new QPushButton(QString::fromUtf8("OK")), QMessageBox::AcceptRole); errorMsg.show(); pApp->exec(); return EXIT_FAILURE; } } CATCH_UNEXPECTED_EXCEPTION }
int main(int argc, char* argv[]) { core::system::initHook(); try { initializeLang(); if (useChromiumDevtools()) { // use QTcpSocket to find an open port. this is unfortunately a bit racey // but AFAICS there isn't a better solution for port selection QByteArray port; QTcpSocket* pSocket = new QTcpSocket(); if (pSocket->bind()) { quint16 port = pSocket->localPort(); desktopInfo().setChromiumDevtoolsPort(port); core::system::setenv("QTWEBENGINE_REMOTE_DEBUGGING", safe_convert::numberToString(port)); pSocket->close(); } } // initialize log core::system::initializeLog("rdesktop", core::system::kLogLevelWarning, desktop::userLogPath()); // ignore SIGPIPE Error error = core::system::ignoreSignal(core::system::SigPipe); if (error) LOG_ERROR(error); // attempt to remove stale lockfiles, as they can impede // application startup error = removeStaleOptionsLockfile(); if (error) LOG_ERROR(error); // set application attributes QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // prepare command line arguments static std::vector<char*> arguments(argv, argv + argc); // enable viewport meta (allows us to control / restrict // certain touch gestures) static char enableViewport[] = "--enable-viewport"; arguments.push_back(enableViewport); #ifndef NDEBUG // disable web security for development builds (so we can // get access to sourcemaps) static char disableWebSecurity[] = "--disable-web-security"; arguments.push_back(disableWebSecurity); #endif // disable chromium renderer accessibility by default (it can cause // slowdown when used in conjunction with some applications; see e.g. // https://github.com/rstudio/rstudio/issues/1990) if (core::system::getenv("RSTUDIO_ACCESSIBILITY").empty()) { static char disableRendererAccessibility[] = "--disable-renderer-accessibility"; arguments.push_back(disableRendererAccessibility); } #ifdef Q_OS_LINUX // workaround for Qt 5.10.1 bug "Could not find QtWebEngineProcess" // https://bugreports.qt.io/browse/QTBUG-67023 // https://bugreports.qt.io/browse/QTBUG-66346 static char noSandbox[] = "--no-sandbox"; arguments.push_back(noSandbox); #endif #ifdef Q_OS_MAC // don't prefer compositing to LCD text rendering. when enabled, this causes the compositor to // be used too aggressively on Retina displays on macOS, with the side effect that the // scrollbar doesn't auto-hide because a compositor layer is present. // https://github.com/rstudio/rstudio/issues/1953 static char disableCompositorPref[] = "--disable-prefer-compositing-to-lcd-text"; arguments.push_back(disableCompositorPref); // disable gpu rasterization for certain display configurations. // this works around some of the rendering issues seen with RStudio. // // https://bugs.chromium.org/p/chromium/issues/detail?id=773705 // https://github.com/rstudio/rstudio/issues/2093 // // because the issue seems to only affect certain video cards on macOS // High Sierra, we scope that change to that particular configuration // for now (we can expand this list if more users report issues) core::Version macVersion(QSysInfo::productVersion().toStdString()); if (macVersion.versionMajor() == 10 && macVersion.versionMinor() == 13) { core::system::ProcessResult processResult; core::system::runCommand( "/usr/sbin/system_profiler SPDisplaysDataType", core::system::ProcessOptions(), &processResult); std::string stdOut = processResult.stdOut; if (!stdOut.empty()) { std::vector<std::string> blackList = { "NVIDIA GeForce GT 650M", "NVIDIA GeForce GT 750M" }; for (const std::string& entry : blackList) { if (stdOut.find(entry) != std::string::npos) { static char disableGpuRasterization[] = "--disable-gpu-rasterization"; arguments.push_back(disableGpuRasterization); break; } } } } #endif // re-assign command line arguments argc = (int) arguments.size(); argv = &arguments[0]; // prepare application for launch boost::scoped_ptr<QApplication> pApp; boost::scoped_ptr<ApplicationLaunch> pAppLaunch; ApplicationLaunch::init(QString::fromUtf8("RStudio"), argc, argv, &pApp, &pAppLaunch); // determine the filename that was passed to us QString filename; #ifdef __APPLE__ // get filename from OpenFile apple-event (pump to ensure delivery) pApp->processEvents(); filename = verifyAndNormalizeFilename( pAppLaunch->startupOpenFileRequest()); #endif // allow all platforms (including OSX) to check the command line. // we include OSX because the way Qt handles apple events is to // re-route them to the first instance to register for events. in // this case (for projects) we use this to initiate a launch // of the application with the project filename on the command line if (filename.isEmpty()) { // get filename from command line arguments if (pApp->arguments().size() > 1) { QString arg = pApp->arguments().at(1); if (arg != QString::fromUtf8(kRunDiagnosticsOption)) filename = verifyAndNormalizeFilename(arg); } } // if we have a filename and it is NOT a project file then see // if we can open it within an existing instance if (isNonProjectFilename(filename)) { if (pAppLaunch->sendMessage(filename)) return 0; } else { // try to register ourselves as a peer for others pAppLaunch->attemptToRegisterPeer(); } // init options from command line desktop::options().initFromCommandLine(pApp->arguments()); // reset log if we are in run-diagnostics mode if (desktop::options().runDiagnostics()) { desktop::reattachConsoleIfNecessary(); initializeStderrLog("rdesktop", core::system::kLogLevelWarning); } initializeSharedSecret(); initializeWorkingDirectory(argc, argv, filename); initializeStartupEnvironment(&filename); Options& options = desktop::options(); if (!prepareEnvironment(options)) return 1; // get install path FilePath installPath; error = core::system::installPath("..", argv[0], &installPath); if (error) { LOG_ERROR(error); return EXIT_FAILURE; } #ifdef _WIN32 RVersion version = detectRVersion(false); #endif // calculate paths to config file, rsession, and desktop scripts FilePath confPath, sessionPath, scriptsPath; bool devMode = false; // check for debug configuration FilePath currentPath = FilePath::safeCurrentPath(installPath); if (currentPath.complete("conf/rdesktop-dev.conf").exists()) { confPath = currentPath.complete("conf/rdesktop-dev.conf"); sessionPath = currentPath.complete("session/rsession"); scriptsPath = currentPath.complete("desktop"); devMode = true; #ifdef _WIN32 if (version.architecture() == ArchX64 && installPath.complete("session/x64").exists()) { sessionPath = installPath.complete("session/x64/rsession"); } #endif } // if there is no conf path then release mode if (confPath.empty()) { // default paths (then tweak) sessionPath = installPath.complete("bin/rsession"); scriptsPath = installPath.complete("bin"); // check for win64 binary on windows #ifdef _WIN32 if (version.architecture() == ArchX64 && installPath.complete("bin/x64").exists()) { sessionPath = installPath.complete("bin/x64/rsession"); } #endif // check for running in a bundle on OSX #ifdef __APPLE__ if (installPath.complete("Info.plist").exists()) { sessionPath = installPath.complete("MacOS/rsession"); scriptsPath = installPath.complete("MacOS"); } #endif } core::system::fixupExecutablePath(&sessionPath); auto* pProxyFactory = new NetworkProxyFactory(); QNetworkProxyFactory::setApplicationProxyFactory(pProxyFactory); // set the scripts path in options desktop::options().setScriptsPath(scriptsPath); // launch session SessionLauncher sessionLauncher(sessionPath, confPath, filename, pAppLaunch.get()); sessionLauncher.launchFirstSession(installPath, devMode, pApp->arguments()); ProgressActivator progressActivator; int result = pApp->exec(); desktop::activation().releaseLicense(); options.cleanUpScratchTempDir(); return result; } CATCH_UNEXPECTED_EXCEPTION }