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