1 /* 2 * Copyright (c) 2005-2009, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 * René Gollent 8 */ 9 10 #include <ctype.h> 11 #include <stdio.h> 12 #include <sys/utsname.h> 13 #include <time.h> 14 #include <unistd.h> 15 16 #include <map> 17 #include <string> 18 19 #include <AppFileInfo.h> 20 #include <Application.h> 21 #include <Bitmap.h> 22 #include <File.h> 23 #include <FindDirectory.h> 24 #include <Font.h> 25 #include <fs_attr.h> 26 #include <LayoutBuilder.h> 27 #include <MessageRunner.h> 28 #include <Messenger.h> 29 #include <OS.h> 30 #include <Path.h> 31 #include <Resources.h> 32 #include <Screen.h> 33 #include <ScrollView.h> 34 #include <String.h> 35 #include <StringView.h> 36 #include <TranslationUtils.h> 37 #include <TranslatorFormats.h> 38 #include <View.h> 39 #include <Volume.h> 40 #include <VolumeRoster.h> 41 #include <Window.h> 42 43 #include <AppMisc.h> 44 #include <AutoDeleter.h> 45 #include <cpu_type.h> 46 47 #include "HyperTextActions.h" 48 #include "HyperTextView.h" 49 #include "Utilities.h" 50 51 52 #ifndef LINE_MAX 53 #define LINE_MAX 2048 54 #endif 55 56 #define SCROLL_CREDITS_VIEW 'mviv' 57 58 59 static const char *UptimeToString(char string[], size_t size); 60 static const char *MemUsageToString(char string[], size_t size, 61 system_info *info); 62 63 static const rgb_color kDarkGrey = { 100, 100, 100, 255 }; 64 static const rgb_color kHaikuGreen = { 42, 131, 36, 255 }; 65 static const rgb_color kHaikuOrange = { 255, 69, 0, 255 }; 66 static const rgb_color kHaikuYellow = { 255, 176, 0, 255 }; 67 static const rgb_color kLinkBlue = { 80, 80, 200, 255 }; 68 69 70 class AboutApp : public BApplication { 71 public: 72 AboutApp(); 73 }; 74 75 class AboutWindow : public BWindow { 76 public: 77 AboutWindow(); 78 79 virtual bool QuitRequested(); 80 }; 81 82 class LogoView : public BView { 83 public: 84 LogoView(); 85 virtual ~LogoView(); 86 87 virtual BSize MinSize(); 88 virtual BSize MaxSize(); 89 90 virtual void Draw(BRect updateRect); 91 92 private: 93 BBitmap* fLogo; 94 }; 95 96 class CropView : public BView { 97 public: 98 CropView(BView* target, int32 left, int32 top, 99 int32 right, int32 bottom); 100 virtual ~CropView(); 101 102 virtual BSize MinSize(); 103 virtual BSize MaxSize(); 104 105 virtual void DoLayout(); 106 107 private: 108 BView* fTarget; 109 int32 fCropLeft; 110 int32 fCropTop; 111 int32 fCropRight; 112 int32 fCropBottom; 113 }; 114 115 class AboutView : public BView { 116 public: 117 AboutView(); 118 ~AboutView(); 119 120 virtual void AttachedToWindow(); 121 virtual void Pulse(); 122 123 virtual void MessageReceived(BMessage* msg); 124 virtual void MouseDown(BPoint point); 125 126 void AddCopyrightEntry(const char* name, 127 const char* text, 128 const StringVector& licenses, 129 const char* url); 130 void AddCopyrightEntry(const char* name, 131 const char* text, const char* url = NULL); 132 void PickRandomHaiku(); 133 134 135 private: 136 typedef std::map<std::string, PackageCredit*> PackageCreditMap; 137 138 private: 139 BView* _CreateLabel(const char* name, const char* label); 140 BView* _CreateCreditsView(); 141 status_t _GetLicensePath(const char* license, 142 BPath& path); 143 void _AddCopyrightsFromAttribute(); 144 void _AddPackageCredit(const PackageCredit& package); 145 void _AddPackageCreditEntries(); 146 147 BStringView* fMemView; 148 BTextView* fUptimeView; 149 BView* fInfoView; 150 HyperTextView* fCreditsView; 151 152 BBitmap* fLogo; 153 154 bigtime_t fLastActionTime; 155 BMessageRunner* fScrollRunner; 156 PackageCreditMap fPackageCredits; 157 }; 158 159 160 // #pragma mark - 161 162 163 AboutApp::AboutApp() 164 : BApplication("application/x-vnd.Haiku-About") 165 { 166 AboutWindow* window = new AboutWindow(); 167 window->Show(); 168 } 169 170 171 // #pragma mark - 172 173 174 AboutWindow::AboutWindow() 175 : BWindow(BRect(0, 0, 500, 300), "About This System", B_TITLED_WINDOW, 176 B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_ZOOMABLE) 177 { 178 SetLayout(new BGroupLayout(B_VERTICAL)); 179 AddChild(new AboutView()); 180 181 // Make sure we take the minimal window size into account when centering 182 BSize size = GetLayout()->MinSize(); 183 ResizeTo(max_c(size.width, Bounds().Width()), 184 max_c(size.height, Bounds().Height())); 185 186 MoveTo((BScreen().Frame().Width() - Bounds().Width()) / 2, 187 (BScreen().Frame().Height() - Bounds().Height()) / 2 ); 188 } 189 190 191 bool 192 AboutWindow::QuitRequested() 193 { 194 be_app->PostMessage(B_QUIT_REQUESTED); 195 return true; 196 } 197 198 199 // #pragma mark - LogoView 200 201 202 LogoView::LogoView() 203 : BView("logo", B_WILL_DRAW) 204 { 205 fLogo = BTranslationUtils::GetBitmap(B_PNG_FORMAT, "haikulogo.png"); 206 SetViewColor(255, 255, 255); 207 } 208 209 210 LogoView::~LogoView() 211 { 212 delete fLogo; 213 } 214 215 216 BSize 217 LogoView::MinSize() 218 { 219 if (fLogo == NULL) 220 return BSize(0, 0); 221 222 return BSize(fLogo->Bounds().Width(), fLogo->Bounds().Height()); 223 } 224 225 226 BSize 227 LogoView::MaxSize() 228 { 229 if (fLogo == NULL) 230 return BSize(0, 0); 231 232 return BSize(B_SIZE_UNLIMITED, fLogo->Bounds().Height()); 233 } 234 235 236 void 237 LogoView::Draw(BRect updateRect) 238 { 239 if (fLogo != NULL) { 240 DrawBitmap(fLogo, 241 BPoint((Bounds().Width() - fLogo->Bounds().Width()) / 2, 0)); 242 } 243 } 244 245 246 // #pragma mark - CropView 247 248 249 CropView::CropView(BView* target, int32 left, int32 top, int32 right, 250 int32 bottom) 251 : BView("crop view", 0), 252 fTarget(target), 253 fCropLeft(left), 254 fCropTop(top), 255 fCropRight(right), 256 fCropBottom(bottom) 257 { 258 AddChild(target); 259 } 260 261 262 CropView::~CropView() 263 { 264 } 265 266 267 BSize 268 CropView::MinSize() 269 { 270 if (fTarget == NULL) 271 return BSize(); 272 273 BSize size = fTarget->MinSize(); 274 if (size.width != B_SIZE_UNSET) 275 size.width -= fCropLeft + fCropRight; 276 if (size.height != B_SIZE_UNSET) 277 size.height -= fCropTop + fCropBottom; 278 279 return size; 280 } 281 282 283 BSize 284 CropView::MaxSize() 285 { 286 if (fTarget == NULL) 287 return BSize(); 288 289 BSize size = fTarget->MaxSize(); 290 if (size.width != B_SIZE_UNSET) 291 size.width -= fCropLeft + fCropRight; 292 if (size.height != B_SIZE_UNSET) 293 size.height -= fCropTop + fCropBottom; 294 295 return size; 296 } 297 298 299 void 300 CropView::DoLayout() 301 { 302 BView::DoLayout(); 303 304 if (fTarget == NULL) 305 return; 306 307 fTarget->MoveTo(-fCropLeft, -fCropTop); 308 fTarget->ResizeTo(Bounds().Width() + fCropLeft + fCropRight, 309 Bounds().Height() + fCropTop + fCropBottom); 310 } 311 312 313 // #pragma mark - AboutView 314 315 316 AboutView::AboutView() 317 : BView("aboutview", B_WILL_DRAW | B_PULSE_NEEDED), 318 fLastActionTime(system_time()), 319 fScrollRunner(NULL) 320 { 321 // Begin Construction of System Information controls 322 323 system_info systemInfo; 324 get_system_info(&systemInfo); 325 326 // Create all the various labels for system infomation 327 328 // OS Version 329 330 char string[1024]; 331 strcpy(string, "Unknown"); 332 333 // the version is stored in the BEOS:APP_VERSION attribute of libbe.so 334 BPath path; 335 if (find_directory(B_BEOS_LIB_DIRECTORY, &path) == B_OK) { 336 path.Append("libbe.so"); 337 338 BAppFileInfo appFileInfo; 339 version_info versionInfo; 340 BFile file; 341 if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK 342 && appFileInfo.SetTo(&file) == B_OK 343 && appFileInfo.GetVersionInfo(&versionInfo, 344 B_APP_VERSION_KIND) == B_OK 345 && versionInfo.short_info[0] != '\0') 346 strcpy(string, versionInfo.short_info); 347 } 348 349 // Add revision from uname() info 350 utsname unameInfo; 351 if (uname(&unameInfo) == 0) { 352 long revision; 353 if (sscanf(unameInfo.version, "r%ld", &revision) == 1) { 354 char version[16]; 355 snprintf(version, sizeof(version), "%ld", revision); 356 strlcat(string, " (Revision ", sizeof(string)); 357 strlcat(string, version, sizeof(string)); 358 strlcat(string, ")", sizeof(string)); 359 } 360 } 361 362 BStringView* versionView = new BStringView("ostext", string); 363 versionView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 364 B_ALIGN_VERTICAL_UNSET)); 365 366 // GCC version 367 #if __GNUC__ != 2 368 snprintf(string, sizeof(string), "GCC %d", __GNUC__); 369 370 BStringView* gccView = new BStringView("gcctext", string); 371 gccView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 372 B_ALIGN_VERTICAL_UNSET)); 373 #endif 374 375 // CPU count, type and clock speed 376 char processorLabel[256]; 377 if (systemInfo.cpu_count > 1) { 378 snprintf(processorLabel, sizeof(processorLabel), "%ld Processors:", 379 systemInfo.cpu_count); 380 } else 381 strlcpy(processorLabel, "Processor:", sizeof(processorLabel)); 382 383 BString cpuType; 384 cpuType << get_cpu_vendor_string(systemInfo.cpu_type) 385 << " " << get_cpu_model_string(&systemInfo); 386 387 BStringView* cpuView = new BStringView("cputext", cpuType.String()); 388 cpuView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 389 B_ALIGN_VERTICAL_UNSET)); 390 391 int32 clockSpeed = get_rounded_cpu_speed(); 392 if (clockSpeed < 1000) 393 sprintf(string,"%ld MHz", clockSpeed); 394 else 395 sprintf(string,"%.2f GHz", clockSpeed / 1000.0f); 396 397 BStringView* frequencyView = new BStringView("frequencytext", string); 398 frequencyView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 399 B_ALIGN_VERTICAL_UNSET)); 400 401 // RAM 402 fMemView = new BStringView("ramtext", 403 MemUsageToString(string, sizeof(string), &systemInfo)); 404 fMemView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 405 B_ALIGN_VERTICAL_UNSET)); 406 407 // Kernel build time/date 408 snprintf(string, sizeof(string), "%s %s", 409 systemInfo.kernel_build_date, systemInfo.kernel_build_time); 410 411 BStringView* kernelView = new BStringView("kerneltext", string); 412 kernelView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 413 B_ALIGN_VERTICAL_UNSET)); 414 415 // Uptime 416 fUptimeView = new BTextView("uptimetext"); 417 fUptimeView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 418 fUptimeView->MakeEditable(false); 419 fUptimeView->MakeSelectable(false); 420 fUptimeView->SetWordWrap(true); 421 422 fUptimeView->SetText(UptimeToString(string, sizeof(string))); 423 424 const float offset = 5; 425 426 SetLayout(new BGroupLayout(B_HORIZONTAL)); 427 428 BLayoutBuilder::Group<>((BGroupLayout*)GetLayout()) 429 .AddGroup(B_VERTICAL) 430 .Add(new LogoView()) 431 .AddGroup(B_VERTICAL) 432 .Add(_CreateLabel("oslabel", "Version:")) 433 .Add(versionView) 434 #if __GNUC__ != 2 435 .Add(gccView) 436 #endif 437 .AddStrut(offset) 438 .Add(_CreateLabel("cpulabel", processorLabel)) 439 .Add(cpuView) 440 .Add(frequencyView) 441 .AddStrut(offset) 442 .Add(_CreateLabel("memlabel", "Memory:")) 443 .Add(fMemView) 444 .AddStrut(offset) 445 .Add(_CreateLabel("kernellabel", "Kernel:")) 446 .Add(kernelView) 447 .AddStrut(offset) 448 .Add(_CreateLabel("uptimelabel", "Time Running:")) 449 .Add(fUptimeView) 450 .SetInsets(5, 5, 5, 5) 451 .End() 452 // TODO: investigate: adding this causes the time to be cut 453 //.AddGlue() 454 .End() 455 .Add(_CreateCreditsView()); 456 457 float min = fMemView->MinSize().width * 1.1f; 458 fCreditsView->SetExplicitMinSize(BSize(min, min)); 459 } 460 461 462 AboutView::~AboutView() 463 { 464 delete fScrollRunner; 465 } 466 467 468 void 469 AboutView::AttachedToWindow() 470 { 471 BView::AttachedToWindow(); 472 Window()->SetPulseRate(500000); 473 SetEventMask(B_POINTER_EVENTS); 474 } 475 476 477 void 478 AboutView::MouseDown(BPoint point) 479 { 480 BRect r(92, 26, 105, 31); 481 if (r.Contains(point)) { 482 printf("Easter Egg\n"); 483 PickRandomHaiku(); 484 } 485 486 if (Bounds().Contains(point)) { 487 fLastActionTime = system_time(); 488 delete fScrollRunner; 489 fScrollRunner = NULL; 490 } 491 } 492 493 494 void 495 AboutView::Pulse() 496 { 497 char string[255]; 498 system_info info; 499 get_system_info(&info); 500 fUptimeView->SetText(UptimeToString(string, sizeof(string))); 501 fMemView->SetText(MemUsageToString(string, sizeof(string), &info)); 502 503 if (fScrollRunner == NULL && system_time() > fLastActionTime + 10000000) { 504 BMessage message(SCROLL_CREDITS_VIEW); 505 //fScrollRunner = new BMessageRunner(this, &message, 25000, -1); 506 } 507 } 508 509 510 void 511 AboutView::MessageReceived(BMessage *msg) 512 { 513 switch (msg->what) { 514 case SCROLL_CREDITS_VIEW: 515 { 516 BScrollBar *scrollBar = fCreditsView->ScrollBar(B_VERTICAL); 517 if (scrollBar == NULL) 518 break; 519 float max, min; 520 scrollBar->GetRange(&min, &max); 521 if (scrollBar->Value() < max) 522 fCreditsView->ScrollBy(0, 1); 523 524 break; 525 } 526 527 default: 528 BView::MessageReceived(msg); 529 break; 530 } 531 } 532 533 534 void 535 AboutView::AddCopyrightEntry(const char *name, const char *text, 536 const char *url) 537 { 538 AddCopyrightEntry(name, text, StringVector(), url); 539 } 540 541 542 void 543 AboutView::AddCopyrightEntry(const char *name, const char *text, 544 const StringVector& licenses, const char *url) 545 { 546 BFont font(be_bold_font); 547 //font.SetSize(be_bold_font->Size()); 548 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 549 550 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuYellow); 551 fCreditsView->Insert(name); 552 fCreditsView->Insert("\n"); 553 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 554 fCreditsView->Insert(text); 555 fCreditsView->Insert("\n"); 556 557 if (licenses.CountStrings() > 0) { 558 if (licenses.CountStrings() > 1) 559 fCreditsView->Insert("Licenses: "); 560 else 561 fCreditsView->Insert("License: "); 562 563 for (int32 i = 0; i < licenses.CountStrings(); i++) { 564 const char* license = licenses.StringAt(i); 565 566 if (i > 0) 567 fCreditsView->Insert(", "); 568 569 BPath licensePath; 570 if (_GetLicensePath(license, licensePath) == B_OK) { 571 fCreditsView->InsertHyperText(license, 572 new OpenFileAction(licensePath.Path())); 573 } else 574 fCreditsView->Insert(license); 575 } 576 577 fCreditsView->Insert("\n"); 578 } 579 580 if (url) { 581 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kLinkBlue); 582 fCreditsView->InsertHyperText(url, new URLAction(url)); 583 fCreditsView->Insert("\n"); 584 } 585 fCreditsView->Insert("\n"); 586 } 587 588 589 void 590 AboutView::PickRandomHaiku() 591 { 592 BFile fortunes( 593 #ifdef __HAIKU__ 594 "/etc/fortunes/Haiku", 595 #else 596 "data/etc/fortunes/Haiku", 597 #endif 598 B_READ_ONLY); 599 struct stat st; 600 if (fortunes.InitCheck() < B_OK) 601 return; 602 if (fortunes.GetStat(&st) < B_OK) 603 return; 604 char *buff = (char *)malloc((size_t)st.st_size + 1); 605 if (!buff) 606 return; 607 buff[(size_t)st.st_size] = '\0'; 608 BList haikuList; 609 if (fortunes.Read(buff, (size_t)st.st_size) == (ssize_t)st.st_size) { 610 char *p = buff; 611 while (p && *p) { 612 char *e = strchr(p, '%'); 613 BString *s = new BString(p, e ? (e - p) : -1); 614 haikuList.AddItem(s); 615 p = e; 616 if (p && (*p == '%')) 617 p++; 618 if (p && (*p == '\n')) 619 p++; 620 } 621 } 622 free(buff); 623 if (haikuList.CountItems() < 1) 624 return; 625 BString *s = (BString *)haikuList.ItemAt(rand() % haikuList.CountItems()); 626 BFont font(be_bold_font); 627 font.SetSize(be_bold_font->Size()); 628 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 629 fCreditsView->SelectAll(); 630 fCreditsView->Delete(); 631 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kDarkGrey); 632 fCreditsView->Insert(s->String()); 633 fCreditsView->Insert("\n"); 634 while ((s = (BString *)haikuList.RemoveItem((int32)0))) { 635 delete s; 636 } 637 } 638 639 640 BView* 641 AboutView::_CreateLabel(const char* name, const char* label) 642 { 643 BStringView* labelView = new BStringView(name, label); 644 labelView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 645 B_ALIGN_VERTICAL_UNSET)); 646 labelView->SetFont(be_bold_font); 647 return labelView; 648 } 649 650 651 BView* 652 AboutView::_CreateCreditsView() 653 { 654 // Begin construction of the credits view 655 fCreditsView = new HyperTextView("credits"); 656 fCreditsView->SetFlags(fCreditsView->Flags() | B_FRAME_EVENTS); 657 fCreditsView->SetStylable(true); 658 fCreditsView->MakeEditable(false); 659 fCreditsView->SetWordWrap(true); 660 fCreditsView->SetInsets(5, 5, 5, 5); 661 662 BScrollView* creditsScroller = new BScrollView("creditsScroller", 663 fCreditsView, B_WILL_DRAW | B_FRAME_EVENTS, false, true, 664 B_PLAIN_BORDER); 665 666 // Haiku copyright 667 BFont font(be_bold_font); 668 font.SetSize(font.Size() + 4); 669 670 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen); 671 fCreditsView->Insert("Haiku\n"); 672 673 char string[1024]; 674 time_t time = ::time(NULL); 675 struct tm* tm = localtime(&time); 676 int32 year = tm->tm_year + 1900; 677 if (year < 2008) 678 year = 2008; 679 snprintf(string, sizeof(string), 680 COPYRIGHT_STRING "2001-%ld The Haiku project. ", year); 681 682 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 683 fCreditsView->Insert(string); 684 685 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 686 fCreditsView->Insert("The copyright to the Haiku code is property of " 687 "Haiku, Inc. or of the respective authors where expressly noted " 688 "in the source." 689 "\n\n"); 690 691 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kLinkBlue); 692 fCreditsView->InsertHyperText("http://www.haiku-os.org", 693 new URLAction("http://www.haiku-os.org")); 694 fCreditsView->Insert("\n\n"); 695 696 font.SetSize(be_bold_font->Size()); 697 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 698 699 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 700 fCreditsView->Insert("Current Maintainers:\n"); 701 702 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 703 fCreditsView->Insert( 704 "Ithamar R. Adema\n" 705 "Bruno G. Albuquerque\n" 706 "Stephan Aßmus\n" 707 "Salvatore Benedetto\n" 708 "Stefano Ceccherini\n" 709 "Rudolf Cornelissen\n" 710 "Alexandre Deckner\n" 711 "Oliver Ruiz Dorantes\n" 712 "Axel Dörfler\n" 713 "Jérôme Duval\n" 714 "René Gollent\n" 715 "Karsten Heimrich\n" 716 "Philippe Houdoin\n" 717 "Maurice Kalinowski\n" 718 "Euan Kirkhope\n" 719 "Ryan Leavengood\n" 720 "Michael Lotz\n" 721 "David McPaul\n" 722 "Fredrik Modéen\n" 723 "Marcus Overhagen\n" 724 "Michael Pfeiffer\n" 725 "François Revol\n" 726 "Andrej Spielmann\n" 727 "Oliver Tappe\n" 728 "Gerasim Troeglazov\n" 729 "Ingo Weinhold\n" 730 "Siarzhuk Zharski\n" 731 "\n"); 732 733 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 734 fCreditsView->Insert("Past Maintainers:\n"); 735 736 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 737 fCreditsView->Insert( 738 "Andrew Bachmann\n" 739 "Tyler Dauwalder\n" 740 "Daniel Furrer\n" 741 "Andre Alves Garzia\n" 742 "Erik Jaesler\n" 743 "Marcin Konicki\n" 744 "Waldemar Kornewald\n" 745 "Thomas Kurschel\n" 746 "Frans Van Nispen\n" 747 "Adi Oanca\n" 748 "Michael Phipps\n" 749 "Niels Sascha Reedijk\n" 750 "David Reid\n" 751 "Hugo Santos\n" 752 "Alexander G. M. Smith\n" 753 "Jonas Sundström\n" 754 "Bryan Varner\n" 755 "Nathan Whitehorn\n" 756 "Michael Wilber\n" 757 "Jonathan Yoder\n" 758 "Gabe Yoder\n" 759 "\n"); 760 761 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 762 fCreditsView->Insert("Website, Marketing & Documentation:\n"); 763 764 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 765 fCreditsView->Insert( 766 "Phil Greenway\n" 767 "Gavin James\n" 768 "Urias McCullough\n" 769 "Niels Sascha Reedijk\n" 770 "Jonathan Yoder\n" 771 "\n"); 772 773 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 774 fCreditsView->Insert("Contributors:\n"); 775 776 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 777 fCreditsView->Insert( 778 "Andrea Anzani\n" 779 "Andre Braga\n" 780 "Bruce Cameron\n" 781 "Greg Crain\n" 782 "David Dengg\n" 783 "John Drinkwater\n" 784 "Cian Duffy\n" 785 "Mark Erben\n" 786 "Christian Fasshauer\n" 787 "Andreas Färber\n" 788 "Marc Flerackers\n" 789 "Matthijs Hollemans\n" 790 "Mathew Hounsell\n" 791 "Morgan Howe\n" 792 "Carwyn Jones\n" 793 "Vasilis Kaoutsis\n" 794 "James Kim\n" 795 "Shintaro Kinugawa\n" 796 "Jan Klötzke\n" 797 "Kurtis Kopf\n" 798 "Tomáš Kučera\n" 799 "Luboš Kulič\n" 800 "Elad Lahav\n" 801 "Anthony Lee\n" 802 "Santiago Lema\n" 803 "Raynald Lesieur\n" 804 "Oscar Lesta\n" 805 "Jerome Leveque\n" 806 "Christof Lutteroth\n" 807 "Graham MacDonald\n" 808 "Jan Matějek\n" 809 "Brian Matzon\n" 810 "Christopher ML Zumwalt May\n" 811 "Andrew McCall\n" 812 "Scott McCreary\n" 813 "Michele (zuMi)\n" 814 "Marius Middelthon\n" 815 "Marco Minutoli\n" 816 "Misza\n" 817 "MrSiggler\n" 818 "Alan Murta\n" 819 "Pahtz\n" 820 "Michael Paine\n" 821 "Adrian Panasiuk\n" 822 "Francesco Piccinno\n" 823 "David Powell\n" 824 "Jeremy Rand\n" 825 "Hartmut Reh\n" 826 "Daniel Reinhold\n" 827 "Samuel Rodriguez Perez\n" 828 "Thomas Roell\n" 829 "Rafael Romo\n" 830 "Philippe Saint-Pierre\n" 831 "Ralf Schülke\n" 832 "Reznikov Sergei\n" 833 "Zousar Shaker\n" 834 "Daniel Switkin\n" 835 "Atsushi Takamatsu\n" 836 "James Urquhart\n" 837 "Jason Vandermark\n" 838 "Sandor Vroemisse\n" 839 "Denis Washington\n" 840 "Ulrich Wimboeck\n" 841 "James Woodcock\n" 842 "Artur Wyszynski\n" 843 "Gerald Zajac\n" 844 "Clemens Zeidler\n" 845 "Łukasz Zemczak\n" 846 "JiSheng Zhang\n" 847 "Zhao Shuai\n" 848 "\n" B_UTF8_ELLIPSIS " and probably some more we forgot to mention " 849 "(sorry!)" 850 "\n\n"); 851 852 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 853 fCreditsView->Insert("Special Thanks To:\n"); 854 855 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 856 fCreditsView->Insert("Travis Geiselbrecht (and his NewOS kernel)\n"); 857 fCreditsView->Insert("Michael Phipps (project founder)\n\n"); 858 859 // copyrights for various projects we use 860 861 BPath mitPath; 862 _GetLicensePath("MIT", mitPath); 863 864 font.SetSize(be_bold_font->Size() + 4); 865 font.SetFace(B_BOLD_FACE); 866 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen); 867 fCreditsView->Insert("\nCopyrights\n\n"); 868 869 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 870 fCreditsView->Insert("[Click a license name to read the respective " 871 "license.]\n\n"); 872 873 // Haiku license 874 fCreditsView->Insert("The code that is unique to Haiku, especially the " 875 "kernel and all code that applications may link against, is " 876 "distributed under the terms of the "); 877 fCreditsView->InsertHyperText("MIT license", 878 new OpenFileAction(mitPath.Path())); 879 fCreditsView->Insert(". Some system libraries contain third party code " 880 "distributed under the LGPL license. You can find the copyrights " 881 "to third party code below.\n\n"); 882 883 // GNU copyrights 884 AddCopyrightEntry("The GNU Project", 885 "Contains software from the GNU Project, " 886 "released under the GPL and LGPL licences:\n" 887 "GNU C Library, " 888 "GNU coretools, diffutils, findutils, " 889 "sharutils, gawk, bison, m4, make, " 890 "gdb, wget, ncurses, termcap, " 891 "Bourne Again Shell.\n" 892 COPYRIGHT_STRING "The Free Software Foundation.", 893 StringVector("GNU LGPL v2.1", "GNU GPL v2", "GNU GPL v3", NULL), 894 "http://www.gnu.org"); 895 896 // FreeBSD copyrights 897 AddCopyrightEntry("The FreeBSD Project", 898 "Contains software from the FreeBSD Project, " 899 "released under the BSD licence:\n" 900 "cal, ftpd, ping, telnet, " 901 "telnetd, traceroute\n" 902 COPYRIGHT_STRING "1994-2008 The FreeBSD Project. " 903 "All rights reserved.", 904 "http://www.freebsd.org"); 905 // TODO: License! 906 907 // NetBSD copyrights 908 AddCopyrightEntry("The NetBSD Project", 909 "Contains software developed by the NetBSD, " 910 "Foundation, Inc. and its contributors:\n" 911 "ftp, tput\n" 912 COPYRIGHT_STRING "1996-2008 The NetBSD Foundation, Inc. " 913 "All rights reserved.", 914 "http://www.netbsd.org"); 915 // TODO: License! 916 917 // FFMpeg copyrights 918 _AddPackageCredit(PackageCredit("FFMpeg libavcodec") 919 .SetCopyright(COPYRIGHT_STRING "2000-2007 Fabrice Bellard, et al.") 920 .SetURL("http://www.ffmpeg.org")); 921 // TODO: License! 922 923 // AGG copyrights 924 _AddPackageCredit(PackageCredit("AntiGrain Geometry") 925 .SetCopyright(COPYRIGHT_STRING "2002-2006 Maxim Shemanarev (McSeem).") 926 .SetURL("http://www.antigrain.com")); 927 // TODO: License! 928 929 // PDFLib copyrights 930 _AddPackageCredit(PackageCredit("PDFLib") 931 .SetCopyright(COPYRIGHT_STRING "1997-2006 PDFlib GmbH and Thomas Merz. " 932 "All rights reserved.\n" 933 "PDFlib and PDFlib logo are registered trademarks of PDFlib GmbH.") 934 .SetURL("http://www.pdflib.com")); 935 // TODO: License! 936 937 // FreeType copyrights 938 _AddPackageCredit(PackageCredit("FreeType2") 939 .SetCopyright("Portions of this software are copyright " 940 B_UTF8_COPYRIGHT " 1996-2006 " 941 "The FreeType Project. All rights reserved.") 942 .SetURL("http://www.freetype.org")); 943 // TODO: License! 944 945 // Mesa3D (http://www.mesa3d.org) copyrights 946 _AddPackageCredit(PackageCredit("Mesa") 947 .SetCopyright(COPYRIGHT_STRING "1999-2006 Brian Paul. " 948 "Mesa3D project. All rights reserved.") 949 .SetURL("http://www.mesa3d.org")); 950 // TODO: License! 951 952 // SGI's GLU implementation copyrights 953 _AddPackageCredit(PackageCredit("GLU") 954 .SetCopyright(COPYRIGHT_STRING 955 "1991-2000 Silicon Graphics, Inc. " 956 "SGI's Software FreeB license. All rights reserved.")); 957 // TODO: License! 958 959 // GLUT implementation copyrights 960 _AddPackageCredit(PackageCredit("GLUT") 961 .SetCopyrights(COPYRIGHT_STRING "1994-1997 Mark Kilgard. " 962 "All rights reserved.", 963 COPYRIGHT_STRING "1997 Be Inc.", 964 COPYRIGHT_STRING "1999 Jake Hamby.", 965 NULL)); 966 // TODO: License! 967 968 // OpenGroup & DEC (BRegion backend) copyright 969 _AddPackageCredit(PackageCredit("BRegion backend (XFree86)") 970 .SetCopyrights(COPYRIGHT_STRING "1987, 1988, 1998 The Open Group.", 971 COPYRIGHT_STRING "1987, 1988 Digital Equipment " 972 "Corporation, Maynard, Massachusetts.\n" 973 "All rights reserved.", 974 NULL)); 975 // TODO: License! 976 977 // Konatu font 978 _AddPackageCredit(PackageCredit("Konatu font") 979 .SetCopyright(COPYRIGHT_STRING "2002- MASUDA mitiya.\n" 980 "MIT license. All rights reserved.")); 981 // TODO: License! 982 983 // expat copyrights 984 _AddPackageCredit(PackageCredit("expat") 985 .SetCopyrights(COPYRIGHT_STRING 986 "1998, 1999, 2000 Thai Open Source " 987 "Software Center Ltd and Clark Cooper.", 988 COPYRIGHT_STRING "2001, 2002, 2003 Expat maintainers.", 989 NULL)); 990 // TODO: License! 991 992 // zlib copyrights 993 _AddPackageCredit(PackageCredit("zlib") 994 .SetCopyright(COPYRIGHT_STRING 995 "1995-2004 Jean-loup Gailly and Mark Adler.")); 996 // TODO: License! 997 998 // zip copyrights 999 _AddPackageCredit(PackageCredit("Info-ZIP") 1000 .SetCopyright(COPYRIGHT_STRING 1001 "1990-2002 Info-ZIP. All rights reserved.")); 1002 // TODO: License! 1003 1004 // bzip2 copyrights 1005 _AddPackageCredit(PackageCredit("bzip2") 1006 .SetCopyright(COPYRIGHT_STRING 1007 "1996-2005 Julian R Seward. All rights reserved.")); 1008 // TODO: License! 1009 1010 // VIM copyrights 1011 _AddPackageCredit(PackageCredit("Vi IMproved") 1012 .SetCopyright(COPYRIGHT_STRING "Bram Moolenaar et al.")); 1013 // TODO: License! 1014 1015 // lp_solve copyrights 1016 _AddPackageCredit(PackageCredit("lp_solve") 1017 .SetCopyright(COPYRIGHT_STRING 1018 "Michel Berkelaar, Kjell Eikland, Peter Notebaert") 1019 .SetLicense("GNU LGPL v2.1") 1020 .SetURL("http://lpsolve.sourceforge.net/")); 1021 1022 // OpenEXR copyrights 1023 _AddPackageCredit(PackageCredit("OpenEXR") 1024 .SetCopyright(COPYRIGHT_STRING "2002-2005 Industrial Light & Magic, " 1025 "a division of Lucas Digital Ltd. LLC.")); 1026 // TODO: License! 1027 1028 // Bullet copyrights 1029 _AddPackageCredit(PackageCredit("Bullet") 1030 .SetCopyright(COPYRIGHT_STRING "2003-2008 Erwin Coumans") 1031 .SetURL("http://www.bulletphysics.com")); 1032 // TODO: License! 1033 1034 // atftp copyrights 1035 _AddPackageCredit(PackageCredit("atftp") 1036 .SetCopyright(COPYRIGHT_STRING 1037 "2000 Jean-Pierre Lefebvre and Remi Lefebvre")); 1038 // TODO: License! 1039 1040 // Netcat copyrights 1041 _AddPackageCredit(PackageCredit("Netcat") 1042 .SetCopyright(COPYRIGHT_STRING "1996 Hobbit")); 1043 // TODO: License! 1044 1045 // acpica copyrights 1046 _AddPackageCredit(PackageCredit("acpica") 1047 .SetCopyright(COPYRIGHT_STRING "1999-2006 Intel Corp.")); 1048 // TODO: License! 1049 1050 // unrar copyrights 1051 _AddPackageCredit(PackageCredit("unrar") 1052 .SetCopyright(COPYRIGHT_STRING "2002-2008 Alexander L. Roshal. " 1053 "All rights reserved.") 1054 .SetURL("http://www.rarlab.com")); 1055 // TODO: License! 1056 1057 // libpng copyrights 1058 _AddPackageCredit(PackageCredit("libpng") 1059 .SetCopyright(COPYRIGHT_STRING "2004, 2006-2008 Glenn " 1060 "Randers-Pehrson.")); 1061 // TODO: License! 1062 1063 // libprint copyrights 1064 _AddPackageCredit(PackageCredit("libprint") 1065 .SetCopyright(COPYRIGHT_STRING 1066 "1999-2000 Y.Takagi. All rights reserved.")); 1067 // TODO: License! 1068 1069 // cortex copyrights 1070 _AddPackageCredit(PackageCredit("Cortex") 1071 .SetCopyright(COPYRIGHT_STRING "1999-2000 Eric Moon.")); 1072 // TODO: License! 1073 1074 // FluidSynth copyrights 1075 _AddPackageCredit(PackageCredit("FluidSynth") 1076 .SetCopyright(COPYRIGHT_STRING "2003 Peter Hanappe and others.")); 1077 // TODO: License! 1078 1079 // CannaIM copyrights 1080 _AddPackageCredit(PackageCredit("CannaIM") 1081 .SetCopyright(COPYRIGHT_STRING "1999 Masao Kawamura.")); 1082 // TODO: License! 1083 1084 // libxml2, libxslt, libexslt copyrights 1085 _AddPackageCredit(PackageCredit("libxml2, libxslt") 1086 .SetCopyright(COPYRIGHT_STRING 1087 "1998-2003 Daniel Veillard. All rights reserved.")); 1088 // TODO: License! 1089 1090 _AddPackageCredit(PackageCredit("libexslt") 1091 .SetCopyright(COPYRIGHT_STRING 1092 "2001-2002 Thomas Broyer, Charlie " 1093 "Bozeman and Daniel Veillard. All rights reserved.")); 1094 // TODO: License! 1095 1096 // Xiph.org Foundation copyrights 1097 _AddPackageCredit(PackageCredit("Xiph.org Foundation") 1098 .SetCopyrights("libvorbis, libogg, libtheora, libspeex", 1099 COPYRIGHT_STRING "1994-2008 Xiph.Org. " 1100 "All rights reserved.", 1101 NULL) 1102 .SetURL("http://www.xiph.org")); 1103 // TODO: License! 1104 1105 // The Tcpdump Group 1106 _AddPackageCredit(PackageCredit("The Tcpdump Group") 1107 .SetCopyright("tcpdump, libpcap") 1108 .SetURL("http://www.tcpdump.org")); 1109 // TODO: License! 1110 1111 // Matroska 1112 _AddPackageCredit(PackageCredit("libmatroska") 1113 .SetCopyright(COPYRIGHT_STRING "2002-2003 Steve Lhomme. " 1114 "All rights reserved.") 1115 .SetURL("http://www.matroska.org")); 1116 // TODO: License! 1117 1118 // BColorQuantizer (originally CQuantizer code) 1119 _AddPackageCredit(PackageCredit("CQuantizer") 1120 .SetCopyright(COPYRIGHT_STRING "1996-1997 Jeff Prosise. " 1121 "All rights reserved.")); 1122 // TODO: License! 1123 1124 // MAPM (Mike's Arbitrary Precision Math Library) used by DeskCalc 1125 _AddPackageCredit(PackageCredit("MAPM") 1126 .SetCopyright(COPYRIGHT_STRING 1127 "1999-2007 Michael C. Ring. All rights reserved.") 1128 .SetURL("http://tc.umn.edu/~ringx004")); 1129 // TODO: License! 1130 1131 // MkDepend 1.7 copyright (Makefile dependency generator) 1132 _AddPackageCredit(PackageCredit("MkDepend") 1133 .SetCopyright(COPYRIGHT_STRING "1995-2001 Lars Düning. " 1134 "All rights reserved.")); 1135 // TODO: License! 1136 1137 // libhttpd copyright (used as Poorman backend) 1138 _AddPackageCredit(PackageCredit("libhttpd") 1139 .SetCopyright(COPYRIGHT_STRING 1140 "1995,1998,1999,2000,2001 by " 1141 "Jef Poskanzer. All rights reserved.") 1142 .SetLicense("LibHTTPd") 1143 .SetURL("http://www.acme.com/software/thttpd/")); 1144 1145 #ifdef __INTEL__ 1146 // Udis86 copyrights 1147 _AddPackageCredit(PackageCredit("Udis86") 1148 .SetCopyright(COPYRIGHT_STRING "2002, 2003, 2004 Vivek Mohan. " 1149 "All rights reserved.") 1150 .SetURL("http://udis86.sourceforge.net")); 1151 // TODO: License! 1152 #endif 1153 1154 _AddCopyrightsFromAttribute(); 1155 _AddPackageCreditEntries(); 1156 1157 return new CropView(creditsScroller, 0, 1, 1, 1); 1158 } 1159 1160 1161 status_t 1162 AboutView::_GetLicensePath(const char* license, BPath& path) 1163 { 1164 static const directory_which directoryConstants[] = { 1165 B_USER_DATA_DIRECTORY, 1166 B_COMMON_DATA_DIRECTORY, 1167 B_SYSTEM_DATA_DIRECTORY 1168 }; 1169 static const int dirCount = 3; 1170 1171 for (int i = 0; i < dirCount; i++) { 1172 struct stat st; 1173 status_t error = find_directory(directoryConstants[i], &path); 1174 if (error == B_OK && path.Append("licenses") == B_OK 1175 && path.Append(license) == B_OK 1176 && lstat(path.Path(), &st) == 0) { 1177 return B_OK; 1178 } 1179 } 1180 1181 path.Unset(); 1182 return B_ENTRY_NOT_FOUND; 1183 } 1184 1185 1186 void 1187 AboutView::_AddCopyrightsFromAttribute() 1188 { 1189 #ifdef __HAIKU__ 1190 // open the app executable file 1191 char appPath[B_PATH_NAME_LENGTH]; 1192 int appFD; 1193 if (BPrivate::get_app_path(appPath) != B_OK 1194 || (appFD = open(appPath, O_RDONLY)) < 0) { 1195 return; 1196 } 1197 1198 // open the attribute 1199 int attrFD = fs_open_attr(appFD, "COPYRIGHTS", B_STRING_TYPE, O_RDONLY); 1200 close(appFD); 1201 if (attrFD < 0) 1202 return; 1203 1204 // attach it to a FILE 1205 FILE* attrFile = fdopen(attrFD, "r"); 1206 if (attrFile == NULL) { 1207 close(attrFD); 1208 return; 1209 } 1210 CObjectDeleter<FILE, int> _(attrFile, fclose); 1211 1212 // read and parse the copyrights 1213 BMessage package; 1214 BString fieldName; 1215 BString fieldValue; 1216 char lineBuffer[LINE_MAX]; 1217 while (char* line = fgets(lineBuffer, sizeof(lineBuffer), attrFile)) { 1218 // chop off line break 1219 size_t lineLen = strlen(line); 1220 if (lineLen > 0 && line[lineLen - 1] == '\n') 1221 line[--lineLen] = '\0'; 1222 1223 // flush previous field, if a new field begins, otherwise append 1224 if (lineLen == 0 || !isspace(line[0])) { 1225 // new field -- flush the previous one 1226 if (fieldName.Length() > 0) { 1227 fieldValue = trim_string(fieldValue.String(), 1228 fieldValue.Length()); 1229 package.AddString(fieldName.String(), fieldValue); 1230 fieldName = ""; 1231 } 1232 } else if (fieldName.Length() > 0) { 1233 // append to current field 1234 fieldValue += line; 1235 continue; 1236 } else { 1237 // bogus line -- ignore 1238 continue; 1239 } 1240 1241 if (lineLen == 0) 1242 continue; 1243 1244 // parse new field 1245 char* colon = strchr(line, ':'); 1246 if (colon == NULL) { 1247 // bogus line -- ignore 1248 continue; 1249 } 1250 1251 fieldName.SetTo(line, colon - line); 1252 fieldName = trim_string(line, colon - line); 1253 if (fieldName.Length() == 0) { 1254 // invalid field name 1255 continue; 1256 } 1257 1258 fieldValue = colon + 1; 1259 1260 if (fieldName == "Package") { 1261 // flush the current package 1262 _AddPackageCredit(PackageCredit(package)); 1263 package.MakeEmpty(); 1264 } 1265 } 1266 1267 // flush current package 1268 _AddPackageCredit(PackageCredit(package)); 1269 #endif 1270 } 1271 1272 1273 void 1274 AboutView::_AddPackageCreditEntries() 1275 { 1276 for (PackageCreditMap::iterator it = fPackageCredits.begin(); 1277 it != fPackageCredits.end(); ++it) { 1278 PackageCredit* package = it->second; 1279 1280 BString text(package->CopyrightAt(0)); 1281 int32 count = package->CountCopyrights(); 1282 for (int32 i = 1; i < count; i++) 1283 text << "\n" << package->CopyrightAt(i); 1284 1285 AddCopyrightEntry(package->PackageName(), text.String(), 1286 package->Licenses(), package->URL()); 1287 } 1288 } 1289 1290 1291 void 1292 AboutView::_AddPackageCredit(const PackageCredit& package) 1293 { 1294 if (!package.IsValid()) 1295 return; 1296 1297 PackageCreditMap::iterator it = fPackageCredits.find(package.PackageName()); 1298 if (it != fPackageCredits.end()) { 1299 // If the new package credit isn't "better" than the old one, ignore it. 1300 PackageCredit* oldPackage = it->second; 1301 if (!package.IsBetterThan(*oldPackage)) 1302 return; 1303 1304 // replace the old credit 1305 fPackageCredits.erase(it); 1306 delete oldPackage; 1307 } 1308 1309 fPackageCredits[package.PackageName()] = new PackageCredit(package); 1310 } 1311 1312 1313 // #pragma mark - 1314 1315 1316 static const char * 1317 MemUsageToString(char string[], size_t size, system_info *info) 1318 { 1319 snprintf(string, size, "%d MB total, %d MB used (%d%%)", 1320 int(info->max_pages / 256.0f + 0.5f), 1321 int(info->used_pages / 256.0f + 0.5f), 1322 int(100 * info->used_pages / info->max_pages)); 1323 1324 return string; 1325 } 1326 1327 1328 static const char * 1329 UptimeToString(char string[], size_t size) 1330 { 1331 int64 days, hours, minutes, seconds, remainder; 1332 int64 systime = system_time(); 1333 1334 days = systime / 86400000000LL; 1335 remainder = systime % 86400000000LL; 1336 1337 hours = remainder / 3600000000LL; 1338 remainder = remainder % 3600000000LL; 1339 1340 minutes = remainder / 60000000; 1341 remainder = remainder % 60000000; 1342 1343 seconds = remainder / 1000000; 1344 1345 char *str = string; 1346 if (days) { 1347 str += snprintf(str, size, "%lld day%s",days, days > 1 ? "s" : ""); 1348 } 1349 if (hours) { 1350 str += snprintf(str, size - strlen(string), "%s%lld hour%s", 1351 str != string ? ", " : "", 1352 hours, hours > 1 ? "s" : ""); 1353 } 1354 if (minutes) { 1355 str += snprintf(str, size - strlen(string), "%s%lld minute%s", 1356 str != string ? ", " : "", 1357 minutes, minutes > 1 ? "s" : ""); 1358 } 1359 1360 if (seconds || str == string) { 1361 // Haiku would be well-known to boot very fast. 1362 // Let's be ready to handle below minute uptime, zero second included ;-) 1363 str += snprintf(str, size - strlen(string), "%s%lld second%s", 1364 str != string ? ", " : "", 1365 seconds, seconds > 1 ? "s" : ""); 1366 } 1367 1368 return string; 1369 } 1370 1371 1372 int 1373 main() 1374 { 1375 AboutApp app; 1376 app.Run(); 1377 return 0; 1378 } 1379 1380