void CaptureContext::LoadLogfile(const QString &logFile, const QString &origFilename, bool temporary, bool local) { m_Progress = new QProgressDialog(QString("Loading Log"), QString(), 0, 1000, m_MainWindow); m_Progress->setWindowTitle("Please Wait"); m_Progress->setWindowFlags(Qt::CustomizeWindowHint | Qt::Dialog | Qt::WindowTitleHint); m_Progress->setWindowIcon(QIcon()); m_Progress->setMinimumSize(QSize(250, 0)); m_Progress->setMaximumSize(QSize(250, 10000)); m_Progress->setCancelButton(NULL); m_Progress->setMinimumDuration(0); m_Progress->setWindowModality(Qt::ApplicationModal); m_Progress->setValue(0); QLabel *label = new QLabel(m_Progress); label->setText(QString("Loading Log: %1").arg(origFilename)); label->setAlignment(Qt::AlignCenter); label->setWordWrap(true); m_Progress->setLabel(label); LambdaThread *thread = new LambdaThread([this, logFile, origFilename, temporary, local]() { LoadLogfileThreaded(logFile, origFilename, temporary, local); GUIInvoke::call([this, origFilename]() { delete m_Progress; m_Progress = NULL; }); }); thread->selfDelete(true); thread->start(); }
void MainWindow::on_action_Resolve_Symbols_triggered() { m_Ctx->Renderer()->AsyncInvoke([this](IReplayRenderer *r) { r->InitResolver(); }); QProgressDialog *m_Progress = new QProgressDialog(tr("Please Wait - Resolving Symbols"), QString(), 0, 0, this); m_Progress->setWindowTitle("Please Wait"); m_Progress->setWindowFlags(Qt::CustomizeWindowHint | Qt::Dialog | Qt::WindowTitleHint); m_Progress->setWindowIcon(QIcon()); m_Progress->setMinimumSize(QSize(250, 0)); m_Progress->setMaximumSize(QSize(250, 10000)); m_Progress->setCancelButton(NULL); m_Progress->setMinimumDuration(0); m_Progress->setWindowModality(Qt::ApplicationModal); m_Progress->setValue(0); QLabel *label = new QLabel(m_Progress); label->setText(tr("Please Wait - Resolving Symbols")); label->setAlignment(Qt::AlignCenter); label->setWordWrap(true); m_Progress->setLabel(label); LambdaThread *thread = new LambdaThread([this, m_Progress]() { bool running = true; while(running) { // just bail if we managed to get here without a resolver. m_Ctx->Renderer()->BlockInvoke( [&running](IReplayRenderer *r) { running = r->HasCallstacks() && !r->InitResolver(); }); } GUIInvoke::call([this, m_Progress]() { m_Progress->hide(); delete m_Progress; if(m_Ctx->hasAPIInspector()) m_Ctx->apiInspector()->on_apiEvents_itemSelectionChanged(); }); }); thread->selfDelete(true); thread->start(); }
void RemoteManager::on_connect_clicked() { RDTreeWidgetItem *node = ui->hosts->selectedItem(); if(!node) return; RemoteConnect connect = getRemoteConnect(node); RemoteHost *host = getRemoteHost(node); if(connect.ident > 0) { connectToApp(node); } else if(host) { if(host->serverRunning) { QMessageBox::StandardButton res = RDDialog::question( this, tr("Remote server shutdown"), tr("Are you sure you wish to shut down running remote server on %1?").arg(host->Name()), RDDialog::YesNoCancel); if(res == QMessageBox::Cancel || res == QMessageBox::No) return; // shut down if(host->connected) { m_Ctx.Replay().ShutdownServer(); setRemoteServerLive(node, false, false); } else { IRemoteServer *server = NULL; ReplayStatus status = RENDERDOC_CreateRemoteServerConnection(host->hostname.c_str(), 0, &server); if(server) server->ShutdownServerAndConnection(); setRemoteServerLive(node, false, false); if(status != ReplayStatus::Succeeded) RDDialog::critical(this, tr("Shutdown error"), tr("Error shutting down remote server: %1").arg(ToQStr(status))); } updateConnectButton(); } else { // try to run ui->refreshOne->setEnabled(false); ui->refreshAll->setEnabled(false); m_Lookups.release(); LambdaThread *th = new LambdaThread([this, node]() { runRemoteServer(node); }); th->selfDelete(true); th->start(); updateLookupsStatus(); } } }
void RemoteManager::refreshHost(RDTreeWidgetItem *node) { RemoteHost *host = getRemoteHost(node); if(!host) return; // this function looks up the remote connections and for each one open // queries it for the API, target (usually executable name) and if any user is already connected LambdaThread *th = new LambdaThread([this, node, host]() { QByteArray username = GetSystemUsername().toUtf8(); host->CheckStatus(); GUIInvoke::call( [this, node, host]() { setRemoteServerLive(node, host->serverRunning, host->busy); }); uint32_t nextIdent = 0; for(;;) { // just a sanity check to make sure we don't hit some unexpected case and infinite loop uint32_t prevIdent = nextIdent; nextIdent = RENDERDOC_EnumerateRemoteTargets(host->hostname.c_str(), nextIdent); if(nextIdent == 0 || prevIdent >= nextIdent) break; ITargetControl *conn = RENDERDOC_CreateTargetControl(host->hostname.c_str(), nextIdent, username.data(), false); if(conn) { QString target = QString::fromUtf8(conn->GetTarget()); QString api = QString::fromUtf8(conn->GetAPI()); QString busy = QString::fromUtf8(conn->GetBusyClient()); QString running; if(!busy.isEmpty()) running = tr("Running %1, %2 is connected").arg(api).arg(busy); else running = tr("Running %1").arg(api); RemoteConnect tag(host->hostname, host->Name(), nextIdent); GUIInvoke::call([this, node, target, running, tag]() { RDTreeWidgetItem *child = new RDTreeWidgetItem({target, running}); setRemoteConnect(child, tag); node->addChild(child); ui->hosts->expandItem(node); }); conn->Shutdown(); } } GUIInvoke::call([node]() { node->setItalic(false); }); m_Lookups.acquire(); GUIInvoke::call([this]() { updateStatus(); }); }); th->selfDelete(true); th->start(); }
void CaptureContext::LoadCapture(const rdcstr &captureFile, const rdcstr &origFilename, bool temporary, bool local) { m_LoadInProgress = true; if(local) m_Config.CrashReport_LastOpenedCapture = origFilename; bool newCapture = (!temporary && !Config().RecentCaptureFiles.contains(origFilename)); LambdaThread *thread = new LambdaThread([this, captureFile, origFilename, temporary, local]() { LoadCaptureThreaded(captureFile, origFilename, temporary, local); }); thread->selfDelete(true); thread->start(); QElapsedTimer loadTimer; loadTimer.start(); ShowProgressDialog(m_MainWindow, tr("Loading Capture: %1").arg(origFilename), [this]() { return !m_LoadInProgress; }, [this]() { return UpdateLoadProgress(); }); ANALYTIC_ADDAVG(Performance.LoadTime, double(loadTimer.nsecsElapsed() * 1.0e-9)); ANALYTIC_SET(CaptureFeatures.ShaderLinkage, m_APIProps.ShaderLinkage); ANALYTIC_SET(CaptureFeatures.YUVTextures, m_APIProps.YUVTextures); ANALYTIC_SET(CaptureFeatures.SparseResources, m_APIProps.SparseResources); ANALYTIC_SET(CaptureFeatures.MultiGPU, m_APIProps.MultiGPU); ANALYTIC_SET(CaptureFeatures.D3D12Bundle, m_APIProps.D3D12Bundle); m_MainWindow->setProgress(-1.0f); if(m_CaptureLoaded) { m_CaptureTemporary = temporary; m_CaptureMods = CaptureModifications::NoModifications; rdcarray<ICaptureViewer *> viewers(m_CaptureViewers); // make sure we're on a consistent event before invoking viewer forms if(m_LastDrawcall) SetEventID(viewers, m_LastDrawcall->eventId, true); else if(!m_Drawcalls.empty()) SetEventID(viewers, m_Drawcalls.back().eventId, true); GUIInvoke::blockcall([&viewers]() { // notify all the registers viewers that a capture has been loaded for(ICaptureViewer *viewer : viewers) { if(viewer) viewer->OnCaptureLoaded(); } }); if(newCapture && m_Notes.contains(lit("comments"))) { if(!HasCommentView()) ShowCommentView(); RaiseDockWindow(GetCommentView()->Widget()); } } }
bool RunProcessAsAdmin(const QString &fullExecutablePath, const QStringList ¶ms, std::function<void()> finishedCallback) { #if defined(Q_OS_WIN32) std::wstring wideExe = fullExecutablePath.toStdWString(); std::wstring wideParams = params.join(QChar(' ')).toStdWString(); SHELLEXECUTEINFOW info = {}; info.cbSize = sizeof(info); info.fMask = SEE_MASK_NOCLOSEPROCESS; info.lpVerb = L"runas"; info.lpFile = wideExe.c_str(); info.lpParameters = wideParams.c_str(); info.nShow = SW_SHOWNORMAL; ShellExecuteExW(&info); if((uintptr_t)info.hInstApp > 32 && info.hProcess != NULL) { if(finishedCallback) { HANDLE h = info.hProcess; // do the wait on another thread LambdaThread *thread = new LambdaThread([h, finishedCallback]() { WaitForSingleObject(h, 30000); CloseHandle(h); GUIInvoke::call(finishedCallback); }); thread->selfDelete(true); thread->start(); } else { CloseHandle(info.hProcess); } return true; } return false; #else // try to find a way to run the application elevated. const QString graphicalSudo[] = { "pkexec", "kdesudo", "gksudo", "beesu", }; // if none of the graphical options, then look for sudo and either const QString termEmulator[] = { "x-terminal-emulator", "gnome-terminal", "knosole", "xterm", }; for(const QString &sudo : graphicalSudo) { QString inPath = QStandardPaths::findExecutable(sudo); // can't find in path if(inPath.isEmpty()) continue; QProcess *process = new QProcess; QStringList sudoParams; sudoParams << fullExecutablePath; for(const QString &p : params) sudoParams << p; qInfo() << "Running" << sudo << "with params" << sudoParams; // run with sudo process->start(sudo, sudoParams); // when the process exits, call the callback and delete QObject::connect(process, OverloadedSlot<int>::of(&QProcess::finished), [process, finishedCallback](int exitCode) { process->deleteLater(); GUIInvoke::call(finishedCallback); }); return true; } QString sudo = QStandardPaths::findExecutable("sudo"); if(sudo.isEmpty()) { qCritical() << "Couldn't find graphical or terminal sudo program!\n" << "Please run " << fullExecutablePath << "with args" << params << "manually."; return false; } for(const QString &term : termEmulator) { QString inPath = QStandardPaths::findExecutable(term); // can't find in path if(inPath.isEmpty()) continue; QProcess *process = new QProcess; // run terminal sudo with emulator QStringList termParams; termParams << "-e" << QString("bash -c 'sudo %1 %2'").arg(fullExecutablePath).arg(params.join(QChar(' '))); process->start(term, termParams); // when the process exits, call the callback and delete QObject::connect(process, OverloadedSlot<int>::of(&QProcess::finished), [process, finishedCallback](int exitCode) { process->deleteLater(); GUIInvoke::call(finishedCallback); }); return true; } qCritical() << "Couldn't find graphical or terminal emulator to launch sudo.\n" << "Please run " << fullExecutablePath << "with args" << params << "manually."; return false; #endif }