Use pkg-config to find ncursesw
[centerim5.git] / src / Notify.cpp
blobfa3390e9111f17d6074e86a30e584c402f81f6be
1 // Copyright (C) 2010-2015 Petr Pavlu <setup@dagobah.cz>
2 //
3 // This file is part of CenterIM.
4 //
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.
9 //
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 "Notify.h"
20 #include "Log.h"
22 #include "gettext.h"
23 #include <cstring>
25 Notify *Notify::my_instance_ = nullptr;
27 Notify *Notify::instance()
29 return my_instance_;
32 Notify::UserInfoDialog::UserInfoDialog(const char *title) : SplitDialog(title)
34 setColorScheme(CenterIM::SCHEME_GENERALWINDOW);
36 treeview_ = new CppConsUI::TreeView(AUTOSIZE, AUTOSIZE);
37 setContainer(*treeview_);
39 buttons_->appendItem(
40 _("Done"), sigc::hide(sigc::mem_fun(this, &UserInfoDialog::close)));
42 onScreenResized();
45 void Notify::UserInfoDialog::onScreenResized()
47 moveResizeRect(CENTERIM->getScreenArea(CenterIM::CHAT_AREA));
50 void Notify::UserInfoDialog::update(
51 PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info)
53 treeview_->clear();
54 CppConsUI::TreeView::NodeReference parent;
55 CppConsUI::Button *button;
57 // Local information.
58 PurpleAccount *account = purple_connection_get_account(gc);
59 PurpleBuddy *buddy = purple_find_buddy(account, who);
60 if (buddy != nullptr) {
61 // Note that we should always be able to find the specified buddy, unless
62 // something goes very wrong.
63 button =
64 new CppConsUI::TreeView::ToggleCollapseButton(_("Local information"));
65 parent = treeview_->appendNode(treeview_->getRootNode(), *button);
67 button = new CppConsUI::Button(
68 CppConsUI::Button::FLAG_VALUE, _("Alias"), purple_buddy_get_alias(buddy));
69 treeview_->appendNode(parent, *button);
71 time_t saved_time;
72 struct tm local_time;
73 const char *formatted_time;
75 // Last seen.
76 if (PURPLE_BUDDY_IS_ONLINE(buddy))
77 formatted_time = _("Now");
78 else {
79 saved_time = static_cast<time_t>(
80 purple_blist_node_get_int(PURPLE_BLIST_NODE(buddy), "last_seen"));
81 if (saved_time != 0 && localtime_r(&saved_time, &local_time) != nullptr)
82 formatted_time = purple_date_format_long(&local_time);
83 else
84 formatted_time = _("Unknown");
86 button = new CppConsUI::Button(
87 CppConsUI::Button::FLAG_VALUE, _("Last seen"), formatted_time);
88 treeview_->appendNode(parent, *button);
90 // Last activity.
91 saved_time = static_cast<time_t>(
92 purple_blist_node_get_int(PURPLE_BLIST_NODE(buddy), "last_activity"));
93 if (saved_time != 0 && localtime_r(&saved_time, &local_time) != nullptr)
94 formatted_time = purple_date_format_long(&local_time);
95 else
96 formatted_time = _("Unknown");
97 button = new CppConsUI::Button(
98 CppConsUI::Button::FLAG_VALUE, _("Last activity"), formatted_time);
99 treeview_->appendNode(parent, *button);
102 // Remote information.
103 button =
104 new CppConsUI::TreeView::ToggleCollapseButton(_("Remote information"));
105 parent = treeview_->appendNode(treeview_->getRootNode(), *button);
106 CppConsUI::TreeView::NodeReference subparent = parent;
107 for (GList *i = purple_notify_user_info_get_entries(user_info); i != nullptr;
108 i = i->next) {
109 PurpleNotifyUserInfoEntry *entry =
110 reinterpret_cast<PurpleNotifyUserInfoEntry *>(i->data);
111 PurpleNotifyUserInfoEntryType type =
112 purple_notify_user_info_entry_get_type(entry);
114 const char *label = purple_notify_user_info_entry_get_label(entry);
115 if (label == nullptr)
116 continue;
117 const char *value = purple_notify_user_info_entry_get_value(entry);
118 char *nohtml = purple_markup_strip_html(value);
119 switch (type) {
120 case PURPLE_NOTIFY_USER_INFO_ENTRY_PAIR:
121 button = new CppConsUI::Button(
122 nohtml ? CppConsUI::Button::FLAG_VALUE : 0, label, nohtml);
123 treeview_->appendNode(subparent, *button);
124 break;
125 case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK:
126 // Ignore section breaks.
127 break;
128 case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER:
129 button = new CppConsUI::TreeView::ToggleCollapseButton(label);
130 subparent = treeview_->appendNode(parent, *button);
131 break;
132 default:
133 LOG->error(_("Unhandled userinfo entry type '%d'."), type);
134 break;
136 g_free(nohtml);
139 treeview_->grabFocus();
142 Notify::Notify()
144 std::memset(&centerim_notify_ui_ops_, 0, sizeof(centerim_notify_ui_ops_));
146 // Set the purple notify callbacks.
147 centerim_notify_ui_ops_.notify_message = notify_message_;
148 // centerim_notify_ui_ops_.notify_email = notify_email_;
149 // centerim_notify_ui_ops_.notify_emails = notify_emails_;
150 // centerim_notify_ui_ops_.notify_formatted = notify_formatted_;
151 // centerim_notify_ui_ops_.notify_searchresults = notify_searchresults_;
152 // centerim_notify_ui_ops_.notify_searchresults_new_rows =
153 // notify_searchresults_new_rows_;
154 centerim_notify_ui_ops_.notify_userinfo = notify_userinfo_;
155 // centerim_notify_ui_ops_.notify_uri = notify_uri_;
156 centerim_notify_ui_ops_.close_notify = close_notify_;
157 purple_notify_set_ui_ops(&centerim_notify_ui_ops_);
160 Notify::~Notify()
162 purple_notify_set_ui_ops(nullptr);
165 void Notify::init()
167 g_assert(my_instance_ == nullptr);
169 my_instance_ = new Notify;
172 void Notify::finalize()
174 g_assert(my_instance_ != nullptr);
176 delete my_instance_;
177 my_instance_ = nullptr;
180 void Notify::onDialogClose(CppConsUI::Window &activator, PurpleNotifyType type)
182 CppConsUI::AbstractDialog *dialog =
183 dynamic_cast<CppConsUI::AbstractDialog *>(&activator);
184 g_assert(dialog != nullptr);
186 if (notifications_.find(dialog) == notifications_.end())
187 return;
189 notifications_.erase(dialog);
190 purple_notify_close(type, dialog);
193 void Notify::onUserInfoDialogClose(CppConsUI::Window & /*activator*/, User user)
195 // The userinfo dialog is gone.
196 user_infos_.erase(user);
199 void *Notify::notify_message(PurpleNotifyMsgType /*type*/, const char *title,
200 const char *primary, const char *secondary)
202 char *text = g_strdup_printf("%s\n\n%s", primary, secondary);
203 auto dialog = new CppConsUI::MessageDialog(title, text);
204 g_free(text);
205 dialog->signal_close.connect(sigc::bind(
206 sigc::mem_fun(this, &Notify::onDialogClose), PURPLE_NOTIFY_MESSAGE));
207 dialog->show();
209 notifications_.insert(dialog);
210 return dialog;
213 void *Notify::notify_userinfo(
214 PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info)
216 User user(purple_connection_get_account(gc), who);
217 UserInfos::iterator i = user_infos_.find(user);
218 UserInfoDialog *dialog;
219 if (i == user_infos_.end()) {
220 // Create a new dialog to display this user info.
221 char *title = g_strdup_printf(_("User information for %s"), who);
222 dialog = new UserInfoDialog(title);
223 g_free(title);
225 dialog->signal_close.connect(
226 sigc::bind(sigc::mem_fun(this, &Notify::onUserInfoDialogClose), user));
227 dialog->signal_close.connect(sigc::bind(
228 sigc::mem_fun(this, &Notify::onDialogClose), PURPLE_NOTIFY_USERINFO));
229 dialog->show();
231 notifications_.insert(dialog);
232 user_infos_[user] = dialog;
234 else {
235 // Update already opened dialog.
236 dialog = i->second;
239 dialog->update(gc, who, user_info);
240 return dialog;
243 void Notify::close_notify(PurpleNotifyType type, void *ui_handle)
245 // Only some notifications are currently supported.
246 g_assert(type == PURPLE_NOTIFY_MESSAGE || type == PURPLE_NOTIFY_USERINFO);
248 CppConsUI::AbstractDialog *dialog =
249 reinterpret_cast<CppConsUI::AbstractDialog *>(ui_handle);
250 if (notifications_.find(dialog) == notifications_.end())
251 return;
253 notifications_.erase(dialog);
254 // Close the notification dialog if one is still opened.
255 dialog->close();
258 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: