/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "CMakeSetupDialog.h"

#include <cm/memory>

#include <QCloseEvent>
#include <QCoreApplication>
#include <QDesktopServices>
#include <QDialogButtonBox>
#include <QDragEnterEvent>
#include <QFileDialog>
#include <QInputDialog>
#include <QKeySequence>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QMimeData>
#include <QProcessEnvironment>
#include <QProgressBar>
#include <QSettings>
#include <QShortcut>
#include <QStatusBar>
#include <QString>
#include <QUrl>
#include <QVector>

#ifdef QT_WINEXTRAS
#  include <QWinTaskbarButton>
#  include <QWinTaskbarProgress>
#endif

#include "QCMake.h"
#include "QCMakeCacheView.h"
#include "QCMakeSizeType.h"

#include "cmSystemTools.h"
#include "cmVersion.h"

#include "AddCacheEntry.h"
#include "EnvironmentDialog.h"
#include "FirstConfigure.h"
#include "RegexExplorer.h"
#include "WarningMessagesDialog.h"

void OpenReferenceManual(QString const& filename)
{
  QString urlFormat("https://cmake.org/cmake/help/v%1.%2/");
  QUrl url(urlFormat.arg(QString::number(cmVersion::GetMajorVersion()),
                         QString::number(cmVersion::GetMinorVersion())));

  if (!cmSystemTools::GetHTMLDoc().empty()) {
    url = QUrl::fromLocalFile(
      QDir(QString::fromStdString(cmSystemTools::GetHTMLDoc()))
        .filePath(filename));
  }

  QDesktopServices::openUrl(url);
}

namespace {
QString const PRESETS_DISABLED_TOOLTIP =
  "This option is disabled because there are no available presets in "
  "CMakePresets.json or CMakeUserPresets.json.";
}

QCMakeThread::QCMakeThread(QObject* p)
  : QThread(p)
{
}

QCMake* QCMakeThread::cmakeInstance() const
{
  return this->CMakeInstance.get();
}

void QCMakeThread::run()
{
  this->CMakeInstance = cm::make_unique<QCMake>();
  // emit that this cmake thread is ready for use
  emit this->cmakeInitialized();
  this->exec();
  this->CMakeInstance.reset();
}

CMakeSetupDialog::CMakeSetupDialog()
  : ExitAfterGenerate(true)
  , CacheModified(false)
  , ConfigureNeeded(true)
  , CurrentState(Interrupting)
{
  QString title = QString(tr("CMake %1"));
  title = title.arg(cmVersion::GetCMakeVersion());
  this->setWindowTitle(title);

  // create the GUI
  QSettings settings;
  settings.beginGroup("Settings/StartPath");
  restoreGeometry(settings.value("geometry").toByteArray());
  restoreState(settings.value("windowState").toByteArray());

  this->AddVariableNames =
    settings.value("AddVariableNames", QStringList("CMAKE_INSTALL_PREFIX"))
      .toStringList();
  this->AddVariableTypes =
    settings.value("AddVariableTypes", QStringList("PATH")).toStringList();

  QWidget* cont = new QWidget(this);
  this->setupUi(cont);
  this->Splitter->setStretchFactor(0, 3);
  this->Splitter->setStretchFactor(1, 1);
  this->setCentralWidget(cont);
  this->ProgressBar->reset();
  this->RemoveEntry->setEnabled(false);
  this->AddEntry->setEnabled(false);
  this->Preset->setStatusTip(PRESETS_DISABLED_TOOLTIP);

  QByteArray p = settings.value("SplitterSizes").toByteArray();
  this->Splitter->restoreState(p);

  bool groupView = settings.value("GroupView", false).toBool();
  this->setGroupedView(groupView);
  this->groupedCheck->setCheckState(groupView ? Qt::Checked : Qt::Unchecked);

  bool advancedView = settings.value("AdvancedView", false).toBool();
  this->setAdvancedView(advancedView);
  this->advancedCheck->setCheckState(advancedView ? Qt::Checked
                                                  : Qt::Unchecked);

  QMenu* FileMenu = this->menuBar()->addMenu(tr("&File"));
  this->ReloadCacheAction = FileMenu->addAction(tr("&Reload Cache"));
  QObject::connect(this->ReloadCacheAction, &QAction::triggered, this,
                   &CMakeSetupDialog::doReloadCache);
  this->DeleteCacheAction = FileMenu->addAction(tr("&Delete Cache"));
  QObject::connect(this->DeleteCacheAction, &QAction::triggered, this,
                   &CMakeSetupDialog::doDeleteCache);
  this->ExitAction = FileMenu->addAction(tr("E&xit"));
  QObject::connect(this->ExitAction, &QAction::triggered, this,
                   &CMakeSetupDialog::close);
  this->ExitAction->setShortcut(QKeySequence::Quit);

  QMenu* ToolsMenu = this->menuBar()->addMenu(tr("&Tools"));
  this->ConfigureAction = ToolsMenu->addAction(tr("&Configure"));
  QObject::connect(this->ConfigureAction, &QAction::triggered, this,
                   &CMakeSetupDialog::doConfigure);
  // prevent merging with Preferences menu item on macOS
  this->ConfigureAction->setMenuRole(QAction::NoRole);
  this->GenerateAction = ToolsMenu->addAction(tr("&Generate"));
  QObject::connect(this->GenerateAction, &QAction::triggered, this,
                   &CMakeSetupDialog::doGenerate);
  auto* a = ToolsMenu->addAction(tr("&Show My Changes"));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::showUserChanges);
#if defined(Q_WS_MAC) || defined(Q_OS_MAC)
  this->InstallForCommandLineAction =
    ToolsMenu->addAction(tr("&How to Install For Command Line Use"));
  QObject::connect(this->InstallForCommandLineAction, &QAction::triggered,
                   this, &CMakeSetupDialog::doInstallForCommandLine);
#endif
  ToolsMenu->addSeparator();
  a = ToolsMenu->addAction(tr("Regular Expression Explorer..."));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doRegexExplorerDialog);
  ToolsMenu->addSeparator();
  a = ToolsMenu->addAction(tr("&Find in Output..."));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doOutputFindDialog);
  a->setShortcut(QKeySequence::Find);
  a = ToolsMenu->addAction(tr("Find Next"));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doOutputFindNext);
  a->setShortcut(QKeySequence::FindNext);
  a = ToolsMenu->addAction(tr("Find Previous"));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doOutputFindPrev);
  a->setShortcut(QKeySequence::FindPrevious);
  a = ToolsMenu->addAction(tr("Goto Next Error")); // in Visual Studio
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doOutputErrorNext);
  a->setShortcut(QKeySequence(Qt::Key_F8));
  auto* s = new QShortcut(this);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
  s->setKey(QKeySequence(Qt::CTRL + Qt::Key_Period));
