1 /* 2 * Copyright 2010 Wim van der Meer <WPJvanderMeer@gmail.com> 3 * Copyright Karsten Heimrich, host.haiku@gmx.de. 4 * All rights reserved. Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Karsten Heimrich 8 * Fredrik Modéen 9 * Christophe Huriaux 10 * Wim van der Meer 11 */ 12 13 14 #include "ScreenshotWindow.h" 15 16 #include <stdlib.h> 17 18 #include <Alert.h> 19 #include <Application.h> 20 #include <Bitmap.h> 21 #include <Box.h> 22 #include <Button.h> 23 #include <Catalog.h> 24 #include <CheckBox.h> 25 #include <File.h> 26 #include <FilePanel.h> 27 #include <FindDirectory.h> 28 #include <GridLayoutBuilder.h> 29 #include <GroupLayoutBuilder.h> 30 #include <Locale.h> 31 #include <Menu.h> 32 #include <MenuField.h> 33 #include <MenuItem.h> 34 #include <MessageFilter.h> 35 #include <Path.h> 36 #include <Roster.h> 37 #include <SpaceLayoutItem.h> 38 #include <String.h> 39 #include <StringView.h> 40 #include <TextControl.h> 41 #include <TranslationUtils.h> 42 #include <TranslatorRoster.h> 43 44 #include "PreviewView.h" 45 #include "Utility.h" 46 47 48 #undef B_TRANSLATE_CONTEXT 49 #define B_TRANSLATE_CONTEXT "ScreenshotWindow" 50 51 52 enum { 53 kActiveWindow, 54 kIncludeBorder, 55 kIncludeCursor, 56 kNewScreenshot, 57 kImageFormat, 58 kLocationChanged, 59 kChooseLocation, 60 kSaveScreenshot, 61 kSettings, 62 kCloseTranslatorSettings 63 }; 64 65 66 // #pragma mark - QuitMessageFilter 67 68 69 class QuitMessageFilter : public BMessageFilter { 70 public: 71 QuitMessageFilter(BWindow* window) 72 : 73 BMessageFilter((uint32)B_QUIT_REQUESTED), 74 fWindow(window) 75 { 76 } 77 78 virtual filter_result Filter(BMessage* message, BHandler** target) 79 { 80 BMessenger(fWindow).SendMessage(kCloseTranslatorSettings); 81 return B_SKIP_MESSAGE; 82 } 83 84 private: 85 BWindow* fWindow; 86 }; 87 88 89 // #pragma mark - DirectoryRefFilter 90 91 92 class DirectoryRefFilter : public BRefFilter { 93 public: 94 virtual ~DirectoryRefFilter() 95 { 96 } 97 98 virtual bool Filter(const entry_ref* ref, BNode* node, 99 struct stat_beos* stat, const char* filetype) 100 { 101 return node->IsDirectory(); 102 } 103 }; 104 105 106 // #pragma mark - ScreenshotWindow 107 108 109 ScreenshotWindow::ScreenshotWindow(const Utility& utility, bool silent, 110 bool clipboard) 111 : 112 BWindow(BRect(0, 0, 200.0, 100.0), B_TRANSLATE_SYSTEM_NAME("Screenshot"), 113 B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_AVOID_FRONT 114 | B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS 115 | B_CLOSE_ON_ESCAPE), 116 fUtility(utility), 117 fDelayControl(NULL), 118 fScreenshot(NULL), 119 fOutputPathPanel(NULL), 120 fLastSelectedPath(NULL), 121 fSettingsWindow(NULL), 122 fDelay(0), 123 fIncludeBorder(false), 124 fIncludeCursor(false), 125 fGrabActiveWindow(false), 126 fOutputFilename(NULL), 127 fExtension(""), 128 fImageFileType(B_PNG_FORMAT) 129 { 130 // _ReadSettings() needs a valid fOutputPathMenu 131 fOutputPathMenu = new BMenu(B_TRANSLATE("Please select")); 132 _ReadSettings(); 133 134 // _NewScreenshot() needs a valid fNameControl 135 BString name(B_TRANSLATE_NOCOLLECT(fUtility.sDefaultFileNameBase)); 136 name << 1; 137 name = _FindValidFileName(name.String()); 138 fNameControl = new BTextControl("", B_TRANSLATE("Name:"), name, NULL); 139 140 // Check if fUtility contains valid data 141 if (fUtility.wholeScreen == NULL) { 142 _NewScreenshot(silent, clipboard); 143 return; 144 } 145 146 fScreenshot = fUtility.MakeScreenshot(fIncludeCursor, fGrabActiveWindow, 147 fIncludeBorder); 148 149 fActiveWindow = new BCheckBox(B_TRANSLATE("Capture active window"), 150 new BMessage(kActiveWindow)); 151 if (fGrabActiveWindow) 152 fActiveWindow->SetValue(B_CONTROL_ON); 153 154 fWindowBorder = new BCheckBox(B_TRANSLATE("Include window border"), 155 new BMessage(kIncludeBorder)); 156 if (fIncludeBorder) 157 fWindowBorder->SetValue(B_CONTROL_ON); 158 if (!fGrabActiveWindow) 159 fWindowBorder->SetEnabled(false); 160 161 fShowCursor = new BCheckBox(B_TRANSLATE("Include mouse pointer"), 162 new BMessage(kIncludeCursor)); 163 if (fIncludeCursor) 164 fShowCursor->SetValue(B_CONTROL_ON); 165 166 BString delay; 167 delay << fDelay / 1000000; 168 fDelayControl = new BTextControl("", B_TRANSLATE("Delay:"), delay.String(), 169 NULL); 170 _DisallowChar(fDelayControl->TextView()); 171 fDelayControl->TextView()->SetAlignment(B_ALIGN_RIGHT); 172 BStringView* seconds = new BStringView("", B_TRANSLATE("seconds")); 173 seconds->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 174 175 BMenuField* menuLocation = new BMenuField(B_TRANSLATE("Save in:"), 176 fOutputPathMenu); 177 178 fTranslatorMenu = new BMenu(B_TRANSLATE("Please select")); 179 _SetupTranslatorMenu(); 180 BMenuField* menuFormat = new BMenuField(B_TRANSLATE("Save as:"), 181 fTranslatorMenu); 182 183 BButton* showSettings = new BButton("", B_TRANSLATE("Settings"B_UTF8_ELLIPSIS), 184 new BMessage(kSettings)); 185 showSettings->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, B_ALIGN_BOTTOM)); 186 187 BBox* divider = new BBox(B_FANCY_BORDER, NULL); 188 divider->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1)); 189 190 BButton* saveScreenshot = new BButton("", B_TRANSLATE("Save"), 191 new BMessage(kSaveScreenshot)); 192 193 fPreview = new PreviewView(); 194 195 BGridLayout* gridLayout = BGridLayoutBuilder(0.0, 5.0) 196 .Add(fDelayControl->CreateLabelLayoutItem(), 0, 0) 197 .Add(fDelayControl->CreateTextViewLayoutItem(), 1, 0) 198 .Add(BSpaceLayoutItem::CreateHorizontalStrut(5), 2, 0) 199 .Add(seconds, 3, 0) 200 .Add(fNameControl->CreateLabelLayoutItem(), 0, 1) 201 .Add(fNameControl->CreateTextViewLayoutItem(), 1, 1, 3, 1) 202 .Add(menuLocation->CreateLabelLayoutItem(), 0, 2) 203 .Add(menuLocation->CreateMenuBarLayoutItem(), 1, 2, 3, 1) 204 .Add(menuFormat->CreateLabelLayoutItem(), 0, 3) 205 .Add(menuFormat->CreateMenuBarLayoutItem(), 1, 3, 3, 1); 206 207 gridLayout->SetMinColumnWidth(1, 208 menuFormat->StringWidth("SomethingLongHere")); 209 210 SetLayout(new BGroupLayout(B_HORIZONTAL, 0)); 211 212 AddChild(BGroupLayoutBuilder(B_VERTICAL, 0) 213 .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10.0) 214 .Add(fPreview) 215 .AddGroup(B_VERTICAL, 0) 216 .Add(fActiveWindow) 217 .Add(fWindowBorder) 218 .Add(fShowCursor) 219 .AddStrut(10.0) 220 .Add(gridLayout) 221 .Add(showSettings) 222 .AddGlue() 223 .End()) 224 .AddStrut(10) 225 .Add(divider) 226 .AddStrut(10) 227 .AddGroup(B_HORIZONTAL, 10.0) 228 .Add(new BButton("", B_TRANSLATE("Copy to clipboard"), 229 new BMessage(B_COPY))) 230 .Add(new BButton("", B_TRANSLATE("New screenshot"), 231 new BMessage(kNewScreenshot))) 232 .AddGlue() 233 .Add(saveScreenshot) 234 .End() 235 .SetInsets(10.0, 10.0, 10.0, 10.0) 236 ); 237 238 saveScreenshot->MakeDefault(true); 239 240 _UpdatePreviewPanel(); 241 _UpdateFilenameSelection(); 242 243 CenterOnScreen(); 244 Show(); 245 } 246 247 248 ScreenshotWindow::~ScreenshotWindow() 249 { 250 if (fOutputPathPanel) 251 delete fOutputPathPanel->RefFilter(); 252 253 delete fOutputPathPanel; 254 delete fScreenshot; 255 } 256 257 258 void 259 ScreenshotWindow::MessageReceived(BMessage* message) 260 { 261 switch (message->what) { 262 case kActiveWindow: 263 fGrabActiveWindow = false; 264 if (fActiveWindow->Value() == B_CONTROL_ON) 265 fGrabActiveWindow = true; 266 267 fWindowBorder->SetEnabled(fGrabActiveWindow); 268 269 delete fScreenshot; 270 fScreenshot = fUtility.MakeScreenshot(fIncludeCursor, 271 fGrabActiveWindow, fIncludeBorder); 272 _UpdatePreviewPanel(); 273 break; 274 275 case kIncludeBorder: 276 fIncludeBorder = (fWindowBorder->Value() == B_CONTROL_ON); 277 delete fScreenshot; 278 fScreenshot = fUtility.MakeScreenshot(fIncludeCursor, 279 fGrabActiveWindow, fIncludeBorder); 280 _UpdatePreviewPanel(); 281 break; 282 283 case kIncludeCursor: 284 fIncludeCursor = (fShowCursor->Value() == B_CONTROL_ON); 285 delete fScreenshot; 286 fScreenshot = fUtility.MakeScreenshot(fIncludeCursor, 287 fGrabActiveWindow, fIncludeBorder); 288 _UpdatePreviewPanel(); 289 break; 290 291 case kNewScreenshot: 292 fDelay = (atoi(fDelayControl->Text()) * 1000000) + 50000; 293 _NewScreenshot(); 294 break; 295 296 case kImageFormat: 297 message->FindInt32("be:type", &fImageFileType); 298 fNameControl->SetText(_FindValidFileName( 299 fNameControl->Text()).String()); 300 _UpdateFilenameSelection(); 301 _ShowSettings(false); 302 break; 303 304 case kLocationChanged: 305 { 306 void* source = NULL; 307 if (message->FindPointer("source", &source) == B_OK) 308 fLastSelectedPath = static_cast<BMenuItem*> (source); 309 310 fNameControl->SetText(_FindValidFileName( 311 fNameControl->Text()).String()); 312 313 _UpdateFilenameSelection(); 314 break; 315 } 316 317 case kChooseLocation: 318 { 319 if (!fOutputPathPanel) { 320 BMessenger target(this); 321 fOutputPathPanel = new BFilePanel(B_OPEN_PANEL, &target, NULL, 322 B_DIRECTORY_NODE, false, NULL, new DirectoryRefFilter()); 323 fOutputPathPanel->Window()->SetTitle( 324 B_TRANSLATE("Choose folder")); 325 fOutputPathPanel->SetButtonLabel(B_DEFAULT_BUTTON, 326 B_TRANSLATE("Select")); 327 fOutputPathPanel->SetButtonLabel(B_CANCEL_BUTTON, 328 B_TRANSLATE("Cancel")); 329 } 330 fOutputPathPanel->Show(); 331 break; 332 } 333 334 case B_REFS_RECEIVED: 335 { 336 entry_ref ref; 337 if (message->FindRef("refs", &ref) == B_OK) { 338 BEntry entry(&ref, true); 339 if (entry.InitCheck() == B_OK) { 340 BPath path; 341 // Could return B_BUSY 342 if (entry.GetPath(&path) == B_OK) { 343 BString label(path.Path()); 344 _AddItemToPathMenu(path.Path(), label, 3, true); 345 } 346 } 347 } 348 break; 349 } 350 351 case B_CANCEL: 352 fLastSelectedPath->SetMarked(true); 353 break; 354 355 case kSaveScreenshot: 356 if (_SaveScreenshot() == B_OK) 357 be_app->PostMessage(B_QUIT_REQUESTED); 358 break; 359 360 case B_COPY: 361 fUtility.CopyToClipboard(fScreenshot); 362 break; 363 364 case kSettings: 365 _ShowSettings(true); 366 break; 367 368 case kCloseTranslatorSettings: 369 fSettingsWindow->Lock(); 370 fSettingsWindow->Quit(); 371 fSettingsWindow = NULL; 372 break; 373 374 default: 375 BWindow::MessageReceived(message); 376 break; 377 } 378 } 379 380 381 void 382 ScreenshotWindow::Quit() 383 { 384 if (fUtility.wholeScreen != NULL) 385 _WriteSettings(); 386 BWindow::Quit(); 387 } 388 389 390 void 391 ScreenshotWindow::_NewScreenshot(bool silent, bool clipboard) 392 { 393 BMessage message(B_ARGV_RECEIVED); 394 int32 argc = 3; 395 BString delay; 396 delay << fDelay / 1000000; 397 message.AddString("argv", "screenshot"); 398 message.AddString("argv", "--delay"); 399 message.AddString("argv", delay); 400 401 if (silent || clipboard) { 402 if (silent) { 403 argc++; 404 message.AddString("argv", "--silent"); 405 } 406 if (clipboard) { 407 argc++; 408 message.AddString("argv", "--clipboard"); 409 } 410 if (fIncludeBorder) { 411 argc++; 412 message.AddString("argv", "--border"); 413 } 414 if (fIncludeCursor) { 415 argc++; 416 message.AddString("argv", "--mouse-pointer"); 417 } 418 if (fGrabActiveWindow) { 419 argc++; 420 message.AddString("argv", "--window"); 421 } 422 if (fLastSelectedPath) { 423 BPath path(_GetDirectory()); 424 if (path != NULL) { 425 path.Append(fNameControl->Text()); 426 argc++; 427 message.AddString("argv", path.Path()); 428 } 429 } 430 } 431 message.AddInt32("argc", argc); 432 433 be_roster->Launch("application/x-vnd.haiku-screenshot-cli", &message); 434 be_app->PostMessage(B_QUIT_REQUESTED); 435 } 436 437 438 void 439 ScreenshotWindow::_UpdatePreviewPanel() 440 { 441 float height = 150.0f; 442 443 float width = (fScreenshot->Bounds().Width() 444 / fScreenshot->Bounds().Height()) * height; 445 446 // to prevent a preview way too wide 447 if (width > 400.0f) { 448 width = 400.0f; 449 height = (fScreenshot->Bounds().Height() 450 / fScreenshot->Bounds().Width()) * width; 451 } 452 453 fPreview->SetExplicitMinSize(BSize(width, height)); 454 455 fPreview->ClearViewBitmap(); 456 fPreview->SetViewBitmap(fScreenshot, fScreenshot->Bounds(), 457 fPreview->Bounds(), B_FOLLOW_ALL, B_FILTER_BITMAP_BILINEAR); 458 } 459 460 461 void 462 ScreenshotWindow::_DisallowChar(BTextView* textView) 463 { 464 for (uint32 i = 0; i < '0'; ++i) 465 textView->DisallowChar(i); 466 467 for (uint32 i = '9' + 1; i < 255; ++i) 468 textView->DisallowChar(i); 469 } 470 471 472 void 473 ScreenshotWindow::_SetupOutputPathMenu(const BMessage& settings) 474 { 475 fOutputPathMenu->SetLabelFromMarked(true); 476 477 BString lastSelectedPath; 478 settings.FindString("lastSelectedPath", &lastSelectedPath); 479 480 BPath path; 481 find_directory(B_USER_DIRECTORY, &path); 482 483 BString label(B_TRANSLATE("Home folder")); 484 _AddItemToPathMenu(path.Path(), label, 0, 485 (path.Path() == lastSelectedPath)); 486 487 path.Append("Desktop"); 488 label.SetTo(B_TRANSLATE("Desktop")); 489 _AddItemToPathMenu(path.Path(), label, 0, ( 490 path.Path() == lastSelectedPath)); 491 492 find_directory(B_BEOS_ETC_DIRECTORY, &path); 493 path.Append("artwork"); 494 495 label.SetTo(B_TRANSLATE("Artwork folder")); 496 _AddItemToPathMenu(path.Path(), label, 2, 497 (path.Path() == lastSelectedPath)); 498 499 int32 i = 0; 500 BString userPath; 501 while (settings.FindString("path", ++i, &userPath) == B_OK) { 502 _AddItemToPathMenu(userPath.String(), userPath, 3, 503 (userPath == lastSelectedPath)); 504 } 505 506 if (!fLastSelectedPath) { 507 if (settings.IsEmpty() || lastSelectedPath.Length() == 0) { 508 fOutputPathMenu->ItemAt(1)->SetMarked(true); 509 fLastSelectedPath = fOutputPathMenu->ItemAt(1); 510 } else 511 _AddItemToPathMenu(lastSelectedPath.String(), lastSelectedPath, 3, 512 true); 513 } 514 515 fOutputPathMenu->AddItem(new BSeparatorItem()); 516 fOutputPathMenu->AddItem(new BMenuItem(B_TRANSLATE("Choose folder..."), 517 new BMessage(kChooseLocation))); 518 } 519 520 521 void 522 ScreenshotWindow::_AddItemToPathMenu(const char* path, BString& label, 523 int32 index, bool markItem) 524 { 525 // Make sure that item won't be a duplicate of an existing one 526 for (int32 i = fOutputPathMenu->CountItems() - 1; i >= 0; --i) { 527 BMenuItem* menuItem = fOutputPathMenu->ItemAt(i); 528 BMessage* message = menuItem->Message(); 529 const char* pathFromItem; 530 if (message != NULL && message->what == kLocationChanged 531 && message->FindString("path", &pathFromItem) == B_OK 532 && !strcmp(path, pathFromItem)) { 533 534 if (markItem) { 535 fOutputPathMenu->ItemAt(i)->SetMarked(true); 536 fLastSelectedPath = fOutputPathMenu->ItemAt(i); 537 } 538 return; 539 } 540 } 541 542 BMessage* message = new BMessage(kLocationChanged); 543 message->AddString("path", path); 544 545 fOutputPathMenu->TruncateString(&label, B_TRUNCATE_MIDDLE, 546 fOutputPathMenu->StringWidth("SomethingLongHere")); 547 548 fOutputPathMenu->AddItem(new BMenuItem(label.String(), message), index); 549 550 if (markItem) { 551 fOutputPathMenu->ItemAt(index)->SetMarked(true); 552 fLastSelectedPath = fOutputPathMenu->ItemAt(index); 553 } 554 } 555 556 557 void 558 ScreenshotWindow::_UpdateFilenameSelection() 559 { 560 fNameControl->MakeFocus(true); 561 fNameControl->TextView()->Select(0, fNameControl->TextView()->TextLength() 562 - fExtension.Length()); 563 564 fNameControl->TextView()->ScrollToSelection(); 565 } 566 567 568 void 569 ScreenshotWindow::_SetupTranslatorMenu() 570 { 571 BMessage message(kImageFormat); 572 fTranslatorMenu = new BMenu("Please select"); 573 BTranslationUtils::AddTranslationItems(fTranslatorMenu, B_TRANSLATOR_BITMAP, 574 &message, NULL, NULL, NULL); 575 576 fTranslatorMenu->SetLabelFromMarked(true); 577 578 if (fTranslatorMenu->ItemAt(0)) 579 fTranslatorMenu->ItemAt(0)->SetMarked(true); 580 581 int32 imageFileType; 582 for (int32 i = 0; i < fTranslatorMenu->CountItems(); ++i) { 583 BMenuItem* item = fTranslatorMenu->ItemAt(i); 584 if (item && item->Message()) { 585 item->Message()->FindInt32("be:type", &imageFileType); 586 if (fImageFileType == imageFileType) { 587 item->SetMarked(true); 588 MessageReceived(item->Message()); 589 break; 590 } 591 } 592 } 593 } 594 595 596 status_t 597 ScreenshotWindow::_SaveScreenshot() 598 { 599 if (!fScreenshot || !fLastSelectedPath) 600 return B_ERROR; 601 602 BPath path(_GetDirectory()); 603 604 if (path == NULL) 605 return B_ERROR; 606 607 path.Append(fNameControl->Text()); 608 609 BEntry entry; 610 entry.SetTo(path.Path()); 611 612 if (entry.Exists()) { 613 BAlert* overwriteAlert = new BAlert( 614 B_TRANSLATE("overwrite"), 615 B_TRANSLATE("This file already exists.\n Are you sure would " 616 "you like to overwrite it?"), 617 B_TRANSLATE("Cancel"), 618 B_TRANSLATE("Overwrite"), 619 NULL, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT); 620 621 overwriteAlert->SetShortcut(0, B_ESCAPE); 622 623 if (overwriteAlert->Go() == 0) 624 return B_CANCELED; 625 } 626 627 return fUtility.Save(&fScreenshot, path.Path(), fImageFileType); 628 } 629 630 631 void 632 ScreenshotWindow::_ShowSettings(bool activate) 633 { 634 if (!fSettingsWindow && !activate) 635 return; 636 637 // Find a translator 638 translator_id translator = 0; 639 BTranslatorRoster *roster = BTranslatorRoster::Default(); 640 translator_id* translators = NULL; 641 int32 numTranslators = 0; 642 if (roster->GetAllTranslators(&translators, &numTranslators) != B_OK) 643 return; 644 bool foundTranslator = false; 645 for (int32 x = 0; x < numTranslators; x++) { 646 const translation_format* formats = NULL; 647 int32 numFormats; 648 if (roster->GetOutputFormats(translators[x], &formats, 649 &numFormats) == B_OK) { 650 for (int32 i = 0; i < numFormats; ++i) { 651 if (formats[i].type == static_cast<uint32>(fImageFileType)) { 652 translator = translators[x]; 653 foundTranslator = true; 654 break; 655 } 656 } 657 } 658 if (foundTranslator) 659 break; 660 } 661 delete [] translators; 662 if (!foundTranslator) 663 return; 664 665 // Create a window with a configuration view 666 BView *view; 667 BRect rect(0, 0, 239, 239); 668 669 status_t err = roster->MakeConfigurationView(translator, NULL, &view, 670 &rect); 671 if (err < B_OK || view == NULL) { 672 BAlert *alert = new BAlert(NULL, strerror(err), "OK"); 673 alert->Go(); 674 } else { 675 if (fSettingsWindow) { 676 fSettingsWindow->RemoveChild(fSettingsWindow->ChildAt(0)); 677 float width, height; 678 view->GetPreferredSize(&width, &height); 679 fSettingsWindow->ResizeTo(width, height); 680 fSettingsWindow->AddChild(view); 681 if (activate) 682 fSettingsWindow->Activate(); 683 } else { 684 fSettingsWindow = new BWindow(rect, 685 B_TRANSLATE("Translator Settings"), 686 B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 687 B_NOT_ZOOMABLE | B_NOT_RESIZABLE); 688 fSettingsWindow->AddFilter(new QuitMessageFilter(this)); 689 fSettingsWindow->AddChild(view); 690 fSettingsWindow->CenterOnScreen(); 691 fSettingsWindow->Show(); 692 } 693 } 694 } 695 696 697 BString 698 ScreenshotWindow::_FindValidFileName(const char* name) 699 { 700 BString baseName(name); 701 702 if (fExtension.Compare("")) 703 baseName.RemoveLast(fExtension); 704 705 if (!fLastSelectedPath) 706 return baseName; 707 708 BPath orgPath(_GetDirectory()); 709 if (orgPath == NULL) 710 return baseName; 711 712 fExtension = BString(fUtility.GetFileNameExtension(fImageFileType)); 713 714 BPath outputPath = orgPath; 715 BString fileName; 716 fileName << baseName << fExtension; 717 outputPath.Append(fileName); 718 719 if (!BEntry(outputPath.Path()).Exists()) 720 return fileName; 721 722 if (baseName.FindFirst(B_TRANSLATE_NOCOLLECT( 723 fUtility.sDefaultFileNameBase)) == 0) 724 baseName.SetTo(fUtility.sDefaultFileNameBase); 725 726 BEntry entry; 727 int32 index = 1; 728 729 do { 730 fileName = ""; 731 fileName << baseName << index++ << fExtension; 732 outputPath.SetTo(orgPath.Path()); 733 outputPath.Append(fileName); 734 entry.SetTo(outputPath.Path()); 735 } while (entry.Exists()); 736 737 return fileName; 738 } 739 740 741 BPath 742 ScreenshotWindow::_GetDirectory() 743 { 744 BPath path; 745 746 BMessage* message = fLastSelectedPath->Message(); 747 const char* stringPath; 748 if (message && message->FindString("path", &stringPath) == B_OK) 749 path.SetTo(stringPath); 750 751 return path; 752 } 753 754 755 void 756 ScreenshotWindow::_ReadSettings() 757 { 758 BMessage settings; 759 760 BPath settingsPath; 761 if (find_directory(B_USER_SETTINGS_DIRECTORY, &settingsPath) != B_OK) 762 return; 763 764 settingsPath.Append("Screenshot_settings"); 765 766 BFile file(settingsPath.Path(), B_READ_ONLY); 767 if (file.InitCheck() == B_OK) 768 settings.Unflatten(&file); 769 770 if (settings.FindInt32("type", &fImageFileType) != B_OK) 771 fImageFileType = B_PNG_FORMAT; 772 settings.FindBool("includeBorder", &fIncludeBorder); 773 settings.FindBool("includeCursor", &fIncludeCursor); 774 settings.FindBool("grabActiveWindow", &fGrabActiveWindow); 775 settings.FindInt64("delay", &fDelay); 776 settings.FindString("outputFilename", &fOutputFilename); 777 778 _SetupOutputPathMenu(settings); 779 } 780 781 782 void 783 ScreenshotWindow::_WriteSettings() 784 { 785 if (fDelayControl) 786 fDelay = (atoi(fDelayControl->Text()) * 1000000) + 50000; 787 788 BMessage settings; 789 790 settings.AddInt32("type", fImageFileType); 791 settings.AddBool("includeBorder", fIncludeBorder); 792 settings.AddBool("includeCursor", fIncludeCursor); 793 settings.AddBool("grabActiveWindow", fGrabActiveWindow); 794 settings.AddInt64("delay", fDelay); 795 settings.AddString("outputFilename", fOutputFilename); 796 797 BString path; 798 int32 count = fOutputPathMenu->CountItems(); 799 if (count > 5) { 800 for (int32 i = count - 3; i > count - 8 && i > 2; --i) { 801 BMenuItem* item = fOutputPathMenu->ItemAt(i); 802 if (item) { 803 BMessage* msg = item->Message(); 804 if (msg && msg->FindString("path", &path) == B_OK) 805 settings.AddString("path", path.String()); 806 } 807 } 808 } 809 810 if (fLastSelectedPath) { 811 BMessage* msg = fLastSelectedPath->Message(); 812 if (msg && msg->FindString("path", &path) == B_OK) 813 settings.AddString("lastSelectedPath", path.String()); 814 } 815 816 BPath settingsPath; 817 if (find_directory(B_USER_SETTINGS_DIRECTORY, &settingsPath) != B_OK) 818 return; 819 settingsPath.Append("Screenshot_settings"); 820 821 BFile file(settingsPath.Path(), B_CREATE_FILE | B_ERASE_FILE 822 | B_WRITE_ONLY); 823 if (file.InitCheck() == B_OK) { 824 ssize_t size; 825 settings.Flatten(&file, &size); 826 } 827 } 828