The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

829 lines
28KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. void createGUIEditorMenu (PopupMenu&);
  18. void handleGUIEditorMenuCommand (int);
  19. void registerGUIEditorCommands();
  20. //==============================================================================
  21. struct ProjucerApplication::MainMenuModel : public MenuBarModel
  22. {
  23. MainMenuModel()
  24. {
  25. setApplicationCommandManagerToWatch (&getCommandManager());
  26. }
  27. StringArray getMenuBarNames() override
  28. {
  29. return getApp().getMenuNames();
  30. }
  31. PopupMenu getMenuForIndex (int /*topLevelMenuIndex*/, const String& menuName) override
  32. {
  33. PopupMenu menu;
  34. getApp().createMenu (menu, menuName);
  35. return menu;
  36. }
  37. void menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/) override
  38. {
  39. getApp().handleMainMenuCommand (menuItemID);
  40. }
  41. };
  42. //==============================================================================
  43. ProjucerApplication::ProjucerApplication() : isRunningCommandLine (false)
  44. {
  45. }
  46. void ProjucerApplication::initialise (const String& commandLine)
  47. {
  48. if (commandLine.trimStart().startsWith ("--server"))
  49. {
  50. initialiseLogger ("Compiler_Log_");
  51. LookAndFeel::setDefaultLookAndFeel (&lookAndFeel);
  52. #if JUCE_MAC
  53. Process::setDockIconVisible (false);
  54. #endif
  55. server = createClangServer (commandLine);
  56. }
  57. else
  58. {
  59. initialiseLogger ("IDE_Log_");
  60. Logger::writeToLog (SystemStats::getOperatingSystemName());
  61. Logger::writeToLog ("CPU: " + String (SystemStats::getCpuSpeedInMegaherz())
  62. + "MHz Cores: " + String (SystemStats::getNumCpus())
  63. + " " + String (SystemStats::getMemorySizeInMegabytes()) + "MB");
  64. initialiseBasics();
  65. if (commandLine.isNotEmpty())
  66. {
  67. isRunningCommandLine = true;
  68. const int appReturnCode = performCommandLine (commandLine);
  69. if (appReturnCode != commandLineNotPerformed)
  70. {
  71. setApplicationReturnValue (appReturnCode);
  72. quit();
  73. return;
  74. }
  75. isRunningCommandLine = false;
  76. }
  77. if (sendCommandLineToPreexistingInstance())
  78. {
  79. DBG ("Another instance is running - quitting...");
  80. quit();
  81. return;
  82. }
  83. if (! initialiseLog())
  84. {
  85. quit();
  86. return;
  87. }
  88. childProcessCache = new ChildProcessCache();
  89. initCommandManager();
  90. menuModel = new MainMenuModel();
  91. settings->appearance.refreshPresetSchemeList();
  92. initialiseWindows (commandLine);
  93. #if JUCE_MAC
  94. MenuBarModel::setMacMainMenu (menuModel, nullptr, "Open Recent");
  95. #endif
  96. versionChecker = new LatestVersionChecker();
  97. showLoginFormAsyncIfNotTriedRecently();
  98. }
  99. }
  100. void ProjucerApplication::initialiseBasics()
  101. {
  102. LookAndFeel::setDefaultLookAndFeel (&lookAndFeel);
  103. settings = new StoredSettings();
  104. ImageCache::setCacheTimeout (30 * 1000);
  105. icons = new Icons();
  106. }
  107. bool ProjucerApplication::initialiseLog()
  108. {
  109. openDocumentManager.registerType (new ProjucerAppClasses::LiveBuildCodeEditorDocument::Type(), 2);
  110. if (currentEULAHasBeenAcceptedPreviously())
  111. return true;
  112. ScopedPointer<AlertWindow> eulaDialogue (new EULADialogue());
  113. bool hasBeenAccepted = (eulaDialogue->runModalLoop() == EULADialogue::accepted);
  114. setCurrentEULAAccepted (hasBeenAccepted);
  115. if (hasBeenAccepted)
  116. return initialiseLogger ("log_");
  117. return false;
  118. }
  119. bool ProjucerApplication::initialiseLogger (const char* filePrefix)
  120. {
  121. if (logger == nullptr)
  122. {
  123. #if JUCE_LINUX
  124. String folder = "~/.config/Projucer/Logs";
  125. #else
  126. String folder = "com.juce.projucer";
  127. #endif
  128. logger = FileLogger::createDateStampedLogger (folder, filePrefix, ".txt",
  129. getApplicationName() + " " + getApplicationVersion()
  130. + " --- Build date: " __DATE__);
  131. Logger::setCurrentLogger (logger);
  132. }
  133. return logger != nullptr;
  134. }
  135. void ProjucerApplication::initialiseWindows (const String& commandLine)
  136. {
  137. const String commandLineWithoutNSDebug (commandLine.replace ("-NSDocumentRevisionsDebugMode YES", ""));
  138. if (commandLineWithoutNSDebug.trim().isNotEmpty() && ! commandLineWithoutNSDebug.trim().startsWithChar ('-'))
  139. anotherInstanceStarted (commandLine);
  140. else
  141. mainWindowList.reopenLastProjects();
  142. mainWindowList.createWindowIfNoneAreOpen();
  143. }
  144. void ProjucerApplication::shutdown()
  145. {
  146. if (server != nullptr)
  147. {
  148. destroyClangServer (server);
  149. Logger::writeToLog ("Server shutdown cleanly");
  150. }
  151. versionChecker = nullptr;
  152. appearanceEditorWindow = nullptr;
  153. globalPreferencesWindow = nullptr;
  154. utf8Window = nullptr;
  155. svgPathWindow = nullptr;
  156. mainWindowList.forceCloseAllWindows();
  157. openDocumentManager.clear();
  158. childProcessCache = nullptr;
  159. #if JUCE_MAC
  160. MenuBarModel::setMacMainMenu (nullptr);
  161. #endif
  162. menuModel = nullptr;
  163. commandManager = nullptr;
  164. settings = nullptr;
  165. LookAndFeel::setDefaultLookAndFeel (nullptr);
  166. if (! isRunningCommandLine)
  167. Logger::writeToLog ("Shutdown");
  168. deleteLogger();
  169. }
  170. struct AsyncQuitRetrier : private Timer
  171. {
  172. AsyncQuitRetrier() { startTimer (500); }
  173. void timerCallback() override
  174. {
  175. stopTimer();
  176. delete this;
  177. if (JUCEApplicationBase* app = JUCEApplicationBase::getInstance())
  178. app->systemRequestedQuit();
  179. }
  180. JUCE_DECLARE_NON_COPYABLE (AsyncQuitRetrier)
  181. };
  182. void ProjucerApplication::systemRequestedQuit()
  183. {
  184. if (server != nullptr)
  185. {
  186. sendQuitMessageToIDE (server);
  187. }
  188. else if (ModalComponentManager::getInstance()->cancelAllModalComponents())
  189. {
  190. new AsyncQuitRetrier();
  191. }
  192. else
  193. {
  194. if (closeAllMainWindows())
  195. quit();
  196. }
  197. }
  198. //==============================================================================
  199. String ProjucerApplication::getVersionDescription() const
  200. {
  201. String s;
  202. const Time buildDate (Time::getCompilationDate());
  203. s << "Projucer " << ProjectInfo::versionString
  204. << newLine
  205. << "Build date: " << buildDate.getDayOfMonth()
  206. << " " << Time::getMonthName (buildDate.getMonth(), true)
  207. << " " << buildDate.getYear();
  208. return s;
  209. }
  210. void ProjucerApplication::anotherInstanceStarted (const String& commandLine)
  211. {
  212. if (server == nullptr && ! commandLine.trim().startsWithChar ('-'))
  213. openFile (File (commandLine.unquoted()));
  214. }
  215. ProjucerApplication& ProjucerApplication::getApp()
  216. {
  217. ProjucerApplication* const app = dynamic_cast<ProjucerApplication*> (JUCEApplication::getInstance());
  218. jassert (app != nullptr);
  219. return *app;
  220. }
  221. ApplicationCommandManager& ProjucerApplication::getCommandManager()
  222. {
  223. ApplicationCommandManager* cm = ProjucerApplication::getApp().commandManager;
  224. jassert (cm != nullptr);
  225. return *cm;
  226. }
  227. //==============================================================================
  228. enum
  229. {
  230. recentProjectsBaseID = 100,
  231. activeDocumentsBaseID = 300,
  232. colourSchemeBaseID = 1000
  233. };
  234. MenuBarModel* ProjucerApplication::getMenuModel()
  235. {
  236. return menuModel.get();
  237. }
  238. StringArray ProjucerApplication::getMenuNames()
  239. {
  240. const char* const names[] = { "File", "Edit", "View", "Build", "Window", "GUI Editor", "Tools", nullptr };
  241. return StringArray (names);
  242. }
  243. void ProjucerApplication::createMenu (PopupMenu& menu, const String& menuName)
  244. {
  245. if (menuName == "File") createFileMenu (menu);
  246. else if (menuName == "Edit") createEditMenu (menu);
  247. else if (menuName == "View") createViewMenu (menu);
  248. else if (menuName == "Build") createBuildMenu (menu);
  249. else if (menuName == "Window") createWindowMenu (menu);
  250. else if (menuName == "Tools") createToolsMenu (menu);
  251. else if (menuName == "GUI Editor") createGUIEditorMenu (menu);
  252. else jassertfalse; // names have changed?
  253. }
  254. void ProjucerApplication::createFileMenu (PopupMenu& menu)
  255. {
  256. menu.addCommandItem (commandManager, CommandIDs::newProject);
  257. menu.addSeparator();
  258. menu.addCommandItem (commandManager, CommandIDs::open);
  259. PopupMenu recentFiles;
  260. settings->recentFiles.createPopupMenuItems (recentFiles, recentProjectsBaseID, true, true);
  261. menu.addSubMenu ("Open Recent", recentFiles);
  262. menu.addSeparator();
  263. menu.addCommandItem (commandManager, CommandIDs::closeDocument);
  264. menu.addCommandItem (commandManager, CommandIDs::saveDocument);
  265. menu.addCommandItem (commandManager, CommandIDs::saveDocumentAs);
  266. menu.addCommandItem (commandManager, CommandIDs::saveAll);
  267. menu.addSeparator();
  268. menu.addCommandItem (commandManager, CommandIDs::closeProject);
  269. menu.addCommandItem (commandManager, CommandIDs::saveProject);
  270. menu.addSeparator();
  271. menu.addCommandItem (commandManager, CommandIDs::openInIDE);
  272. menu.addCommandItem (commandManager, CommandIDs::saveAndOpenInIDE);
  273. #if ! JUCE_MAC
  274. menu.addSeparator();
  275. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit);
  276. #endif
  277. }
  278. void ProjucerApplication::createEditMenu (PopupMenu& menu)
  279. {
  280. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::undo);
  281. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::redo);
  282. menu.addSeparator();
  283. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::cut);
  284. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::copy);
  285. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::paste);
  286. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::del);
  287. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::selectAll);
  288. menu.addCommandItem (commandManager, StandardApplicationCommandIDs::deselectAll);
  289. menu.addSeparator();
  290. menu.addCommandItem (commandManager, CommandIDs::showFindPanel);
  291. menu.addCommandItem (commandManager, CommandIDs::findSelection);
  292. menu.addCommandItem (commandManager, CommandIDs::findNext);
  293. menu.addCommandItem (commandManager, CommandIDs::findPrevious);
  294. }
  295. void ProjucerApplication::createViewMenu (PopupMenu& menu)
  296. {
  297. menu.addCommandItem (commandManager, CommandIDs::showFilePanel);
  298. menu.addCommandItem (commandManager, CommandIDs::showConfigPanel);
  299. menu.addCommandItem (commandManager, CommandIDs::showBuildTab);
  300. menu.addCommandItem (commandManager, CommandIDs::showProjectSettings);
  301. menu.addCommandItem (commandManager, CommandIDs::showProjectModules);
  302. menu.addSeparator();
  303. createColourSchemeItems (menu);
  304. }
  305. void ProjucerApplication::createBuildMenu (PopupMenu& menu)
  306. {
  307. menu.addCommandItem (commandManager, CommandIDs::enableBuild);
  308. menu.addCommandItem (commandManager, CommandIDs::toggleContinuousBuild);
  309. menu.addCommandItem (commandManager, CommandIDs::buildNow);
  310. menu.addSeparator();
  311. menu.addCommandItem (commandManager, CommandIDs::launchApp);
  312. menu.addCommandItem (commandManager, CommandIDs::killApp);
  313. menu.addCommandItem (commandManager, CommandIDs::cleanAll);
  314. menu.addSeparator();
  315. menu.addCommandItem (commandManager, CommandIDs::reinstantiateComp);
  316. menu.addCommandItem (commandManager, CommandIDs::showWarnings);
  317. menu.addSeparator();
  318. menu.addCommandItem (commandManager, CommandIDs::nextError);
  319. menu.addCommandItem (commandManager, CommandIDs::prevError);
  320. }
  321. void ProjucerApplication::createColourSchemeItems (PopupMenu& menu)
  322. {
  323. const StringArray presetSchemes (settings->appearance.getPresetSchemes());
  324. if (presetSchemes.size() > 0)
  325. {
  326. PopupMenu schemes;
  327. for (int i = 0; i < presetSchemes.size(); ++i)
  328. schemes.addItem (colourSchemeBaseID + i, presetSchemes[i]);
  329. menu.addSubMenu ("Colour Scheme", schemes);
  330. }
  331. }
  332. void ProjucerApplication::createWindowMenu (PopupMenu& menu)
  333. {
  334. menu.addCommandItem (commandManager, CommandIDs::closeWindow);
  335. menu.addSeparator();
  336. menu.addCommandItem (commandManager, CommandIDs::goToPreviousDoc);
  337. menu.addCommandItem (commandManager, CommandIDs::goToNextDoc);
  338. menu.addCommandItem (commandManager, CommandIDs::goToCounterpart);
  339. menu.addSeparator();
  340. const int numDocs = jmin (50, openDocumentManager.getNumOpenDocuments());
  341. for (int i = 0; i < numDocs; ++i)
  342. {
  343. OpenDocumentManager::Document* doc = openDocumentManager.getOpenDocument(i);
  344. menu.addItem (activeDocumentsBaseID + i, doc->getName());
  345. }
  346. menu.addSeparator();
  347. menu.addCommandItem (commandManager, CommandIDs::closeAllDocuments);
  348. }
  349. void ProjucerApplication::createToolsMenu (PopupMenu& menu)
  350. {
  351. menu.addCommandItem (commandManager, CommandIDs::showGlobalPreferences);
  352. menu.addSeparator();
  353. menu.addCommandItem (commandManager, CommandIDs::showUTF8Tool);
  354. menu.addCommandItem (commandManager, CommandIDs::showSVGPathTool);
  355. menu.addCommandItem (commandManager, CommandIDs::showTranslationTool);
  356. menu.addSeparator();
  357. menu.addCommandItem (commandManager, CommandIDs::loginLogout);
  358. }
  359. void ProjucerApplication::handleMainMenuCommand (int menuItemID)
  360. {
  361. if (menuItemID >= recentProjectsBaseID && menuItemID < recentProjectsBaseID + 100)
  362. {
  363. // open a file from the "recent files" menu
  364. openFile (settings->recentFiles.getFile (menuItemID - recentProjectsBaseID));
  365. }
  366. else if (menuItemID >= activeDocumentsBaseID && menuItemID < activeDocumentsBaseID + 200)
  367. {
  368. if (OpenDocumentManager::Document* doc = openDocumentManager.getOpenDocument (menuItemID - activeDocumentsBaseID))
  369. mainWindowList.openDocument (doc, true);
  370. else
  371. jassertfalse;
  372. }
  373. else if (menuItemID >= colourSchemeBaseID && menuItemID < colourSchemeBaseID + 200)
  374. {
  375. settings->appearance.selectPresetScheme (menuItemID - colourSchemeBaseID);
  376. }
  377. else
  378. {
  379. handleGUIEditorMenuCommand (menuItemID);
  380. }
  381. }
  382. //==============================================================================
  383. void ProjucerApplication::getAllCommands (Array <CommandID>& commands)
  384. {
  385. JUCEApplication::getAllCommands (commands);
  386. const CommandID ids[] = { CommandIDs::newProject,
  387. CommandIDs::open,
  388. CommandIDs::closeAllDocuments,
  389. CommandIDs::saveAll,
  390. CommandIDs::showGlobalPreferences,
  391. CommandIDs::showUTF8Tool,
  392. CommandIDs::showSVGPathTool,
  393. CommandIDs::loginLogout };
  394. commands.addArray (ids, numElementsInArray (ids));
  395. }
  396. void ProjucerApplication::getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
  397. {
  398. switch (commandID)
  399. {
  400. case CommandIDs::newProject:
  401. result.setInfo ("New Project...", "Creates a new Jucer project", CommandCategories::general, 0);
  402. result.defaultKeypresses.add (KeyPress ('n', ModifierKeys::commandModifier, 0));
  403. break;
  404. case CommandIDs::open:
  405. result.setInfo ("Open...", "Opens a Jucer project", CommandCategories::general, 0);
  406. result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0));
  407. break;
  408. case CommandIDs::showGlobalPreferences:
  409. result.setInfo ("Global Preferences...", "Shows the global preferences window.", CommandCategories::general, 0);
  410. break;
  411. case CommandIDs::closeAllDocuments:
  412. result.setInfo ("Close All Documents", "Closes all open documents", CommandCategories::general, 0);
  413. result.setActive (openDocumentManager.getNumOpenDocuments() > 0);
  414. break;
  415. case CommandIDs::saveAll:
  416. result.setInfo ("Save All", "Saves all open documents", CommandCategories::general, 0);
  417. result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier | ModifierKeys::altModifier, 0));
  418. break;
  419. case CommandIDs::showUTF8Tool:
  420. result.setInfo ("UTF-8 String-Literal Helper", "Shows the UTF-8 string literal utility", CommandCategories::general, 0);
  421. break;
  422. case CommandIDs::showSVGPathTool:
  423. result.setInfo ("SVG Path Helper", "Shows the SVG->Path data conversion utility", CommandCategories::general, 0);
  424. break;
  425. case CommandIDs::loginLogout:
  426. result.setInfo (ProjucerLicences::getInstance()->isLoggedIn()
  427. ? String ("Sign out ") + ProjucerLicences::getInstance()->getLoginName()
  428. : String ("Sign in..."),
  429. "Log out of your JUCE account", CommandCategories::general, 0);
  430. result.setActive (ProjucerLicences::getInstance()->isDLLPresent());
  431. break;
  432. default:
  433. JUCEApplication::getCommandInfo (commandID, result);
  434. break;
  435. }
  436. }
  437. bool ProjucerApplication::perform (const InvocationInfo& info)
  438. {
  439. switch (info.commandID)
  440. {
  441. case CommandIDs::newProject: createNewProject(); break;
  442. case CommandIDs::open: askUserToOpenFile(); break;
  443. case CommandIDs::saveAll: openDocumentManager.saveAll(); break;
  444. case CommandIDs::closeAllDocuments: closeAllDocuments (true); break;
  445. case CommandIDs::showUTF8Tool: showUTF8ToolWindow(); break;
  446. case CommandIDs::showSVGPathTool: showSVGPathDataToolWindow(); break;
  447. case CommandIDs::showGlobalPreferences: AppearanceSettings::showGlobalPreferences (globalPreferencesWindow); break;
  448. case CommandIDs::loginLogout: loginOrLogout(); break;
  449. default: return JUCEApplication::perform (info);
  450. }
  451. return true;
  452. }
  453. //==============================================================================
  454. void ProjucerApplication::createNewProject()
  455. {
  456. MainWindow* mw = mainWindowList.getOrCreateEmptyWindow();
  457. mw->showNewProjectWizard();
  458. mainWindowList.avoidSuperimposedWindows (mw);
  459. }
  460. void ProjucerApplication::updateNewlyOpenedProject (Project& p)
  461. {
  462. LiveBuildProjectSettings::updateNewlyOpenedProject (p);
  463. }
  464. void ProjucerApplication::askUserToOpenFile()
  465. {
  466. FileChooser fc ("Open File");
  467. if (fc.browseForFileToOpen())
  468. openFile (fc.getResult());
  469. }
  470. bool ProjucerApplication::openFile (const File& file)
  471. {
  472. return mainWindowList.openFile (file);
  473. }
  474. bool ProjucerApplication::closeAllDocuments (bool askUserToSave)
  475. {
  476. return openDocumentManager.closeAll (askUserToSave);
  477. }
  478. bool ProjucerApplication::closeAllMainWindows()
  479. {
  480. return server != nullptr || mainWindowList.askAllWindowsToClose();
  481. }
  482. //==============================================================================
  483. void ProjucerApplication::showUTF8ToolWindow()
  484. {
  485. if (utf8Window != nullptr)
  486. utf8Window->toFront (true);
  487. else
  488. new FloatingToolWindow ("UTF-8 String Literal Converter",
  489. "utf8WindowPos",
  490. new UTF8Component(), utf8Window,
  491. 500, 500, 300, 300, 1000, 1000);
  492. }
  493. void ProjucerApplication::showSVGPathDataToolWindow()
  494. {
  495. if (svgPathWindow != nullptr)
  496. svgPathWindow->toFront (true);
  497. else
  498. new FloatingToolWindow ("SVG Path Converter",
  499. "svgPathWindowPos",
  500. new SVGPathDataComponent(), svgPathWindow,
  501. 500, 500, 300, 300, 1000, 1000);
  502. }
  503. //==============================================================================
  504. struct FileWithTime
  505. {
  506. FileWithTime (const File& f) : file (f), time (f.getLastModificationTime()) {}
  507. FileWithTime() {}
  508. bool operator< (const FileWithTime& other) const { return time < other.time; }
  509. bool operator== (const FileWithTime& other) const { return time == other.time; }
  510. File file;
  511. Time time;
  512. };
  513. void ProjucerApplication::deleteLogger()
  514. {
  515. const int maxNumLogFilesToKeep = 50;
  516. Logger::setCurrentLogger (nullptr);
  517. if (logger != nullptr)
  518. {
  519. Array<File> logFiles;
  520. logger->getLogFile().getParentDirectory().findChildFiles (logFiles, File::findFiles, false);
  521. if (logFiles.size() > maxNumLogFilesToKeep)
  522. {
  523. Array <FileWithTime> files;
  524. for (int i = 0; i < logFiles.size(); ++i)
  525. files.addUsingDefaultSort (logFiles.getReference(i));
  526. for (int i = 0; i < files.size() - maxNumLogFilesToKeep; ++i)
  527. files.getReference(i).file.deleteFile();
  528. }
  529. }
  530. logger = nullptr;
  531. }
  532. struct LiveBuildConfigItem : public ConfigTreeItemTypes::ConfigTreeItemBase
  533. {
  534. LiveBuildConfigItem (Project& p) : project (p) {}
  535. bool isMissing() override { return false; }
  536. bool canBeSelected() const override { return true; }
  537. bool mightContainSubItems() override { return false; }
  538. String getUniqueName() const override { return "live_build_settings"; }
  539. String getRenamingName() const override { return getDisplayName(); }
  540. String getDisplayName() const override { return "Live Build Settings"; }
  541. void setName (const String&) override {}
  542. Icon getIcon() const override { return Icon (getIcons().config, getContrastingColour (Colours::green, 0.5f)); }
  543. void showDocument() override { showSettingsPage (new SettingsComp (project)); }
  544. void itemOpennessChanged (bool) override {}
  545. Project& project;
  546. //==============================================================================
  547. struct SettingsComp : public Component
  548. {
  549. SettingsComp (Project& p)
  550. {
  551. addAndMakeVisible (&group);
  552. PropertyListBuilder props;
  553. LiveBuildProjectSettings::getLiveSettings (p, props);
  554. group.setProperties (props);
  555. group.setName ("Live Build Settings");
  556. parentSizeChanged();
  557. }
  558. void parentSizeChanged() override { updateSize (*this, group); }
  559. ConfigTreeItemTypes::PropertyGroupComponent group;
  560. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SettingsComp)
  561. };
  562. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LiveBuildConfigItem)
  563. };
  564. void ProjucerApplication::addLiveBuildConfigItem (Project& project, TreeViewItem& parent)
  565. {
  566. parent.addSubItem (new LiveBuildConfigItem (project));
  567. }
  568. PropertiesFile::Options ProjucerApplication::getPropertyFileOptionsFor (const String& filename)
  569. {
  570. PropertiesFile::Options options;
  571. options.applicationName = filename;
  572. options.filenameSuffix = "settings";
  573. options.osxLibrarySubFolder = "Application Support";
  574. #if JUCE_LINUX
  575. options.folderName = "~/.config/Projucer";
  576. #else
  577. options.folderName = "Projucer";
  578. #endif
  579. return options;
  580. }
  581. void ProjucerApplication::hideLoginForm()
  582. {
  583. jassert (MessageManager::getInstance()->isThisTheMessageThread());
  584. loginForm = nullptr;
  585. }
  586. void ProjucerApplication::showLoginForm()
  587. {
  588. if (ProjucerLicences::getInstance()->isDLLPresent())
  589. {
  590. jassert (MessageManager::getInstance()->isThisTheMessageThread());
  591. if (loginForm != nullptr)
  592. return;
  593. DialogWindow::LaunchOptions lo;
  594. lo.dialogTitle = "Log-in to Projucer";
  595. lo.dialogBackgroundColour = Colour (0xffdddddd);
  596. lo.content.setOwned (loginForm = new LoginForm());
  597. lo.escapeKeyTriggersCloseButton = true;
  598. lo.componentToCentreAround = nullptr;
  599. lo.escapeKeyTriggersCloseButton = true;
  600. lo.resizable = false;
  601. lo.useBottomRightCornerResizer = false;
  602. lo.useNativeTitleBar = true;
  603. lo.launchAsync();
  604. getGlobalProperties().setValue ("lastLoginAttemptTime",
  605. (int) (Time::getCurrentTime().toMilliseconds() / 1000));
  606. }
  607. }
  608. void ProjucerApplication::showLoginFormAsyncIfNotTriedRecently()
  609. {
  610. if (ProjucerLicences::getInstance()->isDLLPresent())
  611. {
  612. Time lastLoginAttempt (getGlobalProperties().getValue ("lastLoginAttemptTime").getIntValue() * (int64) 1000);
  613. if (Time::getCurrentTime().getDayOfMonth() != lastLoginAttempt.getDayOfMonth())
  614. startTimer (1000);
  615. }
  616. else
  617. {
  618. getGlobalProperties().removeValue ("lastLoginAttemptTime");
  619. }
  620. }
  621. void ProjucerApplication::timerCallback()
  622. {
  623. stopTimer();
  624. if (! ProjucerLicences::getInstance()->isLoggedIn())
  625. showLoginForm();
  626. }
  627. void ProjucerApplication::updateAllBuildTabs()
  628. {
  629. for (int i = 0; i < mainWindowList.windows.size(); ++i)
  630. if (ProjectContentComponent* p = mainWindowList.windows.getUnchecked(i)->getProjectContentComponent())
  631. p->rebuildProjectTabs();
  632. }
  633. //==============================================================================
  634. void ProjucerApplication::loginOrLogout()
  635. {
  636. ProjucerLicences& status = *ProjucerLicences::getInstance();
  637. if (status.isLoggedIn())
  638. status.logout();
  639. else
  640. showLoginForm();
  641. updateAllBuildTabs();
  642. }
  643. bool ProjucerApplication::currentEULAHasBeenAcceptedPreviously() const
  644. {
  645. return getGlobalProperties().getValue (getEULAChecksumProperty()).getIntValue() != 0;
  646. }
  647. String ProjucerApplication::getEULAChecksumProperty() const
  648. {
  649. return "eulaChecksum_" + MD5 (BinaryData::projucer_EULA_txt,
  650. BinaryData::projucer_EULA_txtSize).toHexString();
  651. }
  652. void ProjucerApplication::setCurrentEULAAccepted (bool hasBeenAccepted) const
  653. {
  654. const String checksum (getEULAChecksumProperty());
  655. auto& globals = getGlobalProperties();
  656. if (hasBeenAccepted)
  657. globals.setValue (checksum, 1);
  658. else
  659. globals.removeValue (checksum);
  660. globals.saveIfNeeded();
  661. }
  662. void ProjucerApplication::initCommandManager()
  663. {
  664. commandManager = new ApplicationCommandManager();
  665. commandManager->registerAllCommandsForTarget (this);
  666. {
  667. CodeDocument doc;
  668. CppCodeEditorComponent ed (File(), doc);
  669. commandManager->registerAllCommandsForTarget (&ed);
  670. }
  671. registerGUIEditorCommands();
  672. }