#else
  s->setKey(QKeySequence(Qt::CTRL | Qt::Key_Period));
#endif
  QObject::connect(s, &QShortcut::activated, this,
                   &CMakeSetupDialog::doOutputErrorNext); // in Eclipse

  QMenu* OptionsMenu = this->menuBar()->addMenu(tr("&Options"));
  a = OptionsMenu->addAction(tr("Warning Messages..."));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doWarningMessagesDialog);
  this->WarnUninitializedAction =
    OptionsMenu->addAction(tr("&Warn Uninitialized (--warn-uninitialized)"));
  this->WarnUninitializedAction->setCheckable(true);

  QAction* debugAction = OptionsMenu->addAction(tr("&Debug Output"));
  debugAction->setCheckable(true);
  QObject::connect(debugAction, &QAction::toggled, this,
                   &CMakeSetupDialog::setDebugOutput);

  OptionsMenu->addSeparator();
  a = OptionsMenu->addAction(tr("&Expand Grouped Entries"));
  QObject::connect(a, &QAction::triggered, this->CacheValues,
                   &QCMakeCacheView::expandAll);
  a = OptionsMenu->addAction(tr("&Collapse Grouped Entries"));
  QObject::connect(a, &QAction::triggered, this->CacheValues,
                   &QCMakeCacheView::collapseAll);

  QMenu* HelpMenu = this->menuBar()->addMenu(tr("&Help"));
  a = HelpMenu->addAction(tr("Help"));
  QObject::connect(a, &QAction::triggered, this, &CMakeSetupDialog::doHelp);
  a->setShortcut(QKeySequence::HelpContents);
  a = HelpMenu->addAction(tr("CMake Reference Manual"));
  QObject::connect(a, &QAction::triggered, this,
                   [] { OpenReferenceManual("index.html"); });
  a = HelpMenu->addAction(tr("About"));
  QObject::connect(a, &QAction::triggered, this, &CMakeSetupDialog::doAbout);

  this->setAcceptDrops(true);

  // get the saved binary directories
  QStringList buildPaths = this->loadBuildPaths();
  this->BinaryDirectory->addItems(buildPaths);

  this->BinaryDirectory->setCompleter(new QCMakeFileCompleter(this, true));
  this->SourceDirectory->setCompleter(new QCMakeFileCompleter(this, true));

  // fixed pitch font in output window
  QFont outputFont("Courier New");
  outputFont.setStyleHint(QFont::Monospace);
  this->Output->setFont(outputFont);
  this->ErrorFormat.setForeground(QBrush(Qt::red));

  this->Output->setContextMenuPolicy(Qt::CustomContextMenu);
  connect(this->Output, &QTextEdit::customContextMenuRequested, this,
          &CMakeSetupDialog::doOutputContextMenu);

  // disable open project button
  this->OpenProjectButton->setDisabled(true);

  // start the cmake worker thread
  this->CMakeThread = new QCMakeThread(this);
  QObject::connect(this->CMakeThread, &QCMakeThread::cmakeInitialized, this,
                   &CMakeSetupDialog::initialize, Qt::QueuedConnection);
  this->CMakeThread->start();

  this->enterState(ReadyConfigure);

  ProgressOffset = 0.0;
  ProgressFactor = 1.0;
}

void CMakeSetupDialog::initialize()
{
  // now the cmake worker thread is running, lets make our connections to it
  QObject::connect(this->CMakeThread->cmakeInstance(),
                   &QCMake::propertiesChanged, this->CacheValues->cacheModel(),
                   &QCMakeCacheModel::setProperties);

  QObject::connect(this->ConfigureButton, &QAbstractButton::clicked, this,
                   &CMakeSetupDialog::doConfigure);

  QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::configureDone,
                   this, &CMakeSetupDialog::exitLoop);
  QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::generateDone,
                   this, &CMakeSetupDialog::exitLoop);

  QObject::connect(this->GenerateButton, &QAbstractButton::clicked, this,
                   &CMakeSetupDialog::doGenerate);
  QObject::connect(this->OpenProjectButton, &QAbstractButton::clicked, this,
                   &CMakeSetupDialog::doOpenProject);

  QObject::connect(this->BrowseSourceDirectoryButton,
                   &QAbstractButton::clicked, this,
                   &CMakeSetupDialog::doSourceBrowse);
  QObject::connect(this->BrowseBinaryDirectoryButton,
                   &QAbstractButton::clicked, this,
                   &CMakeSetupDialog::doBinaryBrowse);

  QObject::connect(this->BinaryDirectory, &QComboBox::editTextChanged, this,
                   &CMakeSetupDialog::onBinaryDirectoryChanged);
  QObject::connect(this->SourceDirectory, &QLineEdit::textChanged, this,
                   &CMakeSetupDialog::onSourceDirectoryChanged);
  QObject::connect(this->Preset, &QCMakePresetComboBox::presetChanged, this,
                   &CMakeSetupDialog::onBuildPresetChanged);

  QObject::connect(this->CMakeThread->cmakeInstance(),
                   &QCMake::sourceDirChanged, this,
                   &CMakeSetupDialog::updateSourceDirectory);
  QObject::connect(this->CMakeThread->cmakeInstance(),
                   &QCMake::binaryDirChanged, this,
                   &CMakeSetupDialog::updateBinaryDirectory);
  QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::presetsChanged,
                   this, &CMakeSetupDialog::updatePresets);
  QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::presetChanged,
                   this, &CMakeSetupDialog::updatePreset);
  QObject::connect(this->CMakeThread->cmakeInstance(),
                   &QCMake::presetLoadError, this,
                   &CMakeSetupDialog::showPresetLoadError);

  QObject::connect(this->CMakeThread->cmakeInstance(),
                   &QCMake::progressChanged, this,
                   &CMakeSetupDialog::showProgress);

  QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::errorMessage,
                   this, &CMakeSetupDialog::error);

  QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::outputMessage,
                   this, &CMakeSetupDialog::message);

  QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::openPossible,
                   this->OpenProjectButton, &CMakeSetupDialog::setEnabled);

  QObject::connect(this->groupedCheck, &QCheckBox::toggled, this,
                   &CMakeSetupDialog::setGroupedView);
  QObject::connect(this->advancedCheck, &QCheckBox::toggled, this,
                   &CMakeSetupDialog::setAdvancedView);
  QObject::connect(this->Search, &QLineEdit::textChanged, this,
                   &CMakeSetupDialog::setSearchFilter);

  QObject::connect(this->CMakeThread->cmakeInstance(),
                   &QCMake::generatorChanged, this,
                   &CMakeSetupDialog::updateGeneratorLabel);
  this->updateGeneratorLabel(QString());

  QObject::connect(this->CacheValues->cacheModel(),
                   &QCMakeCacheModel::dataChanged, this,
                   &CMakeSetupDialog::setCacheModified);

  QObject::connect(this->CacheValues->selectionModel(),
                   &QItemSelectionModel::selectionChanged, this,
                   &CMakeSetupDialog::selectionChanged);
  QObject::connect(this->RemoveEntry, &QAbstractButton::clicked, this,
                   &CMakeSetupDialog::removeSelectedCacheEntries);
  QObject::connect(this->AddEntry, &QAbstractButton::clicked, this,
                   &CMakeSetupDialog::addCacheEntry);

  QObject::connect(this->Environment, &QAbstractButton::clicked, this,
                   &CMakeSetupDialog::editEnvironment);

  QObject::connect(this->WarnUninitializedAction, &QAction::triggered,
                   this->CMakeThread->cmakeInstance(),
                   &QCMake::setWarnUninitializedMode);
  QObject::connect(this->CMakeThread->cmakeInstance(),
                   &QCMake::warnUninitializedModeChanged,
                   this->WarnUninitializedAction, &QAction::setChecked);

  if (!this->SourceDirectory->text().isEmpty() &&
      !this->DeferredPreset.isNull()) {
    this->onSourceDirectoryChanged(this->SourceDirectory->text());
    if (!this->BinaryDirectory->lineEdit()->text().isEmpty()) {
      this->onBinaryDirectoryChanged(
        this->BinaryDirectory->lineEdit()->text());
    }
  } else if (!this->SourceDirectory->text().isEmpty() ||
             !this->BinaryDirectory->lineEdit()->text().isEmpty()) {
    if (this->SourceDirectory->text().isEmpty() &&
        !cmSystemTools::FileIsFullPath(
          this->BinaryDirectory->lineEdit()->text().toStdString())) {
      // If the binary directory is relative, load the previous source path
      // from the config
      QSettings settings;
      settings.beginGroup("Settings/StartPath");
      QString srcDir = settings.value(QString("WhereSource")).toString();
      this->SourceDirectory->blockSignals(true);
      this->SourceDirectory->setText(srcDir);
      this->SourceDirectory->blockSignals(false);
    }
    this->onSourceDirectoryChanged(this->SourceDirectory->text());
    this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
  } else {
    this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
  }

