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