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