#ifdef QT_WINEXTRAS
  this->TaskbarButton = new QWinTaskbarButton(this);
  this->TaskbarButton->setWindow(this->windowHandle());
#endif
}

CMakeSetupDialog::~CMakeSetupDialog()
{
  QSettings settings;
  settings.beginGroup("Settings/StartPath");
  settings.setValue("windowState", QVariant(saveState()));
  settings.setValue("geometry", QVariant(saveGeometry()));
  settings.setValue("SplitterSizes", this->Splitter->saveState());

  // wait for thread to stop
  this->CMakeThread->quit();
  this->CMakeThread->wait();
}

bool CMakeSetupDialog::prepareConfigure()
{
  // make sure build directory exists
  QString bindir = this->CMakeThread->cmakeInstance()->binaryDirectory();
  QDir dir(bindir);
  if (!dir.exists()) {
    QString msg = tr("Build directory does not exist, "
                     "should I create it?\n\n"
                     "Directory: ");
    msg += bindir;
    QString title = tr("Create Directory");
    QMessageBox::StandardButton btn;
    btn = QMessageBox::information(this, title, msg,
                                   QMessageBox::Yes | QMessageBox::No);
    if (btn == QMessageBox::No) {
      return false;
    }
    if (!dir.mkpath(".")) {
      QMessageBox::information(
        this, tr("Create Directory Failed"),
        QString(tr("Failed to create directory %1")).arg(dir.path()),
        QMessageBox::Ok);

      return false;
    }
  }

  // if no generator, prompt for it and other setup stuff
  if (this->CMakeThread->cmakeInstance()->generator().isEmpty()) {
    if (!this->setupFirstConfigure()) {
      return false;
    }
  }

  // remember paths
  this->addBinaryPath(
    this->CMakeThread->cmakeInstance()->relativeBinaryDirectory());
  QSettings settings;
  settings.beginGroup("Settings/StartPath");
  settings.setValue("WhereSource",
                    this->CMakeThread->cmakeInstance()->sourceDirectory());

  return true;
}

void CMakeSetupDialog::exitLoop(int err)
{
  this->LocalLoop.exit(err);
}

void CMakeSetupDialog::doConfigure()
{
  if (this->CurrentState == Configuring) {
    // stop configure
    doInterrupt();
    return;
  }

  if (!prepareConfigure()) {
    return;
  }

  this->enterState(Configuring);

  bool ret = doConfigureInternal();

  if (ret) {
    this->ConfigureNeeded = false;
  }

  if (ret && !this->CacheValues->cacheModel()->newPropertyCount()) {
    this->enterState(ReadyGenerate);
  } else {
    this->enterState(ReadyConfigure);
    this->CacheValues->scrollToTop();
  }
  this->ProgressBar->reset();

#ifdef QT_WINEXTRAS
  this->TaskbarButton->progress()->reset();
#endif
}

bool CMakeSetupDialog::doConfigureInternal()
{
  this->Output->clear();
  this->CacheValues->selectionModel()->clear();

  QMetaObject::invokeMethod(
    this->CMakeThread->cmakeInstance(), "setProperties", Qt::QueuedConnection,
    Q_ARG(QCMakePropertyList, this->CacheValues->cacheModel()->properties()));
  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "configure",
                            Qt::QueuedConnection);

  int err = this->LocalLoop.exec();

  if (err != 0) {
    QMessageBox::critical(
      this, tr("Error"),
      tr("Error in configuration process, project files may be invalid"),
      QMessageBox::Ok);
  }

  return 0 == err;
}

void CMakeSetupDialog::doInstallForCommandLine()
{
  QString title = tr("How to Install For Command Line Use");
  QString msg = tr("One may add CMake to the PATH:\n"
                   "\n"
                   " PATH=\"%1\":\"$PATH\"\n"
                   "\n"
                   "Or, to install symlinks to '/usr/local/bin', run:\n"
                   "\n"
                   " sudo \"%2\" --install\n"
                   "\n"
                   "Or, to install symlinks to another directory, run:\n"
                   "\n"
                   " sudo \"%3\" --install=/path/to/bin\n");
  msg = msg.arg(
    cmSystemTools::GetFilenamePath(cmSystemTools::GetCMakeCommand()).c_str());
  msg = msg.arg(cmSystemTools::GetCMakeGUICommand().c_str());
  msg = msg.arg(cmSystemTools::GetCMakeGUICommand().c_str());

  QDialog dialog;
  dialog.setWindowTitle(title);
  QVBoxLayout* l = new QVBoxLayout(&dialog);
  QLabel* lab = new QLabel(&dialog);
  l->addWidget(lab);
  lab->setText(msg);
  lab->setWordWrap(false);
  lab->setTextInteractionFlags(Qt::TextSelectableByMouse);
  QDialogButtonBox* btns =
    new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog);
  QObject::connect(btns, &QDialogButtonBox::accepted, &dialog,
                   &QDialog::accept);
  l->addWidget(btns);
  dialog.exec();
}

