1 /* 2 * Copyright (c) 2005-2007, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Author: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 */ 8 9 10 #include <AppFileInfo.h> 11 #include <Application.h> 12 #include <Bitmap.h> 13 #include <File.h> 14 #include <FindDirectory.h> 15 #include <Font.h> 16 #include <MessageRunner.h> 17 #include <Messenger.h> 18 #include <OS.h> 19 #include <Path.h> 20 #include <Query.h> 21 #include <Resources.h> 22 #include <Screen.h> 23 #include <ScrollView.h> 24 #include <String.h> 25 #include <StringView.h> 26 #include <TextView.h> 27 #include <TranslationUtils.h> 28 #include <TranslatorFormats.h> 29 #include <View.h> 30 #include <Volume.h> 31 #include <VolumeRoster.h> 32 #include <Window.h> 33 34 #include <cpu_type.h> 35 36 #include <stdio.h> 37 #include <time.h> 38 #include <sys/utsname.h> 39 40 41 #define SCROLL_CREDITS_VIEW 'mviv' 42 #define READ_APP_QUERY_ENT 'raqe' 43 44 45 static const char *UptimeToString(char string[], size_t size); 46 static const char *MemUsageToString(char string[], size_t size); 47 48 static const rgb_color kDarkGrey = { 100, 100, 100, 255 }; 49 static const rgb_color kHaikuGreen = { 42, 131, 36, 255 }; 50 static const rgb_color kHaikuOrange = { 255, 69, 0, 255 }; 51 static const rgb_color kHaikuYellow = { 255, 176, 0, 255 }; 52 static const rgb_color kLinkBlue = { 80, 80, 200, 255 }; 53 54 55 class AboutApp : public BApplication { 56 public: 57 AboutApp(void); 58 }; 59 60 class AboutWindow : public BWindow { 61 public: 62 AboutWindow(void); 63 bool QuitRequested(void); 64 }; 65 66 class AboutView : public BView { 67 public: 68 AboutView(const BRect &r); 69 ~AboutView(void); 70 71 virtual void AttachedToWindow(); 72 virtual void Pulse(); 73 74 virtual void FrameResized(float width, float height); 75 virtual void Draw(BRect update); 76 virtual void MessageReceived(BMessage *msg); 77 virtual void MouseDown(BPoint pt); 78 79 void AddCopyrightEntry(const char *name, const char *text, const char *url=NULL); 80 void PickRandomHaiku(); 81 82 private: 83 BStringView *fMemView; 84 BStringView *fUptimeView; 85 BView *fInfoView; 86 BTextView *fCreditsView; 87 88 BBitmap *fLogo; 89 90 BPoint fDrawPoint; 91 92 bigtime_t fLastActionTime; 93 BMessageRunner *fScrollRunner; 94 BQuery fAppsQuery; 95 }; 96 97 98 // #pragma mark - 99 100 101 AboutApp::AboutApp(void) 102 : BApplication("application/x-vnd.Haiku-About") 103 { 104 AboutWindow *window = new AboutWindow(); 105 window->Show(); 106 } 107 108 109 // #pragma mark - 110 111 112 AboutWindow::AboutWindow() 113 : BWindow(BRect(0, 0, 500, 300), "About This System", B_TITLED_WINDOW, 114 B_NOT_RESIZABLE | B_NOT_ZOOMABLE) 115 { 116 AboutView *view = new AboutView(Bounds()); 117 AddChild(view); 118 119 // start reading from the app query 120 BMessage msg(READ_APP_QUERY_ENT); 121 BMessenger msgr(view); 122 msgr.SendMessage(&msg); 123 124 MoveTo((BScreen().Frame().Width() - Bounds().Width()) / 2, 125 (BScreen().Frame().Height() - Bounds().Height()) / 2 ); 126 } 127 128 129 bool 130 AboutWindow::QuitRequested() 131 { 132 be_app->PostMessage(B_QUIT_REQUESTED); 133 return true; 134 } 135 136 137 AboutView::AboutView(const BRect &rect) 138 : BView(rect, "aboutview", B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED), 139 fLastActionTime(system_time()), 140 fScrollRunner(NULL) 141 { 142 fLogo = BTranslationUtils::GetBitmap(B_PNG_FORMAT, "haikulogo.png"); 143 if (fLogo) { 144 fDrawPoint.x = (225-fLogo->Bounds().Width()) / 2; 145 fDrawPoint.y = 0; 146 } 147 148 // Begin Construction of System Information controls 149 150 font_height height; 151 float labelHeight, textHeight; 152 153 system_info systemInfo; 154 get_system_info(&systemInfo); 155 156 be_plain_font->GetHeight(&height); 157 textHeight = height.ascent + height.descent + height.leading; 158 159 be_bold_font->GetHeight(&height); 160 labelHeight = height.ascent + height.descent + height.leading; 161 162 BRect r(0, 0, 225, Bounds().bottom); 163 if (fLogo) 164 r.OffsetBy(0, fLogo->Bounds().Height()); 165 166 fInfoView = new BView(r, "infoview", B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, B_WILL_DRAW); 167 fInfoView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 168 fInfoView->SetLowColor(fInfoView->ViewColor()); 169 fInfoView->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); 170 AddChild(fInfoView); 171 172 // Add all the various labels for system infomation 173 174 BStringView *stringView; 175 176 // OS Version 177 r.Set(5, 5, 224, labelHeight + 5); 178 stringView = new BStringView(r, "oslabel", "Version:"); 179 stringView->SetFont(be_bold_font); 180 fInfoView->AddChild(stringView); 181 stringView->ResizeToPreferred(); 182 183 // we update "labelHeight" to the actual height of the string view 184 labelHeight = stringView->Bounds().Height(); 185 186 r.OffsetBy(0, labelHeight); 187 r.bottom = r.top + textHeight; 188 189 char string[256]; 190 strcpy(string, "Unknown"); 191 192 // the version is stored in the BEOS:APP_VERSION attribute of libbe.so 193 BPath path; 194 if (find_directory(B_BEOS_LIB_DIRECTORY, &path) == B_OK) { 195 path.Append("libbe.so"); 196 197 BAppFileInfo appFileInfo; 198 version_info versionInfo; 199 BFile file; 200 if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK 201 && appFileInfo.SetTo(&file) == B_OK 202 && appFileInfo.GetVersionInfo(&versionInfo, B_APP_VERSION_KIND) == B_OK 203 && versionInfo.short_info[0] != '\0') 204 strcpy(string, versionInfo.short_info); 205 } 206 207 // Add revision from uname() info 208 utsname unameInfo; 209 if (uname(&unameInfo) == 0) { 210 long revision; 211 if (sscanf(unameInfo.version, "r%ld", &revision) == 1) { 212 char version[16]; 213 snprintf(version, sizeof(version), "%ld", revision); 214 strlcat(string, " (Revision ", sizeof(string)); 215 strlcat(string, version, sizeof(string)); 216 strlcat(string, ")", sizeof(string)); 217 } 218 } 219 220 stringView = new BStringView(r, "ostext", string); 221 fInfoView->AddChild(stringView); 222 stringView->ResizeToPreferred(); 223 224 // CPU count, type and clock speed 225 r.OffsetBy(0, textHeight * 1.5); 226 r.bottom = r.top + labelHeight; 227 228 if (systemInfo.cpu_count > 1) 229 sprintf(string, "%ld Processors:", systemInfo.cpu_count); 230 else 231 strcpy(string, "Processor:"); 232 233 stringView = new BStringView(r, "cpulabel", string); 234 stringView->SetFont(be_bold_font); 235 fInfoView->AddChild(stringView); 236 stringView->ResizeToPreferred(); 237 238 239 BString cpuType; 240 cpuType << get_cpu_vendor_string(systemInfo.cpu_type) 241 << " " << get_cpu_model_string(&systemInfo); 242 243 r.OffsetBy(0, labelHeight); 244 r.bottom = r.top + textHeight; 245 stringView = new BStringView(r, "cputext", cpuType.String()); 246 fInfoView->AddChild(stringView); 247 stringView->ResizeToPreferred(); 248 249 r.OffsetBy(0, textHeight); 250 r.bottom = r.top + textHeight; 251 252 int32 clockSpeed = get_rounded_cpu_speed(); 253 if (clockSpeed < 1000) 254 sprintf(string,"%ld MHz", clockSpeed); 255 else 256 sprintf(string,"%.2f GHz", clockSpeed / 1000.0f); 257 258 stringView = new BStringView(r, "mhztext", string); 259 fInfoView->AddChild(stringView); 260 stringView->ResizeToPreferred(); 261 262 // RAM 263 r.OffsetBy(0, textHeight * 1.5); 264 r.bottom = r.top + labelHeight; 265 stringView = new BStringView(r, "ramlabel", "Memory:"); 266 stringView->SetFont(be_bold_font); 267 fInfoView->AddChild(stringView); 268 stringView->ResizeToPreferred(); 269 270 r.OffsetBy(0, labelHeight); 271 r.bottom = r.top + textHeight; 272 273 fMemView = new BStringView(r, "ramtext", ""); 274 fInfoView->AddChild(fMemView); 275 //fMemView->ResizeToPreferred(); 276 277 fMemView->SetText(MemUsageToString(string, sizeof(string))); 278 279 // Kernel build time/date 280 r.OffsetBy(0, textHeight * 1.5); 281 r.bottom = r.top + labelHeight; 282 stringView = new BStringView(r, "kernellabel", "Kernel:"); 283 stringView->SetFont(be_bold_font); 284 fInfoView->AddChild(stringView); 285 stringView->ResizeToPreferred(); 286 287 r.OffsetBy(0, labelHeight); 288 r.bottom = r.top + textHeight; 289 290 snprintf(string, sizeof(string), "%s %s", 291 systemInfo.kernel_build_date, systemInfo.kernel_build_time); 292 293 stringView = new BStringView(r, "kerneltext", string); 294 fInfoView->AddChild(stringView); 295 stringView->ResizeToPreferred(); 296 297 // Uptime 298 r.OffsetBy(0, textHeight * 1.5); 299 r.bottom = r.top + labelHeight; 300 stringView = new BStringView(r, "uptimelabel", "Time Running:"); 301 stringView->SetFont(be_bold_font); 302 fInfoView->AddChild(stringView); 303 stringView->ResizeToPreferred(); 304 305 r.OffsetBy(0, labelHeight); 306 r.bottom = r.top + textHeight; 307 308 fUptimeView = new BStringView(r, "uptimetext", ""); 309 fInfoView->AddChild(fUptimeView); 310 // string width changes, so we don't do ResizeToPreferred() 311 312 fUptimeView->SetText(UptimeToString(string, sizeof(string))); 313 314 // Begin construction of the credits view 315 r = Bounds(); 316 r.left += fInfoView->Bounds().right + 1; 317 r.right -= B_V_SCROLL_BAR_WIDTH; 318 319 fCreditsView = new BTextView(r, "credits", 320 r.OffsetToCopy(0, 0).InsetByCopy(5, 5), B_FOLLOW_ALL); 321 fCreditsView->SetFlags(fCreditsView->Flags() | B_FRAME_EVENTS ); 322 fCreditsView->SetStylable(true); 323 fCreditsView->MakeEditable(false); 324 fCreditsView->MakeSelectable(false); 325 fCreditsView->SetWordWrap(true); 326 327 BScrollView *creditsScroller = new BScrollView("creditsScroller", 328 fCreditsView, B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS, false, true, B_PLAIN_BORDER); 329 AddChild(creditsScroller); 330 331 BFont font(be_bold_font); 332 font.SetSize(font.Size() + 4); 333 334 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen); 335 fCreditsView->Insert("Haiku\n"); 336 337 font.SetSize(be_bold_font->Size()); 338 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 339 340 time_t time = ::time(NULL); 341 struct tm* tm = localtime(&time); 342 int32 year = tm->tm_year + 1900; 343 if (year < 2007) 344 year = 2007; 345 snprintf(string, sizeof(string), 346 "Copyright " B_UTF8_COPYRIGHT "2001-%ld Haiku, Inc.\n", year); 347 348 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 349 fCreditsView->Insert(string); 350 351 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kLinkBlue); 352 fCreditsView->Insert("http://haiku-os.org\n\n"); 353 354 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 355 fCreditsView->Insert("Team Leads:\n"); 356 357 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 358 fCreditsView->Insert( 359 "Axel Dörfler\n" 360 "Phil Greenway\n" 361 "Philippe Houdoin\n" 362 "Marcus Overhagen\n" 363 "Ingo Weinhold\n" 364 "Jonathan Yoder\n" 365 "\n"); 366 367 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 368 fCreditsView->Insert("Developers:\n"); 369 370 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 371 fCreditsView->Insert( 372 "Ithamar R. Adema\n" 373 "Bruno G. Albuquerque\n" 374 "Stephan Aßmus\n" 375 "Andrew Bachmann\n" 376 "Salvatore Benedetto\n" 377 "Stefano Ceccherini\n" 378 "Rudolf Cornelissen\n" 379 "Alexandre Deckner\n" 380 "Oliver Ruiz Dorantes\n" 381 "Jérôme Duval\n" 382 "Andre Alves Garzia\n" 383 "René Gollent\n" 384 "Karsten Heimrich\n" 385 "Euan Kirkhope\n" 386 "Waldemar Kornewald\n" 387 "Ryan Leavengood\n" 388 "Michael Lotz\n" 389 "David McPaul\n" 390 "Michael Pfeiffer\n" 391 "Niels Sascha Reedijk\n" 392 "Jonas Sundström\n" 393 "François Revol\n" 394 "Hugo Santos\n" 395 "Gerasim Troeglazov\n" 396 "Bryan Varner\n" 397 "Siarzhuk Zharski\n" 398 "\n"); 399 400 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 401 fCreditsView->Insert("Contributors:\n"); 402 403 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 404 fCreditsView->Insert( 405 "Andrea Anzani\n" 406 "Andre Braga\n" 407 "Bruce Cameron\n" 408 "Greg Crain\n" 409 "Tyler Dauwalder\n" 410 "John Drinkwater\n" 411 "Cian Duffy\n" 412 "Marc Flerackers\n" 413 "Daniel Furrer\n" 414 "Matthijs Hollemans\n" 415 "Morgan Howe\n" 416 "Erik Jaesler\n" 417 "Carwyn Jones\n" 418 "Maurice Kalinowski\n" 419 "Vasilis Kaoutsis\n" 420 "James Kim\n" 421 "Jan Klötzke\n" 422 "Marcin Konicki\n" 423 "Kurtis Kopf\n" 424 "Waldemar Kornewald\n" 425 "Tomáš Kučera\n" 426 "Luboš Kulič\n" 427 "Thomas Kurschel\n" 428 "Elad Lahav\n" 429 "Anthony Lee\n" 430 "Santiago Lema\n" 431 "Oscar Lesta\n" 432 "Jerome Leveque\n" 433 "Christof Lutteroth\n" 434 "Graham MacDonald\n" 435 "Jan Matějek\n" 436 "Brian Matzon\n" 437 "Christopher ML Zumwalt May\n" 438 "Andrew McCall\n" 439 "Michele (zuMi)\n" 440 "Misza\n" 441 "MrSiggler\n" 442 "Alan Murta\n" 443 "Frans Van Nispen\n" 444 "Adi Oanca\n" 445 "Pahtz\n" 446 "Michael Paine\n" 447 "Michael Phipps\n" 448 "Jeremy Rand\n" 449 "Hartmut Reh\n" 450 "David Reid\n" 451 "Daniel Reinhold\n" 452 "Samuel Rodriguez Perez\n" 453 "Thomas Roell\n" 454 "Rafael Romo\n" 455 "Reznikov Sergei\n" 456 "Zousar Shaker\n" 457 "Alexander G. M. Smith\n" 458 "Daniel Switkin\n" 459 "Atsushi Takamatsu\n" 460 "Oliver Tappe\n" 461 "James Urquhart\n" 462 "Jason Vandermark\n" 463 "Sandor Vroemisse\n" 464 "Denis Washington\n" 465 "Nathan Whitehorn\n" 466 "Michael Wilber\n" 467 "Ulrich Wimboeck\n" 468 "Artur Wyszynski\n" 469 "Gabe Yoder\n" 470 "Gerald Zajac\n" 471 "Łukasz Zemczak\n" 472 "JiSheng Zhang\n" 473 "\n" B_UTF8_ELLIPSIS " and probably some more we forgot to mention (sorry!)" 474 "\n\n"); 475 476 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 477 fCreditsView->Insert("Special Thanks To:\n"); 478 479 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 480 fCreditsView->Insert("Travis Geiselbrecht (and his NewOS kernel)\n"); 481 fCreditsView->Insert("Michael Phipps (project founder)\n\n"); 482 483 // copyrights for various projects we use 484 485 font.SetSize(be_bold_font->Size() + 4); 486 font.SetFace(B_BOLD_FACE); 487 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen); 488 fCreditsView->Insert("\nCopyrights\n\n"); 489 490 // GNU copyrights 491 AddCopyrightEntry("The GNU Project", 492 "Contains software from the GNU Project, " 493 "released under the GPL and LGPL licences:\n" 494 " - GNU C Library,\n" 495 " - GNU coretools, diffutils, findutils, gawk, bison, m4, make,\n" 496 " - Bourne Again Shell.\n" 497 "Copyright " B_UTF8_COPYRIGHT " The Free Software Foundation.", 498 "www.gnu.org"); 499 500 // FFMpeg copyrights 501 AddCopyrightEntry("FFMpeg libavcodec", 502 "Copyright " B_UTF8_COPYRIGHT " 2000-2007 Fabrice Bellard, et al.", 503 "www.ffmpeg.org"); 504 505 // AGG copyrights 506 AddCopyrightEntry("AntiGrain Geometry", 507 "Copyright " B_UTF8_COPYRIGHT " 2002-2006 Maxim Shemanarev (McSeem).", 508 "www.antigrain.com"); 509 510 // PDFLib copyrights 511 AddCopyrightEntry("PDFLib", 512 "Copyright " B_UTF8_COPYRIGHT " 1997-2006 PDFlib GmbH and Thomas Merz. " 513 "All rights reserved.\n" 514 "PDFlib and the PDFlib logo are registered trademarks of PDFlib GmbH.", 515 "www.pdflib.com"); 516 517 // FreeType copyrights 518 AddCopyrightEntry("FreeType2", 519 "Portions of this software are copyright " B_UTF8_COPYRIGHT " 1996-2006 The FreeType" 520 " Project. All rights reserved.", 521 "www.freetype.org"); 522 523 // Mesa3D (http://www.mesa3d.org) copyrights 524 AddCopyrightEntry("Mesa", 525 "Copyright " B_UTF8_COPYRIGHT " 1999-2006 Brian Paul. " 526 "Mesa3D project. All rights reserved.", 527 "www.mesa3d.org"); 528 529 // SGI's GLU implementation copyrights 530 AddCopyrightEntry("GLU", 531 "Copyright " B_UTF8_COPYRIGHT " 1991-2000 Silicon Graphics, Inc. " 532 "SGI's Software FreeB license. All rights reserved."); 533 534 // GLUT implementation copyrights 535 AddCopyrightEntry("GLUT", 536 "Copyright " B_UTF8_COPYRIGHT " 1994-1997 Mark Kilgard. " 537 "All rights reserved.\n" 538 "Copyright " B_UTF8_COPYRIGHT " 1997 Be Inc.\n" 539 "Copyright " B_UTF8_COPYRIGHT " 1999 Jake Hamby."); 540 541 // OpenGroup & DEC (BRegion backend) copyright 542 AddCopyrightEntry("BRegion backend (XFree86)", 543 "Copyright " B_UTF8_COPYRIGHT " 1987, 1988, 1998 The Open Group.\n" 544 "Copyright " B_UTF8_COPYRIGHT " 1987, 1988 Digital Equipment Corporation, Maynard, Massachusetts.\n" 545 "All rights reserved."); 546 547 // Konatu font 548 AddCopyrightEntry("Konatu font", 549 "Copyright " B_UTF8_COPYRIGHT " 2002- MASUDA mitiya.\n" 550 "MIT license. All rights reserved."); 551 552 // expat copyrights 553 AddCopyrightEntry("expat", 554 "Copyright " B_UTF8_COPYRIGHT " 1998, 1999, 2000 Thai Open Source Software Center Ltd and Clark Cooper.\n" 555 "Copyright " B_UTF8_COPYRIGHT " 2001, 2002, 2003 Expat maintainers."); 556 557 // zlib copyrights 558 AddCopyrightEntry("zlib", 559 "Copyright " B_UTF8_COPYRIGHT " 1995-2004 Jean-loup Gailly and Mark Adler."); 560 561 // zip copyrights 562 AddCopyrightEntry("Info-ZIP", 563 "Copyright " B_UTF8_COPYRIGHT " 1990-2002 Info-ZIP. All rights reserved."); 564 565 // bzip2 copyrights 566 AddCopyrightEntry("bzip2", 567 "Copyright " B_UTF8_COPYRIGHT " 1996-2005 Julian R Seward. All rights reserved."); 568 569 // VIM copyrights 570 AddCopyrightEntry("Vi IMproved", 571 "Copyright " B_UTF8_COPYRIGHT " Bram Moolenaar et al."); 572 573 // lp_solve copyrights 574 // TODO: Fix! 575 AddCopyrightEntry("lp_solve", 576 "Copyright " B_UTF8_COPYRIGHT 577 " ??? (http://lpsolve.sourceforge.net/)."); 578 579 // OpenEXR copyrights 580 AddCopyrightEntry("OpenEXR", 581 "Copyright " B_UTF8_COPYRIGHT " 2002-2005, Industrial Light & Magic, a division of Lucas Digital Ltd. LLC."); 582 583 // Bullet copyrights 584 AddCopyrightEntry("Bullet", 585 "Copyright " B_UTF8_COPYRIGHT " 2003-2008 Erwin Coumans", 586 "www.bulletphysics.com"); 587 588 // Build a list of installed applications and show their 589 // long version info. Well-behaved apps usually give 590 // copyright info there. 591 592 font.SetSize(be_bold_font->Size() + 4); 593 font.SetFace(B_BOLD_FACE); 594 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen); 595 fCreditsView->Insert("\nInstalled applications\n\n"); 596 597 BVolume bootVolume; 598 BVolumeRoster().GetBootVolume(&bootVolume); 599 fAppsQuery.SetVolume(&bootVolume); 600 if (fAppsQuery.SetPredicate("((BEOS:APP_SIG==\"**\")&&(name!=\"*.so\")&&(name!=\"*.rsrc\")&&" 601 "(BEOS:TYPE==\"application/x-vnd.Be-elfexecutable\"))") >= B_OK) { 602 fAppsQuery.Fetch(); 603 } 604 } 605 606 607 AboutView::~AboutView(void) 608 { 609 delete fScrollRunner; 610 } 611 612 613 void 614 AboutView::AttachedToWindow(void) 615 { 616 BView::AttachedToWindow(); 617 Window()->SetPulseRate(500000); 618 SetEventMask(B_POINTER_EVENTS); 619 } 620 621 622 void 623 AboutView::MouseDown(BPoint pt) 624 { 625 BRect r(92, 26, 105, 31); 626 if (r.Contains(pt)) { 627 printf("Easter Egg\n"); 628 PickRandomHaiku(); 629 } 630 631 if (Bounds().Contains(pt)) { 632 fLastActionTime = system_time(); 633 delete fScrollRunner; 634 fScrollRunner = NULL; 635 } 636 } 637 638 639 void 640 AboutView::FrameResized(float width, float height) 641 { 642 BRect r = fCreditsView->Bounds(); 643 r.OffsetTo(B_ORIGIN); 644 r.InsetBy(3, 3); 645 fCreditsView->SetTextRect(r); 646 } 647 648 649 void 650 AboutView::Draw(BRect update) 651 { 652 if (fLogo) 653 DrawBitmap(fLogo, fDrawPoint); 654 } 655 656 657 void 658 AboutView::Pulse(void) 659 { 660 char string[255]; 661 662 fUptimeView->SetText(UptimeToString(string, sizeof(string))); 663 fMemView->SetText(MemUsageToString(string, sizeof(string))); 664 665 if (fScrollRunner == NULL && (system_time() > fLastActionTime + 10000000)) { 666 BMessage message(SCROLL_CREDITS_VIEW); 667 //fScrollRunner = new BMessageRunner(this, &message, 300000, -1); 668 } 669 } 670 671 672 void 673 AboutView::MessageReceived(BMessage *msg) 674 { 675 switch (msg->what) { 676 case SCROLL_CREDITS_VIEW: 677 { 678 BScrollBar *scrollBar = fCreditsView->ScrollBar(B_VERTICAL); 679 if (scrollBar == NULL) 680 break; 681 float max, min; 682 scrollBar->GetRange(&min, &max); 683 if (scrollBar->Value() < max) 684 fCreditsView->ScrollBy(0, 5); 685 686 break; 687 } 688 689 case READ_APP_QUERY_ENT: 690 { 691 BEntry ent; 692 if (fAppsQuery.GetNextEntry(&ent) < B_OK) { 693 fAppsQuery.Clear(); 694 fCreditsView->MakeSelectable(true); 695 break; 696 } 697 BFile file; 698 BPath path; 699 if (ent.Exists() && 700 ent.GetPath(&path) >= B_OK && 701 file.SetTo(&ent, B_READ_ONLY) >= B_OK) { 702 /* filter only apps */ 703 if (strncmp(path.Path(), "/boot/apps", 10) == 0) { 704 BAppFileInfo appFileInfo(&file); 705 uint32 flags; 706 version_info version; 707 if (appFileInfo.InitCheck() >= B_OK && 708 appFileInfo.GetAppFlags(&flags) >= B_OK && 709 appFileInfo.GetVersionInfo(&version, B_APP_VERSION_KIND) >= B_OK) { 710 //printf("AppFileInfo for %s :\n", path.Path()); 711 //printf("flags: %08x\n", flags); 712 BString name; 713 BString info; 714 name << path.Leaf(); 715 if (strlen(version.short_info) && 716 strcmp(version.short_info, path.Leaf())) 717 name << " (" << version.short_info << ")"; 718 /* 719 info << "\tVersion: "; 720 info << version.major << "."; 721 info << version.middle << "."; 722 info << version.minor; 723 char varieties[] = "dabgmf"; 724 if (version.variety > B_FINAL_VERSION) 725 info << "?"; 726 else 727 info << varieties[version.variety]; 728 info << version.internal; 729 info << "\n"; 730 */ 731 info << version.long_info; 732 AddCopyrightEntry(name.String(), info.String()); 733 734 } 735 } 736 } 737 // note for self: read next entry :) 738 BMessage m(READ_APP_QUERY_ENT); 739 BMessenger(this).SendMessage(&m); 740 break; 741 } 742 743 default: 744 BView::MessageReceived(msg); 745 break; 746 } 747 } 748 749 750 void 751 AboutView::AddCopyrightEntry(const char *name, const char *text, const char *url) 752 { 753 BFont font(be_bold_font); 754 //font.SetSize(be_bold_font->Size()); 755 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 756 757 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuYellow); 758 fCreditsView->Insert(name); 759 fCreditsView->Insert("\n"); 760 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 761 fCreditsView->Insert(text); 762 fCreditsView->Insert("\n"); 763 if (url) { 764 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kLinkBlue); 765 fCreditsView->Insert(url); 766 fCreditsView->Insert("\n"); 767 } 768 fCreditsView->Insert("\n"); 769 } 770 771 void 772 AboutView::PickRandomHaiku() 773 { 774 BFile fortunes( 775 #ifdef __HAIKU__ 776 "/etc/fortunes/Haiku", 777 #else 778 "data/etc/fortunes/Haiku", 779 #endif 780 B_READ_ONLY); 781 struct stat st; 782 if (fortunes.InitCheck() < B_OK) 783 return; 784 if (fortunes.GetStat(&st) < B_OK) 785 return; 786 char *buff = (char *)malloc((size_t)st.st_size + 1); 787 if (!buff) 788 return; 789 buff[(size_t)st.st_size] = '\0'; 790 BList haikuList; 791 if (fortunes.Read(buff, (size_t)st.st_size) == (ssize_t)st.st_size) { 792 char *p = buff; 793 while (p && *p) { 794 char *e = strchr(p, '%'); 795 BString *s = new BString(p, e ? (e - p) : -1); 796 haikuList.AddItem(s); 797 p = e; 798 if (p && (*p == '%')) 799 p++; 800 if (p && (*p == '\n')) 801 p++; 802 } 803 } 804 free(buff); 805 if (haikuList.CountItems() < 1) 806 return; 807 BString *s = (BString *)haikuList.ItemAt(rand() % haikuList.CountItems()); 808 BFont font(be_bold_font); 809 font.SetSize(be_bold_font->Size()); 810 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 811 fCreditsView->SelectAll(); 812 fCreditsView->Delete(); 813 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kDarkGrey); 814 fCreditsView->Insert(s->String()); 815 fCreditsView->Insert("\n"); 816 while ((s = (BString *)haikuList.RemoveItem((int32)0))) { 817 delete s; 818 } 819 } 820 821 822 // #pragma mark - 823 824 825 static const char * 826 MemUsageToString(char string[], size_t size) 827 { 828 system_info systemInfo; 829 830 if (get_system_info(&systemInfo) < B_OK) 831 return "Unknown"; 832 833 snprintf(string, size, "%d MB total, %d MB used (%d%%)", 834 int(systemInfo.max_pages / 256.0f + 0.5f), 835 int(systemInfo.used_pages / 256.0f + 0.5f), 836 int(100 * systemInfo.used_pages / systemInfo.max_pages)); 837 838 return string; 839 } 840 841 842 static const char * 843 UptimeToString(char string[], size_t size) 844 { 845 int64 days, hours, minutes, seconds, remainder; 846 int64 systime = system_time(); 847 848 days = systime / 86400000000LL; 849 remainder = systime % 86400000000LL; 850 851 hours = remainder / 3600000000LL; 852 remainder = remainder % 3600000000LL; 853 854 minutes = remainder / 60000000; 855 remainder = remainder % 60000000; 856 857 seconds = remainder / 1000000; 858 859 char *str = string; 860 if (days) { 861 str += snprintf(str, size, "%lld day%s",days, days > 1 ? "s" : ""); 862 } 863 if (hours) { 864 str += snprintf(str, size - strlen(string), "%s%lld hour%s", 865 str != string ? ", " : "", 866 hours, hours > 1 ? "s" : ""); 867 } 868 if (minutes) { 869 str += snprintf(str, size - strlen(string), "%s%lld minute%s", 870 str != string ? ", " : "", 871 minutes, minutes > 1 ? "s" : ""); 872 } 873 874 if (seconds || str == string) { 875 // Haiku would be well-known to boot very fast. 876 // Let's be ready to handle below minute uptime, zero second included ;-) 877 str += snprintf(str, size - strlen(string), "%s%lld second%s", 878 str != string ? ", " : "", 879 seconds, seconds > 1 ? "s" : ""); 880 } 881 882 return string; 883 } 884 885 886 int 887 main() 888 { 889 AboutApp app; 890 app.Run(); 891 return 0; 892 } 893 894