MainWindow.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. /*
  2. * Copyright 2009-2011, Andrea Anzani. All rights reserved.
  3. * Copyright 2009-2011, Pier Luigi Fiorini. All rights reserved.
  4. * Copyright 2021, Jaidyn Levesque. All rights reserved.
  5. * Distributed under the terms of the MIT License.
  6. *
  7. * Authors:
  8. * Andrea Anzani, andrea.anzani@gmail.com
  9. * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
  10. * Jaidyn Levesque, jadedctrl@teknik.io
  11. */
  12. #include <Application.h>
  13. #include <Alert.h>
  14. #include <Beep.h>
  15. #include <Catalog.h>
  16. #include <LayoutBuilder.h>
  17. #include <MenuBar.h>
  18. #include <ScrollView.h>
  19. #include <TranslationUtils.h>
  20. #include "AccountDialog.h"
  21. #include "AccountsWindow.h"
  22. #include "AppMessages.h"
  23. #include "AppPreferences.h"
  24. #include "ChatOMatic.h"
  25. #include "ChatProtocolAddOn.h"
  26. #include "ChatProtocolMessages.h"
  27. #include "ConversationItem.h"
  28. #include "ConversationListView.h"
  29. #include "ConversationView.h"
  30. #include "MainWindow.h"
  31. #include "NotifyMessage.h"
  32. #include "PreferencesWindow.h"
  33. #include "ProtocolManager.h"
  34. #include "ProtocolSettings.h"
  35. #include "ReplicantStatusView.h"
  36. #include "RosterEditWindow.h"
  37. #include "RosterWindow.h"
  38. #include "StatusManager.h"
  39. #include "StatusView.h"
  40. #include "TemplateWindow.h"
  41. #undef B_TRANSLATION_CONTEXT
  42. #define B_TRANSLATION_CONTEXT "MainWindow"
  43. const uint32 kLogin = 'LOGI';
  44. MainWindow::MainWindow()
  45. :
  46. BWindow(AppPreferences::Get()->MainWindowRect,
  47. B_TRANSLATE_SYSTEM_NAME(APP_NAME), B_TITLED_WINDOW, 0),
  48. fWorkspaceChanged(false),
  49. fConversation(NULL),
  50. fRosterWindow(NULL),
  51. fServer(NULL)
  52. {
  53. // Filter messages using Server
  54. fServer = new Server();
  55. AddFilter(fServer);
  56. _InitInterface();
  57. add_system_beep_event(APP_MENTION_BEEP);
  58. add_system_beep_event(APP_MESSAGE_BEEP);
  59. //TODO check for errors here
  60. ReplicantStatusView::InstallReplicant();
  61. }
  62. void
  63. MainWindow::Start()
  64. {
  65. // No accounts, show account window
  66. if (ProtocolManager::Get()->CountProtocolInstances() == 0)
  67. MessageReceived(new BMessage(APP_SHOW_ACCOUNTS));
  68. // Login all accounts
  69. fServer->LoginAll();
  70. }
  71. bool
  72. MainWindow::QuitRequested()
  73. {
  74. int32 button_index = 0;
  75. if(!AppPreferences::Get()->DisableQuitConfirm)
  76. {
  77. BAlert* alert = new BAlert(B_TRANSLATE("Closing"),
  78. B_TRANSLATE("Are you sure you want to quit?"),
  79. B_TRANSLATE("Yes"), B_TRANSLATE("No"), NULL, B_WIDTH_AS_USUAL,
  80. B_OFFSET_SPACING, B_WARNING_ALERT);
  81. alert->SetShortcut(0, B_ESCAPE);
  82. button_index = alert->Go();
  83. }
  84. AppPreferences::Get()->MainWindowListWeight = fSplitView->ItemWeight(0);
  85. AppPreferences::Get()->MainWindowChatWeight = fSplitView->ItemWeight(1);
  86. AppPreferences::Get()->MainWindowRect = Frame();
  87. if(button_index == 0) {
  88. fServer->Quit();
  89. AppPreferences::Get()->Save();
  90. ReplicantStatusView::RemoveReplicant();
  91. be_app->PostMessage(B_QUIT_REQUESTED);
  92. return true;
  93. } else
  94. return false;
  95. }
  96. void
  97. MainWindow::MessageReceived(BMessage* message)
  98. {
  99. switch (message->what) {
  100. case APP_SHOW_SETTINGS:
  101. {
  102. PreferencesWindow* win = new PreferencesWindow();
  103. win->Show();
  104. break;
  105. }
  106. case APP_SHOW_ACCOUNTS:
  107. {
  108. AccountsWindow* win = new AccountsWindow();
  109. win->Show();
  110. break;
  111. }
  112. case APP_EDIT_ACCOUNT:
  113. {
  114. void* settings = NULL;
  115. BString account = message->FindString("account");
  116. message->FindPointer("settings", &settings);
  117. if (account.IsEmpty() == false && settings != NULL) {
  118. AccountDialog* win = new AccountDialog("Editing account",
  119. (ProtocolSettings*)settings, account.String());
  120. win->Show();
  121. }
  122. break;
  123. }
  124. case APP_TOGGLE_ACCOUNT:
  125. {
  126. ProtocolManager* protoMan = ProtocolManager::Get();
  127. ProtocolSettings* settings = NULL;
  128. BString account = message->FindString("account");
  129. int64 instance = message->GetInt64("instance", -1);
  130. message->FindPointer("settings", (void**)&settings);
  131. if (account.IsEmpty() == false && settings != NULL)
  132. protoMan->ToggleAccount(settings, account);
  133. break;
  134. }
  135. case APP_NEW_CHAT:
  136. {
  137. BMessage* newMsg = new BMessage(IM_MESSAGE);
  138. newMsg->AddInt32("im_what", IM_CREATE_CHAT);
  139. fRosterWindow = new RosterWindow(B_TRANSLATE("Invite contact to "
  140. "chat" B_UTF8_ELLIPSIS), newMsg, new BMessenger(this), fServer);
  141. fRosterWindow->Show();
  142. break;
  143. }
  144. case APP_NEW_ROOM:
  145. {
  146. BMessage* createMsg = new BMessage(IM_MESSAGE);
  147. createMsg->AddInt32("im_what", IM_CREATE_ROOM);
  148. TemplateWindow* win = new TemplateWindow(B_TRANSLATE("Create room"),
  149. "create_room", createMsg, fServer);
  150. win->Show();
  151. break;
  152. }
  153. case APP_JOIN_ROOM:
  154. {
  155. BMessage* joinMsg = new BMessage(IM_MESSAGE);
  156. joinMsg->AddInt32("im_what", IM_JOIN_ROOM);
  157. TemplateWindow* win = new TemplateWindow(B_TRANSLATE("Join a room"),
  158. "join_room", joinMsg, fServer);
  159. win->Show();
  160. break;
  161. }
  162. case APP_SEND_INVITE:
  163. {
  164. if (fConversation == NULL)
  165. break;
  166. BString chat_id = fConversation->GetId();
  167. BMessage* invite = new BMessage(IM_MESSAGE);
  168. invite->AddInt32("im_what", IM_ROOM_SEND_INVITE);
  169. invite->AddString("chat_id", chat_id);
  170. ProtocolLooper* plooper = fConversation->GetProtocolLooper();
  171. BLooper* looper = (BLooper*)plooper;
  172. fRosterWindow = new RosterWindow(B_TRANSLATE("Invite contact to "
  173. "chat" B_UTF8_ELLIPSIS), invite, new BMessenger(looper), fServer,
  174. plooper->GetInstance());
  175. fRosterWindow->Show();
  176. break;
  177. }
  178. case APP_EDIT_ROSTER:
  179. {
  180. RosterEditWindow::Get(fServer)->Show();
  181. break;
  182. }
  183. case APP_MOVE_UP:
  184. {
  185. int32 index = fListView->CurrentSelection();
  186. if (index > 0)
  187. fListView->Select(index - 1);
  188. break;
  189. }
  190. case APP_MOVE_DOWN:
  191. {
  192. int32 index = fListView->CurrentSelection();
  193. int32 count = fListView->CountItems();
  194. if (index < (count - 1))
  195. fListView->Select(index + 1);
  196. break;
  197. }
  198. case APP_REPLICANT_STATUS_SET:
  199. {
  200. int32 status;
  201. message->FindInt32("status", &status);
  202. StatusManager* statusMan = StatusManager::Get();
  203. statusMan->SetStatus((UserStatus)status);
  204. break;
  205. }
  206. case APP_REPLICANT_SHOW_WINDOW:
  207. {
  208. if (LockLooper()) {
  209. SetWorkspaces(B_CURRENT_WORKSPACE);
  210. if ((IsMinimized() || IsHidden())
  211. || fWorkspaceChanged) {
  212. Minimize(false);
  213. Show();
  214. fWorkspaceChanged = false;
  215. } else if ((!IsMinimized() || !IsHidden())
  216. || (!fWorkspaceChanged)) {
  217. Minimize(true);
  218. }
  219. UnlockLooper();
  220. }
  221. break;
  222. }
  223. case APP_ACCOUNT_DISABLED: {
  224. _ToggleMenuItems();
  225. _RefreshAccountsMenu();
  226. fListView->RemoveAccount(message->GetInt64("instance", -1));
  227. break;
  228. }
  229. case IM_MESSAGE:
  230. ImMessage(message);
  231. break;
  232. case B_ABOUT_REQUESTED:
  233. be_app->PostMessage(message);
  234. break;
  235. default:
  236. BWindow::MessageReceived(message);
  237. }
  238. }
  239. void
  240. MainWindow::ImMessage(BMessage* msg)
  241. {
  242. int32 im_what = msg->FindInt32("im_what");
  243. switch (im_what) {
  244. case IM_OWN_CONTACT_INFO:
  245. {
  246. int64 instance;
  247. if (msg->FindInt64("instance", &instance) == B_OK) {
  248. ProtocolLooper* looper = fServer->GetProtocolLooper(instance);
  249. if (looper != NULL) {
  250. Contact* contact = looper->GetOwnContact();
  251. contact->RegisterObserver(fStatusView);
  252. }
  253. }
  254. break;
  255. }
  256. case IM_ROOM_JOINED:
  257. case IM_ROOM_PARTICIPANTS:
  258. case IM_ROOM_CREATED:
  259. case IM_CHAT_CREATED:
  260. case IM_MESSAGE_RECEIVED:
  261. case IM_MESSAGE_SENT:
  262. {
  263. _EnsureConversationItem(msg);
  264. break;
  265. }
  266. case IM_ROOM_LEFT:
  267. {
  268. ConversationItem* item = _EnsureConversationItem(msg);
  269. if (item == NULL)
  270. break;
  271. delete item->GetConversation();
  272. break;
  273. }
  274. case IM_USER_AVATAR_SET:
  275. case IM_USER_STATUS_SET:
  276. case IM_CONTACT_INFO:
  277. case IM_EXTENDED_CONTACT_INFO:
  278. case IM_ROSTER_CONTACT_REMOVED: {
  279. if (fRosterWindow != NULL)
  280. fRosterWindow->PostMessage(msg);
  281. if (RosterEditWindow::Check() == true)
  282. RosterEditWindow::Get(fServer)->PostMessage(msg);
  283. break;
  284. }
  285. case IM_PROTOCOL_READY: {
  286. if (fConversation == NULL)
  287. fBackupChatView->MessageReceived(msg);
  288. fStatusView->MessageReceived(msg);
  289. _ToggleMenuItems();
  290. _RefreshAccountsMenu();
  291. fListView->AddAccount(msg->GetInt64("instance", -1));
  292. break;
  293. }
  294. case IM_PROTOCOL_DISABLE:
  295. fStatusView->MessageReceived(msg);
  296. break;
  297. }
  298. }
  299. void
  300. MainWindow::WorkspaceActivated(int32 workspace, bool active)
  301. {
  302. if (active)
  303. fWorkspaceChanged = false;
  304. else
  305. fWorkspaceChanged = true;
  306. }
  307. void
  308. MainWindow::SetConversation(Conversation* chat)
  309. {
  310. fConversation = chat;
  311. if (chat != NULL) {
  312. SetConversationView(chat->GetView());
  313. BString title(chat->GetName());
  314. title << " ― " << APP_NAME;
  315. SetTitle(title.String());
  316. }
  317. else {
  318. SetConversationView(fBackupChatView);
  319. SetTitle(APP_NAME);
  320. }
  321. }
  322. void
  323. MainWindow::SetConversationView(ConversationView* chatView)
  324. {
  325. // Save split weights
  326. float weightChat = fRightView->ItemWeight((int32)0);
  327. float weightSend = fRightView->ItemWeight((int32)1);
  328. float horizChat, horizList, vertChat, vertSend;
  329. fChatView->GetWeights(&horizChat, &horizList, &vertChat, &vertSend);
  330. fRightView->RemoveChild(fRightView->FindView("chatView"));
  331. fChatView = chatView;
  332. fRightView->AddChild(fChatView, 9);
  333. // Remove "Protocol" menu
  334. BMenuItem* chatMenuItem = fMenuBar->FindItem("Protocol");
  335. BMenu* chatMenu;
  336. if (chatMenuItem != NULL && (chatMenu = chatMenuItem->Submenu()) != NULL)
  337. fMenuBar->RemoveItem(chatMenu);
  338. // Add and populate "Protocol" menu, if appropriate
  339. if (fConversation != NULL) {
  340. ProtocolLooper* looper = fConversation->GetProtocolLooper();
  341. BObjectList<BMessage> menuItems = looper->Protocol()->MenuBarItems();
  342. for (int i = 0; i < menuItems.CountItems(); i++) {
  343. BMessage* itemMsg = menuItems.ItemAt(i);
  344. BMessage* msg = new BMessage(*itemMsg);
  345. BMessage toSend;
  346. msg->FindMessage("_msg", &toSend);
  347. toSend.AddString("chat_id", fConversation->GetId());
  348. toSend.AddInt64("instance", looper->GetInstance());
  349. msg->ReplaceMessage("_msg", &toSend);
  350. BMenuItem* item = new BMenuItem(msg);
  351. if (item == NULL)
  352. continue;
  353. if (msg->GetBool("x_to_protocol", true) == true)
  354. item->SetTarget(looper);
  355. else
  356. item->SetTarget(this);
  357. chatMenu->AddItem(item);
  358. }
  359. }
  360. // Apply saved weights
  361. fSplitView->SetItemWeight(0, AppPreferences::Get()->MainWindowListWeight, true);
  362. fSplitView->SetItemWeight(1, AppPreferences::Get()->MainWindowChatWeight, true);
  363. fChatView->SetWeights(horizChat, horizList, vertChat, vertSend);
  364. if (weightChat * weightSend != 0) {
  365. fRightView->SetItemWeight(0, weightChat, true);
  366. fRightView->SetItemWeight(1, weightSend, true);
  367. }
  368. // Save ChatView weights to settings
  369. AppPreferences::Get()->ChatViewHorizChatWeight = horizChat;
  370. AppPreferences::Get()->ChatViewHorizListWeight = horizList;
  371. AppPreferences::Get()->ChatViewVertChatWeight = vertChat;
  372. AppPreferences::Get()->ChatViewVertSendWeight = vertSend;
  373. }
  374. void
  375. MainWindow::RemoveConversation(Conversation* chat)
  376. {
  377. SetConversation(NULL);
  378. int32 index = fListView->IndexOf(chat->GetListItem());
  379. if (index > 0)
  380. index--;
  381. fListView->RemoveConversation(chat);
  382. if (fListView->CountItems() > 0)
  383. fListView->Select(index);
  384. _ToggleMenuItems();
  385. }
  386. void
  387. MainWindow::SortConversation(Conversation* chat)
  388. {
  389. fListView->SortConversation(chat);
  390. }
  391. void
  392. MainWindow::_InitInterface()
  393. {
  394. // Left side of window, Roomlist + Status
  395. fListView = new ConversationListView("roomList");
  396. fStatusView = new StatusView("statusView", fServer);
  397. fSplitView = new BSplitView(B_HORIZONTAL, 0);
  398. BScrollView* listScroll = new BScrollView("roomListScroll", fListView,
  399. true, false, B_NO_BORDER);
  400. // Right-side of window, Chat + Textbox
  401. fRightView = new BSplitView(B_VERTICAL, 0);
  402. fBackupChatView = new ConversationView();
  403. fChatView = fBackupChatView;
  404. // Load weights from settings
  405. float horizChat, horizList, vertChat, vertSend;
  406. horizChat = AppPreferences::Get()->ChatViewHorizChatWeight;
  407. horizList = AppPreferences::Get()->ChatViewHorizListWeight;
  408. vertChat = AppPreferences::Get()->ChatViewVertChatWeight;
  409. vertSend = AppPreferences::Get()->ChatViewVertSendWeight;
  410. fChatView->SetWeights(horizChat, horizList, vertChat, vertSend);
  411. BLayoutBuilder::Group<>(this, B_VERTICAL)
  412. .Add((fMenuBar = _CreateMenuBar()))
  413. .AddGroup(B_HORIZONTAL)
  414. .SetInsets(5, 5, 0, 10)
  415. .AddSplit(fSplitView)
  416. .AddGroup(B_VERTICAL)
  417. .Add(listScroll, 1)
  418. .Add(fStatusView)
  419. .End()
  420. .Add(fRightView, 5)
  421. .End()
  422. .End()
  423. .End();
  424. SetConversation(NULL);
  425. _ToggleMenuItems();
  426. }
  427. BMenuBar*
  428. MainWindow::_CreateMenuBar()
  429. {
  430. BMenuBar* menuBar = new BMenuBar("MenuBar");
  431. // Program
  432. BMenu* programMenu = new BMenu(B_TRANSLATE("Program"));
  433. programMenu->AddItem(new BMenuItem(B_TRANSLATE("About" B_UTF8_ELLIPSIS),
  434. new BMessage(B_ABOUT_REQUESTED)));
  435. programMenu->AddItem(new BMenuItem(B_TRANSLATE("Preferences" B_UTF8_ELLIPSIS),
  436. new BMessage(APP_SHOW_SETTINGS), ',', B_COMMAND_KEY));
  437. programMenu->AddItem(new BSeparatorItem());
  438. programMenu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
  439. new BMessage(B_QUIT_REQUESTED), 'Q', B_COMMAND_KEY));
  440. programMenu->SetTargetForItems(this);
  441. // Chat
  442. BMenu* chatMenu = new BMenu(B_TRANSLATE("Chat"));
  443. chatMenu->AddItem(new BMenuItem(B_TRANSLATE("Join room" B_UTF8_ELLIPSIS),
  444. new BMessage(APP_JOIN_ROOM), 'J', B_COMMAND_KEY));
  445. chatMenu->AddSeparatorItem();
  446. chatMenu->AddItem(new BMenuItem(B_TRANSLATE("New room" B_UTF8_ELLIPSIS),
  447. new BMessage(APP_NEW_ROOM), 'N', B_COMMAND_KEY));
  448. chatMenu->AddItem(new BMenuItem(B_TRANSLATE("New chat" B_UTF8_ELLIPSIS),
  449. new BMessage(APP_NEW_CHAT), 'M', B_COMMAND_KEY));
  450. chatMenu->SetTargetForItems(this);
  451. // Roster
  452. BMenu* rosterMenu = new BMenu(B_TRANSLATE("Roster"));
  453. rosterMenu->AddItem(new BMenuItem(B_TRANSLATE("Edit roster" B_UTF8_ELLIPSIS),
  454. new BMessage(APP_EDIT_ROSTER), 'R', B_COMMAND_KEY));
  455. rosterMenu->AddSeparatorItem();
  456. rosterMenu->AddItem(new BMenuItem(B_TRANSLATE("Invite user" B_UTF8_ELLIPSIS),
  457. new BMessage(APP_SEND_INVITE), 'I', B_COMMAND_KEY));
  458. rosterMenu->SetTargetForItems(this);
  459. // Window
  460. BMenu* windowMenu = new BMenu(B_TRANSLATE("Window"));
  461. windowMenu->AddItem(new BMenuItem(B_TRANSLATE("Up"),
  462. new BMessage(APP_MOVE_UP), B_UP_ARROW, B_COMMAND_KEY));
  463. windowMenu->AddItem(new BMenuItem(B_TRANSLATE("Down"),
  464. new BMessage(APP_MOVE_DOWN), B_DOWN_ARROW, B_COMMAND_KEY));
  465. windowMenu->SetTargetForItems(this);
  466. menuBar->AddItem(programMenu);
  467. menuBar->AddItem(_CreateAccountsMenu());
  468. menuBar->AddItem(chatMenu);
  469. menuBar->AddItem(rosterMenu);
  470. menuBar->AddItem(windowMenu);
  471. return menuBar;
  472. }
  473. BMenu*
  474. MainWindow::_CreateAccountsMenu()
  475. {
  476. BMenu* accountsMenu = new BMenu(B_TRANSLATE("Accounts"));
  477. ProtocolManager* pm = ProtocolManager::Get();
  478. bool hasAccounts = false;
  479. for (uint32 i = 0; i < pm->CountProtocolAddOns(); i++) {
  480. ChatProtocolAddOn* addOn = pm->ProtocolAddOnAt(i);
  481. ProtocolSettings* settings = new ProtocolSettings(addOn);
  482. if (_PopulateWithAccounts(accountsMenu, settings) == true)
  483. hasAccounts = true;
  484. }
  485. if (hasAccounts == true)
  486. accountsMenu->AddSeparatorItem();
  487. accountsMenu->AddItem(
  488. new BMenuItem(B_TRANSLATE("Manage accounts" B_UTF8_ELLIPSIS),
  489. new BMessage(APP_SHOW_ACCOUNTS), '.', B_COMMAND_KEY));
  490. accountsMenu->SetTargetForItems(this);
  491. return accountsMenu;
  492. }
  493. void
  494. MainWindow::_RefreshAccountsMenu()
  495. {
  496. _ReplaceMenu(B_TRANSLATE("Accounts"), _CreateAccountsMenu());
  497. }
  498. void
  499. MainWindow::_ToggleMenuItems()
  500. {
  501. BMenuItem* chatMenuItem = fMenuBar->FindItem(B_TRANSLATE("Chat"));
  502. BMenuItem* rosterMenuItem = fMenuBar->FindItem(B_TRANSLATE("Roster"));
  503. BMenu* chatMenu = chatMenuItem->Submenu();
  504. BMenu* rosterMenu = rosterMenuItem->Submenu();
  505. if (chatMenu == NULL || rosterMenu == NULL)
  506. return;
  507. bool enabled = (fServer != NULL && fServer->GetAccounts().CountItems() > 0);
  508. for (int i = 0; i < chatMenu->CountItems(); i++)
  509. chatMenu->ItemAt(i)->SetEnabled(enabled);
  510. for (int i = 0; i < rosterMenu->CountItems(); i++)
  511. rosterMenu->ItemAt(i)->SetEnabled(enabled);
  512. BMenuItem* windowMenuItem = fMenuBar->FindItem(B_TRANSLATE("Window"));
  513. BMenu* windowMenu = windowMenuItem->Submenu();
  514. enabled = (fListView->CountItems() > 0);
  515. for (int i = 0; i < windowMenu->CountItems(); i++)
  516. windowMenu->ItemAt(i)->SetEnabled(enabled);
  517. }
  518. ConversationItem*
  519. MainWindow::_EnsureConversationItem(BMessage* msg)
  520. {
  521. ChatMap chats = fServer->Conversations();
  522. BString chat_id = msg->FindString("chat_id");
  523. Conversation* chat = fServer->ConversationById(chat_id, msg->FindInt64("instance"));
  524. ConversationItem* item = chat->GetListItem();
  525. if (chat != NULL) {
  526. if (fListView->HasItem(item))
  527. fListView->InvalidateItem(fListView->IndexOf(item));
  528. else if (item != NULL) {
  529. fListView->AddConversation(chat);
  530. _ToggleMenuItems();
  531. }
  532. if (fListView->CountItems() == 1)
  533. fListView->Select(0);
  534. return item;
  535. }
  536. return NULL;
  537. }
  538. bool
  539. MainWindow::_PopulateWithAccounts(BMenu* menu, ProtocolSettings* settings)
  540. {
  541. if (!settings)
  542. return false;
  543. BObjectList<BString> accounts = settings->Accounts();
  544. // Add accounts to menu
  545. for (int32 i = 0; i < accounts.CountItems(); i++) {
  546. BString* account = accounts.ItemAt(i);
  547. BMenu* accMenu = new BMenu(account->String());
  548. BString toggleLabel = B_TRANSLATE("Enable");
  549. bool isActive = false;
  550. int64 instance = fServer->GetActiveAccounts().ValueFor(*account, &isActive);
  551. if (isActive == true)
  552. toggleLabel = B_TRANSLATE("Disable");
  553. BMessage* toggleMsg = new BMessage(APP_TOGGLE_ACCOUNT);
  554. toggleMsg->AddPointer("settings", settings);
  555. toggleMsg->AddString("account", *account);
  556. if (isActive == true)
  557. toggleMsg->AddInt64("instance", instance);
  558. BMessage* editMsg = new BMessage(APP_EDIT_ACCOUNT);
  559. editMsg->AddPointer("settings", settings);
  560. editMsg->AddString("account", *account);
  561. accMenu->AddItem(new BMenuItem(toggleLabel.String(), toggleMsg));
  562. accMenu->AddItem(
  563. new BMenuItem(B_TRANSLATE("Modify account" B_UTF8_ELLIPSIS),
  564. editMsg));
  565. menu->AddItem(accMenu);
  566. }
  567. return (accounts.CountItems() > 0);
  568. }
  569. void
  570. MainWindow::_ReplaceMenu(const char* name, BMenu* newMenu)
  571. {
  572. BMenuItem* old = fMenuBar->FindItem(name);
  573. if (old == NULL || newMenu == NULL)
  574. return;
  575. int32 index = fMenuBar->IndexOf(old);
  576. fMenuBar->RemoveItem(index);
  577. fMenuBar->AddItem(newMenu, index);
  578. }