bool CMakeSetupDialog::doGenerateInternal()
{
  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "generate",
                            Qt::QueuedConnection);

  int err = this->LocalLoop.exec();

  if (err != 0) {
    QMessageBox::critical(
      this, tr("Error"),
      tr("Error in generation process, project files may be invalid"),
      QMessageBox::Ok);
  }

  return 0 == err;
}

void CMakeSetupDialog::doGenerate()
{
  if (this->CurrentState == Generating) {
    // stop generate
    doInterrupt();
    return;
  }

  // see if we need to configure
  // we'll need to configure if:
  //   the configure step hasn't been done yet
  //   generate was the last step done
  if (this->ConfigureNeeded) {
    if (!prepareConfigure()) {
      return;
    }
  }

  this->enterState(Generating);

  bool config_passed = true;
  if (this->ConfigureNeeded) {
    this->CacheValues->cacheModel()->setShowNewProperties(false);
    this->ProgressFactor = 0.5;
    config_passed = doConfigureInternal();
    this->ProgressOffset = 0.5;
  }

  if (config_passed) {
    doGenerateInternal();
  }

  this->ProgressOffset = 0.0;
  this->ProgressFactor = 1.0;
  this->CacheValues->cacheModel()->setShowNewProperties(true);

  this->enterState(ReadyConfigure);
  this->ProgressBar->reset();
#ifdef QT_WINEXTRAS
  this->TaskbarButton->progress()->reset();
#endif

  this->ConfigureNeeded = true;
}

void CMakeSetupDialog::doOpenProject()
{
  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "open",
                            Qt::QueuedConnection);
}

void CMakeSetupDialog::closeEvent(QCloseEvent* e)
{
  // prompt for close if there are unsaved changes, and we're not busy
  if (this->CacheModified) {
    QString msg = tr("You have changed options but not rebuilt, "
                     "are you sure you want to exit?");
    QString title = tr("Confirm Exit");
    QMessageBox::StandardButton btn;
    btn = QMessageBox::critical(this, title, msg,
                                QMessageBox::Yes | QMessageBox::No);
    if (btn == QMessageBox::No) {
      e->ignore();
    }
  }

  // don't close if we're busy, unless the user really wants to
  if (this->CurrentState == Configuring) {
    QString msg =
      tr("You are in the middle of a Configure.\n"
         "If you Exit now the configure information will be lost.\n"
         "Are you sure you want to Exit?");
    QString title = tr("Confirm Exit");
    QMessageBox::StandardButton btn;
    btn = QMessageBox::critical(this, title, msg,
                                QMessageBox::Yes | QMessageBox::No);
    if (btn == QMessageBox::No) {
      e->ignore();
    } else {
      this->doInterrupt();
    }
  }

  // let the generate finish
  if (this->CurrentState == Generating) {
    e->ignore();
  }
}

void CMakeSetupDialog::doHelp()
{
  QString msg = tr(
    "CMake is used to configure and generate build files for "
    "software projects.   The basic steps for configuring a project are as "
    "follows:\r\n\r\n1. Select the source directory for the project.  This "
    "should "
    "contain the CMakeLists.txt files for the project.\r\n\r\n2. Select the "
    "build "
    "directory for the project.   This is the directory where the project "
    "will be "
    "built.  It can be the same or a different directory than the source "
    "directory.   For easy clean up, a separate build directory is "
    "recommended. "
    "CMake will create the directory if it does not exist.\r\n\r\n3. Once the "
    "source and binary directories are selected, it is time to press the "
    "Configure button.  This will cause CMake to read all of the input files "
    "and "
    "discover all the variables used by the project.   The first time a "
    "variable "
    "is displayed it will be in Red.   Users should inspect red variables "
    "making "
    "sure the values are correct.   For some projects the Configure process "
    "can "
    "be iterative, so continue to press the Configure button until there are "
    "no "
    "longer red entries.\r\n\r\n4. Once there are no longer red entries, you "
    "should click the Generate button.  This will write the build files to "
    "the build "
    "directory.");

  QDialog dialog;
  QFontMetrics met(this->font());
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
  int msgWidth = met.horizontalAdvance(msg);
#else
  int msgWidth = met.width(msg);
#endif
  dialog.setMinimumSize(msgWidth / 15, 20);
  dialog.setWindowTitle(tr("Help"));
  QVBoxLayout* l = new QVBoxLayout(&dialog);
  QLabel* lab = new QLabel(&dialog);
  lab->setText(msg);
  lab->setWordWrap(true);
  QDialogButtonBox* btns =
    new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog);
  QObject::connect(btns, &QDialogButtonBox::accepted, &dialog,
                   &QDialog::accept);
  l->addWidget(lab);
  l->addWidget(btns);
  dialog.exec();
}

void CMakeSetupDialog::doInterrupt()
{
  this->enterState(Interrupting);
  this->CMakeThread->cmakeInstance()->interrupt();
}

