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