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