void CMakeSetupDialog::doSourceBrowse()
{
  QString dir = QFileDialog::getExistingDirectory(
    this, tr("Enter Path to Source"), this->SourceDirectory->text(),
    QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
  if (!dir.isEmpty()) {
    this->setSourceDirectory(dir);
  }
}

void CMakeSetupDialog::updateSourceDirectory(QString const& dir)
{
  if (this->SourceDirectory->text() != dir) {
    this->SourceDirectory->blockSignals(true);
    this->SourceDirectory->setText(dir);
    this->SourceDirectory->blockSignals(false);
  }
}

void CMakeSetupDialog::updateBinaryDirectory(QString const& dir)
{
  if (this->BinaryDirectory->currentText() != dir) {
    this->BinaryDirectory->blockSignals(true);
    this->BinaryDirectory->setEditText(dir);
    this->BinaryDirectory->blockSignals(false);
  }
}

void CMakeSetupDialog::updatePresets(QVector<QCMakePreset> const& presets)
{
  if (this->Preset->presets() != presets) {
    this->Preset->blockSignals(true);
    this->Preset->setPresets(presets);
    this->Preset->blockSignals(false);
  }

  this->Preset->setDisabled(presets.isEmpty());
  this->Preset->setToolTip(presets.isEmpty() ? PRESETS_DISABLED_TOOLTIP : "");

  if (!this->DeferredPreset.isNull()) {
    this->Preset->setPresetName(this->DeferredPreset);
    this->DeferredPreset = QString{};
  }
}

void CMakeSetupDialog::updatePreset(QString const& name)
{
  if (this->Preset->presetName() != name) {
    this->Preset->blockSignals(true);
    this->Preset->setPresetName(name);
    this->Preset->blockSignals(false);
  }
}

void CMakeSetupDialog::showPresetLoadError(QString const& dir,
                                           QString const& message)
{
  QMessageBox::warning(
    this, "Error Reading CMake Presets",
    QString("Could not read presets from %1: %2").arg(dir, message));
}

void CMakeSetupDialog::doBinaryBrowse()
{
  QString abs_path = this->BinaryDirectory->currentText();
  if (!cmSystemTools::FileIsFullPath(abs_path.toStdString())) {
    if (!this->SourceDirectory->text().endsWith("/")) {
      abs_path = "/" + abs_path;
    }
    abs_path = this->SourceDirectory->text() + abs_path;
  }
  QString dir = QFileDialog::getExistingDirectory(
    this, tr("Enter Path to Build"), abs_path,
    QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
  if (!dir.isEmpty() && dir != this->BinaryDirectory->currentText()) {
    this->setBinaryDirectory(dir);
  }
}

void CMakeSetupDialog::setBinaryDirectory(QString const& dir)
{
  this->BinaryDirectory->setEditText(dir);
}

void CMakeSetupDialog::setStartupBinaryDirectory(bool startup)
{
  this->StartupBinaryDirectory = startup;
}

void CMakeSetupDialog::onSourceDirectoryChanged(QString const& dir)
{
  this->Output->clear();
  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
                            "setSourceDirectory", Qt::QueuedConnection,
                            Q_ARG(QString, dir));
}

void CMakeSetupDialog::onBinaryDirectoryChanged(QString const& dir)
{
  QString title = QString(tr("CMake %1 - %2"));
  title = title.arg(cmVersion::GetCMakeVersion());
  title = title.arg(dir);
  this->setWindowTitle(title);

  this->CacheModified = false;
  this->CacheValues->cacheModel()->clear();
  qobject_cast<QCMakeCacheModelDelegate*>(this->CacheValues->itemDelegate())
    ->clearChanges();
  this->Output->clear();
  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
                            "setBinaryDirectory", Qt::QueuedConnection,
                            Q_ARG(QString, dir));
}

void CMakeSetupDialog::onBuildPresetChanged(QString const& name)
{
  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "setPreset",
                            Qt::QueuedConnection, Q_ARG(QString, name),
                            Q_ARG(bool, !this->StartupBinaryDirectory));
  this->StartupBinaryDirectory = false;
}

void CMakeSetupDialog::setSourceDirectory(QString const& dir)
{
  this->SourceDirectory->setText(dir);
}

void CMakeSetupDialog::setDeferredPreset(QString const& preset)
{
  this->DeferredPreset = preset;
}

void CMakeSetupDialog::showProgress(QString const& /*msg*/, float percent)
{
  percent = (percent * ProgressFactor) + ProgressOffset;
  this->ProgressBar->setValue(qRound(percent * 100));

#ifdef QT_WINEXTRAS
  QWinTaskbarProgress* progress = this->TaskbarButton->progress();
  progress->setVisible(true);
  progress->setValue(qRound(percent * 100));
#endif
}

void CMakeSetupDialog::error(QString const& msg)
{
  this->Output->setCurrentCharFormat(this->ErrorFormat);
  // QTextEdit will terminate the msg with a ParagraphSeparator, but it also
  // replaces
  // all newlines with ParagraphSeparators. By replacing the newlines by
  // ourself, one
  // error msg will be one paragraph.
  QString paragraph(msg);
  paragraph.replace(QLatin1Char('\n'), QChar::LineSeparator);
  this->Output->append(paragraph);
}

void CMakeSetupDialog::message(QString const& msg)
{
  this->Output->setCurrentCharFormat(this->MessageFormat);
  this->Output->append(msg);
}

void CMakeSetupDialog::setEnabledState(bool enabled)
{
  // disable parts of the GUI during configure/generate
  this->CacheValues->cacheModel()->setEditEnabled(enabled);
  this->SourceDirectory->setEnabled(enabled);
  this->BrowseSourceDirectoryButton->setEnabled(enabled);
  this->Preset->setEnabled(enabled && !this->Preset->presets().isEmpty());
  this->BinaryDirectory->setEnabled(enabled);
  this->BrowseBinaryDirectoryButton->setEnabled(enabled);
  this->ReloadCacheAction->setEnabled(enabled);
  this->DeleteCacheAction->setEnabled(enabled);
  this->ExitAction->setEnabled(enabled);
  this->ConfigureAction->setEnabled(enabled);
  this->AddEntry->setEnabled(enabled);
  this->RemoveEntry->setEnabled(false); // let selection re-enable it
  this->Environment->setEnabled(enabled);
}

bool CMakeSetupDialog::setupFirstConfigure()
{
  FirstConfigure dialog;

  // initialize dialog and restore saved settings

  // add generators
  dialog.setGenerators(
    this->CMakeThread->cmakeInstance()->availableGenerators());

  // restore from settings
  dialog.loadFromSettings();

  auto presetData = this->Preset->currentData();
  if (presetData.isValid()) {
    auto preset = presetData.value<QCMakePreset>();
    dialog.setCurrentGenerator(preset.generator);
    if (preset.setArchitecture) {
      dialog.setPlatform(preset.architecture);
    }
    if (preset.setToolset) {
      dialog.setToolset(preset.toolset);
    }
    dialog.setCompilerOption(CompilerOption::DefaultPreset);
  }

  if (dialog.exec() == QDialog::Accepted) {
    dialog.saveToSettings();
    this->CMakeThread->cmakeInstance()->setGenerator(dialog.getGenerator());
    this->CMakeThread->cmakeInstance()->setPlatform(dialog.getPlatform());
    this->CMakeThread->cmakeInstance()->setToolset(dialog.getToolset());

    QCMakeCacheModel* m = this->CacheValues->cacheModel();

    if (dialog.compilerSetup()) {
      QString fortranCompiler = dialog.getFortranCompiler();
      if (!fortranCompiler.isEmpty()) {
        m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_Fortran_COMPILER",
                          "Fortran compiler.", fortranCompiler, false);
      }
      QString cxxCompiler = dialog.getCXXCompiler();
      if (!cxxCompiler.isEmpty()) {
        m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_CXX_COMPILER",
                          "CXX compiler.", cxxCompiler, false);
      }

      QString cCompiler = dialog.getCCompiler();
      if (!cCompiler.isEmpty()) {
        m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_C_COMPILER",
                          "C compiler.", cCompiler, false);
      }
    } else if (dialog.crossCompilerSetup()) {
      QString fortranCompiler = dialog.getFortranCompiler();
      if (!fortranCompiler.isEmpty()) {
        m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_Fortran_COMPILER",
                          "Fortran compiler.", fortranCompiler, false);
      }

      QString mode = dialog.getCrossIncludeMode();
      m->insertProperty(QCMakeProperty::STRING,
                        "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE",
                        tr("CMake Find Include Mode"), mode, false);
      mode = dialog.getCrossLibraryMode();
      m->insertProperty(QCMakeProperty::STRING,
                        "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY",
                        tr("CMake Find Library Mode"), mode, false);
      mode = dialog.getCrossProgramMode();
      m->insertProperty(QCMakeProperty::STRING,
                        "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM",
                        tr("CMake Find Program Mode"), mode, false);

      QString rootPath = dialog.getCrossRoot();
      m->insertProperty(QCMakeProperty::PATH, "CMAKE_FIND_ROOT_PATH",
                        tr("CMake Find Root Path"), rootPath, false);

      QString systemName = dialog.getSystemName();
      m->insertProperty(QCMakeProperty::STRING, "CMAKE_SYSTEM_NAME",
                        tr("CMake System Name"), systemName, false);
      QString systemVersion = dialog.getSystemVersion();
      m->insertProperty(QCMakeProperty::STRING, "CMAKE_SYSTEM_VERSION",
                        tr("CMake System Version"), systemVersion, false);
      QString systemProcessor = dialog.getSystemProcessor();
      m->insertProperty(QCMakeProperty::STRING, "CMAKE_SYSTEM_PROCESSOR",
                        tr("CMake System Processor"), systemProcessor, false);
      QString cxxCompiler = dialog.getCXXCompiler();
      if (!cxxCompiler.isEmpty()) {
        m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_CXX_COMPILER",
                          tr("CXX compiler."), cxxCompiler, false);
      }
      QString cCompiler = dialog.getCCompiler();
      if (!cCompiler.isEmpty()) {
        m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_C_COMPILER",
                          tr("C compiler."), cCompiler, false);
      }
    } else if (dialog.crossCompilerToolChainFile()) {
      QString toolchainFile = dialog.getCrossCompilerToolChainFile();
      m->insertProperty(QCMakeProperty::FILEPATH, "CMAKE_TOOLCHAIN_FILE",
                        tr("Cross Compile ToolChain File"), toolchainFile,
                        false);
    }
    return true;
  }

  return false;
}

void CMakeSetupDialog::updateGeneratorLabel(QString const& gen)
{
  QString str = tr("Current Generator: ");
  if (gen.isEmpty()) {
    str += tr("None");
  } else {
    str += gen;
  }
  this->Generator->setText(str);
}

void CMakeSetupDialog::doReloadCache()
{
  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "reloadCache",
                            Qt::QueuedConnection);
}

void CMakeSetupDialog::doDeleteCache()
{
  QString title = tr("Delete Cache");
  QString msg = tr("Are you sure you want to delete the cache?");
  QMessageBox::StandardButton btn;
  btn = QMessageBox::information(this, title, msg,
                                 QMessageBox::Yes | QMessageBox::No);
  if (btn == QMessageBox::No) {
    return;
  }
  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "deleteCache",
                            Qt::QueuedConnection);
}

void CMakeSetupDialog::doAbout()
{
  QString msg = tr(
    "CMake %1 (cmake.org).\n"
    "CMake suite maintained and supported by Kitware (kitware.com/cmake).\n"
    "Distributed under terms of the BSD 3-Clause License.\n"
    "\n"
    "CMake GUI maintained by csimsoft,\n"
    "built using Qt %2 (qt-project.org).\n"
#ifdef USE_LGPL
    "\n"
    "The Qt Toolkit is Copyright (C) The Qt Company Ltd.\n"
    "Qt is licensed under terms of the GNU LGPLv" USE_LGPL ", available at:\n"
    " \"%3\""
#endif
  );
  msg = msg.arg(cmVersion::GetCMakeVersion());
  msg = msg.arg(qVersion());
#ifdef USE_LGPL
  std::string lgpl =
    cmSystemTools::GetCMakeRoot() + "/Licenses/LGPLv" USE_LGPL ".txt";
  msg = msg.arg(lgpl.c_str());
#endif

  QDialog dialog;
  dialog.setWindowTitle(tr("About"));
  QVBoxLayout* l = new QVBoxLayout(&dialog);
  QLabel* lab = new QLabel(&dialog);
  l->addWidget(lab);
  lab->setText(msg);
  lab->setWordWrap(true);
  QDialogButtonBox* btns =
    new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog);
  QObject::connect(btns, &QDialogButtonBox::accepted, &dialog,
                   &QDialog::accept);
  l->addWidget(btns);
  dialog.exec();
}

void CMakeSetupDialog::setExitAfterGenerate(bool b)
{
  this->ExitAfterGenerate = b;
}

void CMakeSetupDialog::addBinaryPath(QString const& path)
{
  QString cleanpath = QDir::cleanPath(path);

  // update UI
  this->BinaryDirectory->blockSignals(true);
  int idx = this->BinaryDirectory->findText(cleanpath);
  if (idx != -1) {
    this->BinaryDirectory->removeItem(idx);
  }
  this->BinaryDirectory->insertItem(0, cleanpath);
  this->BinaryDirectory->setCurrentIndex(0);
  this->BinaryDirectory->blockSignals(false);

  // save to registry
  QStringList buildPaths = this->loadBuildPaths();
  buildPaths.removeAll(cleanpath);
  buildPaths.prepend(cleanpath);
  this->saveBuildPaths(buildPaths);
}

void CMakeSetupDialog::dragEnterEvent(QDragEnterEvent* e)
{
  if (!(this->CurrentState == ReadyConfigure ||
        this->CurrentState == ReadyGenerate)) {
    e->ignore();
    return;
  }

  QMimeData const* dat = e->mimeData();
  QList<QUrl> urls = dat->urls();
  QString file = urls.count() ? urls[0].toLocalFile() : QString();
  if (!file.isEmpty() &&
      (file.endsWith("CMakeCache.txt", Qt::CaseInsensitive) ||
       file.endsWith("CMakeLists.txt", Qt::CaseInsensitive))) {
    e->accept();
  } else {
    e->ignore();
  }
}

