1 /* 2 * Copyright 2005-2022 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Augustin Cavalier <waddlesplash> 7 * DarkWyrm <bpmagic@columbus.rr.com> 8 * René Gollent 9 * John Scipione, jscipione@gmail.com 10 * Wim van der Meer <WPJvanderMeer@gmail.com> 11 */ 12 13 14 #include <ctype.h> 15 #include <stdio.h> 16 #include <time.h> 17 #include <unistd.h> 18 19 #include <algorithm> 20 #include <map> 21 #include <string> 22 23 #include <AboutWindow.h> 24 #include <AppFileInfo.h> 25 #include <Application.h> 26 #include <Bitmap.h> 27 #include <ColorConversion.h> 28 #include <ControlLook.h> 29 #include <DateTimeFormat.h> 30 #include <Dragger.h> 31 #include <DurationFormat.h> 32 #include <File.h> 33 #include <FindDirectory.h> 34 #include <Font.h> 35 #include <fs_attr.h> 36 #include <LayoutBuilder.h> 37 #include <MessageRunner.h> 38 #include <Messenger.h> 39 #include <ObjectList.h> 40 #include <OS.h> 41 #include <Path.h> 42 #include <PathFinder.h> 43 #include <PopUpMenu.h> 44 #include <Resources.h> 45 #include <Screen.h> 46 #include <ScrollView.h> 47 #include <String.h> 48 #include <StringFormat.h> 49 #include <StringList.h> 50 #include <StringView.h> 51 #include <TextView.h> 52 #include <TranslationUtils.h> 53 #include <TranslatorFormats.h> 54 #include <View.h> 55 #include <ViewPrivate.h> 56 #include <Volume.h> 57 #include <VolumeRoster.h> 58 #include <Window.h> 59 #include <WindowPrivate.h> 60 61 #include <AppMisc.h> 62 #include <AutoDeleter.h> 63 #include <AutoDeleterPosix.h> 64 #include <cpu_type.h> 65 #include <parsedate.h> 66 #include <system_revision.h> 67 68 #include <Catalog.h> 69 #include <Language.h> 70 #include <Locale.h> 71 #include <LocaleRoster.h> 72 73 #include "HyperTextActions.h" 74 #include "HyperTextView.h" 75 #include "Utilities.h" 76 77 #include "Credits.h" 78 79 80 #ifndef LINE_MAX 81 #define LINE_MAX 2048 82 #endif 83 84 85 #undef B_TRANSLATION_CONTEXT 86 #define B_TRANSLATION_CONTEXT "AboutWindow" 87 88 89 static const char* kSignature = "application/x-vnd.Haiku-About"; 90 91 static const float kWindowWidth = 500.0f; 92 static const float kWindowHeight = 300.0f; 93 94 static const float kSysInfoMinWidth = 163.0f; 95 static const float kSysInfoMinHeight = 193.0f; 96 97 static const int32 kMsgScrollCreditsView = 'mviv'; 98 99 static int ignored_pages(system_info*); 100 static int max_pages(system_info*); 101 static int max_and_ignored_pages(system_info*); 102 static int used_pages(system_info*); 103 104 static const rgb_color kIdealHaikuGreen = { 42, 131, 36, 255 }; 105 static const rgb_color kIdealHaikuOrange = { 255, 69, 0, 255 }; 106 static const rgb_color kIdealHaikuYellow = { 255, 176, 0, 255 }; 107 static const rgb_color kIdealBeOSBlue = { 0, 0, 200, 255 }; 108 static const rgb_color kIdealBeOSRed = { 200, 0, 0, 255 }; 109 110 static const char* kBSDTwoClause = B_TRANSLATE_MARK("BSD (2-clause)"); 111 static const char* kBSDThreeClause = B_TRANSLATE_MARK("BSD (3-clause)"); 112 static const char* kBSDFourClause = B_TRANSLATE_MARK("BSD (4-clause)"); 113 static const char* kGPLv2 = B_TRANSLATE_MARK("GNU GPL v2"); 114 static const char* kGPLv3 = B_TRANSLATE_MARK("GNU GPL v3"); 115 static const char* kLGPLv2 = B_TRANSLATE_MARK("GNU LGPL v2"); 116 static const char* kLGPLv21 = B_TRANSLATE_MARK("GNU LGPL v2.1"); 117 #if 0 118 static const char* kPublicDomain = B_TRANSLATE_MARK("Public Domain"); 119 #endif 120 #ifdef __i386__ 121 static const char* kIntel2xxxFirmware = B_TRANSLATE_MARK("Intel (2xxx firmware)"); 122 static const char* kIntelFirmware = B_TRANSLATE_MARK("Intel WiFi Firmware"); 123 static const char* kMarvellFirmware = B_TRANSLATE_MARK("Marvell (firmware)"); 124 static const char* kRalinkFirmware = B_TRANSLATE_MARK("Ralink WiFi Firmware"); 125 #endif 126 127 128 // #pragma mark - TranslationComparator function 129 130 131 static int 132 TranslationComparator(const void* left, const void* right) 133 { 134 const Translation* leftTranslation = *(const Translation**)left; 135 const Translation* rightTranslation = *(const Translation**)right; 136 137 BLanguage* language; 138 BString leftName; 139 if (BLocaleRoster::Default()->GetLanguage(leftTranslation->languageCode, 140 &language) == B_OK) { 141 language->GetName(leftName); 142 delete language; 143 } else 144 leftName = leftTranslation->languageCode; 145 146 BString rightName; 147 if (BLocaleRoster::Default()->GetLanguage(rightTranslation->languageCode, 148 &language) == B_OK) { 149 language->GetName(rightName); 150 delete language; 151 } else 152 rightName = rightTranslation->languageCode; 153 154 BCollator collator; 155 BLocale::Default()->GetCollator(&collator); 156 return collator.Compare(leftName.String(), rightName.String()); 157 } 158 159 160 // #pragma mark - class definitions 161 162 163 class AboutApp : public BApplication { 164 public: 165 AboutApp(); 166 void MessageReceived(BMessage* message); 167 }; 168 169 170 class AboutView; 171 172 class AboutWindow : public BWindow { 173 public: 174 AboutWindow(); 175 176 virtual bool QuitRequested(); 177 178 AboutView* fAboutView; 179 }; 180 181 182 class LogoView : public BView { 183 public: 184 LogoView(); 185 virtual ~LogoView(); 186 187 virtual BSize MinSize(); 188 virtual BSize MaxSize(); 189 190 virtual void Draw(BRect updateRect); 191 192 private: 193 BBitmap* fLogo; 194 }; 195 196 197 class CropView : public BView { 198 public: 199 CropView(BView* target, int32 left, int32 top, 200 int32 right, int32 bottom); 201 virtual ~CropView(); 202 203 virtual BSize MinSize(); 204 virtual BSize MaxSize(); 205 206 virtual void DoLayout(); 207 208 private: 209 BView* fTarget; 210 int32 fCropLeft; 211 int32 fCropTop; 212 int32 fCropRight; 213 int32 fCropBottom; 214 }; 215 216 217 class SysInfoView : public BView { 218 public: 219 SysInfoView(); 220 SysInfoView(BMessage* archive); 221 virtual ~SysInfoView(); 222 223 virtual status_t Archive(BMessage* archive, bool deep = true) const; 224 static BArchivable* Instantiate(BMessage* archive); 225 226 virtual void AttachedToWindow(); 227 virtual void AllAttached(); 228 virtual void Draw(BRect); 229 virtual void MessageReceived(BMessage* message); 230 virtual void Pulse(); 231 232 void CacheInitialSize(); 233 234 float MinWidth() const { return fCachedMinWidth; }; 235 float MinHeight() const { return fCachedMinHeight; }; 236 237 private: 238 void _AdjustColors(); 239 void _AdjustTextColors() const; 240 rgb_color _DesktopTextColor(int32 workspace = -1) const; 241 bool _OnDesktop() const; 242 243 BStringView* _CreateLabel(const char*, const char*); 244 void _UpdateLabel(BStringView*); 245 BStringView* _CreateSubtext(const char*, const char*); 246 void _UpdateSubtext(BStringView*); 247 void _UpdateText(BTextView*); 248 void _CreateDragger(); 249 250 float _BaseWidth(); 251 float _BaseHeight(); 252 253 const char* _GetOSVersion(); 254 const char* _GetRamSize(system_info*); 255 const char* _GetRamUsage(system_info*); 256 const char* _GetUptime(); 257 258 float _UptimeHeight(); 259 260 private: 261 BString fText; 262 rgb_color fDesktopTextColor; 263 264 BStringView* fOSVersionView; 265 BStringView* fMemSizeView; 266 BStringView* fMemUsageView; 267 BTextView* fUptimeView; 268 269 BDragger* fDragger; 270 271 float fCachedBaseWidth; 272 float fCachedMinWidth; 273 float fCachedBaseHeight; 274 float fCachedMinHeight; 275 276 bool fIsReplicant : 1; 277 278 static const uint8 kLabelCount = 5; 279 static const uint8 kSubtextCount = 7; 280 }; 281 282 283 class AboutView : public BView { 284 public: 285 AboutView(); 286 ~AboutView(); 287 288 virtual void AttachedToWindow(); 289 virtual void Pulse(); 290 virtual void MessageReceived(BMessage* message); 291 virtual void MouseDown(BPoint where); 292 293 void AddCopyrightEntry(const char* name, 294 const char* text, 295 const StringVector& licenses, 296 const StringVector& sources, 297 const char* url); 298 void AddCopyrightEntry(const char* name, 299 const char* text, const char* url = NULL); 300 void PickRandomHaiku(); 301 302 private: 303 typedef std::map<std::string, PackageCredit*> PackageCreditMap; 304 305 void _CreateScrollRunner(); 306 LogoView* _CreateLogoView(); 307 SysInfoView* _CreateSysInfoView(); 308 CropView* _CreateCreditsView(); 309 status_t _GetLicensePath(const char* license, 310 BPath& path); 311 void _AddCopyrightsFromAttribute(); 312 void _AddPackageCredit(const PackageCredit& package); 313 void _AddPackageCreditEntries(); 314 315 316 private: 317 LogoView* fLogoView; 318 SysInfoView* fSysInfoView; 319 HyperTextView* fCreditsView; 320 321 bigtime_t fLastActionTime; 322 BMessageRunner* fScrollRunner; 323 324 float fCachedMinWidth; 325 float fCachedMinHeight; 326 327 PackageCreditMap fPackageCredits; 328 329 private: 330 rgb_color fTextColor; 331 rgb_color fLinkColor; 332 rgb_color fHaikuOrangeColor; 333 rgb_color fHaikuGreenColor; 334 rgb_color fHaikuYellowColor; 335 rgb_color fBeOSRedColor; 336 rgb_color fBeOSBlueColor; 337 }; 338 339 340 // #pragma mark - AboutApp 341 342 343 AboutApp::AboutApp() 344 : 345 BApplication(kSignature) 346 { 347 B_TRANSLATE_MARK_SYSTEM_NAME_VOID("AboutSystem"); 348 349 AboutWindow* window = new(std::nothrow) AboutWindow(); 350 if (window != NULL) 351 window->Show(); 352 } 353 354 355 void 356 AboutApp::MessageReceived(BMessage* message) 357 { 358 switch (message->what) { 359 case B_SILENT_RELAUNCH: 360 WindowAt(0)->Activate(); 361 break; 362 } 363 364 BApplication::MessageReceived(message); 365 } 366 367 368 // #pragma mark - AboutWindow 369 370 371 AboutWindow::AboutWindow() 372 : 373 BWindow(BRect(0, 0, kWindowWidth, kWindowHeight), 374 B_TRANSLATE("About this system"), B_TITLED_WINDOW, 375 B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_ZOOMABLE) 376 { 377 SetLayout(new BGroupLayout(B_VERTICAL, 0)); 378 379 fAboutView = new AboutView(); 380 AddChild(fAboutView); 381 382 CenterOnScreen(); 383 } 384 385 386 bool 387 AboutWindow::QuitRequested() 388 { 389 be_app->PostMessage(B_QUIT_REQUESTED); 390 return true; 391 } 392 393 394 #undef B_TRANSLATION_CONTEXT 395 #define B_TRANSLATION_CONTEXT "AboutView" 396 397 398 // #pragma mark - LogoView 399 400 401 LogoView::LogoView() 402 : 403 BView("logo", B_WILL_DRAW), 404 fLogo(BTranslationUtils::GetBitmap(B_PNG_FORMAT, "logo.png")) 405 { 406 // Set view color to panel background color when fLogo is NULL 407 // to prevent a white pixel from being drawn. 408 if (fLogo != NULL) 409 SetViewColor(255, 255, 255); 410 else 411 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 412 } 413 414 415 LogoView::~LogoView() 416 { 417 delete fLogo; 418 } 419 420 421 BSize 422 LogoView::MinSize() 423 { 424 if (fLogo == NULL) 425 return BSize(0, 0); 426 427 return BSize(fLogo->Bounds().Width(), fLogo->Bounds().Height()); 428 } 429 430 431 BSize 432 LogoView::MaxSize() 433 { 434 if (fLogo == NULL) 435 return BSize(0, 0); 436 437 return BSize(B_SIZE_UNLIMITED, fLogo->Bounds().Height()); 438 } 439 440 441 void 442 LogoView::Draw(BRect updateRect) 443 { 444 if (fLogo == NULL) 445 return; 446 447 DrawBitmap(fLogo, BPoint((Bounds().Width() - fLogo->Bounds().Width()) / 2, 0)); 448 } 449 450 451 // #pragma mark - CropView 452 453 454 CropView::CropView(BView* target, int32 left, int32 top, int32 right, 455 int32 bottom) 456 : 457 BView("crop view", 0), 458 fTarget(target), 459 fCropLeft(left), 460 fCropTop(top), 461 fCropRight(right), 462 fCropBottom(bottom) 463 { 464 AddChild(target); 465 } 466 467 468 CropView::~CropView() 469 { 470 } 471 472 473 BSize 474 CropView::MinSize() 475 { 476 if (fTarget == NULL) 477 return BSize(); 478 479 BSize size = fTarget->MinSize(); 480 if (size.width != B_SIZE_UNSET) 481 size.width -= fCropLeft + fCropRight; 482 if (size.height != B_SIZE_UNSET) 483 size.height -= fCropTop + fCropBottom; 484 485 return size; 486 } 487 488 489 BSize 490 CropView::MaxSize() 491 { 492 if (fTarget == NULL) 493 return BSize(); 494 495 BSize size = fTarget->MaxSize(); 496 if (size.width != B_SIZE_UNSET) 497 size.width -= fCropLeft + fCropRight; 498 if (size.height != B_SIZE_UNSET) 499 size.height -= fCropTop + fCropBottom; 500 501 return size; 502 } 503 504 505 void 506 CropView::DoLayout() 507 { 508 BView::DoLayout(); 509 510 if (fTarget == NULL) 511 return; 512 513 fTarget->MoveTo(-fCropLeft, -fCropTop); 514 fTarget->ResizeTo(Bounds().Width() + fCropLeft + fCropRight, 515 Bounds().Height() + fCropTop + fCropBottom); 516 } 517 518 519 // #pragma mark - SysInfoView 520 521 522 SysInfoView::SysInfoView() 523 : 524 BView("AboutSystem", B_WILL_DRAW | B_PULSE_NEEDED), 525 fOSVersionView(NULL), 526 fMemSizeView(NULL), 527 fMemUsageView(NULL), 528 fUptimeView(NULL), 529 fDragger(NULL), 530 fCachedBaseWidth(kSysInfoMinWidth), 531 fCachedMinWidth(kSysInfoMinWidth), 532 fCachedBaseHeight(kSysInfoMinHeight), 533 fCachedMinHeight(kSysInfoMinHeight), 534 fIsReplicant(false) 535 { 536 // Begin construction of system information controls. 537 system_info sysInfo; 538 get_system_info(&sysInfo); 539 540 // Create all the various labels for system infomation. 541 542 /* labels */ 543 544 // OS Version 545 BStringView* osLabel = _CreateLabel("oslabel", B_TRANSLATE("Version:")); 546 fOSVersionView = _CreateSubtext("ostext", _GetOSVersion()); 547 548 // CPU count 549 static BStringFormat format(B_TRANSLATE_COMMENT( 550 "{0, plural, one{Processor:} other{# Processors:}}", 551 "\"Processor:\" or \"2 Processors:\"")); 552 BString processorLabel; 553 format.Format(processorLabel, sysInfo.cpu_count); 554 BStringView* cpuLabel = _CreateLabel("cpulabel", processorLabel.String()); 555 556 // Memory 557 BStringView* memoryLabel = _CreateLabel("memlabel", B_TRANSLATE("Memory:")); 558 559 // Kernel 560 BStringView* kernelLabel = _CreateLabel("kernellabel", B_TRANSLATE("Kernel:")); 561 562 // Time running 563 BStringView* uptimeLabel = _CreateLabel("uptimelabel", B_TRANSLATE("Time running:")); 564 565 // x86_gcc2 or x86_64 566 BStringView* abiText = _CreateSubtext("abitext", B_HAIKU_ABI_NAME); 567 568 // CPU count, type and clock speed 569 uint32 topologyNodeCount = 0; 570 cpu_topology_node_info* topology = NULL; 571 get_cpu_topology_info(NULL, &topologyNodeCount); 572 if (topologyNodeCount != 0) 573 topology = new cpu_topology_node_info[topologyNodeCount]; 574 get_cpu_topology_info(topology, &topologyNodeCount); 575 576 enum cpu_platform platform = B_CPU_UNKNOWN; 577 enum cpu_vendor cpuVendor = B_CPU_VENDOR_UNKNOWN; 578 uint32 cpuModel = 0; 579 for (uint32 i = 0; i < topologyNodeCount; i++) { 580 switch (topology[i].type) { 581 case B_TOPOLOGY_ROOT: 582 platform = topology[i].data.root.platform; 583 break; 584 585 case B_TOPOLOGY_PACKAGE: 586 cpuVendor = topology[i].data.package.vendor; 587 break; 588 589 case B_TOPOLOGY_CORE: 590 cpuModel = topology[i].data.core.model; 591 break; 592 593 default: 594 break; 595 } 596 } 597 598 delete[] topology; 599 600 BString cpuType; 601 cpuType << get_cpu_vendor_string(cpuVendor) << " " 602 << get_cpu_model_string(platform, cpuVendor, cpuModel); 603 BStringView* cpuText = _CreateSubtext("cputext", cpuType.String()); 604 605 BString clockSpeed; 606 int32 frequency = get_rounded_cpu_speed(); 607 if (frequency < 1000) 608 clockSpeed.SetToFormat(B_TRANSLATE("%ld MHz"), frequency); 609 else 610 clockSpeed.SetToFormat(B_TRANSLATE("%.2f GHz"), frequency / 1000.0f); 611 612 BStringView* frequencyText = _CreateSubtext("frequencytext", clockSpeed); 613 614 // Memory size and usage 615 fMemSizeView = _CreateSubtext("ramsizetext", _GetRamSize(&sysInfo)); 616 fMemUsageView = _CreateSubtext("ramusagetext", _GetRamUsage(&sysInfo)); 617 618 // Kernel build time/date 619 BString kernelTimeDate; 620 kernelTimeDate << sysInfo.kernel_build_date << " " 621 << sysInfo.kernel_build_time; 622 BString buildTimeDate; 623 624 time_t buildTimeDateStamp = parsedate(kernelTimeDate, -1); 625 if (buildTimeDateStamp > 0) { 626 if (BDateTimeFormat().Format(buildTimeDate, buildTimeDateStamp, 627 B_LONG_DATE_FORMAT, B_MEDIUM_TIME_FORMAT) != B_OK) 628 buildTimeDate.SetTo(kernelTimeDate); 629 } else 630 buildTimeDate.SetTo(kernelTimeDate); 631 632 BStringView* kernelText = _CreateSubtext("kerneltext", buildTimeDate.String()); 633 634 // Uptime 635 fUptimeView = new BTextView("uptimetext"); 636 fUptimeView->SetText(_GetUptime()); 637 _UpdateText(fUptimeView); 638 639 /* layout */ 640 641 const float offset = be_control_look->DefaultLabelSpacing(); 642 const float inset = offset; 643 644 SetLayout(new BGroupLayout(B_VERTICAL, 0)); 645 BLayoutBuilder::Group<>((BGroupLayout*)GetLayout()) 646 // Version: 647 .Add(osLabel) 648 .Add(fOSVersionView) 649 .Add(abiText) 650 .AddStrut(offset) 651 // Processors: 652 .Add(cpuLabel) 653 .Add(cpuText) 654 .Add(frequencyText) 655 .AddStrut(offset) 656 // Memory: 657 .Add(memoryLabel) 658 .Add(fMemSizeView) 659 .Add(fMemUsageView) 660 .AddStrut(offset) 661 // Kernel: 662 .Add(kernelLabel) 663 .Add(kernelText) 664 .AddStrut(offset) 665 // Time running: 666 .Add(uptimeLabel) 667 .Add(fUptimeView) 668 .AddGlue() 669 .SetInsets(inset) 670 .End(); 671 672 _CreateDragger(); 673 } 674 675 676 SysInfoView::SysInfoView(BMessage* archive) 677 : 678 BView(archive), 679 fOSVersionView(NULL), 680 fMemSizeView(NULL), 681 fMemUsageView(NULL), 682 fUptimeView(NULL), 683 fDragger(NULL), 684 fCachedBaseWidth(kSysInfoMinWidth), 685 fCachedMinWidth(kSysInfoMinWidth), 686 fCachedBaseHeight(kSysInfoMinHeight), 687 fCachedMinHeight(kSysInfoMinHeight), 688 fIsReplicant(true) 689 { 690 BLayout* layout = GetLayout(); 691 int32 itemCount = layout->CountItems() - 1; 692 // leave out dragger 693 694 for (int32 index = 0; index < itemCount; index++) { 695 BView* view = layout->ItemAt(index)->View(); 696 if (view == NULL) 697 continue; 698 699 BString name(view->Name()); 700 if (name == "uptimetext") { 701 fUptimeView = dynamic_cast<BTextView*>(view); 702 _UpdateText(fUptimeView); 703 } else if (name.IEndsWith("text")) { 704 _UpdateSubtext(dynamic_cast<BStringView*>(view)); 705 if (name == "ostext") 706 fOSVersionView = dynamic_cast<BStringView*>(view); 707 else if (name == "ramsizetext") 708 fMemSizeView = dynamic_cast<BStringView*>(view); 709 else if (name == "ramusagetext") 710 fMemUsageView = dynamic_cast<BStringView*>(view); 711 } else if (name.IEndsWith("label")) 712 _UpdateLabel(dynamic_cast<BStringView*>(view)); 713 } 714 715 // This might have changed after an update/reboot cycle; 716 fOSVersionView->SetText(_GetOSVersion()); 717 718 fDragger = dynamic_cast<BDragger*>(ChildAt(0)); 719 } 720 721 722 SysInfoView::~SysInfoView() 723 { 724 } 725 726 727 status_t 728 SysInfoView::Archive(BMessage* archive, bool deep) const 729 { 730 // record inherited class members 731 status_t result = BView::Archive(archive, deep); 732 733 // record app signature for replicant add-on loading 734 if (result == B_OK) 735 result = archive->AddString("add_on", kSignature); 736 737 // record class last 738 if (result == B_OK) 739 result = archive->AddString("class", "SysInfoView"); 740 741 return result; 742 } 743 744 745 BArchivable* 746 SysInfoView::Instantiate(BMessage* archive) 747 { 748 if (!validate_instantiation(archive, "SysInfoView")) 749 return NULL; 750 751 return new SysInfoView(archive); 752 } 753 754 755 void 756 SysInfoView::AttachedToWindow() 757 { 758 BView::AttachedToWindow(); 759 760 Window()->SetPulseRate(500000); 761 DoLayout(); 762 } 763 764 765 void 766 SysInfoView::AllAttached() 767 { 768 BView::AllAttached(); 769 770 if (fIsReplicant) { 771 CacheInitialSize(); 772 // if replicant the parent view doesn't do this for us 773 fDesktopTextColor = _DesktopTextColor(); 774 } 775 776 // Update colors here to override system colors for replicant, 777 // this works when the view is in AboutView too. 778 _AdjustColors(); 779 } 780 781 782 void 783 SysInfoView::CacheInitialSize() 784 { 785 fCachedBaseWidth = _BaseWidth(); 786 // memory size is too wide in Greek, account for this here 787 float insets = be_control_look->DefaultLabelSpacing() * 2; 788 fCachedMinWidth = ceilf(std::max(fCachedBaseWidth, 789 fMemSizeView->StringWidth(fMemSizeView->Text()) + insets)); 790 791 // width is fixed, height can grow in Pulse() 792 fCachedBaseHeight = _BaseHeight(); 793 794 // determine initial line count using current font 795 float lineCount = ceilf(be_plain_font->StringWidth(fUptimeView->Text()) 796 / (fCachedMinWidth - insets)); 797 float uptimeHeight = fUptimeView->LineHeight(0) * lineCount; 798 fCachedMinHeight = fCachedBaseHeight + uptimeHeight; 799 800 // set view size 801 SetExplicitMinSize(BSize(fCachedMinWidth, B_SIZE_UNSET)); 802 SetExplicitMaxSize(BSize(fCachedMinWidth, fCachedMinHeight)); 803 fUptimeView->SetExplicitMaxSize(BSize(fCachedMinWidth - insets, 804 uptimeHeight)); 805 } 806 807 808 void 809 SysInfoView::Draw(BRect updateRect) 810 { 811 BView::Draw(updateRect); 812 813 if (_OnDesktop()) { 814 // stroke a line around the view 815 SetHighColor(fDesktopTextColor); 816 StrokeRect(Bounds()); 817 } 818 } 819 820 821 void 822 SysInfoView::MessageReceived(BMessage* message) 823 { 824 switch (message->what) { 825 case B_COLORS_UPDATED: 826 { 827 if (_OnDesktop()) 828 break; 829 830 if (message->HasColor(ui_color_name(B_PANEL_TEXT_COLOR))) { 831 _AdjustTextColors(); 832 Invalidate(); 833 } 834 835 break; 836 } 837 838 case B_WORKSPACE_ACTIVATED: 839 { 840 if (!_OnDesktop()) 841 break; 842 843 bool active; 844 int32 workspace; 845 if (message->FindBool("active", &active) == B_OK && active 846 && message->FindInt32("workspace", &workspace) == B_OK) { 847 BLayout* layout = GetLayout(); 848 int32 itemCount = layout->CountItems() - 2; 849 // leave out dragger and uptime 850 851 fDesktopTextColor = _DesktopTextColor(workspace); 852 SetHighColor(fDesktopTextColor); 853 854 for (int32 index = 0; index < itemCount; index++) { 855 BView* view = layout->ItemAt(index)->View(); 856 if (view == NULL) 857 continue; 858 859 view->SetDrawingMode(B_OP_ALPHA); 860 view->SetHighColor(fDesktopTextColor); 861 } 862 863 fUptimeView->SetDrawingMode(B_OP_ALPHA); 864 fUptimeView->SetFontAndColor(NULL, 0, &fDesktopTextColor); 865 866 Invalidate(); 867 } 868 869 break; 870 } 871 872 default: 873 BView::MessageReceived(message); 874 break; 875 } 876 } 877 878 879 void 880 SysInfoView::Pulse() 881 { 882 system_info sysInfo; 883 get_system_info(&sysInfo); 884 885 fMemUsageView->SetText(_GetRamUsage(&sysInfo)); 886 fUptimeView->SetText(_GetUptime()); 887 888 float newHeight = fCachedBaseHeight + _UptimeHeight(); 889 float difference = newHeight - fCachedMinHeight; 890 if (difference != 0) { 891 if (_OnDesktop()) { 892 // move view to keep the bottom in place 893 // so that the dragger is not pushed off screen 894 ResizeBy(0, difference); 895 MoveBy(0, -difference); 896 Invalidate(); 897 } 898 fCachedMinHeight = newHeight; 899 } 900 901 SetExplicitMinSize(BSize(fCachedMinWidth, B_SIZE_UNSET)); 902 SetExplicitMaxSize(BSize(fCachedMinWidth, fCachedMinHeight)); 903 } 904 905 906 void 907 SysInfoView::_AdjustColors() 908 { 909 if (_OnDesktop()) { 910 // SetColor 911 SetFlags(Flags() | B_TRANSPARENT_BACKGROUND); 912 SetDrawingMode(B_OP_ALPHA); 913 914 SetViewColor(B_TRANSPARENT_COLOR); 915 SetLowColor(B_TRANSPARENT_COLOR); 916 SetHighColor(fDesktopTextColor); 917 } else { 918 // SetUIColor 919 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 920 SetLowUIColor(B_PANEL_BACKGROUND_COLOR); 921 SetHighUIColor(B_PANEL_TEXT_COLOR); 922 } 923 924 _AdjustTextColors(); 925 Invalidate(); 926 } 927 928 929 void 930 SysInfoView::_AdjustTextColors() const 931 { 932 BLayout* layout = GetLayout(); 933 int32 itemCount = layout->CountItems() - 2; 934 // leave out dragger and uptime 935 936 if (_OnDesktop()) { 937 // SetColor 938 for (int32 index = 0; index < itemCount; index++) { 939 BView* view = layout->ItemAt(index)->View(); 940 if (view == NULL) 941 continue; 942 943 view->SetFlags(view->Flags() | B_TRANSPARENT_BACKGROUND); 944 view->SetDrawingMode(B_OP_ALPHA); 945 946 view->SetViewColor(B_TRANSPARENT_COLOR); 947 view->SetLowColor(blend_color(B_TRANSPARENT_COLOR, 948 fDesktopTextColor, 192)); 949 view->SetHighColor(fDesktopTextColor); 950 } 951 952 fUptimeView->SetFlags(fUptimeView->Flags() | B_TRANSPARENT_BACKGROUND); 953 fUptimeView->SetDrawingMode(B_OP_ALPHA); 954 955 fUptimeView->SetViewColor(B_TRANSPARENT_COLOR); 956 fUptimeView->SetLowColor(blend_color(B_TRANSPARENT_COLOR, 957 fDesktopTextColor, 192)); 958 fUptimeView->SetFontAndColor(NULL, 0, &fDesktopTextColor); 959 } else { 960 // SetUIColor 961 for (int32 index = 0; index < itemCount; index++) { 962 BView* view = layout->ItemAt(index)->View(); 963 if (view == NULL) 964 continue; 965 966 view->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 967 view->SetLowUIColor(B_PANEL_BACKGROUND_COLOR); 968 view->SetHighUIColor(B_PANEL_TEXT_COLOR); 969 } 970 971 fUptimeView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 972 fUptimeView->SetLowUIColor(B_PANEL_BACKGROUND_COLOR); 973 rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR); 974 fUptimeView->SetFontAndColor(NULL, 0, &textColor); 975 } 976 } 977 978 979 rgb_color 980 SysInfoView::_DesktopTextColor(int32 workspace) const 981 { 982 // set text color to black or white depending on desktop background color 983 rgb_color textColor; 984 BScreen screen(Window()); 985 if (workspace < 0) 986 workspace = current_workspace(); 987 988 rgb_color viewColor = screen.DesktopColor(workspace); 989 int viewBrightness = BPrivate::perceptual_brightness(viewColor); 990 textColor.blue = textColor.green = textColor.red = viewBrightness > 127 991 ? 0 : 255; 992 textColor.alpha = 255; 993 994 return textColor; 995 } 996 997 998 bool 999 SysInfoView::_OnDesktop() const 1000 { 1001 return fIsReplicant && Window() != NULL 1002 && Window()->Look() == kDesktopWindowLook 1003 && Window()->Feel() == kDesktopWindowFeel; 1004 } 1005 1006 1007 BStringView* 1008 SysInfoView::_CreateLabel(const char* name, const char* text) 1009 { 1010 BStringView* label = new BStringView(name, text); 1011 _UpdateLabel(label); 1012 1013 return label; 1014 } 1015 1016 1017 void 1018 SysInfoView::_UpdateLabel(BStringView* label) 1019 { 1020 label->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 1021 B_ALIGN_VERTICAL_UNSET)); 1022 label->SetFont(be_bold_font, B_FONT_FAMILY_AND_STYLE); 1023 } 1024 1025 1026 BStringView* 1027 SysInfoView::_CreateSubtext(const char* name, const char* text) 1028 { 1029 BStringView* subtext = new BStringView(name, text); 1030 _UpdateSubtext(subtext); 1031 1032 return subtext; 1033 } 1034 1035 1036 void 1037 SysInfoView::_UpdateSubtext(BStringView* subtext) 1038 { 1039 subtext->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 1040 B_ALIGN_VERTICAL_UNSET)); 1041 subtext->SetFont(be_plain_font, B_FONT_FAMILY_AND_STYLE); 1042 } 1043 1044 1045 void 1046 SysInfoView::_UpdateText(BTextView* textView) 1047 { 1048 textView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP)); 1049 textView->SetFontAndColor(be_plain_font, B_FONT_FAMILY_AND_STYLE); 1050 textView->SetColorSpace(B_RGBA32); 1051 textView->MakeResizable(false); 1052 textView->MakeEditable(false); 1053 textView->MakeSelectable(false); 1054 textView->SetWordWrap(true); 1055 textView->SetDoesUndo(false); 1056 textView->SetInsets(0, 0, 0, 0); 1057 } 1058 1059 1060 void 1061 SysInfoView::_CreateDragger() 1062 { 1063 // create replicant dragger and add it as the new child 0 1064 fDragger = new BDragger(BRect(0, 0, 7, 7), this, 1065 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 1066 BPopUpMenu* popUp = new BPopUpMenu("Shelf", false, false, B_ITEMS_IN_COLUMN); 1067 popUp->AddItem(new BMenuItem(B_TRANSLATE("Remove replicant"), 1068 new BMessage(kDeleteReplicant))); 1069 fDragger->SetPopUp(popUp); 1070 AddChild(fDragger, ChildAt(0)); 1071 } 1072 1073 1074 float 1075 SysInfoView::_BaseWidth() 1076 { 1077 // based on font size 1078 return be_plain_font->StringWidth("M") * 24; 1079 } 1080 1081 1082 float 1083 SysInfoView::_BaseHeight() 1084 { 1085 // based on line heights 1086 font_height plainFH; 1087 be_plain_font->GetHeight(&plainFH); 1088 font_height boldFH; 1089 be_bold_font->GetHeight(&boldFH); 1090 1091 return ceilf(((boldFH.ascent + boldFH.descent) * kLabelCount 1092 + (plainFH.ascent + plainFH.descent) * (kSubtextCount + 1) // extra for fUptimeView 1093 + be_control_look->DefaultLabelSpacing() * kLabelCount)); 1094 } 1095 1096 1097 const char* 1098 SysInfoView::_GetOSVersion() 1099 { 1100 BString osVersion; 1101 1102 // the version is stored in the BEOS:APP_VERSION attribute of libbe.so 1103 BPath path; 1104 if (find_directory(B_BEOS_LIB_DIRECTORY, &path) == B_OK) { 1105 path.Append("libbe.so"); 1106 1107 BAppFileInfo appFileInfo; 1108 version_info versionInfo; 1109 BFile file; 1110 if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK 1111 && appFileInfo.SetTo(&file) == B_OK 1112 && appFileInfo.GetVersionInfo(&versionInfo, 1113 B_APP_VERSION_KIND) == B_OK 1114 && versionInfo.short_info[0] != '\0') 1115 osVersion = versionInfo.short_info; 1116 } 1117 1118 if (osVersion.IsEmpty()) 1119 osVersion = B_TRANSLATE("Unknown"); 1120 1121 // add system revision to os version 1122 const char* hrev = __get_haiku_revision(); 1123 if (hrev != NULL) 1124 osVersion << " (" << B_TRANSLATE("Revision") << " " << hrev << ")"; 1125 1126 return osVersion.String(); 1127 } 1128 1129 1130 const char* 1131 SysInfoView::_GetRamSize(system_info* sysInfo) 1132 { 1133 int inaccessibleMemory = ignored_pages(sysInfo); 1134 1135 if (inaccessibleMemory <= 0) 1136 fText.SetToFormat(B_TRANSLATE("%d MiB total"), max_pages(sysInfo)); 1137 else { 1138 BString temp; 1139 fText = B_TRANSLATE("%total MiB total, %inaccessible MiB inaccessible"); 1140 temp << max_and_ignored_pages(sysInfo); 1141 fText.ReplaceFirst("%total", temp); 1142 temp.SetTo(""); 1143 temp << inaccessibleMemory; 1144 fText.ReplaceFirst("%inaccessible", temp); 1145 } 1146 1147 return fText.String(); 1148 } 1149 1150 1151 const char* 1152 SysInfoView::_GetRamUsage(system_info* sysInfo) 1153 { 1154 fText.SetToFormat(B_TRANSLATE("%d MiB used (%d%%)"), used_pages(sysInfo), 1155 (int)(100 * sysInfo->used_pages / sysInfo->max_pages)); 1156 1157 return fText.String(); 1158 } 1159 1160 1161 const char* 1162 SysInfoView::_GetUptime() 1163 { 1164 BDurationFormat formatter; 1165 BString uptimeText; 1166 1167 bigtime_t uptime = system_time(); 1168 bigtime_t now = (bigtime_t)time(NULL) * 1000000; 1169 formatter.Format(uptimeText, now - uptime, now); 1170 1171 return uptimeText.String(); 1172 } 1173 1174 1175 float 1176 SysInfoView::_UptimeHeight() 1177 { 1178 return fUptimeView->LineHeight(0) * fUptimeView->CountLines(); 1179 } 1180 1181 1182 // #pragma mark - AboutView 1183 1184 1185 AboutView::AboutView() 1186 : 1187 BView("aboutview", B_WILL_DRAW | B_PULSE_NEEDED), 1188 fLogoView(NULL), 1189 fSysInfoView(NULL), 1190 fCreditsView(NULL), 1191 fLastActionTime(system_time()), 1192 fScrollRunner(NULL), 1193 fCachedMinWidth(kSysInfoMinWidth), 1194 fCachedMinHeight(kSysInfoMinHeight) 1195 { 1196 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 1197 1198 // Assign the colors, sadly this does not respect live color updates 1199 fTextColor = ui_color(B_DOCUMENT_TEXT_COLOR); 1200 fLinkColor = ui_color(B_LINK_TEXT_COLOR); 1201 fHaikuOrangeColor = mix_color(fTextColor, kIdealHaikuOrange, 191); 1202 fHaikuGreenColor = mix_color(fTextColor, kIdealHaikuGreen, 191); 1203 fHaikuYellowColor = mix_color(fTextColor, kIdealHaikuYellow, 191); 1204 fBeOSRedColor = mix_color(fTextColor, kIdealBeOSRed, 191); 1205 fBeOSBlueColor = mix_color(fTextColor, kIdealBeOSBlue, 191); 1206 1207 SetLayout(new BGroupLayout(B_HORIZONTAL, 0)); 1208 BLayoutBuilder::Group<>((BGroupLayout*)GetLayout()) 1209 .AddGroup(B_VERTICAL, 0) 1210 .Add(_CreateLogoView()) 1211 .Add(_CreateSysInfoView()) 1212 .AddGlue() 1213 .End() 1214 .Add(_CreateCreditsView()) 1215 .End(); 1216 } 1217 1218 1219 AboutView::~AboutView() 1220 { 1221 for (PackageCreditMap::iterator it = fPackageCredits.begin(); 1222 it != fPackageCredits.end(); it++) { 1223 1224 delete it->second; 1225 } 1226 1227 delete fScrollRunner; 1228 delete fCreditsView; 1229 delete fSysInfoView; 1230 delete fLogoView; 1231 } 1232 1233 1234 void 1235 AboutView::AttachedToWindow() 1236 { 1237 BView::AttachedToWindow(); 1238 1239 fSysInfoView->CacheInitialSize(); 1240 1241 float insets = be_control_look->DefaultLabelSpacing() * 2; 1242 float infoWidth = fSysInfoView->MinWidth() + insets; 1243 float creditsWidth = roundf(infoWidth * 1.25f); 1244 fCachedMinWidth = std::max(infoWidth + creditsWidth, 1245 fCachedMinWidth); 1246 // set once 1247 float logoViewHeight = fLogoView->Bounds().Height(); 1248 float sysInfoViewHeight = fSysInfoView->MinHeight() + insets; 1249 fCachedMinHeight = std::max(logoViewHeight + sysInfoViewHeight, 1250 fCachedMinHeight); 1251 // updated when height changes in pulse 1252 fCreditsView->SetExplicitMinSize(BSize(creditsWidth, fCachedMinHeight)); 1253 // set credits min height to logo height + sys-info height 1254 1255 SetEventMask(B_POINTER_EVENTS); 1256 DoLayout(); 1257 } 1258 1259 1260 void 1261 AboutView::MouseDown(BPoint where) 1262 { 1263 BRect rect(92, 26, 105, 31); 1264 if (rect.Contains(where)) 1265 BMessenger(this).SendMessage('eegg'); 1266 1267 if (Bounds().Contains(where)) { 1268 fLastActionTime = system_time(); 1269 delete fScrollRunner; 1270 fScrollRunner = NULL; 1271 } 1272 } 1273 1274 1275 void 1276 AboutView::Pulse() 1277 { 1278 // sys-info handles height because it may be a replicant 1279 float insets = be_control_look->DefaultLabelSpacing() * 2; 1280 float logoViewHeight = fLogoView->Bounds().Height(); 1281 float sysInfoViewHeight = fSysInfoView->MinHeight() + insets; 1282 float newHeight = logoViewHeight + sysInfoViewHeight; 1283 if (newHeight != fCachedMinHeight) { 1284 fCreditsView->SetExplicitMinSize(BSize( 1285 fCachedMinWidth - (fSysInfoView->MinWidth() + insets), newHeight)); 1286 fCachedMinHeight = newHeight; 1287 } 1288 1289 if (fScrollRunner == NULL && system_time() > fLastActionTime + 10000000) 1290 _CreateScrollRunner(); 1291 } 1292 1293 1294 void 1295 AboutView::MessageReceived(BMessage* message) 1296 { 1297 switch (message->what) { 1298 case kMsgScrollCreditsView: 1299 { 1300 BScrollBar* scrollBar = fCreditsView->ScrollBar(B_VERTICAL); 1301 if (scrollBar == NULL) 1302 break; 1303 float min; 1304 float max; 1305 scrollBar->GetRange(&min, &max); 1306 if (scrollBar->Value() < max) 1307 fCreditsView->ScrollBy(0, 1); 1308 1309 break; 1310 } 1311 1312 case 'eegg': 1313 { 1314 printf("Easter egg\n"); 1315 PickRandomHaiku(); 1316 break; 1317 } 1318 1319 default: 1320 BView::MessageReceived(message); 1321 break; 1322 } 1323 } 1324 1325 1326 void 1327 AboutView::AddCopyrightEntry(const char* name, const char* text, 1328 const char* url) 1329 { 1330 AddCopyrightEntry(name, text, StringVector(), StringVector(), url); 1331 } 1332 1333 1334 void 1335 AboutView::AddCopyrightEntry(const char* name, const char* text, 1336 const StringVector& licenses, const StringVector& sources, 1337 const char* url) 1338 { 1339 BFont font(be_bold_font); 1340 //font.SetSize(be_bold_font->Size()); 1341 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 1342 1343 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuYellowColor); 1344 fCreditsView->Insert(name); 1345 fCreditsView->Insert("\n"); 1346 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1347 fCreditsView->Insert(text); 1348 fCreditsView->Insert("\n"); 1349 1350 if (licenses.CountStrings() > 0) { 1351 if (licenses.CountStrings() > 1) 1352 fCreditsView->Insert(B_TRANSLATE("Licenses: ")); 1353 else 1354 fCreditsView->Insert(B_TRANSLATE("License: ")); 1355 1356 for (int32 i = 0; i < licenses.CountStrings(); i++) { 1357 const char* license = licenses.StringAt(i); 1358 1359 if (i > 0) 1360 fCreditsView->Insert(", "); 1361 1362 BString licenseName; 1363 BString licenseURL; 1364 parse_named_url(license, licenseName, licenseURL); 1365 1366 BPath licensePath; 1367 if (_GetLicensePath(licenseURL, licensePath) == B_OK) { 1368 fCreditsView->InsertHyperText(B_TRANSLATE_NOCOLLECT(licenseName), 1369 new OpenFileAction(licensePath.Path())); 1370 } else 1371 fCreditsView->Insert(licenseName); 1372 } 1373 1374 fCreditsView->Insert("\n"); 1375 } 1376 1377 if (sources.CountStrings() > 0) { 1378 fCreditsView->Insert(B_TRANSLATE("Source Code: ")); 1379 1380 for (int32 i = 0; i < sources.CountStrings(); i++) { 1381 const char* source = sources.StringAt(i); 1382 1383 if (i > 0) 1384 fCreditsView->Insert(", "); 1385 1386 BString urlName; 1387 BString urlAddress; 1388 parse_named_url(source, urlName, urlAddress); 1389 1390 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, 1391 &fLinkColor); 1392 fCreditsView->InsertHyperText(urlName, 1393 new URLAction(urlAddress)); 1394 } 1395 1396 fCreditsView->Insert("\n"); 1397 } 1398 1399 if (url) { 1400 BString urlName; 1401 BString urlAddress; 1402 parse_named_url(url, urlName, urlAddress); 1403 1404 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, 1405 &fLinkColor); 1406 fCreditsView->InsertHyperText(urlName, 1407 new URLAction(urlAddress)); 1408 fCreditsView->Insert("\n"); 1409 } 1410 fCreditsView->Insert("\n"); 1411 } 1412 1413 1414 void 1415 AboutView::PickRandomHaiku() 1416 { 1417 BPath path; 1418 if (find_directory(B_SYSTEM_DATA_DIRECTORY, &path) != B_OK) 1419 path = "/system/data"; 1420 path.Append("fortunes"); 1421 path.Append("Haiku"); 1422 1423 BFile fortunes(path.Path(), B_READ_ONLY); 1424 struct stat st; 1425 if (fortunes.InitCheck() < B_OK) 1426 return; 1427 if (fortunes.GetStat(&st) < B_OK) 1428 return; 1429 1430 char* buff = (char*)malloc((size_t)st.st_size + 1); 1431 if (buff == NULL) 1432 return; 1433 1434 buff[(size_t)st.st_size] = '\0'; 1435 BList haikuList; 1436 if (fortunes.Read(buff, (size_t)st.st_size) == (ssize_t)st.st_size) { 1437 char* p = buff; 1438 while (p && *p) { 1439 char* e = strchr(p, '%'); 1440 BString* s = new BString(p, e ? (e - p) : -1); 1441 haikuList.AddItem(s); 1442 p = e; 1443 if (p && (*p == '%')) 1444 p++; 1445 if (p && (*p == '\n')) 1446 p++; 1447 } 1448 } 1449 free(buff); 1450 1451 if (haikuList.CountItems() < 1) 1452 return; 1453 1454 BString* s = (BString*)haikuList.ItemAt(rand() % haikuList.CountItems()); 1455 BFont font(be_bold_font); 1456 font.SetSize(be_bold_font->Size()); 1457 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 1458 fCreditsView->SelectAll(); 1459 fCreditsView->Delete(); 1460 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fTextColor); 1461 fCreditsView->Insert(s->String()); 1462 fCreditsView->Insert("\n"); 1463 while ((s = (BString*)haikuList.RemoveItem((int32)0))) 1464 delete s; 1465 } 1466 1467 1468 void 1469 AboutView::_CreateScrollRunner() 1470 { 1471 #if 0 1472 BMessage scroll(kMsgScrollCreditsView); 1473 fScrollRunner = new(std::nothrow) BMessageRunner(this, &scroll, 25000, -1); 1474 #endif 1475 } 1476 1477 1478 LogoView* 1479 AboutView::_CreateLogoView() 1480 { 1481 fLogoView = new(std::nothrow) LogoView(); 1482 1483 return fLogoView; 1484 } 1485 1486 1487 SysInfoView* 1488 AboutView::_CreateSysInfoView() 1489 { 1490 fSysInfoView = new(std::nothrow) SysInfoView(); 1491 1492 return fSysInfoView; 1493 } 1494 1495 1496 CropView* 1497 AboutView::_CreateCreditsView() 1498 { 1499 // Begin construction of the credits view 1500 fCreditsView = new HyperTextView("credits"); 1501 fCreditsView->SetFlags(fCreditsView->Flags() | B_FRAME_EVENTS); 1502 fCreditsView->SetStylable(true); 1503 fCreditsView->MakeEditable(false); 1504 fCreditsView->SetWordWrap(true); 1505 fCreditsView->SetInsets(5, 5, 5, 5); 1506 fCreditsView->SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR); 1507 1508 BScrollView* creditsScroller = new BScrollView("creditsScroller", 1509 fCreditsView, B_WILL_DRAW | B_FRAME_EVENTS, false, true, 1510 B_PLAIN_BORDER); 1511 1512 // Haiku copyright 1513 BFont font(be_bold_font); 1514 font.SetSize(font.Size() + 4); 1515 1516 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuGreenColor); 1517 fCreditsView->Insert("Haiku\n"); 1518 1519 time_t time = ::time(NULL); 1520 struct tm* tm = localtime(&time); 1521 int32 year = tm->tm_year + 1900; 1522 if (year < 2008) 1523 year = 2008; 1524 BString text; 1525 text.SetToFormat( 1526 B_TRANSLATE(COPYRIGHT_STRING "2001-%" B_PRId32 " The Haiku project. "), 1527 year); 1528 1529 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1530 fCreditsView->Insert(text.String()); 1531 1532 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1533 fCreditsView->Insert(B_TRANSLATE("The copyright to the Haiku code is " 1534 "property of Haiku, Inc. or of the respective authors where expressly " 1535 "noted in the source. Haiku" B_UTF8_REGISTERED 1536 " and the HAIKU logo" B_UTF8_REGISTERED 1537 " are registered trademarks of Haiku, Inc." 1538 "\n\n")); 1539 1540 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fLinkColor); 1541 fCreditsView->InsertHyperText("https://www.haiku-os.org", 1542 new URLAction("https://www.haiku-os.org")); 1543 fCreditsView->Insert("\n\n"); 1544 1545 font.SetSize(be_bold_font->Size()); 1546 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 1547 1548 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuOrangeColor); 1549 fCreditsView->Insert(B_TRANSLATE("Current maintainers:\n")); 1550 1551 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1552 fCreditsView->Insert(kCurrentMaintainers); 1553 1554 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuOrangeColor); 1555 fCreditsView->Insert(B_TRANSLATE("Past maintainers:\n")); 1556 1557 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1558 fCreditsView->Insert(kPastMaintainers); 1559 1560 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuOrangeColor); 1561 fCreditsView->Insert(B_TRANSLATE("Website & marketing:\n")); 1562 1563 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1564 fCreditsView->Insert(kWebsiteTeam); 1565 1566 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuOrangeColor); 1567 fCreditsView->Insert(B_TRANSLATE("Past website & marketing:\n")); 1568 1569 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1570 fCreditsView->Insert(kPastWebsiteTeam); 1571 1572 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuOrangeColor); 1573 fCreditsView->Insert(B_TRANSLATE("Testing and bug triaging:\n")); 1574 1575 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1576 fCreditsView->Insert(kTestingTeam); 1577 1578 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuOrangeColor); 1579 fCreditsView->Insert(B_TRANSLATE("Contributors:\n")); 1580 1581 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1582 fCreditsView->Insert(kContributors); 1583 fCreditsView->Insert( 1584 B_TRANSLATE("\n" B_UTF8_ELLIPSIS 1585 "and probably some more we forgot to mention (sorry!)" 1586 "\n\n")); 1587 1588 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuOrangeColor); 1589 fCreditsView->Insert(B_TRANSLATE("Translations:\n")); 1590 1591 BLanguage* lang; 1592 BString langName; 1593 1594 BList sortedTranslations; 1595 for (uint32 i = 0; i < kNumberOfTranslations; i ++) { 1596 const Translation* translation = &kTranslations[i]; 1597 sortedTranslations.AddItem((void*)translation); 1598 } 1599 sortedTranslations.SortItems(TranslationComparator); 1600 1601 for (uint32 i = 0; i < kNumberOfTranslations; i ++) { 1602 const Translation& translation 1603 = *(const Translation*)sortedTranslations.ItemAt(i); 1604 1605 langName.Truncate(0); 1606 if (BLocaleRoster::Default()->GetLanguage(translation.languageCode, 1607 &lang) == B_OK) { 1608 lang->GetName(langName); 1609 delete lang; 1610 } else { 1611 // We failed to get the localized readable name, 1612 // go with what we have. 1613 langName.Append(translation.languageCode); 1614 } 1615 1616 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuGreenColor); 1617 fCreditsView->Insert("\n"); 1618 fCreditsView->Insert(langName); 1619 fCreditsView->Insert("\n"); 1620 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1621 fCreditsView->Insert(translation.names); 1622 } 1623 1624 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuOrangeColor); 1625 fCreditsView->Insert(B_TRANSLATE("\n\nSpecial thanks to:\n")); 1626 1627 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1628 BString beosCredits(B_TRANSLATE( 1629 "Be Inc. and its developer team, for having created BeOS!\n\n")); 1630 int32 beosOffset = beosCredits.FindFirst("BeOS"); 1631 fCreditsView->Insert(beosCredits.String(), 1632 (beosOffset < 0) ? beosCredits.Length() : beosOffset); 1633 if (beosOffset > -1) { 1634 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fBeOSBlueColor); 1635 fCreditsView->Insert("B"); 1636 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fBeOSRedColor); 1637 fCreditsView->Insert("e"); 1638 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1639 beosCredits.Remove(0, beosOffset + 2); 1640 fCreditsView->Insert(beosCredits.String(), beosCredits.Length()); 1641 } 1642 fCreditsView->Insert( 1643 B_TRANSLATE("Travis Geiselbrecht (and his NewOS kernel)\n")); 1644 fCreditsView->Insert( 1645 B_TRANSLATE("Michael Phipps (project founder)\n\n")); 1646 fCreditsView->Insert( 1647 B_TRANSLATE("The HaikuPorts team\n")); 1648 fCreditsView->Insert( 1649 B_TRANSLATE("The Haikuware team and their bounty program\n")); 1650 fCreditsView->Insert( 1651 B_TRANSLATE("The BeGeistert team\n")); 1652 fCreditsView->Insert( 1653 B_TRANSLATE("Google and their Google Summer of Code and Google Code In " 1654 "programs\n")); 1655 fCreditsView->Insert( 1656 B_TRANSLATE("The University of Auckland and Christof Lutteroth\n\n")); 1657 fCreditsView->Insert( 1658 B_TRANSLATE(B_UTF8_ELLIPSIS "and the many people making donations!\n\n")); 1659 1660 // copyrights for various projects we use 1661 1662 BPath mitPath; 1663 _GetLicensePath("MIT", mitPath); 1664 BPath lgplPath; 1665 _GetLicensePath("GNU LGPL v2.1", lgplPath); 1666 1667 font.SetSize(be_bold_font->Size() + 4); 1668 font.SetFace(B_BOLD_FACE); 1669 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &fHaikuGreenColor); 1670 fCreditsView->Insert(B_TRANSLATE("\nCopyrights\n\n")); 1671 1672 // Haiku license 1673 BString haikuLicense = B_TRANSLATE_COMMENT("The code that is unique to " 1674 "Haiku, especially the kernel and all code that applications may link " 1675 "against, is distributed under the terms of the <MIT license>. " 1676 "Some system libraries contain third party code distributed under the " 1677 "<LGPL license>. You can find the copyrights to third party code below." 1678 "\n\n", "<MIT license> and <LGPL license> aren't variables and can be " 1679 "translated. However, please, don't remove < and > as they're needed " 1680 "as placeholders for proper hypertext functionality."); 1681 int32 licensePart1 = haikuLicense.FindFirst("<"); 1682 int32 licensePart2 = haikuLicense.FindFirst(">"); 1683 int32 licensePart3 = haikuLicense.FindLast("<"); 1684 int32 licensePart4 = haikuLicense.FindLast(">"); 1685 BString part; 1686 haikuLicense.CopyInto(part, 0, licensePart1); 1687 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1688 fCreditsView->Insert(part); 1689 1690 part.Truncate(0); 1691 haikuLicense.CopyInto(part, licensePart1 + 1, licensePart2 - 1 1692 - licensePart1); 1693 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fLinkColor); 1694 fCreditsView->InsertHyperText(part, new OpenFileAction(mitPath.Path())); 1695 1696 part.Truncate(0); 1697 haikuLicense.CopyInto(part, licensePart2 + 1, licensePart3 - 1 1698 - licensePart2); 1699 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1700 fCreditsView->Insert(part); 1701 1702 part.Truncate(0); 1703 haikuLicense.CopyInto(part, licensePart3 + 1, licensePart4 - 1 1704 - licensePart3); 1705 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fLinkColor); 1706 fCreditsView->InsertHyperText(part, new OpenFileAction(lgplPath.Path())); 1707 1708 part.Truncate(0); 1709 haikuLicense.CopyInto(part, licensePart4 + 1, haikuLicense.Length() - 1 1710 - licensePart4); 1711 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &fTextColor); 1712 fCreditsView->Insert(part); 1713 1714 // GNU copyrights 1715 AddCopyrightEntry("The GNU Project", 1716 B_TRANSLATE("Contains software from the GNU Project, " 1717 "released under the GPL and LGPL licenses:\n" 1718 "GNU C Library, " 1719 "GNU coretools, diffutils, findutils, " 1720 "sharutils, gawk, bison, m4, make, " 1721 "wget, ncurses, termcap, " 1722 "Bourne Again Shell.\n" 1723 COPYRIGHT_STRING "The Free Software Foundation."), 1724 StringVector(kLGPLv21, kGPLv2, kGPLv3, NULL), 1725 StringVector(), 1726 "https://www.gnu.org"); 1727 1728 // FreeBSD copyrights 1729 AddCopyrightEntry("The FreeBSD Project", 1730 B_TRANSLATE("Contains software from the FreeBSD Project, " 1731 "released under the BSD license:\n" 1732 "ftpd, ping, telnet, telnetd, traceroute\n" 1733 COPYRIGHT_STRING "1994-2008 The FreeBSD Project. " 1734 "All rights reserved."), 1735 StringVector(kBSDTwoClause, kBSDThreeClause, kBSDFourClause, 1736 NULL), 1737 StringVector(), 1738 "https://www.freebsd.org"); 1739 1740 // FFmpeg copyrights 1741 _AddPackageCredit(PackageCredit("FFmpeg") 1742 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2000-2019 Fabrice " 1743 "Bellard, et al.")) 1744 .SetLicenses(kLGPLv21, kLGPLv2, NULL) 1745 .SetURL("https://www.ffmpeg.org")); 1746 1747 // AGG copyrights 1748 _AddPackageCredit(PackageCredit("AntiGrain Geometry") 1749 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2002-2006 Maxim " 1750 "Shemanarev (McSeem).")) 1751 .SetLicenses("Anti-Grain Geometry", kBSDThreeClause, NULL) 1752 .SetURL("http://www.antigrain.com")); 1753 1754 // FreeType copyrights 1755 _AddPackageCredit(PackageCredit("FreeType2") 1756 .SetCopyrights(B_TRANSLATE(COPYRIGHT_STRING "1996-2002, 2006 " 1757 "David Turner, Robert Wilhelm and Werner Lemberg."), 1758 COPYRIGHT_STRING "2014 The FreeType Project. " 1759 "All rights reserved.", 1760 NULL) 1761 .SetLicense("FreeType") 1762 .SetURL("http://www.freetype.org")); 1763 1764 // Mesa3D (http://www.mesa3d.org) copyrights 1765 _AddPackageCredit(PackageCredit("Mesa") 1766 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1999-2006 Brian Paul. " 1767 "Mesa3D Project. All rights reserved.")) 1768 .SetLicense("MIT") 1769 .SetURL("http://www.mesa3d.org")); 1770 1771 // SGI's GLU implementation copyrights 1772 _AddPackageCredit(PackageCredit("GLU") 1773 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1991-2000 " 1774 "Silicon Graphics, Inc. All rights reserved.")) 1775 .SetLicense("SGI Free B") 1776 .SetURL("http://www.sgi.com/products/software/opengl")); 1777 1778 // GLUT implementation copyrights 1779 _AddPackageCredit(PackageCredit("GLUT") 1780 .SetCopyrights(B_TRANSLATE(COPYRIGHT_STRING "1994-1997 Mark Kilgard. " 1781 "All rights reserved."), 1782 COPYRIGHT_STRING "1997 Be Inc.", 1783 COPYRIGHT_STRING "1999 Jake Hamby.", 1784 NULL) 1785 .SetLicense("MIT") 1786 .SetURL("http://www.opengl.org/resources/libraries/glut")); 1787 1788 // OpenGroup & DEC (BRegion backend) copyright 1789 _AddPackageCredit(PackageCredit("BRegion backend (XFree86)") 1790 .SetCopyrights(COPYRIGHT_STRING "1987-1988, 1998 The Open Group.", 1791 B_TRANSLATE(COPYRIGHT_STRING "1987-1988 Digital Equipment " 1792 "Corporation, Maynard, Massachusetts.\n" 1793 "All rights reserved."), 1794 NULL) 1795 .SetLicenses("OpenGroup", "DEC", NULL) 1796 .SetURL("https://xfree86.org")); 1797 1798 // Bitstream Charter font 1799 _AddPackageCredit(PackageCredit("Bitstream Charter font") 1800 .SetCopyrights(COPYRIGHT_STRING "1989-1992 Bitstream Inc.," 1801 "Cambridge, MA.", 1802 B_TRANSLATE("BITSTREAM CHARTER is a registered trademark of " 1803 "Bitstream Inc."), 1804 NULL) 1805 .SetLicense("Bitstream Charter") 1806 .SetURL("http://www.bitstream.com/")); 1807 1808 // Noto fonts copyright 1809 _AddPackageCredit(PackageCredit("Noto fonts") 1810 .SetCopyrights(B_TRANSLATE(COPYRIGHT_STRING 1811 "2012-2016 Google Internationalization team."), 1812 NULL) 1813 .SetLicense("SIL Open Font Licence v1.1") 1814 .SetURL("http://www.google.com/get/noto/")); 1815 1816 // expat copyrights 1817 _AddPackageCredit(PackageCredit("expat") 1818 .SetCopyrights(B_TRANSLATE(COPYRIGHT_STRING "1998-2000 Thai " 1819 "Open Source Software Center Ltd and Clark Cooper."), 1820 B_TRANSLATE(COPYRIGHT_STRING "2001-2003 Expat maintainers."), 1821 NULL) 1822 .SetLicense("Expat") 1823 .SetURL("http://expat.sourceforge.net")); 1824 1825 // zlib copyrights 1826 _AddPackageCredit(PackageCredit("zlib") 1827 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1995-2004 Jean-loup " 1828 "Gailly and Mark Adler.")) 1829 .SetLicense("Zlib") 1830 .SetURL("http://www.zlib.net")); 1831 1832 // zip copyrights 1833 _AddPackageCredit(PackageCredit("Info-ZIP") 1834 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1990-2002 Info-ZIP. " 1835 "All rights reserved.")) 1836 .SetLicense("Info-ZIP") 1837 .SetURL("http://www.info-zip.org")); 1838 1839 // bzip2 copyrights 1840 _AddPackageCredit(PackageCredit("bzip2") 1841 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1996-2005 Julian R " 1842 "Seward. All rights reserved.")) 1843 .SetLicense(kBSDFourClause) 1844 .SetURL("http://bzip.org")); 1845 1846 // OpenEXR copyrights 1847 _AddPackageCredit(PackageCredit("OpenEXR") 1848 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2002-2014 Industrial " 1849 "Light & Magic, a division of Lucas Digital Ltd. LLC.")) 1850 .SetLicense(kBSDThreeClause) 1851 .SetURL("http://www.openexr.com")); 1852 1853 // acpica copyrights 1854 _AddPackageCredit(PackageCredit("ACPI Component Architecture (ACPICA)") 1855 .SetCopyright(COPYRIGHT_STRING "1999-2018 Intel Corp.") 1856 .SetLicense("Intel (ACPICA)") 1857 .SetURL("https://www.acpica.org")); 1858 1859 // libpng copyrights 1860 _AddPackageCredit(PackageCredit("libpng") 1861 .SetCopyright(COPYRIGHT_STRING "1995-2017 libpng authors") 1862 .SetLicense("LibPNG") 1863 .SetURL("http://www.libpng.org")); 1864 1865 // libjpeg copyrights 1866 _AddPackageCredit(PackageCredit("libjpeg") 1867 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1994-2009, Thomas G. " 1868 "Lane, Guido Vollbeding. This software is based in part on the " 1869 "work of the Independent JPEG Group.")) 1870 .SetLicense("LibJPEG") 1871 .SetURL("http://www.ijg.org")); 1872 1873 // libprint copyrights 1874 _AddPackageCredit(PackageCredit("libprint") 1875 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1999-2000 Y.Takagi. " 1876 "All rights reserved."))); 1877 // TODO: License! 1878 1879 // cortex copyrights 1880 _AddPackageCredit(PackageCredit("Cortex") 1881 .SetCopyright(COPYRIGHT_STRING "1999-2000 Eric Moon.") 1882 .SetLicense(kBSDThreeClause) 1883 .SetURL("http://cortex.sourceforge.net/documentation")); 1884 1885 // FluidSynth copyrights 1886 _AddPackageCredit(PackageCredit("FluidSynth") 1887 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2003 Peter Hanappe " 1888 "and others.")) 1889 .SetLicense(kLGPLv2) 1890 .SetURL("http://www.fluidsynth.org")); 1891 1892 // Xiph.org Foundation copyrights 1893 _AddPackageCredit(PackageCredit("Xiph.org Foundation") 1894 .SetCopyrights("libvorbis, libogg, libtheora, libspeex", 1895 B_TRANSLATE(COPYRIGHT_STRING "1994-2008 Xiph.Org. " 1896 "All rights reserved."), NULL) 1897 .SetLicense(kBSDThreeClause) 1898 .SetURL("http://www.xiph.org")); 1899 1900 // Matroska 1901 _AddPackageCredit(PackageCredit("libmatroska") 1902 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2002-2003 Steve Lhomme. " 1903 "All rights reserved.")) 1904 .SetLicense(kLGPLv21) 1905 .SetURL("http://www.matroska.org")); 1906 1907 // BColorQuantizer (originally CQuantizer code) 1908 _AddPackageCredit(PackageCredit("CQuantizer") 1909 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1996-1997 Jeff Prosise. " 1910 "All rights reserved.")) 1911 .SetLicense("CQuantizer") 1912 .SetURL("http://www.xdp.it")); 1913 1914 // MAPM (Mike's Arbitrary Precision Math Library) used by DeskCalc 1915 _AddPackageCredit(PackageCredit("MAPM") 1916 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1999-2007 Michael C. " 1917 "Ring. All rights reserved.")) 1918 .SetLicense("MAPM") 1919 .SetURL("http://tc.umn.edu/~ringx004")); 1920 1921 // MkDepend 1.7 copyright (Makefile dependency generator) 1922 _AddPackageCredit(PackageCredit("MkDepend") 1923 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1995-2001 Lars Düning. " 1924 "All rights reserved.")) 1925 .SetLicense("MIT") 1926 .SetURL("http://bearnip.com/lars/be")); 1927 1928 // libhttpd copyright (used as Poorman backend) 1929 _AddPackageCredit(PackageCredit("libhttpd") 1930 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1995, 1998-2001 " 1931 "Jef Poskanzer. All rights reserved.")) 1932 .SetLicense(kBSDTwoClause) 1933 .SetURL("http://www.acme.com/software/thttpd/")); 1934 1935 #ifdef __i386__ 1936 // Udis86 copyrights 1937 _AddPackageCredit(PackageCredit("Udis86") 1938 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2002-2004 " 1939 "Vivek Mohan. All rights reserved.")) 1940 .SetLicense(kBSDTwoClause) 1941 .SetURL("http://udis86.sourceforge.net")); 1942 1943 // Intel PRO/Wireless 2100 & 2200BG firmwares 1944 _AddPackageCredit(PackageCredit("Intel PRO/Wireless 2100 & 2200BG firmwares") 1945 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2003-2006 " 1946 "Intel Corporation. All rights reserved.")) 1947 .SetLicense(kIntel2xxxFirmware) 1948 .SetURL("http://www.intellinuxwireless.org/")); 1949 1950 // Intel wireless firmwares 1951 _AddPackageCredit( 1952 PackageCredit("Intel PRO/Wireless network adapter firmwares") 1953 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2006-2015 " 1954 "Intel Corporation. All rights reserved.")) 1955 .SetLicense(kIntelFirmware) 1956 .SetURL("http://www.intellinuxwireless.org/")); 1957 1958 // Marvell 88w8363 1959 _AddPackageCredit(PackageCredit("Marvell 88w8363") 1960 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2007-2009 " 1961 "Marvell Semiconductor, Inc. All rights reserved.")) 1962 .SetLicense(kMarvellFirmware) 1963 .SetURL("http://www.marvell.com/")); 1964 1965 // Ralink Firmware RT2501/RT2561/RT2661 1966 _AddPackageCredit(PackageCredit("Ralink Firmware RT2501/RT2561/RT2661") 1967 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2007 " 1968 "Ralink Technology Corporation. All rights reserved.")) 1969 .SetLicense(kRalinkFirmware) 1970 .SetURL("http://www.ralinktech.com/")); 1971 #endif 1972 1973 // Gutenprint 1974 _AddPackageCredit(PackageCredit("Gutenprint") 1975 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING 1976 "1999-2010 by the authors of Gutenprint. All rights reserved.")) 1977 .SetLicense(kGPLv2) 1978 .SetURL("http://gutenprint.sourceforge.net/")); 1979 1980 // libwebp 1981 _AddPackageCredit(PackageCredit("libwebp") 1982 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING 1983 "2010-2011 Google Inc. All rights reserved.")) 1984 .SetLicense(kBSDThreeClause) 1985 .SetURL("http://www.webmproject.org/code/#libwebp_webp_image_library")); 1986 1987 // libavif 1988 _AddPackageCredit(PackageCredit("libavif") 1989 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING 1990 "2019 Joe Drago. All rights reserved.")) 1991 .SetLicense(kBSDThreeClause) 1992 .SetURL("https://github.com/AOMediaCodec/libavif")); 1993 1994 // GTF 1995 _AddPackageCredit(PackageCredit("GTF") 1996 .SetCopyright(B_TRANSLATE("2001 by Andy Ritger based on the " 1997 "Generalized Timing Formula")) 1998 .SetLicense(kBSDThreeClause) 1999 .SetURL("http://gtf.sourceforge.net/")); 2000 2001 // libqrencode 2002 _AddPackageCredit(PackageCredit("libqrencode") 2003 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2006-2012 Kentaro Fukuchi")) 2004 .SetLicense(kLGPLv21) 2005 .SetURL("http://fukuchi.org/works/qrencode/")); 2006 2007 // scrypt 2008 _AddPackageCredit(PackageCredit("scrypt") 2009 .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2009 Colin Percival")) 2010 .SetLicense(kBSDTwoClause) 2011 .SetURL("https://tarsnap.com/scrypt.html")); 2012 2013 _AddCopyrightsFromAttribute(); 2014 _AddPackageCreditEntries(); 2015 2016 return new CropView(creditsScroller, 0, 1, 1, 1); 2017 } 2018 2019 2020 status_t 2021 AboutView::_GetLicensePath(const char* license, BPath& path) 2022 { 2023 BPathFinder pathFinder; 2024 BStringList paths; 2025 struct stat st; 2026 2027 status_t error = pathFinder.FindPaths(B_FIND_PATH_DATA_DIRECTORY, 2028 "licenses", paths); 2029 2030 for (int i = 0; i < paths.CountStrings(); ++i) { 2031 if (error == B_OK && path.SetTo(paths.StringAt(i)) == B_OK 2032 && path.Append(license) == B_OK 2033 && lstat(path.Path(), &st) == 0) { 2034 return B_OK; 2035 } 2036 } 2037 2038 path.Unset(); 2039 return B_ENTRY_NOT_FOUND; 2040 } 2041 2042 2043 void 2044 AboutView::_AddCopyrightsFromAttribute() 2045 { 2046 #ifdef __HAIKU__ 2047 // open the app executable file 2048 char appPath[B_PATH_NAME_LENGTH]; 2049 int appFD; 2050 if (BPrivate::get_app_path(appPath) != B_OK 2051 || (appFD = open(appPath, O_RDONLY)) < 0) { 2052 return; 2053 } 2054 2055 // open the attribute 2056 int attrFD = fs_fopen_attr(appFD, "COPYRIGHTS", B_STRING_TYPE, O_RDONLY); 2057 close(appFD); 2058 if (attrFD < 0) 2059 return; 2060 2061 // attach it to a FILE 2062 FileCloser attrFile(fdopen(attrFD, "r")); 2063 if (!attrFile.IsSet()) { 2064 close(attrFD); 2065 return; 2066 } 2067 2068 // read and parse the copyrights 2069 BMessage package; 2070 BString fieldName; 2071 BString fieldValue; 2072 char lineBuffer[LINE_MAX]; 2073 while (char* line 2074 = fgets(lineBuffer, sizeof(lineBuffer), attrFile.Get())) { 2075 // chop off line break 2076 size_t lineLen = strlen(line); 2077 if (lineLen > 0 && line[lineLen - 1] == '\n') 2078 line[--lineLen] = '\0'; 2079 2080 // flush previous field, if a new field begins, otherwise append 2081 if (lineLen == 0 || !isspace(line[0])) { 2082 // new field -- flush the previous one 2083 if (fieldName.Length() > 0) { 2084 fieldValue = trim_string(fieldValue.String(), 2085 fieldValue.Length()); 2086 package.AddString(fieldName.String(), fieldValue); 2087 fieldName = ""; 2088 } 2089 } else if (fieldName.Length() > 0) { 2090 // append to current field 2091 fieldValue += line; 2092 continue; 2093 } else { 2094 // bogus line -- ignore 2095 continue; 2096 } 2097 2098 if (lineLen == 0) 2099 continue; 2100 2101 // parse new field 2102 char* colon = strchr(line, ':'); 2103 if (colon == NULL) { 2104 // bogus line -- ignore 2105 continue; 2106 } 2107 2108 fieldName.SetTo(line, colon - line); 2109 fieldName = trim_string(line, colon - line); 2110 if (fieldName.Length() == 0) { 2111 // invalid field name 2112 continue; 2113 } 2114 2115 fieldValue = colon + 1; 2116 2117 if (fieldName == "Package") { 2118 // flush the current package 2119 _AddPackageCredit(PackageCredit(package)); 2120 package.MakeEmpty(); 2121 } 2122 } 2123 2124 // flush current package 2125 _AddPackageCredit(PackageCredit(package)); 2126 #endif 2127 } 2128 2129 2130 void 2131 AboutView::_AddPackageCreditEntries() 2132 { 2133 // sort the packages case-insensitively 2134 PackageCredit* packages[fPackageCredits.size()]; 2135 int32 count = 0; 2136 for (PackageCreditMap::iterator it = fPackageCredits.begin(); 2137 it != fPackageCredits.end(); ++it) { 2138 packages[count++] = it->second; 2139 } 2140 2141 if (count > 1) { 2142 std::sort(packages, packages + count, 2143 &PackageCredit::NameLessInsensitive); 2144 } 2145 2146 // add the credits 2147 BString text; 2148 for (int32 i = 0; i < count; i++) { 2149 PackageCredit* package = packages[i]; 2150 2151 text.SetTo(package->CopyrightAt(0)); 2152 int32 count = package->CountCopyrights(); 2153 for (int32 i = 1; i < count; i++) 2154 text << "\n" << package->CopyrightAt(i); 2155 2156 AddCopyrightEntry(package->PackageName(), text.String(), 2157 package->Licenses(), package->Sources(), package->URL()); 2158 } 2159 } 2160 2161 2162 void 2163 AboutView::_AddPackageCredit(const PackageCredit& package) 2164 { 2165 if (!package.IsValid()) 2166 return; 2167 2168 PackageCreditMap::iterator it = fPackageCredits.find(package.PackageName()); 2169 if (it != fPackageCredits.end()) { 2170 // If the new package credit isn't "better" than the old one, ignore it. 2171 PackageCredit* oldPackage = it->second; 2172 if (!package.IsBetterThan(*oldPackage)) 2173 return; 2174 2175 // replace the old credit 2176 fPackageCredits.erase(it); 2177 delete oldPackage; 2178 } 2179 2180 fPackageCredits[package.PackageName()] = new PackageCredit(package); 2181 } 2182 2183 2184 // #pragma mark - static functions 2185 2186 2187 static int 2188 ignored_pages(system_info* sysInfo) 2189 { 2190 return (int)round(sysInfo->ignored_pages * B_PAGE_SIZE / 1048576.0); 2191 } 2192 2193 2194 static int 2195 max_pages(system_info* sysInfo) 2196 { 2197 return (int)round(sysInfo->max_pages * B_PAGE_SIZE / 1048576.0); 2198 } 2199 2200 2201 static int 2202 max_and_ignored_pages(system_info* sysInfo) 2203 { 2204 return (int)round((sysInfo->max_pages + sysInfo->ignored_pages) 2205 * B_PAGE_SIZE / 1048576.0); 2206 } 2207 2208 2209 static int 2210 used_pages(system_info* sysInfo) 2211 { 2212 return (int)round(sysInfo->used_pages * B_PAGE_SIZE / 1048576.0); 2213 } 2214 2215 2216 // #pragma mark - main 2217 2218 2219 int 2220 main() 2221 { 2222 AboutApp app; 2223 app.Run(); 2224 2225 return 0; 2226 } 2227