CMakeSetupGUIImplementation.cxx 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. /*=========================================================================
  2. Program: Insight Segmentation & Registration Toolkit
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Insight Consortium. All rights reserved.
  8. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "CMakeSetupGUIImplementation.h"
  14. #include "FL/Fl_File_Chooser.H"
  15. #include "FL/filename.H"
  16. #include "FL/fl_ask.H"
  17. #include "../cmCacheManager.h"
  18. #include "../cmMakefile.h"
  19. #include <iostream>
  20. #include "FLTKPropertyList.h"
  21. #include "FLTKPropertyItemRow.h"
  22. #include "FL/fl_draw.H"
  23. #include "../cmake.h"
  24. void FLTKMessageCallback(const char* message, const char* title, bool& nomore, void*)
  25. {
  26. std::string msg = message;
  27. msg += "\nPress cancel to suppress any further messages.";
  28. int choice = fl_choice( msg.c_str(), "Cancel","Ok",0);
  29. if(choice==0)
  30. {
  31. nomore = true;
  32. }
  33. }
  34. /**
  35. * Constructor
  36. */
  37. CMakeSetupGUIImplementation
  38. ::CMakeSetupGUIImplementation():m_CacheEntriesList(this)
  39. {
  40. m_CMakeInstance = new cmake;
  41. cmSystemTools::SetErrorCallback(FLTKMessageCallback);
  42. m_BuildPathChanged = false;
  43. }
  44. /**
  45. * Destructor
  46. */
  47. CMakeSetupGUIImplementation
  48. ::~CMakeSetupGUIImplementation()
  49. {
  50. }
  51. /**
  52. * Show the graphic interface
  53. */
  54. void
  55. CMakeSetupGUIImplementation
  56. ::Show( void )
  57. {
  58. dialogWindow->show();
  59. }
  60. /**
  61. * Hide the graphic interface
  62. */
  63. void
  64. CMakeSetupGUIImplementation
  65. ::Close( void )
  66. {
  67. SaveRecentDirectories();
  68. dialogWindow->hide();
  69. }
  70. /**
  71. * Browse for the path to the sources
  72. */
  73. void
  74. CMakeSetupGUIImplementation
  75. ::BrowseForSourcePath( void )
  76. {
  77. const char * path =
  78. fl_dir_chooser(
  79. "Path to Sources",
  80. sourcePathTextInput->value() );
  81. if( !path )
  82. {
  83. return;
  84. }
  85. SetSourcePath( path );
  86. }
  87. /**
  88. * Browse for the path to the binaries
  89. */
  90. void
  91. CMakeSetupGUIImplementation
  92. ::BrowseForBinaryPath( void )
  93. {
  94. const char * path =
  95. fl_dir_chooser(
  96. "Path to Binaries",
  97. binaryPathTextInput->value() );
  98. if( !path )
  99. {
  100. return;
  101. }
  102. SetBinaryPath( path );
  103. }
  104. /**
  105. * Set path to executable. Used to get the path to CMake
  106. */
  107. void
  108. CMakeSetupGUIImplementation
  109. ::SetPathToExecutable( const char * path )
  110. {
  111. m_PathToExecutable = cmSystemTools::CollapseFullPath(path);
  112. m_PathToExecutable = cmSystemTools::GetProgramPath(m_PathToExecutable.c_str()).c_str();
  113. #ifdef _WIN32
  114. m_PathToExecutable += "/cmake.exe";
  115. #else
  116. m_PathToExecutable += "/cmake";
  117. #endif
  118. }
  119. /**
  120. * Set the source path
  121. */
  122. void
  123. CMakeSetupGUIImplementation
  124. ::SetSourcePath( const char * path )
  125. {
  126. if( !path || strlen(path)==0 )
  127. {
  128. fl_alert("Please select the path to the sources");
  129. return;
  130. }
  131. std::string expandedAbsolutePath = ExpandPathAndMakeItAbsolute( path );
  132. sourcePathTextInput->value( expandedAbsolutePath.c_str() );
  133. if( VerifySourcePath( expandedAbsolutePath ) )
  134. {
  135. m_WhereSource = expandedAbsolutePath;
  136. }
  137. }
  138. /**
  139. * Expand environment variables in the path and make it absolute
  140. */
  141. std::string
  142. CMakeSetupGUIImplementation
  143. ::ExpandPathAndMakeItAbsolute( const std::string & inputPath ) const
  144. {
  145. return cmSystemTools::CollapseFullPath(inputPath.c_str());
  146. }
  147. /**
  148. * Set the binary path
  149. */
  150. void
  151. CMakeSetupGUIImplementation
  152. ::SetBinaryPath( const char * path )
  153. {
  154. if( !path || strlen(path)==0 )
  155. {
  156. fl_alert("Please select the path to the binaries");
  157. return;
  158. }
  159. std::string expandedAbsolutePath = ExpandPathAndMakeItAbsolute( path );
  160. binaryPathTextInput->value( expandedAbsolutePath.c_str() );
  161. if( !VerifyBinaryPath( expandedAbsolutePath.c_str() ) )
  162. {
  163. return;
  164. }
  165. if( m_WhereBuild != expandedAbsolutePath )
  166. {
  167. m_BuildPathChanged = true;
  168. m_WhereBuild = expandedAbsolutePath;
  169. m_CacheEntriesList.RemoveAll(); // remove data from other project
  170. this->LoadCacheFromDiskToGUI();
  171. }
  172. else
  173. {
  174. m_BuildPathChanged = false;
  175. }
  176. }
  177. /**
  178. * Verify the path to binaries
  179. */
  180. bool
  181. CMakeSetupGUIImplementation
  182. ::VerifyBinaryPath( const std::string & path ) const
  183. {
  184. bool pathIsOK = false;
  185. if( cmSystemTools::FileIsDirectory( path.c_str() ) )
  186. {
  187. pathIsOK = true;
  188. }
  189. else
  190. {
  191. int userWantsToCreateDirectory =
  192. fl_ask("The directory \n %s \n Doesn't exist. Do you want to create it ?",
  193. path.c_str() );
  194. if( userWantsToCreateDirectory )
  195. {
  196. cmSystemTools::MakeDirectory( path.c_str() );
  197. pathIsOK = true;
  198. }
  199. else
  200. {
  201. pathIsOK = false;
  202. }
  203. }
  204. return pathIsOK;
  205. }
  206. /**
  207. * Verify the path to sources
  208. */
  209. bool
  210. CMakeSetupGUIImplementation
  211. ::VerifySourcePath( const std::string & path ) const
  212. {
  213. if( !cmSystemTools::FileIsDirectory(( path.c_str())))
  214. {
  215. fl_alert("The Source directory \n %s \n Doesn't exist or is not a directory", path.c_str() );
  216. return false;
  217. }
  218. return true;
  219. }
  220. /**
  221. * Build the project files
  222. */
  223. void
  224. CMakeSetupGUIImplementation
  225. ::RunCMake( bool generateProjectFiles )
  226. {
  227. if(!cmSystemTools::FileIsDirectory( m_WhereBuild.c_str() ))
  228. {
  229. std::string message =
  230. "Build directory does not exist, should I create it?\n\n"
  231. "Directory: ";
  232. message += m_WhereBuild;
  233. int userWantToCreateDirectory =
  234. fl_ask(message.c_str());
  235. if( userWantToCreateDirectory )
  236. {
  237. cmSystemTools::MakeDirectory( m_WhereBuild.c_str() );
  238. }
  239. else
  240. {
  241. fl_alert("Build Project aborted, nothing done.");
  242. return;
  243. }
  244. }
  245. // set the wait cursor
  246. fl_cursor(FL_CURSOR_WAIT,FL_BLACK,FL_WHITE);
  247. // save the current GUI values to the cache
  248. this->SaveCacheFromGUI();
  249. // Make sure we are working from the cache on disk
  250. this->LoadCacheFromDiskToGUI();
  251. UpdateListOfRecentDirectories();
  252. SaveRecentDirectories();
  253. if (generateProjectFiles)
  254. {
  255. if(m_CMakeInstance->Generate() != 0)
  256. {
  257. cmSystemTools::Error(
  258. "Error in generation process, project files may be invalid");
  259. }
  260. }
  261. else
  262. {
  263. m_CMakeInstance->SetHomeDirectory(m_WhereSource.c_str());
  264. m_CMakeInstance->SetStartDirectory(m_WhereSource.c_str());
  265. m_CMakeInstance->SetHomeOutputDirectory(m_WhereBuild.c_str());
  266. m_CMakeInstance->SetStartOutputDirectory(m_WhereBuild.c_str());
  267. const char* defaultGenerator = 0;
  268. #if defined(_WIN32)
  269. defaultGenerator = "NMake Makefiles";
  270. #else defined(_WIN32)
  271. defaultGenerator = "Unix Makefiles";
  272. #endif defined(_WIN32)
  273. m_CMakeInstance->SetGlobalGenerator(
  274. m_CMakeInstance->CreateGlobalGenerator(defaultGenerator));
  275. m_CMakeInstance->SetCMakeCommand(m_PathToExecutable.c_str());
  276. m_CMakeInstance->LoadCache();
  277. if(m_CMakeInstance->Configure() != 0)
  278. {
  279. cmSystemTools::Error(
  280. "Error in configuration process, project files may be invalid");
  281. }
  282. // update the GUI with any new values in the caused by the
  283. // generation process
  284. this->LoadCacheFromDiskToGUI();
  285. }
  286. // path is up-to-date now
  287. m_BuildPathChanged = false;
  288. // put the cursor back
  289. fl_cursor(FL_CURSOR_DEFAULT,FL_BLACK,FL_WHITE);
  290. fl_message("Done !");
  291. }
  292. /**
  293. * Load Cache from disk to GUI
  294. */
  295. void
  296. CMakeSetupGUIImplementation
  297. ::LoadCacheFromDiskToGUI( void )
  298. {
  299. if( m_WhereBuild != "" )
  300. {
  301. cmCacheManager *cachem = this->m_CMakeInstance->GetCacheManager();
  302. cachem->LoadCache( m_WhereBuild.c_str() );
  303. this->FillCacheGUIFromCacheManager();
  304. }
  305. }
  306. /**
  307. * Save Cache from disk to GUI
  308. */
  309. void
  310. CMakeSetupGUIImplementation
  311. ::SaveCacheFromGUI( void )
  312. {
  313. cmCacheManager *cachem = this->m_CMakeInstance->GetCacheManager();
  314. this->FillCacheManagerFromCacheGUI();
  315. if(m_WhereBuild != "")
  316. {
  317. cachem->SaveCache(m_WhereBuild.c_str());
  318. }
  319. }
  320. /**
  321. * Fill Cache GUI from cache manager
  322. */
  323. void
  324. CMakeSetupGUIImplementation
  325. ::FillCacheGUIFromCacheManager( void )
  326. {
  327. cmCacheManager *cachem = this->m_CMakeInstance->GetCacheManager();
  328. cmCacheManager::CacheIterator it = cachem->NewIterator();
  329. size_t size = m_CacheEntriesList.GetItems().size();
  330. bool reverseOrder = false;
  331. // if there are already entries in the cache, then
  332. // put the new ones in the top, so they show up first
  333. if(size)
  334. {
  335. reverseOrder = true;
  336. }
  337. // all the current values are not new any more
  338. std::set<fltk::PropertyItem*> items = m_CacheEntriesList.GetItems();
  339. for(std::set<fltk::PropertyItem*>::iterator i = items.begin();
  340. i != items.end(); ++i)
  341. {
  342. fltk::PropertyItem* item = *i;
  343. item->m_NewValue = false;
  344. }
  345. // Prepare to add rows to the FLTK scroll/pack
  346. propertyListPack->clear();
  347. propertyListPack->begin();
  348. // const cmCacheManager::CacheEntryMap &cache =
  349. // cmCacheManager::GetInstance()->GetCacheMap();
  350. // if(cache.size() == 0)
  351. // {
  352. // m_OKButton->deactivate();
  353. // }
  354. // else
  355. // {
  356. // m_OKButton->activate();
  357. // }
  358. for(cmCacheManager::CacheIterator i = cachem->NewIterator();
  359. !i.IsAtEnd(); i.Next())
  360. {
  361. const char* key = i.GetName();
  362. std::string value = i.GetValue();
  363. bool advanced = i.GetPropertyAsBool("ADVANCED");
  364. switch(i.GetType() )
  365. {
  366. case cmCacheManager::BOOL:
  367. if(cmSystemTools::IsOn(value.c_str()))
  368. {
  369. m_CacheEntriesList.AddProperty(key,
  370. "ON",
  371. i.GetProperty("HELPSTRING"),
  372. fltk::PropertyList::CHECKBOX,"",
  373. reverseOrder);
  374. }
  375. else
  376. {
  377. m_CacheEntriesList.AddProperty(key,
  378. "OFF",
  379. i.GetProperty("HELPSTRING"),
  380. fltk::PropertyList::CHECKBOX,"",
  381. reverseOrder);
  382. }
  383. break;
  384. case cmCacheManager::PATH:
  385. m_CacheEntriesList.AddProperty(key,
  386. value.c_str(),
  387. i.GetProperty("HELPSTRING"),
  388. fltk::PropertyList::PATH,"",
  389. reverseOrder);
  390. break;
  391. case cmCacheManager::FILEPATH:
  392. m_CacheEntriesList.AddProperty(key,
  393. value.c_str(),
  394. i.GetProperty("HELPSTRING"),
  395. fltk::PropertyList::FILE,"",
  396. reverseOrder);
  397. break;
  398. case cmCacheManager::STRING:
  399. m_CacheEntriesList.AddProperty(key,
  400. value.c_str(),
  401. i.GetProperty("HELPSTRING"),
  402. fltk::PropertyList::EDIT,"",
  403. reverseOrder);
  404. break;
  405. case cmCacheManager::STATIC:
  406. case cmCacheManager::INTERNAL:
  407. m_CacheEntriesList.RemoveProperty(key);
  408. break;
  409. }
  410. }
  411. // Add the old entry to the end of the pack
  412. for(std::set<fltk::PropertyItem*>::iterator i = items.begin();
  413. i != items.end(); ++i)
  414. {
  415. fltk::PropertyItem* item = *i;
  416. if( !(item->m_NewValue) )
  417. {
  418. new fltk::PropertyItemRow( item ); // GUI of the old property row
  419. }
  420. }
  421. propertyListPack->end();
  422. propertyListPack->init_sizes();
  423. cacheValuesScroll->position( 0, 0 );
  424. propertyListPack->redraw();
  425. Fl::check();
  426. this->UpdateData(false);
  427. }
  428. /**
  429. * UpdateData
  430. */
  431. void
  432. CMakeSetupGUIImplementation
  433. ::UpdateData( bool option )
  434. {
  435. dialogWindow->redraw();
  436. Fl::check();
  437. }
  438. /**
  439. * Fill cache manager from Cache GUI
  440. */
  441. void
  442. CMakeSetupGUIImplementation
  443. ::FillCacheManagerFromCacheGUI( void )
  444. {
  445. cmCacheManager *cachem = this->m_CMakeInstance->GetCacheManager();
  446. cmCacheManager::CacheIterator it = cachem->NewIterator();
  447. std::set<fltk::PropertyItem*> items = m_CacheEntriesList.GetItems();
  448. for(std::set<fltk::PropertyItem*>::iterator i = items.begin();
  449. i != items.end(); ++i)
  450. {
  451. fltk::PropertyItem* item = *i;
  452. if ( it.Find((const char*)item->m_propName.c_str()) )
  453. {
  454. it.SetValue(item->m_curValue.c_str());
  455. }
  456. if( item->m_Dirty )
  457. {
  458. m_CacheEntriesList.SetDirty();
  459. }
  460. }
  461. }
  462. /**
  463. * Load Recent Directories
  464. */
  465. void
  466. CMakeSetupGUIImplementation
  467. ::LoadRecentDirectories( void )
  468. {
  469. std::string home = getenv("HOME");
  470. std::string filename = home + "/.cmakerc";
  471. std::ifstream input;
  472. input.open(filename.c_str());
  473. if( input.fail() )
  474. {
  475. // probably the file doesn't exist
  476. return;
  477. }
  478. m_RecentBinaryDirectories.clear();
  479. m_RecentSourceDirectories.clear();
  480. std::string key;
  481. std::string onedirectory;
  482. while( !input.eof() )
  483. {
  484. input >> key;
  485. if( input.eof() ) break;
  486. if( key == "MostRecentSource" )
  487. {
  488. input >> onedirectory;
  489. m_WhereSource = onedirectory;
  490. sourcePathTextInput->value( m_WhereSource.c_str() );
  491. } else
  492. if( key == "MostRecentBinary" )
  493. {
  494. input >> onedirectory;
  495. m_WhereBuild = onedirectory;
  496. binaryPathTextInput->value( m_WhereBuild.c_str() );
  497. LoadCacheFromDiskToGUI();
  498. } else
  499. if( key == "Binary" )
  500. {
  501. input >> onedirectory;
  502. // insert is only done if the directory doesn't exist
  503. m_RecentBinaryDirectories.insert( onedirectory );
  504. recentBinaryDirectoriesBrowser->add(
  505. (onedirectory.c_str()),
  506. (void*)(onedirectory.c_str()) );
  507. } else
  508. if( key == "Source" )
  509. {
  510. input >> onedirectory;
  511. // insert is only done if the directory doesn't exist
  512. m_RecentSourceDirectories.insert( onedirectory );
  513. recentSourceDirectoriesBrowser->add(
  514. (onedirectory.c_str()),
  515. (void*)(onedirectory.c_str()) );
  516. }
  517. }
  518. input.close();
  519. }
  520. /**
  521. * Save Recent Directories
  522. */
  523. void
  524. CMakeSetupGUIImplementation
  525. ::SaveRecentDirectories( void )
  526. {
  527. std::string home = getenv("HOME");
  528. if( home.empty() )
  529. {
  530. return;
  531. }
  532. std::string filename = home + "/.cmakerc";
  533. std::ofstream output;
  534. output.open(filename.c_str());
  535. output << "MostRecentBinary " << m_WhereBuild << std::endl;
  536. output << "MostRecentSource " << m_WhereSource << std::endl;
  537. // Save Recent binary directories
  538. std::set< std::string >::iterator bindir =
  539. m_RecentBinaryDirectories.begin();
  540. while( bindir != m_RecentBinaryDirectories.end() )
  541. {
  542. output << "Binary " << *bindir << std::endl;
  543. bindir++;
  544. }
  545. // Save Recent source directories
  546. std::set< std::string >::iterator srcdir =
  547. m_RecentSourceDirectories.begin();
  548. while( srcdir != m_RecentSourceDirectories.end() )
  549. {
  550. output << "Source " << *srcdir << std::endl;
  551. srcdir++;
  552. }
  553. }
  554. /**
  555. * Show Recent Binary Directories
  556. */
  557. void
  558. CMakeSetupGUIImplementation
  559. ::ShowRecentBinaryDirectories( void )
  560. {
  561. if( recentBinaryDirectoriesBrowser->size() )
  562. {
  563. recentBinaryDirectoriesBrowser->Fl_Widget::show();
  564. }
  565. }
  566. /**
  567. * Show Recent Source Directories
  568. */
  569. void
  570. CMakeSetupGUIImplementation
  571. ::ShowRecentSourceDirectories( void )
  572. {
  573. if( recentSourceDirectoriesBrowser->size() )
  574. {
  575. recentSourceDirectoriesBrowser->Fl_Widget::show();
  576. }
  577. }
  578. /**
  579. * Select one Recent Binary Directory
  580. */
  581. void
  582. CMakeSetupGUIImplementation
  583. ::SelectOneRecentBinaryDirectory( void )
  584. {
  585. const int selected = recentBinaryDirectoriesBrowser->value();
  586. if( selected == 0 )
  587. {
  588. return;
  589. }
  590. m_WhereBuild = static_cast<char *>(
  591. recentBinaryDirectoriesBrowser->data( selected ));
  592. binaryPathTextInput->value( m_WhereBuild.c_str() );
  593. recentBinaryDirectoriesBrowser->Fl_Widget::hide();
  594. m_CacheEntriesList.RemoveAll(); // remove data from other project
  595. LoadCacheFromDiskToGUI();
  596. }
  597. /**
  598. * Select one Recent Source Directory
  599. */
  600. void
  601. CMakeSetupGUIImplementation
  602. ::SelectOneRecentSourceDirectory( void )
  603. {
  604. const int selected = recentSourceDirectoriesBrowser->value();
  605. if( selected == 0 )
  606. {
  607. return;
  608. }
  609. m_WhereSource = static_cast< char * >(
  610. recentSourceDirectoriesBrowser->data( selected ));
  611. sourcePathTextInput->value( m_WhereSource.c_str() );
  612. recentSourceDirectoriesBrowser->Fl_Widget::hide();
  613. }
  614. /**
  615. * Update List of Recent Directories
  616. */
  617. void
  618. CMakeSetupGUIImplementation
  619. ::UpdateListOfRecentDirectories( void )
  620. {
  621. // Update Recent binary directories
  622. // insert is only done if the directory doesn't exist
  623. m_RecentBinaryDirectories.insert( m_WhereBuild );
  624. // Update Recent source directories
  625. // insert is only done if the directory doesn't exist
  626. m_RecentSourceDirectories.insert( m_WhereSource );
  627. }
  628. /**
  629. * Clicked on Configure Button
  630. */
  631. void
  632. CMakeSetupGUIImplementation
  633. ::ClickOnConfigure( void )
  634. {
  635. this->RunCMake(false);
  636. }
  637. /**
  638. * Clicked on OK Button
  639. */
  640. void
  641. CMakeSetupGUIImplementation
  642. ::ClickOnOK( void )
  643. {
  644. m_CacheEntriesList.ClearDirty();
  645. this->RunCMake(true);
  646. this->Close();
  647. }
  648. /**
  649. * Clicked on Cancel Button
  650. */
  651. void
  652. CMakeSetupGUIImplementation
  653. ::ClickOnCancel( void )
  654. {
  655. if(m_CacheEntriesList.IsDirty())
  656. {
  657. int userWantsExitEvenThoughOptionsHaveChanged =
  658. fl_ask("You have changed options but not rebuilt, \n"
  659. "are you sure you want to exit?");
  660. if( userWantsExitEvenThoughOptionsHaveChanged )
  661. {
  662. this->Close();
  663. }
  664. }
  665. else
  666. {
  667. this->Close();
  668. }
  669. }