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