Replace CreateAccountMenu() with dedicated class

CreateAccountMenu() is used to populate a BMenu with items corresponding
to the map of accounts provided to it― but when an account is disabled
or enabled, it can't update automatically.

A dedicated class, fAccountsMenu, now replaces it― it'll automatically
repopulate the list whenever the active accounts update.
This commit is contained in:
Jaidyn Ann 2021-07-21 12:12:02 -05:00
parent 9245dc7135
commit 0ffe3e5ce8
14 changed files with 178 additions and 71 deletions

View File

@ -55,6 +55,7 @@ SRCS = \
application/preferences/PreferencesAccounts.cpp \
application/preferences/PreferencesBehavior.cpp \
application/preferences/PreferencesReplicant.cpp \
application/views/AccountsMenu.cpp \
application/views/RenderView.cpp \
application/views/ConversationAccountItem.cpp \
application/views/ConversationItem.cpp \

View File

@ -18,7 +18,9 @@ enum {
INT_USER_PERMS,
INT_NEW_MESSAGE,
INT_NEW_MENTION,
INT_WINDOW_FOCUSED
INT_WINDOW_FOCUSED,
INT_ACCOUNTS_UPDATED
};
#endif // _NOTIFY_MESSAGE_H

View File

@ -34,6 +34,7 @@
#include "Flags.h"
#include "ImageCache.h"
#include "InviteDialogue.h"
#include "NotifyMessage.h"
#include "ProtocolLooper.h"
#include "ProtocolManager.h"
#include "RosterItem.h"
@ -582,6 +583,8 @@ Server::ImMessage(BMessage* msg)
ProtocolLooper* looper = _LooperFromMessage(msg);
if (looper == NULL) break;
fAccountEnabled.AddItem(looper->Protocol()->GetName(), true);
// Ready notification
if (AppPreferences::Item()->NotifyProtocolStatus == true)
_ProtocolNotification(looper, BString(B_TRANSLATE("Connected")),
@ -616,16 +619,19 @@ Server::ImMessage(BMessage* msg)
join.AddString("chat_id", fileName);
looper->PostMessage(&join);
}
NotifyInteger(INT_ACCOUNTS_UPDATED, 0);
break;
}
case IM_PROTOCOL_DISABLE:
{
int64 instance = 0;
if (msg->FindInt64("instance", &instance) != B_OK) {
if (msg->FindInt64("instance", &instance) != B_OK)
result = B_SKIP_MESSAGE;
break;
}
RemoveProtocolLooper(instance);
else
RemoveProtocolLooper(instance);
NotifyInteger(INT_ACCOUNTS_UPDATED, 0);
break;
}
default:
@ -664,6 +670,7 @@ Server::AddProtocolLooper(bigtime_t instanceId, ChatProtocol* cayap)
ProtocolLooper* looper = new ProtocolLooper(cayap, instanceId);
fLoopers.AddItem(instanceId, looper);
fAccounts.AddItem(cayap->GetName(), instanceId);
fAccountEnabled.AddItem(cayap->GetName(), false);
}
@ -684,6 +691,7 @@ Server::RemoveProtocolLooper(bigtime_t instanceId)
fLoopers.RemoveItemFor(instanceId);
fAccounts.RemoveItemFor(looper->Protocol()->GetName());
fAccountEnabled.AddItem(looper->Protocol()->GetName(), false);
looper->Lock();
looper->Quit();
}
@ -704,6 +712,17 @@ Server::GetAccounts()
}
AccountInstances
Server::GetActiveAccounts()
{
AccountInstances fActive;
for (int i = 0; i < fAccounts.CountItems(); i++)
if (fAccountEnabled.ValueFor(fAccounts.KeyAt(i)) == true)
fActive.AddItem(fAccounts.KeyAt(i), fAccounts.ValueAt(i));
return fActive;
}
void
Server::SendProtocolMessage(BMessage* msg)
{

View File

@ -16,6 +16,7 @@
#include "ChatCommand.h"
#include "Contact.h"
#include "Conversation.h"
#include "Notifier.h"
#include "ProtocolLooper.h"
#include "User.h"
@ -26,9 +27,10 @@ class ProtocolLooper;
typedef KeyMap<bigtime_t, ProtocolLooper*> ProtocolLoopers;
typedef KeyMap<BString, bigtime_t> AccountInstances;
typedef KeyMap<BString, bool> BoolMap;
class Server: public BMessageFilter {
class Server: public BMessageFilter, public Notifier {
public:
Server();
void Quit();
@ -43,8 +45,8 @@ public:
void RemoveProtocolLooper(bigtime_t instanceId);
ProtocolLooper* GetProtocolLooper(bigtime_t instanceId);
AccountInstances
GetAccounts();
AccountInstances GetAccounts();
AccountInstances GetActiveAccounts();
void SendProtocolMessage(BMessage* msg);
void SendAllProtocolMessage(BMessage* msg);
@ -87,14 +89,12 @@ private:
void _ReplicantStatusNotify(UserStatus status);
ProtocolLoopers fLoopers;
AccountInstances
fAccounts;
AccountInstances fAccounts;
BoolMap fAccountEnabled;
CommandMap fCommands;
BObjectList<BMessage>
fChatItems;
BObjectList<BMessage>
fUserItems;
CommandMap fCommands;
BObjectList<BMessage> fChatItems;
BObjectList<BMessage> fUserItems;
};

View File

@ -96,26 +96,6 @@ ChatResources()
}
BMenu*
CreateAccountMenu(AccountInstances accounts, BMessage msg, BMessage* allMsg)
{
BMenu* menu = new BMenu("accountMenu");
if (allMsg != NULL)
menu->AddItem(new BMenuItem("All", new BMessage(*allMsg)));
for (int i = 0; i < accounts.CountItems(); i++)
menu->AddItem(new BMenuItem(accounts.KeyAt(i).String(), new BMessage(msg)));
menu->SetRadioMode(true);
menu->SetLabelFromMarked(true);
menu->ItemAt(0)->SetMarked(true);
if (accounts.CountItems() == 0)
menu->SetEnabled(false);
return menu;
}
const char*
AccountsPath()
{

View File

@ -27,9 +27,6 @@ BString CommandArgs(BString line);
BResources* ChatResources();
BMenu* CreateAccountMenu(AccountInstances accounts, BMessage msg,
BMessage* allMsg = NULL);
const char* AccountsPath();
const char* AccountPath(const char* signature, const char* subsignature);

View File

@ -0,0 +1,65 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "AccountsMenu.h"
#include "MainWindow.h"
#include "Server.h"
#include "TheApp.h"
#include <MenuItem.h>
AccountsMenu::AccountsMenu(const char* name, BMessage msg, BMessage* allMsg)
:
BMenu(name),
fAccountMessage(msg),
fAllMessage(allMsg)
{
_PopulateMenu();
SetRadioMode(true);
SetLabelFromMarked(true);
Server* server = ((TheApp*)be_app)->GetMainWindow()->GetServer();
server->RegisterObserver(this);
}
AccountsMenu::~AccountsMenu()
{
delete fAllMessage;
Server* server = ((TheApp*)be_app)->GetMainWindow()->GetServer();
server->UnregisterObserver(this);
}
void
AccountsMenu::ObserveInteger(int32 what, int32 value)
{
_PopulateMenu();
}
void
AccountsMenu::_PopulateMenu()
{
if (CountItems() > 0)
RemoveItems(0, CountItems(), true);
if (fAllMessage != NULL)
AddItem(new BMenuItem("All", new BMessage(*fAllMessage)));
Server* server = ((TheApp*)be_app)->GetMainWindow()->GetServer();
AccountInstances accounts = server->GetActiveAccounts();
for (int i = 0; i < accounts.CountItems(); i++)
AddItem(new BMenuItem(accounts.KeyAt(i).String(),
new BMessage(fAccountMessage)));
if (CountItems() > 0)
ItemAt(0)->SetMarked(true);
else
SetEnabled(false);
}

View File

@ -0,0 +1,27 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef _ACCOUNTS_MENU_H
#define _ACCOUNTS_MENU_H
#include <Menu.h>
#include "Observer.h"
class AccountsMenu : public BMenu, public Observer {
public:
AccountsMenu(const char* name, BMessage msg, BMessage* allMsg = NULL);
~AccountsMenu();
virtual void ObserveInteger(int32 what, int32 value);
private:
void _PopulateMenu();
BMessage fAccountMessage;
BMessage* fAllMessage;
};
#endif // _ACCOUNTS_MENU_H

View File

@ -20,6 +20,7 @@
#include <ScrollView.h>
#include <SeparatorView.h>
#include "AccountsMenu.h"
#include "AppMessages.h"
#include "AppPreferences.h"
#include "ChatProtocolMessages.h"
@ -27,7 +28,6 @@
#include "RosterListView.h"
#include "RosterView.h"
#include "TemplateWindow.h"
#include "Utils.h"
#undef B_TRANSLATION_CONTEXT
@ -47,7 +47,6 @@ RosterEditWindow* RosterEditWindow::fInstance = NULL;
RosterEditWindow::RosterEditWindow(Server* server)
:
BWindow(BRect(0, 0, 300, 400), B_TRANSLATE("Roster"), B_FLOATING_WINDOW, 0),
fAccounts(server->GetAccounts()),
fServer(server),
fEditingWindow(NULL)
{
@ -55,7 +54,7 @@ RosterEditWindow::RosterEditWindow(Server* server)
fRosterView->SetInvocationMessage(new BMessage(kEditMember));
fAccountField = new BMenuField("accountMenuField", NULL,
CreateAccountMenu(fAccounts, BMessage(kSelAccount),
new AccountsMenu("accountMenu", BMessage(kSelAccount),
new BMessage(kSelNoAccount)));
font_height fontHeight;
@ -183,10 +182,12 @@ RosterEditWindow::MessageReceived(BMessage* message)
}
case kSelAccount:
{
AccountInstances accounts = fServer->GetActiveAccounts();
int index = message->FindInt32("index") - 1;
if (index < 0 || index > (fAccounts.CountItems() - 1))
if (index < 0 || index > (accounts.CountItems() - 1))
return;
fRosterView->SetAccount(fAccounts.ValueAt(index));
fRosterView->SetAccount(accounts.ValueAt(index));
break;
}
case kSelNoAccount:

View File

@ -36,7 +36,6 @@ public:
private:
BMenuField* fAccountField;
AccountInstances fAccounts;
BString fEditingUser;
TemplateWindow* fEditingWindow;

View File

@ -18,10 +18,10 @@
#include <Notification.h>
#include <ScrollView.h>
#include "AccountsMenu.h"
#include "AppMessages.h"
#include "AppPreferences.h"
#include "ChatProtocolMessages.h"
#include "Utils.h"
#include "RosterItem.h"
#include "RosterListView.h"
#include "RosterView.h"
@ -38,7 +38,6 @@ RosterWindow::RosterWindow(const char* title, BMessage* selectMsg,
BWindow(BRect(0, 0, 300, 400), title, B_FLOATING_WINDOW, 0),
fTarget(messenger),
fMessage(selectMsg),
fAccounts(server->GetAccounts()),
fServer(server)
{
fRosterView = new RosterView("buddyView", server, instance),
@ -46,27 +45,31 @@ RosterWindow::RosterWindow(const char* title, BMessage* selectMsg,
fOkButton = new BButton("OK", new BMessage(kSendMessage));
BMenu* accountMenu;
AccountInstances accounts = fServer->GetActiveAccounts();
// If a specific instance is given, disallow selecting other accounts
// In fact, don't even bother populating with them
if (instance > -1) {
accountMenu = new BMenu("accountMenu");
BMenu* accountMenu = new BMenu("accountMenu");
BString name = "N/A";
for (int i = 0; i < fAccounts.CountItems(); i++)
if (fAccounts.ValueAt(i) == instance) {
name = fAccounts.KeyAt(i);
for (int i = 0; i < accounts.CountItems(); i++)
if (accounts.ValueAt(i) == instance) {
name = accounts.KeyAt(i);
break;
}
accountMenu->AddItem(new BMenuItem(name.String(), NULL));
accountMenu->SetLabelFromMarked(true);
accountMenu->ItemAt(0)->SetMarked(true);
accountMenu->SetEnabled(false);
fAccountField = new BMenuField("accountMenuField", NULL, accountMenu);
}
else
accountMenu = CreateAccountMenu(fAccounts, BMessage(kSelAccount),
new BMessage(kSelNoAccount));
fAccountField = new BMenuField("accountMenuField", NULL,
new AccountsMenu("accountMenu", BMessage(kSelAccount),
new BMessage(kSelNoAccount)));
fAccountField = new BMenuField("accountMenuField", NULL, accountMenu);
BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
.SetInsets(B_USE_DEFAULT_SPACING)
@ -103,10 +106,12 @@ RosterWindow::MessageReceived(BMessage* message)
}
case kSelAccount:
{
AccountInstances accounts = fServer->GetActiveAccounts();
int index = message->FindInt32("index") - 1;
if (index < 0 || index > (fAccounts.CountItems() - 1))
if (index < 0 || index > (accounts.CountItems() - 1))
return;
fRosterView->SetAccount(fAccounts.ValueAt(index));
fRosterView->SetAccount(accounts.ValueAt(index));
break;
}
case kSelNoAccount:

View File

@ -35,7 +35,6 @@ public:
private:
BButton* fOkButton;
BMenuField* fAccountField;
AccountInstances fAccounts;
Server* fServer;

View File

@ -18,8 +18,8 @@
#include <TextControl.h>
#include <String.h>
#include "AccountsMenu.h"
#include "ChatProtocolMessages.h"
#include "Utils.h"
#include "TemplateView.h"
@ -38,7 +38,6 @@ TemplateWindow::TemplateWindow(const char* title, const char* templateType,
BWindow(BRect(0, 0, 400, 100), title, B_FLOATING_WINDOW,
B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fServer(server),
fAccounts(server->GetAccounts()),
fSelectedAcc(0),
fTemplate(NULL),
fTemplateType(templateType),
@ -57,7 +56,6 @@ TemplateWindow::TemplateWindow(const char* title, ProtocolTemplate* temp,
BWindow(BRect(0, 0, 400, 100), title, B_FLOATING_WINDOW,
B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fServer(server),
fAccounts(server->GetAccounts()),
fSelectedAcc(0),
fTemplate(temp),
fMessage(msg)
@ -100,8 +98,11 @@ TemplateWindow::MessageReceived(BMessage* msg)
alert->Go();
break;
}
AccountInstances accounts = fServer->GetActiveAccounts();
ProtocolLooper* looper
= fServer->GetProtocolLooper(fAccounts.ValueAt(fSelectedAcc));
= fServer->GetProtocolLooper(accounts.ValueAt(fSelectedAcc));
if (looper == NULL)
break;
looper->PostMessage(settings);
@ -133,25 +134,36 @@ void
TemplateWindow::_InitInterface(bigtime_t instance)
{
fTemplateView = new TemplateView("template");
BMenu* menu = CreateAccountMenu(fAccounts, BMessage(kAccSelected));
fMenuField = new BMenuField("accountMenuField", NULL, menu);
AccountInstances accounts = fServer->GetActiveAccounts();
if (instance > -1) {
for (int i = 0; i < fAccounts.CountItems(); i++)
if (fAccounts.ValueAt(i) == instance) {
menu->ItemAt(i)->SetMarked(true);
BMenu* accountMenu = new BMenu("accountMenu");
BString name = "N/A";
for (int i = 0; i < accounts.CountItems(); i++)
if (accounts.ValueAt(i) == instance) {
name = accounts.KeyAt(i);
break;
}
fMenuField->SetEnabled(false);
accountMenu->AddItem(new BMenuItem(name.String(), NULL));
accountMenu->SetLabelFromMarked(true);
accountMenu->ItemAt(0)->SetMarked(true);
accountMenu->SetEnabled(false);
fMenuField = new BMenuField("accountMenuField", NULL, accountMenu);
}
else
fMenuField = new BMenuField("accountMenuField", NULL,
new AccountsMenu("accountMenu", BMessage(kAccSelected)));
BButton* fOkButton = new BButton(B_TRANSLATE("OK"), new BMessage(kOK));
if (fAccounts.CountItems() <= 0)
if (accounts.CountItems() <= 0)
fOkButton->SetEnabled(false);
fOkButton->MakeDefault(true);
const float spacing = be_control_look->DefaultItemSpacing();
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.Add(fTemplateView)
@ -169,11 +181,12 @@ TemplateWindow::_InitInterface(bigtime_t instance)
void
TemplateWindow::_LoadTemplate()
{
if (fAccounts.CountItems() == 0 || fTemplateType.IsEmpty() == true)
AccountInstances accounts = fServer->GetActiveAccounts();
if (accounts.CountItems() == 0 || fTemplateType.IsEmpty() == true)
return;
ProtocolLooper* looper
= fServer->GetProtocolLooper(fAccounts.ValueAt(fSelectedAcc));
= fServer->GetProtocolLooper(accounts.ValueAt(fSelectedAcc));
if (looper == NULL)
return;

View File

@ -42,7 +42,6 @@ private:
void _LoadTemplate();
Server* fServer;
AccountInstances fAccounts;
int32 fSelectedAcc;
BMenuField* fMenuField;