1 //=============================================================================
2 //
3 //   File : libkvinotifier.cpp
4 //   Creation date : Tue Jul 7 2004 20:21:12 CEST by Szymon Stefanek
5 //
6 //   This file is part of the KVIrc IRC client distribution
7 //   Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net)
8 //   Copyright (C) 2005-2008 Iacopo Palazzi < iakko(at)siena(dot)linux(dot)it >
9 //
10 //   This program is FREE software. You can redistribute it and/or
11 //   modify it under the terms of the GNU General Public License
12 //   as published by the Free Software Foundation; either version 2
13 //   of the License, or (at your option) any later version.
14 //
15 //   This program is distributed in the HOPE that it will be USEFUL,
16 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
17 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 //   See the GNU General Public License for more details.
19 //
20 //   You should have received a copy of the GNU General Public License
21 //   along with this program. If not, write to the Free Software Foundation,
22 //   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 //
24 //=============================================================================
25 
26 #include "NotifierWindow.h"
27 #include "NotifierMessage.h"
28 
29 #include "KviModule.h"
30 #include "KviKvsVariant.h"
31 #include "KviApplication.h"
32 #include "KviMainWindow.h"
33 #include "KviWindow.h"
34 #include "KviLocale.h"
35 #include "KviIconManager.h"
36 #include "KviTimeUtils.h"
37 #include "KviOptions.h"
38 
39 NotifierWindow * g_pNotifierWindow = nullptr;
40 kvi_time_t g_tNotifierDisabledUntil = 0;
41 
42 /*
43 	@doc: notifier.message
44 	@type:
45 		command
46 	@title:
47 		notifier.message
48 	@short:
49 		Adds a message to the notifier window
50 	@syntax:
51 		notifier.message [-q|quiet] [-n|noanim] [-w[=<window_id:string>]!] [-i=<image_id:string>] [-t=<timeout:integer>] <messag:string>
52 	@description:
53 		Adds a message to the notifier window.
54 		The notifier window is shown (if not already visible)
55 		unless the -q switch is present.
56 		The new message becomes the current message of the notifier
57 		unless the user is already typing in the input window
58 		and the typed message would be directed to a different window.
59 		In that case the message is appended at the end of the
60 		message queue and the user will be able to scroll to it
61 		by using the proper notifier buttons.[br]
62 		The &lt;message&gt; text can contain simple HTML tags: basically you are
63 		allowed to use &lt;b&gt; and &lt;i&gt;. The usage of other
64 		tags is possible but is discouraged since it tends to
65 		mess up the message display. In particular you should avoid
66 		any color and/or font specification since the notifier is
67 		skinnable and you don't know which color will result in a visible text.
68 		[b]Please note that the user can forcibly disable the notifier
69 		for a limited period of time (a sort of [i]don't bug me[/i] option).[/b]
70 	@switches:
71 		!sw: -n | --noanim
72 		Do not animate
73 		!sw: -w | --windowid
74 		Causes the message gets attached to the specified window and
75 		the user is able to type commands in that window after
76 		showing up the notifier input. If the "=&lt;window_id&gt;" part
77 		is omitted then the current window is used.[br]
78 		!sw: -i | --icon
79 		If the -i=&lt;image_id&gt; switch is present then the
80 		message has the specified image displayed.
81 		See the [doc:image_id]documentation on the image identifier[/doc]
82 		for more information about the image_id parameter.[br]
83 		!sw: -q | --quiet
84 		If you use -q then you must explicitly call [cmd]notifier.show[/cmd] to
85 		show the notifier. If the -n switch is present then
86 		the show action will not be animated (the notifier
87 		will be shown immediately instead of fading in).
88 		Obviously -n has no meaning if -q is used.[br]
89 		!sw: -t | --timeout
90 		Set the message lifetime to <timeout>
91 		Obviously this option has no meaning if the window is not going to be shown.
92 		The timeout may be overridden by new messages but only in the future.
93 		If the timeout expires and is not overridden by any new message
94 		then the window will be automatically hidden.
95 		A zero timeout disables auto-hiding.
96 	@seealso:
97 		[cmd]notifier.show[/cmd] [cmd]notifier.hide[/cmd] [fnc]$notifier.isEnabled[/fnc]()
98 	@examples:
99 		[example]
100 			notifier.message Hello world!
101 			[cmd]notifier.hide[/cmd]
102 			notifier.message -q This is a hidden message!
103 			notifier.message -q -i=14 This is a second hidden message with an icon
104 			[cmd]notifier.show[/cmd]
105 			notifier.message -w This message has the current window associated
106 			notifier.message -w=[fnc]$window[/fnc] This is equivalent to the above
107 			notifier.message &lt;b&gt;Bold text&lt;/b&gt; and normal text
108 			[cmd]notifier.hide[/cmd]
109 			notifier.message -t=10 This message will be shown only for 10 seconds
110 		[/example]
111 */
112 
notifier_kvs_cmd_message(KviKvsModuleCommandCall * c)113 static bool notifier_kvs_cmd_message(KviKvsModuleCommandCall * c)
114 {
115 	QString szMessage;
116 	KVSM_PARAMETERS_BEGIN(c)
117 	KVSM_PARAMETER("message", KVS_PT_STRING, 0, szMessage)
118 	KVSM_PARAMETERS_END(c)
119 
120 	if(!g_pNotifierWindow)
121 		g_pNotifierWindow = new NotifierWindow();
122 
123 	QString szIco = "";
124 	QString szWnd = "";
125 
126 	KviWindow * pWnd = c->window();
127 
128 	if(c->hasSwitch('w', "window_id"))
129 	{
130 		c->switches()->getAsStringIfExisting('w', "window_id", szWnd);
131 		if(!szWnd.isEmpty())
132 		{
133 			pWnd = g_pApp->findWindow(szWnd);
134 			if(!pWnd)
135 				c->warning(__tr2qs_ctx("The specified window does not exist", "notifier"));
136 		}
137 	}
138 	c->switches()->getAsStringIfExisting('i', "icon", szIco);
139 	kvs_int_t uTime = KVI_OPTION_UINT(KviOption_uintNotifierAutoHideTime);
140 	if(c->hasSwitch('t', "timeout"))
141 	{
142 		KviKvsVariant * pTime = c->getSwitch('t', "timeout");
143 		if(pTime)
144 		{
145 			bool bOk = pTime->asInteger(uTime);
146 			if(!bOk)
147 			{
148 				uTime = 0;
149 				c->warning(__tr2qs_ctx("The specified timeout is not valid, assuming 0", "notifier"));
150 			}
151 		}
152 		else
153 		{
154 			c->warning(__tr2qs_ctx("The -t switch expects a timeout in seconds", "notifier"));
155 		}
156 	}
157 
158 	g_pNotifierWindow->addMessage(pWnd, szIco, szMessage, uTime);
159 
160 	if(!c->hasSwitch('q', "quiet"))
161 		g_pNotifierWindow->doShow(!(c->hasSwitch('n', "new")));
162 	return true;
163 }
164 
165 /*
166 	@doc: notifier.hide
167 	@type:
168 		command
169 	@title:
170 		notifier.hide
171 	@short:
172 		Hides the notifier window
173 	@syntax:
174 		notifier.hide [-n|--noanim]
175 	@switches:
176 		!sw: -n
177 		Causes the hide operation is not animated.
178 	@description:
179 		Hide the notifier window
180 		[b]Please note that the user can forcibly disable the notifier
181 		for a limited period of time (a sort of [i]don't bug me[/i] option).[/b]
182 	@seealso:
183 		[cmd]notifier.show[/cmd] [cmd]notifier.message[/cmd] [fnc]$notifier.isEnabled[/fnc]
184 */
185 
notifier_kvs_cmd_hide(KviKvsModuleCommandCall * c)186 static bool notifier_kvs_cmd_hide(KviKvsModuleCommandCall * c)
187 {
188 	if(g_pNotifierWindow)
189 		g_pNotifierWindow->doHide(!(c->hasSwitch('n', "notanimated")));
190 	return true;
191 }
192 
193 /*
194 	@doc: notifier.show
195 	@type:
196 		command
197 	@title:
198 		notifier.show
199 	@short:
200 		Shows the notifier window
201 	@syntax:
202 		notifier.show [-n|--noanim]
203 	@switches:
204 		!sw: -n
205 		Disables the animation
206 	@description:
207 		Shows the notifier window if it is not already visible
208 		If the -n switch is present then the show operation is
209 		not animated.[br]
210 		The notifier is shown [b]only[/b] if it contains some messages.
211 		[b]Please note that the user can forcibly disable the notifier
212 		for a limited period of time (a sort of [i]don't bug me[/i] option).[/b]
213 	@seealso:
214 		[cmd]notifier.hide[/cmd] [cmd]notifier.message[/cmd] [fnc]$notifier.isEnabled[/fnc]
215 */
216 
notifier_kvs_cmd_show(KviKvsModuleCommandCall * c)217 static bool notifier_kvs_cmd_show(KviKvsModuleCommandCall * c)
218 {
219 	if(!g_pNotifierWindow)
220 		return true;
221 	if(!g_pNotifierWindow->countTabs())
222 		return true;
223 
224 	g_pNotifierWindow->setDisableHideOnMainWindowGotAttention(true);
225 	g_pNotifierWindow->doShow(!(c->hasSwitch('n', "noanim")));
226 
227 	return true;
228 }
229 
230 /*
231 	@doc: notifier.isEnabled
232 	@type:
233 		function
234 	@title:
235 		$notifier.isEnabled
236 	@short:
237 		Returns [b]1[/b] if the notifier window is enabled
238 	@syntax:
239 		<boolean> $notifier.isEnabled
240 	@description:
241 		Returns [b]1[/b] if the notifier window is enabled and [b]0[/b] otherwise.
242 		The user can forcibly disable the notifier as a sort of [i]don't bug me[/i]
243 		feature for a limited period of time. When the notifier
244 		is disabled the messages sent to it will not be shown.[br]
245 		The only method that you (the scripter) can use to forcibly
246 		re-enable the notifier is to unload the module and
247 		reload it, but [b]don't do it[/b] :)[br]
248 		There is also a global option that allows forcibly disabling
249 		the notifier forever, this option could be overridden with [cmd]option[/cmd]
250 		instead, but again [b]don't do it[/b] :)[br]
251 
252 */
253 
notifier_kvs_fnc_isEnabled(KviKvsModuleFunctionCall * c)254 static bool notifier_kvs_fnc_isEnabled(KviKvsModuleFunctionCall * c)
255 {
256 	bool bCheck = false;
257 	if(KVI_OPTION_BOOL(KviOption_boolEnableNotifier))
258 		bCheck = g_tNotifierDisabledUntil < kvi_unixTime();
259 	c->returnValue()->setBoolean(bCheck);
260 	return true;
261 }
262 
notifier_module_init(KviModule * m)263 static bool notifier_module_init(KviModule * m)
264 {
265 	KVSM_REGISTER_SIMPLE_COMMAND(m, "message", notifier_kvs_cmd_message);
266 	KVSM_REGISTER_SIMPLE_COMMAND(m, "show", notifier_kvs_cmd_show);
267 	KVSM_REGISTER_SIMPLE_COMMAND(m, "hide", notifier_kvs_cmd_hide);
268 	KVSM_REGISTER_FUNCTION(m, "isEnabled", notifier_kvs_fnc_isEnabled);
269 
270 	return true;
271 }
272 
notifier_module_cleanup(KviModule *)273 static bool notifier_module_cleanup(KviModule *)
274 {
275 	if(g_pNotifierWindow)
276 	{
277 		delete g_pNotifierWindow;
278 		g_pNotifierWindow = nullptr;
279 	}
280 	return true;
281 }
282 
notifier_module_can_unload(KviModule *)283 static bool notifier_module_can_unload(KviModule *)
284 {
285 	return (!g_pNotifierWindow);
286 }
287 
notifier_module_ctrl(KviModule *,const char * pcOperation,void * pParam)288 static bool notifier_module_ctrl(KviModule *, const char * pcOperation, void * pParam)
289 {
290 	if(!kvi_strEqualCI("notifier::message", pcOperation))
291 		return false;
292 
293 	KviNotifierMessageParam * p = (KviNotifierMessageParam *)pParam;
294 	if(!p)
295 		return false;
296 
297 	if(!g_pNotifierWindow)
298 		g_pNotifierWindow = new NotifierWindow();
299 
300 	g_pNotifierWindow->addMessage(p->pWindow, p->szIcon, p->szMessage, p->uMessageLifetime);
301 	g_pNotifierWindow->doShow(KVI_OPTION_BOOL(KviOption_boolNotifierFading) ? true : false);
302 
303 	return true;
304 }
305 
306 KVIRC_MODULE(
307     "Notifier",
308     "4.0.0",
309     "Copyright (C) 2005 Iacopo Palazzi (iakko at siena dot linux dot it)\n"
310     "              2010 Elvio Basello (hell at hellvis69 dot netsons dot org)",
311     "KVIrc Client - Taskbar Notifier",
312     notifier_module_init,
313     notifier_module_can_unload,
314     notifier_module_ctrl,
315     notifier_module_cleanup,
316     "notifier")
317