1 /* 2 * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>. 3 * Copyright 2013, Rene Gollent <rene@gollent.com>. 4 * Copyright 2016-2024, Andrew Lindesay <apl@lindesay.co.nz>. 5 * All rights reserved. Distributed under the terms of the MIT License. 6 */ 7 8 9 #include "PackageInfo.h" 10 11 #include <algorithm> 12 13 #include <package/PackageDefs.h> 14 #include <package/PackageFlags.h> 15 16 #include "HaikuDepotConstants.h" 17 #include "Logger.h" 18 19 20 // #pragma mark - PackageInfo 21 22 23 PackageInfo::PackageInfo() 24 : 25 fName(), 26 fVersion(), 27 fVersionCreateTimestamp(0), 28 fPublisher(), 29 fArchitecture(), 30 fDepotName(""), 31 32 fLocalizedText(), 33 fClassificationInfo(), 34 fScreenshotInfo(), 35 fUserRatingInfo(), 36 fLocalInfo(), 37 38 fListeners(), 39 fIsCollatingChanges(false), 40 fCollatedChanges(0) 41 { 42 } 43 44 45 PackageInfo::PackageInfo(const BPackageInfo& info) 46 : 47 fName(info.Name()), 48 fVersion(info.Version()), 49 fVersionCreateTimestamp(0), 50 fPublisher(), 51 fArchitecture(info.ArchitectureName()), 52 fDepotName(""), 53 54 fClassificationInfo(), 55 fScreenshotInfo(), 56 fUserRatingInfo(), 57 58 fListeners(), 59 fIsCollatingChanges(false), 60 fCollatedChanges(0) 61 { 62 BString publisherURL; 63 if (info.URLList().CountStrings() > 0) 64 publisherURL = info.URLList().StringAt(0); 65 66 BString publisherName = info.Vendor(); 67 const BStringList& copyrightList = info.CopyrightList(); 68 if (!copyrightList.IsEmpty()) { 69 publisherName = ""; 70 71 for (int32 i = 0; i < copyrightList.CountStrings(); i++) { 72 if (!publisherName.IsEmpty()) 73 publisherName << ", "; 74 publisherName << copyrightList.StringAt(i); 75 } 76 } 77 if (!publisherName.IsEmpty()) 78 publisherName.Prepend("© "); 79 80 fPublisher = PublisherInfo(publisherName, publisherURL); 81 82 fLocalizedText = PackageLocalizedTextRef(new PackageLocalizedText(), true); 83 fLocalizedText->SetTitle(info.Name()); 84 fLocalizedText->SetSummary(info.Summary()); 85 fLocalizedText->SetDescription(info.Description()); 86 87 // TODO: Retrieve local file size 88 fLocalInfo = PackageLocalInfoRef(new PackageLocalInfo(), true); 89 fLocalInfo->SetFlags(info.Flags()); 90 fLocalInfo->SetFileName(info.FileName()); 91 } 92 93 94 PackageInfo::PackageInfo(const PackageInfo& other) 95 : 96 fName(other.fName), 97 fVersion(other.fVersion), 98 fVersionCreateTimestamp(other.fVersionCreateTimestamp), 99 fPublisher(other.fPublisher), 100 fArchitecture(other.fArchitecture), 101 fDepotName(other.fDepotName), 102 103 fLocalizedText(other.fLocalizedText), 104 fClassificationInfo(other.fClassificationInfo), 105 fScreenshotInfo(other.fScreenshotInfo), 106 fUserRatingInfo(other.fUserRatingInfo), 107 fLocalInfo(other.fLocalInfo), 108 109 fListeners(), 110 fIsCollatingChanges(false), 111 fCollatedChanges(0) 112 { 113 } 114 115 116 PackageInfo& 117 PackageInfo::operator=(const PackageInfo& other) 118 { 119 fName = other.fName; 120 fVersion = other.fVersion; 121 fVersionCreateTimestamp = other.fVersionCreateTimestamp; 122 fPublisher = other.fPublisher; 123 fLocalizedText = other.fLocalizedText; 124 fClassificationInfo = other.fClassificationInfo; 125 fScreenshotInfo = other.fScreenshotInfo; 126 fUserRatingInfo = other.fUserRatingInfo; 127 fArchitecture = other.fArchitecture; 128 fDepotName = other.fDepotName; 129 fLocalInfo = other.fLocalInfo; 130 131 return *this; 132 } 133 134 135 bool 136 PackageInfo::operator==(const PackageInfo& other) const 137 { 138 return fName == other.fName 139 && fLocalInfo == other.fLocalInfo 140 && fVersion == other.fVersion 141 && fPublisher == other.fPublisher 142 && fLocalizedText == other.fLocalizedText 143 && fClassificationInfo == other.fClassificationInfo 144 && fScreenshotInfo == other.fScreenshotInfo 145 && fUserRatingInfo == fUserRatingInfo 146 && fArchitecture == other.fArchitecture 147 && fVersionCreateTimestamp == other.fVersionCreateTimestamp; 148 } 149 150 151 bool 152 PackageInfo::operator!=(const PackageInfo& other) const 153 { 154 return !(*this == other); 155 } 156 157 158 uint32 159 PackageInfo::DiffMask(const PackageInfo& other) const 160 { 161 uint32 result = 0; 162 if (fLocalizedText != fLocalizedText) 163 result |= PKG_CHANGED_LOCALIZED_TEXT; 164 if (fScreenshotInfo != other.fScreenshotInfo) 165 result |= PKG_CHANGED_SCREENSHOTS; 166 if (fUserRatingInfo != other.fUserRatingInfo) 167 result |= PKG_CHANGED_RATINGS; 168 if (fLocalInfo != other.fLocalInfo) 169 result |= PKG_CHANGED_LOCAL_INFO; 170 if (fClassificationInfo != other.fClassificationInfo) 171 result |= PKG_CHANGED_CLASSIFICATION; 172 if (fVersionCreateTimestamp != other.fVersionCreateTimestamp) 173 result |= PKG_CHANGED_VERSION_CREATE_TIMESTAMP; 174 return result; 175 } 176 177 178 PackageLocalizedTextRef 179 PackageInfo::LocalizedText() const 180 { 181 return fLocalizedText; 182 } 183 184 185 void 186 PackageInfo::SetLocalizedText(PackageLocalizedTextRef value) 187 { 188 if (fLocalizedText != value) { 189 fLocalizedText = value; 190 _NotifyListeners(PKG_CHANGED_LOCALIZED_TEXT); 191 // TODO; separate out these later - they are bundled for now to keep the existing 192 // logic working. 193 } 194 } 195 196 197 UserRatingInfoRef 198 PackageInfo::UserRatingInfo() const 199 { 200 return fUserRatingInfo; 201 } 202 203 204 void 205 PackageInfo::SetUserRatingInfo(UserRatingInfoRef value) 206 { 207 if (fUserRatingInfo != value) { 208 fUserRatingInfo = value; 209 _NotifyListeners(PKG_CHANGED_RATINGS); 210 } 211 } 212 213 214 PackageLocalInfoRef 215 PackageInfo::LocalInfo() const 216 { 217 return fLocalInfo; 218 } 219 220 221 void 222 PackageInfo::SetLocalInfo(PackageLocalInfoRef& localInfo) 223 { 224 if (fLocalInfo != localInfo) { 225 fLocalInfo = localInfo; 226 _NotifyListeners(PKG_CHANGED_LOCAL_INFO); 227 } 228 } 229 230 231 void 232 PackageInfo::SetPackageClassificationInfo(PackageClassificationInfoRef value) 233 { 234 if (value != fClassificationInfo) { 235 fClassificationInfo = value; 236 _NotifyListeners(PKG_CHANGED_CLASSIFICATION); 237 } 238 } 239 240 241 void 242 PackageInfo::SetScreenshotInfo(PackageScreenshotInfoRef value) 243 { 244 if (value != fScreenshotInfo) { 245 fScreenshotInfo = value; 246 _NotifyListeners(PKG_CHANGED_SCREENSHOTS); 247 } 248 } 249 250 251 void 252 PackageInfo::SetVersionCreateTimestamp(uint64 value) 253 { 254 if (fVersionCreateTimestamp != value) { 255 fVersionCreateTimestamp = value; 256 _NotifyListeners(PKG_CHANGED_VERSION_CREATE_TIMESTAMP); 257 } 258 } 259 260 261 void 262 PackageInfo::SetDepotName(const BString& depotName) 263 { 264 fDepotName = depotName; 265 } 266 267 268 bool 269 PackageInfo::AddListener(const PackageInfoListenerRef& listener) 270 { 271 fListeners.push_back(listener); 272 return true; 273 } 274 275 276 void 277 PackageInfo::RemoveListener(const PackageInfoListenerRef& listener) 278 { 279 fListeners.erase(std::remove(fListeners.begin(), fListeners.end(), 280 listener), fListeners.end()); 281 } 282 283 284 void 285 PackageInfo::NotifyChangedIcon() 286 { 287 _NotifyListeners(PKG_CHANGED_ICON); 288 } 289 290 291 void 292 PackageInfo::StartCollatingChanges() 293 { 294 fIsCollatingChanges = true; 295 fCollatedChanges = 0; 296 } 297 298 299 void 300 PackageInfo::EndCollatingChanges() 301 { 302 if (fIsCollatingChanges && fCollatedChanges != 0) 303 _NotifyListenersImmediate(fCollatedChanges); 304 fIsCollatingChanges = false; 305 fCollatedChanges = 0; 306 } 307 308 309 void 310 PackageInfo::_NotifyListeners(uint32 changes) 311 { 312 if (fIsCollatingChanges) 313 fCollatedChanges |= changes; 314 else 315 _NotifyListenersImmediate(changes); 316 } 317 318 319 void 320 PackageInfo::_NotifyListenersImmediate(uint32 changes) 321 { 322 if (fListeners.empty()) 323 return; 324 325 // Clone list to avoid listeners detaching themselves in notifications 326 // to screw up the list while iterating it. 327 std::vector<PackageInfoListenerRef> listeners(fListeners); 328 PackageInfoEvent event(PackageInfoRef(this), changes); 329 330 std::vector<PackageInfoListenerRef>::iterator it; 331 for (it = listeners.begin(); it != listeners.end(); it++) { 332 const PackageInfoListenerRef listener = *it; 333 if (listener.IsSet()) 334 listener->PackageChanged(event); 335 } 336 } 337