SoftwareUpdater updates

*Added a check-only option to check for updates and display a
  notification when updates are available.
*Added argv commands to specify an action when using Terminal or
  BRoster to launch app: commands [update | check | full-sync]
*Draw a download progress bar on the package icon
*Increased the size of the package icon to improve the bar look
*Added package counts to each list category
This commit is contained in:
Brian Hill 2017-04-20 17:58:46 -04:00
parent 0fb349bc5d
commit 73c2c7b4b5
16 changed files with 761 additions and 81 deletions

View File

@ -0,0 +1,76 @@
/*
* Copyright 2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Brian Hill <supernova@warpmail.net>
*/
#include "CheckAction.h"
#include <Application.h>
#include <Catalog.h>
#include <package/manager/Exceptions.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "CheckAction"
using namespace BPackageKit;
//using namespace BPackageKit::BPrivate;
using namespace BPackageKit::BManager::BPrivate;
CheckAction::CheckAction()
{
fCheckManager = new(std::nothrow)
CheckManager(B_PACKAGE_INSTALLATION_LOCATION_SYSTEM);
}
CheckAction::~CheckAction()
{
delete fCheckManager;
}
status_t
CheckAction::Perform()
{
try {
fCheckManager->CheckNetworkConnection();
fCheckManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES
| BPackageManager::B_ADD_REMOTE_REPOSITORIES
| BPackageManager::B_REFRESH_REPOSITORIES);
// fUpdateManager->SetDebugLevel(1);
// These values indicate that all updates should be installed
int packageCount = 0;
const char* const packages = "";
fCheckManager->Update(&packages, packageCount);
} catch (BFatalErrorException ex) {
fprintf(stderr, B_TRANSLATE(
"Fatal error while checking for updates: %s\n"),
ex.Message().String());
be_app->PostMessage(kMsgFinalQuit);
return ex.Error();
} catch (BAbortedByUserException ex) {
be_app->PostMessage(kMsgFinalQuit);
return B_OK;
} catch (BNothingToDoException ex) {
fprintf(stdout, B_TRANSLATE("There were no updates found."));
be_app->PostMessage(kMsgFinalQuit);
return B_OK;
} catch (BException ex) {
fprintf(stderr, B_TRANSLATE(
"Exception occurred while checking for updates: %s\n"),
ex.Message().String());
be_app->PostMessage(kMsgFinalQuit);
return B_ERROR;
}
return B_OK;
}

View File

@ -0,0 +1,26 @@
/*
* Copyright 2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Brian Hill <supernova@warpmail.net>
*/
#ifndef CHECK_ACTION_H
#define CHECK_ACTION_H
#include "CheckManager.h"
class CheckAction {
public:
CheckAction();
~CheckAction();
status_t Perform();
private:
CheckManager* fCheckManager;
};
#endif // CHECK_ACTION_H

View File

