2 * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
3 * Copyright 2013, Rene Gollent <rene@gollent.com>.
4 * Copyright 2016-2017, Andrew Lindesay <apl@lindesay.co.nz>.
5 * All rights reserved. Distributed under the terms of the MIT License.
8 #include "PackageInfo.h"
12 #include <FindDirectory.h>
13 #include <package/PackageDefs.h>
14 #include <package/PackageFlags.h>
19 // #pragma mark - UserInfo
30 UserInfo::UserInfo(const BString
& nickName
)
38 UserInfo::UserInfo(const BitmapRef
& avatar
, const BString
& nickName
)
46 UserInfo::UserInfo(const UserInfo
& other
)
48 fAvatar(other
.fAvatar
),
49 fNickName(other
.fNickName
)
55 UserInfo::operator=(const UserInfo
& other
)
57 fAvatar
= other
.fAvatar
;
58 fNickName
= other
.fNickName
;
64 UserInfo::operator==(const UserInfo
& other
) const
66 return fAvatar
== other
.fAvatar
67 && fNickName
== other
.fNickName
;
72 UserInfo::operator!=(const UserInfo
& other
) const
74 return !(*this == other
);
78 // #pragma mark - UserRating
81 UserRating::UserRating()
94 UserRating::UserRating(const UserInfo
& userInfo
, float rating
,
95 const BString
& comment
, const BString
& language
,
96 const BString
& packageVersion
, int32 upVotes
, int32 downVotes
)
102 fPackageVersion(packageVersion
),
104 fDownVotes(downVotes
)
109 UserRating::UserRating(const UserRating
& other
)
111 fUserInfo(other
.fUserInfo
),
112 fRating(other
.fRating
),
113 fComment(other
.fComment
),
114 fLanguage(other
.fLanguage
),
115 fPackageVersion(other
.fPackageVersion
),
116 fUpVotes(other
.fUpVotes
),
117 fDownVotes(other
.fDownVotes
)
123 UserRating::operator=(const UserRating
& other
)
125 fUserInfo
= other
.fUserInfo
;
126 fRating
= other
.fRating
;
127 fComment
= other
.fComment
;
128 fLanguage
= other
.fLanguage
;
129 fPackageVersion
= other
.fPackageVersion
;
130 fUpVotes
= other
.fUpVotes
;
131 fDownVotes
= other
.fDownVotes
;
137 UserRating::operator==(const UserRating
& other
) const
139 return fUserInfo
== other
.fUserInfo
140 && fRating
== other
.fRating
141 && fComment
== other
.fComment
142 && fLanguage
== other
.fLanguage
143 && fPackageVersion
== other
.fPackageVersion
144 && fUpVotes
== other
.fUpVotes
145 && fDownVotes
== other
.fDownVotes
;
150 UserRating::operator!=(const UserRating
& other
) const
152 return !(*this == other
);
156 // #pragma mark - RatingSummary
159 RatingSummary::RatingSummary()
164 for (int i
= 0; i
< 5; i
++)
165 ratingCountByStar
[i
] = 0;
169 RatingSummary::RatingSummary(const RatingSummary
& other
)
176 RatingSummary::operator=(const RatingSummary
& other
)
178 averageRating
= other
.averageRating
;
179 ratingCount
= other
.ratingCount
;
181 for (int i
= 0; i
< 5; i
++)
182 ratingCountByStar
[i
] = other
.ratingCountByStar
[i
];
189 RatingSummary::operator==(const RatingSummary
& other
) const
191 if (averageRating
!= other
.averageRating
192 || ratingCount
!= other
.ratingCount
) {
196 for (int i
= 0; i
< 5; i
++) {
197 if (ratingCountByStar
[i
] != other
.ratingCountByStar
[i
])
206 RatingSummary::operator!=(const RatingSummary
& other
) const
208 return !(*this == other
);
212 // #pragma mark - StabilityRating
215 StabilityRating::StabilityRating()
223 StabilityRating::StabilityRating(const BString
& label
,
232 StabilityRating::StabilityRating(const StabilityRating
& other
)
234 fLabel(other
.fLabel
),
241 StabilityRating::operator=(const StabilityRating
& other
)
243 fLabel
= other
.fLabel
;
250 StabilityRating::operator==(const StabilityRating
& other
) const
252 return fLabel
== other
.fLabel
253 && fName
== other
.fName
;
258 StabilityRating::operator!=(const StabilityRating
& other
) const
260 return !(*this == other
);
264 // #pragma mark - PublisherInfo
267 PublisherInfo::PublisherInfo()
277 PublisherInfo::PublisherInfo(const BitmapRef
& logo
, const BString
& name
,
278 const BString
& email
, const BString
& website
)
288 PublisherInfo::PublisherInfo(const PublisherInfo
& other
)
292 fEmail(other
.fEmail
),
293 fWebsite(other
.fWebsite
)
299 PublisherInfo::operator=(const PublisherInfo
& other
)
303 fEmail
= other
.fEmail
;
304 fWebsite
= other
.fWebsite
;
310 PublisherInfo::operator==(const PublisherInfo
& other
) const
312 return fLogo
== other
.fLogo
313 && fName
== other
.fName
314 && fEmail
== other
.fEmail
315 && fWebsite
== other
.fWebsite
;
320 PublisherInfo::operator!=(const PublisherInfo
& other
) const
322 return !(*this == other
);
326 // #pragma mark - PackageCategory
329 PackageCategory::PackageCategory()
339 PackageCategory::PackageCategory(const BitmapRef
& icon
, const BString
& label
,
350 PackageCategory::PackageCategory(const PackageCategory
& other
)
354 fLabel(other
.fLabel
),
361 PackageCategory::operator=(const PackageCategory
& other
)
364 fLabel
= other
.fLabel
;
371 PackageCategory::operator==(const PackageCategory
& other
) const
373 return fIcon
== other
.fIcon
374 && fLabel
== other
.fLabel
375 && fName
== other
.fName
;
380 PackageCategory::operator!=(const PackageCategory
& other
) const
382 return !(*this == other
);
386 // #pragma mark - ScreenshotInfo
389 ScreenshotInfo::ScreenshotInfo()
399 ScreenshotInfo::ScreenshotInfo(const BString
& code
,
400 int32 width
, int32 height
, int32 dataSize
)
410 ScreenshotInfo::ScreenshotInfo(const ScreenshotInfo
& other
)
413 fWidth(other
.fWidth
),
414 fHeight(other
.fHeight
),
415 fDataSize(other
.fDataSize
)
421 ScreenshotInfo::operator=(const ScreenshotInfo
& other
)
424 fWidth
= other
.fWidth
;
425 fHeight
= other
.fHeight
;
426 fDataSize
= other
.fDataSize
;
432 ScreenshotInfo::operator==(const ScreenshotInfo
& other
) const
434 return fCode
== other
.fCode
435 && fWidth
== other
.fWidth
436 && fHeight
== other
.fHeight
437 && fDataSize
== other
.fDataSize
;
442 ScreenshotInfo::operator!=(const ScreenshotInfo
& other
) const
444 return !(*this == other
);
448 // #pragma mark - PackageInfo
452 PackageInfo::sDefaultIcon(new(std::nothrow
) SharedBitmap(
453 "application/x-vnd.haiku-package"), true);
456 PackageInfo::PackageInfo()
467 fCachedRatingSummary(),
472 fDownloadProgress(0.0),
474 fSystemDependency(false),
483 PackageInfo::PackageInfo(const BPackageInfo
& info
)
488 fVersion(info
.Version()),
490 fShortDescription(info
.Summary()),
491 fFullDescription(info
.Description()),
494 fCachedRatingSummary(),
499 fDownloadProgress(0.0),
500 fFlags(info
.Flags()),
501 fSystemDependency(false),
502 fArchitecture(info
.ArchitectureName()),
504 fFileName(info
.FileName()),
505 fSize(0) // TODO: Retrieve local file size
507 BString publisherURL
;
508 if (info
.URLList().CountStrings() > 0)
509 publisherURL
= info
.URLList().StringAt(0);
511 BString publisherName
= info
.Vendor();
512 const BStringList
& rightsList
= info
.CopyrightList();
513 if (rightsList
.CountStrings() > 0)
514 publisherName
= rightsList
.StringAt(0);
515 if (!publisherName
.IsEmpty())
516 publisherName
.Prepend("© ");
518 fPublisher
= PublisherInfo(BitmapRef(), publisherName
, "", publisherURL
);
522 PackageInfo::PackageInfo(const BString
& name
,
523 const BPackageVersion
& version
, const PublisherInfo
& publisher
,
524 const BString
& shortDescription
, const BString
& fullDescription
,
525 int32 flags
, const char* architecture
)
531 fPublisher(publisher
),
532 fShortDescription(shortDescription
),
533 fFullDescription(fullDescription
),
537 fCachedRatingSummary(),
542 fDownloadProgress(0.0),
544 fSystemDependency(false),
545 fArchitecture(architecture
),
553 PackageInfo::PackageInfo(const PackageInfo
& other
)
557 fTitle(other
.fTitle
),
558 fVersion(other
.fVersion
),
559 fPublisher(other
.fPublisher
),
560 fShortDescription(other
.fShortDescription
),
561 fFullDescription(other
.fFullDescription
),
562 fChangelog(other
.fChangelog
),
563 fCategories(other
.fCategories
),
564 fUserRatings(other
.fUserRatings
),
565 fCachedRatingSummary(other
.fCachedRatingSummary
),
566 fProminence(other
.fProminence
),
567 fScreenshotInfos(other
.fScreenshotInfos
),
568 fScreenshots(other
.fScreenshots
),
569 fState(other
.fState
),
570 fInstallationLocations(other
.fInstallationLocations
),
571 fDownloadProgress(other
.fDownloadProgress
),
572 fFlags(other
.fFlags
),
573 fSystemDependency(other
.fSystemDependency
),
574 fArchitecture(other
.fArchitecture
),
575 fLocalFilePath(other
.fLocalFilePath
),
576 fFileName(other
.fFileName
),
583 PackageInfo::operator=(const PackageInfo
& other
)
587 fTitle
= other
.fTitle
;
588 fVersion
= other
.fVersion
;
589 fPublisher
= other
.fPublisher
;
590 fShortDescription
= other
.fShortDescription
;
591 fFullDescription
= other
.fFullDescription
;
592 fChangelog
= other
.fChangelog
;
593 fCategories
= other
.fCategories
;
594 fUserRatings
= other
.fUserRatings
;
595 fCachedRatingSummary
= other
.fCachedRatingSummary
;
596 fProminence
= other
.fProminence
;
597 fScreenshotInfos
= other
.fScreenshotInfos
;
598 fScreenshots
= other
.fScreenshots
;
599 fState
= other
.fState
;
600 fInstallationLocations
= other
.fInstallationLocations
;
601 fDownloadProgress
= other
.fDownloadProgress
;
602 fFlags
= other
.fFlags
;
603 fSystemDependency
= other
.fSystemDependency
;
604 fArchitecture
= other
.fArchitecture
;
605 fLocalFilePath
= other
.fLocalFilePath
;
606 fFileName
= other
.fFileName
;
614 PackageInfo::operator==(const PackageInfo
& other
) const
616 return fIcon
== other
.fIcon
617 && fName
== other
.fName
618 && fTitle
== other
.fTitle
619 && fVersion
== other
.fVersion
620 && fPublisher
== other
.fPublisher
621 && fShortDescription
== other
.fShortDescription
622 && fFullDescription
== other
.fFullDescription
623 && fChangelog
== other
.fChangelog
624 && fCategories
== other
.fCategories
625 && fUserRatings
== other
.fUserRatings
626 && fCachedRatingSummary
== other
.fCachedRatingSummary
627 && fProminence
== other
.fProminence
628 && fScreenshotInfos
== other
.fScreenshotInfos
629 && fScreenshots
== other
.fScreenshots
630 && fState
== other
.fState
631 && fFlags
== other
.fFlags
632 && fDownloadProgress
== other
.fDownloadProgress
633 && fSystemDependency
== other
.fSystemDependency
634 && fArchitecture
== other
.fArchitecture
635 && fLocalFilePath
== other
.fLocalFilePath
636 && fFileName
== other
.fFileName
637 && fSize
== other
.fSize
;
642 PackageInfo::operator!=(const PackageInfo
& other
) const
644 return !(*this == other
);
649 PackageInfo::SetTitle(const BString
& title
)
651 if (fTitle
!= title
) {
653 _NotifyListeners(PKG_CHANGED_TITLE
);
659 PackageInfo::Title() const
661 return fTitle
.Length() > 0 ? fTitle
: fName
;
666 PackageInfo::SetShortDescription(const BString
& description
)
668 if (fShortDescription
!= description
) {
669 fShortDescription
= description
;
670 _NotifyListeners(PKG_CHANGED_SUMMARY
);
676 PackageInfo::SetFullDescription(const BString
& description
)
678 if (fFullDescription
!= description
) {
679 fFullDescription
= description
;
680 _NotifyListeners(PKG_CHANGED_DESCRIPTION
);
686 PackageInfo::SetIcon(const BitmapRef
& icon
)
690 _NotifyListeners(PKG_CHANGED_ICON
);
696 PackageInfo::SetChangelog(const BString
& changelog
)
698 if (fChangelog
!= changelog
) {
699 fChangelog
= changelog
;
700 _NotifyListeners(PKG_CHANGED_CHANGELOG
);
706 PackageInfo::IsSystemPackage() const
708 return (fFlags
& BPackageKit::B_PACKAGE_FLAG_SYSTEM_PACKAGE
) != 0;
713 PackageInfo::ClearCategories()
715 if (!fCategories
.IsEmpty()) {
717 _NotifyListeners(PKG_CHANGED_CATEGORIES
);
723 PackageInfo::AddCategory(const CategoryRef
& category
)
725 if (fCategories
.Add(category
)) {
726 _NotifyListeners(PKG_CHANGED_CATEGORIES
);
734 PackageInfo::SetSystemDependency(bool isDependency
)
736 fSystemDependency
= isDependency
;
741 PackageInfo::SetState(PackageState state
)
743 if (fState
!= state
) {
745 if (fState
!= DOWNLOADING
)
746 fDownloadProgress
= 0.0;
747 _NotifyListeners(PKG_CHANGED_STATE
);
753 PackageInfo::AddInstallationLocation(int32 location
)
755 fInstallationLocations
.insert(location
);
757 // TODO: determine how to differentiate between installed and active.
762 PackageInfo::SetDownloadProgress(float progress
)
764 fState
= DOWNLOADING
;
765 fDownloadProgress
= progress
;
766 _NotifyListeners(PKG_CHANGED_STATE
);
771 PackageInfo::SetLocalFilePath(const char* path
)
773 fLocalFilePath
= path
;
778 PackageInfo::IsLocalFile() const
780 return !fLocalFilePath
.IsEmpty() && fInstallationLocations
.empty();
785 PackageInfo::ClearUserRatings()
787 if (!fUserRatings
.IsEmpty()) {
788 fUserRatings
.Clear();
789 _NotifyListeners(PKG_CHANGED_RATINGS
);
795 PackageInfo::AddUserRating(const UserRating
& rating
)
797 if (!fUserRatings
.Add(rating
))
800 _NotifyListeners(PKG_CHANGED_RATINGS
);
807 PackageInfo::SetRatingSummary(const RatingSummary
& summary
)
809 if (fCachedRatingSummary
== summary
)
812 fCachedRatingSummary
= summary
;
814 _NotifyListeners(PKG_CHANGED_RATINGS
);
819 PackageInfo::CalculateRatingSummary() const
821 if (fUserRatings
.CountItems() == 0)
822 return fCachedRatingSummary
;
824 RatingSummary summary
;
825 summary
.ratingCount
= fUserRatings
.CountItems();
826 summary
.averageRating
= 0.0f
;
827 int starRatingCount
= sizeof(summary
.ratingCountByStar
) / sizeof(int);
828 for (int i
= 0; i
< starRatingCount
; i
++)
829 summary
.ratingCountByStar
[i
] = 0;
831 if (summary
.ratingCount
<= 0)
834 float ratingSum
= 0.0f
;
836 int ratingsSpecified
= summary
.ratingCount
;
837 for (int i
= 0; i
< summary
.ratingCount
; i
++) {
838 float rating
= fUserRatings
.ItemAtFast(i
).Rating();
842 else if (rating
> 5.0f
)
849 ratingsSpecified
--; // No rating specified by user
850 else if (rating
<= 1.0f
)
851 summary
.ratingCountByStar
[0]++;
852 else if (rating
<= 2.0f
)
853 summary
.ratingCountByStar
[1]++;
854 else if (rating
<= 3.0f
)
855 summary
.ratingCountByStar
[2]++;
856 else if (rating
<= 4.0f
)
857 summary
.ratingCountByStar
[3]++;
858 else if (rating
<= 5.0f
)
859 summary
.ratingCountByStar
[4]++;
862 if (ratingsSpecified
> 1)
863 ratingSum
/= ratingsSpecified
;
865 summary
.averageRating
= ratingSum
;
866 summary
.ratingCount
= ratingsSpecified
;
873 PackageInfo::SetProminence(float prominence
)
875 if (fProminence
!= prominence
) {
876 fProminence
= prominence
;
877 _NotifyListeners(PKG_CHANGED_PROMINENCE
);
883 PackageInfo::IsProminent() const
885 return HasProminence() && Prominence() <= 200;
890 PackageInfo::ClearScreenshotInfos()
892 fScreenshotInfos
.Clear();
897 PackageInfo::AddScreenshotInfo(const ScreenshotInfo
& info
)
899 return fScreenshotInfos
.Add(info
);
904 PackageInfo::ClearScreenshots()
906 if (!fScreenshots
.IsEmpty()) {
907 fScreenshots
.Clear();
908 _NotifyListeners(PKG_CHANGED_SCREENSHOTS
);
914 PackageInfo::AddScreenshot(const BitmapRef
& screenshot
)
916 if (!fScreenshots
.Add(screenshot
))
919 _NotifyListeners(PKG_CHANGED_SCREENSHOTS
);
926 PackageInfo::SetSize(int64 size
)
930 _NotifyListeners(PKG_CHANGED_SIZE
);
936 PackageInfo::SetDepotName(const BString
& depotName
)
938 if (fDepotName
!= depotName
) {
939 fDepotName
= depotName
;
940 _NotifyListeners(PKG_CHANGED_DEPOT
);
946 PackageInfo::AddListener(const PackageInfoListenerRef
& listener
)
948 return fListeners
.Add(listener
);
953 PackageInfo::RemoveListener(const PackageInfoListenerRef
& listener
)
955 fListeners
.Remove(listener
);
960 PackageInfo::CleanupDefaultIcon()
962 sDefaultIcon
.Unset();
967 PackageInfo::_NotifyListeners(uint32 changes
)
969 int count
= fListeners
.CountItems();
973 // Clone list to avoid listeners detaching themselves in notifications
974 // to screw up the list while iterating it.
975 PackageListenerList
listeners(fListeners
);
976 // Check if it worked:
977 if (listeners
.CountItems() != count
)
980 PackageInfoEvent
event(PackageInfoRef(this), changes
);
982 for (int i
= 0; i
< count
; i
++) {
983 const PackageInfoListenerRef
& listener
= listeners
.ItemAtFast(i
);
984 if (listener
.Get() != NULL
)
985 listener
->PackageChanged(event
);
993 DepotInfo::DepotInfo()
997 fWebAppRepositoryCode()
1002 DepotInfo::DepotInfo(const BString
& name
)
1006 fWebAppRepositoryCode(),
1007 fWebAppRepositorySourceCode()
1012 DepotInfo::DepotInfo(const DepotInfo
& other
)
1015 fPackages(other
.fPackages
),
1016 fWebAppRepositoryCode(other
.fWebAppRepositoryCode
),
1017 fWebAppRepositorySourceCode(other
.fWebAppRepositorySourceCode
),
1018 fBaseURL(other
.fBaseURL
)
1024 DepotInfo::operator=(const DepotInfo
& other
)
1026 fName
= other
.fName
;
1027 fPackages
= other
.fPackages
;
1028 fBaseURL
= other
.fBaseURL
;
1029 fWebAppRepositoryCode
= other
.fWebAppRepositoryCode
;
1030 fWebAppRepositorySourceCode
= other
.fWebAppRepositorySourceCode
;
1036 DepotInfo::operator==(const DepotInfo
& other
) const
1038 return fName
== other
.fName
1039 && fPackages
== other
.fPackages
;
1044 DepotInfo::operator!=(const DepotInfo
& other
) const
1046 return !(*this == other
);
1050 static int32
PackageCompare(const PackageInfoRef
& p1
, const PackageInfoRef
& p2
)
1052 return p1
->Name().Compare(p2
->Name());
1056 /*! This method will insert the package into the list of packages
1057 in order so that the list of packages remains in order.
1061 DepotInfo::AddPackage(const PackageInfoRef
& package
)
1063 return fPackages
.AddOrdered(package
, &PackageCompare
);
1067 static int32
PackageFixedNameCompare(const void* context
,
1068 const PackageInfoRef
& package
)
1070 const BString
* packageName
= static_cast<const BString
*>(context
);
1071 return packageName
->Compare(package
->Name());
1076 DepotInfo::PackageIndexByName(const BString
& packageName
)
1078 return fPackages
.BinarySearch(&packageName
, &PackageFixedNameCompare
);
1083 DepotInfo::SyncPackages(const PackageList
& otherPackages
)
1085 PackageList
packages(fPackages
);
1087 for (int32 i
= otherPackages
.CountItems() - 1; i
>= 0; i
--) {
1088 const PackageInfoRef
& otherPackage
= otherPackages
.ItemAtFast(i
);
1090 for (int32 j
= packages
.CountItems() - 1; j
>= 0; j
--) {
1091 const PackageInfoRef
& package
= packages
.ItemAtFast(j
);
1092 if (package
->Name() == otherPackage
->Name()) {
1093 // printf("%s: found package: '%s'\n", fName.String(),
1094 // package->Name().String());
1095 package
->SetState(otherPackage
->State());
1096 package
->SetLocalFilePath(otherPackage
->LocalFilePath());
1097 package
->SetSystemDependency(
1098 otherPackage
->IsSystemDependency());
1105 printf("%s: new package: '%s'\n", fName
.String(),
1106 otherPackage
->Name().String());
1107 fPackages
.Add(otherPackage
);
1111 for (int32 i
= packages
.CountItems() - 1; i
>= 0; i
--) {
1112 const PackageInfoRef
& package
= packages
.ItemAtFast(i
);
1113 printf("%s: removing package: '%s'\n", fName
.String(),
1114 package
->Name().String());
1115 fPackages
.Remove(package
);
1121 DepotInfo::SetBaseURL(const BString
& baseURL
)
1128 DepotInfo::SetWebAppRepositoryCode(const BString
& code
)
1130 fWebAppRepositoryCode
= code
;
1135 DepotInfo::SetWebAppRepositorySourceCode(const BString
& code
)
1137 fWebAppRepositorySourceCode
= code
;