1 /*
2 * Copyright © 2004-2008 Jens Oknelid, paskharen@gmail.com
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * In addition, as a special exception, compiling, linking, and/or
19 * using OpenSSL with this program is allowed.
20 */
21
22 #include "privatemessage.hh"
23
24 #include <dcpp/ClientManager.h>
25 #include <dcpp/FavoriteManager.h>
26 #include "wulformanager.hh"
27 #include "WulforUtil.hh"
28 #include "search.hh"
29
30 using namespace std;
31 using namespace dcpp;
32
33 const std::string PrivateMessage::USER_AVAILABLE_ICON = "user-available";
34 const std::string PrivateMessage::USER_OFFLINE_ICON = "user-offline";
35
PrivateMessage(const string & cid,const string & hubUrl)36 PrivateMessage::PrivateMessage(const string &cid, const string &hubUrl):
37 BookEntry(Entry::PRIVATE_MESSAGE, cid, "privatemessage.glade", cid),
38 cid(cid),
39 hubUrl(hubUrl),
40 historyIndex(0),
41 sentAwayMessage(FALSE),
42 scrollToBottom(TRUE)
43 {
44 // Intialize the chat window
45 if (SETTING(USE_OEM_MONOFONT))
46 {
47 PangoFontDescription *fontDesc = pango_font_description_new();
48 pango_font_description_set_family(fontDesc, "Mono");
49 gtk_widget_modify_font(getWidget("text"), fontDesc);
50 pango_font_description_free(fontDesc);
51 }
52 GtkTextIter iter;
53 buffer = gtk_text_buffer_new(NULL);
54 gtk_text_view_set_buffer(GTK_TEXT_VIEW(getWidget("text")), buffer);
55 gtk_text_buffer_get_end_iter(buffer, &iter);
56 mark = gtk_text_buffer_create_mark(buffer, NULL, &iter, FALSE);
57 handCursor = gdk_cursor_new(GDK_HAND2);
58
59 /* FIXME: BOOLSETTING(PRIVATE_MESSGE_BEEP_OPEN) has been changed to
60 * FIXME: STRINGSETTING(SOUND_PM_WINDOW)
61
62 if (BOOLSETTING(PRIVATE_MESSAGE_BEEP_OPEN))
63 gdk_beep();
64 */
65
66 GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(getWidget("scroll")));
67
68 // Connect the signals to their callback functions.
69 g_signal_connect(getContainer(), "focus-in-event", G_CALLBACK(onFocusIn_gui), (gpointer)this);
70 g_signal_connect(getWidget("entry"), "activate", G_CALLBACK(onSendMessage_gui), (gpointer)this);
71 g_signal_connect(getWidget("entry"), "key-press-event", G_CALLBACK(onKeyPress_gui), (gpointer)this);
72 g_signal_connect(getWidget("text"), "motion-notify-event", G_CALLBACK(onChatPointerMoved_gui), (gpointer)this);
73 g_signal_connect(getWidget("text"), "visibility-notify-event", G_CALLBACK(onChatVisibilityChanged_gui), (gpointer)this);
74 g_signal_connect(adjustment, "value_changed", G_CALLBACK(onChatScroll_gui), (gpointer)this);
75 g_signal_connect(adjustment, "changed", G_CALLBACK(onChatResize_gui), (gpointer)this);
76 g_signal_connect(getWidget("copyLinkItem"), "activate", G_CALLBACK(onCopyURIClicked_gui), (gpointer)this);
77 g_signal_connect(getWidget("openLinkItem"), "activate", G_CALLBACK(onOpenLinkClicked_gui), (gpointer)this);
78 g_signal_connect(getWidget("copyhubItem"), "activate", G_CALLBACK(onCopyURIClicked_gui), (gpointer)this);
79 g_signal_connect(getWidget("openhubItem"), "activate", G_CALLBACK(onOpenHubClicked_gui), (gpointer)this);
80 g_signal_connect(getWidget("copyMagnetItem"), "activate", G_CALLBACK(onCopyURIClicked_gui), (gpointer)this);
81 g_signal_connect(getWidget("searchMagnetItem"), "activate", G_CALLBACK(onSearchMagnetClicked_gui), (gpointer)this);
82 g_signal_connect(getWidget("magnetPropertiesItem"), "activate", G_CALLBACK(onMagnetPropertiesClicked_gui), (gpointer)this);
83
84 gtk_widget_grab_focus(getWidget("entry"));
85 history.push_back("");
86 user = ClientManager::getInstance()->findUser(CID(cid));
87 isBot = user ? user->isSet(User::BOT) : FALSE;
88
89 updateUserStatus_gui(WulforUtil::getNicks(cid), WulforUtil::getHubNames(cid));
90 }
91
~PrivateMessage()92 PrivateMessage::~PrivateMessage()
93 {
94 ClientManager::getInstance()->removeListener(this);
95 if (handCursor)
96 {
97 gdk_cursor_unref(handCursor);
98 handCursor = NULL;
99 }
100 }
101
show()102 void PrivateMessage::show()
103 {
104 ClientManager::getInstance()->addListener(this);
105 }
106
addMessage_gui(string message)107 void PrivateMessage::addMessage_gui(string message)
108 {
109 addLine_gui(message);
110
111 if (BOOLSETTING(LOG_PRIVATE_CHAT))
112 {
113 StringMap params;
114 params["message"] = message;
115 params["hubNI"] = WulforUtil::getHubNames(cid);
116 params["hubURL"] = Util::toString(ClientManager::getInstance()->getHubs(CID(cid)));
117 params["userCID"] = cid;
118 params["userNI"] = ClientManager::getInstance()->getNicks(CID(cid))[0];
119 params["myCID"] = ClientManager::getInstance()->getMe()->getCID().toBase32();
120 LOG(LogManager::PM, params);
121 }
122
123 if (BOOLSETTING(BOLD_PM))
124 setUrgent_gui();
125
126 /*if (BOOLSETTING(PRIVATE_MESSAGE_BEEP) && !isActive_gui())
127 gdk_beep();
128 */
129
130 // Send an away message, but only the first time after setting away mode.
131 if (!Util::getAway())
132 {
133 sentAwayMessage = FALSE;
134 }
135 else if (!sentAwayMessage && !(BOOLSETTING(NO_AWAYMSG_TO_BOTS) && isBot))
136 {
137 sentAwayMessage = TRUE;
138 typedef Func1<PrivateMessage, string> F1;
139 F1 *func = new F1(this, &PrivateMessage::sendMessage_client, Util::getAwayMessage());
140 WulforManager::get()->dispatchClientFunc(func);
141 }
142
143 /* FIXME: BOOLSETTING(PRIVATE_MESSAGE_BEEP) has been changed to
144 * FIXME: STRINGSETTING(SOUND_PM)
145 if (BOOLSETTING(PRIVATE_MESSAGE_BEEP))
146 {
147 MainWindow *mw = WulforManager::get()->getMainWindow();
148 GdkWindowState state = gdk_window_get_state(mw->getContainer()->window);
149 if ((state & GDK_WINDOW_STATE_ICONIFIED) || mw->currentPage_gui() != getContainer())
150 gdk_beep();
151 }
152 */
153 }
154
addStatusMessage_gui(string message)155 void PrivateMessage::addStatusMessage_gui(string message)
156 {
157 addLine_gui("*** " + message);
158 }
159
addLine_gui(const string & message)160 void PrivateMessage::addLine_gui(const string &message)
161 {
162 GtkTextIter iter;
163 string line = "";
164 string::size_type start, end = 0;
165 GtkTextIter i_start, i_end;
166
167 // Add a new line if this isn't the first line in buffer.
168 if (gtk_text_buffer_get_char_count(buffer) > 0)
169 line = "\n";
170
171 if (BOOLSETTING(TIME_STAMPS))
172 line += "[" + Util::getShortTimeString() + "] ";
173
174 line += message;
175
176 gtk_text_buffer_get_end_iter(buffer, &iter);
177 gtk_text_buffer_insert(buffer, &iter, line.c_str(), line.size());
178
179 // check for URIs in line
180 gtk_text_buffer_get_end_iter(buffer, &iter);
181
182 while ((start = line.find_first_not_of(" \n\r\t", end)) != string::npos)
183 {
184 end = line.find_first_of(" \n\r\t", start);
185 if (end == string::npos)
186 end = line.size();
187
188 string uri = line.substr(start, end - start);
189 GCallback callback = NULL;
190
191 if (WulforUtil::isLink(uri))
192 callback = G_CALLBACK(onLinkTagEvent_gui);
193 else if (WulforUtil::isHubURL(uri))
194 callback = G_CALLBACK(onHubTagEvent_gui);
195 else if (WulforUtil::isMagnet(uri))
196 callback = G_CALLBACK(onMagnetTagEvent_gui);
197
198 if (callback)
199 {
200 // check for the URI in our buffer
201 GtkTextTag *tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), uri.c_str());
202
203 if (!tag)
204 {
205 tag = gtk_text_buffer_create_tag(buffer, uri.c_str(), "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL);
206 g_signal_connect(tag, "event", callback, (gpointer)this);
207 }
208
209 i_start = i_end = iter;
210 gtk_text_iter_backward_chars(&i_start, g_utf8_strlen(line.c_str() + start, -1));
211 gtk_text_iter_backward_chars(&i_end, g_utf8_strlen(line.c_str() + end, -1));
212 gtk_text_buffer_apply_tag(buffer, tag, &i_start, &i_end);
213 }
214 }
215
216 if (gtk_text_buffer_get_line_count(buffer) > maxLines)
217 {
218 GtkTextIter next;
219 gtk_text_buffer_get_start_iter(buffer, &iter);
220 gtk_text_buffer_get_iter_at_line(buffer, &next, 1);
221 gtk_text_buffer_delete(buffer, &iter, &next);
222 }
223 }
224
updateCursor(GtkWidget * widget)225 void PrivateMessage::updateCursor(GtkWidget *widget)
226 {
227 gint x, y, buf_x, buf_y;
228 GtkTextIter iter;
229 GSList *tagList;
230 GtkTextTag *newTag = NULL;
231
232 gdk_window_get_pointer(widget->window, &x, &y, NULL);
233
234 // Check for tags under the cursor, and change mouse cursor appropriately
235 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_WIDGET, x, y, &buf_x, &buf_y);
236 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &iter, buf_x, buf_y);
237 tagList = gtk_text_iter_get_tags(&iter);
238
239 if (tagList != NULL)
240 {
241 newTag = GTK_TEXT_TAG(tagList->data);
242 g_slist_free(tagList);
243 }
244
245
246 if (newTag != selectedTag)
247 {
248 // Cursor is in transition.
249 if (newTag != NULL)
250 {
251 // Cursor is entering a tag.
252 selectedURI = newTag->name;
253 if (selectedTag == NULL)
254 {
255 // Cursor was in neutral space.
256 gdk_window_set_cursor(gtk_text_view_get_window(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT), handCursor);
257 }
258 }
259 else
260 {
261 // Cursor is entering neutral space.
262 gdk_window_set_cursor(gtk_text_view_get_window(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT), NULL);
263 }
264
265 selectedTag = newTag;
266 }
267 }
268
updateUserStatus_gui(string nicks,string hubs,bool online,string statusMessage)269 void PrivateMessage::updateUserStatus_gui(string nicks, string hubs, bool online, string statusMessage)
270 {
271 setLabel_gui(nicks + " - " + hubs);
272 setIcon_gui(online ? USER_AVAILABLE_ICON : USER_OFFLINE_ICON);
273
274 if (!statusMessage.empty())
275 addStatusMessage_gui(statusMessage);
276 }
277
onFocusIn_gui(GtkWidget * widget,GdkEventFocus * event,gpointer data)278 gboolean PrivateMessage::onFocusIn_gui(GtkWidget *widget, GdkEventFocus *event, gpointer data)
279 {
280 PrivateMessage *pm = (PrivateMessage *)data;
281
282 gtk_widget_grab_focus(pm->getWidget("entry"));
283
284 return TRUE;
285 }
286
onSendMessage_gui(GtkEntry * entry,gpointer data)287 void PrivateMessage::onSendMessage_gui(GtkEntry *entry, gpointer data)
288 {
289 string text = gtk_entry_get_text(entry);
290 if (text.empty())
291 return;
292
293 PrivateMessage *pm = (PrivateMessage *)data;
294 gtk_entry_set_text(entry, "");
295
296 // Store line in chat history
297 pm->history.pop_back();
298 pm->history.push_back(text);
299 pm->history.push_back("");
300 pm->historyIndex = pm->history.size() - 1;
301 if (pm->history.size() > maxHistory + 1)
302 pm->history.erase(pm->history.begin());
303
304 // Process special commands
305 if (text[0] == '/')
306 {
307 string command, param;
308 string::size_type separator = text.find_first_of(' ');
309 if (separator != string::npos && text.size() > separator + 1)
310 {
311 command = text.substr(1, separator - 1);
312 param = text.substr(separator + 1);
313 }
314 else
315 {
316 command = text.substr(1);
317 }
318 std::transform(command.begin(), command.end(), command.begin(), (int(*)(int))tolower);
319
320 if (command == "away")
321 {
322 if (Util::getAway() && param.empty())
323 {
324 Util::setAway(FALSE);
325 Util::setManualAway(FALSE);
326 pm->addStatusMessage_gui(_("Away mode off"));
327 pm->sentAwayMessage = FALSE;
328 }
329 else
330 {
331 Util::setAway(TRUE);
332 Util::setManualAway(TRUE);
333 Util::setAwayMessage(param);
334 pm->addStatusMessage_gui(F_("Away mode on: %1%", % Util::getAwayMessage()));
335 }
336 }
337 else if (command == "back")
338 {
339 Util::setAway(FALSE);
340 pm->addStatusMessage_gui(_("Away mode off"));
341 }
342 else if (command == "clear")
343 {
344 GtkTextIter startIter, endIter;
345 gtk_text_buffer_get_start_iter(pm->buffer, &startIter);
346 gtk_text_buffer_get_end_iter(pm->buffer, &endIter);
347 gtk_text_buffer_delete(pm->buffer, &startIter, &endIter);
348 }
349 else if (command == "close")
350 {
351 WulforManager::get()->getMainWindow()->removeBookEntry_gui(pm);
352 }
353 else if (command == "favorite" || text == "fav")
354 {
355 typedef Func0<PrivateMessage> F0;
356 F0 *func = new F0(pm, &PrivateMessage::addFavoriteUser_client);
357 WulforManager::get()->dispatchClientFunc(func);
358 pm->addStatusMessage_gui(_("Added user to favorites list"));
359 }
360 else if (command == "getlist")
361 {
362 typedef Func0<PrivateMessage> F0;
363 F0 *func = new F0(pm, &PrivateMessage::getFileList_client);
364 WulforManager::get()->dispatchClientFunc(func);
365 }
366 else if (command == "grant")
367 {
368 typedef Func0<PrivateMessage> F0;
369 F0 *func = new F0(pm, &PrivateMessage::grantSlot_client);
370 WulforManager::get()->dispatchClientFunc(func);
371 pm->addStatusMessage_gui(_("Slot granted"));
372 }
373 else if (command == "help")
374 {
375 // TRANSLATORS: /commands aren't translatable. So leave them as they are in the help string
376 pm->addStatusMessage_gui(_("Available commands: /away <message>, /back, /clear, /close, /favorite, /getlist, /grant, /help"));
377 }
378 else
379 {
380 pm->addStatusMessage_gui(F_("Unknown command '%1%': Type /help for a list of available commands", % text));
381 }
382 }
383 else
384 {
385 typedef Func1<PrivateMessage, string> F1;
386 F1 *func = new F1(pm, &PrivateMessage::sendMessage_client, text);
387 WulforManager::get()->dispatchClientFunc(func);
388 }
389 }
390
onKeyPress_gui(GtkWidget * widget,GdkEventKey * event,gpointer data)391 gboolean PrivateMessage::onKeyPress_gui(GtkWidget *widget, GdkEventKey *event, gpointer data)
392 {
393 PrivateMessage *pm = (PrivateMessage *)data;
394 string text;
395 size_t index;
396
397 if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up)
398 {
399 index = pm->historyIndex - 1;
400 if (index >= 0 && index < pm->history.size())
401 {
402 text = pm->history[index];
403 pm->historyIndex = index;
404 gtk_entry_set_text(GTK_ENTRY(widget), text.c_str());
405 }
406 return TRUE;
407 }
408 else if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
409 {
410 index = pm->historyIndex + 1;
411 if (index >= 0 && index < pm->history.size())
412 {
413 text = pm->history[index];
414 pm->historyIndex = index;
415 gtk_entry_set_text(GTK_ENTRY(widget), text.c_str());
416 }
417 return TRUE;
418 }
419
420 return FALSE;
421 }
422
onLinkTagEvent_gui(GtkTextTag * tag,GObject * textView,GdkEvent * event,GtkTextIter * iter,gpointer data)423 gboolean PrivateMessage::onLinkTagEvent_gui(GtkTextTag *tag, GObject *textView, GdkEvent *event, GtkTextIter *iter, gpointer data)
424 {
425 PrivateMessage *pm = (PrivateMessage *)data;
426
427 if (event->type == GDK_BUTTON_PRESS)
428 {
429 pm->selectedURI = tag->name;
430
431 switch (event->button.button)
432 {
433 case 1:
434 onOpenLinkClicked_gui(NULL, data);
435 break;
436 case 3:
437 // Pop-up link context menu
438 gtk_widget_show_all(pm->getWidget("linkMenu"));
439 gtk_menu_popup(GTK_MENU(pm->getWidget("linkMenu")), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
440 break;
441 }
442 return TRUE;
443 }
444 return FALSE;
445 }
446
onHubTagEvent_gui(GtkTextTag * tag,GObject * textView,GdkEvent * event,GtkTextIter * iter,gpointer data)447 gboolean PrivateMessage::onHubTagEvent_gui(GtkTextTag *tag, GObject *textView, GdkEvent *event, GtkTextIter *iter, gpointer data)
448 {
449 PrivateMessage *pm = (PrivateMessage *)data;
450
451 if (event->type == GDK_BUTTON_PRESS)
452 {
453 pm->selectedURI = tag->name;
454
455 switch (event->button.button)
456 {
457 case 1:
458 onOpenHubClicked_gui(NULL, data);
459 break;
460 case 3:
461 // Popup hub context menu
462 gtk_widget_show_all(pm->getWidget("hubMenu"));
463 gtk_menu_popup(GTK_MENU(pm->getWidget("hubMenu")), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
464 break;
465 }
466 return TRUE;
467 }
468 return FALSE;
469 }
470
onMagnetTagEvent_gui(GtkTextTag * tag,GObject * textView,GdkEvent * event,GtkTextIter * iter,gpointer data)471 gboolean PrivateMessage::onMagnetTagEvent_gui(GtkTextTag *tag, GObject *textView, GdkEvent *event, GtkTextIter *iter, gpointer data)
472 {
473 PrivateMessage *pm = (PrivateMessage *)data;
474
475 if (event->type == GDK_BUTTON_PRESS)
476 {
477 pm->selectedURI = tag->name;
478
479 switch (event->button.button)
480 {
481 case 1:
482 // Search for magnet
483 onSearchMagnetClicked_gui(NULL, data);
484 break;
485 case 3:
486 // Popup magnet context menu
487 gtk_widget_show_all(pm->getWidget("magnetMenu"));
488 gtk_menu_popup(GTK_MENU(pm->getWidget("magnetMenu")), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
489 break;
490 }
491 return TRUE;
492 }
493 return FALSE;
494 }
495
onChatPointerMoved_gui(GtkWidget * widget,GdkEventMotion * event,gpointer data)496 gboolean PrivateMessage::onChatPointerMoved_gui(GtkWidget* widget, GdkEventMotion* event, gpointer data)
497 {
498 PrivateMessage *pm = (PrivateMessage *)data;
499
500 pm->updateCursor(widget);
501
502 return FALSE;
503 }
504
onChatVisibilityChanged_gui(GtkWidget * widget,GdkEventVisibility * event,gpointer data)505 gboolean PrivateMessage::onChatVisibilityChanged_gui(GtkWidget* widget, GdkEventVisibility* event, gpointer data)
506 {
507 PrivateMessage *pm = (PrivateMessage *)data;
508
509 pm->updateCursor(widget);
510
511 return FALSE;
512 }
513
onChatScroll_gui(GtkAdjustment * adjustment,gpointer data)514 void PrivateMessage::onChatScroll_gui(GtkAdjustment *adjustment, gpointer data)
515 {
516 PrivateMessage *pm = (PrivateMessage *)data;
517 gdouble value = gtk_adjustment_get_value(adjustment);
518 pm->scrollToBottom = value >= (adjustment->upper - adjustment->page_size);
519 }
520
onChatResize_gui(GtkAdjustment * adjustment,gpointer data)521 void PrivateMessage::onChatResize_gui(GtkAdjustment *adjustment, gpointer data)
522 {
523 PrivateMessage *pm = (PrivateMessage *)data;
524 gdouble value = gtk_adjustment_get_value(adjustment);
525
526 if (pm->scrollToBottom && value < (adjustment->upper - adjustment->page_size))
527 {
528 GtkTextIter iter;
529
530 gtk_text_buffer_get_end_iter(pm->buffer, &iter);
531 gtk_text_buffer_move_mark(pm->buffer, pm->mark, &iter);
532 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(pm->getWidget("text")), pm->mark, 0, FALSE, 0, 0);
533 }
534 }
535
onCopyURIClicked_gui(GtkMenuItem * item,gpointer data)536 void PrivateMessage::onCopyURIClicked_gui(GtkMenuItem *item, gpointer data)
537 {
538 PrivateMessage *pm = (PrivateMessage *)data;
539
540 gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), pm->selectedURI.c_str(), pm->selectedURI.length());
541 }
542
onOpenLinkClicked_gui(GtkMenuItem * item,gpointer data)543 void PrivateMessage::onOpenLinkClicked_gui(GtkMenuItem *item, gpointer data)
544 {
545 PrivateMessage *pm = (PrivateMessage *)data;
546
547 WulforUtil::openURI(pm->selectedURI);
548 }
549
onOpenHubClicked_gui(GtkMenuItem * item,gpointer data)550 void PrivateMessage::onOpenHubClicked_gui(GtkMenuItem *item, gpointer data)
551 {
552 PrivateMessage *pm = (PrivateMessage *)data;
553
554 WulforManager::get()->getMainWindow()->showHub_gui(pm->selectedURI);
555 }
556
onSearchMagnetClicked_gui(GtkMenuItem * item,gpointer data)557 void PrivateMessage::onSearchMagnetClicked_gui(GtkMenuItem *item, gpointer data)
558 {
559 PrivateMessage *pm = (PrivateMessage *)data;
560 string name;
561 int64_t size;
562 string tth;
563
564 if (WulforUtil::splitMagnet(pm->selectedURI, name, size, tth))
565 {
566 Search *s = WulforManager::get()->getMainWindow()->addSearch_gui();
567 s->putValue_gui(tth, 0, SearchManager::SIZE_DONTCARE, SearchManager::TYPE_TTH);
568 }
569 }
570
onMagnetPropertiesClicked_gui(GtkMenuItem * item,gpointer data)571 void PrivateMessage::onMagnetPropertiesClicked_gui(GtkMenuItem *item, gpointer data)
572 {
573 PrivateMessage *pm = (PrivateMessage *)data;
574
575 WulforManager::get()->getMainWindow()->openMagnetDialog_gui(pm->selectedURI);
576 }
577
sendMessage_client(std::string message)578 void PrivateMessage::sendMessage_client(std::string message)
579 {
580 if (user->isOnline())
581 {
582 // FIXME: WTF does the 3rd param (bool thirdPerson) do? A: Used for /me stuff
583 ClientManager::getInstance()->privateMessage(user, message, false, hubUrl);
584 }
585 else
586 {
587 typedef Func1<PrivateMessage, string> F1;
588 F1 *func = new F1(this, &PrivateMessage::addStatusMessage_gui, _("User went offline"));
589 WulforManager::get()->dispatchGuiFunc(func);
590 }
591 }
592
addFavoriteUser_client()593 void PrivateMessage::addFavoriteUser_client()
594 {
595 FavoriteManager::getInstance()->addFavoriteUser(user);
596 }
597
getFileList_client()598 void PrivateMessage::getFileList_client()
599 {
600 try
601 {
602 QueueManager::getInstance()->addList(user, hubUrl, QueueItem::FLAG_CLIENT_VIEW);
603 }
604 catch (const Exception& e)
605 {
606 typedef Func1<PrivateMessage, string> F1;
607 F1 *func = new F1(this, &PrivateMessage::addStatusMessage_gui, e.getError());
608 WulforManager::get()->dispatchGuiFunc(func);
609 }
610 }
611
grantSlot_client()612 void PrivateMessage::grantSlot_client()
613 {
614 UploadManager::getInstance()->reserveSlot(user, hubUrl);
615 }
616
on(ClientManagerListener::UserConnected,const UserPtr & aUser)617 void PrivateMessage::on(ClientManagerListener::UserConnected, const UserPtr& aUser) throw()
618 {
619 if (aUser == user)
620 {
621 string statusMessage;
622 string nicks = WulforUtil::getNicks(user); // TODO: Use aUser->hubHint on later cores
623 string hubs = WulforUtil::getHubNames(cid);
624
625 if (BOOLSETTING(SHOW_JOINS) || (BOOLSETTING(FAV_SHOW_JOINS) &&
626 FavoriteManager::getInstance()->isFavoriteUser(user)))
627 {
628 statusMessage = nicks + _(" has joined");
629 }
630
631 typedef Func4<PrivateMessage, string, string, bool, string> F4;
632 F4 *func = new F4(this, &PrivateMessage::updateUserStatus_gui, nicks, hubs, user->isOnline(), statusMessage);
633 WulforManager::get()->dispatchGuiFunc(func);
634 }
635 }
636
on(ClientManagerListener::UserDisconnected,const UserPtr & aUser)637 void PrivateMessage::on(ClientManagerListener::UserDisconnected, const UserPtr& aUser) throw()
638 {
639 if (aUser == user)
640 {
641 string statusMessage;
642 string nicks = WulforUtil::getNicks(user);
643 string hubs = WulforUtil::getHubNames(cid);
644
645 if (BOOLSETTING(SHOW_JOINS) || (BOOLSETTING(FAV_SHOW_JOINS) &&
646 FavoriteManager::getInstance()->isFavoriteUser(user)))
647 {
648 statusMessage = F_("%1% has quit", % nicks);
649 }
650
651 typedef Func4<PrivateMessage, string, string, bool, string> F4;
652 F4 *func = new F4(this, &PrivateMessage::updateUserStatus_gui, nicks, hubs, user->isOnline(), statusMessage);
653 WulforManager::get()->dispatchGuiFunc(func);
654 }
655 }
656
on(ClientManagerListener::UserUpdated,const OnlineUser & aUser)657 void PrivateMessage::on(ClientManagerListener::UserUpdated, const OnlineUser& aUser) throw()
658 {
659 if (aUser.getUser() == user)
660 {
661 string nicks = WulforUtil::getNicks(user);
662 string hubs = WulforUtil::getHubNames(cid);
663
664 typedef Func4<PrivateMessage, string, string, bool, string> F4;
665 F4 *func = new F4(this, &PrivateMessage::updateUserStatus_gui, nicks, hubs, user->isOnline(), "");
666 WulforManager::get()->dispatchGuiFunc(func);
667 }
668 }
669
670