void CMakeSetupDialog::dropEvent(QDropEvent* e)
{
  if (!(this->CurrentState == ReadyConfigure ||
        this->CurrentState == ReadyGenerate)) {
    return;
  }

  QMimeData const* dat = e->mimeData();
  QList<QUrl> urls = dat->urls();
  QString file = urls.count() ? urls[0].toLocalFile() : QString();
  if (file.endsWith("CMakeCache.txt", Qt::CaseInsensitive)) {
    QFileInfo info(file);
    if (this->CMakeThread->cmakeInstance()->binaryDirectory() !=
        info.absolutePath()) {
      this->setBinaryDirectory(info.absolutePath());
    }
  } else if (file.endsWith("CMakeLists.txt", Qt::CaseInsensitive)) {
    QFileInfo info(file);
    if (this->CMakeThread->cmakeInstance()->binaryDirectory() !=
        info.absolutePath()) {
      this->setSourceDirectory(info.absolutePath());
      this->setBinaryDirectory(info.absolutePath());
    }
  }
}

QStringList CMakeSetupDialog::loadBuildPaths()
{
  QSettings settings;
  settings.beginGroup("Settings/StartPath");

  QStringList buildPaths;
  for (int i = 0; i < 10; i++) {
    QString p = settings.value(QString("WhereBuild%1").arg(i)).toString();
    if (!p.isEmpty()) {
      buildPaths.append(p);
    }
  }
  return buildPaths;
}

void CMakeSetupDialog::saveBuildPaths(QStringList const& paths)
{
  QSettings settings;
  settings.beginGroup("Settings/StartPath");

  cm_qsizetype num = paths.count();
  if (num > 10) {
    num = 10;
  }

  for (cm_qsizetype i = 0; i < num; i++) {
    settings.setValue(QString("WhereBuild%1").arg(i), paths[i]);
  }
}

void CMakeSetupDialog::setCacheModified()
{
  this->CacheModified = true;
  this->ConfigureNeeded = true;
  this->enterState(ReadyConfigure);
}

void CMakeSetupDialog::removeSelectedCacheEntries()
{
  QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
  QList<QPersistentModelIndex> pidxs;
  foreach (QModelIndex const& i, idxs) {
    pidxs.append(i);
  }
  foreach (QPersistentModelIndex const& pi, pidxs) {
    this->CacheValues->model()->removeRow(pi.row(), pi.parent());
  }
}

void CMakeSetupDialog::selectionChanged()
{
  QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
  if (idxs.count() &&
      (this->CurrentState == ReadyConfigure ||
       this->CurrentState == ReadyGenerate)) {
    this->RemoveEntry->setEnabled(true);
  } else {
    this->RemoveEntry->setEnabled(false);
  }
}

void CMakeSetupDialog::enterState(CMakeSetupDialog::State s)
{
  if (s == this->CurrentState) {
    return;
  }

  this->CurrentState = s;

  if (s == Interrupting) {
    this->ConfigureButton->setEnabled(false);
    this->GenerateButton->setEnabled(false);
    this->OpenProjectButton->setEnabled(false);
  } else if (s == Configuring) {
    this->setEnabledState(false);
    this->GenerateButton->setEnabled(false);
    this->GenerateAction->setEnabled(false);
    this->OpenProjectButton->setEnabled(false);
    this->ConfigureButton->setText(tr("&Stop"));
  } else if (s == Generating) {
    this->CacheModified = false;
    this->setEnabledState(false);
    this->ConfigureButton->setEnabled(false);
    this->GenerateAction->setEnabled(false);
    this->OpenProjectButton->setEnabled(false);
    this->GenerateButton->setText(tr("&Stop"));
  } else if (s == ReadyConfigure || s == ReadyGenerate) {
    this->setEnabledState(true);
    this->GenerateButton->setEnabled(true);
    this->GenerateAction->setEnabled(true);
    this->ConfigureButton->setEnabled(true);
    this->ConfigureButton->setText(tr("&Configure"));
    this->GenerateButton->setText(tr("&Generate"));
  }
}

void CMakeSetupDialog::editEnvironment()
{
  EnvironmentDialog dialog(this->CMakeThread->cmakeInstance()->environment(),
                           this);
  if (dialog.exec() == QDialog::Accepted) {
    QMetaObject::invokeMethod(
      this->CMakeThread->cmakeInstance(), "setEnvironment",
      Q_ARG(QProcessEnvironment, dialog.environment()));
  }
}

void CMakeSetupDialog::addCacheEntry()
{
  QDialog dialog(this);
  dialog.resize(400, 200);
  dialog.setWindowTitle(tr("Add Cache Entry"));
  QVBoxLayout* l = new QVBoxLayout(&dialog);
  AddCacheEntry* w =
    new AddCacheEntry(&dialog, this->AddVariableNames, this->AddVariableTypes);
  QDialogButtonBox* btns = new QDialogButtonBox(
    QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
  QObject::connect(btns, &QDialogButtonBox::accepted, &dialog,
                   &QDialog::accept);
  QObject::connect(btns, &QDialogButtonBox::rejected, &dialog,
                   &QDialog::reject);
  l->addWidget(w);
  l->addStretch();
  l->addWidget(btns);
  if (QDialog::Accepted == dialog.exec()) {
    QCMakeCacheModel* m = this->CacheValues->cacheModel();
    m->insertProperty(w->type(), w->name(), w->description(), w->value(),
                      false);

    // only add variable names to the completion which are new
    if (!this->AddVariableNames.contains(w->name())) {
      this->AddVariableNames << w->name();
      this->AddVariableTypes << w->typeString();
      // limit to at most 100 completion items
      if (this->AddVariableNames.size() > 100) {
        this->AddVariableNames.removeFirst();
        this->AddVariableTypes.removeFirst();
      }
      // make sure CMAKE_INSTALL_PREFIX is always there
      if (!this->AddVariableNames.contains("CMAKE_INSTALL_PREFIX")) {
        this->AddVariableNames << "CMAKE_INSTALL_PREFIX";
        this->AddVariableTypes << "PATH";
      }
      QSettings settings;
      settings.beginGroup("Settings/StartPath");
      settings.setValue("AddVariableNames", this->AddVariableNames);
      settings.setValue("AddVariableTypes", this->AddVariableTypes);
    }
  }
}

void CMakeSetupDialog::startSearch()
{
  this->Search->setFocus(Qt::OtherFocusReason);
  this->Search->selectAll();
}

void CMakeSetupDialog::setDebugOutput(bool flag)
{
  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
                            "setDebugOutput", Qt::QueuedConnection,
                            Q_ARG(bool, flag));
}

void CMakeSetupDialog::setGroupedView(bool v)
{
  this->CacheValues->cacheModel()->setViewType(v ? QCMakeCacheModel::GroupView
                                                 : QCMakeCacheModel::FlatView);
  this->CacheValues->setRootIsDecorated(v);

  QSettings settings;
  settings.beginGroup("Settings/StartPath");
  settings.setValue("GroupView", v);
}

