CMakeSetupGUIImplementation.cxx 17 KB

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