ProtocolTemplate.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * Copyright 2009-2011, Pier Luigi Fiorini. All rights reserved.
  3. * Copyright 2003-2009, IM Kit Team. All rights reserved.
  4. * Copyright 2021, Jaidyn Levesque. All rights reserved.
  5. * Distributed under the terms of the MIT License.
  6. *
  7. * Authors:
  8. * Michael Davidson, slaad@bong.com.au
  9. * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
  10. * Jaidyn Levesque, jadedctrl@teknik.io
  11. */
  12. #include "ProtocolTemplate.h"
  13. #include <cstdio>
  14. #include <stdlib.h>
  15. #include <CheckBox.h>
  16. #include <GroupLayoutBuilder.h>
  17. #include <MenuItem.h>
  18. #include <MenuField.h>
  19. #include <PopUpMenu.h>
  20. #include <ScrollView.h>
  21. #include <StringView.h>
  22. #include <TextControl.h>
  23. #include "ChatProtocol.h"
  24. #include "ChatProtocolAddOn.h"
  25. #include "Utils.h"
  26. const float kDividerWidth = 1.0f;
  27. ProtocolTemplate::ProtocolTemplate(ChatProtocol* protocol, const char* type)
  28. :
  29. fProtocol(protocol),
  30. fTemplate(new BMessage())
  31. {
  32. // Load protocol's settings template
  33. BMessage settingsTemplate = fProtocol->SettingsTemplate(type);
  34. if (settingsTemplate.IsEmpty() == true) {
  35. size_t size;
  36. const void* buff =
  37. ChatResources().LoadResource(B_MESSAGE_TYPE, type, &size);
  38. if (buff != NULL)
  39. settingsTemplate.Unflatten((const char*)buff);
  40. }
  41. *fTemplate = settingsTemplate;
  42. }
  43. ProtocolTemplate::ProtocolTemplate(BMessage pTemplate)
  44. :
  45. fProtocol(NULL),
  46. fTemplate(new BMessage())
  47. {
  48. *fTemplate = pTemplate;
  49. }
  50. ProtocolTemplate::~ProtocolTemplate()
  51. {
  52. delete fTemplate;
  53. }
  54. ChatProtocol*
  55. ProtocolTemplate::Protocol() const
  56. {
  57. return fProtocol;
  58. }
  59. status_t
  60. ProtocolTemplate::Load(BView* parent, BMessage* settings)
  61. {
  62. if (!parent)
  63. debugger("Couldn't build protocol's settings GUI on a NULL parent!");
  64. BMessage curr;
  65. // Setup layout
  66. parent->SetLayout(new BGroupLayout(B_VERTICAL));
  67. BGroupLayoutBuilder layout(B_VERTICAL);
  68. for (int32 i = 0; fTemplate->FindMessage("setting", i, &curr) == B_OK; i++) {
  69. char temp[512];
  70. // Get stuff from settings template
  71. const char* name = curr.FindString("name");
  72. const char* desc = curr.FindString("description");
  73. const char* value = NULL;
  74. int32 type = -1;
  75. bool secret = false;
  76. bool freeText = true;
  77. bool multiLine = false;
  78. BView* control = NULL;
  79. BMenu* menu = NULL;
  80. // Ignore settings with errors
  81. if (curr.FindInt32("type", &type) != B_OK)
  82. continue;
  83. switch (type) {
  84. case B_STRING_TYPE: {
  85. if (curr.FindString("valid_value")) {
  86. // It's a "select one of these" setting
  87. freeText = false;
  88. menu = new BPopUpMenu(name);
  89. for (int j = 0; curr.FindString("valid_value", j); j++) {
  90. BMenuItem* item
  91. = new BMenuItem(curr.FindString("valid_value", j),
  92. NULL);
  93. menu->AddItem(item);
  94. }
  95. if (settings)
  96. value = settings->FindString(name);
  97. if (value)
  98. menu->FindItem(value)->SetMarked(true);
  99. } else {
  100. // It's a free-text setting
  101. if (curr.FindBool("multi_line", &multiLine) != B_OK)
  102. multiLine = false;
  103. if (settings)
  104. value = settings->FindString(name);
  105. if (!value)
  106. value = curr.FindString("default");
  107. if (curr.FindBool("is_secret",&secret) != B_OK)
  108. secret = false;
  109. }
  110. break;
  111. }
  112. case B_INT32_TYPE: {
  113. if (curr.FindInt32("valid_value")) {
  114. // It's a "select one of these" setting
  115. freeText = false;
  116. menu = new BPopUpMenu(name);
  117. int32 def = 0;
  118. status_t hasValue = B_ERROR;
  119. if (settings)
  120. settings->FindInt32(name, 0, &def);
  121. if (hasValue != B_OK)
  122. hasValue = curr.FindInt32("default", 0, &def);
  123. int32 v = 0;
  124. for (int32 j = 0; curr.FindInt32("valid_value", j, &v) == B_OK; j++) {
  125. sprintf(temp, "%ld", v);
  126. BMenuItem* item = new BMenuItem(temp, NULL);
  127. if (hasValue != B_OK && j == 0)
  128. item->SetMarked(true);
  129. else if ((hasValue == B_OK) && (def == v))
  130. item->SetMarked(true);
  131. menu->AddItem(item);
  132. }
  133. } else {
  134. // It's a free-text (but number) setting
  135. int32 v = 0;
  136. if (settings && settings->FindInt32(name, &v) == B_OK) {
  137. sprintf(temp,"%ld", v);
  138. value = temp;
  139. } else if (curr.FindInt32("default", &v) == B_OK) {
  140. sprintf(temp,"%ld", v);
  141. value = temp;
  142. }
  143. if (curr.FindBool("is_secret",&secret) != B_OK)
  144. secret = false;
  145. }
  146. break;
  147. }
  148. case B_BOOL_TYPE: {
  149. bool active;
  150. if (settings && settings->FindBool(name, &active) != B_OK) {
  151. if (curr.FindBool("default", &active) != B_OK)
  152. active = false;
  153. }
  154. control = new BCheckBox(name, desc, NULL);
  155. if (active)
  156. dynamic_cast<BCheckBox*>(control)->SetValue(B_CONTROL_ON);
  157. break;
  158. }
  159. default:
  160. continue;
  161. }
  162. if (!value)
  163. value = "";
  164. if (!control) {
  165. if (freeText) {
  166. if (!multiLine) {
  167. control = new BTextControl(name, desc, value, NULL);
  168. if (secret) {
  169. dynamic_cast<BTextControl*>(control)->TextView()->HideTyping(true);
  170. dynamic_cast<BTextControl*>(control)->SetText(value);
  171. }
  172. dynamic_cast<BTextControl*>(control)->SetDivider(
  173. kDividerWidth);
  174. } else {
  175. BStringView* label = new BStringView("NA", desc,
  176. B_WILL_DRAW);
  177. layout.Add(label);
  178. BTextView* textView = new BTextView(name);
  179. control = new BScrollView("NA", textView, 0, false, true);
  180. textView->SetText(value);
  181. }
  182. } else {
  183. control = new BMenuField(name, desc, menu);
  184. dynamic_cast<BMenuField*>(control)->SetDivider(kDividerWidth);
  185. }
  186. }
  187. #if 0
  188. if (curr.FindString("help"))
  189. gHelper.SetHelp(control, strdup(curr.FindString("help")));
  190. #endif
  191. layout.Add(control);
  192. }
  193. layout.AddGlue();
  194. parent->AddChild(layout);
  195. return B_OK;
  196. }
  197. status_t
  198. ProtocolTemplate::Save(BView* parent, BMessage* settings, BString* errorText)
  199. {
  200. if (!parent)
  201. debugger("Couldn't save protocol's settings GUI on a NULL parent!");
  202. BMessage cur;
  203. for (int32 i = 0; fTemplate->FindMessage("setting", i, &cur) == B_OK; i++) {
  204. const char* name = cur.FindString("name");
  205. BString error = cur.FindString("error");
  206. // Skip NULL names
  207. if (!name)
  208. continue;
  209. int32 type = -1;
  210. if (cur.FindInt32("type", &type) != B_OK)
  211. continue;
  212. BView* view = parent->FindView(name);
  213. if (!view)
  214. continue;
  215. BTextControl* textControl
  216. = dynamic_cast<BTextControl*>(view);
  217. if (textControl && BString(textControl->Text()).IsEmpty() == true
  218. && error.IsEmpty() == false)
  219. {
  220. if (errorText != NULL)
  221. errorText->SetTo(error);
  222. return B_BAD_VALUE;
  223. }
  224. else if (textControl)
  225. switch (type) {
  226. case B_STRING_TYPE:
  227. settings->AddString(name, textControl->Text());
  228. break;
  229. case B_INT32_TYPE:
  230. settings->AddInt32(name, atoi(textControl->Text()));
  231. break;
  232. default:
  233. return B_BAD_TYPE;
  234. }
  235. BMenuField* menuField
  236. = dynamic_cast<BMenuField*>(view);
  237. if (menuField) {
  238. BMenuItem* item = menuField->Menu()->FindMarked();
  239. if (!item)
  240. return B_ERROR;
  241. switch (type) {
  242. case B_STRING_TYPE:
  243. settings->AddString(name, item->Label());
  244. break;
  245. case B_INT32_TYPE:
  246. settings->AddInt32(name, atoi(item->Label()));
  247. break;
  248. default:
  249. return B_BAD_TYPE;
  250. }
  251. }
  252. BCheckBox* checkBox
  253. = dynamic_cast<BCheckBox*>(view);
  254. if (checkBox)
  255. settings->AddBool(name, (checkBox->Value() == B_CONTROL_ON));
  256. BTextView* textView = dynamic_cast<BTextView*>(view);
  257. if (textView)
  258. settings->AddString(name, textView->Text());
  259. }
  260. BMessage hidden;
  261. if (fTemplate->FindMessage("hidden", &hidden) == B_OK)
  262. settings->AddMessage("hidden", &hidden);
  263. return B_OK;
  264. }