@ -0,0 +1,297 @@
/*
* Copyright 2013-2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler <axeld@pinc-software.de>
* Rene Gollent <rene@gollent.com>
* Ingo Weinhold <ingo_weinhold@gmx.de>
* Brian Hill <supernova@warpmail.net>
*/
#include "CheckManager.h"
#include <sys/ioctl.h>
#include <unistd.h>
#include <Catalog.h>
#include <Message.h>
#include <Messenger.h>
#include <NetworkInterface.h>
#include <NetworkRoster.h>
#include <NodeInfo.h>
#include <Notification.h>
#include <Roster.h>
#include <package/manager/Exceptions.h>
#include <package/solver/SolverPackage.h>
#include <package/solver/SolverProblem.h>
#include <package/solver/SolverProblemSolution.h>
#include "constants.h"
using namespace BPackageKit;
using namespace BPackageKit::BManager::BPrivate;
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "CheckManager"
CheckManager::CheckManager(BPackageInstallationLocation location)
:
BPackageManager(location, &fClientInstallationInterface, this),
BPackageManager::UserInteractionHandler(),
fClientInstallationInterface()
{
}
void
CheckManager::CheckNetworkConnection()
{
BNetworkRoster& roster = BNetworkRoster::Default();
BNetworkInterface interface;
uint32 cookie = 0;
while (roster.GetNextInterface(&cookie, interface) == B_OK) {
uint32 flags = interface.Flags();
if ((flags & IFF_LOOPBACK) == 0
&& (flags & (IFF_UP | IFF_LINK)) == (IFF_UP | IFF_LINK)) {
return;
}
}
// No network connection detected, cannot continue
fprintf(stderr, B_TRANSLATE("No active network connection was found.\n"));
throw BAbortedByUserException();
}
void
CheckManager::JobFailed(BSupportKit::BJob* job)
{
BString error = job->ErrorString();
if (error.Length() > 0) {
error.ReplaceAll("\n", "\n*** ");
fprintf(stderr, "%s", error.String());
}
}
void
CheckManager::JobAborted(BSupportKit::BJob* job)
{
printf("Job aborted\n");
BString error = job->ErrorString();
if (error.Length() > 0) {
error.ReplaceAll("\n", "\n*** ");
fprintf(stderr, "%s", error.String());
}
}
void
CheckManager::HandleProblems()
{
printf("Encountered problems:\n");
int32 problemCount = fSolver->CountProblems();
for (int32 i = 0; i < problemCount; i++) {
BSolverProblem* problem = fSolver->ProblemAt(i);
printf("problem %" B_PRId32 ": %s\n", i + 1,
problem->ToString().String());
}
BString title(B_TRANSLATE("Available updates found"));
BString text(B_TRANSLATE("Click here to run SoftwareUpdater. Some updates "
"will require a problem solution to be selected."));
_SendNotification(title, text);
throw BAbortedByUserException();
}
void
CheckManager::ConfirmChanges(bool fromMostSpecific)
{
int32 count = fInstalledRepositories.CountItems();
int32 updateCount = 0;
if (fromMostSpecific) {
for (int32 i = count - 1; i >= 0; i--)
_CountUpdates(*fInstalledRepositories.ItemAt(i), updateCount);
} else {
for (int32 i = 0; i < count; i++)
_CountUpdates(*fInstalledRepositories.ItemAt(i), updateCount);
}
printf("Update count=%" B_PRId32 "\n", updateCount);
if (updateCount > 0) {
BString title(B_TRANSLATE("%count% packages have available updates"));
BString count;
count << updateCount;
title.ReplaceFirst("%count%", count);
BString text(B_TRANSLATE("Click here to install updates."));
_SendNotification(title, text);
}
throw BAbortedByUserException();
}
void
CheckManager::Warn(status_t error, const char* format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
if (error == B_OK)
printf("\n");
else
printf(": %s\n", strerror(error));
}
void
CheckManager::ProgressPackageDownloadStarted(const char* packageName)
{
printf("Downloading %s...\n", packageName);
}
void
CheckManager::ProgressPackageDownloadActive(const char* packageName,
float completionPercentage, off_t bytes, off_t totalBytes)
{
static const char* progressChars[] = {
"\xE2\x96\x8F",
"\xE2\x96\x8E",
"\xE2\x96\x8D",
"\xE2\x96\x8C",
"\xE2\x96\x8B",
"\xE2\x96\x8A",
"\xE2\x96\x89",
"\xE2\x96\x88",
};
int width = 70;
struct winsize winSize;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winSize) == 0
&& winSize.ws_col < 77) {
// We need 7 characters for the percent display
width = winSize.ws_col - 7;
}
int position;
int ipart = (int)(completionPercentage * width);
int fpart = (int)(((completionPercentage * width) - ipart) * 8);
printf("\r"); // return to the beginning of the line
for (position = 0; position < width; position++) {
if (position < ipart) {
// This part is fully downloaded, show a full block
printf(progressChars[7]);
} else if (position > ipart) {
// This part is not downloaded, show a space
printf(" ");
} else {
// This part is partially downloaded
printf(progressChars[fpart]);
}
}
// Also print the progress percentage
printf(" %3d%%", (int)(completionPercentage * 100));
fflush(stdout);
}
void
CheckManager::ProgressPackageDownloadComplete(const char* packageName)
{
// Overwrite the progress bar with whitespace
printf("\r");
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
for (int i = 0; i < (w.ws_col); i++)
printf(" ");
printf("\r\x1b[1A"); // Go to previous line.
printf("Downloading %s...done.\n", packageName);
}
void
CheckManager::ProgressPackageChecksumStarted(const char* title)
{
printf("%s...", title);
}
void
CheckManager::ProgressPackageChecksumComplete(const char* title)
{
printf("done.\n");
}
void
CheckManager::_CountUpdates(InstalledRepository& installationRepository,
int32& updateCount)
{
if (!installationRepository.HasChanges())
return;
PackageList& packagesToActivate
= installationRepository.PackagesToActivate();
PackageList& packagesToDeactivate
= installationRepository.PackagesToDeactivate();
for (int32 i = 0;
BSolverPackage* installPackage = packagesToActivate.ItemAt(i);
i++) {
for (int32 j = 0;
BSolverPackage* uninstallPackage = packagesToDeactivate.ItemAt(j);
j++) {
if (installPackage->Info().Name() == uninstallPackage->Info().Name()) {
updateCount++;
break;
}
}
}
}
void
CheckManager::_SendNotification(const char* title, const char* text)
{
BNotification notification(B_INFORMATION_NOTIFICATION);
notification.SetGroup("SoftwareUpdater");
notification.SetTitle(title);
notification.SetContent(text);
notification.SetOnClickApp(kAppSignature);
BBitmap icon(_GetIcon());
if (icon.IsValid())
notification.SetIcon(&icon);
bigtime_t timeout = 30000000;
notification.Send(timeout);
}
BBitmap
CheckManager::_GetIcon()
{
int32 iconSize = B_LARGE_ICON;
BBitmap icon(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32);
team_info teamInfo;
get_team_info(B_CURRENT_TEAM, &teamInfo);
app_info appInfo;
be_roster->GetRunningAppInfo(teamInfo.team, &appInfo);
BNodeInfo::GetTrackerIcon(&appInfo.ref, &icon, icon_size(iconSize));
return icon;
}

