xref: /haiku/src/add-ons/tracker/zipomatic/ZipOMaticWindow.cpp (revision 10e3075f26f13443c7a74e5d81430f30330feeeb)
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 "ZipOMaticWindow.h"
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 
15 #include <Alert.h>
16 #include <Application.h>
17 #include <Directory.h>
18 #include <File.h>
19 #include <FindDirectory.h>
20 #include <GroupLayout.h>
21 #include <LayoutBuilder.h>
22 #include <Path.h>
23 #include <Roster.h>
24 #include <SeparatorView.h>
25 #include <String.h>
26 
27 #include "ZipOMatic.h"
28 #include "ZipOMaticActivity.h"
29 #include "ZipOMaticMisc.h"
30 #include "ZipperThread.h"
31 
32 
33 ZippoWindow::ZippoWindow(BRect frame, BMessage* refs)
34 	:
35 	BWindow(frame, "Zip-O-Matic", B_TITLED_WINDOW,
36 		B_NOT_RESIZABLE	| B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_ZOOMABLE),
37 	fThread(NULL),
38 	fWindowGotRefs(false),
39 	fZippingWasStopped(false),
40 	fFileCount(0),
41 	fWindowInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL,
42 		this))
43 {
44 	fActivityView = new Activity("activity");
45 	fActivityView->SetExplicitMinSize(BSize(171, 17));
46 
47 	fArchiveNameView = new BStringView("archive_text", "");
48 	fArchiveNameView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
49 		B_ALIGN_VERTICAL_UNSET));
50 
51 	fZipOutputView = new BStringView("output_text", "Drop files to zip.");
52 	fZipOutputView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
53 		B_ALIGN_VERTICAL_UNSET));
54 
55 	fStopButton = new BButton("stop", "Stop", new BMessage(B_QUIT_REQUESTED));
56 	fStopButton->SetEnabled(false);
57 	fStopButton->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT,
58 		B_ALIGN_VERTICAL_UNSET));
59 
60 	BSeparatorView* separator = new BSeparatorView(B_HORIZONTAL);
61 
62 	BLayoutBuilder::Group<>(this)
63 		.AddGroup(B_VERTICAL, 10)
64 			.Add(fActivityView)
65 			.Add(fArchiveNameView)
66 			.Add(fZipOutputView)
67 			.Add(separator)
68 			.Add(fStopButton)
69 			.SetInsets(14, 14, 14, 14)
70 			.End()
71 		.End();
72 
73 	if (refs != NULL) {
74 		fWindowGotRefs = true;
75 		_StartZipping(refs);
76 	}
77 }
78 
79 
80 ZippoWindow::~ZippoWindow()
81 {
82 	delete fWindowInvoker;
83 }
84 
85 
86 void
87 ZippoWindow::MessageReceived(BMessage* message)
88 {
89 	switch (message->what) {
90 		case B_REFS_RECEIVED:
91 			_StartZipping(message);
92 			break;
93 
94 		case B_SIMPLE_DATA:
95 			if (IsZipping()) {
96 				message->what = B_REFS_RECEIVED;
97 				be_app_messenger.SendMessage(message);
98 			} else {
99 				_StartZipping(message);
100 			}
101 			break;
102 
103 		case ZIPPO_THREAD_EXIT:
104 			fThread = NULL;
105 			fActivityView->Stop();
106 			fStopButton->SetEnabled(false);
107 			fArchiveNameView->SetText(" ");
108 			if (fZippingWasStopped)
109 				fZipOutputView->SetText("Stopped");
110 			else
111 				fZipOutputView->SetText("Archive created OK");
112 
113 			_CloseWindowOrKeepOpen();
114 			break;
115 
116 		case ZIPPO_THREAD_EXIT_ERROR:
117 			// TODO: figure out why this case does not happen when it should
118 			fThread = NULL;
119 			fActivityView->Stop();
120 			fStopButton->SetEnabled(false);
121 			fArchiveNameView->SetText("");
122 			fZipOutputView->SetText("Error creating archive");
123 			break;
124 
125 		case ZIPPO_TASK_DESCRIPTION:
126 		{
127 			BString string;
128 			if (message->FindString("archive_filename", &string) == B_OK)
129 				fArchiveNameView->SetText(string.String());
130 			break;
131 		}
132 
133 		case ZIPPO_LINE_OF_STDOUT:
134 		{
135 			BString string;
136 			if (message->FindString("zip_output", &string) == B_OK) {
137 				if (string.FindFirst("Adding: ") == 0
138 					|| string.FindFirst("Updating: ") == 0) {
139 
140 					// This is a workaround for the current window resizing
141 					// behavior as the window resizes for each line of output.
142 					// Instead of showing the true output of /bin/zip
143 					// we display a file count and whether the archive is
144 					// being created (added to) or if we're updating an
145 					// already existing archive.
146 
147 					fFileCount++;
148 					BString countString;
149 					countString << fFileCount;
150 
151 					if (fFileCount == 1)
152 						countString << " file";
153 					else
154 						countString << " files";
155 
156 					if (string.FindFirst("Adding: ") == 0)
157 						countString << " added.";
158 
159 					if (string.FindFirst("Updating: ") == 0)
160 						countString << " updated.";
161 
162 					fZipOutputView->SetText(countString.String());
163 				} else {
164 					fZipOutputView->SetText(string.String());
165 				}
166 			}
167 			break;
168 		}
169 
170 		case ZIPPO_QUIT_OR_CONTINUE:
171 		{
172 			int32 which_button = -1;
173 			if (message->FindInt32("which", &which_button) == B_OK) {
174 				if (which_button == 0) {
175 					StopZipping();
176 				} else {
177 					if (fThread != NULL)
178 						fThread->ResumeExternalZip();
179 
180 					fActivityView->Start();
181 				}
182 			}
183 			break;
184 		}
185 
186 		default:
187 			BWindow::MessageReceived(message);
188 			break;
189 	}
190 }
191 
192 
193 bool
194 ZippoWindow::QuitRequested()
195 {
196 	if (!IsZipping()) {
197 		BMessage message(ZIPPO_WINDOW_QUIT);
198 		message.AddRect("frame", Frame());
199 		be_app_messenger.SendMessage(&message);
200 		return true;
201 	} else {
202 		fThread->SuspendExternalZip();
203 		fActivityView->Pause();
204 
205 		BAlert* alert = new BAlert("Stop or Continue",
206 			"Are you sure you want to stop creating this archive?", "Stop",
207 			"Continue", NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
208 		alert->Go(fWindowInvoker);
209 
210 		return false;
211 	}
212 }
213 
214 
215 void
216 ZippoWindow::_StartZipping(BMessage* message)
217 {
218 	fStopButton->SetEnabled(true);
219 	fActivityView->Start();
220 	fFileCount = 0;
221 
222 	fThread = new ZipperThread(message, this);
223 	fThread->Start();
224 
225 	fZippingWasStopped = false;
226 }
227 
228 
229 void
230 ZippoWindow::StopZipping()
231 {
232 	fZippingWasStopped = true;
233 
234 	fStopButton->SetEnabled(false);
235 	fActivityView->Stop();
236 
237 	fThread->InterruptExternalZip();
238 	fThread->Quit();
239 
240 	status_t status = B_OK;
241 	fThread->WaitForThread(&status);
242 	fThread = NULL;
243 
244 	fArchiveNameView->SetText(" ");
245 	fZipOutputView->SetText("Stopped");
246 
247 	_CloseWindowOrKeepOpen();
248 }
249 
250 
251 bool
252 ZippoWindow::IsZipping()
253 {
254 	if (fThread == NULL)
255 		return false;
256 	else
257 		return true;
258 }
259 
260 
261 void
262 ZippoWindow::_CloseWindowOrKeepOpen()
263 {
264 	if (fWindowGotRefs)
265 		PostMessage(B_QUIT_REQUESTED);
266 }
267 
268