CMakeSetupGUIImplementation.cxx 16 KB

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