View File

@ -0,0 +1,75 @@
/*
* Copyright 2013-2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <ingo_weinhold@gmx.de>
* Rene Gollent <rene@gollent.com>
* Brian Hill <supernova@warpmail.net>
*/
#ifndef CHECK_MANAGER_H
#define CHECK_MANAGER_H
#include <Bitmap.h>
#include <package/DaemonClient.h>
#include <package/manager/PackageManager.h>
#include "constants.h"
#include "SoftwareUpdaterWindow.h"
class ProblemWindow;
//using namespace BPackageKit;
using BPackageKit::BPackageInstallationLocation;
using BPackageKit::BPrivate::BDaemonClient;
using BPackageKit::BManager::BPrivate::BPackageManager;
class CheckManager : public BPackageManager,
private BPackageManager::UserInteractionHandler {
public:
CheckManager(
BPackageInstallationLocation location);
void CheckNetworkConnection();
virtual void JobFailed(BSupportKit::BJob* job);
virtual void JobAborted(BSupportKit::BJob* job);
private:
// UserInteractionHandler
virtual void HandleProblems();
virtual void ConfirmChanges(bool fromMostSpecific);
virtual void Warn(status_t error, const char* format, ...);
virtual void ProgressPackageDownloadStarted(
const char* packageName);
virtual void ProgressPackageDownloadActive(
const char* packageName,
float completionPercentage,
off_t bytes, off_t totalBytes);
virtual void ProgressPackageDownloadComplete(
const char* packageName);
virtual void ProgressPackageChecksumStarted(
const char* packageName);
virtual void ProgressPackageChecksumComplete(
const char* packageName);
private:
void _CountUpdates(InstalledRepository&
installationRepository,
int32& updateCount);
void _SendNotification(const char* title,
const char* text);
BBitmap _GetIcon();
private:
BPackageManager::ClientInstallationInterface
fClientInstallationInterface;
ProblemWindow* fProblemWindow;
};
#endif // CHECK_MANAGER_H

View File

@ -10,6 +10,8 @@ Application SoftwareUpdater :
StripeView.cpp
UpdateAction.cpp
UpdateManager.cpp
CheckAction.cpp
CheckManager.cpp
WorkingLooper.cpp
# package_daemon

View File

@ -9,14 +9,31 @@
#include "SoftwareUpdaterApp.h"
#include "constants.h"
#include <Catalog.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "SoftwareUpdaterApp"
static const char* const kUsage = B_TRANSLATE_COMMENT(
"Usage: SoftwareUpdater <command>\n"
"Updates installed packages.\n"
"\n"
"Commands:\n"
" update - Search repositories for updates on all packages.\n"
" check - Check for available updates but only display a "
"notification with results.\n"
" full-sync - Synchronize the installed packages with the "
"repositories.\n", "Command line usage help")
;
SoftwareUpdaterApp::SoftwareUpdaterApp()
:
BApplication("application/x-vnd.haiku-softwareupdater"),
BApplication(kAppSignature),
fWorker(NULL),
fFinalQuitFlag(false)
fFinalQuitFlag(false),
fActionRequested(UPDATE)
{
}
@ -50,7 +67,30 @@ SoftwareUpdaterApp::QuitRequested()
void
SoftwareUpdaterApp::ReadyToRun()
{
fWorker = new WorkingLooper();
fWorker = new WorkingLooper(fActionRequested);
}
void
SoftwareUpdaterApp::ArgvReceived(int32 argc, char **argv)
{
// Only one command allowed
if (argc > 2) {
fprintf(stderr, kUsage);
PostMessage(B_QUIT_REQUESTED);
return;
} else if (argc == 2) {
fActionRequested = USER_SELECTION_NEEDED;
const char* command = argv[1];
if (strcmp("update", command) == 0)
fActionRequested = UPDATE;
else if (strcmp("check", command) == 0)
fActionRequested = UPDATE_CHECK_ONLY;
else if (strcmp("full-sync", command) == 0)
fActionRequested = FULLSYNC;
else
fprintf(stderr, kUsage);
}
}
@ -74,8 +114,13 @@ SoftwareUpdaterApp::MessageReceived(BMessage* message)
int
main()
main(int argc, const char* const* argv)
{
if (argc > 2) {
fprintf(stderr, kUsage);
return 1;
}
SoftwareUpdaterApp app;
return app.Run();
}

