HaikuDepot: notify work status from main window
[haiku.git] / src / apps / softwareupdater / CheckManager.cpp
blobf1297786a9d4c4ace7c9130939303a5f102c8097
1 /*
2 * Copyright 2013-2017, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler <axeld@pinc-software.de>
7 * Rene Gollent <rene@gollent.com>
8 * Ingo Weinhold <ingo_weinhold@gmx.de>
9 * Brian Hill <supernova@tycho.email>
13 #include "CheckManager.h"
15 #include <sys/ioctl.h>
16 #include <unistd.h>
18 #include <Application.h>
19 #include <Catalog.h>
20 #include <Message.h>
21 #include <Messenger.h>
22 #include <NetworkInterface.h>
23 #include <NetworkRoster.h>
24 #include <NodeInfo.h>
25 #include <Notification.h>
26 #include <Roster.h>
28 #include <package/manager/Exceptions.h>
29 #include <package/solver/SolverPackage.h>
30 #include <package/solver/SolverProblem.h>
31 #include <package/solver/SolverProblemSolution.h>
33 #include "constants.h"
35 using namespace BPackageKit;
36 using namespace BPackageKit::BManager::BPrivate;
38 #undef B_TRANSLATION_CONTEXT
39 #define B_TRANSLATION_CONTEXT "CheckManager"
42 CheckManager::CheckManager(BPackageInstallationLocation location,
43 bool verbose)
45 BPackageManager(location, &fClientInstallationInterface, this),
46 BPackageManager::UserInteractionHandler(),
47 fClientInstallationInterface(),
48 fVerbose(verbose),
49 fNotificationId("")
51 if (verbose) {
52 app_info info;
53 if (be_app->GetAppInfo(&info)!= B_OK)
54 fVerbose = false;
55 else
56 fNotificationId << info.team;
58 fHeaderChecking = B_TRANSLATE("Checking for updates");
59 fTextContacting = B_TRANSLATE("Contacting software repositories to check "
60 "for package updates.");
64 void
65 CheckManager::CheckNetworkConnection()
67 BNetworkRoster& roster = BNetworkRoster::Default();
68 BNetworkInterface interface;
69 uint32 cookie = 0;
70 while (roster.GetNextInterface(&cookie, interface) == B_OK) {
71 uint32 flags = interface.Flags();
72 if ((flags & IFF_LOOPBACK) == 0
73 && (flags & (IFF_UP | IFF_LINK)) == (IFF_UP | IFF_LINK)) {
74 return;
78 // No network connection detected, cannot continue
79 fputs(B_TRANSLATE("No active network connection was found.\n"), stderr);
80 throw BAbortedByUserException();
84 void
85 CheckManager::JobFailed(BSupportKit::BJob* job)
87 BString error = job->ErrorString();
88 if (error.Length() > 0) {
89 error.ReplaceAll("\n", "\n*** ");
90 fprintf(stderr, "%s", error.String());
95 void
96 CheckManager::JobAborted(BSupportKit::BJob* job)
98 puts("Job aborted");
99 BString error = job->ErrorString();
100 if (error.Length() > 0) {
101 error.ReplaceAll("\n", "\n*** ");
102 fprintf(stderr, "%s", error.String());
107 void
108 CheckManager::NoUpdatesNotification()
110 if (fVerbose) {
111 BString header = B_TRANSLATE("No updates available");
112 BString text = B_TRANSLATE("There were no updates found.");
113 _SendNotification(header.String(), text.String());
118 void
119 CheckManager::HandleProblems()
121 puts("Encountered problems:");
123 int32 problemCount = fSolver->CountProblems();
124 for (int32 i = 0; i < problemCount; i++) {
125 BSolverProblem* problem = fSolver->ProblemAt(i);
126 printf("problem %" B_PRId32 ": %s\n", i + 1,
127 problem->ToString().String());
130 BString title(B_TRANSLATE("Available updates found"));
131 BString text(B_TRANSLATE("Click here to run SoftwareUpdater. Some updates "
132 "will require a problem solution to be selected."));
133 _SendNotification(title, text);
135 throw BAbortedByUserException();
139 void
140 CheckManager::ConfirmChanges(bool fromMostSpecific)
142 int32 count = fInstalledRepositories.CountItems();
143 int32 updateCount = 0;
145 if (fromMostSpecific) {
146 for (int32 i = count - 1; i >= 0; i--)
147 _CountUpdates(*fInstalledRepositories.ItemAt(i), updateCount);
148 } else {
149 for (int32 i = 0; i < count; i++)
150 _CountUpdates(*fInstalledRepositories.ItemAt(i), updateCount);
153 printf("Update count=%" B_PRId32 "\n", updateCount);
154 if (updateCount > 0) {
155 BString title(B_TRANSLATE("%count% packages have available updates"));
156 BString count;
157 count << updateCount;
158 title.ReplaceFirst("%count%", count);
159 BString text(B_TRANSLATE("Click here to install updates."));
160 _SendNotification(title.String(), text.String());
162 throw BAbortedByUserException();
166 void
167 CheckManager::Warn(status_t error, const char* format, ...)
169 va_list args;
170 va_start(args, format);
171 vfprintf(stderr, format, args);
172 va_end(args);
174 if (error == B_OK)
175 puts("");
176 else
177 printf(": %s\n", strerror(error));
181 void
182 CheckManager::ProgressPackageDownloadStarted(const char* packageName)
184 if (fVerbose)
185 _SendNotification(fHeaderChecking.String(), fTextContacting.String());
187 printf("Downloading %s...\n", packageName);
191 void
192 CheckManager::ProgressPackageDownloadActive(const char* packageName,
193 float completionPercentage, off_t bytes, off_t totalBytes)
195 static const char* progressChars[] = {
196 "\xE2\x96\x8F",
197 "\xE2\x96\x8E",
198 "\xE2\x96\x8D",
199 "\xE2\x96\x8C",
200 "\xE2\x96\x8B",
201 "\xE2\x96\x8A",
202 "\xE2\x96\x89",
203 "\xE2\x96\x88",
206 int width = 70;
208 struct winsize winSize;
209 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winSize) == 0
210 && winSize.ws_col < 77) {
211 // We need 7 characters for the percent display
212 width = winSize.ws_col - 7;
215 int position;
216 int ipart = (int)(completionPercentage * width);
217 int fpart = (int)(((completionPercentage * width) - ipart) * 8);
219 fputs("\r", stdout); // return to the beginning of the line
221 for (position = 0; position < width; position++) {
222 if (position < ipart) {
223 // This part is fully downloaded, show a full block
224 fputs(progressChars[7], stdout);
225 } else if (position > ipart) {
226 // This part is not downloaded, show a space
227 fputs(" ", stdout);
228 } else {
229 // This part is partially downloaded
230 fputs(progressChars[fpart], stdout);
234 // Also print the progress percentage
235 printf(" %3d%%", (int)(completionPercentage * 100));
237 fflush(stdout);
242 void
243 CheckManager::ProgressPackageDownloadComplete(const char* packageName)
245 // Overwrite the progress bar with whitespace
246 fputs("\r", stdout);
247 struct winsize w;
248 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
249 for (int i = 0; i < (w.ws_col); i++)
250 fputs(" ", stdout);
251 fputs("\r\x1b[1A", stdout); // Go to previous line.
253 printf("Downloading %s...done.\n", packageName);
257 void
258 CheckManager::ProgressPackageChecksumStarted(const char* title)
260 if (fVerbose)
261 _SendNotification(fHeaderChecking.String(), title);
263 printf("%s...", title);
267 void
268 CheckManager::ProgressPackageChecksumComplete(const char* title)
270 puts("done.");
274 void
275 CheckManager::_CountUpdates(InstalledRepository& installationRepository,
276 int32& updateCount)
278 if (!installationRepository.HasChanges())
279 return;
281 PackageList& packagesToActivate
282 = installationRepository.PackagesToActivate();
283 PackageList& packagesToDeactivate
284 = installationRepository.PackagesToDeactivate();
286 for (int32 i = 0;
287 BSolverPackage* installPackage = packagesToActivate.ItemAt(i);
288 i++) {
289 for (int32 j = 0;
290 BSolverPackage* uninstallPackage = packagesToDeactivate.ItemAt(j);
291 j++) {
292 if (installPackage->Info().Name() == uninstallPackage->Info().Name()) {
293 updateCount++;
294 break;
301 void
302 CheckManager::_SendNotification(const char* title, const char* text)
304 BNotification notification(B_INFORMATION_NOTIFICATION);
305 notification.SetGroup("SoftwareUpdater");
306 notification.SetTitle(title);
307 notification.SetContent(text);
308 notification.SetOnClickApp(kAppSignature);
309 if(fVerbose)
310 notification.SetMessageID(fNotificationId);
311 notification.Send();