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