CMakeSetupGUIImplementation.cxx 17 KB

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