ENH: Add cross compiling support in the GUI in the same dialog that prompts for
[cmake.git] / Source / QtDialog / CMakeSetupDialog.cxx
blob270f0612d7ea46782c251dfb67a368ef9c33efdd
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: CMakeSetupDialog.cxx,v $
5 Language: C++
6 Date: $Date: 2008-05-15 23:21:01 $
7 Version: $Revision: 1.51 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "CMakeSetupDialog.h"
19 #include <QFileDialog>
20 #include <QProgressBar>
21 #include <QMessageBox>
22 #include <QStatusBar>
23 #include <QToolButton>
24 #include <QDialogButtonBox>
25 #include <QCloseEvent>
26 #include <QCoreApplication>
27 #include <QSettings>
28 #include <QMenu>
29 #include <QMenuBar>
30 #include <QDragEnterEvent>
31 #include <QMimeData>
32 #include <QUrl>
33 #include <QShortcut>
34 #include <QMacInstallDialog.h>
36 #include "QCMake.h"
37 #include "QCMakeCacheView.h"
38 #include "AddCacheEntry.h"
39 #include "CMakeFirstConfigure.h"
41 QCMakeThread::QCMakeThread(QObject* p)
42 : QThread(p), CMakeInstance(NULL)
46 QCMake* QCMakeThread::cmakeInstance() const
48 return this->CMakeInstance;
51 void QCMakeThread::run()
53 this->CMakeInstance = new QCMake;
54 // emit that this cmake thread is ready for use
55 emit this->cmakeInitialized();
56 this->exec();
57 delete this->CMakeInstance;
58 this->CMakeInstance = NULL;
61 CMakeSetupDialog::CMakeSetupDialog()
62 : ExitAfterGenerate(true), CacheModified(false), CurrentState(Interrupting)
64 // create the GUI
65 QSettings settings;
66 settings.beginGroup("Settings/StartPath");
67 int h = settings.value("Height", 500).toInt();
68 int w = settings.value("Width", 700).toInt();
69 this->resize(w, h);
71 QWidget* cont = new QWidget(this);
72 this->setupUi(cont);
73 this->Splitter->setStretchFactor(0, 3);
74 this->Splitter->setStretchFactor(1, 1);
75 this->setCentralWidget(cont);
76 this->ProgressBar->reset();
77 this->RemoveEntry->setEnabled(false);
78 this->AddEntry->setEnabled(false);
80 QMenu* FileMenu = this->menuBar()->addMenu(tr("&File"));
81 this->ReloadCacheAction = FileMenu->addAction(tr("&Reload Cache"));
82 QObject::connect(this->ReloadCacheAction, SIGNAL(triggered(bool)),
83 this, SLOT(doReloadCache()));
84 this->DeleteCacheAction = FileMenu->addAction(tr("&Delete Cache"));
85 QObject::connect(this->DeleteCacheAction, SIGNAL(triggered(bool)),
86 this, SLOT(doDeleteCache()));
87 this->ExitAction = FileMenu->addAction(tr("E&xit"));
88 QObject::connect(this->ExitAction, SIGNAL(triggered(bool)),
89 this, SLOT(close()));
91 QMenu* ToolsMenu = this->menuBar()->addMenu(tr("&Tools"));
92 this->ConfigureAction = ToolsMenu->addAction(tr("&Configure"));
93 // prevent merging with Preferences menu item on Mac OS X
94 this->ConfigureAction->setMenuRole(QAction::NoRole);
95 QObject::connect(this->ConfigureAction, SIGNAL(triggered(bool)),
96 this, SLOT(doConfigure()));
97 this->GenerateAction = ToolsMenu->addAction(tr("&Generate"));
98 QObject::connect(this->GenerateAction, SIGNAL(triggered(bool)),
99 this, SLOT(doGenerate()));
100 #if defined(Q_WS_MAC)
101 this->InstallForCommandLineAction
102 = ToolsMenu->addAction(tr("&Install For Command Line Use"));
103 QObject::connect(this->InstallForCommandLineAction, SIGNAL(triggered(bool)),
104 this, SLOT(doInstallForCommandLine()));
105 #endif
106 QMenu* OptionsMenu = this->menuBar()->addMenu(tr("&Options"));
107 this->SuppressDevWarningsAction = OptionsMenu->addAction(tr("&Suppress dev Warnings (-Wno-dev)"));
108 this->SuppressDevWarningsAction->setCheckable(true);
110 QAction* debugAction = OptionsMenu->addAction(tr("&Debug Output"));
111 debugAction->setCheckable(true);
112 QObject::connect(debugAction, SIGNAL(toggled(bool)),
113 this, SLOT(setDebugOutput(bool)));
115 QMenu* HelpMenu = this->menuBar()->addMenu(tr("&Help"));
116 QAction* a = HelpMenu->addAction(tr("About"));
117 QObject::connect(a, SIGNAL(triggered(bool)),
118 this, SLOT(doAbout()));
119 a = HelpMenu->addAction(tr("Help"));
120 QObject::connect(a, SIGNAL(triggered(bool)),
121 this, SLOT(doHelp()));
123 QShortcut* filterShortcut = new QShortcut(QKeySequence::Find, this);
124 QObject::connect(filterShortcut, SIGNAL(activated()),
125 this, SLOT(startSearch()));
127 this->setAcceptDrops(true);
129 // get the saved binary directories
130 QStringList buildPaths = this->loadBuildPaths();
131 this->BinaryDirectory->addItems(buildPaths);
133 this->BinaryDirectory->setCompleter(new QCMakeFileCompleter(this, true));
134 this->SourceDirectory->setCompleter(new QCMakeFileCompleter(this, true));
136 // fixed pitch font in output window
137 QFont outputFont("Courier");
138 this->Output->setFont(outputFont);
139 this->ErrorFormat.setForeground(QBrush(Qt::red));
141 // start the cmake worker thread
142 this->CMakeThread = new QCMakeThread(this);
143 QObject::connect(this->CMakeThread, SIGNAL(cmakeInitialized()),
144 this, SLOT(initialize()), Qt::QueuedConnection);
145 this->CMakeThread->start();
147 this->enterState(ReadyConfigure);
150 void CMakeSetupDialog::initialize()
152 // now the cmake worker thread is running, lets make our connections to it
153 QObject::connect(this->CMakeThread->cmakeInstance(),
154 SIGNAL(propertiesChanged(const QCMakePropertyList&)),
155 this->CacheValues->cacheModel(),
156 SLOT(setProperties(const QCMakePropertyList&)));
158 QObject::connect(this->ConfigureButton, SIGNAL(clicked(bool)),
159 this, SLOT(doConfigure()));
160 QObject::connect(this->CMakeThread->cmakeInstance(),
161 SIGNAL(configureDone(int)),
162 this, SLOT(finishConfigure(int)));
163 QObject::connect(this->CMakeThread->cmakeInstance(),
164 SIGNAL(generateDone(int)),
165 this, SLOT(finishGenerate(int)));
167 QObject::connect(this->GenerateButton, SIGNAL(clicked(bool)),
168 this, SLOT(doGenerate()));
170 QObject::connect(this->BrowseSourceDirectoryButton, SIGNAL(clicked(bool)),
171 this, SLOT(doSourceBrowse()));
172 QObject::connect(this->BrowseBinaryDirectoryButton, SIGNAL(clicked(bool)),
173 this, SLOT(doBinaryBrowse()));
175 QObject::connect(this->BinaryDirectory, SIGNAL(editTextChanged(QString)),
176 this, SLOT(onBinaryDirectoryChanged(QString)));
177 QObject::connect(this->SourceDirectory, SIGNAL(textChanged(QString)),
178 this, SLOT(onSourceDirectoryChanged(QString)));
180 QObject::connect(this->CMakeThread->cmakeInstance(),
181 SIGNAL(sourceDirChanged(QString)),
182 this, SLOT(updateSourceDirectory(QString)));
183 QObject::connect(this->CMakeThread->cmakeInstance(),
184 SIGNAL(binaryDirChanged(QString)),
185 this, SLOT(updateBinaryDirectory(QString)));
187 QObject::connect(this->CMakeThread->cmakeInstance(),
188 SIGNAL(progressChanged(QString, float)),
189 this, SLOT(showProgress(QString,float)));
191 QObject::connect(this->CMakeThread->cmakeInstance(),
192 SIGNAL(errorMessage(QString)),
193 this, SLOT(error(QString)));
195 QObject::connect(this->CMakeThread->cmakeInstance(),
196 SIGNAL(outputMessage(QString)),
197 this, SLOT(message(QString)));
199 QObject::connect(this->Advanced, SIGNAL(clicked(bool)),
200 this->CacheValues, SLOT(setShowAdvanced(bool)));
201 QObject::connect(this->Search, SIGNAL(textChanged(QString)),
202 this->CacheValues, SLOT(setSearchFilter(QString)));
204 QObject::connect(this->CMakeThread->cmakeInstance(),
205 SIGNAL(generatorChanged(QString)),
206 this, SLOT(updateGeneratorLabel(QString)));
207 this->updateGeneratorLabel(QString());
209 QObject::connect(this->CacheValues->cacheModel(),
210 SIGNAL(dataChanged(QModelIndex,QModelIndex)),
211 this, SLOT(setCacheModified()));
213 QObject::connect(this->CacheValues->selectionModel(),
214 SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
215 this, SLOT(selectionChanged()));
216 QObject::connect(this->RemoveEntry, SIGNAL(clicked(bool)),
217 this, SLOT(removeSelectedCacheEntries()));
218 QObject::connect(this->AddEntry, SIGNAL(clicked(bool)),
219 this, SLOT(addCacheEntry()));
221 QObject::connect(this->SuppressDevWarningsAction, SIGNAL(triggered(bool)),
222 this->CMakeThread->cmakeInstance(), SLOT(setSuppressDevWarnings(bool)));
224 if(!this->SourceDirectory->text().isEmpty() ||
225 !this->BinaryDirectory->lineEdit()->text().isEmpty())
227 this->onSourceDirectoryChanged(this->SourceDirectory->text());
228 this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
230 else
232 this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
236 CMakeSetupDialog::~CMakeSetupDialog()
238 QSettings settings;
239 settings.beginGroup("Settings/StartPath");
240 settings.setValue("Height", this->height());
241 settings.setValue("Width", this->width());
243 // wait for thread to stop
244 this->CMakeThread->quit();
245 this->CMakeThread->wait(2000);
248 void CMakeSetupDialog::doConfigure()
250 if(this->CurrentState == Configuring)
252 // stop configure
253 doInterrupt();
254 return;
257 // make sure build directory exists
258 QString bindir = this->CMakeThread->cmakeInstance()->binaryDirectory();
259 QDir dir(bindir);
260 if(!dir.exists())
262 QString message = tr("Build directory does not exist, "
263 "should I create it?")
264 + "\n\n"
265 + tr("Directory: ");
266 message += bindir;
267 QString title = tr("Create Directory");
268 QMessageBox::StandardButton btn;
269 btn = QMessageBox::information(this, title, message,
270 QMessageBox::Yes | QMessageBox::No);
271 if(btn == QMessageBox::No)
273 return;
275 dir.mkpath(".");
278 // if no generator, prompt for it and other setup stuff
279 if(this->CMakeThread->cmakeInstance()->generator().isEmpty())
281 if(!this->setupFirstConfigure())
283 return;
287 // remember path
288 this->addBinaryPath(dir.absolutePath());
290 this->enterState(Configuring);
292 this->CacheValues->selectionModel()->clear();
293 QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
294 "setProperties", Qt::QueuedConnection,
295 Q_ARG(QCMakePropertyList,
296 this->CacheValues->cacheModel()->properties()));
297 QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
298 "configure", Qt::QueuedConnection);
301 void CMakeSetupDialog::finishConfigure(int err)
303 if(0 == err && 0 == this->CacheValues->cacheModel()->newCount())
305 this->enterState(ReadyGenerate);
307 else
309 this->enterState(ReadyConfigure);
310 this->CacheValues->scrollToTop();
313 if(err != 0)
315 QMessageBox::critical(this, tr("Error"),
316 tr("Error in configuration process, project files may be invalid"),
317 QMessageBox::Ok);
321 void CMakeSetupDialog::finishGenerate(int err)
323 this->enterState(ReadyGenerate);
324 if(err != 0)
326 QMessageBox::critical(this, tr("Error"),
327 tr("Error in generation process, project files may be invalid"),
328 QMessageBox::Ok);
332 void CMakeSetupDialog::doInstallForCommandLine()
334 QMacInstallDialog setupdialog(0);
335 setupdialog.exec();
338 void CMakeSetupDialog::doGenerate()
340 if(this->CurrentState == Generating)
342 // stop generate
343 doInterrupt();
344 return;
346 this->enterState(Generating);
347 QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
348 "generate", Qt::QueuedConnection);
351 void CMakeSetupDialog::closeEvent(QCloseEvent* e)
353 // prompt for close if there are unsaved changes, and we're not busy
354 if(this->CacheModified)
356 QString message = tr("You have changed options but not rebuilt, "
357 "are you sure you want to exit?");
358 QString title = tr("Confirm Exit");
359 QMessageBox::StandardButton btn;
360 btn = QMessageBox::critical(this, title, message,
361 QMessageBox::Yes | QMessageBox::No);
362 if(btn == QMessageBox::No)
364 e->ignore();
368 // don't close if we're busy, unless the user really wants to
369 if(this->CurrentState == Configuring)
371 QString message = "You are in the middle of a Configure.\n"
372 "If you Exit now the configure information will be lost.\n"
373 "Are you sure you want to Exit?";
374 QString title = tr("Confirm Exit");
375 QMessageBox::StandardButton btn;
376 btn = QMessageBox::critical(this, title, message,
377 QMessageBox::Yes | QMessageBox::No);
378 if(btn == QMessageBox::No)
380 e->ignore();
382 else
384 this->doInterrupt();
388 // let the generate finish
389 if(this->CurrentState == Generating)
391 e->ignore();
395 void CMakeSetupDialog::doHelp()
397 QString msg = tr("CMake is used to configure and generate build files for "
398 "software projects. The basic steps for configuring a project are as "
399 "follows:\r\n\r\n1. Select the source directory for the project. This should "
400 "contain the CMakeLists.txt files for the project.\r\n\r\n2. Select the build "
401 "directory for the project. This is the directory where the project will be "
402 "built. It can be the same or a different directory than the source "
403 "directory. For easy clean up, a separate build directory is recommended. "
404 "CMake will create the directory if it does not exist.\r\n\r\n3. Once the "
405 "source and binary directories are selected, it is time to press the "
406 "Configure button. This will cause CMake to read all of the input files and "
407 "discover all the variables used by the project. The first time a variable "
408 "is displayed it will be in Red. Users should inspect red variables making "
409 "sure the values are correct. For some projects the Configure process can "
410 "be iterative, so continue to press the Configure button until there are no "
411 "longer red entries.\r\n\r\n4. Once there are no longer red entries, you "
412 "should click the Generate button. This will write the build files to the build "
413 "directory.");
415 QDialog dialog;
416 QFontMetrics met(this->font());
417 int msgWidth = met.width(msg);
418 dialog.setMinimumSize(msgWidth/15,20);
419 dialog.setWindowTitle(tr("Help"));
420 QVBoxLayout* l = new QVBoxLayout(&dialog);
421 QLabel* lab = new QLabel(&dialog);
422 lab->setText(msg);
423 lab->setWordWrap(true);
424 QDialogButtonBox* btns = new QDialogButtonBox(QDialogButtonBox::Ok,
425 Qt::Horizontal, &dialog);
426 QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
427 l->addWidget(lab);
428 l->addWidget(btns);
429 dialog.exec();
432 void CMakeSetupDialog::doInterrupt()
434 this->enterState(Interrupting);
435 QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
436 "interrupt", Qt::QueuedConnection);
439 void CMakeSetupDialog::doSourceBrowse()
441 QString dir = QFileDialog::getExistingDirectory(this,
442 tr("Enter Path to Source"), this->SourceDirectory->text());
443 if(!dir.isEmpty())
445 this->setSourceDirectory(dir);
449 void CMakeSetupDialog::updateSourceDirectory(const QString& dir)
451 if(this->SourceDirectory->text() != dir)
453 this->SourceDirectory->blockSignals(true);
454 this->SourceDirectory->setText(dir);
455 this->SourceDirectory->blockSignals(false);
459 void CMakeSetupDialog::updateBinaryDirectory(const QString& dir)
461 if(this->BinaryDirectory->currentText() != dir)
463 this->BinaryDirectory->blockSignals(true);
464 this->BinaryDirectory->setEditText(dir);
465 this->BinaryDirectory->blockSignals(false);
469 void CMakeSetupDialog::doBinaryBrowse()
471 QString dir = QFileDialog::getExistingDirectory(this,
472 tr("Enter Path to Build"), this->BinaryDirectory->currentText());
473 if(!dir.isEmpty() && dir != this->BinaryDirectory->currentText())
475 this->setBinaryDirectory(dir);
479 void CMakeSetupDialog::setBinaryDirectory(const QString& dir)
481 this->BinaryDirectory->setEditText(dir);
484 void CMakeSetupDialog::onSourceDirectoryChanged(const QString& dir)
486 this->Output->clear();
487 QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
488 "setSourceDirectory", Qt::QueuedConnection, Q_ARG(QString, dir));
491 void CMakeSetupDialog::onBinaryDirectoryChanged(const QString& dir)
493 this->CacheModified = false;
494 this->CacheValues->cacheModel()->clear();
495 this->Output->clear();
496 QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
497 "setBinaryDirectory", Qt::QueuedConnection, Q_ARG(QString, dir));
500 void CMakeSetupDialog::setSourceDirectory(const QString& dir)
502 this->SourceDirectory->setText(dir);
505 void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent)
507 this->ProgressBar->setValue(qRound(percent * 100));
510 void CMakeSetupDialog::error(const QString& message)
512 this->Output->setCurrentCharFormat(this->ErrorFormat);
513 this->Output->append(message);
516 void CMakeSetupDialog::message(const QString& message)
518 this->Output->setCurrentCharFormat(this->MessageFormat);
519 this->Output->append(message);
522 void CMakeSetupDialog::setEnabledState(bool enabled)
524 // disable parts of the GUI during configure/generate
525 this->CacheValues->cacheModel()->setEditEnabled(enabled);
526 this->SourceDirectory->setEnabled(enabled);
527 this->BrowseSourceDirectoryButton->setEnabled(enabled);
528 this->BinaryDirectory->setEnabled(enabled);
529 this->BrowseBinaryDirectoryButton->setEnabled(enabled);
530 this->ReloadCacheAction->setEnabled(enabled);
531 this->DeleteCacheAction->setEnabled(enabled);
532 this->ExitAction->setEnabled(enabled);
533 this->ConfigureAction->setEnabled(enabled);
534 this->AddEntry->setEnabled(enabled);
535 this->RemoveEntry->setEnabled(false); // let selection re-enable it
538 bool CMakeSetupDialog::setupFirstConfigure()
540 CMakeFirstConfigure dialog;
542 // initialize dialog and restore saved settings
544 // add generators
545 dialog.setGenerators(this->CMakeThread->cmakeInstance()->availableGenerators());
547 // restore from settings
548 dialog.loadFromSettings();
550 if(dialog.exec() == QDialog::Accepted)
552 dialog.saveToSettings();
553 this->CMakeThread->cmakeInstance()->setGenerator(dialog.getGenerator());
555 QCMakeCacheModel* m = this->CacheValues->cacheModel();
557 if(dialog.compilerSetup())
559 QString fortranCompiler = dialog.getFortranCompiler();
560 if(!fortranCompiler.isEmpty())
562 m->insertProperty(0, QCMakeProperty::FILEPATH, "CMAKE_Fortran_COMPILER",
563 "Fortran compiler.", fortranCompiler, false);
565 QString cxxCompiler = dialog.getCXXCompiler();
566 if(!cxxCompiler.isEmpty())
568 m->insertProperty(0, QCMakeProperty::FILEPATH, "CMAKE_CXX_COMPILER",
569 "CXX compiler.", cxxCompiler, false);
572 QString cCompiler = dialog.getCCompiler();
573 if(!cCompiler.isEmpty())
575 m->insertProperty(0, QCMakeProperty::FILEPATH, "CMAKE_C_COMPILER",
576 "C compiler.", cCompiler, false);
579 else if(dialog.crossCompilerSetup())
581 QString toolchainFile = dialog.crossCompilerToolChainFile();
582 if(!toolchainFile.isEmpty())
584 m->insertProperty(0, QCMakeProperty::FILEPATH, "CMAKE_TOOLCHAIN_FILE",
585 "Cross Compile ToolChain File", toolchainFile, false);
587 else
589 QString fortranCompiler = dialog.getFortranCompiler();
590 if(!fortranCompiler.isEmpty())
592 m->insertProperty(0, QCMakeProperty::FILEPATH, "CMAKE_Fortran_COMPILER",
593 "Fortran compiler.", fortranCompiler, false);
596 QString mode = dialog.getCrossIncludeMode();
597 m->insertProperty(0, QCMakeProperty::STRING, "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE",
598 "CMake Find Include Mode", mode, false);
599 mode = dialog.getCrossLibraryMode();
600 m->insertProperty(0, QCMakeProperty::STRING, "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY",
601 "CMake Find Library Mode", mode, false);
602 mode = dialog.getCrossProgramMode();
603 m->insertProperty(0, QCMakeProperty::STRING, "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM",
604 "CMake Find Program Mode", mode, false);
606 QString rootPath = dialog.getCrossRoot();
607 m->insertProperty(0, QCMakeProperty::PATH, "CMAKE_FIND_ROOT_PATH",
608 "CMake Find Root Path", rootPath, false);
610 QString systemName = dialog.getSystemName();
611 m->insertProperty(0, QCMakeProperty::STRING, "CMAKE_SYSTEM_NAME",
612 "CMake System Name", systemName, false);
613 QString cxxCompiler = dialog.getCXXCompiler();
614 m->insertProperty(0, QCMakeProperty::FILEPATH, "CMAKE_CXX_COMPILER",
615 "CXX compiler.", cxxCompiler, false);
616 QString cCompiler = dialog.getCCompiler();
617 m->insertProperty(0, QCMakeProperty::FILEPATH, "CMAKE_C_COMPILER",
618 "C compiler.", cCompiler, false);
621 return true;
624 return false;
627 void CMakeSetupDialog::updateGeneratorLabel(const QString& gen)
629 QString str = tr("Current Generator: ");
630 if(gen.isEmpty())
632 str += tr("None");
634 else
636 str += gen;
638 this->Generator->setText(str);
641 void CMakeSetupDialog::doReloadCache()
643 QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
644 "reloadCache", Qt::QueuedConnection);
647 void CMakeSetupDialog::doDeleteCache()
649 QString title = tr("Delete Cache");
650 QString message = "Are you sure you want to delete the cache?";
651 QMessageBox::StandardButton btn;
652 btn = QMessageBox::information(this, title, message,
653 QMessageBox::Yes | QMessageBox::No);
654 if(btn == QMessageBox::No)
656 return;
658 QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
659 "deleteCache", Qt::QueuedConnection);
662 void CMakeSetupDialog::doAbout()
664 QString msg = "CMake\nwww.cmake.org";
666 QDialog dialog;
667 dialog.setWindowTitle(tr("About"));
668 QVBoxLayout* l = new QVBoxLayout(&dialog);
669 QLabel* lab = new QLabel(&dialog);
670 l->addWidget(lab);
671 lab->setText(msg);
672 lab->setWordWrap(true);
673 QDialogButtonBox* btns = new QDialogButtonBox(QDialogButtonBox::Ok,
674 Qt::Horizontal, &dialog);
675 QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
676 l->addWidget(btns);
677 dialog.exec();
680 void CMakeSetupDialog::setExitAfterGenerate(bool b)
682 this->ExitAfterGenerate = b;
685 void CMakeSetupDialog::addBinaryPath(const QString& path)
687 QString cleanpath = QDir::cleanPath(path);
689 // update UI
690 this->BinaryDirectory->blockSignals(true);
691 int idx = this->BinaryDirectory->findText(cleanpath);
692 if(idx != -1)
694 this->BinaryDirectory->removeItem(idx);
696 this->BinaryDirectory->insertItem(0, cleanpath);
697 this->BinaryDirectory->setCurrentIndex(0);
698 this->BinaryDirectory->blockSignals(false);
700 // save to registry
701 QStringList buildPaths = this->loadBuildPaths();
702 buildPaths.removeAll(cleanpath);
703 buildPaths.prepend(cleanpath);
704 this->saveBuildPaths(buildPaths);
707 void CMakeSetupDialog::dragEnterEvent(QDragEnterEvent* e)
709 if(!(this->CurrentState == ReadyConfigure ||
710 this->CurrentState == ReadyGenerate))
712 e->ignore();
713 return;
716 const QMimeData* dat = e->mimeData();
717 QList<QUrl> urls = dat->urls();
718 QString file = urls.count() ? urls[0].toLocalFile() : QString();
719 if(!file.isEmpty() &&
720 (file.endsWith("CMakeCache.txt", Qt::CaseInsensitive) ||
721 file.endsWith("CMakeLists.txt", Qt::CaseInsensitive) ) )
723 e->accept();
725 else
727 e->ignore();
731 void CMakeSetupDialog::dropEvent(QDropEvent* e)
733 if(!(this->CurrentState == ReadyConfigure ||
734 this->CurrentState == ReadyGenerate))
736 return;
739 const QMimeData* dat = e->mimeData();
740 QList<QUrl> urls = dat->urls();
741 QString file = urls.count() ? urls[0].toLocalFile() : QString();
742 if(file.endsWith("CMakeCache.txt", Qt::CaseInsensitive))
744 QFileInfo info(file);
745 if(this->CMakeThread->cmakeInstance()->binaryDirectory() != info.absolutePath())
747 this->setBinaryDirectory(info.absolutePath());
750 else if(file.endsWith("CMakeLists.txt", Qt::CaseInsensitive))
752 QFileInfo info(file);
753 if(this->CMakeThread->cmakeInstance()->binaryDirectory() != info.absolutePath())
755 this->setSourceDirectory(info.absolutePath());
756 this->setBinaryDirectory(info.absolutePath());
761 QStringList CMakeSetupDialog::loadBuildPaths()
763 QSettings settings;
764 settings.beginGroup("Settings/StartPath");
766 QStringList buildPaths;
767 for(int i=0; i<10; i++)
769 QString p = settings.value(QString("WhereBuild%1").arg(i)).toString();
770 if(!p.isEmpty())
772 buildPaths.append(p);
775 return buildPaths;
778 void CMakeSetupDialog::saveBuildPaths(const QStringList& paths)
780 QSettings settings;
781 settings.beginGroup("Settings/StartPath");
783 int num = paths.count();
784 if(num > 10)
786 num = 10;
789 for(int i=0; i<num; i++)
791 settings.setValue(QString("WhereBuild%1").arg(i), paths[i]);
795 void CMakeSetupDialog::setCacheModified()
797 this->CacheModified = true;
798 this->enterState(ReadyConfigure);
801 void CMakeSetupDialog::removeSelectedCacheEntries()
803 QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
804 QList<QPersistentModelIndex> pidxs;
805 foreach(QModelIndex i, idxs)
807 pidxs.append(i);
809 foreach(QPersistentModelIndex pi, pidxs)
811 this->CacheValues->model()->removeRow(pi.row());
815 void CMakeSetupDialog::selectionChanged()
817 QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
818 if(idxs.count() &&
819 (this->CurrentState == ReadyConfigure ||
820 this->CurrentState == ReadyGenerate) )
822 this->RemoveEntry->setEnabled(true);
824 else
826 this->RemoveEntry->setEnabled(false);
830 void CMakeSetupDialog::enterState(CMakeSetupDialog::State s)
832 if(s == this->CurrentState)
834 return;
837 this->CurrentState = s;
839 if(s == Interrupting)
841 this->ConfigureButton->setEnabled(false);
842 this->GenerateButton->setEnabled(false);
844 else if(s == Configuring)
846 this->Output->clear();
847 this->setEnabledState(false);
848 this->GenerateButton->setEnabled(false);
849 this->GenerateAction->setEnabled(false);
850 this->ConfigureButton->setText(tr("&Stop"));
852 else if(s == Generating)
854 this->CacheModified = false;
855 this->setEnabledState(false);
856 this->ConfigureButton->setEnabled(false);
857 this->GenerateAction->setEnabled(false);
858 this->GenerateButton->setText(tr("&Stop"));
860 else if(s == ReadyConfigure)
862 this->ProgressBar->reset();
863 this->setEnabledState(true);
864 this->GenerateButton->setEnabled(false);
865 this->GenerateAction->setEnabled(false);
866 this->ConfigureButton->setEnabled(true);
867 this->ConfigureButton->setText(tr("&Configure"));
868 this->GenerateButton->setText(tr("&Generate"));
870 else if(s == ReadyGenerate)
872 this->ProgressBar->reset();
873 this->setEnabledState(true);
874 this->GenerateButton->setEnabled(true);
875 this->GenerateAction->setEnabled(true);
876 this->ConfigureButton->setEnabled(true);
877 this->ConfigureButton->setText(tr("&Configure"));
878 this->GenerateButton->setText(tr("&Generate"));
882 void CMakeSetupDialog::addCacheEntry()
884 QDialog dialog(this);
885 dialog.resize(400, 200);
886 dialog.setWindowTitle(tr("Add Cache Entry"));
887 QVBoxLayout* l = new QVBoxLayout(&dialog);
888 AddCacheEntry* w = new AddCacheEntry(&dialog);
889 QDialogButtonBox* btns = new QDialogButtonBox(
890 QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
891 Qt::Horizontal, &dialog);
892 QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept()));
893 QObject::connect(btns, SIGNAL(rejected()), &dialog, SLOT(reject()));
894 l->addWidget(w);
895 l->addStretch();
896 l->addWidget(btns);
897 if(QDialog::Accepted == dialog.exec())
899 QCMakeCacheModel* m = this->CacheValues->cacheModel();
900 m->insertProperty(0, w->type(), w->name(), w->description(), w->value(), false);
904 void CMakeSetupDialog::startSearch()
906 this->Search->setFocus(Qt::OtherFocusReason);
907 this->Search->selectAll();
910 void CMakeSetupDialog::setDebugOutput(bool flag)
912 QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(),
913 "setDebugOutput", Qt::QueuedConnection, Q_ARG(bool, flag));