1 // Copyright (C) 2015 Wade Berrier <wberrier@gmail.com>
3 // This file is part of CenterIM.
5 // CenterIM is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // CenterIM is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with CenterIM. If not, see <http://www.gnu.org/licenses/>.
18 #include "ConversationRoomList.h"
20 // Move the widget to a position according to sorting function.
21 void ConversationRoomList::moveToSortedPosition(Buddy
*new_buddy
)
23 Buddy
*buddy
= nullptr;
24 CppConsUI::Widgets::iterator iter
;
26 g_assert(new_buddy
!= nullptr);
28 for (iter
= children_
.begin(); iter
!= children_
.end(); ++iter
) {
29 buddy
= dynamic_cast<Buddy
*>(*iter
);
30 g_assert(buddy
!= nullptr);
32 // If buddy is in the list already, skip it.
33 if (*buddy
== *new_buddy
)
36 // Break once insertion point is found.
37 if (!Buddy::less_than_op_away_name(*buddy
, *new_buddy
))
41 // Do not change anything if wanting to put into the same position (also
42 // returns on single node case).
43 if (*buddy
== *new_buddy
)
46 // Insert after if at end.
47 if (iter
== children_
.end())
48 moveWidgetAfter(*new_buddy
, *buddy
);
50 moveWidgetBefore(*new_buddy
, *buddy
);
53 void ConversationRoomList::add_users(GList
*cbuddies
, gboolean
/*new_arrivals*/)
55 for (GList
*l
= cbuddies
; l
!= nullptr; l
= l
->next
) {
56 PurpleConvChatBuddy
*pbuddy
= static_cast<PurpleConvChatBuddy
*>(l
->data
);
58 auto buddy
= new Buddy(pbuddy
);
59 buddy
->setButtonText();
60 buddies_
[pbuddy
->name
] = buddy
;
64 moveToSortedPosition(buddy
);
68 void ConversationRoomList::rename_user(
69 const char *old_name
, const char *new_name
, const char * /*new_alias*/)
71 // The old PurpleConvChatBuddy is still valid while
72 // this function is executing
73 // PurpleConvChatBuddy * old_pbuddy = purple_conv_chat_cb_find(
74 // conv_->u.chat, old_name);
76 PurpleConvChat
*conv
= PURPLE_CONV_CHAT(conv_
);
77 g_assert(conv
!= nullptr);
79 PurpleConvChatBuddy
*new_pbuddy
= purple_conv_chat_cb_find(conv
, new_name
);
80 // g_assert(old_pbuddy != nullptr);
81 g_assert(new_pbuddy
!= nullptr);
83 // NOTE: PurpleConvChatBuddy::ui_data is pidgin 2.9!!
84 // Buddy * buddy = static_cast<Buddy *>(old_pbuddy->ui_data);
85 Buddy
*buddy
= buddies_
[old_name
];
86 g_assert(buddy
!= nullptr);
89 buddy
->setPurpleBuddy(new_pbuddy
);
92 buddies_
.erase(old_name
);
93 buddies_
[new_name
] = buddy
;
95 // Move and then update.
96 moveToSortedPosition(buddy
);
97 buddy
->setButtonText();
100 void ConversationRoomList::remove_users(GList
*users
)
102 for (GList
*l
= users
; l
!= nullptr; l
= l
->next
) {
103 const char *name
= static_cast<const char *>(l
->data
);
105 // NOTE: can't remove purple_conv_chat_cb_find, because the user
106 // and PurpleConvChatBuddy has already been removed
108 Buddies::iterator iter
= buddies_
.find(name
);
110 if (buddies_
.end() != iter
) {
111 buddies_
.erase(iter
);
112 // NOTE: this deletes the buddy object.
113 removeWidget(*iter
->second
);
118 void ConversationRoomList::update_user(const char *user
)
120 PurpleConvChat
*conv
= PURPLE_CONV_CHAT(conv_
);
121 g_assert(conv
!= nullptr);
123 PurpleConvChatBuddy
*pbuddy
= purple_conv_chat_cb_find(conv
, user
);
124 g_assert(pbuddy
!= nullptr);
126 // NOTE: PurpleConvChatBuddy::ui_data is pidgin 2.9!!
127 // Buddy * buddy = static_cast<Buddy *>(pbuddy->ui_data);
128 Buddy
*buddy
= buddies_
[user
];
129 g_assert(buddy
!= nullptr);
131 // Move and then update.
132 moveToSortedPosition(buddy
);
133 buddy
->setButtonText();
136 ConversationRoomList::Buddy::Buddy(PurpleConvChatBuddy
*pbuddy
)
137 : CppConsUI::Button(AUTOSIZE
, 1, ""), pbuddy_(pbuddy
)
140 // NOTE: PurpleConvChatBuddy::ui_data is pidgin 2.9!!
141 // pbuddy_->ui_data = static_cast<void*>(this);
144 ConversationRoomList::Buddy::~Buddy()
148 void ConversationRoomList::Buddy::readFlags(
149 bool &is_op
, bool &is_typing
, bool &is_away
) const
151 g_assert(pbuddy_
!= nullptr);
153 PurpleConvChatBuddyFlags flags
= pbuddy_
->flags
;
155 // TODO: how about founder? Does that matter?
157 is_op
= (((flags
& PURPLE_CBFLAGS_OP
) != 0));
158 is_typing
= (((flags
& PURPLE_CBFLAGS_TYPING
) != 0));
159 #if PURPLE_VERSION_CHECK(2, 8, 0)
160 is_away
= (((flags
& PURPLE_CBFLAGS_AWAY
) != 0));
166 void ConversationRoomList::Buddy::setButtonText()
168 char *text
= displayText();
173 char *ConversationRoomList::Buddy::displayText() const
178 bool is_typing
= false;
179 bool is_away
= false;
181 readFlags(is_op
, is_typing
, is_away
);
183 ret
= g_strdup_printf("[%s] %s%s%s", (is_away
? "a" : "o"),
184 (is_op
? "@" : ""), displayName(), (is_typing
? "*" : ""));
186 // TODO: elide long names?
191 const char *ConversationRoomList::Buddy::displayName() const
193 g_assert(pbuddy_
!= nullptr);
196 // NOTE: pbuddy_->alias_key isn't used yet... (according to docs)
197 if (pbuddy_
->alias
!= nullptr)
198 return pbuddy_
->alias
;
200 return pbuddy_
->name
;
203 bool ConversationRoomList::Buddy::operator==(const Buddy
&rhs
)
205 return pbuddy_
== rhs
.pbuddy_
;
208 void ConversationRoomList::Buddy::setPurpleBuddy(PurpleConvChatBuddy
*pbuddy
)
211 // NOTE: PurpleConvChatBuddy::ui_data is pidgin 2.9!!
212 // pbuddy_->ui_data = static_cast<void*>(this);
215 bool ConversationRoomList::Buddy::less_than_op_away_name(
216 const Buddy
&lhs
, const Buddy
&rhs
)
221 // 2. online (vs away)
224 bool lhs_is_op
, lhs_is_typing
, lhs_is_away
;
225 bool rhs_is_op
, rhs_is_typing
, rhs_is_away
;
227 lhs
.readFlags(lhs_is_op
, lhs_is_typing
, lhs_is_away
);
228 rhs
.readFlags(rhs_is_op
, rhs_is_typing
, rhs_is_away
);
230 // Probably a more elegant way to do this.
231 if (lhs_is_op
&& !rhs_is_op
)
233 else if (!lhs_is_op
&& rhs_is_op
)
235 // Equal op or non-op status.
237 if (lhs_is_away
&& !rhs_is_away
)
239 else if (!lhs_is_away
&& rhs_is_away
)
241 // On equal online/away status.
243 return g_utf8_collate(lhs
.displayName(), rhs
.displayName()) < 0;
247 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: