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();
}
Example #2
0
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();
}
Example #3
0
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();
    }
  }
}
Example #4
0
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();
}
Example #5
0
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());
    }
  }
}
Example #6
0
bool RunProcessAsAdmin(const QString &fullExecutablePath, const QStringList &params,
                       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
}