CMakeSetupGUIImplementation.cxx 18 KB

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