deploy_dialog.vala 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*
  2. * Copyright (c) 2012-2024 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: GPL-3.0-or-later
  4. */
  5. using Gtk;
  6. using Gee;
  7. namespace Crown
  8. {
  9. public ComboBoxMap make_deploy_config_combo()
  10. {
  11. return new ComboBoxMap(0
  12. , new string?[] { TargetConfig.RELEASE.to_label(), TargetConfig.DEVELOPMENT.to_label() }
  13. , new string?[] { ((int)TargetConfig.RELEASE).to_string(), ((int)TargetConfig.DEVELOPMENT).to_string() }
  14. );
  15. }
  16. public Gtk.Button make_deploy_button(TargetPlatform platform)
  17. {
  18. var btn = new Gtk.Button();
  19. btn.label = "Package Project for %s".printf(platform.to_label());
  20. btn.margin_start = 12;
  21. btn.margin_end = 12;
  22. btn.margin_top = 12;
  23. btn.get_style_context().add_class(Gtk.STYLE_CLASS_SUGGESTED_ACTION);
  24. return btn;
  25. }
  26. #if CROWN_PLATFORM_WINDOWS
  27. public bool can_build_32bit_arm = false;
  28. #else
  29. public bool can_build_32bit_arm = true;
  30. #endif
  31. public class DeployDialog : Gtk.Dialog
  32. {
  33. public RuntimeInstance _editor;
  34. // Android page.
  35. public Gtk.Button _android_deploy_button;
  36. public Gtk.FileChooserButton _android_output_path;
  37. public ComboBoxMap _android_config;
  38. public CheckBox _android_armv7;
  39. public CheckBox _android_armv8;
  40. public CheckBox _android_use_debug_keystore;
  41. public Gtk.FileChooserButton _android_keystore;
  42. public Gtk.Entry _android_keystore_password;
  43. public Gtk.Entry _android_key_alias;
  44. public Gtk.Entry _android_key_password;
  45. public Gtk.Entry _android_app_title;
  46. public Gtk.Entry _android_app_identifier;
  47. public Gtk.Entry _android_app_version_code;
  48. public Gtk.Entry _android_app_version_name;
  49. public PropertyGridSet _android_set;
  50. public Gtk.Box _android_box;
  51. // HTML5 page.
  52. public Gtk.Button _html5_deploy_button;
  53. public Gtk.FileChooserButton _html5_output_path;
  54. public ComboBoxMap _html5_config;
  55. public Gtk.Entry _html5_app_title;
  56. public PropertyGridSet _html5_set;
  57. public Gtk.Box _html5_box;
  58. // Linux page.
  59. public Gtk.Button _linux_deploy_button;
  60. public Gtk.FileChooserButton _linux_output_path;
  61. public ComboBoxMap _linux_config;
  62. public Gtk.Entry _linux_app_title;
  63. public PropertyGridSet _linux_set;
  64. public Gtk.Box _linux_box;
  65. // Windows page.
  66. public Gtk.Button _windows_deploy_button;
  67. public Gtk.FileChooserButton _windows_output_path;
  68. public ComboBoxMap _windows_config;
  69. public EntryText _windows_app_title;
  70. public PropertyGridSet _windows_set;
  71. public Gtk.Box _windows_box;
  72. public Gtk.Notebook _notebook;
  73. public DeployDialog(RuntimeInstance editor)
  74. {
  75. this.title = "Deploy";
  76. this.border_width = 0;
  77. this.set_icon_name(CROWN_ICON_NAME);
  78. _editor = editor;
  79. // Android page.
  80. _android_deploy_button = make_deploy_button(TargetPlatform.ANDROID);
  81. _android_deploy_button.clicked.connect(() => {
  82. // Validate input fields.
  83. string? output_path = _android_output_path.get_filename();
  84. if (output_path == null) {
  85. loge("Select a valid output Destination");
  86. return;
  87. }
  88. string app_title = _android_app_title.text.strip();
  89. if (app_title.length == 0) {
  90. loge("Enter a valid App Title");
  91. return;
  92. }
  93. string app_identifier = _android_app_identifier.text.strip();
  94. if (app_title.length == 0 || app_identifier.split(".").length != 3) {
  95. loge("Enter a valid App Identifier");
  96. return;
  97. }
  98. int app_version_code;
  99. if (int.try_parse(_android_app_version_code.text, out app_version_code) == false) {
  100. loge("Enter a valid App Version Code");
  101. return;
  102. }
  103. string app_version_name = _android_app_version_name.text.strip();
  104. if (app_version_name.length == 0) {
  105. loge("Enter a valid App Version Name");
  106. return;
  107. }
  108. string? keystore_path = _android_use_debug_keystore.get_active()
  109. ? GLib.Path.build_filename(GLib.Environment.get_home_dir(), ".android", "debug.keystore")
  110. : _android_keystore.get_filename()
  111. ;
  112. if (keystore_path == null) {
  113. loge("Enter a valid Keystore file");
  114. return;
  115. }
  116. string keystore_pass = _android_use_debug_keystore.get_active()
  117. ? "android"
  118. : _android_keystore_password.text
  119. ;
  120. if (keystore_path.length == 0) {
  121. loge("Enter a valid Keystore Password");
  122. return;
  123. }
  124. string key_alias = _android_use_debug_keystore.get_active()
  125. ? "androiddebugkey"
  126. : _android_key_alias.text
  127. ;
  128. if (key_alias.length == 0) {
  129. loge("Enter a valid Key Alias");
  130. return;
  131. }
  132. string key_pass = _android_use_debug_keystore.get_active()
  133. ? "android"
  134. : _android_key_password.text
  135. ;
  136. if (key_pass.length == 0) {
  137. loge("Enter a valid Key Password");
  138. return;
  139. }
  140. TargetArch[] archs =
  141. {
  142. TargetArch.ARM,
  143. TargetArch.ARM64
  144. };
  145. for (int ii = 0; ii < archs.length; ++ii) {
  146. if (archs[ii] == TargetArch.ARM && !_android_armv7.value)
  147. continue;
  148. if (archs[ii] == TargetArch.ARM64 && !_android_armv8.value)
  149. continue;
  150. // Create the package.
  151. GLib.Variant paramz[] =
  152. {
  153. (string)output_path,
  154. int.parse(_android_config.get_active_id()),
  155. app_title,
  156. app_identifier,
  157. app_version_code,
  158. app_version_name,
  159. keystore_path,
  160. keystore_pass,
  161. key_alias,
  162. key_pass,
  163. archs[ii]
  164. };
  165. GLib.Application.get_default().activate_action("create-package-android"
  166. , new GLib.Variant.tuple(paramz));
  167. }
  168. });
  169. _android_output_path = new Gtk.FileChooserButton("Select folder", Gtk.FileChooserAction.SELECT_FOLDER);
  170. _android_config = make_deploy_config_combo();
  171. _android_armv7 = new CheckBox();
  172. _android_armv7.value = false;
  173. _android_armv8 = new CheckBox();
  174. _android_armv8.value = true;
  175. _android_use_debug_keystore = new CheckBox();
  176. _android_use_debug_keystore.value_changed.connect(() => { android_set_debug_keystore(); });
  177. _android_use_debug_keystore.value = true;
  178. _android_keystore = new Gtk.FileChooserButton("Select file", Gtk.FileChooserAction.OPEN);
  179. _android_keystore_password = new Gtk.Entry();
  180. _android_keystore_password.set_visibility(false);
  181. _android_keystore_password.input_purpose = Gtk.InputPurpose.PASSWORD;
  182. _android_key_alias = new Gtk.Entry();
  183. _android_key_password = new Gtk.Entry();
  184. _android_key_password.set_visibility(false);
  185. _android_key_password.input_purpose = Gtk.InputPurpose.PASSWORD;
  186. _android_app_title = new EntryText();
  187. _android_app_title.placeholder_text = "My Application";
  188. _android_app_identifier = new Gtk.Entry();
  189. _android_app_identifier.placeholder_text = "org.company.product";
  190. _android_app_version_code = new Gtk.Entry();
  191. _android_app_version_code.input_purpose = Gtk.InputPurpose.DIGITS;
  192. _android_app_version_code.placeholder_text = "1";
  193. _android_app_version_name = new Gtk.Entry();
  194. _android_app_version_name.placeholder_text = "1.0";
  195. android_set_debug_keystore();
  196. _android_set = new PropertyGridSet();
  197. _android_set.border_width = 12;
  198. // Android Output grid.
  199. PropertyGrid cv;
  200. cv = new PropertyGrid();
  201. cv.column_homogeneous = true;
  202. cv.add_row("Destination", _android_output_path);
  203. cv.add_row("Config", _android_config);
  204. cv.add_row("ARMv7-A", _android_armv7).sensitive = can_build_32bit_arm;
  205. _android_armv7.sensitive = can_build_32bit_arm;
  206. cv.add_row("ARMv8-A", _android_armv8);
  207. _android_set.add_property_grid(cv, "Output");
  208. // Android Application.
  209. cv = new PropertyGrid();
  210. cv.column_homogeneous = true;
  211. cv.add_row("Title", _android_app_title);
  212. cv.add_row("Identifier", _android_app_identifier);
  213. cv.add_row("Version Code", _android_app_version_code);
  214. cv.add_row("Version Name", _android_app_version_name);
  215. _android_set.add_property_grid(cv, "Application");
  216. // Android Signing.
  217. cv = new PropertyGrid();
  218. cv.column_homogeneous = true;
  219. cv.add_row("Use debug keystore", _android_use_debug_keystore);
  220. cv.add_row("Keystore", _android_keystore);
  221. cv.add_row("Keystore password", _android_keystore_password);
  222. cv.add_row("Alias", _android_key_alias);
  223. cv.add_row("Key password", _android_key_password);
  224. _android_set.add_property_grid(cv, "Signing");
  225. // Android box.
  226. _android_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
  227. _android_box.pack_start(_android_deploy_button, false, true, 0);
  228. _android_box.pack_start(_android_set, false, true, 0);
  229. // HTML5 page.
  230. _html5_deploy_button = make_deploy_button(TargetPlatform.HTML5);
  231. _html5_deploy_button.clicked.connect(() => {
  232. // Validate input fields.
  233. string? output_path = _html5_output_path.get_filename();
  234. if (output_path == null) {
  235. loge("Select a valid output Destination");
  236. return;
  237. }
  238. string app_title = _html5_app_title.text.strip();
  239. if (app_title.length == 0) {
  240. loge("Enter a valid Title");
  241. return;
  242. }
  243. // Create the package.
  244. GLib.Variant paramz[] =
  245. {
  246. (string)output_path,
  247. int.parse(_html5_config.get_active_id()),
  248. app_title
  249. };
  250. GLib.Application.get_default().activate_action("create-package-html5"
  251. , new GLib.Variant.tuple(paramz));
  252. });
  253. _html5_output_path = new Gtk.FileChooserButton("Select folder", Gtk.FileChooserAction.SELECT_FOLDER);
  254. _html5_config = make_deploy_config_combo();
  255. _html5_app_title = new EntryText();
  256. _html5_app_title.placeholder_text = "My Application";
  257. _html5_set = new PropertyGridSet();
  258. _html5_set.border_width = 12;
  259. // HTML5 box.
  260. _html5_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
  261. _html5_box.pack_start(_html5_deploy_button, false, true, 0);
  262. _html5_box.pack_start(_html5_set, false, true, 0);
  263. // HTML5 General page.
  264. cv = new PropertyGrid();
  265. cv.column_homogeneous = true;
  266. cv.add_row("Destination", _html5_output_path);
  267. cv.add_row("Config", _html5_config);
  268. _html5_set.add_property_grid(cv, "Output");
  269. // HTML5 Application.
  270. cv = new PropertyGrid();
  271. cv.column_homogeneous = true;
  272. cv.add_row("Title", _html5_app_title);
  273. _html5_set.add_property_grid(cv, "Application");
  274. // Linux page.
  275. _linux_deploy_button = make_deploy_button(TargetPlatform.LINUX);
  276. _linux_deploy_button.clicked.connect(() => {
  277. // Validate input fields.
  278. string? output_path = _linux_output_path.get_filename();
  279. if (output_path == null) {
  280. loge("Select a valid output Destination");
  281. return;
  282. }
  283. string app_title = _linux_app_title.text.strip();
  284. if (app_title.length == 0) {
  285. loge("Enter a valid Title");
  286. return;
  287. }
  288. // Create the package.
  289. GLib.Variant paramz[] =
  290. {
  291. (string)output_path,
  292. int.parse(_linux_config.get_active_id()),
  293. app_title
  294. };
  295. GLib.Application.get_default().activate_action("create-package-linux"
  296. , new GLib.Variant.tuple(paramz));
  297. });
  298. _linux_output_path = new Gtk.FileChooserButton("Select folder", Gtk.FileChooserAction.SELECT_FOLDER);
  299. _linux_config = make_deploy_config_combo();
  300. _linux_app_title = new EntryText();
  301. _linux_app_title.placeholder_text = "My Application";
  302. _linux_set = new PropertyGridSet();
  303. _linux_set.border_width = 12;
  304. // Linux box.
  305. _linux_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
  306. _linux_box.pack_start(_linux_deploy_button, false, true, 0);
  307. _linux_box.pack_start(_linux_set, false, true, 0);
  308. // Linux General page.
  309. cv = new PropertyGrid();
  310. cv.column_homogeneous = true;
  311. cv.add_row("Destination", _linux_output_path);
  312. cv.add_row("Config", _linux_config);
  313. _linux_set.add_property_grid(cv, "Output");
  314. // Linux Application.
  315. cv = new PropertyGrid();
  316. cv.column_homogeneous = true;
  317. cv.add_row("Title", _linux_app_title);
  318. _linux_set.add_property_grid(cv, "Application");
  319. // Windows page.
  320. _windows_deploy_button = make_deploy_button(TargetPlatform.WINDOWS);
  321. _windows_deploy_button.clicked.connect(() => {
  322. // Validate input fields.
  323. string? output_path = _windows_output_path.get_filename();
  324. if (output_path == null) {
  325. loge("Select a valid output Destination");
  326. return;
  327. }
  328. string app_title = _windows_app_title.text.strip();
  329. if (app_title.length == 0) {
  330. loge("Enter a valid Title");
  331. return;
  332. }
  333. // Create the package.
  334. GLib.Variant paramz[] =
  335. {
  336. (string)output_path,
  337. int.parse(_windows_config.get_active_id()),
  338. app_title
  339. };
  340. GLib.Application.get_default().activate_action("create-package-windows"
  341. , new GLib.Variant.tuple(paramz));
  342. });
  343. _windows_output_path = new Gtk.FileChooserButton("Select folder", Gtk.FileChooserAction.SELECT_FOLDER);
  344. _windows_config = make_deploy_config_combo();
  345. _windows_app_title = new EntryText();
  346. _windows_app_title.placeholder_text = "My Application";
  347. _windows_set = new PropertyGridSet();
  348. _windows_set.border_width = 12;
  349. // Windows box.
  350. _windows_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
  351. _windows_box.pack_start(_windows_deploy_button, false, true, 0);
  352. _windows_box.pack_start(_windows_set, false, true, 0);
  353. // Windows General page.
  354. cv = new PropertyGrid();
  355. cv.column_homogeneous = true;
  356. cv.add_row("Destination", _windows_output_path);
  357. cv.add_row("Config", _windows_config);
  358. _windows_set.add_property_grid(cv, "Output");
  359. // Windows Application.
  360. cv = new PropertyGrid();
  361. cv.column_homogeneous = true;
  362. cv.add_row("Title", _windows_app_title);
  363. _windows_set.add_property_grid(cv, "Application");
  364. // Add pages.
  365. _notebook = new Gtk.Notebook();
  366. _notebook.append_page(_android_box, new Gtk.Label(TargetPlatform.ANDROID.to_label()));
  367. _notebook.append_page(_html5_box, new Gtk.Label(TargetPlatform.HTML5.to_label()));
  368. #if CROWN_PLATFORM_LINUX
  369. _notebook.append_page(_linux_box, new Gtk.Label(TargetPlatform.LINUX.to_label()));
  370. #elif CROWN_PLATFORM_WINDOWS
  371. _notebook.append_page(_windows_box, new Gtk.Label(TargetPlatform.WINDOWS.to_label()));
  372. #endif
  373. _notebook.vexpand = true;
  374. _notebook.show_border = false;
  375. this.get_content_area().border_width = 0;
  376. this.get_content_area().add(_notebook);
  377. }
  378. public void android_set_debug_keystore()
  379. {
  380. bool sensitive = !_android_use_debug_keystore.get_active();
  381. _android_keystore.sensitive = sensitive;
  382. _android_keystore_password.sensitive = sensitive;
  383. _android_key_alias.sensitive = sensitive;
  384. _android_key_password.sensitive = sensitive;
  385. }
  386. }
  387. } /* namespace Crown */