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