////////////////////////////////////////////////// // Blabber [BlabberMainWindow.cpp] ////////////////////////////////////////////////// #include "MainWindow.h" #include #include "support/AppLocation.h" #include "ui/AddBuddyWindow.h" #include "ui/BuddyInfoWindow.h" #include "ui/ChangeNameWindow.h" #include "ui/ModalAlertFactory.h" #include "ui/RegisterAccountWindow.h" #include "ui/RotateChatFilter.h" #include "ui/TalkView.h" #include "jabber/BlabberSettings.h" #include "jabber/CustomStatusWindow.h" #include "jabber/GenericFunctions.h" #include "jabber/JabberSpeak.h" #include "jabber/Messages.h" #include "jabber/MessageRepeater.h" #include "jabber/PreferencesWindow.h" #include "jabber/RosterItem.h" #include "jabber/SendTalkWindow.h" #include "jabber/TalkManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum { kCreateAccount = 'crea' }; BlabberMainWindow *BlabberMainWindow::_instance = NULL; BlabberMainWindow *BlabberMainWindow::Instance() { BlabberSettings *settings = BlabberSettings::Instance(); if (_instance == NULL && !settings->Data("no-window-on-startup")) { float main_window_width, main_window_height; // determine what the width and height of the window should be if (settings->Data("main-window-width") && settings->Data("main-window-height")) { main_window_width = atof(settings->Data("main-window-width")); main_window_height = atof(settings->Data("main-window-height")); } else { // default main_window_width = 210; main_window_height = 332; } // create window frame position BRect frame(GenericFunctions::CenteredFrame(main_window_width, main_window_height)); // poition window to last known position if (settings->Data("main-window-left") && settings->Data("main-window-top")) { frame.OffsetTo(BPoint(atof(settings->Data("main-window-left")), atof(settings->Data("main-window-top")))); } // create window singleton _instance = new BlabberMainWindow(frame); } return _instance; } BlabberMainWindow::~BlabberMainWindow() { // remove self from message family MessageRepeater::Instance()->RemoveTarget(this); _instance = NULL; } void BlabberMainWindow::MessageReceived(BMessage *msg) { switch (msg->what) { case kCreateAccount: { (new RegisterAccountWindow(this))->Show(); break; } // transplanted from LoginWindow case JAB_LOGIN: { // must pass validation if (!ValidateLogin()) { break; } // switch out views _login_login->MakeDefault(false); BCardLayout* cl = (BCardLayout*)GetLayout(); cl->SetVisibleItem((int32)0); // connect with current username or register new account JabberSpeak::Instance()->SendConnect(_login_username->Text(), _login_password->Text(), _login_realname->Text()); break; } case B_ABOUT_REQUESTED: { be_app->PostMessage(B_ABOUT_REQUESTED); break; } case JAB_QUIT: { be_app->PostMessage(B_QUIT_REQUESTED); break; } case JAB_PREFERENCES: { PreferencesWindow::Instance()->Show(); PreferencesWindow::Instance()->Activate(); break; } case JAB_CONNECT: { _status_view->SetMessage("connecting"); JabberSpeak::Instance()->SendConnect("", "", "", true); break; } case JAB_RECONNECTING: { // we are connecting _status_view->SetMessage("reconnecting"); break; } case JAB_LOGGED_IN: { // we just logged in _status_view->SetMessage("connected as " + JabberSpeak::Instance()->CurrentLogin()); // save these settings BlabberSettings::Instance()->SetData("last-realname", _login_realname->Text()); BlabberSettings::Instance()->SetData("last-login", _login_username->Text()); BlabberSettings::Instance()->SetData("last-password", _login_password->Text()); BlabberSettings::Instance()->SetTag("auto-login", _login_auto_login->Value()); BlabberSettings::Instance()->WriteToFile(); break; } case JAB_DISCONNECT: { JabberSpeak::Instance()->SendDisconnect(); _status_view->SetMessage("disconnecting"); JabberSpeak::Instance()->Reset(); break; } case JAB_DISCONNECTED: { JRoster::Instance()->RefreshRoster(); break; } case JAB_RIV: { string jabber_org = "http://github.com/haikuarchives/renga"; char *argv[] = {const_cast(jabber_org.c_str()), NULL}; if (!be_roster->IsRunning("text/html")) be_roster->Launch("text/html", 1, argv); else { BMessenger messenger("text/html"); BMessage msg(B_NETPOSITIVE_OPEN_URL); msg.AddString("be:url", jabber_org.c_str()); messenger.SendMessage(&msg); } break; } case JAB_BE_USERS: { string jabber_org = "http://home.t-online.de/home/sascha.offe/jabber.html"; char *argv[] = {const_cast(jabber_org.c_str()), NULL}; if (!be_roster->IsRunning("text/html")) be_roster->Launch("text/html", 1, argv); else { BMessenger messenger("text/html"); BMessage msg(B_NETPOSITIVE_OPEN_URL); msg.AddString("be:url", jabber_org.c_str()); messenger.SendMessage(&msg); } break; } case JAB_JABBER_ORG: { string jabber_org = "http://www.jabber.org"; char *argv[] = {const_cast(jabber_org.c_str()), NULL}; if (!be_roster->IsRunning("text/html")) be_roster->Launch("text/html", 1, argv); else { BMessenger messenger("text/html"); BMessage msg(B_NETPOSITIVE_OPEN_URL); msg.AddString("be:url", jabber_org.c_str()); messenger.SendMessage(&msg); } break; } case JAB_JABBER_CENTRAL_ORG: { string jabber_org = "http://www.jabbercentral.org"; char *argv[] = {const_cast(jabber_org.c_str()), NULL}; if (!be_roster->IsRunning("text/html")) be_roster->Launch("text/html", 1, argv); else { BMessenger messenger("text/html"); BMessage msg(B_NETPOSITIVE_OPEN_URL); msg.AddString("be:url", jabber_org.c_str()); messenger.SendMessage(&msg); } break; } case JAB_JABBER_VIEW_COM: { string jabber_org = "http://www.jabberview.com"; char *argv[] = {const_cast(jabber_org.c_str()), NULL}; if (!be_roster->IsRunning("text/html")) be_roster->Launch("text/html", 1, argv); else { BMessenger messenger("text/html"); BMessage msg(B_NETPOSITIVE_OPEN_URL); msg.AddString("be:url", jabber_org.c_str()); messenger.SendMessage(&msg); } break; } case JAB_FAQ: { string user_guide = "http://www.users.uswest.net/~jblanco/jabber-faq.html"; char *argv[] = {const_cast(user_guide.c_str()), NULL}; if (!be_roster->IsRunning("text/html")) be_roster->Launch("text/html", 1, argv); else { BMessenger messenger("text/html"); BMessage msg(B_NETPOSITIVE_OPEN_URL); msg.AddString("be:url", user_guide.c_str()); messenger.SendMessage(&msg); } break; } case JAB_USER_GUIDE: { string user_guide = AppLocation::Instance()->AbsolutePath("resources/user-guide/user_guide.html"); char *argv[] = {const_cast(user_guide.c_str()), NULL}; if (!be_roster->IsRunning("text/html")) be_roster->Launch("text/html", 1, argv); else { BMessenger messenger("text/html"); BMessage msg(B_NETPOSITIVE_OPEN_URL); msg.AddString("be:url", user_guide.c_str()); messenger.SendMessage(&msg); } break; } case BLAB_UPDATE_ROSTER: { // a message that the roster singleton was updated _roster->UpdateRoster(); break; } case JAB_SUBSCRIBE_PRESENCE: { RosterItem *item = _roster->CurrentItemSelection(); // if there was a user selected (shouldn't be otherwise) if (item) { // don't send subscription request if we have it already if (!item->GetUserID()->HaveSubscriptionTo()) { JabberSpeak::Instance()->SendSubscriptionRequest(item->GetUserID()->JabberHandle()); } } break; } case JAB_UNSUBSCRIBE_PRESENCE: { RosterItem *item = _roster->CurrentItemSelection(); // if there was a user selected (shouldn't be otherwise) if (item) { // don't send unsubscription request if we don't have it already if (item->GetUserID()->HaveSubscriptionTo()) { JabberSpeak::Instance()->SendUnsubscriptionRequest(item->GetUserID()->Handle()); } } break; } case JAB_OPEN_CHAT_WITH_DOUBLE_CLICK: { // works in combination with JAB_OPEN_CHAT case if (!BlabberSettings::Instance()->Tag("enable-double-click")) { break; } } __attribute__ ((fallthrough)); case JAB_OPEN_CHAT: { // if there's a current selection, begin chat with that user RosterItem *item = _roster->CurrentItemSelection(); if (item != NULL) { const UserID *user = item->GetUserID(); // open chat window TalkManager::Instance()->CreateTalkSession(gloox::Message::Chat, &user->JID(), "", "", NULL); } // if there's a current selection, begin chat with that group BookmarkItem *bookmark = _roster->CurrentBookmarkSelection(); if (bookmark != NULL) { const gloox::JID& group = bookmark->GetUserID(); const gloox::ConferenceListItem* info = BookmarkManager::Instance().GetBookmark(group.full().c_str()); // open chat window TalkManager::Instance()->CreateTalkSession(gloox::Message::Groupchat, NULL, group.full(), info->nick, NULL); // Enable autojoin if needed BookmarkManager::Instance().SetBookmark(group.full().c_str(), info->nick.c_str(), bookmark->Text(), true); } break; } case JAB_SHOW_CHATLOG: { BString path; // try to get the chatlog path from message if(B_OK != msg->FindString("path", &path)) { // no path provided with message? try to open history for selected user... RosterItem *item = _roster->CurrentItemSelection(); if (item != NULL) { const UserID *user = item->GetUserID(); string chatlog_path = BlabberSettings::Instance()->Data("chatlog-path"); if(0 == chatlog_path.size()) { BPath path; find_directory(B_USER_DIRECTORY, &path); chatlog_path = path.Path(); } chatlog_path += "/" + user->JabberHandle(); path = chatlog_path.c_str(); } } // now attemt to open history file with default application for "text/x-jabber-chatlog" MIME type if(path.Length() > 0) { BEntry entry(path.String()); entry_ref ref; entry.GetRef(&ref); BMessage *msgRefs = new BMessage(B_REFS_RECEIVED); msgRefs->AddRef("refs", &ref); be_roster->Launch("text/plain", msgRefs); //be_roster->Launch(path.String()); } break; } case JAB_OPEN_NEW_CHAT: { (new SendTalkWindow(gloox::Message::Chat))->Show(); break; } case JAB_OPEN_NEW_GROUP_CHAT: { (new SendTalkWindow(gloox::Message::Groupchat))->Show(); break; } case JAB_OPEN_MESSAGE: { // if there's a current selection, begin message with that user RosterItem *item = _roster->CurrentItemSelection(); const UserID *user = item->GetUserID(); // open message window TalkManager::Instance()->CreateTalkSession(gloox::Message::Normal, &user->JID(), "", "", NULL); break; } case JAB_OPEN_NEW_MESSAGE: { (new SendTalkWindow(gloox::Message::Normal))->Show(); break; } case JAB_OPEN_ADD_BUDDY_WINDOW: { // open buddy window AddBuddyWindow::Instance()->Show(); break; } case JAB_OPEN_EDIT_BUDDY_WINDOW: { // pick out user to be edited from RosterView RosterItem *item = _roster->CurrentItemSelection(); if (item != NULL) { // open edit buddy window (new ChangeNameWindow(item->GetUserID()->JID(), item->GetUserID()->FriendlyName().c_str()))->Show(); } BookmarkItem *bookmark = _roster->CurrentBookmarkSelection(); if (bookmark != NULL) { // open edit buddy window (new ChangeNameWindow(bookmark->GetUserID(), bookmark->Text()))->Show(); } break; } case JAB_USER_INFO: { // pick out user to be analyzed RosterItem *item = _roster->CurrentItemSelection(); if (item != NULL) { // pick out user UserID *user = const_cast(item->GetUserID()); // open edit buddy window (new BuddyInfoWindow(user))->Show(); } break; } case JAB_REMOVE_BUDDY: { // pick out user to be removed from RosterView RosterItem *item = _roster->CurrentItemSelection(); if (item != NULL) { // pick out user const UserID *user = item->GetUserID(); // remove the user JabberSpeak::Instance()->RemoveFromRoster(user); } BookmarkItem *bookmark = _roster->CurrentBookmarkSelection(); if (bookmark) BookmarkManager::Instance().RemoveBookmark(bookmark->GetUserID().full().c_str()); break; } case BLAB_AVAILABLE_FOR_CHAT: { JabberSpeak::Instance()->SendPresence(gloox::Presence::Chat); _chat_item->SetMarked(true); BlabberSettings::Instance()->SetTag("last-used-custom-status", false); BlabberSettings::Instance()->SetData("last-custom-exact-status", "chat"); BlabberSettings::Instance()->WriteToFile(); break; } case BLAB_DO_NOT_DISTURB: { JabberSpeak::Instance()->SendPresence(gloox::Presence::DND); _dnd_item->SetMarked(true); BlabberSettings::Instance()->SetTag("last-used-custom-status", false); BlabberSettings::Instance()->SetData("last-custom-exact-status", "dnd"); BlabberSettings::Instance()->WriteToFile(); break; } case BLAB_AWAY_TEMPORARILY: { JabberSpeak::Instance()->SendPresence(gloox::Presence::Away); _away_item->SetMarked(true); BlabberSettings::Instance()->SetTag("last-used-custom-status", false); BlabberSettings::Instance()->SetData("last-custom-exact-status", "away"); BlabberSettings::Instance()->WriteToFile(); break; } case BLAB_AWAY_EXTENDED: { JabberSpeak::Instance()->SendPresence(gloox::Presence::XA); _xa_item->SetMarked(true); BlabberSettings::Instance()->SetTag("last-used-custom-status", false); BlabberSettings::Instance()->SetData("last-custom-exact-status", "xa"); BlabberSettings::Instance()->WriteToFile(); break; } case BLAB_SCHOOL: { JabberSpeak::Instance()->SendPresence(gloox::Presence::XA, "Off to School"); _school_item->SetMarked(true); BlabberSettings::Instance()->SetTag("last-used-custom-status", false); BlabberSettings::Instance()->SetData("last-custom-exact-status", "school"); BlabberSettings::Instance()->WriteToFile(); break; } case BLAB_WORK: { JabberSpeak::Instance()->SendPresence(gloox::Presence::XA, "Busy at Work"); _work_item->SetMarked(true); BlabberSettings::Instance()->SetTag("last-used-custom-status", false); BlabberSettings::Instance()->SetData("last-custom-exact-status", "work"); BlabberSettings::Instance()->WriteToFile(); break; } case BLAB_LUNCH: { JabberSpeak::Instance()->SendPresence(gloox::Presence::Away, "Lunch"); _lunch_item->SetMarked(true); BlabberSettings::Instance()->SetTag("last-used-custom-status", false); BlabberSettings::Instance()->SetData("last-custom-exact-status", "lunch"); BlabberSettings::Instance()->WriteToFile(); break; } case BLAB_DINNER: { JabberSpeak::Instance()->SendPresence(gloox::Presence::Away, "Dinner"); _dinner_item->SetMarked(true); BlabberSettings::Instance()->SetTag("last-used-custom-status", false); BlabberSettings::Instance()->SetData("last-custom-exact-status", "dinner"); BlabberSettings::Instance()->WriteToFile(); break; } case BLAB_SLEEP: { JabberSpeak::Instance()->SendPresence(gloox::Presence::XA, "Sleeping"); _sleep_item->SetMarked(true); BlabberSettings::Instance()->SetTag("last-used-custom-status", false); BlabberSettings::Instance()->SetData("last-custom-exact-status", "sleep"); BlabberSettings::Instance()->WriteToFile(); break; } case BLAB_CUSTOM_STATUS: { CustomStatusWindow::Instance()->Show(); CustomStatusWindow::Instance()->Activate(); break; } case kResetWindow: { JabberSpeak::Instance()->Reset(); ShowLogin(); break; } case JAB_ROTATE_CHAT_FORWARD: { int currentIndex = fTalkCards->VisibleIndex(); int itemCount = fTalkCards->CountItems(); if (++currentIndex >= itemCount) currentIndex = 0; if (currentIndex < itemCount) { fTalkCards->SetVisibleItem(currentIndex); TalkView* v = (TalkView*)fTalkCards->ItemAt(currentIndex)->View(); if (v->IsGroupChat()) { int item = _roster->FindBookmark(gloox::JID(v->GetGroupRoom())); _roster->Select(item); } else { int item = _roster->FindUser(v->GetUserID()); _roster->Select(item); } } break; } case JAB_ROTATE_CHAT_BACKWARD: { int currentIndex = fTalkCards->VisibleIndex(); int itemCount = fTalkCards->CountItems(); if (--currentIndex < 0) currentIndex = itemCount - 1; if (currentIndex > 0) { fTalkCards->SetVisibleItem(currentIndex); TalkView* v = (TalkView*)fTalkCards->ItemAt(currentIndex)->View(); if (v->IsGroupChat()) { int item = _roster->FindBookmark(gloox::JID(v->GetGroupRoom())); _roster->Select(item); } else { int item = _roster->FindUser(v->GetUserID()); _roster->Select(item); } } break; } case kAddTalkView: { TalkView* view; msg->FindPointer("view", (void**)&view); AddTalkView(view); break; } case B_OBSERVER_NOTICE_CHANGE: { int32 orig_what = msg->FindInt32("be:observe_change_what"); switch (orig_what) { case kAuthenticationFailed: { ShowLogin(); _login_username->MarkAsInvalid(true); _login_password->MarkAsInvalid(true); break; } } break; } default: BWindow::MessageReceived(msg); break; } } void BlabberMainWindow::MenusBeginning() { char buffer[1024]; // FILE menu if (!_full_view->IsHidden()) { _disconnect_item->SetEnabled(true); } else { _disconnect_item->SetEnabled(false); } // EDIT menu if (RosterItem *item = _roster->CurrentItemSelection()) { // if a item is selected sprintf(buffer, "Edit %s", item->GetUserID()->FriendlyName().c_str()); _change_buddy_item->SetLabel(buffer); _change_buddy_item->SetEnabled(true); sprintf(buffer, "Remove %s", item->GetUserID()->FriendlyName().c_str()); _remove_buddy_item->SetLabel(buffer); _remove_buddy_item->SetEnabled(true); _user_info_item->SetEnabled(true); } else { sprintf(buffer, "Edit Buddy"); _change_buddy_item->SetLabel(buffer); _change_buddy_item->SetEnabled(false); sprintf(buffer, "Remove Buddy"); _remove_buddy_item->SetLabel(buffer); _remove_buddy_item->SetEnabled(false); _user_info_item->SetEnabled(false); } } bool BlabberMainWindow::QuitRequested() { // remember last coordinates BlabberSettings::Instance()->SetFloatData("main-window-left", Frame().left); BlabberSettings::Instance()->SetFloatData("main-window-top", Frame().top); BlabberSettings::Instance()->SetFloatData("main-window-width", Bounds().Width()); BlabberSettings::Instance()->SetFloatData("main-window-height", Bounds().Height()); BlabberSettings::Instance()->WriteToFile(); // FIXME we are doing this from the wrong thread, but I see no better place. // It needs to be done immediately here, so that closing the other windows // doen't remove them from autojoin. BookmarkManager::Instance().Disconnect(); be_app->PostMessage(B_QUIT_REQUESTED); return true; } BlabberMainWindow::BlabberMainWindow(BRect frame) : BWindow(frame, "Renga", B_DOCUMENT_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS) { // editing filter for taksing AddCommonFilter(new RotateChatFilter()); // add self to message family MessageRepeater::Instance()->AddTarget(this); // encompassing view _full_view = new BGroupView("main-full", B_VERTICAL); _full_view->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); // status bar _status_view = new StatusView(); _status_view->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); // menubar BMenuBar* menubar = new BMenuBar("menubar"); // FILE MENU BMenu* file_menu = new BMenu("Window"); _disconnect_item = new BMenuItem("Log Out", new BMessage(JAB_DISCONNECT)); _about_item = new BMenuItem("About Renga" B_UTF8_ELLIPSIS, new BMessage(B_ABOUT_REQUESTED)); _quit_item = new BMenuItem("Quit", new BMessage(JAB_QUIT)); _quit_item->SetShortcut('Q', 0); _preferences_item = new BMenuItem("Preferences" B_UTF8_ELLIPSIS, new BMessage(JAB_PREFERENCES)); _preferences_item->SetShortcut(',', 0); file_menu->AddItem(_preferences_item); file_menu->AddSeparatorItem(); file_menu->AddItem(_disconnect_item); file_menu->AddSeparatorItem(); file_menu->AddItem(_quit_item); file_menu->SetTargetForItems(MessageRepeater::Instance()); // EDIT MENU BMenu* edit_menu = new BMenu("Buddy"); _add_buddy_item = new BMenuItem("Add New Buddy", new BMessage(JAB_OPEN_ADD_BUDDY_WINDOW)); _add_buddy_item->SetShortcut('N', 0); _change_buddy_item = new BMenuItem("Edit Buddy", new BMessage(JAB_OPEN_EDIT_BUDDY_WINDOW)); _change_buddy_item->SetShortcut('E', 0); _remove_buddy_item = new BMenuItem("Remove Buddy", new BMessage(JAB_REMOVE_BUDDY)); _remove_buddy_item->SetShortcut('T', 0); _user_info_item = new BMenuItem("Get Buddy Info", new BMessage(JAB_USER_INFO)); _user_info_item->SetShortcut('G', 0); edit_menu->AddItem(_add_buddy_item); edit_menu->AddItem(_change_buddy_item); edit_menu->AddItem(_remove_buddy_item); edit_menu->AddSeparatorItem(); edit_menu->AddItem(_user_info_item); edit_menu->SetTargetForItems(this); // STATUS MENU BMenu* status_menu = new BMenu("Status"); _chat_item = new BMenuItem("I'm available for chat.", new BMessage(BLAB_AVAILABLE_FOR_CHAT)); _away_item = new BMenuItem("I will be away temporarily.", new BMessage(BLAB_AWAY_TEMPORARILY)); _dnd_item = new BMenuItem("Do not disturb me.", new BMessage(BLAB_DO_NOT_DISTURB)); _xa_item = new BMenuItem("I will be away for an extended time period.", new BMessage(BLAB_AWAY_EXTENDED)); _school_item = new BMenuItem("Off to School", new BMessage(BLAB_SCHOOL)); _work_item = new BMenuItem("Busy at Work", new BMessage(BLAB_WORK)); _lunch_item = new BMenuItem("Lunch", new BMessage(BLAB_LUNCH)); _dinner_item = new BMenuItem("Dinner", new BMessage(BLAB_DINNER)); _sleep_item = new BMenuItem("Sleeping", new BMessage(BLAB_SLEEP)); _custom_item = new BMenuItem("Custom...", new BMessage(BLAB_CUSTOM_STATUS)); status_menu->AddItem(_chat_item); status_menu->AddSeparatorItem(); status_menu->AddItem(_away_item); status_menu->AddItem(_dnd_item); status_menu->AddItem(_xa_item); status_menu->AddSeparatorItem(); status_menu->AddItem(_school_item); status_menu->AddItem(_work_item); status_menu->AddItem(_lunch_item); status_menu->AddItem(_dinner_item); status_menu->AddItem(_sleep_item); status_menu->AddSeparatorItem(); status_menu->AddItem(_custom_item); status_menu->SetRadioMode(true); _chat_item->SetMarked(true); // TALK MENU BMenu* talk_menu = new BMenu("Talk"); BMenuItem* rotate_chat_forward_item = new BMenuItem("Rotate Chat Forward", new BMessage(JAB_ROTATE_CHAT_FORWARD)); rotate_chat_forward_item->SetShortcut(B_UP_ARROW, B_SHIFT_KEY); BMenuItem* rotate_chat_backward_item = new BMenuItem("Rotate Chat Backward", new BMessage(JAB_ROTATE_CHAT_BACKWARD)); rotate_chat_backward_item->SetShortcut(B_DOWN_ARROW, B_SHIFT_KEY); _send_message_item = new BMenuItem("Send Message...", new BMessage(JAB_OPEN_NEW_MESSAGE)); _send_message_item->SetShortcut('M', 0); _send_chat_item = new BMenuItem("Start Chat...", new BMessage(JAB_OPEN_NEW_CHAT)); _send_groupchat_item = new BMenuItem("Start Group Chat...", new BMessage(JAB_OPEN_NEW_GROUP_CHAT)); talk_menu->AddItem(rotate_chat_forward_item); talk_menu->AddItem(rotate_chat_backward_item); talk_menu->AddSeparatorItem(); talk_menu->AddItem(_send_message_item); talk_menu->AddItem(_send_chat_item); talk_menu->AddItem(_send_groupchat_item); talk_menu->SetTargetForItems(this); // HELP MENU BMenu* help_menu = new BMenu("Help"); BMenuItem* user_guide_item = new BMenuItem("Renga Manual", new BMessage(JAB_USER_GUIDE)); BMenuItem* faq_item = new BMenuItem("Renga FAQ", new BMessage(JAB_FAQ)); help_menu->AddItem(user_guide_item); help_menu->AddItem(faq_item); help_menu->AddSeparatorItem(); help_menu->AddItem(_about_item); help_menu->SetTargetForItems(this); menubar->AddItem(file_menu); menubar->AddItem(edit_menu); menubar->AddItem(status_menu); menubar->AddItem(talk_menu); menubar->AddItem(help_menu); // tabbed view // roster view _roster = new RosterView(); BScrollView* roster_scroller = new BScrollView(NULL, _roster, 0, false, true, B_NO_BORDER); _roster->TargetedByScrollView(roster_scroller); // chat service BLayoutBuilder::Group<>(_full_view, B_VERTICAL, 0) .SetInsets(0, 0, 0, 0) .Add(menubar) .AddSplit(B_HORIZONTAL, 0) .AddGroup(B_VERTICAL, 0, 0) .Add(roster_scroller) .Add(_status_view) .End() .AddCards() .GetLayout(&fTalkCards) .End() .End() .End(); ///// NOW DO LOGIN STUFF // encompassing view _login_full_view = new BGroupView("login-full", B_VERTICAL); _login_full_view->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); // graphics _login_bulb = new PictureView("bulb-normal"); // username/password controls _login_realname = new BTextControl(NULL, "Nickname: ", NULL, NULL); _login_username = new BTextControl(NULL, "Jabber ID: ", NULL, NULL); _login_password = new BTextControl(NULL, "Password: ", NULL, NULL); _login_password->TextView()->HideTyping(true); BMessage* createAccount = new BMessage(kCreateAccount); _login_new_account = new BButton("create", "Create a new account", createAccount); _login_auto_login = new BCheckBox(NULL, "Auto-login", NULL); // login button _login_login = new BButton("login", "Login", new BMessage(JAB_LOGIN)); _login_login->MakeDefault(false); _login_login->SetTarget(this); BStringView* appName = new BStringView("app name", "Renga"); BFont bigfont(be_plain_font); bigfont.SetSize(bigfont.Size() * 3); appName->SetFont(&bigfont); BLayoutBuilder::Group<>(_login_full_view, B_HORIZONTAL) .AddGlue() .AddGroup(B_VERTICAL) .SetInsets(B_USE_DEFAULT_SPACING) .AddGrid() .Add(_login_bulb, 0, 0, 1, 4) .Add(appName, 1, 1) .Add(new BStringView("", "XMPP client for Haiku"), 1, 2) .End() .Add(_login_new_account) .AddGlue() .AddGrid() .AddTextControl(_login_realname, 0, 0) .AddTextControl(_login_username, 0, 1) .AddTextControl(_login_password, 0, 2) .End() .AddGroup(B_HORIZONTAL) .Add(_login_auto_login) .AddGlue() .Add(_login_login) .End() .AddGlue() .End() .AddGlue() .End(); // attach all-encompassing main view to window BCardLayout* cl = new BCardLayout(); SetLayout(cl); AddChild(_full_view); AddChild(_login_full_view); // login always hidden at start cl->SetVisibleItem((int32)0); // default if(BlabberSettings::Instance()->Data("last-realname")) { _login_realname->SetText(BlabberSettings::Instance()->Data("last-realname")); } else { _login_realname->SetText("Me"); } if (BlabberSettings::Instance()->Data("last-login")) { _login_username->SetText(BlabberSettings::Instance()->Data("last-login")); } else { _login_username->SetText("newuser@jabber.org"); } _login_password->SetText(BlabberSettings::Instance()->Data("last-password")); _login_auto_login->SetValue(BlabberSettings::Instance()->Tag("auto-login")); // focus to start if (BlabberSettings::Instance()->Data("last-login")) { _login_password->MakeFocus(true); } else { _login_username->MakeFocus(true); } JabberSpeak::Instance()->StartWatchingAll(this); // editing filter for taksing AddCommonFilter(new RotateChatFilter()); } bool BlabberMainWindow::ValidateLogin() { // existance of username if (!strcmp(_login_username->Text(), "")) { ModalAlertFactory::Alert("Wait, you haven't specified your Jabber ID yet.\n(e.g. haikuFan@jabber.org)", "Doh!", NULL, NULL, B_WIDTH_FROM_LABEL, B_STOP_ALERT); _login_username->MakeFocus(true); return false; } // validity of username std::string validate = UserID::WhyNotValidJabberHandle(_login_username->Text()); if (validate.size()) { BString buffer; buffer.SetToFormat("The Jabber ID you specified must not be yours because it's invalid for the following reason:\n\n%s\n\nIf you can't remember it, it's OK to create a new one by checking the \"Create a new Jabber Account!\" box.", validate.c_str()); ModalAlertFactory::Alert(buffer, "OK", NULL, NULL, B_WIDTH_FROM_LABEL, B_STOP_ALERT); _login_username->MakeFocus(true); return false; } gloox::JID username(_login_username->Text()); // check existance of password if (!strcmp(_login_password->Text(), "")) { char buffer[1024]; sprintf(buffer, "You must specify a password so I can make sure it's you, %s.", username.username().c_str()); ModalAlertFactory::Alert(buffer, "Sorry!", NULL, NULL, B_WIDTH_FROM_LABEL, B_STOP_ALERT); _login_password->MakeFocus(true); return false; } return true; } void BlabberMainWindow::ShowLogin() { // reassign button as default _login_login->MakeDefault(true); // reset _login_realname->SetText(""); _login_username->SetText(""); _login_password->SetText(""); _login_username->MarkAsInvalid(false); _login_password->MarkAsInvalid(false); // default if(BlabberSettings::Instance()->Data("last-realname")) { _login_realname->SetText(BlabberSettings::Instance()->Data("last-realname")); } else { _login_realname->SetText("Me"); } if (BlabberSettings::Instance()->Data("last-login")) { _login_username->SetText(BlabberSettings::Instance()->Data("last-login")); } else { _login_username->SetText("newuser@jabber.org"); } _login_password->SetText(BlabberSettings::Instance()->Data("last-password")); // focus to start if (BlabberSettings::Instance()->Data("last-login")) { _login_password->MakeFocus(true); } else { _login_username->MakeFocus(true); } BCardLayout* cl = (BCardLayout*)GetLayout(); cl->SetVisibleItem(1); } void BlabberMainWindow::SetCustomStatus(string status) { char buffer[2048]; // create menued status message sprintf(buffer, "[Custom] %s", status.c_str()); _custom_item->SetMarked(true); _custom_item->SetLabel(buffer); } void BlabberMainWindow::FlagBookmarkItem(const gloox::JID& room, uint32 flags) { int32 pos = _roster->FindBookmark(room); if (pos < 0) return; auto* item = dynamic_cast(_roster->FullListItemAt(pos)); item->SetFlag(flags); // Need to redo a FindItem because there is no FullListInvalidateItem, so we need to convert the // FullList index returned by FindBookmark to a BListView index... int32 listIndex = _roster->IndexOf(item); // ... and this can fail if the item is in a collapsed part of the list if (listIndex < 0) return; _roster->InvalidateItem(listIndex); } void BlabberMainWindow::AddTalkView(TalkView* view) { if (view->Window() != this) { fTalkCards->AddView(view); } fTalkCards->SetVisibleItem(fTalkCards->IndexOfView(view)); }