5ddeef6e7b
* Shows notifications when contacts go online or offline. Unfortunately XMPP plugins will send presence notifications when the roster is populate so presence notification is shown for every online contact when the roster list view is populated the first time.
348 lines
7.6 KiB
C++
348 lines
7.6 KiB
C++
/*
|
|
* Copyright 2009-2010, Andrea Anzani. All rights reserved.
|
|
* Copyright 2009-2010, Pier Luigi Fiorini. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Andrea Anzani, andrea.anzani@gmail.com
|
|
* Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
|
|
*/
|
|
|
|
#include <Application.h>
|
|
#include <Alert.h>
|
|
#include <Button.h>
|
|
#include <CardLayout.h>
|
|
#include <ListView.h>
|
|
#include <Box.h>
|
|
#include <CheckBox.h>
|
|
#include <Entry.h>
|
|
#include <GridLayout.h>
|
|
#include <GridLayoutBuilder.h>
|
|
#include <GroupLayout.h>
|
|
#include <GroupLayoutBuilder.h>
|
|
#include <MenuItem.h>
|
|
#include <Notification.h>
|
|
#include <PopUpMenu.h>
|
|
#include <Roster.h>
|
|
#include <SpaceLayoutItem.h>
|
|
#include <ScrollView.h>
|
|
#include <StringView.h>
|
|
#include <TextControl.h>
|
|
#include <TranslationUtils.h>
|
|
|
|
#include <libinterface/BitmapUtils.h>
|
|
#include <libinterface/ToolButton.h>
|
|
|
|
#include "CayaConstants.h"
|
|
#include "CayaMessages.h"
|
|
#include "CayaProtocolMessages.h"
|
|
#include "CayaPreferences.h"
|
|
#include "CayaResources.h"
|
|
#include "CayaUtils.h"
|
|
#include "NotifyMessage.h"
|
|
#include "MainWindow.h"
|
|
#include "PreferencesDialog.h"
|
|
#include "RosterItem.h"
|
|
#include "RosterListView.h"
|
|
#include "Server.h"
|
|
#include "StatusView.h"
|
|
|
|
const uint32 kLogin = 'LOGI';
|
|
const uint32 kSearchContact = 'SRCH';
|
|
|
|
const uint32 kPreferences = 'WPRF';
|
|
|
|
|
|
MainWindow::MainWindow()
|
|
:
|
|
BWindow(BRect(0, 0, 300, 400), "Caya", B_DOCUMENT_WINDOW, 0)
|
|
{
|
|
fStatusView = new StatusView("statusView");
|
|
|
|
BTextControl* searchBox = new BTextControl("searchBox", NULL, NULL,
|
|
new BMessage(kSearchContact));
|
|
|
|
fListView = new RosterListView("buddyView");
|
|
fListView->SetInvocationMessage(new BMessage(CAYA_OPEN_WINDOW));
|
|
BScrollView* scrollView = new BScrollView("scrollview", fListView,
|
|
B_WILL_DRAW, false, true);
|
|
|
|
// Wrench menu
|
|
BPopUpMenu* wrenchMenu = new BPopUpMenu("Wrench");
|
|
(void)wrenchMenu->AddItem(new BMenuItem("About" B_UTF8_ELLIPSIS,
|
|
new BMessage(B_ABOUT_REQUESTED)));
|
|
(void)wrenchMenu->AddItem(new BSeparatorItem());
|
|
(void)wrenchMenu->AddItem(new BMenuItem("Preferences" B_UTF8_ELLIPSIS,
|
|
new BMessage(kPreferences)));
|
|
(void)wrenchMenu->AddItem(new BSeparatorItem());
|
|
(void)wrenchMenu->AddItem(new BMenuItem("Quit",
|
|
new BMessage(B_QUIT_REQUESTED)));
|
|
wrenchMenu->SetTargetForItems(this);
|
|
|
|
// Tool icon
|
|
BResources* res = CayaResources();
|
|
BBitmap* toolIcon = IconFromResources(res, kToolIcon);
|
|
delete res;
|
|
|
|
// Wrench tool button
|
|
ToolButton* wrench = new ToolButton(NULL, NULL);
|
|
wrench->SetBitmap(toolIcon);
|
|
wrench->SetMenu(wrenchMenu);
|
|
|
|
SetLayout(new BGridLayout(5, 5));
|
|
AddChild(BGridLayoutBuilder(5, 5)
|
|
.Add(fStatusView, 0, 0)
|
|
.Add(wrench, 1, 0)
|
|
.Add(searchBox, 0, 1)
|
|
.Add(scrollView, 0, 2, 2)
|
|
.SetInsets(5, 5, 5, 10)
|
|
);
|
|
|
|
AddShortcut('a', B_COMMAND_KEY, new BMessage(B_ABOUT_REQUESTED));
|
|
MoveTo(BAlert::AlertPosition(Bounds().Width(), Bounds().Height() / 2));
|
|
|
|
// Filter messages using Server
|
|
fServer = new Server();
|
|
AddFilter(fServer);
|
|
|
|
CenterOnScreen();
|
|
}
|
|
|
|
|
|
void
|
|
MainWindow::Start()
|
|
{
|
|
// Login all accounts
|
|
fServer->LoginAll();
|
|
}
|
|
|
|
|
|
bool
|
|
MainWindow::QuitRequested()
|
|
{
|
|
fListView->MakeEmpty();
|
|
fServer->Quit();
|
|
CayaPreferences::Get()->Save();
|
|
be_app->PostMessage(B_QUIT_REQUESTED);
|
|
return true;
|
|
}
|
|
|
|
|
|
void
|
|
MainWindow::MessageReceived(BMessage* message)
|
|
{
|
|
switch (message->what) {
|
|
case kSearchContact: {
|
|
void* control = NULL;
|
|
if (message->FindPointer("source", &control) != B_OK)
|
|
return;
|
|
|
|
BTextControl* searchBox = static_cast<BTextControl*>(control);
|
|
if (searchBox == NULL)
|
|
return;
|
|
|
|
RosterMap map = fServer->RosterItems();
|
|
for (uint32 i = 0; i < map.CountItems(); i++) {
|
|
ContactLinker* linker = map.ValueAt(i);
|
|
RosterItem* item = linker->GetRosterItem();
|
|
|
|
// If the search filter has been deleted show all the items,
|
|
// otherwise remove the item in order to show only items
|
|
// that matches the search criteria
|
|
if (strcmp(searchBox->Text(), "") == 0)
|
|
AddItem(item);
|
|
else if (linker->GetName().IFindFirst(searchBox->Text()) == B_ERROR)
|
|
RemoveItem(item);
|
|
else
|
|
AddItem(item);
|
|
UpdateListItem(item);
|
|
}
|
|
break;
|
|
}
|
|
case kPreferences: {
|
|
PreferencesDialog* dialog = new PreferencesDialog();
|
|
dialog->Show();
|
|
break;
|
|
}
|
|
case CAYA_OPEN_WINDOW: {
|
|
int index = message->FindInt32("index");
|
|
RosterItem* ritem = ItemAt(index);
|
|
if (ritem != NULL)
|
|
ritem->GetContactLinker()->ShowWindow();
|
|
break;
|
|
}
|
|
case IM_MESSAGE:
|
|
ImMessage(message);
|
|
break;
|
|
case IM_ERROR:
|
|
ImError(message);
|
|
break;
|
|
case B_ABOUT_REQUESTED:
|
|
be_app->PostMessage(message);
|
|
break;
|
|
default:
|
|
BWindow::MessageReceived(message);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
MainWindow::ImError(BMessage* msg)
|
|
{
|
|
// FIXME: better error handling..
|
|
BAlert* alert = new BAlert("Error", msg->FindString("error"), "Ouch!");
|
|
alert->Go();
|
|
}
|
|
|
|
|
|
void
|
|
MainWindow::ImMessage(BMessage* msg)
|
|
{
|
|
int32 im_what = msg->FindInt32("im_what");
|
|
switch (im_what) {
|
|
case IM_OWN_CONTACT_INFO:
|
|
fStatusView->SetName(msg->FindString("name"));
|
|
break;
|
|
case IM_OWN_AVATAR_SET:
|
|
{
|
|
entry_ref ref;
|
|
|
|
if (msg->FindRef("ref", &ref) == B_OK) {
|
|
BBitmap* bitmap = BTranslationUtils::GetBitmap(&ref);
|
|
fStatusView->SetAvatarIcon(bitmap);
|
|
}
|
|
break;
|
|
}
|
|
case IM_STATUS_SET:
|
|
{
|
|
int32 status;
|
|
|
|
if (msg->FindInt32("status", &status) != B_OK)
|
|
return;
|
|
|
|
RosterItem* rosterItem = fServer->RosterItemForId(msg->FindString("id"));
|
|
|
|
if (rosterItem) {
|
|
UpdateListItem(rosterItem);
|
|
|
|
// Add or remove item
|
|
switch (status) {
|
|
case CAYA_OFFLINE:
|
|
// By default offline contacts are hidden
|
|
if (HasItem(rosterItem))
|
|
RemoveItem(rosterItem);
|
|
return;
|
|
default:
|
|
// Add item because it has a non-offline status
|
|
if (!HasItem(rosterItem))
|
|
AddItem(rosterItem);
|
|
break;
|
|
}
|
|
|
|
UpdateListItem(rosterItem);
|
|
|
|
// Sort list view again
|
|
fListView->Sort();
|
|
|
|
switch (status) {
|
|
case CAYA_ONLINE:
|
|
case CAYA_OFFLINE:
|
|
// Notify when contact is online or offline
|
|
if (status == CAYA_ONLINE) {
|
|
BString message;
|
|
message << rosterItem->GetContactLinker()->GetName();
|
|
|
|
if (status == CAYA_ONLINE)
|
|
message << " is available!";
|
|
else
|
|
message << " is offline!";
|
|
|
|
BNotification notification(B_INFORMATION_NOTIFICATION);
|
|
notification.SetApplication("Caya");
|
|
notification.SetTitle("Presence");
|
|
notification.SetIcon(rosterItem->Bitmap());
|
|
notification.SetContent(message.String());
|
|
be_roster->Notify(notification);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case IM_AVATAR_SET:
|
|
case IM_CONTACT_INFO:
|
|
case IM_EXTENDED_CONTACT_INFO:
|
|
{
|
|
RosterItem* rosterItem
|
|
= fServer->RosterItemForId(msg->FindString("id"));
|
|
if (rosterItem)
|
|
UpdateListItem(rosterItem);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
MainWindow::ObserveInteger(int32 what, int32 val)
|
|
{
|
|
switch (what) {
|
|
case INT_ACCOUNT_STATUS:
|
|
fStatusView->SetStatus((CayaStatus)val);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
MainWindow::UpdateListItem(RosterItem* item)
|
|
{
|
|
if (fListView->HasItem(item))
|
|
fListView->InvalidateItem(fListView->IndexOf(item));
|
|
}
|
|
|
|
|
|
int32
|
|
MainWindow::CountItems() const
|
|
{
|
|
return fListView->CountItems();
|
|
}
|
|
|
|
|
|
RosterItem*
|
|
MainWindow::ItemAt(int index)
|
|
{
|
|
return dynamic_cast<RosterItem*>(fListView->ItemAt(index));
|
|
}
|
|
|
|
|
|
void
|
|
MainWindow::AddItem(RosterItem* item)
|
|
{
|
|
// Don't add offline items and avoid duplicates
|
|
if ((item->Status() == CAYA_OFFLINE) || HasItem(item))
|
|
return;
|
|
|
|
// Add item and sort
|
|
fListView->AddItem(item);
|
|
fListView->Sort();
|
|
}
|
|
|
|
|
|
bool
|
|
MainWindow::HasItem(RosterItem* item)
|
|
{
|
|
return fListView->HasItem(item);
|
|
}
|
|
|
|
|
|
void
|
|
MainWindow::RemoveItem(RosterItem* item)
|
|
{
|
|
// Remove item and sort
|
|
fListView->RemoveItem(item);
|
|
fListView->Sort();
|
|
}
|