View File

@ -20,13 +20,15 @@ public:
SoftwareUpdaterApp();
~SoftwareUpdaterApp();
virtual bool QuitRequested();
void ReadyToRun();
virtual void ReadyToRun();
virtual void ArgvReceived(int32 argc, char **argv);
void MessageReceived(BMessage* message);
private:
WorkingLooper* fWorker;
BMessenger fWindowMessenger;
bool fFinalQuitFlag;
update_type fActionRequested;
};

View File

@ -18,7 +18,6 @@
#include <LayoutBuilder.h>
#include <LayoutUtils.h>
#include <Message.h>
#include <NodeInfo.h>
#include <Roster.h>
#include <String.h>
@ -63,7 +62,7 @@ SoftwareUpdaterWindow::SoftwareUpdaterWindow()
fDetailView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
fDetailView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP));
fStatusBar = new BStatusBar("progress");
fStatusBar->SetMaxValue(1.0);
fStatusBar->SetMaxValue(100);
fListView = new PackageListView();
fScrollView = new BScrollView("scrollview", fListView, B_WILL_DRAW,
@ -175,6 +174,8 @@ SoftwareUpdaterWindow::MessageReceived(BMessage* message)
fStatusBar->SetTo(percent, packageName.String(),
packageCount.String());
Unlock();
fListView->UpdatePackageProgress(packageName.String(), percent);
break;
}
@ -332,11 +333,11 @@ SoftwareUpdaterWindow::UserCancelRequested()
void
SoftwareUpdaterWindow::AddPackageInfo(uint32 install_type,
const char* package_name, const char* cur_ver, const char* new_ver,
const char* summary, const char* repository)
const char* summary, const char* repository, const char* file_name)
{
Lock();
fListView->AddPackage(install_type, package_name, cur_ver, new_ver,
summary, repository);
summary, repository, file_name);
Unlock();
}
@ -481,7 +482,8 @@ SuperItem::SuperItem(const char* label)
BListItem(),
fLabel(label),
fShowMoreDetails(false),
fPackageIcon(NULL)
fPackageIcon(NULL),
fItemCount(0)
{
}
@ -495,15 +497,21 @@ SuperItem::~SuperItem()
void
SuperItem::DrawItem(BView* owner, BRect item_rect, bool complete)
{
owner->PushState();
float width;
owner->GetPreferredSize(&width, NULL);
BString label(fLabel);
label.Append(" (");
label << fItemCount;
label.Append(")");
owner->TruncateString(&label, B_TRUNCATE_END, width);
owner->SetHighColor(ui_color(B_LIST_ITEM_TEXT_COLOR));
owner->SetFont(&fBoldFont);
owner->DrawString(label.String(), BPoint(item_rect.left,
item_rect.bottom - fFontHeight.descent - 1));
owner->SetFont(&fRegularFont);
owner->PopState();
}
@ -548,7 +556,7 @@ void
SuperItem::_GetPackageIcon()
{
delete fPackageIcon;
fIconSize = int(fPackageItemHeight * .7);
fIconSize = int(fPackageItemHeight * .8);
status_t result = B_ERROR;
BRect iconRect(0, 0, fIconSize - 1, fIconSize - 1);
@ -571,7 +579,7 @@ SuperItem::_GetPackageIcon()
PackageItem::PackageItem(const char* name, const char* simple_version,
const char* detailed_version, const char* repository, const char* summary,
SuperItem* super)
const char* file_name, SuperItem* super)
:
BListItem(),
fName(name),
@ -579,7 +587,10 @@ PackageItem::PackageItem(const char* name, const char* simple_version,
fDetailedVersion(detailed_version),
fRepository(repository),
fSummary(summary),
fSuperItem(super)
fSuperItem(super),
fFileName(file_name),
fDownloadProgress(0),
fDrawBarFlag(false)
{
fLabelOffset = be_control_look->DefaultLabelSpacing();
}
@ -588,6 +599,8 @@ PackageItem::PackageItem(const char* name, const char* simple_version,
void
PackageItem::DrawItem(BView* owner, BRect item_rect, bool complete)
{
owner->PushState();
float width;
owner->GetPreferredSize(&width, NULL);
float nameWidth = width / 2.0;
@ -601,13 +614,20 @@ PackageItem::DrawItem(BView* owner, BRect item_rect, bool complete)
//owner->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
owner->SetDrawingMode(B_OP_ALPHA);
owner->DrawBitmap(icon, BPoint(item_rect.left,
item_rect.top + offsetMarginHeight));
BPoint location = BPoint(item_rect.left,
item_rect.top + offsetMarginHeight);
owner->DrawBitmap(icon, location);
owner->SetDrawingMode(B_OP_COPY);
if (fDrawBarFlag)
_DrawBar(location, owner, icon_size(iconSize));
offset_width += iconSize + fLabelOffset;
}
owner->SetFont(&fRegularFont);
owner->SetHighColor(ui_color(B_LIST_ITEM_TEXT_COLOR));
// Package name
font_height fontHeight = fSuperItem->GetFontHeight();
BString name(fName);
@ -647,7 +667,61 @@ PackageItem::DrawItem(BView* owner, BRect item_rect, bool complete)
owner->DrawString(version.String(), cursor);
}
owner->SetFont(&fRegularFont);
owner->PopState();
}
// Modified slightly from Tracker's BPose::DrawBar
void
PackageItem::_DrawBar(BPoint where, BView* view, icon_size which)
{
int32 yOffset;
int32 size = which - 1;
int32 barWidth = (int32)(7.0f / 32.0f * (float)which);
if (barWidth < 4) {
barWidth = 4;
yOffset = 0;
} else
yOffset = 2;
int32 barHeight = size - 3 - 2 * yOffset;
// the black shadowed line
view->SetHighColor(32, 32, 32, 92);
view->MovePenTo(BPoint(where.x + size, where.y + 1 + yOffset));
view->StrokeLine(BPoint(where.x + size, where.y + size - yOffset));
view->StrokeLine(BPoint(where.x + size - barWidth + 1,
where.y + size - yOffset));
view->SetDrawingMode(B_OP_ALPHA);
// the gray frame
view->SetHighColor(76, 76, 76, 192);
BRect rect(where.x + size - barWidth,where.y + yOffset,
where.x + size - 1,where.y + size - 1 - yOffset);
view->StrokeRect(rect);
// calculate bar height
int32 barPos = barHeight - int32(barHeight * fDownloadProgress / 100.0);
if (barPos < 0)
barPos = 0;
else if (barPos > barHeight)
barPos = barHeight;
// the free space bar
view->SetHighColor(255, 255, 255, 192);
rect.InsetBy(1,1);
BRect bar(rect);
bar.bottom = bar.top + barPos - 1;
if (barPos > 0)
view->FillRect(bar);
// the used space bar
bar.top = bar.bottom + 1;
bar.bottom = rect.bottom;
view->SetHighColor(0, 203, 0, 192);
view->FillRect(bar);
}
@ -681,6 +755,13 @@ PackageItem::NameCompare(PackageItem* item)
}
void
PackageItem::SetDownloadProgress(float percent)
{
fDownloadProgress = percent;
}
int
SortPackageItems(const BListItem* item1, const BListItem* item2)
{
@ -696,7 +777,9 @@ PackageListView::PackageListView()
fSuperUpdateItem(NULL),
fSuperInstallItem(NULL),
fSuperUninstallItem(NULL),
fShowMoreDetails(false)
fShowMoreDetails(false),
fLastProgressItem(NULL),
fLastProgressValue(-1)
{
fMenu = new BPopUpMenu(B_EMPTY_STRING, false, false);
fDetailMenuItem = new BMenuItem("Show more details", new BMessage());
@ -778,7 +861,7 @@ PackageListView::MouseDown(BPoint where)
void
PackageListView::AddPackage(uint32 install_type, const char* name,
const char* cur_ver, const char* new_ver, const char* summary,
const char* repository)
const char* repository, const char* file_name)
{
SuperItem* super;
BString simpleVersion;
@ -844,11 +927,43 @@ PackageListView::AddPackage(uint32 install_type, const char* name,
}
PackageItem* item = new PackageItem(name, simpleVersion.String(),
detailedVersion.String(), repositoryText.String(), summary, super);
detailedVersion.String(), repositoryText.String(), summary, file_name,
super);
AddUnder(item, super);
super->SetItemCount(CountItemsUnder(super, true));
}
void
PackageListView::UpdatePackageProgress(const char* packageName, float percent)
{
// Update only every 1 percent change
int16 wholePercent = int16(percent);
if (wholePercent == fLastProgressValue)
return;
fLastProgressValue = wholePercent;
// A new package started downloading, find the PackageItem by name
if (percent == 0) {
fLastProgressItem = NULL;
int32 count = FullListCountItems();
for (int32 i = 0; i < count; i++) {
PackageItem* item = dynamic_cast<PackageItem*>(FullListItemAt(i));
if (item != NULL && strcmp(item->FileName(), packageName) == 0) {
fLastProgressItem = item;
fLastProgressItem->ShowProgressBar();
break;
}
}
}
if (fLastProgressItem != NULL) {
fLastProgressItem->SetDownloadProgress(percent);
Invalidate();
}
}
void
PackageListView::SortItems()
{

View File

@ -14,6 +14,7 @@
#include <GroupView.h>
#include <OutlineListView.h>
#include <MenuItem.h>
#include <NodeInfo.h>
#include <Point.h>
#include <PopUpMenu.h>
#include <ScrollView.h>
@ -45,6 +46,8 @@ public:
int16 GetIconSize() { return fIconSize; };
void SetDetailLevel(bool showMoreDetails);
bool GetDetailLevel() { return fShowMoreDetails; };
void SetItemCount(int32 count)
{ fItemCount = count; };
private:
void _SetHeights();
@ -58,6 +61,7 @@ private:
float fPackageItemHeight;
BBitmap* fPackageIcon;
int16 fIconSize;
int32 fItemCount;
};
@ -68,13 +72,20 @@ public:
const char* detailed_version,
const char* repository,
const char* summary,
const char* file_name,
SuperItem* super);
virtual void DrawItem(BView*, BRect, bool);
virtual void Update(BView *owner, const BFont *font);
void SetItemHeight(const BFont* font);
int NameCompare(PackageItem* item);
const char* FileName() { return fFileName.String(); };
void SetDownloadProgress(float percent);
void ShowProgressBar() { fDrawBarFlag = true; };
private:
void _DrawBar(BPoint where, BView* view,
icon_size which);
BString fName;
BString fSimpleVersion;
BString fDetailedVersion;
@ -86,6 +97,9 @@ private:
float fSmallTotalHeight;
float fLabelOffset;
SuperItem* fSuperItem;
BString fFileName;
float fDownloadProgress;
bool fDrawBarFlag;
};
@ -101,7 +115,10 @@ public:
const char* cur_ver,
const char* new_ver,
const char* summary,
const char* repository);
const char* repository,
const char* file_name);
void UpdatePackageProgress(const char* packageName,
float percent);
void SortItems();
float ItemHeight();
@ -114,6 +131,8 @@ private:
bool fShowMoreDetails;
BPopUpMenu *fMenu;
BMenuItem *fDetailMenuItem;
PackageItem* fLastProgressItem;
int16 fLastProgressValue;
};
@ -130,7 +149,8 @@ public:
const char* cur_ver,
const char* new_ver,
const char* summary,
const char* repository);
const char* repository,
const char* file_name);
void ShowWarningAlert(const char* text);
BBitmap GetIcon(int32 iconSize);
BBitmap GetNotificationIcon();

