xref: /haiku/src/apps/expander/ExpanderWindow.cpp (revision b55a57da7173b9af0432bd3e148d03f06161d036)
1 /*
2  * Copyright 2004-2006, Jérôme DUVAL. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "ExpanderApp.h"
8 #include "ExpanderWindow.h"
9 #include "ExpanderThread.h"
10 #include "ExpanderPreferences.h"
11 
12 #include <Alert.h>
13 #include <Application.h>
14 #include <Box.h>
15 #include <Button.h>
16 #include <CheckBox.h>
17 #include <Entry.h>
18 #include <File.h>
19 #include <Menu.h>
20 #include <MenuBar.h>
21 #include <MenuItem.h>
22 #include <Path.h>
23 #include <ScrollView.h>
24 #include <StringView.h>
25 #include <TextView.h>
26 
27 const uint32 MSG_SOURCE		= 'mSOU';
28 const uint32 MSG_DEST		= 'mDES';
29 const uint32 MSG_EXPAND		= 'mEXP';
30 const uint32 MSG_SHOW		= 'mSHO';
31 const uint32 MSG_STOP		= 'mSTO';
32 const uint32 MSG_PREFERENCES = 'mPRE';
33 const uint32 MSG_SOURCETEXT = 'mSTX';
34 const uint32 MSG_DESTTEXT = 'mDTX';
35 const uint32 MSG_SHOWCONTENTS = 'mSCT';
36 
37 
38 ExpanderWindow::ExpanderWindow(BRect frame, const entry_ref *ref, BMessage *settings)
39 	: BWindow(frame, "Expander", B_TITLED_WINDOW, B_NOT_ZOOMABLE),
40 	fSourceChanged(true),
41 	fListingThread(NULL),
42 	fListingStarted(false),
43 	fExpandingThread(NULL),
44 	fExpandingStarted(false),
45 	fSettings(*settings),
46 	fPreferences(NULL)
47 {
48 	fSourcePanel = NULL;
49 	fDestPanel = NULL;
50 
51 	// create menu bar
52 	fBar = new BMenuBar(BRect(0, 0, Bounds().right, 20), "menu_bar");
53 	BMenu *menu = new BMenu("File");
54 	BMenuItem *item;
55 	menu->AddItem(item = new BMenuItem("About Expander" B_UTF8_ELLIPSIS, new BMessage(B_ABOUT_REQUESTED)));
56 	item->SetTarget(be_app_messenger);
57 	menu->AddSeparatorItem();
58 	menu->AddItem(fSourceItem = new BMenuItem("Set source" B_UTF8_ELLIPSIS, new BMessage(MSG_SOURCE), 'O'));
59 	menu->AddItem(fDestItem = new BMenuItem("Set destination" B_UTF8_ELLIPSIS, new BMessage(MSG_DEST), 'D'));
60 	menu->AddSeparatorItem();
61 	menu->AddItem(fExpandItem = new BMenuItem("Expand", new BMessage(MSG_EXPAND), 'E'));
62 	fExpandItem->SetEnabled(false);
63 	menu->AddItem(fShowItem = new BMenuItem("Show contents", new BMessage(MSG_SHOW), 'L'));
64 	fShowItem->SetEnabled(false);
65 	menu->AddSeparatorItem();
66 	menu->AddItem(fStopItem = new BMenuItem("Stop", new BMessage(MSG_STOP), 'K'));
67 	fStopItem->SetEnabled(false);
68 	menu->AddSeparatorItem();
69 	menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W'));
70 	fBar->AddItem(menu);
71 
72 	menu = new BMenu("Settings");
73 	menu->AddItem(fPreferencesItem = new BMenuItem("Settings" B_UTF8_ELLIPSIS,
74 		new BMessage(MSG_PREFERENCES), 'S'));
75 	fBar->AddItem(menu);
76 	AddChild(fBar);
77 
78 	BRect rect = Bounds();
79 	rect.top += fBar->Bounds().Height() + 1;
80 	BView *topView = new BView(rect, "background", B_FOLLOW_ALL, B_WILL_DRAW);
81 	topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
82 	AddChild(topView);
83 
84 	// Buttons
85 
86 	rect = topView->Bounds().InsetByCopy(8, 8);
87 	fDestButton = new BButton(rect, "destButton", "Destination",
88 		new BMessage(MSG_DEST), B_FOLLOW_LEFT | B_FOLLOW_TOP);
89 	fDestButton->ResizeToPreferred();
90 
91 	rect = fDestButton->Frame();
92 	fDestButton->MoveBy(0, rect.Height() + 4);
93 
94 	fSourceButton = new BButton(rect, "sourceButton", "Source",
95 		new BMessage(MSG_SOURCE), B_FOLLOW_LEFT | B_FOLLOW_TOP);
96 
97 	rect = fDestButton->Frame();
98 	rect.OffsetBy(0, rect.Height() + 4);
99 	fExpandButton = new BButton(rect, "expandButton", "Expand",
100 		new BMessage(MSG_EXPAND), B_FOLLOW_LEFT | B_FOLLOW_TOP);
101 	fExpandButton->SetEnabled(false);
102 
103 	// TextControls
104 
105 	rect = fSourceButton->Frame();
106 	rect.left = rect.right + 8;
107 	rect.right = frame.Width() - 8;
108 	fSourceText = new BTextControl(rect, "sourceText", "", NULL,
109 		new BMessage(MSG_SOURCETEXT), B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
110 	fSourceText->SetDivider(0);
111 	float width, height;
112 	fSourceText->GetPreferredSize(&width, &height);
113 	fSourceText->ResizeTo(rect.Width(), height);
114 	float offset = (rect.Height() - fSourceText->Bounds().Height()) / 2;
115 	fSourceText->MoveBy(0, offset);
116 	topView->AddChild(fSourceButton);
117 	topView->AddChild(fSourceText);
118 
119 	rect = fSourceText->Frame();
120 	rect.OffsetBy(0, fSourceButton->Bounds().Height() + 4);
121 	fDestText = new BTextControl(rect, "destText", "", NULL,
122 		new BMessage(MSG_DESTTEXT), B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
123 	fDestText->SetDivider(0);
124 	topView->AddChild(fDestButton);
125 	topView->AddChild(fDestText);
126 
127 	rect.OffsetBy(0, fSourceButton->Bounds().Height() + 4 + offset);
128 	fShowContents = new BCheckBox(rect, "showContents", "Show contents",
129 		new BMessage(MSG_SHOWCONTENTS), B_FOLLOW_RIGHT | B_FOLLOW_TOP);
130 	fShowContents->ResizeToPreferred();
131 	fShowContents->MoveTo(Bounds().right - 8 - fShowContents->Bounds().Width(),
132 		rect.top);
133 	topView->AddChild(fExpandButton);
134 	topView->AddChild(fShowContents);
135 	fShowContents->SetEnabled(false);
136 
137 	rect.left = fExpandButton->Frame().right + 8;
138 	rect.right = fShowContents->Frame().left - 4;
139 	fStatusView = new BStringView(rect, "statusView", "",
140 		B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS);
141 	topView->AddChild(fStatusView);
142 
143 	ResizeTo(frame.Width(), topView->Frame().top + fExpandButton->Frame().bottom + 8);
144 	SetSizeLimits(fExpandButton->Bounds().Width() * 3 + fShowContents->Bounds().Width() + 24,
145 		32767.0f, Frame().Height(), Frame().Height());
146 
147 	rect = topView->Bounds();
148 	rect.InsetBy(10, 0);
149 	rect.top = rect.bottom + 2;
150 	rect.bottom -= 10;
151 	rect.right -= B_V_SCROLL_BAR_WIDTH;
152 
153 	BRect textRect = rect;
154 	textRect.OffsetTo(B_ORIGIN);
155 	textRect.InsetBy(1, 1);
156 	fListingText = new BTextView(rect, "listingText", textRect,
157 		be_fixed_font, NULL, B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS);
158 	fListingText->SetText("");
159 	fListingText->MakeEditable(false);
160 	fListingScroll = new BScrollView("listingScroll", fListingText,
161 		B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS, false, true);
162 	topView->AddChild(fListingScroll);
163 	fListingScroll->Hide();
164 
165 	// finish creating window
166 	Show();
167 }
168 
169 
170 ExpanderWindow::~ExpanderWindow()
171 {
172 	if (fDestPanel && fDestPanel->RefFilter())
173 		delete fDestPanel->RefFilter();
174 
175 	if (fSourcePanel && fSourcePanel->RefFilter())
176 		delete fSourcePanel->RefFilter();
177 
178 	delete fDestPanel;
179 	delete fSourcePanel;
180 }
181 
182 bool
183 ExpanderWindow::ValidateDest()
184 {
185 	BEntry entry(fDestText->Text(), true);
186 	BVolume volume;
187 	if (!entry.Exists()) {
188 		BAlert *alert = new BAlert("destAlert", "The destination"
189 			" folder does not exist.", "Cancel", NULL, NULL,
190 			B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
191 		alert->Go();
192 		return false;
193 	} else if (!entry.IsDirectory()) {
194 		(new BAlert("destAlert", "The destination"
195 			" is not a folder.", "Cancel", NULL, NULL,
196 			B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT))->Go();
197 		return false;
198 	} else if (entry.GetVolume(&volume) != B_OK || volume.IsReadOnly()) {
199 		(new BAlert("destAlert", "The destination is read only.",
200 			"Cancel", NULL, NULL, B_WIDTH_AS_USUAL, B_EVEN_SPACING,
201 			B_WARNING_ALERT))->Go();
202 		return false;
203 	} else {
204 		entry.GetRef(&fDestRef);
205 		return true;
206 	}
207 }
208 
209 void
210 ExpanderWindow::FrameResized(float width, float height)
211 {
212 	if (fListingText->DoesWordWrap()) {
213 		BRect textRect;
214 		textRect = fListingText->Bounds();
215 		textRect.OffsetTo(B_ORIGIN);
216 		textRect.InsetBy(1, 1);
217 		fListingText->SetTextRect(textRect);
218 	}
219 }
220 
221 
222 void
223 ExpanderWindow::MessageReceived(BMessage *msg)
224 {
225 	switch (msg->what) {
226 		case MSG_SOURCE:
227 		{
228 			BEntry entry(fSourceText->Text(), true);
229 			entry_ref srcRef;
230 			if (entry.Exists() && entry.IsDirectory())
231 				entry.GetRef(&srcRef);
232 			if (!fSourcePanel) {
233 				BMessenger messenger(this);
234 				fSourcePanel = new BFilePanel(B_OPEN_PANEL, &messenger, &srcRef,
235 					B_FILE_NODE, false, NULL, new RuleRefFilter(fRules), true);
236 			} else
237 				fSourcePanel->SetPanelDirectory(&srcRef);
238 			fSourcePanel->Show();
239 			break;
240 		}
241 		case MSG_DEST:
242 		{
243 			BEntry entry(fDestText->Text(), true);
244 			entry_ref destRef;
245 			if (entry.Exists() && entry.IsDirectory())
246 				entry.GetRef(&destRef);
247 			if (!fDestPanel) {
248 				BMessenger messenger(this);
249 				fDestPanel = new DirectoryFilePanel(B_OPEN_PANEL, &messenger, &destRef,
250 					B_DIRECTORY_NODE, false, NULL, new DirectoryRefFilter(), true);
251 			} else
252 				fDestPanel->SetPanelDirectory(&destRef);
253 			fDestPanel->Show();
254 			break;
255 		}
256 		case MSG_DIRECTORY:
257 		{
258 			entry_ref ref;
259 			fDestPanel->GetPanelDirectory(&ref);
260 			fDestRef = ref;
261 			BEntry entry(&ref);
262 			BPath path(&entry);
263 			fDestText->SetText(path.Path());
264 			fDestPanel->Hide();
265 			break;
266 		}
267 
268 		case B_SIMPLE_DATA:
269 		case B_REFS_RECEIVED:
270 			RefsReceived(msg);
271 			break;
272 
273 		case MSG_EXPAND:
274 			if (!ValidateDest())
275 				break;
276 			if (!fExpandingStarted) {
277 				StartExpanding();
278 				break;
279 			}
280 			// supposed to fall through
281 		case MSG_STOP:
282 			if (fExpandingStarted) {
283 				fExpandingThread->SuspendExternalExpander();
284 				BAlert *alert = new BAlert("stopAlert", "Are you sure you want to stop expanding this\n"
285 					"archive? The expanded items may not be complete.", "Stop", "Continue", NULL,
286 					B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
287 				if (alert->Go() == 0) {
288 					fExpandingThread->ResumeExternalExpander();
289 					StopExpanding();
290 				} else
291 					fExpandingThread->ResumeExternalExpander();
292 			}
293 			break;
294 
295 		case MSG_SHOW:
296 			fShowContents->SetValue(fShowContents->Value() == B_CONTROL_OFF
297 				? B_CONTROL_ON : B_CONTROL_OFF);
298 			// supposed to fall through
299 		case MSG_SHOWCONTENTS:
300 			// change menu item label
301 			fShowItem->SetLabel(fShowContents->Value() == B_CONTROL_OFF
302 				? "Show contents" : "Hide contents");
303 
304 			if (fShowContents->Value() == B_CONTROL_OFF) {
305 				if (fListingStarted)
306 					StopListing();
307 
308 				_UpdateWindowSize(false);
309 			} else
310 				StartListing();
311 			break;
312 
313 		case MSG_SOURCETEXT:
314 		{
315 			BEntry entry(fSourceText->Text(), true);
316 			if (!entry.Exists()) {
317 				BAlert *alert = new BAlert("srcAlert", "The file doesn't exist",
318 					"Cancel", NULL, NULL,
319 					B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
320 				alert->Go();
321 				break;
322 			}
323 
324 			entry_ref ref;
325 			entry.GetRef(&ref);
326 			ExpanderRule *rule = fRules.MatchingRule(&ref);
327 			if (rule) {
328 				fSourceChanged = true;
329 				fSourceRef = ref;
330 				fShowContents->SetEnabled(true);
331 				fExpandButton->SetEnabled(true);
332 				fExpandItem->SetEnabled(true);
333 				fShowItem->SetEnabled(true);
334 				break;
335 			}
336 
337 			BString string = "The file : ";
338 			string += fSourceText->Text();
339 			string += " is not supported";
340 			BAlert *alert = new BAlert("srcAlert", string.String(),
341 				"Cancel", NULL, NULL, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_INFO_ALERT);
342 			alert->Go();
343 
344 			fShowContents->SetEnabled(false);
345 			fExpandButton->SetEnabled(false);
346 			fExpandItem->SetEnabled(false);
347 			fShowItem->SetEnabled(false);
348 		}
349 		break;
350 		case MSG_DESTTEXT:
351 		{
352 			ValidateDest();
353 		}
354 		break;
355 		case MSG_PREFERENCES:
356 			if (!fPreferences)
357 				fPreferences = new ExpanderPreferences(&fSettings);
358 			fPreferences->Show();
359 			break;
360 		case 'outp':
361 			if (!fExpandingStarted && fListingStarted) {
362 				BString string;
363 				int32 i = 0;
364 				while (msg->FindString("output", i++, &string) == B_OK) {
365 					// expand the window if we need...
366 					float delta = fListingText->StringWidth(string.String())
367 						- fListingText->Frame().Width();
368 					if (delta > fLargestDelta) {
369 						fLargestDelta = delta;
370 					}
371 					fListingText->Insert(string.String());
372 				}
373 				fListingText->ScrollToSelection();
374 			}
375 
376 			break;
377 		case 'exit':	// thread has finished		(finished, quit, killed, we don't know)
378 			// reset window state
379 			if (fExpandingStarted) {
380 				fStatusView->SetText("File expanded");
381 				StopExpanding();
382 				OpenDestFolder();
383 				CloseWindowOrKeepOpen();
384 			} else if (fListingStarted){
385 				fSourceChanged = false;
386 				StopListing();
387 				if (fLargestDelta > 0.0f)
388 					ResizeBy(fLargestDelta, 0.0f);
389 				fLargestDelta = 0.0f;
390 			} else
391 				fStatusView->SetText("");
392 			break;
393 		case 'exrr':	// thread has finished
394 			// reset window state
395 
396 			fStatusView->SetText("Error when expanding archive");
397 			CloseWindowOrKeepOpen();
398 			break;
399 		default:
400 			BWindow::MessageReceived(msg);
401 			break;
402 	}
403 }
404 
405 
406 bool
407 ExpanderWindow::CanQuit()
408 {
409 	if ((fSourcePanel && fSourcePanel->IsShowing())
410 		|| (fDestPanel && fDestPanel->IsShowing()))
411 		return false;
412 
413 	if (fExpandingStarted) {
414 		fExpandingThread->SuspendExternalExpander();
415 		BAlert *alert = new BAlert("stopAlert", "Are you sure you want to stop expanding this\n"
416 			"archive? The expanded items may not be complete.", "Stop", "Continue", NULL,
417 			B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
418 		if (alert->Go() == 0) {
419 			fExpandingThread->ResumeExternalExpander();
420 			StopExpanding();
421 		} else {
422 			fExpandingThread->ResumeExternalExpander();
423 			return false;
424 		}
425 	}
426 	return true;
427 }
428 
429 
430 bool
431 ExpanderWindow::QuitRequested()
432 {
433 	if (!CanQuit())
434 		return false;
435 
436 	if (fListingStarted)
437 		StopListing();
438 
439 	be_app->PostMessage(B_QUIT_REQUESTED);
440 	fSettings.ReplacePoint("window_position", Frame().LeftTop());
441 	((ExpanderApp*)(be_app))->UpdateSettingsFrom(&fSettings);
442 	return true;
443 }
444 
445 
446 void
447 ExpanderWindow::RefsReceived(BMessage *msg)
448 {
449 	entry_ref ref;
450 	int32 i = 0;
451 	int8 destination_folder = 0x63;
452 	fSettings.FindInt8("destination_folder", &destination_folder);
453 
454 	while (msg->FindRef("refs", i++, &ref) == B_OK) {
455 		BEntry entry(&ref, true);
456 		BPath path(&entry);
457 		BNode node(&entry);
458 
459 		if (node.IsFile()) {
460 			fSourceChanged = true;
461 			fSourceRef = ref;
462 			fSourceText->SetText(path.Path());
463 			if (destination_folder == 0x63) {
464 				BPath parent;
465 				path.GetParent(&parent);
466 				fDestText->SetText(parent.Path());
467 				get_ref_for_path(parent.Path(), &fDestRef);
468 			} else if (destination_folder == 0x65) {
469 				fSettings.FindRef("destination_folder_use", &fDestRef);
470 				BEntry dEntry(&fDestRef, true);
471 				BPath dPath(&dEntry);
472 				fDestText->SetText(dPath.Path());
473 			}
474 
475 			BEntry dEntry(&fDestRef, true);
476 			if (dEntry.Exists()) {
477 				fExpandButton->SetEnabled(true);
478 				fExpandItem->SetEnabled(true);
479 			}
480 
481 			if (fShowContents->Value() == B_CONTROL_ON) {
482 				StopListing();
483 				StartListing();
484 			} else {
485 				fShowContents->SetEnabled(true);
486 				fShowItem->SetEnabled(true);
487 			}
488 
489 			bool fromApp;
490 			if (msg->FindBool("fromApp", &fromApp) == B_OK) {
491 				AutoExpand();
492 			} else
493 				AutoListing();
494 		} else if (node.IsDirectory()) {
495 			fDestRef = ref;
496 			fDestText->SetText(path.Path());
497 		}
498 	}
499 }
500 
501 
502 void
503 ExpanderWindow::StartExpanding()
504 {
505 	ExpanderRule *rule = fRules.MatchingRule(&fSourceRef);
506 	if (!rule)
507 		return;
508 
509 	BEntry destEntry(fDestText->Text(), true);
510 	if (!destEntry.Exists()) {
511 		BAlert *alert = new BAlert("destAlert", "The folder was either moved, renamed or not\n"
512 			"supported.",
513 			"Cancel", NULL, NULL,
514 			B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
515 		alert->Go();
516 		return;
517 	}
518 
519 	BMessage message;
520 	message.AddString("cmd", rule->ExpandCmd());
521 	message.AddRef("srcRef", &fSourceRef);
522 	message.AddRef("destRef", &fDestRef);
523 
524 	fExpandButton->SetLabel("Stop");
525 	fSourceButton->SetEnabled(false);
526 	fDestButton->SetEnabled(false);
527 	fShowContents->SetEnabled(false);
528 	fSourceItem->SetEnabled(false);
529 	fDestItem->SetEnabled(false);
530 	fExpandItem->SetEnabled(false);
531 	fShowItem->SetEnabled(false);
532 	fStopItem->SetEnabled(true);
533 	fPreferencesItem->SetEnabled(false);
534 
535 	BEntry entry(&fSourceRef);
536 	BPath path(&entry);
537 	BString text("Expanding file ");
538 	text.Append(path.Leaf());
539 	fStatusView->SetText(text.String());
540 
541 	fExpandingThread = new ExpanderThread(&message, new BMessenger(this));
542 	fExpandingThread->Start();
543 
544 	fExpandingStarted = true;
545 }
546 
547 
548 void
549 ExpanderWindow::StopExpanding(void)
550 {
551 	if (fExpandingThread) {
552 		fExpandingThread->InterruptExternalExpander();
553 		fExpandingThread = NULL;
554 	}
555 
556 	fExpandingStarted = false;
557 
558 	fExpandButton->SetLabel("Expand");
559 	fSourceButton->SetEnabled(true);
560 	fDestButton->SetEnabled(true);
561 	fShowContents->SetEnabled(true);
562 	fSourceItem->SetEnabled(true);
563 	fDestItem->SetEnabled(true);
564 	fExpandItem->SetEnabled(true);
565 	fShowItem->SetEnabled(true);
566 	fStopItem->SetEnabled(false);
567 	fPreferencesItem->SetEnabled(true);
568 }
569 
570 
571 void
572 ExpanderWindow::_UpdateWindowSize(bool showContents)
573 {
574 	float minWidth, maxWidth, minHeight, maxHeight;
575 	GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
576 
577 	float bottom = fExpandButton->Parent()->Frame().top + fExpandButton->Frame().bottom + 8;
578 
579 	if (showContents) {
580 		font_height fontHeight;
581 		be_plain_font->GetHeight(&fontHeight);
582 		float lineHeight = ceilf(fontHeight.ascent + fontHeight.descent + fontHeight.leading);
583 
584 		minHeight = bottom + 14 + 4 * lineHeight;
585 		maxHeight = 32767.0;
586 		bottom = minHeight + 10 * lineHeight;
587 	} else {
588 		minHeight = bottom;
589 		maxHeight = bottom;
590 	}
591 
592 	SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight);
593 	ResizeTo(Frame().Width(), bottom);
594 }
595 
596 
597 void
598 ExpanderWindow::StartListing()
599 {
600 	_UpdateWindowSize(true);
601 
602 	fLargestDelta = 0.0f;
603 
604 	if (fListingScroll->IsHidden())
605 		fListingScroll->Show();
606 
607 	if (!fSourceChanged)
608 		return;
609 
610 	ExpanderRule *rule = fRules.MatchingRule(&fSourceRef);
611 	if (!rule)
612 		return;
613 
614 	BMessage message;
615 	message.AddString("cmd", rule->ListingCmd());
616 	message.AddRef("srcRef", &fSourceRef);
617 
618 	fShowContents->SetEnabled(true);
619 	fSourceItem->SetEnabled(false);
620 	fDestItem->SetEnabled(false);
621 	fExpandItem->SetEnabled(false);
622 	fShowItem->SetEnabled(true);
623 	fShowItem->SetLabel("Hide contents");
624 	fStopItem->SetEnabled(false);
625 	fPreferencesItem->SetEnabled(false);
626 
627 	fSourceButton->SetEnabled(false);
628 	fDestButton->SetEnabled(false);
629 	fExpandButton->SetEnabled(false);
630 
631 	BEntry entry(&fSourceRef);
632 	BPath path(&entry);
633 	BString text("Creating listing for ");
634 	text.Append(path.Leaf());
635 	fStatusView->SetText(text.String());
636 	fListingText->SetText("");
637 
638 	fListingThread = new ExpanderThread(&message, new BMessenger(this));
639 	fListingThread->Start();
640 
641 	fListingStarted = true;
642 }
643 
644 
645 void
646 ExpanderWindow::StopListing(void)
647 {
648 	if (fListingThread) {
649 		fListingThread->InterruptExternalExpander();
650 		fListingThread = NULL;
651 	}
652 
653 	fListingStarted = false;
654 
655 	fShowContents->SetEnabled(true);
656 	fSourceItem->SetEnabled(true);
657 	fDestItem->SetEnabled(true);
658 	fExpandItem->SetEnabled(true);
659 	fShowItem->SetEnabled(true);
660 	fStopItem->SetEnabled(false);
661 	fPreferencesItem->SetEnabled(true);
662 
663 	fSourceButton->SetEnabled(true);
664 	fDestButton->SetEnabled(true);
665 	fExpandButton->SetEnabled(true);
666 	fStatusView->SetText("");
667 }
668 
669 
670 void
671 ExpanderWindow::CloseWindowOrKeepOpen()
672 {
673 	bool expandFiles = false;
674 	fSettings.FindBool("automatically_expand_files", &expandFiles);
675 
676 	bool closeWhenDone = false;
677 	fSettings.FindBool("close_when_done", &closeWhenDone);
678 
679 	if (expandFiles || closeWhenDone)
680 		PostMessage(B_QUIT_REQUESTED);
681 }
682 
683 
684 void
685 ExpanderWindow::OpenDestFolder()
686 {
687 	bool openFolder = true;
688 	fSettings.FindBool("open_destination_folder", &openFolder);
689 
690 	if (!openFolder)
691 		return;
692 
693 	BMessage * message = new BMessage(B_REFS_RECEIVED);
694 	message->AddRef("refs", &fDestRef);
695 	BPath path(&fDestRef);
696 	BMessenger tracker("application/x-vnd.Be-TRAK");
697 	tracker.SendMessage(message);
698 }
699 
700 
701 void
702 ExpanderWindow::AutoListing()
703 {
704 	bool showContents = false;
705 	fSettings.FindBool("show_contents_listing", &showContents);
706 
707 	if (!showContents)
708 		return;
709 
710 	fShowContents->SetValue(B_CONTROL_ON);
711 	fShowContents->Invoke();
712 }
713 
714 
715 void
716 ExpanderWindow::AutoExpand()
717 {
718 	bool expandFiles = false;
719 	fSettings.FindBool("automatically_expand_files", &expandFiles);
720 
721 	if (!expandFiles) {
722 		AutoListing();
723 		return;
724 	}
725 
726 	fExpandButton->Invoke();
727 }
728