void CMakeSetupDialog::setAdvancedView(bool v)
{
  this->CacheValues->setShowAdvanced(v);
  QSettings settings;
  settings.beginGroup("Settings/StartPath");
  settings.setValue("AdvancedView", v);
}

void CMakeSetupDialog::showUserChanges()
{
  QSet<QCMakeProperty> changes =
    qobject_cast<QCMakeCacheModelDelegate*>(this->CacheValues->itemDelegate())
      ->changes();

  QDialog dialog(this);
  dialog.setWindowTitle(tr("My Changes"));
  dialog.resize(600, 400);
  QVBoxLayout* l = new QVBoxLayout(&dialog);
  QTextEdit* textedit = new QTextEdit(&dialog);
  textedit->setReadOnly(true);
  l->addWidget(textedit);
  QDialogButtonBox* btns =
    new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, &dialog);
  QObject::connect(btns, &QDialogButtonBox::rejected, &dialog,
                   &QDialog::accept);
  l->addWidget(btns);

  QString command;
  QString cache;

  foreach (QCMakeProperty const& prop, changes) {
    QString type;
    switch (prop.Type) {
      case QCMakeProperty::BOOL:
        type = "BOOL";
        break;
      case QCMakeProperty::PATH:
        type = "PATH";
        break;
      case QCMakeProperty::FILEPATH:
        type = "FILEPATH";
        break;
      case QCMakeProperty::STRING:
        type = "STRING";
        break;
    }
    QString value;
    if (prop.Type == QCMakeProperty::BOOL) {
      value = prop.Value.toBool() ? "1" : "0";
    } else {
      value = prop.Value.toString();
    }

    QString const line = QString("%1:%2=").arg(prop.Key, type);
    command += QString("-D%1\"%2\" ").arg(line, value);
    cache += QString("%1%2\n").arg(line, value);
  }

  textedit->append(tr("Commandline options:"));
  textedit->append(command);
  textedit->append("\n");
  textedit->append(tr("Cache file:"));
  textedit->append(cache);

  dialog.exec();
}

void CMakeSetupDialog::setSearchFilter(QString const& str)
{
  this->CacheValues->selectionModel()->clear();
  bool const valid = this->CacheValues->setSearchFilter(str);
  QtCMake::setSearchFilterColor(this->Search, valid);
}

void CMakeSetupDialog::doOutputContextMenu(QPoint pt)
{
  std::unique_ptr<QMenu> menu(this->Output->createStandardContextMenu());

  menu->addSeparator();
  auto* a = menu->addAction(tr("Find..."));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doOutputFindDialog);
  a->setShortcut(QKeySequence::Find);
  a = menu->addAction(tr("Find Next"));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doOutputFindNext);
  a->setShortcut(QKeySequence::FindNext);
  a = menu->addAction(tr("Find Previous"));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doOutputFindPrev);
  a->setShortcut(QKeySequence::FindPrevious);
  menu->addSeparator();
  a = menu->addAction(tr("Goto Next Error"));
  QObject::connect(a, &QAction::triggered, this,
                   &CMakeSetupDialog::doOutputErrorNext);
  a->setShortcut(QKeySequence(Qt::Key_F8));

  menu->exec(this->Output->mapToGlobal(pt));
}

void CMakeSetupDialog::doOutputFindDialog()
{
  QStringList strings(this->FindHistory);

  QString selection = this->Output->textCursor().selectedText();
  if (!selection.isEmpty() && !selection.contains(QChar::ParagraphSeparator) &&
      !selection.contains(QChar::LineSeparator)) {
    strings.push_front(selection);
  }

  bool ok;
  QString search = QInputDialog::getItem(this, tr("Find in Output"),
                                         tr("Find:"), strings, 0, true, &ok);
  if (ok && !search.isEmpty()) {
    if (!this->FindHistory.contains(search)) {
      this->FindHistory.push_front(search);
    }
    doOutputFindNext();
  }
}

void CMakeSetupDialog::doRegexExplorerDialog()
{
  RegexExplorer dialog(this);
  dialog.exec();
}

void CMakeSetupDialog::doOutputFindPrev()
{
  doOutputFindNext(false);
}

void CMakeSetupDialog::doOutputFindNext(bool directionForward)
{
  if (this->FindHistory.isEmpty()) {
    doOutputFindDialog(); // will re-call this function again
    return;
  }

  QString search = this->FindHistory.front();

  QTextCursor textCursor = this->Output->textCursor();
  QTextDocument* document = this->Output->document();
  QTextDocument::FindFlags flags;
  if (!directionForward) {
    flags |= QTextDocument::FindBackward;
  }

  textCursor = document->find(search, textCursor, flags);

  if (textCursor.isNull()) {
    // first search found nothing, wrap around and search again
    textCursor = this->Output->textCursor();
    textCursor.movePosition(directionForward ? QTextCursor::Start
                                             : QTextCursor::End);
    textCursor = document->find(search, textCursor, flags);
  }

  if (textCursor.hasSelection()) {
    this->Output->setTextCursor(textCursor);
  }
}

void CMakeSetupDialog::doOutputErrorNext()
{
  QTextCursor textCursor = this->Output->textCursor();
  bool atEnd = false;

  // move cursor out of current error-block
  if (textCursor.blockCharFormat() == this->ErrorFormat) {
    atEnd = !textCursor.movePosition(QTextCursor::NextBlock);
  }

  // move cursor to next error-block
  while (textCursor.blockCharFormat() != this->ErrorFormat && !atEnd) {
    atEnd = !textCursor.movePosition(QTextCursor::NextBlock);
  }

  if (atEnd) {
    // first search found nothing, wrap around and search again
    atEnd = !textCursor.movePosition(QTextCursor::Start);

    // move cursor to next error-block
    while (textCursor.blockCharFormat() != this->ErrorFormat && !atEnd) {
      atEnd = !textCursor.movePosition(QTextCursor::NextBlock);
    }
  }

  if (!atEnd) {
    textCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);

    QTextCharFormat selectionFormat;
    selectionFormat.setBackground(Qt::yellow);
    QTextEdit::ExtraSelection extraSelection = { textCursor, selectionFormat };
    this->Output->setExtraSelections(QList<QTextEdit::ExtraSelection>()
                                     << extraSelection);

    // make the whole error-block visible
    this->Output->setTextCursor(textCursor);

    // remove the selection to see the extraSelection
    textCursor.setPosition(textCursor.anchor());
    this->Output->setTextCursor(textCursor);
  }
}

void CMakeSetupDialog::doWarningMessagesDialog()
{
  WarningMessagesDialog dialog(this, this->CMakeThread->cmakeInstance());
  dialog.exec();
}
