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