View File

@ -13,8 +13,6 @@
#include <Catalog.h>
#include <package/manager/Exceptions.h>
#include "constants.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "UpdateAction"
@ -39,15 +37,21 @@ UpdateAction::~UpdateAction()
status_t
UpdateAction::Perform()
UpdateAction::Perform(update_type action_request)
{
try {
fUpdateManager->CheckNetworkConnection();
int32 action = fUpdateManager->GetUpdateType();
update_type action = action_request;
// Prompt the user if needed
if (action == USER_SELECTION_NEEDED)
action = fUpdateManager->GetUpdateType();
if (action == CANCEL_UPDATE)
throw BAbortedByUserException();
else if (action <= INVALID_SELECTION || action >= UPDATE_TYPE_END)
throw BException("Invalid update type, cannot continue with updates");
throw BException(B_TRANSLATE(
"Invalid update type, cannot continue with updates"));
fUpdateManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES
| BPackageManager::B_ADD_REMOTE_REPOSITORIES
@ -61,7 +65,11 @@ UpdateAction::Perform()
fUpdateManager->Update(&packages, packageCount);
} else if (action == FULLSYNC)
fUpdateManager->FullSync();
else
// Should not happen but just in case
throw BException(B_TRANSLATE(
"Invalid update type, cannot continue with updates"));
} catch (BFatalErrorException ex) {
fUpdateManager->FinalUpdate(B_TRANSLATE("Updates did not complete"),
ex.Message());
@ -79,7 +87,8 @@ UpdateAction::Perform()
B_TRANSLATE("There were no updates found."));
return B_OK;
} catch (BException ex) {
fprintf(stderr, "Exception occurred while updating packages : %s\n",
fprintf(stderr, B_TRANSLATE(
"Exception occurred while updating packages : %s\n"),
ex.Message().String());
fUpdateManager->FinalUpdate(B_TRANSLATE("Updates did not complete"),
ex.Message());

View File

@ -16,7 +16,7 @@ class UpdateAction {
public:
UpdateAction();
~UpdateAction();
status_t Perform();
status_t Perform(update_type action_request);
private:
UpdateManager* fUpdateManager;

View File

@ -23,18 +23,11 @@
#include <NetworkRoster.h>
#include <Notification.h>
#include <package/CommitTransactionResult.h>
#include <package/DownloadFileRequest.h>
#include <package/RefreshRepositoryRequest.h>
#include <package/manager/Exceptions.h>
#include <package/solver/SolverPackage.h>
#include <package/solver/SolverProblem.h>
#include <package/solver/SolverProblemSolution.h>
#include "constants.h"
#include "AutoDeleter.h"
#include "ProblemWindow.h"
#include "ResultWindow.h"
using namespace BPackageKit;
using namespace BPackageKit::BManager::BPrivate;
@ -102,7 +95,7 @@ UpdateManager::CheckNetworkConnection()
}
int32
update_type
UpdateManager::GetUpdateType()
{
int32 action = USER_SELECTION_NEEDED;
@ -113,7 +106,7 @@ UpdateManager::GetUpdateType()
messenger.SendMessage(&message, &reply);
reply.FindInt32(kKeyAlertResult, &action);
}
return action;
return (update_type)action;
}
@ -278,13 +271,7 @@ UpdateManager::ProgressPackageDownloadStarted(const char* packageName)
{
if (fCurrentStep == ACTION_STEP_DOWNLOAD) {
BString header(B_TRANSLATE("Downloading packages"));
BString packageCount;
packageCount.SetToFormat(
B_TRANSLATE_COMMENT("%i of %i", "Do not translate %i"),
fPackageDownloadsCount,
fPackageDownloadsTotal);
_UpdateDownloadProgress(header.String(), packageName, packageCount,
0.0);
_UpdateDownloadProgress(header.String(), packageName, 0.0);
fNewDownloadStarted = false;
}
@ -294,24 +281,18 @@ UpdateManager::ProgressPackageDownloadStarted(const char* packageName)
void
UpdateManager::ProgressPackageDownloadActive(const char* packageName,
float completionPercentage, off_t bytes, off_t totalBytes)
float completionValue, off_t bytes, off_t totalBytes)
{
if (fCurrentStep == ACTION_STEP_DOWNLOAD) {
// Fix a bug where a 100% completion percentage gets sent at the start
// of a package download
if (!fNewDownloadStarted) {
if (completionPercentage > 0 && completionPercentage < 1)
if (completionValue > 0 && completionValue < 1)
fNewDownloadStarted = true;
else
completionPercentage = 0.0;
completionValue = 0.0;
}
BString packageCount;
packageCount.SetToFormat(
B_TRANSLATE_COMMENT("%i of %i", "Do not translate %i"),
fPackageDownloadsCount,
fPackageDownloadsTotal);
_UpdateDownloadProgress(NULL, packageName, packageCount,
completionPercentage);
_UpdateDownloadProgress(NULL, packageName, completionValue * 100.0);
}
static const char* progressChars[] = {
@ -335,8 +316,8 @@ UpdateManager::ProgressPackageDownloadActive(const char* packageName,
}
int position;
int ipart = (int)(completionPercentage * width);
int fpart = (int)(((completionPercentage * width) - ipart) * 8);
int ipart = (int)(completionValue * width);
int fpart = (int)(((completionValue * width) - ipart) * 8);
printf("\r"); // return to the beginning of the line
@ -354,7 +335,7 @@ UpdateManager::ProgressPackageDownloadActive(const char* packageName,
}
// Also print the progress percentage
printf(" %3d%%", (int)(completionPercentage * 100));
printf(" %3d%%", (int)(completionValue * 100));
fflush(stdout);
@ -364,8 +345,10 @@ UpdateManager::ProgressPackageDownloadActive(const char* packageName,
void
UpdateManager::ProgressPackageDownloadComplete(const char* packageName)
{
if (fCurrentStep == ACTION_STEP_DOWNLOAD)
if (fCurrentStep == ACTION_STEP_DOWNLOAD) {
_UpdateDownloadProgress(NULL, packageName, 100.0);
fPackageDownloadsCount++;
}
// Overwrite the progress bar with whitespace
printf("\r");
@ -497,7 +480,8 @@ UpdateManager::_PrintResult(InstalledRepository& installationRepository,
upgradedPackageVersions.StringAt(position).String(),
package->Info().Version().ToString().String(),
package->Info().Summary().String(),
package->Repository()->Name().String());
package->Repository()->Name().String(),
package->Info().FileName().String());
upgradeCount++;
} else {
printf(" install package %s-%s from %s\n",
@ -509,7 +493,8 @@ UpdateManager::_PrintResult(InstalledRepository& installationRepository,
NULL,
package->Info().Version().ToString().String(),
package->Info().Summary().String(),
package->Repository()->Name().String());
package->Repository()->Name().String(),
package->Info().FileName().String());
installCount++;
}
}
@ -525,7 +510,8 @@ UpdateManager::_PrintResult(InstalledRepository& installationRepository,
package->Info().Version().ToString(),
NULL,
package->Info().Summary().String(),
package->Repository()->Name().String());
package->Repository()->Name().String(),
package->Info().FileName().String());
uninstallCount++;
}
}
@ -551,21 +537,25 @@ UpdateManager::_UpdateStatusWindow(const char* header, const char* detail)
void
UpdateManager::_UpdateDownloadProgress(const char* header,
const char* packageName, const char* packageCount,
float completionPercentage)
const char* packageName, float percentageComplete)
{
if (packageName == NULL || packageCount == NULL)
if (packageName == NULL)
return;
if (fStatusWindow->UserCancelRequested())
throw BAbortedByUserException();
BString packageCount;
packageCount.SetToFormat(
B_TRANSLATE_COMMENT("%i of %i", "Do not translate %i"),
fPackageDownloadsCount,
fPackageDownloadsTotal);
BMessage message(kMsgProgressUpdate);
if (header != NULL)
message.AddString(kKeyHeader, header);
message.AddString(kKeyPackageName, packageName);
message.AddString(kKeyPackageCount, packageCount);
message.AddFloat(kKeyPercentage, completionPercentage);
message.AddString(kKeyPackageCount, packageCount.String());
message.AddFloat(kKeyPercentage, percentageComplete);
fStatusWindow->PostMessage(&message);
}

View File

@ -14,11 +14,13 @@
#include <package/DaemonClient.h>
#include <package/manager/PackageManager.h>
#include "constants.h"
#include "SoftwareUpdaterWindow.h"
class ProblemWindow;
//using namespace BPackageKit;
using BPackageKit::BPackageInstallationLocation;
using BPackageKit::BPrivate::BDaemonClient;
using BPackageKit::BManager::BPrivate::BPackageManager;
@ -27,11 +29,11 @@ class UpdateManager : public BPackageManager,
private BPackageManager::UserInteractionHandler {
public:
UpdateManager(
BPackageKit::BPackageInstallationLocation location);
BPackageInstallationLocation location);
~UpdateManager();
void CheckNetworkConnection();
int32 GetUpdateType();
update_type GetUpdateType();
virtual void JobFailed(BSupportKit::BJob* job);
virtual void JobAborted(BSupportKit::BJob* job);
void FinalUpdate(const char* header,
@ -46,7 +48,7 @@ private:
const char* packageName);
virtual void ProgressPackageDownloadActive(
const char* packageName,
float completionPercentage,
float completionValue,
off_t bytes, off_t totalBytes);
virtual void ProgressPackageDownloadComplete(
const char* packageName);
@ -73,8 +75,7 @@ private:
const char* detail);
void _UpdateDownloadProgress(const char* header,
const char* packageName,
const char* packageCount,
float completionPercentage);
float percentageComplete);
void _FinalUpdate(const char* header,
const char* text);
void _SetCurrentStep(int32 step);

