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