1 // ========================================================================
2 // gnubiff -- a mail notification program
3 // Copyright (c) 2000-2009 Nicolas Rougier, 2004-2009 Robert Sowada
4 //
5 // This program is free software: you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation, either version 3 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 // ========================================================================
18 //
19 // File          : $RCSfile: ui-applet.cc,v $
20 // Revision      : $Revision: 1.39.2.4 $
21 // Revision date : $Date: 2009/04/05 16:08:05 $
22 // Author(s)     : Nicolas Rougier, Robert Sowada
23 // Short         :
24 //
25 // This file is part of gnubiff.
26 //
27 // -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
28 // ========================================================================
29 
30 #include <sstream>
31 #include <iomanip>
32 #include <cstdio>
33 #include <string>
34 #include <glib.h>
35 
36 #include "mailbox.h"
37 #include "support.h"
38 #include "ui-applet.h"
39 
40 /**
41  *  Constructor.
42  *
43  *  @param  biff  Pointer to the biff object of the current gnubiff session.
44  */
Applet(Biff * biff)45 Applet::Applet (Biff *biff)
46 {
47 	biff_ = biff;
48 	update_mutex_ = g_mutex_new ();
49 }
50 
51 /// Destructor
~Applet(void)52 Applet::~Applet (void)
53 {
54 	g_mutex_lock (update_mutex_);
55 	g_mutex_unlock (update_mutex_);
56 	g_mutex_free (update_mutex_);
57 }
58 
59 /**
60  *  Start the applet.
61  *
62  *  @param  showpref  If true and supported by the frontend the preferences
63  *                    dialog is shown before monitoring starts (the default is
64  *                    false).
65  */
66 void
start(gboolean showpref)67 Applet::start (gboolean showpref)
68 {
69 	if (!showpref)
70 		if (biff_->value_uint ("check_mode") == AUTOMATIC_CHECK)
71 			biff_->start_monitoring (3);
72 }
73 
74 /**
75  *  Update the applet status. If new messages are present the new
76  *  mail command is executed.
77  *
78  *  @param  init  True if called when initializing gnubiff (the default is
79  *                false)
80  *  @return       True if new messages are present
81  */
82 gboolean
update(gboolean init)83 Applet::update (gboolean init)
84 {
85 #ifdef DEBUG
86 	g_message ("Applet update");
87 #endif
88 
89 	// Check if there is new mail
90 	guint unread = 0;
91 	gboolean newmail = biff_->get_number_of_unread_messages (unread);
92 
93 	// New mail command
94 	if ((newmail == true) && (unread > 0))
95 		execute_command ("newmail_command", "use_newmail_command");
96 
97 	// Messages have been displayed now
98 	biff_->messages_displayed ();
99 
100 	return newmail;
101 }
102 
103 /**
104  *  Mark all messages from all mailboxes as read and update the applet
105  *  status.  The config file is saved with the information which
106  *  messages have been read.
107  */
108 void
mark_messages_as_read(void)109 Applet::mark_messages_as_read (void)
110 {
111 	// Mark messages as read
112 	biff_->mark_messages_as_read ();
113 
114 	// Save config file (especially the seen messages)
115 	biff_->save ();
116 
117 	// Update the applet status
118 	update ();
119 }
120 
121 /**
122  *  Execute a shell command that is stored in the biff string option
123  *  {\em option_command} if the biff boolean option {\em option_use_command}
124  *  is true.
125  *
126  *  @param option_command     Name of the biff string option that stores the
127  *                            command.
128  *  @param option_use_command Name of the biff boolean option that indicates
129  *                            whether the command should be executed or not.
130  *                            If this string is empty the command will be
131  *                            executed (the default is the empty string).
132  */
133 void
execute_command(std::string option_command,std::string option_use_command)134 Applet::execute_command (std::string option_command,
135 						 std::string option_use_command)
136 {
137 	// Shall the command be executed?
138 	if ((!option_use_command.empty()) &&
139 		(!(biff_->value_bool (option_use_command))))
140 		return;
141 	// Execute the command (if there is one).
142 	std::string command = biff_->value_string (option_command);
143     if (!command.empty ()) {
144 		command += " &";
145 		int result = system (command.c_str ());
146 		if (result == -1)
147 			g_warning ("Cannot execute command \"%s\".", command.c_str());
148 	}
149 }
150 
151 /**
152  *  Get the number of unread messages in all mailboxes as a string.
153  *
154  *  @return    Number of unread messages as a string.
155  */
156 std::string
get_number_of_unread_messages(void)157 Applet::get_number_of_unread_messages (void)
158 {
159 	std::stringstream smax, text_zero, text_num;
160 	std::string text;
161 
162 	// Get number of unread messages
163 	guint unread;
164 	biff_->get_number_of_unread_messages (unread);
165 
166 	// Zero padded number of unread messages
167 	smax << biff_->value_uint ("max_mail");
168 	text_zero << std::setfill('0') << std::setw (smax.str().size()) << unread;
169 
170 	// Number of unread messages
171 	text_num << unread;
172 
173 	// Use the correct user supplied message to create the text
174 	const std::string chars = "dD";
175 	std::vector<std::string> vec(2);
176 	vec[0] = text_zero.str (); // 'd'
177 	vec[1] = text_num.str ();  // 'D'
178 	if (unread == 0)
179 		text = substitute (biff_->value_string ("nomail_text"), chars, vec);
180 	else if (unread < biff_->value_uint ("max_mail"))
181 		text = substitute (biff_->value_string ("newmail_text"), chars, vec);
182 	else {
183 		vec[0] = std::string (std::string(smax.str().size(), '+'));
184 		vec[1] = "+";
185 		text = substitute (biff_->value_string ("newmail_text"), chars, vec);
186 	}
187 
188 	return text;
189 }
190 
191 /**
192  *  Returns a string with a overview of the statuses of all
193  *  mailboxes. Each mailbox's status is presented on a separate line,
194  *  if there is no problem the number of unread messages is
195  *  given. This text is suitable for displaying as a tooltip.
196  *
197  *  @return    String that contains the mailboxes' statuses.
198  */
199 std::string
get_mailbox_status_text(void)200 Applet::get_mailbox_status_text (void)
201 {
202 	// Get max collected mail number in a stringstream
203 	//  just to have a default string size.
204 	std::stringstream smax;
205 	smax << biff_->value_uint ("max_mail");
206 
207 	std::string tooltip;
208 	for (unsigned int i=0; i < biff_->get_number_of_mailboxes (); i++) {
209 		if (i > 0)
210 			tooltip += "\n";
211 		// Mailbox's name
212 		tooltip += biff_->mailbox(i)->name();
213 		tooltip += ": ";
214 
215 		// No protocol?
216 		if (biff_->mailbox(i)->protocol() == PROTOCOL_NONE) {
217 			tooltip += _(" unknown");
218 			continue;
219 		}
220 		// Error?
221 		if (biff_->mailbox(i)->status() == MAILBOX_ERROR) {
222 			tooltip += _(" error");
223 			continue;
224 		}
225 		// Put number of unread messages in the current mailbox into a string
226 		guint unread = biff_->mailbox(i)->unreads();
227 		std::stringstream s;
228 		s << std::setfill('0') << std::setw (smax.str().size()) << unread;
229 		// Checking mailbox?
230 		if (biff_->mailbox(i)->status() == MAILBOX_CHECK) {
231 			tooltip += "(" + s.str() + ")" + _(" checking...");
232 			continue;
233 		}
234 		// More unread messages in mailbox than got by gnubiff?
235 		if (unread >= biff_->value_uint ("max_mail")) {
236 			tooltip += std::string(smax.str().size(), '+');
237 			continue;
238 		}
239 		// Just the number of unread messages
240 		tooltip += s.str();
241 	}
242 	return tooltip;
243 }
244 
245 /**
246  *  The return value indicates whether the applet wants the mailboxes to be
247  *  monitored.
248  *
249  *  @return true, if the applet thinks monitoring the mailboxes is okay
250  */
251 gboolean
can_monitor_mailboxes(void)252 Applet::can_monitor_mailboxes (void)
253 {
254 	return true;
255 }
256 
257 /**
258  *  Return an AppletGUI pointer of the applet or NULL if the applet is no
259  *  AppletGUI applet.
260  *
261  *  @return see description above
262  */
263 class AppletGUI *
appletgui_ptr(void)264 Applet::appletgui_ptr (void)
265 {
266 	return NULL;
267 }
268