View File

@ -10,22 +10,38 @@
#include "WorkingLooper.h"
WorkingLooper::WorkingLooper()
WorkingLooper::WorkingLooper(update_type action)
:
BLooper("WorkingLooper")
BLooper("WorkingLooper"),
fUpdateAction(NULL),
fCheckAction(NULL),
fActionRequested(action)
{
Run();
PostMessage(kMsgStart);
}
WorkingLooper::~WorkingLooper()
{
delete fUpdateAction;
delete fCheckAction;
}
void
WorkingLooper::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgStart:
{
fAction.Perform();
if (fActionRequested == UPDATE_CHECK_ONLY) {
fCheckAction = new CheckAction;
fCheckAction->Perform();
} else {
fUpdateAction = new UpdateAction();
fUpdateAction->Perform(fActionRequested);
}
break;
}

View File

@ -12,6 +12,7 @@
#include <Looper.h>
#include <Message.h>
#include "CheckAction.h"
#include "UpdateAction.h"
@ -20,11 +21,15 @@ const uint32 kMsgStart = 'iSTA';
class WorkingLooper : public BLooper {
public:
WorkingLooper();
WorkingLooper(update_type action);
~WorkingLooper();
void MessageReceived(BMessage* message);
private:
UpdateAction fAction;
UpdateAction* fUpdateAction;
CheckAction* fCheckAction;
update_type fActionRequested;
};

View File

@ -8,6 +8,8 @@
#ifndef CONSTANTS_H
#define CONSTANTS_H
#define kAppSignature "application/x-vnd.haiku-softwareupdater"
enum {
ACTION_STEP_INIT = 0,
ACTION_STEP_START,
@ -34,9 +36,8 @@ enum update_type {
UPDATE,
UPDATE_CHECK_ONLY,
FULLSYNC,
FULLSYNC_CHECK_ONLY,
UPDATE_TYPE_END
} ;
};
// Message what values
static const uint32 kMsgTextUpdate = 'iUPD';