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