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