xref: /haiku/src/add-ons/tracker/zipomatic/ZipOMatic.cpp (revision 7457ccb4b2f4786525d3b7bda42598487d57ab7d)
1 /*
2  * Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Jonas Sundström, jonas@kirilla.com
7  */
8 
9 
10 #include "ZipOMatic.h"
11 
12 #include <Alert.h>
13 #include <Roster.h>
14 #include <StringFormat.h>
15 #include <TrackerAddOnAppLaunch.h>
16 
17 #include "ZipOMaticMisc.h"
18 #include "ZipOMaticWindow.h"
19 
20 
21 #undef B_TRANSLATION_CONTEXT
22 #define B_TRANSLATION_CONTEXT "file:ZipOMatic.cpp"
23 
24 
25 int
main()26 main()
27 {
28 	ZipOMatic app;
29 	app.Run();
30 
31 	return 0;
32 }
33 
34 
ZipOMatic()35 ZipOMatic::ZipOMatic()
36 	:
37 	BApplication(ZIPOMATIC_APP_SIG),
38 	fGotRefs(false),
39 	fInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, this))
40 {
41 }
42 
43 
~ZipOMatic()44 ZipOMatic::~ZipOMatic()
45 {
46 }
47 
48 
49 void
RefsReceived(BMessage * message)50 ZipOMatic::RefsReceived(BMessage* message)
51 {
52 	entry_ref ref;
53 	if (message->FindRef("refs", &ref) == B_OK) {
54 		_UseExistingOrCreateNewWindow(message);
55 		fGotRefs = true;
56 	} else if (!IsLaunching()) {
57 		PostMessage(B_SILENT_RELAUNCH);
58 	}
59 }
60 
61 
62 void
ReadyToRun()63 ZipOMatic::ReadyToRun()
64 {
65 	if (!fGotRefs)
66 		_UseExistingOrCreateNewWindow();
67 }
68 
69 
70 void
MessageReceived(BMessage * message)71 ZipOMatic::MessageReceived(BMessage* message)
72 {
73 	switch (message->what) {
74 		case ZIPPO_WINDOW_QUIT:
75 		{
76 			snooze(200000);
77 			if (CountWindows() == 0)
78 				Quit();
79 			break;
80 		}
81 		case B_SILENT_RELAUNCH:
82 			_SilentRelaunch();
83 			break;
84 
85 		case ZIPPO_QUIT_OR_CONTINUE:
86 		{
87 			int32 button;
88 			if (message->FindInt32("which", &button) == B_OK) {
89 				if (button == 0) {
90 					_StopZipping();
91 				} else {
92 					if (CountWindows() == 0)
93 						Quit();
94 				}
95 			}
96 			break;
97 		}
98 
99 		default:
100 			BApplication::MessageReceived(message);
101 			break;
102 	}
103 }
104 
105 
106 bool
QuitRequested(void)107 ZipOMatic::QuitRequested(void)
108 {
109 	if (CountWindows() <= 0)
110 		return true;
111 
112 	BWindow* window;
113 	ZippoWindow* zippo;
114 	ZippoWindow* lastFoundZippo = NULL;
115 	int32 zippoCount = 0;
116 
117 	for (int32 i = 0;; i++) {
118 		window = WindowAt(i);
119 		if (window == NULL)
120 			break;
121 
122 		zippo = dynamic_cast<ZippoWindow*>(window);
123 		if (zippo == NULL)
124 			continue;
125 
126 		lastFoundZippo = zippo;
127 
128 		if (zippo->Lock()) {
129 			if (zippo->IsZipping())
130 				zippoCount++;
131 			else
132 				zippo->PostMessage(B_QUIT_REQUESTED);
133 
134 			zippo->Unlock();
135 		}
136 	}
137 
138 	if (zippoCount == 1) {
139 		// This is likely the most frequent case - a single zipper.
140 		// We post a message to the window so it can put up its own
141 		// BAlert instead of the app-wide BAlert. This avoids making
142 		// a difference between having pressed Commmand-W or Command-Q.
143 		// Closing or quitting, it doesn't matter for a single window.
144 
145 		if (lastFoundZippo->Lock()) {
146 			lastFoundZippo->Activate();
147 			lastFoundZippo->PostMessage(B_QUIT_REQUESTED);
148 			lastFoundZippo->Unlock();
149 		}
150 		return false;
151 	}
152 
153 	if (zippoCount > 0) {
154 		// The multi-zipper case differs from the single-zipper case
155 		// in that zippers are not paused while the BAlert is up.
156 
157 		static BStringFormat format(
158 			B_TRANSLATE("You have {0, plural, one{# Zip-O-Matic} "
159 				"other{# Zip-O-Matics}} running.\n\n"));
160 
161 		BString question;
162 
163 		format.Format(question, zippoCount);
164 
165 		question << B_TRANSLATE("Do you want to stop them?");
166 
167 		BAlert* alert = new BAlert(NULL, question.String(),
168 			B_TRANSLATE("Stop them"), B_TRANSLATE("Let them continue"), NULL,
169 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
170 		alert->Go(fInvoker);
171 		alert->Activate();
172 			// BAlert, being modal, does not show on the current workspace
173 			// if the application has no window there. Activate() triggers
174 			// a switch to a workspace where it does have a window.
175 
176 			// TODO: See if AS_ACTIVATE_WINDOW should be handled differently
177 			// in src/servers/app/Desktop.cpp Desktop::ActivateWindow()
178 			// or if maybe BAlert should (and does not?) activate itself.
179 
180 		return false;
181 	}
182 
183 	if (CountWindows() <= 0)
184 		return true;
185 
186 	return false;
187 }
188 
189 
190 void
_SilentRelaunch()191 ZipOMatic::_SilentRelaunch()
192 {
193 	_UseExistingOrCreateNewWindow();
194 }
195 
196 
197 void
_UseExistingOrCreateNewWindow(BMessage * message)198 ZipOMatic::_UseExistingOrCreateNewWindow(BMessage* message)
199 {
200 	int32 windowCount = 0;
201 	BWindow* bWindow;
202 	ZippoWindow* zWindow;
203 	BList list;
204 
205 	while (1) {
206 		bWindow = WindowAt(windowCount++);
207 		if (bWindow == NULL)
208 			break;
209 
210 		zWindow = dynamic_cast<ZippoWindow*>(bWindow);
211 		if (zWindow == NULL)
212 			continue;
213 
214 		list.AddItem(zWindow);
215 
216 		if (zWindow->Lock()) {
217 			if (!zWindow->IsZipping()) {
218 				if (message != NULL)
219 					zWindow->PostMessage(message);
220 				zWindow->SetWorkspaces(B_CURRENT_WORKSPACE);
221 				zWindow->Activate();
222 				zWindow->Unlock();
223 				return;
224 			}
225 			zWindow->Unlock();
226 		}
227 	}
228 
229 	if (message) {
230 		zWindow = new ZippoWindow(list);
231 		zWindow->PostMessage(message);
232 	} else {
233 		zWindow = new ZippoWindow(list, true);
234 	}
235 
236 	zWindow->Show();
237 }
238 
239 
240 void
_StopZipping()241 ZipOMatic::_StopZipping()
242 {
243 	BWindow* window;
244 	ZippoWindow* zippo;
245 	BList list;
246 
247 	for (int32 i = 0;; i++) {
248 		window = WindowAt(i);
249 		if (window == NULL)
250 			break;
251 
252 		zippo = dynamic_cast<ZippoWindow*>(window);
253 		if (zippo == NULL)
254 			continue;
255 
256 		list.AddItem(zippo);
257 	}
258 
259 	for (int32 i = 0;; i++) {
260 		zippo = static_cast<ZippoWindow*>(list.ItemAt(i));
261 		if (zippo == NULL)
262 			break;
263 
264 		if (zippo->Lock()) {
265 			if (zippo->IsZipping())
266 				zippo->StopZipping();
267 
268 			zippo->PostMessage(B_QUIT_REQUESTED);
269 			zippo->Unlock();
270 		}
271 	}
272 }
273 
274